From eb7bcb1a1b7af84f3bd8090db1ef3b73f89cee6c Mon Sep 17 00:00:00 2001 From: Bottersnike Date: Fri, 10 Feb 2023 04:22:16 +0000 Subject: [PATCH] Idk if this is even stable --- .gitignore | 1 - Makefile | 3 + src/micetools/amBackupStructs.h | 8 + src/micetools/dll/comdevice.c | 3 +- src/micetools/dll/comdevice.h | 2 +- src/micetools/dll/common.h | 2 +- src/micetools/dll/devices/_devices.c | 14 +- src/micetools/dll/devices/_devices.h | 8 - src/micetools/dll/devices/_ds_sha.c | 45 + src/micetools/dll/devices/_ds_sha.h | 1 + src/micetools/dll/devices/meson.build | 7 +- src/micetools/dll/devices/ser_tn32msec.c | 130 ++- .../{smb_at24c64a.c => smb_at24c64an.c} | 25 +- src/micetools/dll/devices/smb_at24c64an.h | 15 + src/micetools/dll/devices/smb_ds.c | 85 -- src/micetools/dll/devices/smb_ds2460.c | 144 +++ src/micetools/dll/devices/smb_ds2460.h | 42 + src/micetools/dll/devices/smb_ds28cn01.c | 200 ++++ src/micetools/dll/devices/smb_ds28cn01.h | 43 + src/micetools/dll/devices/smb_exio.c | 53 - src/micetools/dll/devices/smb_n2.c | 40 +- src/micetools/dll/devices/smb_pca9535.c | 2 +- src/micetools/dll/devices/smb_pca9535.h | 14 + src/micetools/dll/dllmain.c | 38 +- src/micetools/dll/drivers/mxjvs.c | 214 +++-- src/micetools/dll/drivers/mxparallel.c | 19 +- src/micetools/dll/drivers/mxsmbus.c | 3 - src/micetools/dll/drivers/mxsram.c | 2 +- src/micetools/dll/hooks/_hooks.h | 6 +- src/micetools/dll/hooks/com.c | 18 +- src/micetools/dll/hooks/drive.c | 904 ------------------ src/micetools/dll/hooks/drive/disks.c | 110 +++ src/micetools/dll/hooks/drive/disks.h | 82 ++ src/micetools/dll/hooks/drive/drive.c | 743 ++++++++++++++ src/micetools/dll/hooks/drive/drive.h | 149 +++ src/micetools/dll/hooks/drive/hooks.c | 279 ++++++ src/micetools/dll/hooks/drive/irb.h | 375 ++++++++ src/micetools/dll/hooks/drive/physicalDrive.c | 417 ++++++++ .../dll/hooks/{drive.h => drive/segastruct.h} | 229 ++--- src/micetools/dll/hooks/drivers/framework.c | 133 +++ src/micetools/dll/hooks/drivers/framework.h | 483 ++++++++++ src/micetools/dll/hooks/drivers/mxhwreset.c | 59 ++ src/micetools/dll/hooks/files.c | 175 +++- src/micetools/dll/hooks/files.h | 5 + src/micetools/dll/hooks/gui.c | 14 +- src/micetools/dll/hooks/gui.h | 2 + src/micetools/dll/hooks/logging.c | 14 +- src/micetools/dll/hooks/meson.build | 11 +- src/micetools/dll/hooks/network.c | 27 +- src/micetools/dll/hooks/processes.c | 59 +- src/micetools/dll/hooks/registry.c | 12 +- src/micetools/dll/hooks/setupapi.c | 8 +- src/micetools/dll/hooks/system.c | 47 +- src/micetools/dll/hooks/time.c | 26 +- src/micetools/dll/hooks/time.h | 2 - src/micetools/dll/meson.build | 1 + src/micetools/dll/smbus.h | 38 +- src/micetools/dll/util/_util.h | 3 + src/micetools/dll/util/hook.c | 69 +- src/micetools/dll/util/hook.h | 5 +- src/micetools/dll/util/log.c | 18 +- src/micetools/dll/util/log.h | 51 +- src/micetools/dll/util/misc.c | 52 + src/micetools/launcher/main.c | 7 +- src/micetools/lib/am/amDongle.c | 55 +- src/micetools/lib/am/amDongle.h | 6 +- src/micetools/lib/am/amPlatform.h | 3 +- src/micetools/lib/am/amSerialId.c | 4 +- src/micetools/lib/ami/amiCrc.h | 4 +- src/micetools/lib/ami/amiMd5.c | 129 +++ src/micetools/lib/ami/amiMd5.h | 15 + src/micetools/lib/ami/amiTimer.c | 2 +- src/micetools/lib/ami/meson.build | 7 + src/micetools/lib/dmi/dmi.c | 10 +- src/micetools/lib/libpcp/pcpp.c | 9 +- src/micetools/lib/mice/config.c | 1 + src/micetools/lib/mice/config.def | 4 +- src/micetools/lib/mice/exe.c | 5 +- src/micetools/lib/mice/exe.h | 2 +- src/micetools/lib/util/hex.c | 18 +- .../micemaster/callbacks/foreground.c | 10 +- src/micetools/micemaster/callbacks/logs.c | 237 ++--- src/micetools/micemaster/main.c | 157 ++- src/micetools/micemaster/meson.build | 2 + src/micetools/micemaster/mxm.c | 111 ++- src/micetools/micemaster/mxm.h | 28 +- src/micetools/micemaster/mxmEventLog.c | 390 +++++++- src/micetools/micemaster/mxmEventLog.h | 42 +- src/micetools/sysconf.h | 14 + src/micetools/util/dongleDecrypt.c | 134 +++ src/micetools/util/exio_test.c | 341 +++++++ src/micetools/util/meson.build | 28 + src/micetools/util/micedump/kc_mxkeychip.c | 19 +- src/micetools/util/micedump/platform.c | 6 +- src/micetools/util/micetinker.c | 4 +- src/micetools/util/test.c | 55 ++ src/patches/ALLNetProc_Win.patch | 21 + src/patches/nxAuth.patch | 20 + src/patches/patches.index | 4 +- 99 files changed, 5794 insertions(+), 1899 deletions(-) create mode 100644 src/micetools/dll/devices/_ds_sha.c create mode 100644 src/micetools/dll/devices/_ds_sha.h rename src/micetools/dll/devices/{smb_at24c64a.c => smb_at24c64an.c} (92%) create mode 100644 src/micetools/dll/devices/smb_at24c64an.h delete mode 100644 src/micetools/dll/devices/smb_ds.c create mode 100644 src/micetools/dll/devices/smb_ds2460.c create mode 100644 src/micetools/dll/devices/smb_ds2460.h create mode 100644 src/micetools/dll/devices/smb_ds28cn01.c create mode 100644 src/micetools/dll/devices/smb_ds28cn01.h delete mode 100644 src/micetools/dll/devices/smb_exio.c create mode 100644 src/micetools/dll/devices/smb_pca9535.h delete mode 100644 src/micetools/dll/hooks/drive.c create mode 100644 src/micetools/dll/hooks/drive/disks.c create mode 100644 src/micetools/dll/hooks/drive/disks.h create mode 100644 src/micetools/dll/hooks/drive/drive.c create mode 100644 src/micetools/dll/hooks/drive/drive.h create mode 100644 src/micetools/dll/hooks/drive/hooks.c create mode 100644 src/micetools/dll/hooks/drive/irb.h create mode 100644 src/micetools/dll/hooks/drive/physicalDrive.c rename src/micetools/dll/hooks/{drive.h => drive/segastruct.h} (76%) create mode 100644 src/micetools/dll/hooks/drivers/framework.c create mode 100644 src/micetools/dll/hooks/drivers/framework.h create mode 100644 src/micetools/dll/hooks/drivers/mxhwreset.c create mode 100644 src/micetools/lib/ami/amiMd5.c create mode 100644 src/micetools/sysconf.h create mode 100644 src/micetools/util/dongleDecrypt.c create mode 100644 src/micetools/util/exio_test.c create mode 100644 src/micetools/util/test.c create mode 100644 src/patches/ALLNetProc_Win.patch create mode 100644 src/patches/nxAuth.patch diff --git a/.gitignore b/.gitignore index fdfecc3..9927fcc 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,3 @@ build/ builddir/ srcdir/ .vscode/ -openssl-1.0.1/ diff --git a/Makefile b/Makefile index 58d8db8..2c10756 100644 --- a/Makefile +++ b/Makefile @@ -71,6 +71,9 @@ dist: @copy /Y "$(BUILD_DIR_32)/src/micetools/util\micedump.exe" "$(DIST_DIR)/util/micedump.exe" @copy /Y "$(BUILD_DIR_32)/src/micetools/util\micetinker.exe" "$(DIST_DIR)/util/micetinker.exe" @copy /Y "$(BUILD_DIR_32)/src/micetools/util\micemonitor.exe" "$(DIST_DIR)/util/micemonitor.exe" + @copy /Y "$(BUILD_DIR_32)/src/micetools/util\exio_test.exe" "$(DIST_DIR)/util/exio_test.exe" + @copy /Y "$(BUILD_DIR_32)/src/micetools/util\dongleDecrypt.exe" "$(DIST_DIR)/util/dongleDecrypt.exe" + @copy /Y "$(BUILD_DIR_32)/src/micetools/util\testBin.exe" "$(DIST_DIR)/util/testBin.exe" @copy /Y "src/micetools/miceboot\TrueCrypt.cmd" "$(DIST_DIR)/Execute/TrueCrypt.cmd" diff --git a/src/micetools/amBackupStructs.h b/src/micetools/amBackupStructs.h index 2045595..f8c4ccc 100644 --- a/src/micetools/amBackupStructs.h +++ b/src/micetools/amBackupStructs.h @@ -210,3 +210,11 @@ typedef struct { * 0x0600 - 0x07ff, sram * 0x1600 - 0x17ff, sram */ +#define AM_SYSDATAwH_BACKUP_REG 0x0000 +#define AM_SYSDATAwH_BACKUP_DUP 0x1000 +#define AM_SYSDATAwH_HM_PEAK_REG 0x0200 +#define AM_SYSDATAwH_HM_PEAK_DUP 0x1200 +#define AM_SYSDATAwH_TIMEZONE_REG 0x0400 +#define AM_SYSDATAwH_TIMEZONE_DUP 0x1400 +#define AM_SYSDATAwH_ERROR_LOG_REG 0x0600 +#define AM_SYSDATAwH_ERROR_LOG_DUP 0x1600 diff --git a/src/micetools/dll/comdevice.c b/src/micetools/dll/comdevice.c index cd411a8..9a60ce0 100644 --- a/src/micetools/dll/comdevice.c +++ b/src/micetools/dll/comdevice.c @@ -110,7 +110,7 @@ void comio_write(com_device_t* com, BYTE* data, BYTE len) { comdev_write(com, &one_byte, 1); } } -void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) { +unsigned char comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) { BYTE one_byte; do { if (comdev_available(com) < (sizeof *head + 1)) { @@ -131,6 +131,7 @@ void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) { comio_read(com, data, head->length); unsigned char sum; comio_read(com, &sum, 1); + return sum; } void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, BYTE* data) { BYTE one_byte; diff --git a/src/micetools/dll/comdevice.h b/src/micetools/dll/comdevice.h index 12a29c4..df79015 100644 --- a/src/micetools/dll/comdevice.h +++ b/src/micetools/dll/comdevice.h @@ -47,7 +47,7 @@ BYTE comdev_peek(com_device_t* com); void comio_read(com_device_t* com, BYTE* data, BYTE len); void comio_write(com_device_t* com, BYTE* data, BYTE len); -void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data); +unsigned char comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data); void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, BYTE* data); void com_device_thread(com_device_t* com, FnComDeviceThread* thread); diff --git a/src/micetools/dll/common.h b/src/micetools/dll/common.h index e1b3c70..22f2642 100644 --- a/src/micetools/dll/common.h +++ b/src/micetools/dll/common.h @@ -24,5 +24,5 @@ #include "../lib/mice/mice.h" #include "./util/_util.h" -extern WCHAR exePath[MAX_PATH + 1]; +extern WCHAR exeName[MAX_PATH + 1]; extern DWORD imageOffset; diff --git a/src/micetools/dll/devices/_devices.c b/src/micetools/dll/devices/_devices.c index 930dae9..f84c6d6 100644 --- a/src/micetools/dll/devices/_devices.c +++ b/src/micetools/dll/devices/_devices.c @@ -1,11 +1,16 @@ #include "_devices.h" +#include "smb_pca9535.h" +#include "smb_at24c64an.h" +#include "smb_ds28cn01.h" +#include "smb_ds2460.h" + void install_devices() { install_led_bd(); install_touch_bd(); install_aime_bd(); - smbus_install(0x20, &smbus_PCA9535_write, &smbus_PCA9535_read); + smbus_install(/* 0x20 */ PCA9535_ADDRESS, &smbus_PCA9535_write, &smbus_PCA9535_read); // mxkN2CmdWriteData(byte addr,byte *data,ushort nbytes,ushort *nbytesOut) // -> smbusWriteByte(addr, command:0xcc, byte:data[i]) @@ -13,10 +18,9 @@ void install_devices() { smbus_install(0x30, &smbus_N2_write, &smbus_N2_read); // mxkDsExioRequestComputeMac() -> smbusWriteByte(addr:0x54, command:0x5c, byte:0x94) - smbus_install(0x54, &smbus_EXIO_write, &smbus_EXIO_read); + smbus_install(/* 0x54 */ DS2460_ADDRESS, &smbus_ds2460_write, &smbus_ds2460_read); // mxkDsKeychipComputeMac - smbus_install(0x55, &smbus_DS_write, &smbus_DS_read); - - smbus_install(0x57, &smbus_AT24C64AN_write, &smbus_AT24C64AN_read); + smbus_install(/* 0x55 */ DS28CN01_ADDRESS, &smbus_ds28cn01_write, &smbus_ds28cn01_read); + smbus_install(/* 0x57 */ AT24C64AN_ADDRESS, &smbus_AT24C64AN_write, &smbus_AT24C64AN_read); } diff --git a/src/micetools/dll/devices/_devices.h b/src/micetools/dll/devices/_devices.h index 671e2b8..9bc9956 100644 --- a/src/micetools/dll/devices/_devices.h +++ b/src/micetools/dll/devices/_devices.h @@ -7,15 +7,7 @@ void install_led_bd(); void install_touch_bd(); void install_aime_bd(); -smbus_callback_t smbus_PCA9535_write; -smbus_callback_t smbus_PCA9535_read; -smbus_callback_t smbus_DS_write; -smbus_callback_t smbus_DS_read; smbus_callback_t smbus_N2_write; smbus_callback_t smbus_N2_read; -smbus_callback_t smbus_AT24C64AN_write; -smbus_callback_t smbus_AT24C64AN_read; -smbus_callback_t smbus_EXIO_write; -smbus_callback_t smbus_EXIO_read; void install_devices(); diff --git a/src/micetools/dll/devices/_ds_sha.c b/src/micetools/dll/devices/_ds_sha.c new file mode 100644 index 0000000..d3ce5a6 --- /dev/null +++ b/src/micetools/dll/devices/_ds_sha.c @@ -0,0 +1,45 @@ +#include "_ds_sha.h" + +#define KTN(n) ((n < 20) ? 0x5a827999 : (n < 40) ? 0x6ed9eba1 : (n < 60) ? 0x8f1bbcdc : 0xca62c1d6) + +#define NLF(B, C, D, n) \ + ((n < 20) ? ((B & C) | ((~B) & D)) \ + : (n < 40) ? (B ^ C ^ D) \ + : (n < 60) ? ((B & C) | (B & D) | (C & D)) \ + : (B ^ C ^ D)) + +/** + * @brief This is almost identical to a typical SHA1 implementation, except the final step involving + * the addition of constants is ommitted as per the datasheet. + */ +void ComputeDallasSha(unsigned char *MT, long *A, long *B, long *C, long *D, long *E) { + unsigned long MTword[80]; + int i; + long ShftTmp; + long Temp; + + for (i = 0; i < 16; i++) + MTword[i] = + (MT[i * 4] << 24) | (MT[i * 4 + 1] << 16) | (MT[i * 4 + 2] << 8) | MT[i * 4 + 3]; + + for (i = 16; i < 80; i++) { + ShftTmp = MTword[i - 3] ^ MTword[i - 8] ^ MTword[i - 14] ^ MTword[i - 16]; + MTword[i] = ((ShftTmp << 1) & 0xfffffffe) | ((ShftTmp >> 31) & 0x00000001); + } + + *A = 0x67452301; + *B = 0xefcdab89; + *C = 0x98badcfe; + *D = 0x10325476; + *E = 0xc3d2e1f0; + + for (i = 0; i < 80; i++) { + ShftTmp = ((*A << 5) & 0xffffffe0) | ((*A >> 27) & 0x0000001f); + Temp = NLF(*B, *C, *D, i) + *E + KTN(i) + MTword[i] + ShftTmp; + *E = *D; + *D = *C; + *C = ((*B << 30) & 0xc0000000) | ((*B >> 2) & 0x3fffffff); + *B = *A; + *A = Temp; + } +} diff --git a/src/micetools/dll/devices/_ds_sha.h b/src/micetools/dll/devices/_ds_sha.h new file mode 100644 index 0000000..6b6f4dc --- /dev/null +++ b/src/micetools/dll/devices/_ds_sha.h @@ -0,0 +1 @@ +void ComputeDallasSha(unsigned char *MT, long *A, long *B, long *C, long *D, long *E); diff --git a/src/micetools/dll/devices/meson.build b/src/micetools/dll/devices/meson.build index c1812fc..e439f02 100644 --- a/src/micetools/dll/devices/meson.build +++ b/src/micetools/dll/devices/meson.build @@ -1,13 +1,14 @@ devices_files = files( + '_ds_sha.c', '_devices.c', # Serial devices 'ser_led_bd.c', 'ser_maitouch.c', 'ser_tn32msec.c', # SMBus devices - 'smb_exio.c', 'smb_pca9535.c', - 'smb_ds.c', + 'smb_ds2460.c', + 'smb_ds28cn01.c', 'smb_n2.c', - 'smb_at24c64a.c', + 'smb_at24c64an.c', ) \ No newline at end of file diff --git a/src/micetools/dll/devices/ser_tn32msec.c b/src/micetools/dll/devices/ser_tn32msec.c index 56f6056..75e209e 100644 --- a/src/micetools/dll/devices/ser_tn32msec.c +++ b/src/micetools/dll/devices/ser_tn32msec.c @@ -15,30 +15,45 @@ BYTE extra[0xff]; * TODO: Validate against a real board */ enum TN32_Opcode { - TN32Op_Unknown20 = 0x20, + TN32Op_Unknown20 = 0x20, // where did this come from?? TN32Op_GetFWVersion = 0x30, TN32Op_GetHWVersion = 0x32, + TN32Op_RadioOn = 0x40, TN32Op_RadioOff = 0x41, TN32Op_Poll = 0x42, TN32Op_MifareSelectTag = 0x43, TN32Op_Unknown44 = 0x44, // Present in code, not seen used + TN32Op_SetKeyBana = 0x50, TN32Op_GetKeyBana = 0x51, TN32Op_ReadBlock = 0x52, TN32Op_Unknown53 = 0x53, // Present in code, not seen used TN32Op_SetKeyAime = 0x54, TN32Op_GetKeyAime = 0x55, + + // Firmware update (I think) TN32Op_Unknown60 = 0x60, // Present in code, not seen used TN32Op_Unknown61 = 0x61, // Present in code, not seen used TN32Op_Reset = 0x62, + TN32Op_Unknown63 = 0x63, + TN32Op_Unknown64 = 0x64, + TN32Op_Unknown70 = 0x70, // Present in code, not seen used TN32Op_FelicaEncap = 0x71, + + // No responses to either + LedUnknown80 = 0x80, + LedSetColour = 0x81, + + LedGetInfo = 0xf0, + LedF2 = 0xf2, + LedF3 = 0xf3, + LedF4 = 0xf4, + LedReset = 0xf5, }; -#define LedReset 0xf5 -#define LedGetInfo 0xf0 -#define LedSetColour 0x81 +char* OpcodeNames[256]; const char FWVer[] = "TN32MSEC003S F/W Ver1.2"; const char HWVer[] = "TN32MSEC003S H/W Ver3.0"; @@ -84,7 +99,7 @@ typedef struct FelicaMemory { MifareMemory_t mifareMemory; FelicaMemory_t felicaMemory; -BYTE luid[10] = {0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89}; +BYTE luid[10] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0x01, 0x23, 0x45, 0x67, 0x89 }; #define PMm_VALUE 0x00F1000000014300ULL #define FelicaSystemBlock_RC 0x00 @@ -135,8 +150,7 @@ void populate_felica(NFCFelica_t* card) { 0x00, 0x2a, 0x05, 0x73, 0x02, 0x01, 0x03, 0x00, // ^DFC^ ^~~~~~ arbitary value }; - memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_ID].bytes, blockID, - 16); + memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_ID].bytes, blockID, 16); BYTE blockDID[16] = { // IDd (=IDm) 0x01, @@ -157,8 +171,7 @@ void populate_felica(NFCFelica_t* card) { 0x43, 0x00, }; - memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_D_ID].bytes, blockDID, - 16); + memcpy(felicaMemory.systemBlocks[FelicaSystemBlock_D_ID].bytes, blockDID, 16); } void populate_mifare(NFCMifare_t* card) { card->type = CardType_Mifare; @@ -202,14 +215,16 @@ BYTE AIME_KEY[6]; BYTE BANA_KEY[6]; DWORD WINAPI aime_bd_thread(com_device_t* dev) { + static int fwNumBytes = 0; + log_info("aime_bd", "%ls woke up", dev->com->wName); bool radio = false; while (1) { comio_recv_head_t req; - comio_next_req(dev, &req, extra); + unsigned char sum = comio_next_req(dev, &req, extra); - log_info("aime_bd", "(%d) %02x", req.dst, req.op); + log_info("aime_bd", "(%d) %02x(%d) = %s", req.dst, req.op, req.length, OpcodeNames[req.op]); if (req.dst == 0x00 || req.dst == 0x01) { // Aime readers @@ -218,12 +233,14 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); break; case TN32Op_GetFWVersion: - comio_reply(dev, &req, COMIO_STATUS_OK, sizeof FWVer - 1, - (LPBYTE)FWVer); + // BYTE fver = 0x10; + // comio_reply(dev, &req, COMIO_STATUS_OK, 1, &fver); + comio_reply(dev, &req, COMIO_STATUS_OK, sizeof FWVer - 1, (LPBYTE)FWVer); break; case TN32Op_GetHWVersion: - comio_reply(dev, &req, COMIO_STATUS_OK, sizeof HWVer - 1, - (LPBYTE)HWVer); + // BYTE hver = 0x10; + // comio_reply(dev, &req, COMIO_STATUS_OK, 1, &hver); + comio_reply(dev, &req, COMIO_STATUS_OK, sizeof HWVer - 1, (LPBYTE)HWVer); break; case TN32Op_SetKeyAime: if (req.length != sizeof AIME_KEY) { @@ -232,10 +249,8 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { memcpy(AIME_KEY, extra, sizeof AIME_KEY); comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); - log_info("aime_bd", - "Aime key: %02x %02x %02x %02x %02x %02x", - AIME_KEY[0], AIME_KEY[1], AIME_KEY[2], - AIME_KEY[3], AIME_KEY[4], AIME_KEY[5]); + log_info("aime_bd", "Aime key: %02x %02x %02x %02x %02x %02x", AIME_KEY[0], + AIME_KEY[1], AIME_KEY[2], AIME_KEY[3], AIME_KEY[4], AIME_KEY[5]); } break; case TN32Op_SetKeyBana: @@ -245,10 +260,8 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { memcpy(BANA_KEY, extra, sizeof BANA_KEY); comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); - log_info("aime_bd", - "Bana key: %02x %02x %02x %02x %02x %02x", - BANA_KEY[0], BANA_KEY[1], BANA_KEY[2], - BANA_KEY[3], BANA_KEY[4], BANA_KEY[5]); + log_info("aime_bd", "Bana key: %02x %02x %02x %02x %02x %02x", BANA_KEY[0], + BANA_KEY[1], BANA_KEY[2], BANA_KEY[3], BANA_KEY[4], BANA_KEY[5]); } break; case TN32Op_RadioOn: @@ -274,6 +287,43 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); break; + case TN32Op_Unknown60: + // req.length == 0; start firmware update? + comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + break; + case TN32Op_Unknown61: + // null-terminated line of the firmware hex! + comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + log_info("aime_bd", "Recv firmware: %s", extra); + break; + case TN32Op_Unknown63: + // req.length == 0; start binary firmware update? + fwNumBytes = 0; + comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + break; + case TN32Op_Unknown64: + // Raw binary firmware data + // [req.length == 256 -> wraps to 00] [256 bytes] + if (req.length == 0) { + unsigned char update_buffer[256]; + update_buffer[0] = sum; + comio_read(dev, update_buffer + 1, 255); + // We need to account for the actual checksum at the end of this lot + comio_read(dev, &sum, 1); + + fwNumBytes += 256; + } else { + fwNumBytes += req.length; + } + + // nxAuth is segfaulting past this. Rather than figure it out, let's just + // protect it from itself for now. + if (fwNumBytes >= 0x3000) + ; + else + comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL); + break; + // TODO: These case TN32Op_ReadBlock: comio_reply(dev, &req, COMIO_STATUS_NG, 0, NULL); @@ -291,12 +341,10 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { case LedGetInfo: // TODO: I'm not sure what this actually means. // 838-15084 is probably a part number - comio_reply(dev, &req, COMIO_STATUS_OK, 9, - (BYTE*)"15084\xff\x10\x00\x12"); + comio_reply(dev, &req, COMIO_STATUS_OK, 9, (BYTE*)"15084\xff\x10\x00\x12"); break; case LedSetColour: - log_misc("nfc", "Set LED: #%02x%02x%02x", extra[0], - extra[1], extra[2]); + log_misc("nfc", "Set LED: #%02x%02x%02x", extra[0], extra[1], extra[2]); printf( "\033[48;2;%d;%d;%dm " " \033[0m", @@ -311,6 +359,31 @@ DWORD WINAPI aime_bd_thread(com_device_t* dev) { } void install_aime_bd() { + ZeroMemory(OpcodeNames, sizeof OpcodeNames); + OpcodeNames[TN32Op_Unknown20] = "Unknown20"; + OpcodeNames[TN32Op_GetFWVersion] = "GetFWVersion"; + OpcodeNames[TN32Op_GetHWVersion] = "GetHWVersion"; + OpcodeNames[TN32Op_RadioOn] = "RadioOn"; + OpcodeNames[TN32Op_RadioOff] = "RadioOff"; + OpcodeNames[TN32Op_Poll] = "Poll"; + OpcodeNames[TN32Op_MifareSelectTag] = "MifareSelectTag"; + OpcodeNames[TN32Op_Unknown44] = "Unknown44"; + OpcodeNames[TN32Op_SetKeyBana] = "SetKeyBana"; + OpcodeNames[TN32Op_GetKeyBana] = "GetKeyBana"; + OpcodeNames[TN32Op_ReadBlock] = "ReadBlock"; + OpcodeNames[TN32Op_Unknown53] = "Unknown53"; + OpcodeNames[TN32Op_SetKeyAime] = "SetKeyAime"; + OpcodeNames[TN32Op_GetKeyAime] = "GetKeyAime"; + OpcodeNames[TN32Op_Unknown60] = "Unknown60"; + OpcodeNames[TN32Op_Unknown61] = "Unknown61"; + OpcodeNames[TN32Op_Reset] = "Reset"; + OpcodeNames[TN32Op_Unknown70] = "Unknown70"; + OpcodeNames[TN32Op_FelicaEncap] = "FelicaEncap"; + + OpcodeNames[LedReset] = "LedReset"; + OpcodeNames[LedGetInfo] = "LedGetInfo"; + OpcodeNames[LedSetColour] = "LedSetColour"; + char* text = MiceConfig.devices.aime_bd; char* copy = (char*)malloc(strlen(text) + 1); memcpy_s(copy, strlen(text) + 1, text, strlen(text) + 1); @@ -319,8 +392,7 @@ void install_aime_bd() { char* token = strtok_s(copy, ",", &next_token); while (token != NULL) { BYTE com_port = atoi(token) & 0xFF; - if (com_port) - com_device_thread(new_com_device(com_port), aime_bd_thread); + if (com_port) com_device_thread(new_com_device(com_port), aime_bd_thread); token = strtok_s(NULL, ",", &next_token); } diff --git a/src/micetools/dll/devices/smb_at24c64a.c b/src/micetools/dll/devices/smb_at24c64an.c similarity index 92% rename from src/micetools/dll/devices/smb_at24c64a.c rename to src/micetools/dll/devices/smb_at24c64an.c index 15739fc..fb17c8d 100644 --- a/src/micetools/dll/devices/smb_at24c64a.c +++ b/src/micetools/dll/devices/smb_at24c64an.c @@ -4,6 +4,8 @@ #define EEPROM_DUMP L"dev/eeprom.bin" +#include "../../sysconf.h" + // 8192 x 8 (64kbit) of eeprom BYTE EEPROM_DATA[0x2000]; @@ -39,9 +41,9 @@ void eeprom_restore() { *(uint32_t*)&val = (uint32_t)((a << 24) | (b << 16) | (c << 8) | d); \ } while (0) -#define fix_crc(block) \ - do { \ - (block).m_Crc = amCrc32RGet(sizeof(block) - 4, (BYTE*)(&(block)) + 4, 0); \ +#define fix_crc(block) \ + do { \ + (block).m_Crc = amiCrc32RCalc(sizeof(block) - 4, (BYTE*)(&(block)) + 4, 0); \ } while (0) void set_eeprom_network_config() { @@ -87,7 +89,14 @@ int build_eeprom() { memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_REG], &Static, sizeof Static); memcpy(&EEPROM_DATA[AM_SYSDATAwH_STATIC_DUP], &Static, sizeof Static); - AM_SYSDATAwH_CREDIT Credit = { 0 }; + AM_SYSDATAwH_CREDIT Credit = { + .m_Config = { + .ServiceType = 1, + .CreditRate = 1, + .CoinRate = { 1, 1 }, + .Cost = { 1, 1, 1, 1, 1, 1, 1, 1 }, + }, + }; fix_crc(Credit); memcpy(&EEPROM_DATA[AM_SYSDATAwH_CREDIT_REG], &Credit, sizeof Credit); memcpy(&EEPROM_DATA[AM_SYSDATAwH_CREDIT_DUP], &Credit, sizeof Credit); @@ -96,10 +105,10 @@ int build_eeprom() { AM_SYSDATAwH_HISTORY History = { 0 }; // TODO: Game ID here should be configurable. - History.m_GameId[0] = 'S'; - History.m_GameId[1] = 'D'; - History.m_GameId[2] = 'E'; - History.m_GameId[3] = 'Y'; + History.m_GameId[0] = GAME_ID_0; + History.m_GameId[1] = GAME_ID_1; + History.m_GameId[2] = GAME_ID_2; + History.m_GameId[3] = GAME_ID_3; History.m_Region = MiceConfig.sysconf.region & (1 | 2 | 4 | 8); fix_crc(History); memcpy(&EEPROM_DATA[AM_SYSDATAwH_HISTORY_REG], &History, sizeof History); diff --git a/src/micetools/dll/devices/smb_at24c64an.h b/src/micetools/dll/devices/smb_at24c64an.h new file mode 100644 index 0000000..c3c34ab --- /dev/null +++ b/src/micetools/dll/devices/smb_at24c64an.h @@ -0,0 +1,15 @@ +#include "smbus.h" + +smbus_callback_t smbus_AT24C64AN_write; +smbus_callback_t smbus_AT24C64AN_read; + +#define AT24C64AN_GND 0 +#define AT24C64AN_VCC 1 + +// Ref: MS-9667 rev 0A sheet 10 +#define AT24C64AN_PIN_A0 AT24C64AN_VCC +#define AT24C64AN_PIN_A1 AT24C64AN_VCC +#define AT24C64AN_PIN_A2 AT24C64AN_VCC + +#define AT24C64AN_ADDRESS \ + (0b1010'000 | (AT24C64AN_PIN_A2 << 2) | (AT24C64AN_PIN_A1 << 1) | AT24C64AN_PIN_A0) diff --git a/src/micetools/dll/devices/smb_ds.c b/src/micetools/dll/devices/smb_ds.c deleted file mode 100644 index 4f0e823..0000000 --- a/src/micetools/dll/devices/smb_ds.c +++ /dev/null @@ -1,85 +0,0 @@ -#include "_devices.h" - -/** - * TODO: This whole device, properly - */ - -BOOL smbus_DS_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { - static unsigned char challenge[7]; - - switch (cmd) { - case ICH9_CMD_BLOCK: { - switch (code) { - case 0xa9d0: - case 0xa9d1: - case 0xa9d2: - case 0xa9d3: { - if (dlen != 7) { - log_error("smb-ds", "Expected challenge length of 7 (saw %d)!", dlen); - return FALSE; - } - - memcpy(challenge, &(data[2]), 7); - - char* challenge_s = malloc(dlen * 3 + 1); - if (challenge_s == NULL) { - log_info("smb-ds", "Challenge: (buffer failed)"); - return TRUE; - } - - for (int i = 0; i < dlen; i++) { - sprintf_s(challenge_s + i * 3, 4, "%02x ", data[2 + i]); - } - challenge_s[dlen * 3 + 1] = '\0'; - log_info("smb-ds", "Challenge: %s", challenge_s); - free(challenge_s); - return TRUE; - } - default: - log_error("smb-ds", "Unknown write command: %04x", code); - } - } - case ICH9_CMD_I2C_READ: { - switch (code) { - case DS_I2C_CHALLENGE_RESPONSE: - // This just has to match EXIO! - for (int i = 0; i < dlen; i++) data[i] = 0x69; - return TRUE; - default: - log_error("smb-ds", "Unknown I2C read command: %04x", code); - } - } - default: - log_error("smb-ds", "Unsupported write mode: %01x (%04x)", cmd, code); - return FALSE; - } -} - -BOOL smbus_DS_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { - static unsigned char DS_eeprom[3][0x20]; - - switch (cmd) { - case ICH9_CMD_BYTE_DATA: - if (code < 0x80) { - BYTE page = (code >> 5) & 0b11; - BYTE offset = code & 0x1f; - - data[0] = DS_eeprom[page][offset]; - - return TRUE; - } else if (code >= DS_GET_UNIQUE_NUMBER && code < DS_GET_UNIQUE_NUMBER + 0xf) { - data[0] = 0x04; // chosen by fair dice roll. - return TRUE; - } else if (code == DS_GET_STATUS) { - // Polled until DS_STATUS_FLAG_BUSY low - data[0] = 0x00; - return TRUE; - } else { - log_error("smb-ds", "Unknown read command: %04x", code); - return FALSE; - } - default: - log_error("smb-ds", "Unsupported read mode: %01x (%04x)", cmd, code); - return FALSE; - } -} diff --git a/src/micetools/dll/devices/smb_ds2460.c b/src/micetools/dll/devices/smb_ds2460.c new file mode 100644 index 0000000..f1a0a72 --- /dev/null +++ b/src/micetools/dll/devices/smb_ds2460.c @@ -0,0 +1,144 @@ +/** + * This board is located on the mezzanine board in the Ring (IC7). + * + * Similar to the DS28CN01, this is a SHA-1 coprocessor with EEPROM + * storage. + * + * The pins are wired as: + * + * pin | name | connection + * 1 | AD0 | GND + * 2 | AD1 | Floating + * 3 | AD2 | Floating + * 4 | GND | GND + * 5 | NC | + * 6 | SDA | SMData + * 7 | SCL | SMClock + * 8 | Vcc | VCC3 + * + * Pins 2 and 3 are floating, when they should be pulled to Vcc. It is + * therefore assumed that there's an internal pull-up on all three AD + * pins, as otherwise this device would be at address 0x40! + * + * In code it is referred to as the "ds exio" device, complemeting the + * "ds" device on the keychip. + */ + +#include "smb_ds2460.h" + +#include + +#include "_ds_sha.h" + +static BYTE USER_EEPROM[DS2460_EEPROM_SIZE]; +static BYTE INPUT_BUFFER[DS2460_INPUT_BUFFER_SIZE]; + +static BYTE COMPUTED_MAC[DS2460_MAC_LEN]; + +static BYTE SECRETS[4][8] = { + // S-Secret + { 0 }, + // E-Secret 1 + { 0 }, + // E-Secret 2 <-- The one that's used + { 0 }, + // E-Secret 3 + { 0 }, +}; + +void ds2460_update_mac(bool gpSha, byte* secret) { + memcpy(&INPUT_BUFFER[0], &secret[0], 4); + memcpy(&INPUT_BUFFER[48], &secret[4], 4); + INPUT_BUFFER[55] = 0x80; + for (int i = 56; i < 62; i++) INPUT_BUFFER[i] = 0; + INPUT_BUFFER[62] = 0x01; + INPUT_BUFFER[63] = 0xB8; + + puts("ds2460: SHA1 input buffer:"); + for (int i = 0; i < DS2460_INPUT_BUFFER_SIZE; i++) { + printf("%02x", INPUT_BUFFER[i]); + } + puts(""); + + if (gpSha) { + EVP_MD_CTX* ctx = EVP_MD_CTX_create(); + EVP_DigestInit(ctx, EVP_sha1()); + EVP_DigestUpdate(ctx, INPUT_BUFFER, DS2460_INPUT_BUFFER_SIZE); + unsigned int outlen; + EVP_DigestFinal_ex(ctx, COMPUTED_MAC, &outlen); + EVP_MD_CTX_destroy(ctx); + } else { + ComputeDallasSha(INPUT_BUFFER, (long*)&COMPUTED_MAC[0], (long*)&COMPUTED_MAC[4], + (long*)&COMPUTED_MAC[8], (long*)&COMPUTED_MAC[12], + (long*)&COMPUTED_MAC[16]); + } +} + +BOOL smbus_ds2460_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { + switch (cmd) { + case ICH9_CMD_BYTE_DATA: + switch (code) { + case DS2460_MEM_CMD: + /** + * 0x94 = + * | 0x80 -> DS2460_CMD_COMPUTE + * | 0x10 -> (secret = ESecret2) << 3 + * | 0x04 -> DS2460_CMD_COMPUTE_TO_MAC_BUFFER + */ + if (!(data[0] & DS2460_CMD_COMPUTE)) { + log_error("ds2460", "Unknown command: %02x", data[0]); + return FALSE; + } + BYTE numSecret = (data[0] >> 3) & 3; + BOOL toMacBuffer = !!(data[0] & DS2460_CMD_COMPUTE_TO_MAC_BUFFER); + BYTE gpSha = !!(data[0] & DS2460_CMD_COMPUTE_GP_SHA); + + if (data[0] != DS2460_REQUEST_COMPUTE_MAC) { + } + + ds2460_update_mac(gpSha, SECRETS[numSecret]); + return TRUE; + default: + log_error("ds2460", "Unknown write command: %02x", code); + return FALSE; + } + case ICH9_CMD_BLOCK: { + BYTE offset = code >> 8; + + // One extra byte of data is stuffed into the command code + if (offset < DS2460_INPUT_BUFFER_SIZE) INPUT_BUFFER[offset] = code & 0xff; + if (offset + 1 < DS2460_INPUT_BUFFER_SIZE) + memcpy_s(&INPUT_BUFFER[offset + 1], DS2460_INPUT_BUFFER_SIZE - (offset + 1), data, + dlen); + + log_info("ds2460", "Block write, %d @ %04x: ", dlen + 1, offset); + return TRUE; + } + + default: + log_error("ds2460", "Unsupported write mode: %01x (%02x)", cmd, code); + return FALSE; + } +} + +BOOL smbus_ds2460_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { + switch (cmd) { + case ICH9_CMD_BYTE_DATA: + if (code == DS2460_MEM_SHA) { + // if we were busy processing something we'd: + // return FALSE; + return TRUE; + } + + if (DS2460_MEM_MAC <= code < DS2460_MEM_MAC + DS2460_MAC_LEN) { + data[0] = COMPUTED_MAC[code - DS2460_MEM_MAC]; + return TRUE; + } + + log_error("smx-exio", "Unknown read command: %02x", code); + return FALSE; + default: + log_error("ds2460", "Unsupported read mode: %01x (%02x)", cmd, code); + return FALSE; + } +} diff --git a/src/micetools/dll/devices/smb_ds2460.h b/src/micetools/dll/devices/smb_ds2460.h new file mode 100644 index 0000000..05e921b --- /dev/null +++ b/src/micetools/dll/devices/smb_ds2460.h @@ -0,0 +1,42 @@ +#include "smbus.h" + +smbus_callback_t smbus_ds2460_write; +smbus_callback_t smbus_ds2460_read; + +// Specification +#define DS2460_EEPROM_SIZE 112 +#define DS2460_INPUT_BUFFER_SIZE 64 + +#define DS2460_MAC_LEN 20 + +// Registers +#define DS2460_MEM_SHA 0x00 +#define DS2460_MEM_MAC 0x40 +#define DS2460_MEM_SSECRET 0x54 +#define DS2460_MEM_CMD 0x5C +#define DS2460_MEM_MATCHMAC 0x5E +#define DS2460_MEM_ESECRET1 0x60 +#define DS2460_MEM_ESECRET2 0x68 +#define DS2460_MEM_ESECRET3 0x70 +#define DS2460_MEM_EEPROM 0x80 +#define DS2460_MEM_SERIAL 0xF0 + +#define DS2460_CMD_COMPUTE 0x80 +#define DS2460_CMD_COMPUTE_GP_SHA 0x20 +#define DS2460_CMD_COMPUTE_TO_MAC_BUFFER 0x04 + +#define DS2460_CMD_TXSECRET 0x40 + +// Consts +#define DS2460_REQUEST_COMPUTE_MAC 0x94 + +// Wiring +#define DS2460_GND 0 +#define DS2460_VCC 1 + +#define DS2460_PIN_AD0 DS2460_GND +#define DS2460_PIN_AD1 DS2460_VCC +#define DS2460_PIN_AD2 DS2460_VCC + +#define DS2460_ADDRESS \ + (0b10'0'0'0'0'0 | DS2460_PIN_AD0 | (DS2460_PIN_AD1 << 2) | (DS2460_PIN_AD2 << 4)) diff --git a/src/micetools/dll/devices/smb_ds28cn01.c b/src/micetools/dll/devices/smb_ds28cn01.c new file mode 100644 index 0000000..ef3666d --- /dev/null +++ b/src/micetools/dll/devices/smb_ds28cn01.c @@ -0,0 +1,200 @@ +/** + * This is one of three uniquely accesible chips on the keychip, and one + * of two on the SMBus. + * + * The DS28CN01 is a 1Kbit EEPROM with hardware SHA-1 and a factory- + * unique random number. + * + * The pins are wired as: + * + * pin | name | connection + * ----------------------- + * 1 | AD0 | VCC3 + * 2 | AD1 | VCC3 + * 3 | NC | + * 4 | GND | GND + * 5 | SDA | SMData + * 6 | SCL | SMClock + * 7 | NC | + * 8 | Vcc | VCC3 + */ + +#include "smb_ds28cn01.h" + +#include + +#include "_ds_sha.h" + +// Keychip secrets! +static BYTE USER_EEPROM[DS28CN01_EEPROM_PAGES][DS28CN01_EEPROM_PAGE_SIZE] = { + { + 0x09, 0xb7, 0xcc, 0xe7, 0x74, 0x5f, 0x5c, 0xd9, 0xf2, 0x29, 0x70, + 0x86, 0x70, 0x61, 0xf4, 0xba, 0xdb, 0x4f, 0xde, 0x1e, 0x85, 0x0b, + 0xb6, 0xaf, 0xcb, 0x93, 0x55, 0x6e, 0xf5, 0x1b, 0xed, 0x59, + }, + { + 0x5d, 0xa4, 0x49, 0x9b, 0xd4, 0xd0, 0x56, 0x00, 0x41, 0xf5, 0xe3, + 0xab, 0x8b, 0x70, 0xa5, 0x0b, 0xb9, 0x3c, 0x7e, 0x0b, 0x58, 0xc3, + 0xfe, 0x89, 0x1d, 0xf3, 0x2b, 0x0a, 0xcc, 0x95, 0x7d, 0xac, + }, + { + 0x58, 0xda, 0x2d, 0x5c, 0x4c, 0x37, 0xb0, 0x48, 0x69, 0x73, 0x7e, + 0x97, 0x91, 0xff, 0x17, 0x58, 0xe4, 0x85, 0x48, 0xb9, 0x28, 0xc3, + 0xaa, 0x7a, 0x6e, 0x9a, 0x6d, 0xa1, 0xf2, 0x62, 0x53, 0x6e, + }, + { + 0x44, 0x81, 0xff, 0x91, 0xa5, 0x3c, 0x70, 0x9b, 0xb4, 0xcd, 0xc9, + 0xb3, 0x4a, 0xb5, 0x53, 0x8a, 0xa2, 0x53, 0xc4, 0x91, 0xbd, 0xb6, + 0xc2, 0x69, 0x04, 0xb0, 0xa3, 0x9a, 0x30, 0x2b, 0x77, 0x89, + }, +}; + +// TODO: Make this actually a valid ID (crc and whatnot) +// Unique per keychip +static const BYTE UNIQUE_NUMBER[DS28CN01_UNIQUE_NUMBER_SIZE] = { + 'M', 'I', 'C', 'E', 'K', 'E', 'Y', '\0', +}; + +#define DS28CN01_INPUT_BUFFER_SIZE 64 +static BYTE MAC_INPUT_BUFFER[DS28CN01_INPUT_BUFFER_SIZE]; +static BYTE COMPUTED_MAC[DS28CN01_MAC_LEN]; + +static BYTE SECRET[8] = { 0 }; + +void ds28cn01_update_mac(void) { + puts("ds28cn01: SHA1 input buffer:"); + for (int i = 0; i < DS28CN01_INPUT_BUFFER_SIZE; i++) { + printf("%02x", MAC_INPUT_BUFFER[i]); + } + puts(""); + + // EVP_MD_CTX* ctx = EVP_MD_CTX_create(); + // EVP_DigestInit(ctx, EVP_sha1()); + // EVP_DigestUpdate(ctx, MAC_INPUT_BUFFER, DS28CN01_INPUT_BUFFER_SIZE); + // unsigned int outlen; + // EVP_DigestFinal_ex(ctx, COMPUTED_MAC, &outlen); + // EVP_MD_CTX_destroy(ctx); + + ComputeDallasSha(MAC_INPUT_BUFFER, (long*)&COMPUTED_MAC[0], (long*)&COMPUTED_MAC[4], + (long*)&COMPUTED_MAC[8], (long*)&COMPUTED_MAC[12], + (long*)&COMPUTED_MAC[16]); + + puts("ds28cn01: SHA1 out buffer:"); + for (int i = 0; i < 20; i++) { + printf("%02x", COMPUTED_MAC[i]); + } + puts(""); +} + +BOOL smbus_ds28cn01_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { + static unsigned char challenge[8]; + + switch (cmd) { + case ICH9_CMD_BLOCK: { + if (code >> 8 == 0xa9) { + BYTE command = code & 0xff; + + BYTE page = command & 3; + BYTE upper = command & 0xf0; + + if (upper == 0xD0) { + log_warning("ds28cn01", "Computing for: authentication (flag = 1)"); + } else if (upper == 0xE0) { + log_warning("ds28cn01", "Computing for: ds.compute (flag = 0)"); + } else { + log_error("ds28cn01", "Unknown A9"); + return FALSE; + } + + if (dlen != 7) { + log_error("ds28cn01", "Expected challenge length of 7 (saw %d)!", dlen); + return FALSE; + } + + memcpy(&MAC_INPUT_BUFFER[0], &SECRET[0], 4); + memcpy(&MAC_INPUT_BUFFER[4], USER_EEPROM[page], DS28CN01_EEPROM_PAGE_SIZE); + memcpy(&MAC_INPUT_BUFFER[36], &data[0], 4); + MAC_INPUT_BUFFER[40] = 0x40 | page; + memcpy(&MAC_INPUT_BUFFER[41], UNIQUE_NUMBER, 7); + memcpy(&MAC_INPUT_BUFFER[48], &SECRET[4], 4); + memcpy(&MAC_INPUT_BUFFER[52], &data[4], 3); + MAC_INPUT_BUFFER[55] = 0x80; + for (int i = 56; i < 62; i++) MAC_INPUT_BUFFER[i] = 0; + MAC_INPUT_BUFFER[62] = 0x01; + MAC_INPUT_BUFFER[63] = 0xB8; + + // + + // Stuffing into the command code, as ever + // challenge[0] = command & 0xff; + // memcpy(&(challenge[1]), data, dlen); + + // dlen++; + // char* challenge_s = malloc(dlen * 3 + 1); + // if (challenge_s == NULL) { + // log_info("ds28cn01", "Challenge: (buffer failed)"); + // return TRUE; + // } + + // for (int i = 0; i < dlen; i++) { + // sprintf_s(challenge_s + i * 3, 4, "%02x ", data[i]); + // } + // challenge_s[dlen * 3 + 1] = '\0'; + // log_info("ds28cn01", "Challenge: %s", challenge_s); + // free(challenge_s); + + return TRUE; + } + + log_error("ds28cn01", "Unknown write command: %04x", code); + } + case ICH9_CMD_I2C_READ: { + switch (code) { + case DS28CN01_REG_MAC: + // This just has to match EXIO! + if (dlen > DS28CN01_MAC_LEN) return FALSE; + + ds28cn01_update_mac(); + + for (int i = 0; i < dlen; i++) data[i] = COMPUTED_MAC[i]; + return TRUE; + default: + log_error("ds28cn01", "Unknown I2C read command: %04x", code); + } + } + default: + log_error("ds28cn01", "Unsupported write mode: %01x (%04x)", cmd, code); + return FALSE; + } +} + +BOOL smbus_ds28cn01_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { + switch (cmd) { + case ICH9_CMD_BYTE_DATA: + if (code < DS28CN01_EEPROM_SIZE) { + BYTE page = (code >> 5) & 0b11; + BYTE offset = code & 0x1f; + + data[0] = USER_EEPROM[page][offset]; + + return TRUE; + } + + if (code >= DS28CN01_REG_NUM && code <= DS28CN01_REG_NUM_END) { + data[0] = UNIQUE_NUMBER[code - DS28CN01_REG_NUM]; + return TRUE; + } + + if (code == DS28CN01_REG_STATUS) { + // Polled until DS_STATUS_FLAG_BUSY low + data[0] = 0x00; + return TRUE; + } + + log_error("ds28cn01", "Unknown read command: %04x", code); + return FALSE; + default: + log_error("ds28cn01", "Unsupported read mode: %01x (%04x)", cmd, code); + return FALSE; + } +} diff --git a/src/micetools/dll/devices/smb_ds28cn01.h b/src/micetools/dll/devices/smb_ds28cn01.h new file mode 100644 index 0000000..78e1b8c --- /dev/null +++ b/src/micetools/dll/devices/smb_ds28cn01.h @@ -0,0 +1,43 @@ +#include "smbus.h" + +smbus_callback_t smbus_ds28cn01_write; +smbus_callback_t smbus_ds28cn01_read; + +// Specification + +#define DS28CN01_EEPROM_PAGES 4 +#define DS28CN01_EEPROM_PAGE_SIZE 32 +#define DS28CN01_EEPROM_SIZE (DS28CN01_EEPROM_PAGES * DS28CN01_EEPROM_PAGE_SIZE) + +#define DS28CN01_UNIQUE_NUMBER_SIZE 8 +#define DS28CN01_MAC_LEN 20 + +// Registers +#define DS28CN01_REG_NUM 0xA0 +#define DS28CN01_REG_NUM_END (DS28CN01_REG_NUM + DS28CN01_UNIQUE_NUMBER_SIZE - 1) +#define DS28CN01_REG_STATUS 0xA8 +#define DS28CN01_REG_MAC 0xB0 + +// Flags +#define DS28CN01_STATUS_FLAG_BUSY 2 + +// Wiring +#define DS28CN01_GND 0 +#define DS28CN01_VCC 1 +#define DS28CN01_SCL 2 +#define DS28CN01_SDA 3 + +#define DS28CN01_PIN_AD1 DS28CN01_VCC +#define DS28CN01_PIN_AD0 DS28CN01_VCC + +#define DS28CN01_ADDRESS \ + (0b101'00'00 | \ + (((DS28CN01_PIN_AD1 == DS28CN01_GND) ? 0b00 \ + : (DS28CN01_PIN_AD1 == DS28CN01_VCC) ? 0b01 \ + : (DS28CN01_PIN_AD1 == DS28CN01_SCL) ? 0b10 \ + : 0b11) \ + << 2) | \ + ((DS28CN01_PIN_AD0 == DS28CN01_GND) ? 0b00 \ + : (DS28CN01_PIN_AD0 == DS28CN01_VCC) ? 0b01 \ + : (DS28CN01_PIN_AD0 == DS28CN01_SCL) ? 0b10 \ + : 0b11)) diff --git a/src/micetools/dll/devices/smb_exio.c b/src/micetools/dll/devices/smb_exio.c deleted file mode 100644 index c43a3d4..0000000 --- a/src/micetools/dll/devices/smb_exio.c +++ /dev/null @@ -1,53 +0,0 @@ -#include "_devices.h" - -BOOL smbus_EXIO_write(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { - switch (cmd) { - case ICH9_CMD_BYTE_DATA: - switch (code) { - case 0x5c: - if (data[0] == 0x94) return TRUE; - default: - log_error("smb-exio", "Unknown write command: %02x", code); - return FALSE; - } - case ICH9_CMD_BLOCK: { - WORD reg = *(WORD*)(&data[-1]); - dlen = data[1]; - - // char* data_s = malloc(dlen * 3 + 1); - // for (int i = 0; i < dlen; i++) { - // sprintf_s(data_s + i * 3, 3, "%02x ", data[2 + i]); - // } - // data_s[dlen * 3 + 1] = '\0'; - - log_info("smb-exio", "Block write, %d @ %04x: ", dlen, reg); - // free(data_s); - return TRUE; - } - - default: - log_error("smb-exio", "Unsupported write mode: %01x (%02x)", cmd, code); - return FALSE; - } -} - -BOOL smbus_EXIO_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { - switch (cmd) { - case ICH9_CMD_BYTE_DATA: - if (0x40 <= code < 0x40 + 0x14) { - // mxkDsExioReadMacOutputBuffer - // This just has to match N2_I2C_CHALLENGE_RESPONSE! - data[0] = 0x69; - return TRUE; - } else if (code == EXIO_GET_BUSY) { - data[0] = 0x00; // Anything non-zero = busy - return TRUE; - } else { - log_error("smx-exio", "Unknown read command: %02x", code); - return FALSE; - } - default: - log_error("smb-exio", "Unsupported read mode: %01x (%02x)", cmd, code); - return FALSE; - } -} diff --git a/src/micetools/dll/devices/smb_n2.c b/src/micetools/dll/devices/smb_n2.c index 824ed8d..b4eee56 100644 --- a/src/micetools/dll/devices/smb_n2.c +++ b/src/micetools/dll/devices/smb_n2.c @@ -3,6 +3,7 @@ #include #include "../../lib/mxk/mxk.h" +#include "../../sysconf.h" #include "_devices.h" #define N2_TAG_OFFSET 0 @@ -111,19 +112,18 @@ typedef struct { } N2_KEYCHIP_INFO, *PN2_KEYCHIP_INFO; #pragma pack(pop) -N2_KEYCHIP_INFO n2_keychip_info = { - .m_KeyId = { 'A', '7', '2', 'E', '-', '0', '2', 'D', '1', '1', '2', '6', '1', '1', '1', '6' }, - .m_Appboot = { - .m_Format = 1, - .m_GameId = { 'S' , 'D', 'E', 'Y' }, - .m_Region = 0xff, - .m_ModelType = 2, - .m_SystemFlag = 0x24, - .m_PlatformId = {'A', 'A', 'S'}, - .m_DvdFlag = 1, - .m_NetworkAddr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24), - } -}; +N2_KEYCHIP_INFO n2_keychip_info = { .m_KeyId = KEY_ID, + .m_Appboot = { + .m_Format = 1, + .m_GameId = GAME_ID, + .m_Region = 0xff, + .m_ModelType = 2, + .m_SystemFlag = 0x24, + .m_PlatformId = HW_ID, + .m_DvdFlag = 1, + .m_NetworkAddr = + (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24), + } }; WORD n2_enable_session(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nOut) { *nOut = 20; @@ -172,10 +172,13 @@ WORD n2_read_keychip_id(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD nO *nOut = (nbytes & 0xff) + 2; - n2_keychip_info.m_Appboot.m_Crc = amCrc32RGet(sizeof n2_keychip_info.m_Appboot - 4, (LPBYTE)&n2_keychip_info.m_Appboot + 4, 0); - n2_keychip_info.m_Crc = amCrc32RGet(sizeof n2_keychip_info - 4, (LPBYTE)&n2_keychip_info + 4, 0); + n2_keychip_info.m_Appboot.m_Crc = amiCrc32RCalc(sizeof n2_keychip_info.m_Appboot - 4, + (LPBYTE)&n2_keychip_info.m_Appboot + 4, 0); + n2_keychip_info.m_Crc = + amiCrc32RCalc(sizeof n2_keychip_info - 4, (LPBYTE)&n2_keychip_info + 4, 0); - mxkCryptEncryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataOut + 2, (LPBYTE)&n2_keychip_info, nbytes); + mxkCryptEncryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataOut + 2, (LPBYTE)&n2_keychip_info, + nbytes); log_misc("smb-n2", "Read keychip ID: %08x", nbytes); return N2_SUCCESS; @@ -192,9 +195,9 @@ WORD n2_encrypt_with_gkey(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD BYTE temp[16]; mxkCryptDecryptAes128CBC(n2_enc_key.key, n2_enc_key.iv, dataIn + 1, temp, sizeof temp); - for(size_t i=0;i<17;i++)printf(" %02x",dataIn[i]); + for (size_t i = 0; i < 17; i++) printf(" %02x", dataIn[i]); puts(""); - for(size_t i=0;i<17;i++)printf(" %02x",temp[i]); + for (size_t i = 0; i < 17; i++) printf(" %02x", temp[i]); puts(""); // Do Gkey encryption @@ -246,7 +249,6 @@ WORD n2_decrypt_with_skey(WORD paramSize, LPBYTE dataIn, LPBYTE dataOut, LPWORD return N2_SUCCESS; } - n2_command N2_COMMANDS[0xff]; #define N2_INSTALL_COMMAND(ord, tag_, paramSize_, handler_) \ do { \ diff --git a/src/micetools/dll/devices/smb_pca9535.c b/src/micetools/dll/devices/smb_pca9535.c index 3af1aa5..828d980 100644 --- a/src/micetools/dll/devices/smb_pca9535.c +++ b/src/micetools/dll/devices/smb_pca9535.c @@ -74,7 +74,7 @@ BOOL smbus_PCA9535_read(ich9_cmd_t cmd, WORD code, BYTE dlen, BYTE* data) { // data[0] = 0b00001000; // data[0] = 0b0'111'0'000; - data[0] = DIPSW_LANDSCAPE | DIPSW_RES_DEFAULT; + data[0] = DIPSW_LANDSCAPE | DIPSW_RES_1920x1080; return TRUE; case PCA9535_IN1: // SW1/2 + extras diff --git a/src/micetools/dll/devices/smb_pca9535.h b/src/micetools/dll/devices/smb_pca9535.h new file mode 100644 index 0000000..f0996f9 --- /dev/null +++ b/src/micetools/dll/devices/smb_pca9535.h @@ -0,0 +1,14 @@ +#include "smbus.h" + +smbus_callback_t smbus_PCA9535_write; +smbus_callback_t smbus_PCA9535_read; + +#define PCA9535_GND 0 +#define PCA9535_VCC 1 + +#define PCA9535_PIN_A0 PCA9535_GND +#define PCA9535_PIN_A1 PCA9535_GND +#define PCA9535_PIN_A2 PCA9535_GND + +#define PCA9535_ADDRESS \ + (0b0100'000 | (PCA9535_PIN_A2 << 2) | (PCA9535_PIN_A1 << 1) | PCA9535_PIN_A0) diff --git a/src/micetools/dll/dllmain.c b/src/micetools/dll/dllmain.c index 9c872dd..1215040 100644 --- a/src/micetools/dll/dllmain.c +++ b/src/micetools/dll/dllmain.c @@ -3,15 +3,21 @@ #include "drivers/mx.h" #include "hooks/_hooks.h" -WCHAR exePath[MAX_PATH + 1]; +WCHAR exeName[MAX_PATH + 1]; DWORD imageOffset; #define WIN32_EXE_BASE 0x00400000 -DWORD GetImageBase(LPCWSTR sModulePath) { +DWORD GetImageBase(void) { + WCHAR sModulePath[MAX_PATH]; + GetModuleFileNameW(NULL, sModulePath, MAX_PATH); + HANDLE hObject = _CreateFileW(sModulePath, FILE_READ_DATA, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hObject == INVALID_HANDLE_VALUE) return 0; + if (hObject == INVALID_HANDLE_VALUE) { + log_error(BOOT_LOGGER, "Failed to open %ls %03x", sModulePath, GetLastError()); + return 0; + } IMAGE_DOS_HEADER dosHeader = { 0 }; DWORD nRead; @@ -45,17 +51,17 @@ DWORD GetImageBase(LPCWSTR sModulePath) { void apply_patches(HMODULE hModule) { void* baseAddress = (void*)hModule; - DWORD imageBase = GetImageBase(exePath); + DWORD imageBase = GetImageBase(); if (imageBase == 0) { log_error(BOOT_LOGGER, "Failed to locate image base. Patches will not be applied."); return; } imageOffset = (DWORD)hModule - imageBase; - char exePathC[MAX_PATH + 1]; - WideCharToMultiByte(CP_ACP, 0, exePath, -1, exePathC, sizeof exePathC, NULL, NULL); + char exeNameC[MAX_PATH + 1]; + WideCharToMultiByte(CP_ACP, 0, exeName, -1, exeNameC, sizeof exeNameC, NULL, NULL); - if (!load_patches(MiceConfig.mice.patches_file, exePathC)) { + if (!load_patches(MiceConfig.mice.patches_file, exeNameC)) { log_error(BOOT_LOGGER, "Failed to load patches file %s", MiceConfig.mice.patches_file); return; } @@ -89,7 +95,7 @@ void prebind_hooks() { hook_all(); install_devices(); // TODO: Figure out why we're needing to call this manually (medium priority) - if (wcscmp(exePath, L"ALLNetProc.exe") == 0) { + if (wcscmp(exeName, L"ALLNetProc.exe") == 0) { log_warning(BOOT_LOGGER, "Making explicit call to OPENSSL_add_all_algorithms_noconf"); // OPENSSL_add_all_algorithms_noconf @@ -99,13 +105,13 @@ void prebind_hooks() { void init_injection(HMODULE hModule) { // Make sure our CRC32 tables are ready for anything that might want to use them - amCrc32RCreateTable(); + amiCrc32RInit(); load_mice_config(); // We're in a new context now, so need to reconfigure setup_logging(); - log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exePath); + log_info(BOOT_LOGGER, "Handover complete. Now executing within %ls", exeName); if (MiceConfig.mice.apply_patches) apply_patches(hModule); @@ -145,20 +151,20 @@ void tea_hook_test(char* fmt, ...) { BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { if (ul_reason_for_call != DLL_PROCESS_ATTACH) return TRUE; - GetModuleFileNameW(NULL, exePath, MAX_PATH); - wcscpy_s(exePath, MAX_PATH + 1, PathFindFileNameW(exePath)); + GetModuleFileNameW(NULL, exeName, MAX_PATH); + wcscpy_s(exeName, MAX_PATH + 1, PathFindFileNameW(exeName)); HMODULE exeModule = GetModuleHandleA(NULL); init_injection(exeModule); - if (wcscmp(exePath, L"InitialD8_GLW_RE_SBZZ_dumped_.exe") == 0) { - CreateHook((void*)(0x00407850), &tea_hook_test, 5); + if (wcscmp(exeName, L"InitialD8_GLW_RE_SBZZ_dumped_.exe") == 0) { + CreateHook32((void*)(0x00407850), &tea_hook_test); // *((DWORD*)(0x00407850)) = (DWORD)(&logcb); } - if (wcscmp(exePath, L"RingGame.exe") == 0) { + if (wcscmp(exeName, L"RingGame.exe") == 0) { log_warning(BOOT_LOGGER, "Bodge hook goo!"); - CreateHook((void*)(0x005f2580), &tea_hook_test, 5); + CreateHook32((void*)(0x005f2580), &tea_hook_test); } return TRUE; diff --git a/src/micetools/dll/drivers/mxjvs.c b/src/micetools/dll/drivers/mxjvs.c index 5b5c223..40f1908 100644 --- a/src/micetools/dll/drivers/mxjvs.c +++ b/src/micetools/dll/drivers/mxjvs.c @@ -10,8 +10,10 @@ BOOL test_btn = false; #define PLAYER_COUNT 2 #define COIN_COUNTERS 2 +#define SWITCH_BYTES 2 -const char JVS_837_13551_ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10"; +// const char JVS_837_14572_ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-14572 ;Ver1.00;98/10"; +const char JVS_837_14572_ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10"; typedef struct _jvs_board { char test_keybind; @@ -26,6 +28,8 @@ typedef struct _jvs_board { unsigned char* outData, unsigned char* outCount); const char* id; + unsigned char last_sysbuttons; + unsigned short last_buttons[PLAYER_COUNT]; } jvs_board_t; #define JVS_FLAG_NONE 0 #define JVS_FLAG_NC 1 @@ -34,10 +38,6 @@ typedef struct _jvs_board { jvs_board_t (*jvs_config)[]; size_t jvs_num_boards; -// unsigned short coin_data[COIN_COUNTERS]; -// #define JVS_BUTTON_COIN_1 '1' -// #define JVS_BUTTON_COIN_2 '2' - short jvs_unpad(unsigned char* paddedData, short length, unsigned char* unpaddedData) { short index = 0; bool escape = false; @@ -69,6 +69,27 @@ short jvs_pad(unsigned char* unpaddedData, short length, unsigned char* paddedDa return index; } +void update_jvs_buttons(jvs_board_t* board) { + unsigned char sysButtons = 0x00; + if (GetAsyncKeyState(board->test_keybind) < 0) sysButtons |= 0x80; + board->last_sysbuttons = sysButtons; + + for (int player = 0; player < PLAYER_COUNT; player++) { + unsigned short buttons = 0x0000; + for (int i = 0; i < SWITCH_BYTES * 8; i++) { + int scancode = board->keybinds[player][i]; + unsigned char flags = board->flags[player][i]; + + if (flags & JVS_FLAG_NC) continue; + if (flags & JVS_FLAG_INVERT) + buttons |= (GetAsyncKeyState(scancode) >= 0) << i; + else + buttons |= (GetAsyncKeyState(scancode) < 0) << i; + } + board->last_buttons[player] = buttons; + } +} + unsigned char jvs_exchange(jvs_board_t* board, unsigned char* inData, short inCount, unsigned char* response, unsigned char* outCount) { short jvsIndex = 0; @@ -136,7 +157,7 @@ unsigned char jvs_exchange(jvs_board_t* board, unsigned char* inData, short inCo jvs_write(JVS_FEATURE_PLAYERS); jvs_write(PLAYER_COUNT); - jvs_write(13); + jvs_write(13); // bits per player jvs_write(JVS_FEATURE_PAD); jvs_write(JVS_FEATURE_COINS); jvs_write(COIN_COUNTERS); @@ -169,31 +190,15 @@ unsigned char jvs_exchange(jvs_board_t* board, unsigned char* inData, short inCo jvs_write(JVS_REPORT_PARAM_INVALID); break; } + update_jvs_buttons(board); jvs_write(JVS_REPORT_OK); - unsigned char buttons = 0x00; - if (GetAsyncKeyState(board->test_keybind) < 0) buttons |= 0x80; - jvs_write(buttons); - + jvs_write(board->last_sysbuttons); for (int player = 0; player < players; player++) { - for (int j = 0; j < switch_bytes; j++) { - buttons = 0x00; - for (int bit = 0; bit < 8; bit++) { - int scancode = - board->keybinds[player][(switch_bytes - j - 1) * 8 + bit]; - unsigned char flags = - board->flags[player][(switch_bytes - j - 1) * 8 + bit]; - - if (flags & JVS_FLAG_NC) continue; - if (flags & JVS_FLAG_INVERT) - buttons |= (GetAsyncKeyState(scancode) >= 0) << bit; - else - buttons |= (GetAsyncKeyState(scancode) < 0) << bit; - } - jvs_write(buttons); + for (int i = switch_bytes - 1; i >= 0; i--) { + jvs_write((board->last_buttons[player] >> (i * 8)) & 0xff); } } - break; case JVS_CMD_READ_COIN: @@ -323,6 +328,7 @@ void mxjvs_handle(unsigned char* paddedIn, short inCount, unsigned char* outData unsigned char* response = malloc(maxOut); jvs_board_t* board = &(*jvs_config)[jvs_num_boards - destination]; + // jvs_board_t* board = &(*jvs_config)[0]; unsigned char packetSize; unsigned char status = board->handler(board, inData + 3, inData[2] - 1, response + 4, &packetSize); @@ -475,10 +481,10 @@ jvs_board_t maimai_jvs_config[1] = { { }, .coin_counts = {0, 0}, .handler = &jvs_exchange, - .id = JVS_837_13551_ID, + .id = JVS_837_14572_ID, } }; -jvs_board_t under_night_jvs_config[2] = { +jvs_board_t under_night_jvs_config[1] = { { .test_keybind = VK_OEM_4, // [{ .coin_keybinds = {'1', '2'}, @@ -497,57 +503,7 @@ jvs_board_t under_night_jvs_config[2] = { VK_RETURN, // Start }, { - 0 - }, - }, - .flags = { - { - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - JVS_FLAG_NONE, - }, - { - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - }, - }, - .coin_counts = {0, 0}, - .handler = &jvs_exchange, - .id = JVS_837_13551_ID, - }, - { - .test_keybind = VK_OEM_4, // [{ - .coin_keybinds = {0, 0}, - .keybinds = { - { - 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 'J', // D (EXCs) 'P', // C (Heavy) 'O', // B (Middle) @@ -559,7 +515,6 @@ jvs_board_t under_night_jvs_config[2] = { VK_BACK, // Service VK_RETURN, // Start }, - {0}, }, .flags = { { @@ -581,28 +536,105 @@ jvs_board_t under_night_jvs_config[2] = { JVS_FLAG_NONE, }, { + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, JVS_FLAG_NC, JVS_FLAG_NC, JVS_FLAG_NC, JVS_FLAG_NC, JVS_FLAG_NC, JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, - JVS_FLAG_NC, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, + JVS_FLAG_NONE, }, }, .coin_counts = {0, 0}, .handler = &jvs_exchange, - .id = JVS_837_13551_ID, + .id = JVS_837_14572_ID, }, + // { + // .test_keybind = VK_OEM_4, // [{ + // .coin_keybinds = {0, 0}, + // .keybinds = { + // { + // 0, 0, 0, 0, 0, 0, + // 'J', // D (EXCs) + // 'P', // C (Heavy) + // 'O', // B (Middle) + // 'I', // A (Light) + // VK_NUMPAD6, // Right + // VK_NUMPAD4, // Left + // VK_NUMPAD2, // Down + // VK_NUMPAD8, // Up + // VK_BACK, // Service + // VK_RETURN, // Start + // }, + // {0}, + // }, + // .flags = { + // { + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // JVS_FLAG_NONE, + // }, + // { + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // JVS_FLAG_NC, + // }, + // }, + // .coin_counts = {0, 0}, + // .handler = &jvs_exchange, + // .id = JVS_837_14572_ID, + // }, }; // jvs_board_t (*jvs_config)[] = &maimai_jvs_config; diff --git a/src/micetools/dll/drivers/mxparallel.c b/src/micetools/dll/drivers/mxparallel.c index 8eecff8..814312b 100644 --- a/src/micetools/dll/drivers/mxparallel.c +++ b/src/micetools/dll/drivers/mxparallel.c @@ -1,24 +1,25 @@ #include "mxparallel.h" +#include "../../sysconf.h" + BYTE parallel_flags = 0x00; BYTE parallel_ctrl = 0x00; BYTE parallel_status = 0x00; BYTE parallel_data = 0x00; -BYTE KEYCHIP_ID[16] = { 'A', '7', '2', 'E', '-', '0', '2', 'D', - '1', '1', '2', '6', '1', '1', '1', '6' }; -BYTE MAIN_ID[16] = { 'A', 'A', 'S', 'E', '-', '0', '1', 'A', '6', '5', '6', '4' }; +BYTE KEYCHIP_ID[16] = KEY_ID; +BYTE _MAIN_ID[16] = MAIN_ID; appboot_t APPBOOT = { .format = 1, - .game_id = { 'S', 'D', 'E', 'Y' }, + .game_id = GAME_ID, .region = 8 | 4 | 2 | 1, .model_type = 2, // Bitfield // 1 = use flash for appboot .system_flag = 0x24, ._ = 0, - .platform_id = { 'A', 'A', 'S' }, + .platform_id = HW_ID, .dvd_flag = 1, .network_addr = (192 << 0) | (168 << 8) | (103 << 16) | (0 << 24), .__ = 0, @@ -155,7 +156,7 @@ void init_nv_storage() { billing_info.nearfull = 512; mxkSignValue(billing_info.nearfull, billing_info.nearfull_sig); mxkSignValue(billing_info.playlimit, billing_info.playlimit_sig); - billing_info.crc = amCrc32RGet(sizeof billing_info - 4, (unsigned char*)&billing_info + 4, 0); + billing_info.crc = amiCrc32RCalc(sizeof billing_info - 4, (unsigned char*)&billing_info + 4, 0); memcpy(&flash[0x7a000], &billing_info, sizeof billing_info); memcpy(&flash[0x7b000], &billing_info, sizeof billing_info); @@ -263,7 +264,7 @@ void mxparallel_process_packet(BYTE* request) { log_warning("mxparallel", "GetAppBootInfo[%d] unexpected!", request[1]); } - APPBOOT.crc = amCrc32RGet(sizeof APPBOOT - 4, (unsigned char*)&APPBOOT + 4, 0); + APPBOOT.crc = amiCrc32RCalc(sizeof APPBOOT - 4, (unsigned char*)&APPBOOT + 4, 0); for (int i = 0; i < sizeof APPBOOT; i += 16) { micexkSendPacket((unsigned char*)(&APPBOOT) + i); } @@ -381,14 +382,14 @@ void mxparallel_process_packet(BYTE* request) { case SetMainId: log_info("mxparallel", "SetMainId"); - // micexkRecvPacket(MAIN_ID); + // micexkRecvPacket(_MAIN_ID); micexkRecvPacket(request); response[0] = 0xff; micexkSendPacket(response); break; case GetMainId: log_info("mxparallel", "GetMainId"); - micexkSendPacket(MAIN_ID); + micexkSendPacket(_MAIN_ID); break; case SetKeyId: log_info("mxparallel", "SetKeyId"); diff --git a/src/micetools/dll/drivers/mxsmbus.c b/src/micetools/dll/drivers/mxsmbus.c index ffcf105..42a56e1 100644 --- a/src/micetools/dll/drivers/mxsmbus.c +++ b/src/micetools/dll/drivers/mxsmbus.c @@ -69,9 +69,6 @@ BOOL handle_smbus(BYTE command, WORD v_addr, WORD command_code, BYTE nbytes, BYT BOOL WINAPI mxsmbus_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { - mxsmbus_i2c_packet* i2c_packet = (mxsmbus_i2c_packet*)lpInBuffer; - mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer; - // Default value if (lpBytesReturned) *lpBytesReturned = nOutBufferSize; diff --git a/src/micetools/dll/drivers/mxsram.c b/src/micetools/dll/drivers/mxsram.c index 37432d4..348482f 100644 --- a/src/micetools/dll/drivers/mxsram.c +++ b/src/micetools/dll/drivers/mxsram.c @@ -35,7 +35,7 @@ void sram_restore() { #define fix_crc(block) \ do { \ - (block).m_Crc = amCrc32RGet(sizeof(block) - 4, (BYTE*)(&(block)) + 4, 0); \ + (block).m_Crc = amiCrc32RCalc(sizeof(block) - 4, (BYTE*)(&(block)) + 4, 0); \ } while (0) int build_sram() { diff --git a/src/micetools/dll/hooks/_hooks.h b/src/micetools/dll/hooks/_hooks.h index 10d30c3..4b18174 100644 --- a/src/micetools/dll/hooks/_hooks.h +++ b/src/micetools/dll/hooks/_hooks.h @@ -1,15 +1,15 @@ #pragma once #include "com.h" +#include "drive/drive.h" #include "files.h" #include "gui.h" #include "logging.h" #include "network.h" #include "processes.h" -#include "setupapi_.h" -#include "time.h" #include "registry.h" -#include "drive.h" +#include "setupapi_.h" #include "system.h" +#include "time.h" void hook_all(); diff --git a/src/micetools/dll/hooks/com.c b/src/micetools/dll/hooks/com.c index e65674f..925ff26 100644 --- a/src/micetools/dll/hooks/com.c +++ b/src/micetools/dll/hooks/com.c @@ -159,14 +159,14 @@ BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) } void hook_commio() { - hook("Kernel32.dll", "GetCommState", FakeGetCommState, (void**)&TrueGetCommState, 6); - hook("Kernel32.dll", "SetCommState", FakeSetCommState, (void**)&TrueSetCommState, 6); - hook("Kernel32.dll", "GetCommTimeouts", FakeGetCommTimeouts, (void**)&TrueGetCommTimeouts, 6); - hook("Kernel32.dll", "SetCommTimeouts", FakeSetCommTimeouts, (void**)&TrueSetCommTimeouts, 6); - hook("Kernel32.dll", "SetupComm", FakeSetupComm, (void**)&TrueSetupComm, 6); - hook("Kernel32.dll", "PurgeComm", FakePurgeComm, (void**)&TruePurgeComm, 6); + hook("Kernel32.dll", "GetCommState", FakeGetCommState, (void**)&TrueGetCommState); + hook("Kernel32.dll", "SetCommState", FakeSetCommState, (void**)&TrueSetCommState); + hook("Kernel32.dll", "GetCommTimeouts", FakeGetCommTimeouts, (void**)&TrueGetCommTimeouts); + hook("Kernel32.dll", "SetCommTimeouts", FakeSetCommTimeouts, (void**)&TrueSetCommTimeouts); + hook("Kernel32.dll", "SetupComm", FakeSetupComm, (void**)&TrueSetupComm); + hook("Kernel32.dll", "PurgeComm", FakePurgeComm, (void**)&TruePurgeComm); hook("Kernel32.dll", "GetCommModemStatus", FakeGetCommModemStatus, - (void**)&TrueGetCommModemStatus, 6); - hook("Kernel32.dll", "WaitCommEvent", FakeWaitCommEvent, (void**)&TrueWaitCommEvent, 6); - hook("Kernel32.dll", "ClearCommError", FakeClearCommError, (void**)&TrueClearCommError, 6); + (void**)&TrueGetCommModemStatus); + hook("Kernel32.dll", "WaitCommEvent", FakeWaitCommEvent, (void**)&TrueWaitCommEvent); + hook("Kernel32.dll", "ClearCommError", FakeClearCommError, (void**)&TrueClearCommError); } \ No newline at end of file diff --git a/src/micetools/dll/hooks/drive.c b/src/micetools/dll/hooks/drive.c deleted file mode 100644 index 4ca0aa1..0000000 --- a/src/micetools/dll/hooks/drive.c +++ /dev/null @@ -1,904 +0,0 @@ -#include "drive.h" - -#include -#include - -#include "./files.h" - -typedef struct _physical_disk physical_disk_t; -typedef struct _disk_partition disk_partition_t; -typedef struct _disk_volume disk_volume_t; - -struct _disk_volume { - wchar_t m_FilenameW[MAX_PATH + 1]; - char m_FilenameA[MAX_PATH + 1]; - LPSTR m_Name; - char m_MountPoint; - - // Back-references - physical_disk_t* m_pDrive; - disk_partition_t* m_pPartition; - BOOL m_NameIsOnHeap; -}; -struct _disk_partition { - DWORD m_Size; - UCHAR m_Filesystem; - spd_slot_t m_SPDContent; - UCHAR* m_Content; - LONGLONG m_ContentSize; - - disk_volume_t m_Volume; - - DWORD m_PhysicalLBA; - DWORD m_SlotLBA; - DWORD m_PartitionNumber; -}; -struct _physical_disk { - DWORD m_DriveNumber; - STORAGE_BUS_TYPE m_BusType; - LPSTR m_VID; - LPSTR m_PID; - DWORD m_BootPartition; - BOOL m_HasSegaboot; - - disk_partition_t m_Partitions[4]; - disk_partition_t m_Extended[]; -}; - -/* - First 512 bytes of SPD_Original0: - LOADER::LoadBootIDHeader -*/ -BYTE Original0BootIDHeader[512] = { - 0x4B, 0xDF, 0xB4, 0x43, 0x27, 0x3C, 0xFE, 0xD6, 0xA2, 0xA8, 0xF8, 0xFD, 0xB4, 0x55, 0xE6, 0xBA, - 0x5A, 0x0F, 0xBF, 0x14, 0xA4, 0x37, 0xB6, 0x42, 0xB3, 0xAD, 0x11, 0x4A, 0xCA, 0x1A, 0x4C, 0xD9, - 0x11, 0xF1, 0x60, 0x4B, 0x37, 0x58, 0x9C, 0x9A, 0x89, 0x8F, 0x07, 0x9C, 0xE7, 0xF2, 0x64, 0xCC, - 0x6E, 0x84, 0x87, 0xAA, 0x20, 0xA0, 0xB8, 0x55, 0x9B, 0xE7, 0x79, 0x4F, 0x51, 0x25, 0xC3, 0x7E, - 0xEF, 0xD9, 0x25, 0xA9, 0x94, 0xF1, 0x7F, 0xEF, 0xE1, 0xD9, 0xAE, 0x4F, 0xC2, 0xEE, 0xB6, 0xA8, - 0xD9, 0x54, 0x0F, 0x33, 0xA8, 0xA9, 0x22, 0x72, 0x81, 0xD0, 0xA3, 0x04, 0x5C, 0x45, 0x3E, 0xBE, - 0xF7, 0x2A, 0xED, 0x55, 0xAB, 0x16, 0xC1, 0xA8, 0x61, 0x70, 0xEE, 0x55, 0xCB, 0xE6, 0x68, 0xA5, - 0xB4, 0xDC, 0x30, 0x6D, 0x32, 0xD6, 0x69, 0x8D, 0xFC, 0x90, 0x71, 0x7E, 0xDB, 0x6B, 0x17, 0xFA, - 0xAB, 0xE0, 0x11, 0x14, 0xBA, 0xD9, 0x33, 0xB7, 0x7C, 0x54, 0x9E, 0x21, 0xA1, 0x43, 0xFD, 0x8F, - 0x14, 0xF4, 0xBE, 0x5F, 0x0B, 0x02, 0x8E, 0x87, 0xCA, 0x85, 0xE9, 0xC1, 0x60, 0xF7, 0x7E, 0x44, - 0x55, 0x3A, 0x5E, 0x94, 0x65, 0x95, 0xFD, 0x02, 0xF9, 0xFF, 0xBF, 0x07, 0x80, 0xC5, 0x26, 0x58, - 0x6F, 0x37, 0xFA, 0x59, 0x2F, 0x02, 0xF3, 0x9D, 0x24, 0x7D, 0x42, 0x6B, 0xF3, 0x49, 0x63, 0xC9, - 0x2A, 0xCB, 0xFC, 0x71, 0x69, 0x44, 0xB5, 0xAC, 0xD3, 0x37, 0xA0, 0x01, 0x65, 0x3D, 0x49, 0xC4, - 0x7D, 0xE5, 0xF8, 0x6E, 0x09, 0xC7, 0x3E, 0xD1, 0x96, 0x09, 0x23, 0xA4, 0xE8, 0xA5, 0x6A, 0xA2, - 0x5B, 0x5B, 0xA5, 0x9C, 0xF8, 0x8D, 0x84, 0x55, 0x3F, 0x19, 0x8F, 0xDC, 0xFA, 0x7B, 0xF1, 0xC9, - 0xB6, 0xBF, 0xE8, 0x73, 0xB9, 0xC9, 0xC3, 0x17, 0x14, 0xAB, 0xA3, 0x60, 0x13, 0xED, 0x6D, 0xCC, - 0x10, 0x7B, 0x1D, 0xC6, 0xBC, 0xEC, 0x56, 0xFA, 0x52, 0xC5, 0x4E, 0xAC, 0x8F, 0x36, 0x8B, 0x92, - 0x6C, 0xB5, 0x9A, 0x57, 0x7D, 0xFA, 0x97, 0x72, 0xFC, 0xFA, 0xB8, 0xFE, 0x20, 0x71, 0xFB, 0x63, - 0x00, 0x96, 0x29, 0xCE, 0xE2, 0x06, 0xFF, 0x64, 0x48, 0xB5, 0x1F, 0xD6, 0x88, 0x48, 0x7A, 0x62, - 0x2B, 0xBE, 0xE6, 0xC4, 0xFD, 0xF6, 0x85, 0x45, 0x0A, 0x8C, 0x6C, 0x20, 0x64, 0x05, 0x81, 0x13, - 0xB5, 0x59, 0xAE, 0x34, 0x41, 0x0B, 0xB5, 0x65, 0x57, 0x59, 0x9C, 0xE8, 0xD0, 0xAE, 0x81, 0xD8, - 0x6D, 0xC9, 0xFD, 0xF8, 0xC9, 0x15, 0xB6, 0xDC, 0xC9, 0x13, 0xF2, 0x6E, 0xD9, 0xA5, 0x77, 0x62, - 0xB7, 0x15, 0x61, 0x21, 0x73, 0xFE, 0x0A, 0x57, 0x3B, 0x2C, 0x2F, 0x23, 0xC3, 0x33, 0xB8, 0x77, - 0xCE, 0xCE, 0x76, 0x98, 0xDB, 0xE5, 0x9A, 0x00, 0xE1, 0xC3, 0x6F, 0x7D, 0x42, 0xC4, 0xDE, 0xB7, - 0x1D, 0xA0, 0xC1, 0x1C, 0xB9, 0x09, 0x28, 0xD9, 0x59, 0x9D, 0x3F, 0xEA, 0xF1, 0xB6, 0xA0, 0x1C, - 0x5E, 0x4A, 0xE4, 0x1A, 0xE7, 0xA7, 0x1C, 0xAD, 0xF6, 0xF1, 0xCB, 0x9C, 0x06, 0xE6, 0x4C, 0xF4, - 0xD6, 0xEE, 0x5F, 0x18, 0xF5, 0x00, 0x4A, 0x76, 0x5E, 0x7D, 0x96, 0x20, 0x57, 0x68, 0x23, 0x69, - 0x8F, 0x60, 0x91, 0xBF, 0x00, 0x08, 0xFE, 0x4F, 0x36, 0x45, 0x86, 0x14, 0x48, 0xC5, 0x8B, 0xEA, - 0xE3, 0x64, 0x27, 0x1E, 0x49, 0xDF, 0x98, 0xAD, 0xE2, 0x66, 0x09, 0x07, 0xDD, 0x24, 0xB0, 0x4D, - 0x52, 0xA6, 0xD1, 0x3D, 0xB9, 0x52, 0x0B, 0x88, 0x97, 0x97, 0x0F, 0x83, 0x85, 0xD5, 0x3F, 0x0E, - 0x1A, 0xF2, 0x26, 0xBA, 0x14, 0x53, 0xDD, 0xF4, 0x7D, 0xAF, 0xB6, 0xEE, 0x36, 0x3A, 0xB5, 0xDA, - 0x2F, 0x99, 0xC8, 0x54, 0xD2, 0xDB, 0x52, 0x49, 0xD6, 0xB6, 0x07, 0x1A, 0xBA, 0x9A, 0x85, 0xBB, -}; - -physical_disk_t SSD = { - .m_DriveNumber = 0, - .m_BusType = BusTypeAta, - .m_BootPartition = 1, - .m_HasSegaboot = TRUE, - .m_Partitions = { - // 1.5GB boot partitions - { - .m_Size = 0x300B85, - .m_Filesystem = MBR_FS_NTFS, - }, - // 1.5GB recovery partitions - { - .m_Size = 0x300BC4, - .m_Filesystem = MBR_FS_NTFS, - }, - }, - .m_Extended = { - { 0x102d83, MBR_FS_FAT16, SPD_OS }, // 512MB OS update - { 0x403947, MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0 - { 0x403947, MBR_FS_FAT16, SPD_Patch1 }, // 2GB patch1 - { 0x48ed459, MBR_FS_NTFS, SPD_AppData }, // 40GB something - { - 0x20014aa, - MBR_FS_FAT16, - SPD_Original0, - .m_Content = Original0BootIDHeader, - .m_ContentSize = sizeof Original0BootIDHeader, - }, // 16GB game - { 0 }, - }, -}; -physical_disk_t UPDATE_USB = { - .m_DriveNumber = 1, - .m_BusType = BusTypeUsb, - .m_VID = "13FE", - .m_PID = "4200", - .m_Partitions = { - // 59050 MB update partitions - { - .m_Size = 0x735a080, - .m_Filesystem = MBR_FS_NTFS, - .m_Volume = { - .m_Name = "SEGA_INS", - }, - }, - }, - .m_Extended = {{0}}, -}; -physical_disk_t* PHYSICAL_DISKS[] = { &SSD, &UPDATE_USB }; - -BOOL WINAPI c_drive_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, - DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, - LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { - log_trace("C", "DeviceIOControl %08x", dwIoControlCode); - ZeroMemory(lpOutBuffer, nOutBufferSize); - switch (dwIoControlCode) { - case IOCTL_STORAGE_GET_DEVICE_NUMBER: - ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK; - ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceNumber = 0; - return TRUE; - case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: - ((VOLUME_DISK_EXTENTS*)lpOutBuffer)->NumberOfDiskExtents = 1; - ((VOLUME_DISK_EXTENTS*)lpOutBuffer)->Extents[0].DiskNumber = 0; - return TRUE; - default: - return FALSE; - } -} - -BOOL WINAPI x_drive_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, - DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, - LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { - log_trace("X", "DeviceIOControl %08x", dwIoControlCode); - ZeroMemory(lpOutBuffer, nOutBufferSize); - switch (dwIoControlCode) { - case IOCTL_STORAGE_GET_DEVICE_NUMBER: - ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK; - ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceNumber = 0; - return TRUE; - default: - log_warning("X", "Unhandled DeviceIOControl %08x", dwIoControlCode); - return FALSE; - } -} - -BOOL WINAPI pd_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, - DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, - LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { - physical_disk_t* pd = (physical_disk_t*)ctx->m_HookData; - if (pd == NULL) { - log_error("drive", "ioctl:ctx->m_HookData NULL; expected a physical drive!"); - return FALSE; - } - - log_trace("drive", "DeviceIOControl %08x", dwIoControlCode); - ZeroMemory(lpOutBuffer, nOutBufferSize); - switch (dwIoControlCode) { - case IOCTL_ATA_PASS_THROUGH: - if (pd->m_BusType != BusTypeAta) return FALSE; - - PATA_PASS_THROUGH_EX ata = (PATA_PASS_THROUGH_EX)lpInBuffer; - - BYTE command = ata->CurrentTaskFile[6]; - if (command != 0xC1) { - log_error("pd0", "Unimplemented ATA command: %02x", command); - return FALSE; - } - - BYTE data = ata->CurrentTaskFile[0]; - switch (data) { - // These are used un UnlockSection1, 2, and 3 in mxstorage! - - case 0x11: // mxkSsdHostProofSet (step == 0) - // Game -> ATA | 128 bytes: random from N2 - case 0x12: // mxkSsdHostProofGet (step == 0) - // ATA -> GAME | 128 bytes: (guess) readback of 0x11 - case 0x21: // mxkSsdHostProofSet (step == 1) - // Game -> ATA | 128 bytes: random from N2 - case 0x22: // mxkSsdHostProofGet (step == 1) - // ATA -> GAME | 128 bytes: (guess) readback of 0x21 - case 0x31: // mxkSsdHostProofSeed - // ATA -> Game | 80 bytes: seed - case 0x32: // mxkSsdHostProofChallenge - // Game -> ATA | 80 bytes: the seed, encrypted by N2 with S-Key - - // It looks like mxkeychip never actually checks the response buffer, - // as long as the ioctl succeeds! Saves us a lot of work here! - return TRUE; - } - log_error("drive", "Unimeplemented ATA C1 command: %02x", data); - return FALSE; - } - log_error("drive", "Unimplemented ioctl: %08x", dwIoControlCode); - return FALSE; -} - -sbr_t SegaBootRecord = { - .version = SBR_VERSION, - .bootslot = 0x02, - - .slot_status = { Slot_Complete, Slot_Complete, Slot_Invalid, Slot_Check, Slot_Complete }, - - .slot_os = { - // Starts at 0xc5469400 - // i.e. [partition 6] - (segcount * segsize) - // i.e. partition 5 = [dead space] [slot_os] - .id = {'A', 'A', 'S', '0'}, - .time = { 0 }, - .version = 0x450a01, - .segcount = 1745, - .segsize = 0x40000, - .hw = { 'A', 'A', 'S' }, - .instant = 0, - .osver = 0x450a01, - .ossegcount = 0, - .orgtime = { 0 }, - .orgversion = 0x450a01, - }, - .slot_original0 = { - // Starts at 0xb065bae00 - // i.e. [end of disk] - (segcount * segsize) - // i.e. partition 9 = [dead space] [slot_original0] - - .id = {'S', 'D', 'E', 'Y'}, - .time = { 2018, 10, 29, 15, 7, 36 }, - .version = 0x10061, - .segcount = 65082, - .segsize = 0x40000, - .hw = { 'A', 'A', 'S' }, - .instant = 0, - .osver = 0x450a01, - .ossegcount = 1745, - .orgtime = { 2018, 10, 29, 15, 7, 36 }, - .orgversion = 0x10061, - }, - .slot_appdata = { 0 }, - .slot_patch0 = { - // Starts at 0x15e49a000 - // i.e. [partition 7] - (segcount * segsize) - // i.e. partition 6 = [dead space] [something] [patch0] - - .id = { 'S', 'D', 'D', 'Z' }, - .time = { 2018, 6, 21, 13, 46, 24 }, - .version = 0x10060, - .segcount = 173, - .segsize = 0x40000, - .hw = { 'A', 'A', 'S' }, - .instant = 0, - .osver = 0, - .ossegcount = 0, - .orgtime = { 2018, 5, 16, 20, 7, 12 }, - .orgversion = 0x01005f, - }, - .slot_patch1 = { - // Starts at 0x1debcac00 - // i.e. [partition 8] - (segcount * segsize) - // i.e. partition 7 = [dead space] [something] [patch0] - - .id = { 'S', 'D', 'E', 'Y' }, - .time = { 2018, 11, 16, 19, 4, 48}, - .version = 0x10062, - .segcount = 173, - .segsize = 0x40000, - .hw = { 'A', 'A', 'S' }, - .instant = 0, - .osver = 0, - .ossegcount = 0, - .orgtime = { 2018, 10, 29, 15, 7, 36 }, - .orgversion = 0x10061, - }, -}; - -// Partitions -#define BOOT_PARITION_SIZE 0x300B85 // 1.5GB -#define RECOVER_PARTITION_SIZE 0x300BC4 // 1.5GB -typedef struct { - uint32_t size; - uint8_t type; - spd_slot_t content; - uint32_t offset; - LONGLONG slot_offset; -} partition_t; -#define PARITION_OS 0 -#define PARITION_PATCH0 1 -#define PARITION_PATCH1 2 -#define PARITION_APP_DATA 3 -#define PARITION_ORIGINAL0 4 - -#define MBR_LBA_GAP 0x3f // 1 track worth of sectors is claimed for the MBR -#define EXT_HEADER_GAP 0x3f - -#define BLOCKSIZE 512ll - -#define SPD_OFFSET 1 -#define SBR0_OFFSET 2 -#define SBR1_OFFSET 3 - -// Drives -/** - * VID_0CA3 = SEGA CORPROATION - * VID_0928 = PLX / Oxford Semiconductor - * VID/PID pairs for B: - * 0CA3/000E - * 0928/0007 - * 0CA3/000C - * - * Mountpoints based on drive name: - * Z: DEV - * L: SEGA_AM_LOG - */ - -// Volumes -typedef struct { - size_t disk; - size_t partition; -} find_index_t; - -sbr_slot_t* get_sbr_slot(spd_slot_t slot) { - switch (slot) { - case SPD_Original0: - return &SegaBootRecord.slot_original0; - case SPD_Original1: - return NULL; - case SPD_Patch0: - return &SegaBootRecord.slot_patch0; - case SPD_Patch1: - return &SegaBootRecord.slot_patch1; - case SPD_OS: - return &SegaBootRecord.slot_os; - case SPD_AppData: - return &SegaBootRecord.slot_appdata; - default: - return NULL; - } -} - -BOOL pd_ReadFile(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, - LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { - physical_disk_t* pd = (physical_disk_t*)ctx->m_HookData; - if (pd == NULL) { - log_error("drive", "read:ctx->m_HookData NULL; expected a physical drive!"); - return FALSE; - } - - log_info("drive", "PhysicalDrive%d: Read %d @ %llx", pd->m_DriveNumber, nNumberOfBytesToRead, - ctx->m_Pointer.QuadPart); - - // ! WARNING: This ReadFile implementation is currently limited to aligned - // ! reads. Given the main purpose of this function is to allow reading - // ! the partition information, this doesn't currently pose an issue. - - DWORD ptrLBA = (ctx->m_Pointer.QuadPart / BLOCKSIZE) & 0xffffffff; - - // MBR header - if (ptrLBA == 0) { - mbr_t* mbr = (mbr_t*)lpBuffer; - if (nNumberOfBytesToRead < sizeof *mbr) { - log_error("drive", "Buffer too small for master boot record!"); - return FALSE; - } - - memset(mbr, 0, sizeof *mbr); - mbr->sig[0] = 0x55; - mbr->sig[1] = 0xAA; - - for (size_t i = 0; i < 4; i++) { - if (pd->m_Partitions[i].m_Size == 0) break; - - mbr->partitions[i].status = - (pd->m_BootPartition == i + 1) ? MBR_FLAG_BOOTABLE : MBR_FLAG_NONE; - mbr->partitions[i].type = pd->m_Partitions[i].m_Filesystem; - mbr->partitions[i].lba = pd->m_Partitions[i].m_PhysicalLBA; - mbr->partitions[i].sectors = pd->m_Partitions[i].m_Size; - } - - *lpNumberOfBytesRead = sizeof *mbr; - - return TRUE; - } - if (ptrLBA <= MBR_LBA_GAP) { - // Read within the 63 extra tracks - log_error("drive", "Read failed"); - return FALSE; - } - - // MBR partitions - for (size_t i = 0; i < 4; i++) { - if (pd->m_Partitions[i].m_PartitionNumber == 0) break; - - if (ptrLBA >= pd->m_Partitions[i].m_PhysicalLBA && - ptrLBA < pd->m_Partitions[i].m_PhysicalLBA + pd->m_Partitions[i].m_Size) { - DWORD readOffset = ptrLBA - pd->m_Partitions[i].m_PhysicalLBA; - int willRead = pd->m_Partitions[i].m_ContentSize - (readOffset * BLOCKSIZE); - if (willRead > nNumberOfBytesToRead) willRead = nNumberOfBytesToRead; - - if (willRead < 0) { - log_error("disk", "Attempted read in %d/%d at block offset %08x; No data to read!", - pd->m_DriveNumber, pd->m_Partitions[i].m_PartitionNumber, readOffset); - return FALSE; - } - - memcpy(lpBuffer, pd->m_Partitions[i].m_Content, willRead); - *lpNumberOfBytesRead = willRead; - - log_info("drive", "Read at %d/%d+%d", pd->m_DriveNumber, - pd->m_Partitions[i].m_PartitionNumber, readOffset); - return TRUE; - } - } - - // Extended partitions - for (size_t i = 0; pd->m_Extended[i].m_Size; i++) { - // Extended header - DWORD headerLBA = pd->m_Extended[i].m_PhysicalLBA - EXT_HEADER_GAP; - if (ptrLBA == headerLBA) { - mbr_t* mbr = (mbr_t*)lpBuffer; - if (nNumberOfBytesToRead < sizeof *mbr) { - log_error("drive", "Buffer too small for an extended boot record!"); - return FALSE; - } - - memset(mbr, 0, sizeof *mbr); - mbr->sig[0] = 0x55; - mbr->sig[1] = 0xAA; - - mbr->partitions[0].status = MBR_FLAG_NONE; - mbr->partitions[0].type = pd->m_Extended[i].m_Filesystem; - mbr->partitions[0].lba = EXT_HEADER_GAP; - mbr->partitions[0].sectors = pd->m_Extended[i].m_Size; - - if (pd->m_Extended[i + 1].m_Size) { - mbr->partitions[1].status = MBR_FLAG_NONE; - // ! mxinstaller expects to see CHS here, then uses the LBA values - mbr->partitions[1].type = MBR_FS_EXT_CHS; - mbr->partitions[1].lba = - pd->m_Extended[i + 1].m_PhysicalLBA - pd->m_Extended[0].m_PhysicalLBA; - mbr->partitions[1].sectors = pd->m_Extended[i + 1].m_Size + EXT_HEADER_GAP; - } - - *lpNumberOfBytesRead = sizeof *mbr; - return TRUE; - } - - if (i == 0 && pd->m_HasSegaboot) { - // SEGA Partition Description - if (ptrLBA == headerLBA + SPD_OFFSET) { - spd_t* spd = (spd_t*)lpBuffer; - if (nNumberOfBytesToRead < sizeof *spd) { - log_error("drive", "Buffer too small for SPD!"); - return FALSE; - } - - spd->version = SPD_VERSION; - for (size_t j = 0; pd->m_Extended[j].m_Size; j++) { - spd->slots[j].block_size = BLOCKSIZE; - spd->slots[j].block_count = pd->m_Extended[j].m_Size; - spd->slots[j].slot_content = pd->m_Extended[j].m_SPDContent; - spd->slots[j].uk1 = pd->m_Extended[j].m_Filesystem == MBR_FS_FAT16 ? 0 : 1; - } - - spd->crc = amCrc32RGet(sizeof *spd - 4, &(spd->version), 0); - *lpNumberOfBytesRead = sizeof *spd; - return TRUE; - } - // SEGA Boot Record 0 and 1. The two are a redundant copy of each other - if (ptrLBA == headerLBA + SBR0_OFFSET || ptrLBA == headerLBA + SBR1_OFFSET) { - SegaBootRecord.crc = amCrc32RGet(sizeof SegaBootRecord - 4, &SegaBootRecord.version, 0); - - memcpy(lpBuffer, &SegaBootRecord, sizeof SegaBootRecord); - *lpNumberOfBytesRead = sizeof SegaBootRecord; - return TRUE; - } - } - - if (ptrLBA >= pd->m_Extended[i].m_PhysicalLBA - EXT_HEADER_GAP && - ptrLBA < pd->m_Extended[i].m_PhysicalLBA) { - // Read within the 63 extra tracks - log_error("drive", "Read failed"); - return FALSE; - } - - if (ptrLBA >= pd->m_Extended[i].m_PhysicalLBA && - ptrLBA < pd->m_Extended[i].m_PhysicalLBA + pd->m_Extended[i].m_Size) { - DWORD readOffset = ptrLBA - pd->m_Extended[i].m_PhysicalLBA; - int willRead = pd->m_Extended[i].m_ContentSize - (readOffset * BLOCKSIZE); - if (willRead > nNumberOfBytesToRead) willRead = nNumberOfBytesToRead; - - if (willRead < 0) { - log_error("disk", "Attempted read in %d/%d at block offset %08x; No data to read!", - pd->m_DriveNumber, pd->m_Extended[i].m_PartitionNumber, readOffset); - return FALSE; - } - - memcpy(lpBuffer, pd->m_Extended[i].m_Content, willRead); - *lpNumberOfBytesRead = willRead; - - log_info("drive", "Read at %d/%d+%d", pd->m_DriveNumber, - pd->m_Partitions[i].m_PartitionNumber, readOffset); - return TRUE; - } - } - - log_error("drive", "Read failed"); - return FALSE; -} - -BOOL pd_WriteFile(file_context_t* ctx, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, - LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { - physical_disk_t* pd = (physical_disk_t*)ctx->m_HookData; - if (pd == NULL) { - log_error("drive", "write:ctx->m_HookData NULL; expected a physical drive!"); - return FALSE; - } - - log_warning("drive", "PhysicalDrive%d: Write %d @ %llx", pd->m_DriveNumber, - nNumberOfBytesToWrite, ctx->m_Pointer.QuadPart); - - for (DWORD i = 0; i < nNumberOfBytesToWrite; i += 32) { - for (int j = 0; j < 32; j++) { - printf("%02x ", ((BYTE*)lpBuffer)[i + j]); - } - puts(""); - } - - *lpNumberOfBytesWritten = nNumberOfBytesToWrite; - return TRUE; -} - -disk_volume_t* incrementFindIndex(HANDLE hFindVolume) { - find_index_t* find_index = GetDataForHandle(hFindVolume, HDATA_FIND_VOLUME); - if (find_index == NULL) return NULL; - - while (1) { - if (find_index->disk >= sizeof PHYSICAL_DISKS / sizeof PHYSICAL_DISKS[0]) { - return NULL; - } - - if (find_index->partition > 3) { - if (PHYSICAL_DISKS[find_index->disk] - ->m_Extended[find_index->partition - 4] - .m_PartitionNumber == 0) { - find_index->disk++; - find_index->partition = 0; - continue; - } - - return &(PHYSICAL_DISKS[find_index->disk] - ->m_Extended[(find_index->partition++) - 4] - .m_Volume); - } - if (PHYSICAL_DISKS[find_index->disk] - ->m_Partitions[find_index->partition] - .m_PartitionNumber == 0) { - find_index->partition = 4; - continue; - } - - return &(PHYSICAL_DISKS[find_index->disk]->m_Partitions[find_index->partition++].m_Volume); - } -} -BOOL WINAPI FakeFindNextVolumeW(HANDLE hFindVolume, LPWSTR lpszVolumeName, DWORD cchBufferLength) { - disk_volume_t* volume = incrementFindIndex(hFindVolume); - if (volume == NULL) { - SetLastError(ERROR_NO_MORE_FILES); - return FALSE; - } - - wcscpy_s(lpszVolumeName, cchBufferLength, volume->m_FilenameW); - wcscat_s(lpszVolumeName, cchBufferLength, L"\\"); - return TRUE; -} -BOOL WINAPI FakeFindNextVolumeA(HANDLE hFindVolume, LPSTR lpszVolumeName, DWORD cchBufferLength) { - disk_volume_t* volume = incrementFindIndex(hFindVolume); - if (volume == NULL) { - SetLastError(ERROR_NO_MORE_FILES); - return FALSE; - } - - strcpy_s(lpszVolumeName, cchBufferLength, volume->m_FilenameA); - strcat_s(lpszVolumeName, cchBufferLength, "\\"); - return TRUE; -} -HANDLE WINAPI FakeFindFirstVolumeW(LPWSTR lpszVolumeName, DWORD cchBufferLength) { - find_index_t* find_index = malloc(sizeof(find_index_t)); - find_index->disk = 0; - find_index->partition = 0; - HANDLE handle = GetDummyHandle(); - SetDataForHandle(handle, HDATA_FIND_VOLUME, find_index, TRUE); - - FakeFindNextVolumeW(handle, lpszVolumeName, cchBufferLength); - return handle; -} -HANDLE WINAPI FakeFindFirstVolumeA(LPSTR lpszVolumeName, DWORD cchBufferLength) { - find_index_t* find_index = malloc(sizeof(find_index_t)); - find_index->disk = 0; - find_index->partition = 0; - HANDLE handle = GetDummyHandle(); - SetDataForHandle(handle, HDATA_FIND_VOLUME, find_index, TRUE); - - FakeFindNextVolumeA(handle, lpszVolumeName, cchBufferLength); - return handle; -} -BOOL WINAPI FakeFindVolumeClose(HANDLE hFindVolume) { - if (RemoveDataForHandle(hFindVolume, HDATA_FIND_VOLUME)) return _CloseHandle(hFindVolume); - return FALSE; -} - -disk_volume_t* getVolumeByPath(LPCSTR lpRootPathName) { - // Unimplemented - if (lpRootPathName == NULL) return FALSE; - - char filename[MAX_PATH + 1]; - - for (size_t disk = 0; disk < sizeof PHYSICAL_DISKS / sizeof PHYSICAL_DISKS[0]; disk++) { - for (size_t part = 0; part < 4; part++) { - strcpy_s(filename, sizeof filename, - PHYSICAL_DISKS[disk]->m_Partitions[part].m_Volume.m_FilenameA); - strcat_s(filename, sizeof filename, "\\"); - if (strcmp(filename, lpRootPathName)) continue; - - return &(PHYSICAL_DISKS[disk]->m_Partitions[part].m_Volume); - } - - for (size_t part = 0; PHYSICAL_DISKS[disk]->m_Extended[part].m_PartitionNumber; part++) { - strcpy_s(filename, sizeof filename, - PHYSICAL_DISKS[disk]->m_Extended[part].m_Volume.m_FilenameA); - strcat_s(filename, sizeof filename, "\\"); - if (strcmp(filename, lpRootPathName)) continue; - - return &(PHYSICAL_DISKS[disk]->m_Extended[part].m_Volume); - } - } - return NULL; -} - -BOOL WINAPI FakeGetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, - DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, - LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, - LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { - if (nVolumeNameSize) lpVolumeNameBuffer[0] = '\0'; - if (lpVolumeSerialNumber) lpVolumeSerialNumber[0] = 0; - if (lpMaximumComponentLength) *lpMaximumComponentLength = MAX_PATH; - if (lpFileSystemFlags) *lpFileSystemFlags = 0; - if (nFileSystemNameSize) lpFileSystemNameBuffer[0] = '\0'; - - disk_volume_t* volume = getVolumeByPath(lpRootPathName); - if (volume == NULL) return FALSE; - - if (volume->m_Name && lpVolumeNameBuffer) - strcpy_s(lpVolumeNameBuffer, nVolumeNameSize, volume->m_Name); - return TRUE; -} -BOOL WINAPI FakeSetVolumeLabelA(LPCSTR lpRootPathName, LPCSTR lpVolumeName) { - disk_volume_t* volume = getVolumeByPath(lpRootPathName); - if (volume == NULL) return FALSE; - - if (lpVolumeName) { - size_t len = strlen(lpVolumeName); - // By default volume names are pointers to constants! - if (volume->m_NameIsOnHeap) - realloc(volume->m_Name, len + 1); - else { - volume->m_Name = malloc(len + 1); - volume->m_NameIsOnHeap = TRUE; - } - memcpy(volume->m_Name, lpVolumeName, len); - } else { - volume->m_Name = NULL; - } - return TRUE; -}; - -BOOL WINAPI volume_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, - DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, - LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { - disk_volume_t* volume = (disk_volume_t*)ctx->m_HookData; - if (volume == NULL) { - log_error("drive", "ctx->m_HookData NULL; expected a volume!"); - return FALSE; - } - - memset(lpOutBuffer, 0, nInBufferSize); - switch (dwIoControlCode) { - case IOCTL_STORAGE_GET_DEVICE_NUMBER: - ((PSTORAGE_DEVICE_NUMBER)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK; - ((PSTORAGE_DEVICE_NUMBER)lpOutBuffer)->DeviceNumber = volume->m_pDrive->m_DriveNumber; - ((PSTORAGE_DEVICE_NUMBER)lpOutBuffer)->PartitionNumber = - volume->m_pPartition->m_PartitionNumber; - return TRUE; - case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: - PVOLUME_DISK_EXTENTS vde = (PVOLUME_DISK_EXTENTS)lpOutBuffer; - - vde->NumberOfDiskExtents = 1; - vde->Extents[0].DiskNumber = volume->m_pDrive->m_DriveNumber; - - vde->Extents[0].StartingOffset.QuadPart = - volume->m_pPartition->m_PhysicalLBA * BLOCKSIZE; - vde->Extents[0].ExtentLength.QuadPart = volume->m_pPartition->m_Size * BLOCKSIZE; - - return TRUE; - case IOCTL_STORAGE_QUERY_PROPERTY: - PSTORAGE_PROPERTY_QUERY queryIn = (PSTORAGE_PROPERTY_QUERY)lpInBuffer; - - if (queryIn->PropertyId != StorageDeviceProperty || - queryIn->QueryType != PropertyStandardQuery) { - log_error("drive", "Unimplemented storage query: %d/%d", queryIn->PropertyId, - queryIn->QueryType); - return FALSE; - } - PSTORAGE_DEVICE_DESCRIPTOR descriptor = (PSTORAGE_DEVICE_DESCRIPTOR)(lpOutBuffer); - - descriptor->BusType = volume->m_pDrive->m_BusType; - - size_t rdpOffset = offsetof(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties); - if (volume->m_pDrive->m_VID) { - descriptor->VendorIdOffset = rdpOffset; - rdpOffset += sprintf_s((char*)descriptor + rdpOffset, nOutBufferSize - rdpOffset, - "%s", volume->m_pDrive->m_VID) + - 1; - } - if (volume->m_pDrive->m_PID) { - descriptor->ProductIdOffset = rdpOffset; - rdpOffset += sprintf_s((char*)descriptor + rdpOffset, nOutBufferSize - rdpOffset, - "%s", volume->m_pDrive->m_PID) + - 1; - } - descriptor->RawPropertiesLength = - rdpOffset - offsetof(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties); - return TRUE; - case IOCTL_DISK_GET_LENGTH_INFO: - PGET_LENGTH_INFORMATION length = (PGET_LENGTH_INFORMATION)lpOutBuffer; - if (volume->m_pPartition) { - length->Length.QuadPart = volume->m_pPartition->m_Size; - } - return TRUE; - default: - log_error("drive", "Unimplemented IOCTL: %08x", dwIoControlCode); - return FALSE; - } -} - -void init_volume(disk_volume_t* vol) { - wchar_t* volume_name = vol->m_FilenameW; - wcscpy_s(volume_name, MAX_PATH + 1, L"\\\\?\\Volume"); - - GUID guid; - CoCreateGuid(&guid); - StringFromGUID2(&guid, volume_name + 10, MAX_PATH + 1 - 10); - - file_hook_t* volume_hook = new_file_hook(volume_name); - log_misc("disk", "Creating fake volume: %ls", volume_name); - - volume_hook->DeviceIoControl = &volume_DeviceIoControl; - volume_hook->hook_data = (void*)vol; - - hook_file(volume_hook); - - // This is a pretty nasty way to convert from W to A, but all values - // are always going to be within ASCII range so it's.. okay. - for (size_t i = 0; i < sizeof vol->m_FilenameA; i++) { - vol->m_FilenameA[i] = vol->m_FilenameW[i] & 0xff; - } -} -void init_pd(physical_disk_t* pd) { - DWORD partitionNumber = 1; - DWORD currentLBA = MBR_LBA_GAP; - - // Init MBR - for (int i = 0; i < 4; i++) { - if (pd->m_Partitions[i].m_Size == 0) break; - - pd->m_Partitions[i].m_PartitionNumber = partitionNumber++; - pd->m_Partitions[i].m_PhysicalLBA = currentLBA; - - init_volume(&(pd->m_Partitions[i].m_Volume)); - pd->m_Partitions[i].m_Volume.m_pDrive = pd; - pd->m_Partitions[i].m_Volume.m_pPartition = &(pd->m_Partitions[i]); - - currentLBA += pd->m_Partitions[i].m_Size; - } - - // If we have any extended partitions - DWORD extendedPartNo = 0; - if (pd->m_Extended[0].m_Size) { - if (partitionNumber == 5) { - log_error("drive", "Fatal: Too many paritions in drive %d!", pd->m_DriveNumber); - exit(1); - } - pd->m_Partitions[partitionNumber - 1].m_Filesystem = MBR_FS_EXT_LBA; - pd->m_Partitions[partitionNumber - 1].m_PhysicalLBA = currentLBA; - extendedPartNo = partitionNumber; - - // Note: We don't increment partitionNumber, to keep the presence of this partition - // transparent elsewhere. - } - DWORD extendedStart = currentLBA; - - // Init extended partitions - for (int i = 0; pd->m_Extended[i].m_Size; i++) { - pd->m_Extended[i].m_PartitionNumber = partitionNumber++; - - currentLBA += EXT_HEADER_GAP; - pd->m_Extended[i].m_PhysicalLBA = currentLBA; - pd->m_Extended[i].m_SlotLBA = currentLBA; - currentLBA += pd->m_Extended[i].m_Size; - - init_volume(&(pd->m_Extended[i].m_Volume)); - pd->m_Extended[i].m_Volume.m_pDrive = pd; - pd->m_Extended[i].m_Volume.m_pPartition = &(pd->m_Extended[i]); - - sbr_slot_t* pslot = get_sbr_slot(pd->m_Extended[i].m_SPDContent); - if (pslot != NULL) { - DWORD slot_size = ((LONGLONG)pslot->segcount * (LONGLONG)pslot->segsize) / BLOCKSIZE; - DWORD slot_offset = pd->m_Extended[i].m_Size - slot_size; - pd->m_Extended[i].m_SlotLBA += slot_offset; - } - } - - // Back-fill, if needed - if (extendedPartNo) { - pd->m_Partitions[extendedPartNo - 1].m_Size = currentLBA - extendedStart; - } - - // Install hooks - // strlen(\\.\PhysicalDrive255) = 20, then +1 for null - wchar_t* hookPath = malloc(21 * sizeof(wchar_t)); - swprintf_s(hookPath, 21, L"\\\\.\\PhysicalDrive%d", pd->m_DriveNumber); - file_hook_t* hook = new_file_hook(hookPath); - hook->DeviceIoControl = pd_DeviceIoControl; - hook->ReadFile = pd_ReadFile; - hook->WriteFile = pd_WriteFile; - hook->hook_data = (void*)pd; - hook_file(hook); -} - -void hook_drives() { - init_pd(&SSD); - init_pd(&UPDATE_USB); - - file_hook_t* c_drive = new_file_hook(L"\\\\.\\C:"); - c_drive->DeviceIoControl = &c_drive_DeviceIoControl; - hook_file(c_drive); - - file_hook_t* x_drive = new_file_hook(L"X:"); - x_drive->DeviceIoControl = &x_drive_DeviceIoControl; - hook_file(x_drive); - - hook("Kernel32.dll", "FindFirstVolumeW", &FakeFindFirstVolumeW, NULL, 5); - hook("Kernel32.dll", "FindNextVolumeW", &FakeFindNextVolumeW, NULL, 5); - hook("Kernel32.dll", "FindFirstVolumeA", &FakeFindFirstVolumeA, NULL, 5); - hook("Kernel32.dll", "FindNextVolumeA", &FakeFindNextVolumeA, NULL, 5); - hook("Kernel32.dll", "FindVolumeClose", &FakeFindVolumeClose, NULL, 5); - hook("Kernel32.dll", "SetVolumeLabelA", &FakeSetVolumeLabelA, NULL, 5); - hook("Kernel32.dll", "GetVolumeInformationA", &FakeGetVolumeInformationA, NULL, 5); - - /** - * mxinstaller iterates all volumes to find those that match the slot metadata. - * It uses: - * - FindFirstVolumeW - * - FindNextVolumeW - * - FindVolumeClose - * to iterate volumes. - * For each volume, it: - * - opens it with CreateFileW - * - calls IOCTL_STORAGE_GET_DEVICE_NUMBER - * - asserts that DeviceType == FILE_DEVICE_DISK - * - calls IOCTL_VOLUME_GET_VOLUME_DISK_EXTENT - * - checks that NumberOfDiskExtents < 128 - * - this is not fatal, however an error will be shown and only the first 128 will be checked - * - for each extent (!! sizeof DISK_EXTENT == 24; it's 8-byte aligned): - * - asserts that [].DiskNumber == state_->DiskNumber - * - finds a slot that matches: - * - slot->offset == [].StartingOffset - * - slot->segments == ([].ExtentLength.LowPart >> 9) | ([].ExtentLength.HighPart << 23) - * == [].ExtentLength / 512 - */ -} diff --git a/src/micetools/dll/hooks/drive/disks.c b/src/micetools/dll/hooks/drive/disks.c new file mode 100644 index 0000000..5067c3d --- /dev/null +++ b/src/micetools/dll/hooks/drive/disks.c @@ -0,0 +1,110 @@ +#include "drive.h" + +physical_disk_t SSD = { + .m_SerialNumber = 0x00144DB0, + + .m_BusType = BusTypeAta, + .m_BootPartition = 1, + .m_HasSegaboot = TRUE, + .m_BlockSize = BLOCK_SIZE_HDD, + .m_TotalSize = 64 * 1024 * 1024 * (1024 / BLOCK_SIZE_HDD), + .m_DiskType = DiskType_HardDisk, + .m_IsFormatted = true, + .m_Partitions = { + // 1.5GB boot partitions + { + .m_Size = 0x300B85, + .m_Filesystem = MBR_FS_NTFS, + }, + // 1.5GB recovery partitions + { + .m_Size = 0x300BC4, + .m_Filesystem = MBR_FS_NTFS, + }, + }, + .m_Extended = { + { 0x102d83, MBR_FS_FAT16, SPD_OS, .m_ReadFunc = &ReadFunc_OSLogFiles }, // 512MB OS update + { 0x403947, MBR_FS_FAT16, SPD_Patch0, .m_ReadFunc = NULL }, // 2GB patch0 + { 0x403947, MBR_FS_FAT16, SPD_Patch1, .m_ReadFunc = NULL }, // 2GB patch1 + { 0x48ed459, MBR_FS_NTFS, SPD_AppData, .m_ReadFunc = NULL }, // 40GB something + { + // mxinstaller.exe -cmdport 40102 -bindport 40103 + // 16GB partition for the game + // The real value here should be "0x20014aa," + 0x20014aa, // 16GB, FiNALE + + // Instead, we're going to just allocate ~8GB, the exact size of SDCQ + // 0xeafc00, // ~8GB. Lol. Lmao. + MBR_FS_FAT16, + SPD_Original0, + .m_ReadFunc = &ReadFunc_Original0, + .m_WriteFunc = &WriteFunc_Original0, + }, + { 0 }, + }, +}; +physical_disk_t UPDATE_USB = { + .m_BusType = BusTypeUsb, + .m_VID = "13FE", + .m_PID = "4200", + .m_BlockSize = BLOCK_SIZE_FLASH, + .m_TotalSize = 64 * 1024 * ((1024 * 1024) / BLOCK_SIZE_FLASH), + .m_IsFormatted = true, + .m_DiskType = DiskType_Flash, + .m_Partitions = { + // 59050 MB update partitions + { + .m_Size = 0xe6b410, + .m_Filesystem = MBR_FS_NTFS, + .m_Volume = { + .m_Name = "SEGA_INS", + }, + }, + }, + .m_Extended = {{ 0 }}, +}; +physical_disk_t LOG_USB = { + .m_BusType = BusTypeUsb, + .m_VID = "13FE", + .m_PID = "4200", + .m_BlockSize = BLOCK_SIZE_FLASH, + .m_TotalSize = 16 * 1024 * ((1024 * 1024) / BLOCK_SIZE_FLASH), + .m_IsFormatted = true, + .m_DiskType = DiskType_Flash, + .m_Partitions = { + // 16 GB partition to store logs + { + .m_Size = 0x400000, + .m_Filesystem = MBR_FS_NTFS, + .m_Volume = { + .m_Name = "SEGA_AM_LOG", + .m_MountPoint = 'L', + }, + }, + }, + .m_Extended = {{ 0 }}, +}; +physical_disk_t ALPHA_DVD = { + .m_BusType = BusTypeScsi, + .m_DeviceType = DeviceTypeCdRom, + .m_VID = "", + .m_PID = "", + .m_BlockSize = BLOCK_SIZE_DVD, + .m_TotalSize = 0, + .m_IsFormatted = FALSE, + .m_DiskType = DiskType_CdRom, + .m_Partitions = { { + .m_ReadFunc = NULL, + .m_Volume = { + .m_Name = "DVR5048_1_60_00", + .m_MountPoint = 'Q', + }, + } }, +}; + +physical_disk_t* PHYSICAL_DISKS[] = { + &SSD, + &UPDATE_USB, + // &LOG_USB, + // &ALPHA_DVD, +}; diff --git a/src/micetools/dll/hooks/drive/disks.h b/src/micetools/dll/hooks/drive/disks.h new file mode 100644 index 0000000..4308d0c --- /dev/null +++ b/src/micetools/dll/hooks/drive/disks.h @@ -0,0 +1,82 @@ +#pragma once +#include + +#include "segastruct.h" + +typedef struct _physical_disk physical_disk_t; +typedef struct _disk_partition disk_partition_t; +typedef struct _disk_volume disk_volume_t; +typedef struct _disk_raw disk_raw_t; + +#define MAX_DISKS 32 +extern physical_disk_t* PHYSICAL_DISKS[MAX_DISKS]; + +typedef BOOL(mice_partition_read_function_t)(DWORD nOffset, LPVOID lpBuffer, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead); +typedef BOOL(mice_partition_write_function_t)(DWORD nOffset, LPCVOID lpBuffer, + DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten); + +typedef enum { + DiskType_HardDisk, + DiskType_Flash, + DiskType_CdRom, + DiskType_Floppy, +} DiskType; +struct _disk_volume { + wchar_t m_FilenameW[MAX_PATH + 1]; + char m_FilenameA[MAX_PATH + 1]; + LPSTR m_Name; + char m_MountPoint; + + // Used for: \\Device\\DeviceName (kernel mode) + wchar_t m_DeviceName[MAX_PATH]; + // Used for: \\OsDevices\\DosDeviceName (kernel mode), \\\\.\\DosDeviceName (user mode) + wchar_t m_DosDeviceName[MAX_PATH]; + + // Back-references + physical_disk_t* m_pDrive; + disk_partition_t* m_pPartition; + BOOL m_NameIsOnHeap; +}; +struct _disk_partition { + DWORD m_Size; + UCHAR m_Filesystem; + spd_slot_t m_SPDContent; + mice_partition_read_function_t* m_ReadFunc; + mice_partition_write_function_t* m_WriteFunc; + + disk_volume_t m_Volume; + + DWORD m_PhysicalLBA; + DWORD m_SlotLBA; + DWORD m_PartitionNumber; +}; +struct _disk_raw { + mice_partition_read_function_t* m_ReadFunc; + mice_partition_write_function_t* m_WriteFunc; +}; +struct _physical_disk { + DWORD m_SerialNumber; + + DWORD m_DriveNumber; + STORAGE_BUS_TYPE m_BusType; + DEVICE_TYPE m_DeviceType; + LPSTR m_VID; + LPSTR m_PID; + DWORD m_BootPartition; + BOOL m_HasSegaboot; + DWORD m_BlockSize; + DWORD m_TotalSize; + DiskType m_DiskType; + + // Used for: \\Device\\DeviceName (kernel mode) + wchar_t m_DeviceName[MAX_PATH]; + // Used for: \\OsDevices\\DosDeviceName (kernel mode), \\\\.\\DosDeviceName (user mode) + wchar_t m_DosDeviceName[MAX_PATH]; + + BOOL m_IsFormatted; + disk_partition_t m_Partitions[4]; + disk_partition_t m_Extended[]; +}; diff --git a/src/micetools/dll/hooks/drive/drive.c b/src/micetools/dll/hooks/drive/drive.c new file mode 100644 index 0000000..e1d4b76 --- /dev/null +++ b/src/micetools/dll/hooks/drive/drive.c @@ -0,0 +1,743 @@ +#define _MICE_DRIVE +#include "drive.h" + +#include "../../../lib/ami/amiMd5.h" +#include "../../../micemaster/mxmEventLog.h" +#include "../../../sysconf.h" +#include "../files.h" + +/* + First 512 bytes of SPD_Original0: + LOADER::LoadBootIDHeader +*/ +BYTE Original0BootIDHeader[512] = { + 0x4B, 0xDF, 0xB4, 0x43, 0x27, 0x3C, 0xFE, 0xD6, 0xA2, 0xA8, 0xF8, 0xFD, 0xB4, 0x55, 0xE6, 0xBA, + 0x5A, 0x0F, 0xBF, 0x14, 0xA4, 0x37, 0xB6, 0x42, 0xB3, 0xAD, 0x11, 0x4A, 0xCA, 0x1A, 0x4C, 0xD9, + 0x11, 0xF1, 0x60, 0x4B, 0x37, 0x58, 0x9C, 0x9A, 0x89, 0x8F, 0x07, 0x9C, 0xE7, 0xF2, 0x64, 0xCC, + 0x6E, 0x84, 0x87, 0xAA, 0x20, 0xA0, 0xB8, 0x55, 0x9B, 0xE7, 0x79, 0x4F, 0x51, 0x25, 0xC3, 0x7E, + 0xEF, 0xD9, 0x25, 0xA9, 0x94, 0xF1, 0x7F, 0xEF, 0xE1, 0xD9, 0xAE, 0x4F, 0xC2, 0xEE, 0xB6, 0xA8, + 0xD9, 0x54, 0x0F, 0x33, 0xA8, 0xA9, 0x22, 0x72, 0x81, 0xD0, 0xA3, 0x04, 0x5C, 0x45, 0x3E, 0xBE, + 0xF7, 0x2A, 0xED, 0x55, 0xAB, 0x16, 0xC1, 0xA8, 0x61, 0x70, 0xEE, 0x55, 0xCB, 0xE6, 0x68, 0xA5, + 0xB4, 0xDC, 0x30, 0x6D, 0x32, 0xD6, 0x69, 0x8D, 0xFC, 0x90, 0x71, 0x7E, 0xDB, 0x6B, 0x17, 0xFA, + 0xAB, 0xE0, 0x11, 0x14, 0xBA, 0xD9, 0x33, 0xB7, 0x7C, 0x54, 0x9E, 0x21, 0xA1, 0x43, 0xFD, 0x8F, + 0x14, 0xF4, 0xBE, 0x5F, 0x0B, 0x02, 0x8E, 0x87, 0xCA, 0x85, 0xE9, 0xC1, 0x60, 0xF7, 0x7E, 0x44, + 0x55, 0x3A, 0x5E, 0x94, 0x65, 0x95, 0xFD, 0x02, 0xF9, 0xFF, 0xBF, 0x07, 0x80, 0xC5, 0x26, 0x58, + 0x6F, 0x37, 0xFA, 0x59, 0x2F, 0x02, 0xF3, 0x9D, 0x24, 0x7D, 0x42, 0x6B, 0xF3, 0x49, 0x63, 0xC9, + 0x2A, 0xCB, 0xFC, 0x71, 0x69, 0x44, 0xB5, 0xAC, 0xD3, 0x37, 0xA0, 0x01, 0x65, 0x3D, 0x49, 0xC4, + 0x7D, 0xE5, 0xF8, 0x6E, 0x09, 0xC7, 0x3E, 0xD1, 0x96, 0x09, 0x23, 0xA4, 0xE8, 0xA5, 0x6A, 0xA2, + 0x5B, 0x5B, 0xA5, 0x9C, 0xF8, 0x8D, 0x84, 0x55, 0x3F, 0x19, 0x8F, 0xDC, 0xFA, 0x7B, 0xF1, 0xC9, + 0xB6, 0xBF, 0xE8, 0x73, 0xB9, 0xC9, 0xC3, 0x17, 0x14, 0xAB, 0xA3, 0x60, 0x13, 0xED, 0x6D, 0xCC, + 0x10, 0x7B, 0x1D, 0xC6, 0xBC, 0xEC, 0x56, 0xFA, 0x52, 0xC5, 0x4E, 0xAC, 0x8F, 0x36, 0x8B, 0x92, + 0x6C, 0xB5, 0x9A, 0x57, 0x7D, 0xFA, 0x97, 0x72, 0xFC, 0xFA, 0xB8, 0xFE, 0x20, 0x71, 0xFB, 0x63, + 0x00, 0x96, 0x29, 0xCE, 0xE2, 0x06, 0xFF, 0x64, 0x48, 0xB5, 0x1F, 0xD6, 0x88, 0x48, 0x7A, 0x62, + 0x2B, 0xBE, 0xE6, 0xC4, 0xFD, 0xF6, 0x85, 0x45, 0x0A, 0x8C, 0x6C, 0x20, 0x64, 0x05, 0x81, 0x13, + 0xB5, 0x59, 0xAE, 0x34, 0x41, 0x0B, 0xB5, 0x65, 0x57, 0x59, 0x9C, 0xE8, 0xD0, 0xAE, 0x81, 0xD8, + 0x6D, 0xC9, 0xFD, 0xF8, 0xC9, 0x15, 0xB6, 0xDC, 0xC9, 0x13, 0xF2, 0x6E, 0xD9, 0xA5, 0x77, 0x62, + 0xB7, 0x15, 0x61, 0x21, 0x73, 0xFE, 0x0A, 0x57, 0x3B, 0x2C, 0x2F, 0x23, 0xC3, 0x33, 0xB8, 0x77, + 0xCE, 0xCE, 0x76, 0x98, 0xDB, 0xE5, 0x9A, 0x00, 0xE1, 0xC3, 0x6F, 0x7D, 0x42, 0xC4, 0xDE, 0xB7, + 0x1D, 0xA0, 0xC1, 0x1C, 0xB9, 0x09, 0x28, 0xD9, 0x59, 0x9D, 0x3F, 0xEA, 0xF1, 0xB6, 0xA0, 0x1C, + 0x5E, 0x4A, 0xE4, 0x1A, 0xE7, 0xA7, 0x1C, 0xAD, 0xF6, 0xF1, 0xCB, 0x9C, 0x06, 0xE6, 0x4C, 0xF4, + 0xD6, 0xEE, 0x5F, 0x18, 0xF5, 0x00, 0x4A, 0x76, 0x5E, 0x7D, 0x96, 0x20, 0x57, 0x68, 0x23, 0x69, + 0x8F, 0x60, 0x91, 0xBF, 0x00, 0x08, 0xFE, 0x4F, 0x36, 0x45, 0x86, 0x14, 0x48, 0xC5, 0x8B, 0xEA, + 0xE3, 0x64, 0x27, 0x1E, 0x49, 0xDF, 0x98, 0xAD, 0xE2, 0x66, 0x09, 0x07, 0xDD, 0x24, 0xB0, 0x4D, + 0x52, 0xA6, 0xD1, 0x3D, 0xB9, 0x52, 0x0B, 0x88, 0x97, 0x97, 0x0F, 0x83, 0x85, 0xD5, 0x3F, 0x0E, + 0x1A, 0xF2, 0x26, 0xBA, 0x14, 0x53, 0xDD, 0xF4, 0x7D, 0xAF, 0xB6, 0xEE, 0x36, 0x3A, 0xB5, 0xDA, + 0x2F, 0x99, 0xC8, 0x54, 0xD2, 0xDB, 0x52, 0x49, 0xD6, 0xB6, 0x07, 0x1A, 0xBA, 0x9A, 0x85, 0xBB, +}; + +BOOL ReadFunc_Original0(DWORD nOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead) { + *lpNumberOfBytesRead = 0; + if (!_PathFileExistsA(ORIGINAL0_PATH)) { + log_error("drive", "Failed to open %s (does not exist)", ORIGINAL0_PATH); + return FALSE; + } + + HANDLE hFile = + _CreateFileA(ORIGINAL0_PATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("drive", "Failed to open %s", ORIGINAL0_PATH); + return FALSE; + } + LARGE_INTEGER seekTo; + seekTo.QuadPart = (LONGLONG)nOffset * (LONGLONG)SSD.m_BlockSize; + _SetFilePointerEx(hFile, seekTo, NULL, FILE_BEGIN); + BOOL ret = _ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, NULL); + if (!ret) log_error("drive", "Failed to read to %s: %03x", ORIGINAL0_PATH, GetLastError()); + _CloseHandle(hFile); + return ret; +} +BOOL WriteFunc_Original0(DWORD nOffset, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten) { + *lpNumberOfBytesWritten = 0; + + HANDLE hFile = + _CreateFileA(ORIGINAL0_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("drive", "Failed to open %s", ORIGINAL0_PATH); + return FALSE; + } + LARGE_INTEGER seekTo; + seekTo.QuadPart = (LONGLONG)nOffset * (LONGLONG)SSD.m_BlockSize; + _SetFilePointerEx(hFile, seekTo, NULL, FILE_BEGIN); + BOOL ret = _WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, NULL); + if (!ret) log_error("drive", "Failed to write to %s: %03x", ORIGINAL0_PATH, GetLastError()); + _CloseHandle(hFile); + return ret; +} + +BOOL ReadFunc_OSLogFiles(DWORD nOffset, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead) { + if (nOffset == 2047 && nNumberOfBytesToRead == sizeof(AM_EVENT_LOG_HEADER)) { + AM_EVENT_LOG_HEADER header; + ZeroMemory(&header, sizeof header); + + // BYTE nullBuffer[512]; + // ZeroMemory(nullBuffer, sizeof nullBuffer); + + // AmiMd5 md5; + // amiMd5Init(&md5); + // amiMd5Update(&md5, sizeof nullBuffer, nullBuffer); + // amiMd5Finalise(&md5); + + AmiMd5 md5; + amiMd5Init(&md5); + amiMd5Update(&md5, 0, NULL); + amiMd5Finalise(&md5); + + header.m_nBytes[0] = 0; + header.m_nBytes[1] = 0; + + memcpy(header.m_md5[0], md5.m_digest, sizeof header.m_md5[0]); + memcpy(header.m_md5[1], md5.m_digest, sizeof header.m_md5[1]); + + header.m_crc32 = amiCrc32RCalc(sizeof header - 4, ((unsigned char*)&header) + 4, 0); + + memcpy(lpBuffer, &header, sizeof header); + *lpNumberOfBytesRead = sizeof header; + return TRUE; + } + if (nOffset == 2048) { + log_warning("drive", "Requsted %d bytes of application log file", nNumberOfBytesToRead); + ZeroMemory(lpBuffer, nNumberOfBytesToRead); + *lpNumberOfBytesRead = nNumberOfBytesToRead; + return TRUE; + } + if (nOffset == 2048 + 1024) { + log_warning("drive", "Requsted %d bytes of system log file", nNumberOfBytesToRead); + ZeroMemory(lpBuffer, nNumberOfBytesToRead); + *lpNumberOfBytesRead = nNumberOfBytesToRead; + return TRUE; + } + + *lpNumberOfBytesRead = 0; + return FALSE; +} + +BOOL WINAPI c_drive_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + log_trace("C", "DeviceIOControl %08x", dwIoControlCode); + ZeroMemory(lpOutBuffer, nOutBufferSize); + switch (dwIoControlCode) { + case IOCTL_STORAGE_GET_DEVICE_NUMBER: + ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK; + ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceNumber = 0; + return TRUE; + case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: + ((VOLUME_DISK_EXTENTS*)lpOutBuffer)->NumberOfDiskExtents = 1; + ((VOLUME_DISK_EXTENTS*)lpOutBuffer)->Extents[0].DiskNumber = 0; + return TRUE; + default: + return FALSE; + } +} + +BOOL WINAPI x_drive_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + log_trace("X", "DeviceIOControl %08x", dwIoControlCode); + ZeroMemory(lpOutBuffer, nOutBufferSize); + switch (dwIoControlCode) { + case IOCTL_STORAGE_GET_DEVICE_NUMBER: + ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK; + ((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceNumber = 0; + return TRUE; + default: + log_warning("X", "Unhandled DeviceIOControl %08x", dwIoControlCode); + return FALSE; + } +} + +BOOL WINAPI q_drive_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + log_trace("Q", "DeviceIOControl %08x", dwIoControlCode); + ZeroMemory(lpOutBuffer, nOutBufferSize); + switch (dwIoControlCode) { + case IOCTL_STORAGE_MEDIA_REMOVAL: + // The game wants to disable ejecting the disk during installing + return TRUE; + case IOCTL_CDROM_GET_DRIVE_GEOMETRY: + ((PDISK_GEOMETRY)lpOutBuffer)->BytesPerSector = ALPHA_DVD.m_BlockSize; + return TRUE; + default: + log_warning("Q", "Unhandled DeviceIOControl %08x", dwIoControlCode); + return FALSE; + } +} + +sbr_t SegaBootRecordDefault = { + .version = SBR_VERSION, + .bootslot = 0x02, + + .slot_status = { Slot_Complete, Slot_Complete, Slot_Invalid, Slot_Check, Slot_Complete }, + + .slot_os = { + // Starts at 0xc5469400 + // i.e. [partition 6] - (segcount * segsize) + // i.e. partition 5 = [dead space] [slot_os] + .id = {'A', 'A', 'S', '0'}, + .time = { 0 }, + .version = 0x450a01, + .segcount = 1745, + .segsize = 0x40000, + .hw = HW_ID, + .instant = 0, + .osver = 0x450a01, + .ossegcount = 0, + .orgtime = { 0 }, + .orgversion = 0x450a01, + }, + .slot_original0 = { + // Starts at 0xb065bae00 + // i.e. [end of disk] - (segcount * segsize) + // i.e. partition 9 = [dead space] [slot_original0] + + .id = GAME_ID, + .time = { 2018, 10, 29, 15, 7, 36 }, + .version = 0x10061, + .segcount = 65082, + .segsize = 0x40000, + .hw = HW_ID, + .instant = 0, + .osver = 0x450a01, + .ossegcount = 1745, + .orgtime = { 2018, 10, 29, 15, 7, 36 }, + .orgversion = 0x10061, + }, + .slot_appdata = { 0 }, + .slot_patch0 = { + // Starts at 0x15e49a000 + // i.e. [partition 7] - (segcount * segsize) + // i.e. partition 6 = [dead space] [something] [patch0] + + .id = GAME_ID, + .time = { 2018, 6, 21, 13, 46, 24 }, + .version = 0x10060, + .segcount = 173, + .segsize = 0x40000, + .hw = HW_ID, + .instant = 0, + .osver = 0, + .ossegcount = 0, + .orgtime = { 2018, 5, 16, 20, 7, 12 }, + .orgversion = 0x01005f, + }, + .slot_patch1 = { + // Starts at 0x1debcac00 + // i.e. [partition 8] - (segcount * segsize) + // i.e. partition 7 = [dead space] [something] [patch0] + + .id = GAME_ID, + .time = { 2018, 11, 16, 19, 4, 48}, + .version = 0x10062, + .segcount = 173, + .segsize = 0x40000, + .hw = HW_ID, + .instant = 0, + .osver = 0, + .ossegcount = 0, + .orgtime = { 2018, 10, 29, 15, 7, 36 }, + .orgversion = 0x10061, + }, +}; +sbr_t SegaBootRecord0; +sbr_t SegaBootRecord1; + +// Drives +/** + * VID_0CA3 = SEGA CORPROATION + * VID_0928 = PLX / Oxford Semiconductor + * VID/PID pairs for B: + * 0CA3/000E + * 0928/0007 + * 0CA3/000C + * + * Mountpoints based on drive name: + * Z: DEV + * L: SEGA_AM_LOG + */ + +// Volumes +sbr_slot_t* get_sbr_slot(spd_slot_t slot) { + switch (slot) { + case SPD_Original0: + return &SegaBootRecord0.slot_original0; + case SPD_Original1: + return NULL; + case SPD_Patch0: + return &SegaBootRecord0.slot_patch0; + case SPD_Patch1: + return &SegaBootRecord0.slot_patch1; + case SPD_OS: + return &SegaBootRecord0.slot_os; + case SPD_AppData: + return &SegaBootRecord0.slot_appdata; + default: + return NULL; + } +} + +inline char char_lower(char value) { + if ('A' <= value && value <= 'Z') return value - 'A' + 'a'; + return value; +} +inline char char_upper(char value) { + if ('a' <= value && value <= 'z') return value - 'a' + 'A'; + return value; +} +char matchWorkFilename[MAX_PATH + 1]; +inline static BOOL matchVolume(disk_volume_t* volume, LPCSTR lpRootPathName, DWORD match) { + if (match & VOL_MATCH_GUID) { + strcpy_s(matchWorkFilename, sizeof matchWorkFilename, volume->m_FilenameA); + strcat_s(matchWorkFilename, sizeof matchWorkFilename, "\\"); + if (strcmp(matchWorkFilename, lpRootPathName) == 0) return TRUE; + } + if (match & VOL_MATCH_PATH && volume->m_MountPoint) { + sprintf_s(matchWorkFilename, sizeof matchWorkFilename, + "\\\\.\\%c:", char_lower(volume->m_MountPoint)); + if (strstr(lpRootPathName, matchWorkFilename) == lpRootPathName) return TRUE; + + sprintf_s(matchWorkFilename, sizeof matchWorkFilename, + "\\\\.\\%c:", char_upper(volume->m_MountPoint)); + if (strstr(lpRootPathName, matchWorkFilename) == lpRootPathName) return TRUE; + } + if (match & VOL_MATCH_DOS_DEVICE && volume->m_MountPoint) { + if (char_lower(volume->m_MountPoint) == char_lower(lpRootPathName[0])) { + if (lpRootPathName[1] == ':' && lpRootPathName[2] == '\0') return TRUE; + } + } + return FALSE; +} + +disk_volume_t* getVolumeByPath(LPCSTR lpRootPathName, DWORD match) { + if (lpRootPathName == NULL) { + log_error("file", "getVolumeByPath(NULL) unimplemented!"); + return FALSE; + } + + for (size_t disk = 0; disk < MAX_DISKS && PHYSICAL_DISKS[disk] != NULL; disk++) { + for (size_t part = 0; part < 4; part++) { + disk_volume_t* volume = &(PHYSICAL_DISKS[disk]->m_Partitions[part].m_Volume); + if (matchVolume(volume, lpRootPathName, match)) return volume; + } + + for (size_t part = 0; PHYSICAL_DISKS[disk]->m_Extended[part].m_PartitionNumber; part++) { + disk_volume_t* volume = &(PHYSICAL_DISKS[disk]->m_Extended[part].m_Volume); + if (matchVolume(volume, lpRootPathName, match)) return volume; + } + } + return NULL; +} + +BOOL WINAPI volume_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + disk_volume_t* volume = (disk_volume_t*)ctx->m_HookData; + if (volume == NULL) { + log_error("drive", "ctx->m_HookData NULL; expected a volume!"); + return FALSE; + } + + memset(lpOutBuffer, 0, nInBufferSize); + switch (dwIoControlCode) { + case IOCTL_STORAGE_GET_DEVICE_NUMBER: + if (volume->m_pDrive->m_DiskType == DiskType_CdRom) + ((PSTORAGE_DEVICE_NUMBER)lpOutBuffer)->DeviceType = FILE_DEVICE_CD_ROM; + else + ((PSTORAGE_DEVICE_NUMBER)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK; + ((PSTORAGE_DEVICE_NUMBER)lpOutBuffer)->DeviceNumber = volume->m_pDrive->m_DriveNumber; + ((PSTORAGE_DEVICE_NUMBER)lpOutBuffer)->PartitionNumber = + volume->m_pPartition->m_PartitionNumber; + return TRUE; + case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS: + PVOLUME_DISK_EXTENTS vde = (PVOLUME_DISK_EXTENTS)lpOutBuffer; + + vde->NumberOfDiskExtents = 1; + vde->Extents[0].DiskNumber = volume->m_pDrive->m_DriveNumber; + + vde->Extents[0].StartingOffset.QuadPart = + volume->m_pPartition->m_PhysicalLBA * (long long)volume->m_pDrive->m_BlockSize; + vde->Extents[0].ExtentLength.QuadPart = + volume->m_pPartition->m_Size * (long long)volume->m_pDrive->m_BlockSize; + + return TRUE; + case IOCTL_STORAGE_QUERY_PROPERTY: + PSTORAGE_PROPERTY_QUERY queryIn = (PSTORAGE_PROPERTY_QUERY)lpInBuffer; + + if (queryIn->PropertyId != StorageDeviceProperty || + queryIn->QueryType != PropertyStandardQuery) { + log_error("drive", "Unimplemented storage query: %d/%d", queryIn->PropertyId, + queryIn->QueryType); + return FALSE; + } + PSTORAGE_DEVICE_DESCRIPTOR descriptor = (PSTORAGE_DEVICE_DESCRIPTOR)(lpOutBuffer); + + descriptor->DeviceType = volume->m_pDrive->m_DeviceType & 0xff; + descriptor->BusType = volume->m_pDrive->m_BusType; + + size_t rdpOffset = offsetof(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties); + if (volume->m_pDrive->m_VID) { + descriptor->VendorIdOffset = rdpOffset; + rdpOffset += sprintf_s((char*)descriptor + rdpOffset, nOutBufferSize - rdpOffset, + "%s", volume->m_pDrive->m_VID) + + 1; + } + if (volume->m_pDrive->m_PID) { + descriptor->ProductIdOffset = rdpOffset; + rdpOffset += sprintf_s((char*)descriptor + rdpOffset, nOutBufferSize - rdpOffset, + "%s", volume->m_pDrive->m_PID) + + 1; + } + descriptor->RawPropertiesLength = + rdpOffset - offsetof(STORAGE_DEVICE_DESCRIPTOR, RawDeviceProperties); + return TRUE; + case IOCTL_DISK_GET_LENGTH_INFO: + PGET_LENGTH_INFORMATION length = (PGET_LENGTH_INFORMATION)lpOutBuffer; + if (volume->m_pPartition) { + length->Length.QuadPart = volume->m_pPartition->m_Size; + } + return TRUE; + default: + log_error("drive", "Unimplemented IOCTL: %08x", dwIoControlCode); + return FALSE; + } +} + +void init_volume(disk_volume_t* vol) { + wchar_t* volume_name = vol->m_FilenameW; + wcscpy_s(volume_name, MAX_PATH + 1, L"\\\\?\\Volume"); + + GUID guid; + CoCreateGuid(&guid); + StringFromGUID2(&guid, volume_name + 10, MAX_PATH + 1 - 10); + + file_hook_t* volume_hook = new_file_hook(volume_name); + log_misc("disk", "Creating fake volume: %ls", volume_name); + + volume_hook->DeviceIoControl = &volume_DeviceIoControl; + volume_hook->hook_data = (void*)vol; + + hook_file(volume_hook); + + // This is a pretty nasty way to convert from W to A, but all values + // are always going to be within ASCII range so it's.. okay. + for (size_t i = 0; i < sizeof vol->m_FilenameA; i++) { + vol->m_FilenameA[i] = vol->m_FilenameW[i] & 0xff; + } + + // Construct default device names + if (vol->m_DeviceName[0] == '\0') { + swprintf_s(vol->m_DeviceName, (sizeof vol->m_DeviceName) / (sizeof vol->m_DeviceName[0]), + L"Volume%s", volume_name + 10); + } + if (vol->m_DosDeviceName[0] == '\0') { + swprintf_s( + vol->m_DosDeviceName, (sizeof vol->m_DosDeviceName) / (sizeof vol->m_DosDeviceName[0]), + L"%ls\\Volume%d", vol->m_pDrive->m_DosDeviceName, vol->m_pPartition->m_PartitionNumber); + } +} +void init_pd(physical_disk_t* pd) { + // Apply default block sizes + if (!pd->m_BlockSize) { + switch (pd->m_DiskType) { + case DiskType_HardDisk: + pd->m_BlockSize = BLOCK_SIZE_HDD; + break; + case DiskType_Flash: + pd->m_BlockSize = BLOCK_SIZE_FLASH; + break; + case DiskType_CdRom: + pd->m_BlockSize = BLOCK_SIZE_CDROM; + break; + default: + log_error("disk", "Unable to guess block size for drive %d", pd->m_DriveNumber); + break; + } + } + + // Construct default device paths + if (pd->m_DeviceName[0] == '\0') { + switch (pd->m_DiskType) { + case DiskType_HardDisk: + case DiskType_Flash: // TODO: Figure out what flash is meant to be called + swprintf_s(pd->m_DeviceName, + (sizeof pd->m_DeviceName) / (sizeof pd->m_DeviceName[0]), L"Harddisk%d", + pd->m_DriveNumber); + break; + case DiskType_CdRom: + swprintf_s(pd->m_DeviceName, + (sizeof pd->m_DeviceName) / (sizeof pd->m_DeviceName[0]), L"CdRom%d", + pd->m_DriveNumber); + break; + case DiskType_Floppy: + swprintf_s(pd->m_DeviceName, + (sizeof pd->m_DeviceName) / (sizeof pd->m_DosDeviceName[0]), L"Floppy%d", + pd->m_DriveNumber); + break; + default: + log_error("disk", "Unable to set DeviceName for drive %d (type: %d)", + pd->m_DriveNumber, pd->m_DiskType); + break; + } + } + if (pd->m_DosDeviceName[0] == '\0') + swprintf_s(pd->m_DosDeviceName, + (sizeof pd->m_DosDeviceName) / (sizeof pd->m_DosDeviceName[0]), + L"PhysicalDrive%d", pd->m_DriveNumber); + + // Non-SCSI devices don't have a SCSI type to report + if (pd->m_BusType != BusTypeScsi) pd->m_DeviceType = DeviceTypeUnknown; + + // If we need to initialise the partition tables, do so + if (pd->m_IsFormatted) { + DWORD partitionNumber = 1; + DWORD currentLBA = MBR_LBA_GAP; + + // Init MBR + for (int i = 0; i < 4; i++) { + if (pd->m_Partitions[i].m_Size == 0) break; + + pd->m_Partitions[i].m_PartitionNumber = partitionNumber++; + pd->m_Partitions[i].m_PhysicalLBA = currentLBA; + + pd->m_Partitions[i].m_Volume.m_pDrive = pd; + pd->m_Partitions[i].m_Volume.m_pPartition = &(pd->m_Partitions[i]); + init_volume(&(pd->m_Partitions[i].m_Volume)); + + currentLBA += pd->m_Partitions[i].m_Size; + } + + // If we have any extended partitions + DWORD extendedPartNo = 0; + if (pd->m_Extended[0].m_Size) { + if (partitionNumber == 5) { + log_error("drive", "Fatal: Too many paritions in drive %d!", pd->m_DriveNumber); + exit(1); + } + pd->m_Partitions[partitionNumber - 1].m_Filesystem = MBR_FS_EXT_LBA; + pd->m_Partitions[partitionNumber - 1].m_PhysicalLBA = currentLBA; + extendedPartNo = partitionNumber; + + // Note: We don't increment partitionNumber, to keep the presence of this partition + // transparent elsewhere. + } + DWORD extendedStart = currentLBA; + + // Init extended partitions + for (int i = 0;; i++) { + if (!pd->m_Extended[i].m_Size) break; + + pd->m_Extended[i].m_PartitionNumber = partitionNumber++; + + currentLBA += EXT_HEADER_GAP; + pd->m_Extended[i].m_PhysicalLBA = currentLBA; + pd->m_Extended[i].m_SlotLBA = currentLBA; + currentLBA += pd->m_Extended[i].m_Size; + + pd->m_Extended[i].m_Volume.m_pDrive = pd; + pd->m_Extended[i].m_Volume.m_pPartition = &(pd->m_Extended[i]); + init_volume(&(pd->m_Extended[i].m_Volume)); + + sbr_slot_t* pslot = get_sbr_slot(pd->m_Extended[i].m_SPDContent); + if (pslot != NULL) { + DWORD slot_size = ((LONGLONG)pslot->segcount * (LONGLONG)pslot->segsize) / + (long long)pd->m_BlockSize; + DWORD slot_offset = pd->m_Extended[i].m_Size - slot_size; + pd->m_Extended[i].m_SlotLBA += slot_offset; + } + } + + // Back-fill, if needed + if (extendedPartNo) { + pd->m_Partitions[extendedPartNo - 1].m_Size = currentLBA - extendedStart; + } + } else { + // Raw disks have just a single spanning volume + pd->m_Partitions[0].m_PartitionNumber = 1; + pd->m_Partitions[0].m_PhysicalLBA = 0; + pd->m_Partitions[0].m_Size = pd->m_TotalSize; + pd->m_Partitions[0].m_Volume.m_pDrive = pd; + pd->m_Partitions[0].m_Volume.m_pPartition = &(pd->m_Partitions[0]); + init_volume(&(pd->m_Partitions[0].m_Volume)); + + wcscpy_s(pd->m_Partitions[0].m_Volume.m_DeviceName, + sizeof pd->m_Partitions[0].m_Volume.m_DeviceName / + sizeof pd->m_Partitions[0].m_Volume.m_DeviceName[0], + pd->m_DeviceName); + wcscpy_s(pd->m_Partitions[0].m_Volume.m_DosDeviceName, + sizeof pd->m_Partitions[0].m_Volume.m_DosDeviceName / + sizeof pd->m_Partitions[0].m_Volume.m_DosDeviceName[0], + pd->m_DosDeviceName); + } + + // Install hooks + // strlen(\\.\PhysicalDrive255) = 20, then +1 for null + wchar_t* hookPath = malloc(21 * sizeof(wchar_t)); + swprintf_s(hookPath, 21, L"\\\\.\\%ls", pd->m_DosDeviceName); + file_hook_t* hook = new_file_hook(hookPath); + hook->DeviceIoControl = pd_DeviceIoControl; + hook->ReadFile = pd_ReadFile; + hook->WriteFile = pd_WriteFile; + hook->hook_data = (void*)pd; + hook_file(hook); +} + +void init_all_pd() { + for (int i = 0; i < MAX_DISKS && PHYSICAL_DISKS[i] != NULL; i++) { + PHYSICAL_DISKS[i]->m_DriveNumber = i; + init_pd(PHYSICAL_DISKS[i]); + } +} + +BOOL q_drive_ReadFile(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { + log_misc("q", "CDROM read 0x%04x bytes at 0x%08x", nNumberOfBytesToRead, + ctx->m_Pointer.QuadPart); + + /** + * [ Drive format ] + * + * - AlphaDVD authentication is prefixed onto the drive. + * - The real start can be extracted from the header + * - offset = 1264 (for my SDCQ) + * + * +511: Disk header (1 sector) + * 000800004574A1180002000053444351 + * +512: Boot ID (128 sectors) [keychip.decrypt] + */ + + HANDLE hFile = _CreateFileA("\\\\.\\E:", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("q", "READ FAILED. FILE FALLBACK FAILED. %d", GetLastError()); + return FALSE; + } + + _SetFilePointerEx(hFile, ctx->m_Pointer, NULL, FILE_BEGIN); + _ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); + _CloseHandle(hFile); + + log_warning("q", "READ FAILED. FILE FALLBACK (Read %d bytes).", *lpNumberOfBytesRead); + return TRUE; +} + +void hook_drives() { + init_all_pd(); + + file_hook_t* c_drive = new_file_hook(L"\\\\.\\C:"); + c_drive->DeviceIoControl = &c_drive_DeviceIoControl; + hook_file(c_drive); + + file_hook_t* x_drive = new_file_hook(L"X:"); + x_drive->DeviceIoControl = &x_drive_DeviceIoControl; + hook_file(x_drive); + + file_hook_t* q_drive = new_file_hook(L"\\\\.\\Q:"); + q_drive->DeviceIoControl = &q_drive_DeviceIoControl; + q_drive->ReadFile = &q_drive_ReadFile; + hook_file(q_drive); + // ewwwwwwwwwwwwwwwwww + file_hook_t* q_drive_lower = new_file_hook(L"\\\\.\\q:"); + q_drive_lower->DeviceIoControl = &q_drive_DeviceIoControl; + q_drive_lower->ReadFile = &q_drive_ReadFile; + hook_file(q_drive_lower); + + hook("Kernel32.dll", "FindFirstVolumeW", &FakeFindFirstVolumeW, NULL); + hook("Kernel32.dll", "FindNextVolumeW", &FakeFindNextVolumeW, NULL); + hook("Kernel32.dll", "FindFirstVolumeA", &FakeFindFirstVolumeA, NULL); + hook("Kernel32.dll", "FindNextVolumeA", &FakeFindNextVolumeA, NULL); + hook("Kernel32.dll", "FindVolumeClose", &FakeFindVolumeClose, NULL); + hook("Kernel32.dll", "SetVolumeLabelA", &FakeSetVolumeLabelA, NULL); + hook("Kernel32.dll", "GetVolumeInformationA", &FakeGetVolumeInformationA, NULL); + hook("Kernel32.dll", "QueryDosDeviceA", &FakeQueryDosDeviceA, NULL); + + hook("Kernel32.dll", "GetVolumeNameForVolumeMountPointA", + &FakeGetVolumeNameForVolumeMountPointA, NULL); + hook("Kernel32.dll", "GetVolumePathNamesForVolumeNameA", &FakeGetVolumePathNamesForVolumeNameA, + NULL); + hook("Kernel32.dll", "DeleteVolumeMountPointA", &FakeDeleteVolumeMountPointA, NULL); + hook("Kernel32.dll", "SetVolumeMountPointA", &FakeSetVolumeMountPointA, NULL); + hook("Kernel32.dll", "GetDriveTypeA", &FakeGetDriveTypeA, NULL); + hook("Kernel32.dll", "GetDiskFreeSpaceExA", &FakeGetDiskFreeSpaceExA, (void**)&TrueGetDiskFreeSpaceExA); + + hook("Winmm.dll", "mciSendStringA", &Fake_mciSendStringA, NULL); + + make_dirs(DISK_PATH); + + SegaBootRecordDefault.crc = + amiCrc32RCalc(sizeof SegaBootRecordDefault - 4, &SegaBootRecordDefault.version, 0); + + HANDLE hFile; + DWORD numberOfBytesRead; + if (_PathFileExistsA(SBR0_PATH)) { + hFile = + _CreateFileA(SBR0_PATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("drive", "Failed to open %s", SBR0_PATH); + } else { + _ReadFile(hFile, &SegaBootRecord0, sizeof SegaBootRecord0, &numberOfBytesRead, NULL); + _CloseHandle(hFile); + log_info("drive", "Restored SBR0 from %s", SBR0_PATH); + } + } else { + // memcpy(&SegaBootRecord0, &SegaBootRecordDefault, sizeof SegaBootRecord0); + } + + if (_PathFileExistsA(SBR1_PATH)) { + hFile = + _CreateFileA(SBR1_PATH, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("drive", "Failed to open %s", SBR1_PATH); + } else { + _ReadFile(hFile, &SegaBootRecord1, sizeof SegaBootRecord1, &numberOfBytesRead, NULL); + _CloseHandle(hFile); + log_info("drive", "Restored SBR1 from %s", SBR0_PATH); + } + } else { + memcpy(&SegaBootRecord1, &SegaBootRecord0, sizeof SegaBootRecord0); + } + + /** + * mxinstaller iterates all volumes to find those that match the slot metadata. + * It uses: + * - FindFirstVolumeW + * - FindNextVolumeW + * - FindVolumeClose + * to iterate volumes. + * For each volume, it: + * - opens it with CreateFileW + * - calls IOCTL_STORAGE_GET_DEVICE_NUMBER + * - asserts that DeviceType == FILE_DEVICE_DISK + * - calls IOCTL_VOLUME_GET_VOLUME_DISK_EXTENT + * - checks that NumberOfDiskExtents < 128 + * - this is not fatal, however an error will be shown and only the first 128 will be checked + * - for each extent (!! sizeof DISK_EXTENT == 24; it's 8-byte aligned): + * - asserts that [].DiskNumber == state_->DiskNumber + * - finds a slot that matches: + * - slot->offset == [].StartingOffset + * - slot->segments == ([].ExtentLength.LowPart >> 9) | ([].ExtentLength.HighPart << 23) + * == [].ExtentLength / 512 + */ +} diff --git a/src/micetools/dll/hooks/drive/drive.h b/src/micetools/dll/hooks/drive/drive.h new file mode 100644 index 0000000..ece2d52 --- /dev/null +++ b/src/micetools/dll/hooks/drive/drive.h @@ -0,0 +1,149 @@ +#pragma once + +#ifndef _MICE_DRIVE +#define _MICE_DRIVE extern +#endif + +#include +// (clang-format moves Windows.h if this isn't here!) +#include +#include +#include + +#include "../../common.h" +#include "../files.h" +#include "disks.h" +#include "irb.h" + +#define DISK_PATH "dev/disk/" +#define SPD_PATH (DISK_PATH "spd.bin") +#define SBR0_PATH (DISK_PATH "sbr0.bin") +#define SBR1_PATH (DISK_PATH "sbr1.bin") +#define ORIGINAL0_PATH (DISK_PATH "original0.bin") + +extern physical_disk_t SSD; +extern physical_disk_t UPDATE_USB; +extern physical_disk_t LOG_USB; +extern physical_disk_t ALPHA_DVD; + +extern sbr_t SegaBootRecordDefault; +extern sbr_t SegaBootRecord0; +extern sbr_t SegaBootRecord1; + +// Functions +void init_volume(disk_volume_t* vol); +void init_pd(physical_disk_t* pd); +void init_all_pd(); + +mice_partition_read_function_t ReadFunc_Original0; +mice_partition_write_function_t WriteFunc_Original0; +mice_partition_read_function_t ReadFunc_OSLogFiles; + +FnDeviceIoControl c_drive_DeviceIoControl; +FnDeviceIoControl x_drive_DeviceIoControl; +FnDeviceIoControl q_drive_DeviceIoControl; +FnDeviceIoControl pd_DeviceIoControl; +FnDeviceIoControl volume_DeviceIoControl; + +FnReadFile pd_ReadFile; +FnWriteFile pd_WriteFile; +FnReadFile q_drive_ReadFile; + +sbr_slot_t* get_sbr_slot(spd_slot_t slot); +disk_volume_t* incrementFindIndex(HANDLE hFindVolume); + +#define VOL_MATCH_PATH 1 +#define VOL_MATCH_GUID 2 +#define VOL_MATCH_DOS_DEVICE 4 +#define VOL_MATCH_ALL (VOL_MATCH_PATH | VOL_MATCH_GUID | VOL_MATCH_DOS_DEVICE) +inline static BOOL matchVolume(disk_volume_t* volume, LPCSTR lpRootPathName, DWORD match); +disk_volume_t* getVolumeByPath(LPCSTR lpRootPathName, DWORD match); + +// Hooks +BOOL WINAPI FakeFindNextVolumeW(HANDLE hFindVolume, LPWSTR lpszVolumeName, DWORD cchBufferLength); +BOOL WINAPI FakeFindNextVolumeA(HANDLE hFindVolume, LPSTR lpszVolumeName, DWORD cchBufferLength); +HANDLE WINAPI FakeFindFirstVolumeW(LPWSTR lpszVolumeName, DWORD cchBufferLength); +HANDLE WINAPI FakeFindFirstVolumeA(LPSTR lpszVolumeName, DWORD cchBufferLength); +BOOL WINAPI FakeFindVolumeClose(HANDLE hFindVolume); +BOOL WINAPI FakeGetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, + LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize); +BOOL WINAPI FakeSetVolumeLabelA(LPCSTR lpRootPathName, LPCSTR lpVolumeName); +BOOL WINAPI FakeGetVolumeNameForVolumeMountPointA(LPCSTR lpszVolumeMountPoint, LPSTR lpszVolumeName, + DWORD cchBufferLength); +BOOL WINAPI FakeGetVolumePathNamesForVolumeNameA(LPCSTR lpszVolumeName, LPCH lpszVolumePathNames, + DWORD cchBufferLength, PDWORD lpcchReturnLength); +BOOL WINAPI FakeDeleteVolumeMountPointA(LPCSTR lpszVolumeMountPoint); +BOOL WINAPI FakeSetVolumeMountPointA(LPCSTR lpszVolumeMountPoint, LPCSTR lpszVolumeName); +DWORD WINAPI FakeQueryDosDeviceA(LPCSTR lpDeviceName, LPSTR lpTargetPath, DWORD ucchMax); +MCIERROR WINAPI Fake_mciSendStringA(LPCTSTR lpszCommand, LPTSTR lpszReturnString, UINT cchReturn, + HANDLE hwndCallback); +UINT WINAPI FakeGetDriveTypeA(LPCSTR lpRootPathName); +BOOL WINAPI FakeGetDiskFreeSpaceExA(LPCSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes); + +_MICE_DRIVE BOOL(WINAPI* TrueGetDiskFreeSpaceExA)(LPCSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes); + +void hook_drives(); + +// MBR +#define MBR_LBA_GAP 0x3f // 1 track worth of sectors is claimed for the MBR +#define EXT_HEADER_GAP 0x3f + +#define MBR_FLAG_NONE 0x00 +#define MBR_FLAG_BOOTABLE 0x80 + +#define MBR_FS_NONE 0x00 +#define MBR_FS_EXT_CHS 0x05 +#define MBR_FS_FAT16 0x06 +#define MBR_FS_NTFS 0x07 +#define MBR_FS_EXT_LBA 0x0F + +#pragma pack(push, 1) +typedef struct mbr { + BYTE bootstrap_code[446]; + struct { + BYTE status; + BYTE start_chs[3]; + BYTE type; + BYTE end_chs[3]; + DWORD lba; + DWORD sectors; + } partitions[4]; + BYTE sig[2]; +} mbr_t; +#pragma pack(pop) + +#define IOCTL_CDROM_GET_DRIVE_GEOMETRY 0x2404c // #include causes errors + +#define BLOCK_SIZE_FLASH 4096 +#define BLOCK_SIZE_HDD 512 +#define BLOCK_SIZE_CDROM 2048 +#define BLOCK_SIZE_DVD BLOCK_SIZE_CDROM + +// SCSI Peripheral Device Type +typedef enum { + DeviceTypeDAB = 0, + DeviceTypeSAB, + DeviceTypePrinter, + DeviceTypeProcessor, + DeviceTypeWriteOnce, + DeviceTypeCdRom, + DeviceTypeScanner, + DeviceTypeOpticalMemory, + DeviceTypeMediumChanger, + DeviceTypeCommunications, + DeviceTypeSAC = 12, + DeviceTypeEnclosure, + DeviceTypeOpticalCard, + DeviceTypeAutomationInterface, + DeviceTypeSecurityManager, + DeviceTypeHMBlock, + DeviceTypeUnknown = 31, +} DEVICE_TYPE; diff --git a/src/micetools/dll/hooks/drive/hooks.c b/src/micetools/dll/hooks/drive/hooks.c new file mode 100644 index 0000000..f7dfda3 --- /dev/null +++ b/src/micetools/dll/hooks/drive/hooks.c @@ -0,0 +1,279 @@ +#include "drive.h" + +typedef struct { + size_t disk; + size_t partition; +} find_index_t; +disk_volume_t* incrementFindIndex(HANDLE hFindVolume) { + find_index_t* find_index = GetDataForHandle(hFindVolume, HDATA_FIND_VOLUME); + if (find_index == NULL) return NULL; + + while (1) { + if (find_index->disk >= MAX_DISKS || PHYSICAL_DISKS[find_index->disk] == NULL) { + return NULL; + } + + if (find_index->partition > 3) { + if (PHYSICAL_DISKS[find_index->disk] + ->m_Extended[find_index->partition - 4] + .m_PartitionNumber == 0) { + find_index->disk++; + find_index->partition = 0; + continue; + } + + return &(PHYSICAL_DISKS[find_index->disk] + ->m_Extended[(find_index->partition++) - 4] + .m_Volume); + } + if (PHYSICAL_DISKS[find_index->disk] + ->m_Partitions[find_index->partition] + .m_PartitionNumber == 0) { + find_index->partition = 4; + continue; + } + + return &(PHYSICAL_DISKS[find_index->disk]->m_Partitions[find_index->partition++].m_Volume); + } +} + +BOOL WINAPI FakeFindNextVolumeW(HANDLE hFindVolume, LPWSTR lpszVolumeName, DWORD cchBufferLength) { + disk_volume_t* volume = incrementFindIndex(hFindVolume); + if (volume == NULL) { + SetLastError(ERROR_NO_MORE_FILES); + return FALSE; + } + + wcscpy_s(lpszVolumeName, cchBufferLength, volume->m_FilenameW); + wcscat_s(lpszVolumeName, cchBufferLength, L"\\"); + return TRUE; +} +BOOL WINAPI FakeFindNextVolumeA(HANDLE hFindVolume, LPSTR lpszVolumeName, DWORD cchBufferLength) { + disk_volume_t* volume = incrementFindIndex(hFindVolume); + if (volume == NULL) { + SetLastError(ERROR_NO_MORE_FILES); + return FALSE; + } + + strcpy_s(lpszVolumeName, cchBufferLength, volume->m_FilenameA); + strcat_s(lpszVolumeName, cchBufferLength, "\\"); + return TRUE; +} +HANDLE WINAPI FakeFindFirstVolumeW(LPWSTR lpszVolumeName, DWORD cchBufferLength) { + find_index_t* find_index = malloc(sizeof(find_index_t)); + find_index->disk = 0; + find_index->partition = 0; + HANDLE handle = GetDummyHandle(); + SetDataForHandle(handle, HDATA_FIND_VOLUME, find_index, TRUE); + + FakeFindNextVolumeW(handle, lpszVolumeName, cchBufferLength); + return handle; +} +HANDLE WINAPI FakeFindFirstVolumeA(LPSTR lpszVolumeName, DWORD cchBufferLength) { + find_index_t* find_index = malloc(sizeof(find_index_t)); + find_index->disk = 0; + find_index->partition = 0; + HANDLE handle = GetDummyHandle(); + SetDataForHandle(handle, HDATA_FIND_VOLUME, find_index, TRUE); + + FakeFindNextVolumeA(handle, lpszVolumeName, cchBufferLength); + return handle; +} +BOOL WINAPI FakeFindVolumeClose(HANDLE hFindVolume) { + if (RemoveDataForHandle(hFindVolume, HDATA_FIND_VOLUME)) return _CloseHandle(hFindVolume); + return FALSE; +} + +BOOL WINAPI FakeGetVolumeInformationA(LPCSTR lpRootPathName, LPSTR lpVolumeNameBuffer, + DWORD nVolumeNameSize, LPDWORD lpVolumeSerialNumber, + LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, + LPSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { + disk_volume_t* volume = getVolumeByPath(lpRootPathName, VOL_MATCH_ALL); + if (volume == NULL) return FALSE; + + if (lpVolumeSerialNumber) *lpVolumeSerialNumber = volume->m_pDrive->m_SerialNumber; + + // TODO: Ripped from a RingEdge. Make these part of our emulation. + if (lpFileSystemFlags) *lpFileSystemFlags = 0x700ff; + if (lpMaximumComponentLength) *lpMaximumComponentLength = 255; + // TODO: This isn't even true for non-NTFS partitions + if (lpFileSystemNameBuffer) strncpy_s(lpFileSystemNameBuffer, nFileSystemNameSize, "NTFS", 5); + + if (lpVolumeNameBuffer && nVolumeNameSize) { + if (volume->m_Name) + strcpy_s(lpVolumeNameBuffer, nVolumeNameSize, volume->m_Name); + else + lpVolumeNameBuffer[0] = '\0'; + } + return TRUE; +} +BOOL WINAPI FakeSetVolumeLabelA(LPCSTR lpRootPathName, LPCSTR lpVolumeName) { + disk_volume_t* volume = getVolumeByPath(lpRootPathName, VOL_MATCH_ALL); + if (volume == NULL) return FALSE; + + if (lpVolumeName) { + size_t len = strlen(lpVolumeName); + // By default volume names are pointers to constants! + if (volume->m_NameIsOnHeap) + realloc(volume->m_Name, len + 1); + else { + volume->m_Name = malloc(len + 1); + volume->m_NameIsOnHeap = TRUE; + } + memcpy(volume->m_Name, lpVolumeName, len); + } else { + volume->m_Name = NULL; + } + return TRUE; +} +BOOL WINAPI FakeGetVolumeNameForVolumeMountPointA(LPCSTR lpszVolumeMountPoint, LPSTR lpszVolumeName, + DWORD cchBufferLength) { + log_trace("drive", "GetVolumeNameForVolumeMountPointA(%s)", lpszVolumeMountPoint); + + disk_volume_t* volume = getVolumeByPath(lpszVolumeMountPoint, VOL_MATCH_PATH); + if (volume == NULL) { + SetLastError(ERROR_FILE_NOT_FOUND); + return FALSE; + } + + strcpy_s(lpszVolumeName, cchBufferLength, volume->m_FilenameA); + return TRUE; +} +BOOL WINAPI FakeGetVolumePathNamesForVolumeNameA(LPCSTR lpszVolumeName, LPCH lpszVolumePathNames, + DWORD cchBufferLength, PDWORD lpcchReturnLength) { + log_trace("drive", "GetVolumeNameForVolumeMountPointA(%s)", lpszVolumeName); + + disk_volume_t* volume = getVolumeByPath(lpszVolumeName, VOL_MATCH_GUID); + if (volume == NULL) { + SetLastError(ERROR_FILE_NOT_FOUND); + return FALSE; + } + + if (volume->m_MountPoint) { + // TODO: Handle the situation where the buffer is too small + *lpcchReturnLength = + sprintf_s(lpszVolumePathNames, cchBufferLength, "\\\\.\\%c:", volume->m_MountPoint); + if (*lpcchReturnLength != cchBufferLength) { + lpszVolumePathNames[*lpcchReturnLength] = '\0'; + *lpcchReturnLength++; + } + } else { + *lpcchReturnLength = 0; + } + + return TRUE; +} +BOOL WINAPI FakeDeleteVolumeMountPointA(LPCSTR lpszVolumeMountPoint) { + log_trace("drive", "DeleteVolumeMountPointA(%s)", lpszVolumeMountPoint); + disk_volume_t* volume = getVolumeByPath(lpszVolumeMountPoint, VOL_MATCH_PATH); + if (volume == NULL) { + SetLastError(ERROR_FILE_NOT_FOUND); + return FALSE; + } + + volume->m_MountPoint = '\0'; + return TRUE; +} +BOOL WINAPI FakeSetVolumeMountPointA(LPCSTR lpszVolumeMountPoint, LPCSTR lpszVolumeName) { + log_trace("drive", "SetVolumeMountPointA(%s)", lpszVolumeMountPoint); + disk_volume_t* volume = getVolumeByPath(lpszVolumeName, VOL_MATCH_GUID); + if (volume == NULL) { + SetLastError(ERROR_FILE_NOT_FOUND); + return FALSE; + } + + char cMountPoint; + DWORD nScan; + if (sscanf_s(lpszVolumeMountPoint, "\\\\.\\%c:%n", &cMountPoint, 1, &nScan) == 1 && + nScan == 6) { + log_info("drive", "Mounting %s at %c:\\", volume->m_Name, cMountPoint); + volume->m_MountPoint = cMountPoint; + return TRUE; + } + if (sscanf_s(lpszVolumeMountPoint, "%c:\\%n", &cMountPoint, 1, &nScan) == 1 && nScan == 3) { + log_info("drive", "Mounting %s at %c:\\", volume->m_Name, cMountPoint); + volume->m_MountPoint = cMountPoint; + return TRUE; + } + + return FALSE; +} + +DWORD WINAPI FakeQueryDosDeviceA(LPCSTR lpDeviceName, LPSTR lpTargetPath, DWORD ucchMax) { + if (lpDeviceName != NULL) { + disk_volume_t* volume = getVolumeByPath(lpDeviceName, VOL_MATCH_DOS_DEVICE); + if (volume == NULL) { + SetLastError(ERROR_FILE_NOT_FOUND); + return 0; + } + + size_t mountLen = wcslen(volume->m_DeviceName); + if (ucchMax < mountLen + 1) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return 0; + } + sprintf_s(lpTargetPath, ucchMax, "\\Device\\%ls", volume->m_DeviceName); + return ucchMax; + } + return 0; +} + +MCIERROR WINAPI Fake_mciSendStringA(LPCTSTR lpszCommand, LPTSTR lpszReturnString, UINT cchReturn, + HANDLE hwndCallback) { + if (strcmp(lpszCommand, "open cdaudio") == 0) { + return 0; + } + if (strcmp(lpszCommand, "set cdaudio door open") == 0) { + log_game("mci", "Cupholder opened!"); + return 0; + } + if (strcmp(lpszCommand, "status cdaudio media present") == 0) { + if (lpszReturnString) { + if (TRUE) + strcpy_s(lpszReturnString, cchReturn, "true"); + else + strcpy_s(lpszReturnString, cchReturn, "false"); + } + return 0; + } + if (strcmp(lpszCommand, "close cdaudio") == 0) { + return 0; + } + return MCIERR_UNRECOGNIZED_COMMAND; +} + +UINT WINAPI FakeGetDriveTypeA(LPCSTR lpRootPathName) { + disk_volume_t* volume = getVolumeByPath(lpRootPathName, VOL_MATCH_PATH | VOL_MATCH_DOS_DEVICE); + if (volume == NULL) { + SetLastError(ERROR_FILE_NOT_FOUND); + return DRIVE_NO_ROOT_DIR; + } + + switch (volume->m_pDrive->m_DiskType) { + case DiskType_CdRom: + return DRIVE_CDROM; + case DiskType_HardDisk: + return DRIVE_FIXED; + case DiskType_Flash: + case DiskType_Floppy: + return DRIVE_REMOVABLE; + default: + return DRIVE_UNKNOWN; + } +} + +BOOL WINAPI FakeGetDiskFreeSpaceExA(LPCSTR lpDirectoryName, + PULARGE_INTEGER lpFreeBytesAvailableToCaller, + PULARGE_INTEGER lpTotalNumberOfBytes, + PULARGE_INTEGER lpTotalNumberOfFreeBytes) { + // disk_volume_t* volume = getVolumeByPath(lpDirectoryName, VOL_MATCH_ALL); + // if (volume == NULL) { + // SetLastError(ERROR_FILE_NOT_FOUND); + // return FALSE; + // } + + // We're going to be remapping the drive to ./dev/, so the free bytes are whatever the current + // real drive has free. No point claiming we have more than we do! + return TrueGetDiskFreeSpaceExA(NULL, lpFreeBytesAvailableToCaller, lpTotalNumberOfBytes, + lpTotalNumberOfFreeBytes); +} diff --git a/src/micetools/dll/hooks/drive/irb.h b/src/micetools/dll/hooks/drive/irb.h new file mode 100644 index 0000000..28be014 --- /dev/null +++ b/src/micetools/dll/hooks/drive/irb.h @@ -0,0 +1,375 @@ +#pragma once +#include + +// Lifted from Irb.h +typedef struct _IDENTIFY_DEVICE_DATA { + struct { + USHORT Reserved1 : 1; + USHORT Retired3 : 1; + USHORT ResponseIncomplete : 1; + USHORT Retired2 : 3; + USHORT FixedDevice : 1; + USHORT RemovableMedia : 1; + USHORT Retired1 : 7; + USHORT DeviceType : 1; + } GeneralConfiguration; + USHORT NumCylinders; + USHORT SpecificConfiguration; + USHORT NumHeads; + USHORT Retired1[2]; + USHORT NumSectorsPerTrack; + USHORT VendorUnique1[3]; + UCHAR SerialNumber[20]; + USHORT Retired2[2]; + USHORT Obsolete1; + UCHAR FirmwareRevision[8]; + UCHAR ModelNumber[40]; + UCHAR MaximumBlockTransfer; + UCHAR VendorUnique2; + struct { + USHORT FeatureSupported : 1; + USHORT Reserved : 15; + } TrustedComputing; + struct { + UCHAR CurrentLongPhysicalSectorAlignment : 2; + UCHAR ReservedByte49 : 6; + UCHAR DmaSupported : 1; + UCHAR LbaSupported : 1; + UCHAR IordyDisable : 1; + UCHAR IordySupported : 1; + UCHAR Reserved1 : 1; + UCHAR StandybyTimerSupport : 1; + UCHAR Reserved2 : 2; + USHORT ReservedWord50; + } Capabilities; + USHORT ObsoleteWords51[2]; + USHORT TranslationFieldsValid : 3; + USHORT Reserved3 : 5; + USHORT FreeFallControlSensitivity : 8; + USHORT NumberOfCurrentCylinders; + USHORT NumberOfCurrentHeads; + USHORT CurrentSectorsPerTrack; + ULONG CurrentSectorCapacity; + UCHAR CurrentMultiSectorSetting; + UCHAR MultiSectorSettingValid : 1; + UCHAR ReservedByte59 : 3; + UCHAR SanitizeFeatureSupported : 1; + UCHAR CryptoScrambleExtCommandSupported : 1; + UCHAR OverwriteExtCommandSupported : 1; + UCHAR BlockEraseExtCommandSupported : 1; + ULONG UserAddressableSectors; + USHORT ObsoleteWord62; + USHORT MultiWordDMASupport : 8; + USHORT MultiWordDMAActive : 8; + USHORT AdvancedPIOModes : 8; + USHORT ReservedByte64 : 8; + USHORT MinimumMWXferCycleTime; + USHORT RecommendedMWXferCycleTime; + USHORT MinimumPIOCycleTime; + USHORT MinimumPIOCycleTimeIORDY; + struct { + USHORT ZonedCapabilities : 2; + USHORT NonVolatileWriteCache : 1; + USHORT ExtendedUserAddressableSectorsSupported : 1; + USHORT DeviceEncryptsAllUserData : 1; + USHORT ReadZeroAfterTrimSupported : 1; + USHORT Optional28BitCommandsSupported : 1; + USHORT IEEE1667 : 1; + USHORT DownloadMicrocodeDmaSupported : 1; + USHORT SetMaxSetPasswordUnlockDmaSupported : 1; + USHORT WriteBufferDmaSupported : 1; + USHORT ReadBufferDmaSupported : 1; + USHORT DeviceConfigIdentifySetDmaSupported : 1; + USHORT LPSAERCSupported : 1; + USHORT DeterministicReadAfterTrimSupported : 1; + USHORT CFastSpecSupported : 1; + } AdditionalSupported; + USHORT ReservedWords70[5]; + USHORT QueueDepth : 5; + USHORT ReservedWord75 : 11; + struct { + USHORT Reserved0 : 1; + USHORT SataGen1 : 1; + USHORT SataGen2 : 1; + USHORT SataGen3 : 1; + USHORT Reserved1 : 4; + USHORT NCQ : 1; + USHORT HIPM : 1; + USHORT PhyEvents : 1; + USHORT NcqUnload : 1; + USHORT NcqPriority : 1; + USHORT HostAutoPS : 1; + USHORT DeviceAutoPS : 1; + USHORT ReadLogDMA : 1; + USHORT Reserved2 : 1; + USHORT CurrentSpeed : 3; + USHORT NcqStreaming : 1; + USHORT NcqQueueMgmt : 1; + USHORT NcqReceiveSend : 1; + USHORT DEVSLPtoReducedPwrState : 1; + USHORT Reserved3 : 8; + } SerialAtaCapabilities; + struct { + USHORT Reserved0 : 1; + USHORT NonZeroOffsets : 1; + USHORT DmaSetupAutoActivate : 1; + USHORT DIPM : 1; + USHORT InOrderData : 1; + USHORT HardwareFeatureControl : 1; + USHORT SoftwareSettingsPreservation : 1; + USHORT NCQAutosense : 1; + USHORT DEVSLP : 1; + USHORT HybridInformation : 1; + USHORT Reserved1 : 6; + } SerialAtaFeaturesSupported; + struct { + USHORT Reserved0 : 1; + USHORT NonZeroOffsets : 1; + USHORT DmaSetupAutoActivate : 1; + USHORT DIPM : 1; + USHORT InOrderData : 1; + USHORT HardwareFeatureControl : 1; + USHORT SoftwareSettingsPreservation : 1; + USHORT DeviceAutoPS : 1; + USHORT DEVSLP : 1; + USHORT HybridInformation : 1; + USHORT Reserved1 : 6; + } SerialAtaFeaturesEnabled; + USHORT MajorRevision; + USHORT MinorRevision; + struct { + USHORT SmartCommands : 1; + USHORT SecurityMode : 1; + USHORT RemovableMediaFeature : 1; + USHORT PowerManagement : 1; + USHORT Reserved1 : 1; + USHORT WriteCache : 1; + USHORT LookAhead : 1; + USHORT ReleaseInterrupt : 1; + USHORT ServiceInterrupt : 1; + USHORT DeviceReset : 1; + USHORT HostProtectedArea : 1; + USHORT Obsolete1 : 1; + USHORT WriteBuffer : 1; + USHORT ReadBuffer : 1; + USHORT Nop : 1; + USHORT Obsolete2 : 1; + USHORT DownloadMicrocode : 1; + USHORT DmaQueued : 1; + USHORT Cfa : 1; + USHORT AdvancedPm : 1; + USHORT Msn : 1; + USHORT PowerUpInStandby : 1; + USHORT ManualPowerUp : 1; + USHORT Reserved2 : 1; + USHORT SetMax : 1; + USHORT Acoustics : 1; + USHORT BigLba : 1; + USHORT DeviceConfigOverlay : 1; + USHORT FlushCache : 1; + USHORT FlushCacheExt : 1; + USHORT WordValid83 : 2; + USHORT SmartErrorLog : 1; + USHORT SmartSelfTest : 1; + USHORT MediaSerialNumber : 1; + USHORT MediaCardPassThrough : 1; + USHORT StreamingFeature : 1; + USHORT GpLogging : 1; + USHORT WriteFua : 1; + USHORT WriteQueuedFua : 1; + USHORT WWN64Bit : 1; + USHORT URGReadStream : 1; + USHORT URGWriteStream : 1; + USHORT ReservedForTechReport : 2; + USHORT IdleWithUnloadFeature : 1; + USHORT WordValid : 2; + } CommandSetSupport; + struct { + USHORT SmartCommands : 1; + USHORT SecurityMode : 1; + USHORT RemovableMediaFeature : 1; + USHORT PowerManagement : 1; + USHORT Reserved1 : 1; + USHORT WriteCache : 1; + USHORT LookAhead : 1; + USHORT ReleaseInterrupt : 1; + USHORT ServiceInterrupt : 1; + USHORT DeviceReset : 1; + USHORT HostProtectedArea : 1; + USHORT Obsolete1 : 1; + USHORT WriteBuffer : 1; + USHORT ReadBuffer : 1; + USHORT Nop : 1; + USHORT Obsolete2 : 1; + USHORT DownloadMicrocode : 1; + USHORT DmaQueued : 1; + USHORT Cfa : 1; + USHORT AdvancedPm : 1; + USHORT Msn : 1; + USHORT PowerUpInStandby : 1; + USHORT ManualPowerUp : 1; + USHORT Reserved2 : 1; + USHORT SetMax : 1; + USHORT Acoustics : 1; + USHORT BigLba : 1; + USHORT DeviceConfigOverlay : 1; + USHORT FlushCache : 1; + USHORT FlushCacheExt : 1; + USHORT Resrved3 : 1; + USHORT Words119_120Valid : 1; + USHORT SmartErrorLog : 1; + USHORT SmartSelfTest : 1; + USHORT MediaSerialNumber : 1; + USHORT MediaCardPassThrough : 1; + USHORT StreamingFeature : 1; + USHORT GpLogging : 1; + USHORT WriteFua : 1; + USHORT WriteQueuedFua : 1; + USHORT WWN64Bit : 1; + USHORT URGReadStream : 1; + USHORT URGWriteStream : 1; + USHORT ReservedForTechReport : 2; + USHORT IdleWithUnloadFeature : 1; + USHORT Reserved4 : 2; + } CommandSetActive; + USHORT UltraDMASupport : 8; + USHORT UltraDMAActive : 8; + struct { + USHORT TimeRequired : 15; + USHORT ExtendedTimeReported : 1; + } NormalSecurityEraseUnit; + struct { + USHORT TimeRequired : 15; + USHORT ExtendedTimeReported : 1; + } EnhancedSecurityEraseUnit; + USHORT CurrentAPMLevel : 8; + USHORT ReservedWord91 : 8; + USHORT MasterPasswordID; + USHORT HardwareResetResult; + USHORT CurrentAcousticValue : 8; + USHORT RecommendedAcousticValue : 8; + USHORT StreamMinRequestSize; + USHORT StreamingTransferTimeDMA; + USHORT StreamingAccessLatencyDMAPIO; + ULONG StreamingPerfGranularity; + ULONG Max48BitLBA[2]; + USHORT StreamingTransferTime; + USHORT DsmCap; + struct { + USHORT LogicalSectorsPerPhysicalSector : 4; + USHORT Reserved0 : 8; + USHORT LogicalSectorLongerThan256Words : 1; + USHORT MultipleLogicalSectorsPerPhysicalSector : 1; + USHORT Reserved1 : 2; + } PhysicalLogicalSectorSize; + USHORT InterSeekDelay; + USHORT WorldWideName[4]; + USHORT ReservedForWorldWideName128[4]; + USHORT ReservedForTlcTechnicalReport; + USHORT WordsPerLogicalSector[2]; + struct { + USHORT ReservedForDrqTechnicalReport : 1; + USHORT WriteReadVerify : 1; + USHORT WriteUncorrectableExt : 1; + USHORT ReadWriteLogDmaExt : 1; + USHORT DownloadMicrocodeMode3 : 1; + USHORT FreefallControl : 1; + USHORT SenseDataReporting : 1; + USHORT ExtendedPowerConditions : 1; + USHORT Reserved0 : 6; + USHORT WordValid : 2; + } CommandSetSupportExt; + struct { + USHORT ReservedForDrqTechnicalReport : 1; + USHORT WriteReadVerify : 1; + USHORT WriteUncorrectableExt : 1; + USHORT ReadWriteLogDmaExt : 1; + USHORT DownloadMicrocodeMode3 : 1; + USHORT FreefallControl : 1; + USHORT SenseDataReporting : 1; + USHORT ExtendedPowerConditions : 1; + USHORT Reserved0 : 6; + USHORT Reserved1 : 2; + } CommandSetActiveExt; + USHORT ReservedForExpandedSupportandActive[6]; + USHORT MsnSupport : 2; + USHORT ReservedWord127 : 14; + struct { + USHORT SecuritySupported : 1; + USHORT SecurityEnabled : 1; + USHORT SecurityLocked : 1; + USHORT SecurityFrozen : 1; + USHORT SecurityCountExpired : 1; + USHORT EnhancedSecurityEraseSupported : 1; + USHORT Reserved0 : 2; + USHORT SecurityLevel : 1; + USHORT Reserved1 : 7; + } SecurityStatus; + USHORT ReservedWord129[31]; + struct { + USHORT MaximumCurrentInMA : 12; + USHORT CfaPowerMode1Disabled : 1; + USHORT CfaPowerMode1Required : 1; + USHORT Reserved0 : 1; + USHORT Word160Supported : 1; + } CfaPowerMode1; + USHORT ReservedForCfaWord161[7]; + USHORT NominalFormFactor : 4; + USHORT ReservedWord168 : 12; + struct { + USHORT SupportsTrim : 1; + USHORT Reserved0 : 15; + } DataSetManagementFeature; + USHORT AdditionalProductID[4]; + USHORT ReservedForCfaWord174[2]; + USHORT CurrentMediaSerialNumber[30]; + struct { + USHORT Supported : 1; + USHORT Reserved0 : 1; + USHORT WriteSameSuported : 1; + USHORT ErrorRecoveryControlSupported : 1; + USHORT FeatureControlSuported : 1; + USHORT DataTablesSuported : 1; + USHORT Reserved1 : 6; + USHORT VendorSpecific : 4; + } SCTCommandTransport; + USHORT ReservedWord207[2]; + struct { + USHORT AlignmentOfLogicalWithinPhysical : 14; + USHORT Word209Supported : 1; + USHORT Reserved0 : 1; + } BlockAlignment; + USHORT WriteReadVerifySectorCountMode3Only[2]; + USHORT WriteReadVerifySectorCountMode2Only[2]; + struct { + USHORT NVCachePowerModeEnabled : 1; + USHORT Reserved0 : 3; + USHORT NVCacheFeatureSetEnabled : 1; + USHORT Reserved1 : 3; + USHORT NVCachePowerModeVersion : 4; + USHORT NVCacheFeatureSetVersion : 4; + } NVCacheCapabilities; + USHORT NVCacheSizeLSW; + USHORT NVCacheSizeMSW; + USHORT NominalMediaRotationRate; + USHORT ReservedWord218; + struct { + UCHAR NVCacheEstimatedTimeToSpinUpInSeconds; + UCHAR Reserved; + } NVCacheOptions; + USHORT WriteReadVerifySectorCountMode : 8; + USHORT ReservedWord220 : 8; + USHORT ReservedWord221; + struct { + USHORT MajorVersion : 12; + USHORT TransportType : 4; + } TransportMajorVersion; + USHORT TransportMinorVersion; + USHORT ReservedWord224[6]; + ULONG ExtendedNumberOfUserAddressableSectors[2]; + USHORT MinBlocksPerDownloadMicrocodeMode03; + USHORT MaxBlocksPerDownloadMicrocodeMode03; + USHORT ReservedWord236[19]; + USHORT Signature : 8; + USHORT CheckSum : 8; +} IDENTIFY_DEVICE_DATA, *PIDENTIFY_DEVICE_DATA; diff --git a/src/micetools/dll/hooks/drive/physicalDrive.c b/src/micetools/dll/hooks/drive/physicalDrive.c new file mode 100644 index 0000000..b4fb7e2 --- /dev/null +++ b/src/micetools/dll/hooks/drive/physicalDrive.c @@ -0,0 +1,417 @@ +#include "drive.h" + +BOOL WINAPI pd_DeviceIoControl(file_context_t* ctx, DWORD dwIoControlCode, LPVOID lpInBuffer, + DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize, + LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) { + physical_disk_t* pd = (physical_disk_t*)ctx->m_HookData; + if (pd == NULL) { + log_error("drive", "ioctl:ctx->m_HookData NULL; expected a physical drive!"); + return FALSE; + } + + log_trace("drive", "DeviceIOControl %08x", dwIoControlCode); + ZeroMemory(lpOutBuffer, nOutBufferSize); + switch (dwIoControlCode) { + case IOCTL_ATA_PASS_THROUGH: + if (pd->m_BusType != BusTypeAta) return FALSE; + + PATA_PASS_THROUGH_EX ata = (PATA_PASS_THROUGH_EX)lpInBuffer; + + BYTE command = ata->CurrentTaskFile[6]; + if (command == 0xEC) { + // TODO: One day re-visit this if amPlatformGetStorageInfo is used elsewhere + // PIDENTIFY_DEVICE_DATA identifyData = + // (PIDENTIFY_DEVICE_DATA)((LPBYTE)lpOutBuffer + sizeof *ata + + // ata->DataBufferOffset - 5); + + // // ZeroMemory(identifyData, sizeof *identifyData); + // // TODO: Is there any point worth spoofing anything else? + // strcpy_s((char*)identifyData->ModelNumber, sizeof identifyData->ModelNumber, + // "VDrive"); + // strcpy_s((char*)identifyData->SerialNumber, sizeof identifyData->SerialNumber, + // "AAAAAAAAAAA"); + // identifyData->NumSectorsPerTrack = 0x4243; + *lpBytesReturned = nOutBufferSize; + return TRUE; + } + + if (command != 0xC1) { + log_error("pd0", "Unimplemented ATA command: %02x", command); + + return FALSE; + } + + BYTE data = ata->CurrentTaskFile[0]; + switch (data) { + // These are used un UnlockSection1, 2, and 3 in mxstorage! + + case 0x11: // mxkSsdHostProofSet (step == 0) + // Game -> ATA | 128 bytes: random from N2 + case 0x12: // mxkSsdHostProofGet (step == 0) + // ATA -> GAME | 128 bytes: (guess) readback of 0x11 + case 0x21: // mxkSsdHostProofSet (step == 1) + // Game -> ATA | 128 bytes: random from N2 + case 0x22: // mxkSsdHostProofGet (step == 1) + // ATA -> GAME | 128 bytes: (guess) readback of 0x21 + case 0x31: // mxkSsdHostProofSeed + // ATA -> Game | 80 bytes: seed + case 0x32: // mxkSsdHostProofChallenge + // Game -> ATA | 80 bytes: the seed, encrypted by N2 with S-Key + + // It looks like mxkeychip never actually checks the response buffer, + // as long as the ioctl succeeds! Saves us a lot of work here! + return TRUE; + } + log_error("drive", "Unimeplemented ATA C1 command: %02x", data); + return FALSE; + case IOCTL_DISK_GET_LENGTH_INFO: + PGET_LENGTH_INFORMATION pLi = (PGET_LENGTH_INFORMATION)lpOutBuffer; + pLi->Length.QuadPart = SSD.m_TotalSize * (long long)SSD.m_BlockSize; + *lpBytesReturned = sizeof *pLi; + return TRUE; + } + log_error("drive", "Unimplemented ioctl: %08x", dwIoControlCode); + return FALSE; +} + +BOOL pd_ReadFile(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { + physical_disk_t* pd = (physical_disk_t*)ctx->m_HookData; + if (pd == NULL) { + log_error("drive", "read:ctx->m_HookData NULL; expected a physical drive!"); + return FALSE; + } + + log_misc("drive", "PhysicalDrive%d: Read %d @ %llx", pd->m_DriveNumber, nNumberOfBytesToRead, + ctx->m_Pointer.QuadPart); + + // ! WARNING: This ReadFile implementation is currently limited to aligned + // ! reads. Given the main purpose of this function is to allow reading + // ! the partition information, this doesn't currently pose an issue. + + DWORD ptrLBA = (ctx->m_Pointer.QuadPart / (long long)pd->m_BlockSize) & 0xffffffff; + + // MBR header + if (ptrLBA == 0) { + mbr_t* mbr = (mbr_t*)lpBuffer; + if (nNumberOfBytesToRead < sizeof *mbr) { + log_error("drive", "Buffer too small for master boot record!"); + return FALSE; + } + + memset(mbr, 0, sizeof *mbr); + mbr->sig[0] = 0x55; + mbr->sig[1] = 0xAA; + + for (size_t i = 0; i < 4; i++) { + if (pd->m_Partitions[i].m_Size == 0) break; + + mbr->partitions[i].status = + (pd->m_BootPartition == i + 1) ? MBR_FLAG_BOOTABLE : MBR_FLAG_NONE; + mbr->partitions[i].type = pd->m_Partitions[i].m_Filesystem; + mbr->partitions[i].lba = pd->m_Partitions[i].m_PhysicalLBA; + mbr->partitions[i].sectors = pd->m_Partitions[i].m_Size; + } + + *lpNumberOfBytesRead = sizeof *mbr; + + return TRUE; + } + if (ptrLBA <= MBR_LBA_GAP) { + // Read within the 63 extra tracks + log_error("drive", "Read failed"); + return FALSE; + } + + // MBR partitions + for (size_t i = 0; i < 4; i++) { + if (pd->m_Partitions[i].m_PartitionNumber == 0) break; + + if (ptrLBA >= pd->m_Partitions[i].m_PhysicalLBA && + ptrLBA < pd->m_Partitions[i].m_PhysicalLBA + pd->m_Partitions[i].m_Size) { + DWORD readOffset = ptrLBA - pd->m_Partitions[i].m_PhysicalLBA; + + if (pd->m_Partitions[i].m_ReadFunc == NULL) { + log_error("disk", "Attempted read in %d/%d at block offset %08x; No read function", + pd->m_DriveNumber, pd->m_Partitions[i].m_PartitionNumber, readOffset); + return FALSE; + } + BOOL ret = pd->m_Partitions[i].m_ReadFunc(readOffset, lpBuffer, nNumberOfBytesToRead, + lpNumberOfBytesRead); + if (!ret) { + log_error("disk", "Attempted read in %d/%d at block offset %08x; Read rejected", + pd->m_DriveNumber, pd->m_Partitions[i].m_PartitionNumber, readOffset); + return FALSE; + } + + log_misc("drive", "Read at %d/%d+%d", pd->m_DriveNumber, + pd->m_Partitions[i].m_PartitionNumber, readOffset); + return TRUE; + } + } + + // Extended partitions + for (size_t i = 0; pd->m_Extended[i].m_Size; i++) { + // Extended header + DWORD headerLBA = pd->m_Extended[i].m_PhysicalLBA - EXT_HEADER_GAP; + if (ptrLBA == headerLBA) { + mbr_t* mbr = (mbr_t*)lpBuffer; + if (nNumberOfBytesToRead < sizeof *mbr) { + log_error("drive", "Buffer too small for an extended boot record!"); + return FALSE; + } + + memset(mbr, 0, sizeof *mbr); + mbr->sig[0] = 0x55; + mbr->sig[1] = 0xAA; + + mbr->partitions[0].status = MBR_FLAG_NONE; + mbr->partitions[0].type = pd->m_Extended[i].m_Filesystem; + mbr->partitions[0].lba = EXT_HEADER_GAP; + mbr->partitions[0].sectors = pd->m_Extended[i].m_Size; + + if (pd->m_Extended[i + 1].m_Size) { + mbr->partitions[1].status = MBR_FLAG_NONE; + // ! mxinstaller expects to see CHS here, then uses the LBA values + mbr->partitions[1].type = MBR_FS_EXT_CHS; + mbr->partitions[1].lba = + pd->m_Extended[i + 1].m_PhysicalLBA - pd->m_Extended[0].m_PhysicalLBA; + mbr->partitions[1].sectors = pd->m_Extended[i + 1].m_Size + EXT_HEADER_GAP; + } + + *lpNumberOfBytesRead = sizeof *mbr; + return TRUE; + } + + if (i == 0 && pd->m_HasSegaboot) { + // SEGA Partition Description + if (ptrLBA == headerLBA + SPD_OFFSET) { + spd_t* spd = (spd_t*)lpBuffer; + if (nNumberOfBytesToRead < sizeof *spd) { + log_error("drive", "Buffer too small for SPD!"); + return FALSE; + } + + spd->version = SPD_VERSION; + for (size_t j = 0; pd->m_Extended[j].m_Size; j++) { + spd->slots[j].block_size = pd->m_BlockSize & 0xFFFF; + spd->slots[j].block_count = pd->m_Extended[j].m_Size; + spd->slots[j].slot_content = pd->m_Extended[j].m_SPDContent; + spd->slots[j].uk1 = pd->m_Extended[j].m_Filesystem == MBR_FS_FAT16 ? 0 : 1; + } + + spd->crc = amiCrc32RCalc(sizeof *spd - 4, &(spd->version), 0); + *lpNumberOfBytesRead = sizeof *spd; + return TRUE; + } + // SEGA Boot Record 0 and 1. The two are a redundant copy of each other + if (ptrLBA == headerLBA + SBR0_OFFSET) { + if (nNumberOfBytesToRead < sizeof SegaBootRecord0) { + log_error("drive", "Buffer too small for SBR0!"); + return FALSE; + } + memcpy(lpBuffer, &SegaBootRecord0, sizeof SegaBootRecord0); + *lpNumberOfBytesRead = sizeof SegaBootRecord0; + return TRUE; + } + if (ptrLBA == headerLBA + SBR1_OFFSET) { + if (nNumberOfBytesToRead < sizeof SegaBootRecord1) { + log_error("drive", "Buffer too small for SBR1!"); + return FALSE; + } + memcpy(lpBuffer, &SegaBootRecord1, sizeof SegaBootRecord1); + *lpNumberOfBytesRead = sizeof SegaBootRecord1; + return TRUE; + } + } + + if (ptrLBA >= pd->m_Extended[i].m_PhysicalLBA - EXT_HEADER_GAP && + ptrLBA < pd->m_Extended[i].m_PhysicalLBA) { + // Read within the 63 extra tracks + log_error("drive", "Read failed"); + return FALSE; + } + + if (ptrLBA >= pd->m_Extended[i].m_PhysicalLBA && + ptrLBA < pd->m_Extended[i].m_PhysicalLBA + pd->m_Extended[i].m_Size) { + DWORD readOffset = ptrLBA - pd->m_Extended[i].m_PhysicalLBA; + + if (pd->m_Extended[i].m_ReadFunc == NULL) { + log_error("disk", "Attempted read in %d/%d at block offset %08x; No read function", + pd->m_DriveNumber, pd->m_Extended[i].m_PartitionNumber, readOffset); + return FALSE; + } + BOOL ret = pd->m_Extended[i].m_ReadFunc(readOffset, lpBuffer, nNumberOfBytesToRead, + lpNumberOfBytesRead); + if (!ret) { + log_error("disk", "Attempted read in %d/%d at block offset %08x; Read rejected", + pd->m_DriveNumber, pd->m_Extended[i].m_PartitionNumber, readOffset); + return FALSE; + } + + log_misc("drive", "Read at %d/%d+%d", pd->m_DriveNumber, + pd->m_Extended[i].m_PartitionNumber, readOffset); + return TRUE; + } + } + + log_error("drive", "Read failed"); + return FALSE; +} + +BOOL pd_WriteFile(file_context_t* ctx, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { + *lpNumberOfBytesWritten = 0; + + physical_disk_t* pd = (physical_disk_t*)ctx->m_HookData; + if (pd == NULL) { + log_error("drive", "write:ctx->m_HookData NULL; expected a physical drive!"); + return FALSE; + } + + log_misc("drive", "PhysicalDrive%d: Write %d @ %llx", pd->m_DriveNumber, nNumberOfBytesToWrite, + ctx->m_Pointer.QuadPart); + + // for (DWORD i = 0; i < nNumberOfBytesToWrite; i += 32) { + // for (int j = 0; j < 32; j++) { + // printf("%02x ", ((BYTE*)lpBuffer)[i + j]); + // } + // puts(""); + // } + + // *lpNumberOfBytesWritten = nNumberOfBytesToWrite; + // return TRUE; + + // ! WARNING: This WriteFile implementation is currently limited to aligned + // ! reads. Given the main purpose of this function is to allow reading + // ! the partition information, this doesn't currently pose an issue. + + DWORD ptrLBA = (ctx->m_Pointer.QuadPart / (long long)pd->m_BlockSize) & 0xffffffff; + + // Writes to the MBR header or slack are blocked + if (ptrLBA <= MBR_LBA_GAP) { + log_error("drive", "Write rejected"); + return FALSE; + } + + // MBR partitions + for (size_t i = 0; i < 4; i++) { + if (pd->m_Partitions[i].m_PartitionNumber == 0) break; + + if (ptrLBA >= pd->m_Partitions[i].m_PhysicalLBA && + ptrLBA < pd->m_Partitions[i].m_PhysicalLBA + pd->m_Partitions[i].m_Size) { + DWORD writeOffset = ptrLBA - pd->m_Partitions[i].m_PhysicalLBA; + + if (pd->m_Partitions[i].m_WriteFunc == NULL) { + log_error("disk", + "Attempted write in %d/%d at block offset %08x; No write function", + pd->m_DriveNumber, pd->m_Partitions[i].m_PartitionNumber, writeOffset); + return FALSE; + } + BOOL ret = pd->m_Partitions[i].m_WriteFunc(writeOffset, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten); + if (!ret) { + log_error("disk", "Attempted write in %d/%d at block offset %08x; Write rejected", + pd->m_DriveNumber, pd->m_Partitions[i].m_PartitionNumber, writeOffset); + return FALSE; + } + + log_misc("drive", "Write at %d/%d+%d", pd->m_DriveNumber, + pd->m_Partitions[i].m_PartitionNumber, writeOffset); + return TRUE; + } + } + + // Extended partitions + for (size_t i = 0; pd->m_Extended[i].m_Size; i++) { + // Extended header + DWORD headerLBA = pd->m_Extended[i].m_PhysicalLBA - EXT_HEADER_GAP; + if (ptrLBA == headerLBA) { + log_error("drive", "Write to extended header rejected"); + return FALSE; + } + + if (i == 0 && pd->m_HasSegaboot) { + // SEGA Partition Description + if (ptrLBA == headerLBA + SPD_OFFSET) { + if (nNumberOfBytesToWrite < sizeof(spd_t)) { + log_error("drive", "Buffer too small for SPD!"); + return FALSE; + } + HANDLE hFile = _CreateFileA(SPD_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("drive", "Failed to open %s", SPD_PATH); + return FALSE; + } + BOOL ret = _WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten, lpOverlapped); + _CloseHandle(hFile); + return ret; + } + // SEGA Boot Records + if (ptrLBA == headerLBA + SBR0_OFFSET) { + if (nNumberOfBytesToWrite < sizeof(sbr_t)) { + log_error("drive", "Buffer too small for SBR!"); + return FALSE; + } + HANDLE hFile = _CreateFileA(SBR0_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("drive", "Failed to open %s", SBR0_PATH); + return FALSE; + } + BOOL ret = _WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten, lpOverlapped); + _CloseHandle(hFile); + return ret; + } + if (ptrLBA == headerLBA + SBR1_OFFSET) { + if (nNumberOfBytesToWrite < sizeof(sbr_t)) { + log_error("drive", "Buffer too small for SBR!"); + return FALSE; + } + HANDLE hFile = _CreateFileA(SBR1_PATH, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, + OPEN_ALWAYS, 0, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + log_error("drive", "Failed to open %s", SBR1_PATH); + return FALSE; + } + BOOL ret = _WriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten, lpOverlapped); + _CloseHandle(hFile); + return ret; + } + } + + if (ptrLBA >= pd->m_Extended[i].m_PhysicalLBA - EXT_HEADER_GAP && + ptrLBA < pd->m_Extended[i].m_PhysicalLBA) { + // Write within the 63 extra tracks + log_error("drive", "Write failed"); + return FALSE; + } + + if (ptrLBA >= pd->m_Extended[i].m_PhysicalLBA && + ptrLBA < pd->m_Extended[i].m_PhysicalLBA + pd->m_Extended[i].m_Size) { + DWORD writeOffset = ptrLBA - pd->m_Extended[i].m_PhysicalLBA; + + if (pd->m_Extended[i].m_WriteFunc == NULL) { + log_error("disk", + "Attempted write in %d/%d at block offset %08x; No write function", + pd->m_DriveNumber, pd->m_Extended[i].m_PartitionNumber, writeOffset); + return FALSE; + } + BOOL ret = pd->m_Extended[i].m_WriteFunc(writeOffset, lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten); + if (!ret) { + log_error("disk", "Attempted write in %d/%d at block offset %08x; Write rejected", + pd->m_DriveNumber, pd->m_Extended[i].m_PartitionNumber, writeOffset); + return FALSE; + } + + log_misc("drive", "Write at %d/%d+%d", pd->m_DriveNumber, + pd->m_Extended[i].m_PartitionNumber, writeOffset); + return TRUE; + } + } +} diff --git a/src/micetools/dll/hooks/drive.h b/src/micetools/dll/hooks/drive/segastruct.h similarity index 76% rename from src/micetools/dll/hooks/drive.h rename to src/micetools/dll/hooks/drive/segastruct.h index fa0144a..b3734a9 100644 --- a/src/micetools/dll/hooks/drive.h +++ b/src/micetools/dll/hooks/drive/segastruct.h @@ -1,125 +1,104 @@ -#pragma once -#include "../common.h" - -void hook_drives(); - -// MBR -#define MBR_FLAG_NONE 0x00 -#define MBR_FLAG_BOOTABLE 0x80 - -#define MBR_FS_NONE 0x00 -#define MBR_FS_EXT_CHS 0x05 -#define MBR_FS_FAT16 0x06 -#define MBR_FS_NTFS 0x07 -#define MBR_FS_EXT_LBA 0x0F - -#pragma pack(push, 1) -typedef struct mbr { - BYTE bootstrap_code[446]; - struct { - BYTE status; - BYTE start_chs[3]; - BYTE type; - BYTE end_chs[3]; - DWORD lba; - DWORD sectors; - } partitions[4]; - BYTE sig[2]; -} mbr_t; - -// SEGA -#define SPD_VERSION 1 -#define SBR_VERSION 1 - -// Sega Partition Descriptor -enum spd_slot { - SPD_Original0 = 0x10, - SPD_Original1 = 0x11, - SPD_Patch0 = 0x20, - SPD_Patch1 = 0x21, - SPD_OS = 0x30, - SPD_AppData = 0x40, -}; -typedef uint8_t spd_slot_t; - -typedef struct spd { - uint32_t crc; - uint8_t version; - uint8_t _[11]; - struct { - /* - (BCD) - 1.0 = original0 - 1.1 = original1 - 2.0 = patch0 - 2.1 = patch1 - 3.0 = os - 4.0 = app_data - */ - spd_slot_t slot_content; - /* - Guess: Filesystem type - 0: Encrypted FAT16 - 1: Decrypted NTFS - */ - uint8_t uk1; - uint16_t block_size; - uint32_t block_count; - uint8_t __[8]; - } slots[31]; -} spd_t; - -// Sega Boot Record -typedef struct { - uint16_t year; - uint8_t mon; - uint8_t day; - uint8_t hour; - uint8_t min; - uint8_t sec; - uint8_t _; -} slot_time_t; - -typedef struct { - char id[4]; - slot_time_t time; - uint32_t version; - uint32_t _[2]; - uint32_t segcount; - uint32_t segsize; - - char hw[3]; - uint8_t instant; - slot_time_t orgtime; - uint32_t orgversion; - uint32_t osver; - uint32_t ossegcount; - - uint8_t __[8]; -} sbr_slot_t; - -enum { - Slot_Check = 0x00, // status=error - Slot_Install = 0x01, // status=install -> FAILED TO READ PREMADE BLOCK!! - Slot_Complete = 0x02, // status=complete - Slot_Empty = 0x03, // status=error - Slot_Error = 0x04, // status=error - Slot_Invalid = 0xff, -}; - -typedef uint8_t slot_status_t; -typedef struct { - uint32_t crc; - uint8_t version; - uint8_t _[11 + 16 + 32]; - uint8_t bootslot; - uint8_t __[2]; - slot_status_t slot_status[5]; - uint8_t ___[8 + 16 + 32 + 64]; - sbr_slot_t slot_os; - sbr_slot_t slot_original0; - sbr_slot_t slot_appdata; - sbr_slot_t slot_patch0; - sbr_slot_t slot_patch1; -} sbr_t; -#pragma pack(pop) +#pragma once +#include + +#define SPD_VERSION 1 +#define SBR_VERSION 1 + +// Block count offsets from the extended partition header +#define SPD_OFFSET 1 +#define SBR0_OFFSET 2 +#define SBR1_OFFSET 3 + +// Sega Partition Descriptor +#pragma pack(push, 1) +enum spd_slot { + SPD_Original0 = 0x10, + SPD_Original1 = 0x11, + SPD_Patch0 = 0x20, + SPD_Patch1 = 0x21, + SPD_OS = 0x30, + SPD_AppData = 0x40, +}; +typedef uint8_t spd_slot_t; + +typedef struct spd { + uint32_t crc; + uint8_t version; + uint8_t _[11]; + struct { + /* + (BCD) + 1.0 = original0 + 1.1 = original1 + 2.0 = patch0 + 2.1 = patch1 + 3.0 = os + 4.0 = app_data + */ + spd_slot_t slot_content; + /* + Guess: Filesystem type + 0: Encrypted FAT16 + 1: Decrypted NTFS + */ + uint8_t uk1; + uint16_t block_size; + uint32_t block_count; + uint8_t __[8]; + } slots[31]; +} spd_t; + +// Sega Boot Record +typedef struct { + uint16_t year; + uint8_t mon; + uint8_t day; + uint8_t hour; + uint8_t min; + uint8_t sec; + uint8_t _; +} slot_time_t; + +typedef struct { + char id[4]; + slot_time_t time; + uint32_t version; + uint32_t _[2]; + uint32_t segcount; + uint32_t segsize; + + char hw[3]; + uint8_t instant; + slot_time_t orgtime; + uint32_t orgversion; + uint32_t osver; + uint32_t ossegcount; + + uint8_t __[8]; +} sbr_slot_t; + +enum { + Slot_Check = 0x00, // status=error + Slot_Install = 0x01, // status=install -> FAILED TO READ PREMADE BLOCK!! + Slot_Complete = 0x02, // status=complete + Slot_Empty = 0x03, // status=error + Slot_Error = 0x04, // status=error + Slot_Invalid = 0xff, +}; + +typedef uint8_t slot_status_t; +typedef struct { + uint32_t crc; + uint8_t version; + uint8_t _[11 + 16 + 32]; + uint8_t bootslot; + uint8_t __[2]; + slot_status_t slot_status[5]; + uint8_t ___[8 + 16 + 32 + 64]; + sbr_slot_t slot_os; + sbr_slot_t slot_original0; + sbr_slot_t slot_appdata; + sbr_slot_t slot_patch0; + sbr_slot_t slot_patch1; +} sbr_t; +#pragma pack(pop) diff --git a/src/micetools/dll/hooks/drivers/framework.c b/src/micetools/dll/hooks/drivers/framework.c new file mode 100644 index 0000000..6778187 --- /dev/null +++ b/src/micetools/dll/hooks/drivers/framework.c @@ -0,0 +1,133 @@ +#include "framework.h" + +#include + +typedef struct _LIST { + UINT Num; + UINT MaxNum; + PVOID *Entries; +} LIST, *PLIST; + +typedef struct { + PDRIVER_OBJECT DriverObject; + ULONG DeviceExtensionSize; + PUNICODE_STRING DeviceName; + ULONG DeviceType; + ULONG DeviceCharacteristics; + BOOLEAN Exclusive; + PDEVICE_OBJECT *DeviceObject; +} DRIVER, *PDRIVER; +static LIST DriversList; + +typedef struct { + UNICODE_STRING SymbolicLinkName; + UNICODE_STRING DeviceName; +} SYMBOLIC_LINK, *PSYMBOLIC_LINK; +static LIST SymbolicLinkList; + +PVOID MT_ListAppend(PLIST List, UINT Size) { + if (List->Num == List->MaxNum) { + UINT newMaxNum = (List->MaxNum + 1) * 2; + + PVOID newEntries = malloc(newMaxNum * sizeof List->Entries[0]); + memcpy(newEntries, List->Entries, List->Num * sizeof List->Entries[0]); + List->Entries = newEntries; + List->MaxNum = newMaxNum; + } + PVOID entry = malloc(Size); + return (List->Entries[List->Num++] = entry); +} +VOID MT_ListRemove(PLIST List, UINT Index) { + if (Index >= List->Num || List->Num == 0) return; + + free(List->Entries[Index]); + for (UINT i = Index; i < List->Num - 1; i++) { + List->Entries[i] = List->Entries[i + 1]; + } + List->Num--; +} + +NTSTATUS MT_IoCreateDevice(PDRIVER_OBJECT DriverObject, ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, ULONG DeviceType, + ULONG DeviceCharacteristics, BOOLEAN Exclusive, + PDEVICE_OBJECT *DeviceObject) { + PDRIVER Driver = MT_ListAppend(&DriversList, sizeof *Driver); + + Driver->DriverObject = DriverObject; + Driver->DeviceExtensionSize = DeviceExtensionSize; + Driver->DeviceName = DeviceName; + Driver->DeviceType = DeviceType; + Driver->DeviceCharacteristics = DeviceCharacteristics; + Driver->Exclusive = Exclusive; + Driver->DeviceObject = DeviceObject; + + return STATUS_SUCCESS; +} +NTSTATUS MT_RtlInitUnicodeStringEx(PUNICODE_STRING DestinationString, PCWSTR SourceString) { + if (SourceString) { + USHORT length = wcslen(SourceString) & 0xffff; + DestinationString->Length = length; + DestinationString->MaximumLength = length + 1; + DestinationString->Buffer = malloc(length + 1); + memcpy(DestinationString->Buffer, SourceString, length); + DestinationString->Buffer[length] = L'\0'; + return STATUS_SUCCESS; + } + DestinationString->Buffer = NULL; + DestinationString->Length = 0; + DestinationString->MaximumLength = 0; + return STATUS_SUCCESS; +} +void MT_RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString) { + MT_RtlInitUnicodeStringEx(DestinationString, SourceString); +} +void MT_RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString) { + if (DestinationString->Buffer) { + if (DestinationString->MaximumLength < SourceString->Length + 1) { + realloc(DestinationString->Buffer, SourceString->MaximumLength); + DestinationString->MaximumLength = SourceString->MaximumLength; + } + } else { + DestinationString->Buffer = malloc(SourceString->MaximumLength); + DestinationString->MaximumLength = SourceString->MaximumLength; + } + DestinationString->Length = SourceString->Length; + memcpy(DestinationString->Buffer, SourceString->Buffer, SourceString->Length + 1); +} + +LONG RtlCompareUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, + BOOLEAN CaseInSensitive) { + if (CaseInSensitive) return _wcsicmp(String1->Buffer, String2->Buffer); + return wcscmp(String1->Buffer, String2->Buffer); +} + +PIO_STACK_LOCATION MT_IoGetCurrentIrpStackLocation(PIRP Irp) { + return Irp->Tail.Overlay.CurrentStackLocation; +} +NTSTATUS MT_IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, PUNICODE_STRING DeviceName) { + PSYMBOLIC_LINK SymbolicLink = MT_ListAppend(&SymbolicLinkList, sizeof *SymbolicLink); + MT_RtlCopyUnicodeString(&SymbolicLink->DeviceName, DeviceName); + MT_RtlCopyUnicodeString(&SymbolicLink->SymbolicLinkName, SymbolicLinkName); + return STATUS_SUCCESS; +} +NTSTATUS MT_IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName) { + for (UINT i = 0; i < SymbolicLinkList.Num; i++) { + if (RtlCompareUnicodeString( + SymbolicLinkName, &((PSYMBOLIC_LINK)SymbolicLinkList.Entries[i])->SymbolicLinkName, + TRUE) == 0) { + MT_ListRemove(&SymbolicLinkList, i--); + } + } + return STATUS_SUCCESS; +} +NTSTATUS MT_IoDeleteDevice(PDEVICE_OBJECT DeviceObject) { + for (UINT i = 0; i < DriversList.Num; i++) { + if (*((PDRIVER)DriversList.Entries[i])->DeviceObject == DeviceObject) { + MT_ListRemove(&DriversList, i--); + } + } + return STATUS_SUCCESS; +} +void MT_IofCompleteRequest(PIRP Irp, CCHAR PriorityBoost) { + // TODO: This +} diff --git a/src/micetools/dll/hooks/drivers/framework.h b/src/micetools/dll/hooks/drivers/framework.h new file mode 100644 index 0000000..73e2fac --- /dev/null +++ b/src/micetools/dll/hooks/drivers/framework.h @@ -0,0 +1,483 @@ +#include + +typedef short CSHORT; +typedef struct { + USHORT Length; + USHORT MaximumLength; + PWCH Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +#ifdef NTSTATUS +#undef NTSTATUS +#endif +#define NTSTATUS LONG + +#define EVENT_INCREMENT 1 +#define EVENT_PAIR_INCREMENT 1 +#define LPC_RELEASE_WAIT_INCREMENT 1 +#define IO_NO_INCREMENT 0 +#define IO_CD_ROM_INCREMENT 1 +#define IO_DISK_INCREMENT 1 +#define IO_KEYBOARD_INCREMENT 6 +#define IO_MAILSLOT_INCREMENT 2 +#define IO_MOUSE_INCREMENT 6 +#define IO_NAMED_PIPE_INCREMENT 2 +#define IO_NETWORK_INCREMENT 2 +#define IO_PARALLEL_INCREMENT 1 +#define IO_SERIAL_INCREMENT 2 +#define IO_SOUND_INCREMENT 8 +#define IO_VIDEO_INCREMENT 1 +#define MUTANT_INCREMENT 1 +#define SEMAPHORE_INCREMENT 1 +#define TIMER_APC_INCREMENT 0 +#define ERESOURCE_INCREMENT 4 + +// https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55 +#define STATUS_SUCCESS 0 +#define STATUS_INVALID_DEVICE_REQUEST 0xC0000010 +#define STATUS_NOT_SUPPORTED 0xC00000BB + +#define IRP_MJ_CREATE 0 +#define IRP_MJ_CREATE_NAMED_PIPE 1 +#define IRP_MJ_CLOSE 2 +#define IRP_MJ_READ 3 +#define IRP_MJ_WRITE 4 +#define IRP_MJ_QUERY_INFORMATION 5 +#define IRP_MJ_SET_INFORMATION 6 +#define IRP_MJ_QUERY_EA 7 +#define IRP_MJ_SET_EA 8 +#define IRP_MJ_FLUSH_BUFFERS 9 +#define IRP_MJ_QUERY_VOLUME_INFORMATION 10 +#define IRP_MJ_SET_VOLUME_INFORMATION 11 +#define IRP_MJ_DIRECTORY_CONTROL 12 +#define IRP_MJ_FILE_SYSTEM_CONTROL 13 +#define IRP_MJ_DEVICE_CONTROL 14 +#define IRP_MJ_INTERNAL_DEVICE_CONTROL 15 +#define IRP_MJ_SHUTDOWN 16 +#define IRP_MJ_LOCK_CONTROL 17 +#define IRP_MJ_CLEANUP 18 +#define IRP_MJ_CREATE_MAILSLOT 19 +#define IRP_MJ_QUERY_SECURITY 20 +#define IRP_MJ_SET_SECURITY 21 +#define IRP_MJ_POWER 22 +#define IRP_MJ_SYSTEM_CONTROL 23 +#define IRP_MJ_DEVICE_CHANGE 24 +#define IRP_MJ_QUERY_QUOTA 25 +#define IRP_MJ_SET_QUOTA 26 +#define IRP_MJ_PNP 27 +#define IRP_MJ_MAXIMUM_FUNCTION 27 + +typedef struct _DEVICE_OBJECT DEVICE_OBJECT, *PDEVICE_OBJECT; +typedef struct _DRIVER_OBJECT DRIVER_OBJECT, *PDRIVER_OBJECT; +typedef struct _IRP IRP, *PIRP; +typedef struct _IO_STACK_LOCATION IO_STACK_LOCATION, *PIO_STACK_LOCATION; +typedef struct _FILE_OBJECT FILE_OBJECT, *PFILE_OBJECT; +typedef struct _IO_STATUS_BLOCK IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; +typedef struct _KDEVICE_QUEUE_ENTRY KDEVICE_QUEUE_ENTRY, *PKDEVICE_QUEUE_ENTRY; + +typedef NTSTATUS(__stdcall *PDRIVER_DISPATCH)(PDEVICE_OBJECT DeviceObject, PIRP Irp); +typedef void(__stdcall *PDRIVER_UNLOAD)(PDRIVER_OBJECT DriverObject); +typedef NTSTATUS(__stdcall *PDRIVER_ADD_DEVICE)(PDRIVER_OBJECT DriverObject, + PDEVICE_OBJECT PhysicalDeviceObject); + +struct _KDEVICE_QUEUE_ENTRY { + LIST_ENTRY DeviceListEntry; + ULONG SortKey; + UCHAR Inserted; +}; + +typedef PVOID PETHREAD; // TODO: This + +struct _FILE_OBJECT { + SHORT Type; + SHORT Size; + PDEVICE_OBJECT DeviceObject; + // PVPB Vpb; + PVOID FsContext; + PVOID FsContext2; + // PSECTION_OBJECT_POINTERS SectionObjectPointer; + PVOID PrivateCacheMap; + LONG FinalStatus; + PFILE_OBJECT RelatedFileObject; + UCHAR LockOperation; + UCHAR DeletePending; + UCHAR ReadAccess; + UCHAR WriteAccess; + UCHAR DeleteAccess; + UCHAR SharedRead; + UCHAR SharedWrite; + UCHAR SharedDelete; + ULONG Flags; + UNICODE_STRING FileName; + LARGE_INTEGER CurrentByteOffset; + ULONG Waiters; + ULONG Busy; + PVOID LastLock; + // KEVENT Lock; + // KEVENT Event; + // PIO_COMPLETION_CONTEXT CompletionContext; + ULONG IrpListLock; + LIST_ENTRY IrpList; + PVOID FileObjectExtension; +}; + +struct _DEVICE_OBJECT { + CSHORT Type; + USHORT Size; + LONG ReferenceCount; + struct _DRIVER_OBJECT *DriverObject; + struct _DEVICE_OBJECT *NextDevice; + struct _DEVICE_OBJECT *AttachedDevice; + struct _IRP *CurrentIrp; + // PIO_TIMER Timer; + ULONG Flags; + ULONG Characteristics; + // __volatile PVPB Vpb; + PVOID DeviceExtension; + // DEVICE_TYPE DeviceType; + CCHAR StackSize; + // union { + // LIST_ENTRY ListEntry; + // WAIT_CONTEXT_BLOCK Wcb; + // } Queue; + ULONG AlignmentRequirement; + // KDEVICE_QUEUE DeviceQueue; + // KDPC Dpc; + ULONG ActiveThreadCount; + PSECURITY_DESCRIPTOR SecurityDescriptor; + // KEVENT DeviceLock; + USHORT SectorSize; + USHORT Spare1; + struct _DEVOBJ_EXTENSION *DeviceObjectExtension; + PVOID Reserved; +}; + +struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + }; + ULONG_PTR Information; +}; + +struct _IO_STACK_LOCATION { + UCHAR MajorFunction; + UCHAR MinorFunction; + UCHAR Flags; + UCHAR Control; + union { + // struct { + // PIO_SECURITY_CONTEXT SecurityContext; + // ULONG Options; + // USHORT FileAttributes; + // USHORT ShareAccess; + // ULONG EaLength; + // } Create; + // struct { + // PIO_SECURITY_CONTEXT SecurityContext; + // ULONG Options; + // USHORT Reserved; + // USHORT ShareAccess; + // PNAMED_PIPE_CREATE_PARAMETERS Parameters; + // } CreatePipe; + // struct { + // PIO_SECURITY_CONTEXT SecurityContext; + // ULONG Options; + // USHORT Reserved; + // USHORT ShareAccess; + // PMAILSLOT_CREATE_PARAMETERS Parameters; + // } CreateMailslot; + // struct { + // ULONG Length; + // ULONG Key; + // ULONG Flags; + // LARGE_INTEGER ByteOffset; + // } Read; + // struct { + // ULONG Length; + // ULONG Key; + // ULONG Flags; + // LARGE_INTEGER ByteOffset; + // } Write; + // struct { + // ULONG Length; + // PUNICODE_STRING FileName; + // FILE_INFORMATION_CLASS FileInformationClass; + // ULONG FileIndex; + // } QueryDirectory; + // struct { + // ULONG Length; + // ULONG CompletionFilter; + // } NotifyDirectory; + // struct { + // ULONG Length; + // ULONG CompletionFilter; + // DIRECTORY_NOTIFY_INFORMATION_CLASS DirectoryNotifyInformationClass; + // } NotifyDirectoryEx; + // struct { + // ULONG Length; + // FILE_INFORMATION_CLASS FileInformationClass; + // } QueryFile; + // struct { + // ULONG Length; + // FILE_INFORMATION_CLASS FileInformationClass; + // PFILE_OBJECT FileObject; + // union { + // struct { + // BOOLEAN ReplaceIfExists; + // BOOLEAN AdvanceOnly; + // }; + // ULONG ClusterCount; + // HANDLE DeleteHandle; + // }; + // } SetFile; + // struct { + // ULONG Length; + // PVOID EaList; + // ULONG EaListLength; + // ULONG EaIndex; + // } QueryEa; + // struct { + // ULONG Length; + // } SetEa; + // struct { + // ULONG Length; + // FS_INFORMATION_CLASS FsInformationClass; + // } QueryVolume; + // struct { + // ULONG Length; + // FS_INFORMATION_CLASS FsInformationClass; + // } SetVolume; + // struct { + // ULONG OutputBufferLength; + // ULONG InputBufferLength; + // ULONG FsControlCode; + // PVOID Type3InputBuffer; + // } FileSystemControl; + // struct { + // PLARGE_INTEGER Length; + // ULONG Key; + // LARGE_INTEGER ByteOffset; + // } LockControl; + struct { + ULONG OutputBufferLength; + ULONG InputBufferLength; + ULONG IoControlCode; + PVOID Type3InputBuffer; + } DeviceIoControl; + // struct { + // SECURITY_INFORMATION SecurityInformation; + // ULONG Length; + // } QuerySecurity; + // struct { + // SECURITY_INFORMATION SecurityInformation; + // PSECURITY_DESCRIPTOR SecurityDescriptor; + // } SetSecurity; + // struct { + // PVPB Vpb; + // PDEVICE_OBJECT DeviceObject; + // } MountVolume; + // struct { + // PVPB Vpb; + // PDEVICE_OBJECT DeviceObject; + // } VerifyVolume; + // struct { + // struct _SCSI_REQUEST_BLOCK *Srb; + // } Scsi; + // struct { + // ULONG Length; + // PSID StartSid; + // PFILE_GET_QUOTA_INFORMATION SidList; + // ULONG SidListLength; + // } QueryQuota; + // struct { + // ULONG Length; + // } SetQuota; + // struct { + // DEVICE_RELATION_TYPE Type; + // } QueryDeviceRelations; + // struct { + // const GUID *InterfaceType; + // USHORT Size; + // USHORT Version; + // PINTERFACE Interface; + // PVOID InterfaceSpecificData; + // } QueryInterface; + // struct { + // PDEVICE_CAPABILITIES Capabilities; + // } DeviceCapabilities; + // struct { + // PIO_RESOURCE_REQUIREMENTS_LIST IoResourceRequirementList; + // } FilterResourceRequirements; + // struct { + // ULONG WhichSpace; + // PVOID Buffer; + // ULONG Offset; + // ULONG Length; + // } ReadWriteConfig; + // struct { + // BOOLEAN Lock; + // } SetLock; + // struct { + // BUS_QUERY_ID_TYPE IdType; + // } QueryId; + // struct { + // DEVICE_TEXT_TYPE DeviceTextType; + // LCID LocaleId; + // } QueryDeviceText; + // struct { + // BOOLEAN InPath; + // BOOLEAN Reserved[3]; + // DEVICE_USAGE_NOTIFICATION_TYPE Type; + // } UsageNotification; + // struct { + // SYSTEM_POWER_STATE PowerState; + // } WaitWake; + // struct { + // PPOWER_SEQUENCE PowerSequence; + // } PowerSequence; + // #if... + // struct { + // union { + // ULONG SystemContext; + // SYSTEM_POWER_STATE_CONTEXT SystemPowerStateContext; + // }; + // POWER_STATE_TYPE Type; + // POWER_STATE State; + // POWER_ACTION ShutdownType; + // } Power; + // #else + // struct { + // ULONG SystemContext; + // POWER_STATE_TYPE Type; + // POWER_STATE State; + // POWER_ACTION ShutdownType; + // } Power; + // #endif + // struct { + // PCM_RESOURCE_LIST AllocatedResources; + // PCM_RESOURCE_LIST AllocatedResourcesTranslated; + // } StartDevice; + // struct { + // ULONG_PTR ProviderId; + // PVOID DataPath; + // ULONG BufferSize; + // PVOID Buffer; + // } WMI; + // struct { + // PVOID Argument1; + // PVOID Argument2; + // PVOID Argument3; + // PVOID Argument4; + // } Others; + } Parameters; + PDEVICE_OBJECT DeviceObject; + // PFILE_OBJECT FileObject; + // PIO_COMPLETION_ROUTINE CompletionRoutine; + PVOID Context; +}; + +struct _IRP { + // CSHORT Type; + // USHORT Size; + // PMDL MdlAddress; + // ULONG Flags; + // union { + // struct _IRP *MasterIrp; + // __volatile LONG IrpCount; + // PVOID SystemBuffer; + // } AssociatedIrp; + // LIST_ENTRY ThreadListEntry; + IO_STATUS_BLOCK IoStatus; + // KPROCESSOR_MODE RequestorMode; + // BOOLEAN PendingReturned; + // CHAR StackCount; + // CHAR CurrentLocation; + // BOOLEAN Cancel; + // KIRQL CancelIrql; + // CCHAR ApcEnvironment; + // UCHAR AllocationFlags; + // union { + // PIO_STATUS_BLOCK UserIosb; + // PVOID IoRingContext; + // }; + // PKEVENT UserEvent; + // union { + // struct { + // union { + // PIO_APC_ROUTINE UserApcRoutine; + // PVOID IssuingProcess; + // }; + // union { + // PVOID UserApcContext; + // // #if... + // // _IORING_OBJECT *IoRing; + // // #else + // struct _IORING_OBJECT *IoRing; + // // #endif + // }; + // } AsynchronousParameters; + // LARGE_INTEGER AllocationSize; + // } Overlay; + // __volatile PDRIVER_CANCEL CancelRoutine; + PVOID UserBuffer; + union { + struct { + union { + KDEVICE_QUEUE_ENTRY DeviceQueueEntry; + struct { + PVOID DriverContext[4]; + }; + }; + PETHREAD Thread; + PCHAR AuxiliaryBuffer; + struct { + LIST_ENTRY ListEntry; + union { + struct _IO_STACK_LOCATION *CurrentStackLocation; + ULONG PacketType; + }; + }; + PFILE_OBJECT OriginalFileObject; + } Overlay; + // KAPC Apc; + PVOID CompletionKey; + } Tail; +}; + +struct _DRIVER_OBJECT { + CSHORT Type; + CSHORT Size; + PDEVICE_OBJECT DeviceObject; + // ULONG Flags; + // PVOID DriverStart; + // ULONG DriverSize; + // PVOID DriverSection; + // PDRIVER_EXTENSION DriverExtension; + // UNICODE_STRING DriverName; + // PUNICODE_STRING HardwareDatabase; + // PFAST_IO_DISPATCH FastIoDispatch; + // PDRIVER_INITIALIZE DriverInit; + // PDRIVER_STARTIO DriverStartIo; + PDRIVER_UNLOAD DriverUnload; + PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION + 1]; +}; + +NTSTATUS MT_IoCreateDevice(PDRIVER_OBJECT DriverObject, ULONG DeviceExtensionSize, + PUNICODE_STRING DeviceName, ULONG DeviceType, + ULONG DeviceCharacteristics, BOOLEAN Exclusive, + PDEVICE_OBJECT *DeviceObject); +NTSTATUS MT_IoDeleteDevice(PDEVICE_OBJECT DeviceObject); + +NTSTATUS MT_RtlInitUnicodeStringEx(PUNICODE_STRING DestinationString, PCWSTR SourceString); +void MT_RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString); +void MT_RtlCopyUnicodeString(PUNICODE_STRING DestinationString, PUNICODE_STRING SourceString); +LONG RtlCompareUnicodeString(PUNICODE_STRING String1, PUNICODE_STRING String2, + BOOLEAN CaseInSensitive); + +NTSTATUS MT_IoCreateSymbolicLink(PUNICODE_STRING SymbolicLinkName, PUNICODE_STRING DeviceName); +NTSTATUS MT_IoDeleteSymbolicLink(PUNICODE_STRING SymbolicLinkName); + +void MT_IofCompleteRequest(PIRP Irp, CCHAR PriorityBoost); + +PIO_STACK_LOCATION MT_IoGetCurrentIrpStackLocation(PIRP Irp); diff --git a/src/micetools/dll/hooks/drivers/mxhwreset.c b/src/micetools/dll/hooks/drivers/mxhwreset.c new file mode 100644 index 0000000..edc5047 --- /dev/null +++ b/src/micetools/dll/hooks/drivers/mxhwreset.c @@ -0,0 +1,59 @@ +#include "../../../lib/mice/ioctl.h" +#include "framework.h" + +#define NTDEVICE_NAME_STRING L"\\Device\\mxhwreset" +#define SYMBOLIC_NAME_STRING L"\\DosDevices\\mxhwreset" + +static NTSTATUS IrpComplete(PIRP Irp, NTSTATUS Status, PVOID Information) { + (Irp->IoStatus).Status = Status; + (Irp->IoStatus).Information = (ULONG_PTR)Information; + MT_IofCompleteRequest(Irp, IO_NO_INCREMENT); + return Status; +} + +static NTSTATUS __stdcall EventNotSupported(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + return IrpComplete(Irp, STATUS_NOT_SUPPORTED, NULL); +} +static NTSTATUS __stdcall EventCreateClose(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + return IrpComplete(Irp, STATUS_SUCCESS, NULL); +} +static NTSTATUS __stdcall EventDispatchIoControl(PDEVICE_OBJECT DeviceObject, PIRP Irp) { + IrpComplete(Irp, STATUS_NOT_SUPPORTED, NULL); + + PIO_STACK_LOCATION irpStack = MT_IoGetCurrentIrpStackLocation(Irp); + if (irpStack->Parameters.DeviceIoControl.IoControlCode != IOCTL_MXHWRESET_RESET) { + return IrpComplete(Irp, STATUS_INVALID_DEVICE_REQUEST, NULL); + } + + return IrpComplete(Irp, STATUS_SUCCESS, NULL); +} + +static void __stdcall EventUnload(PDRIVER_OBJECT DriverObject) { + UNICODE_STRING dosDevice; + MT_RtlInitUnicodeString(&dosDevice, SYMBOLIC_NAME_STRING); + MT_IoDeleteSymbolicLink(&dosDevice); + MT_IoDeleteDevice(DriverObject->DeviceObject); +} + +NTSTATUS entry_mxHwReset(PDRIVER_OBJECT driver) { + UNICODE_STRING deviceName; + UNICODE_STRING dosDeviceName; + + PDEVICE_OBJECT device = NULL; + + MT_RtlInitUnicodeString(&deviceName, NTDEVICE_NAME_STRING); + MT_RtlInitUnicodeString(&dosDeviceName, SYMBOLIC_NAME_STRING); + NTSTATUS ret = MT_IoCreateDevice(driver, 0, &deviceName, 34, 0, '\0', &device); + if (ret != STATUS_SUCCESS) return ret; + + for (int i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++) { + driver->MajorFunction[i] = &EventNotSupported; + } + driver->MajorFunction[IRP_MJ_CREATE] = EventCreateClose; + driver->MajorFunction[IRP_MJ_CLOSE] = EventCreateClose; + driver->MajorFunction[IRP_MJ_DEVICE_CONTROL] = EventDispatchIoControl; + driver->DriverUnload = EventUnload; + + MT_IoCreateSymbolicLink(&dosDeviceName, &deviceName); + return STATUS_SUCCESS; +} diff --git a/src/micetools/dll/hooks/files.c b/src/micetools/dll/hooks/files.c index 4b1a034..30c352d 100644 --- a/src/micetools/dll/hooks/files.c +++ b/src/micetools/dll/hooks/files.c @@ -37,9 +37,69 @@ void hook_file(file_hook_t* hook) { hl->next = hook; }; +struct buffer_file { + LPBYTE buffer; + DWORD nBytes; + DWORD access; +}; +BOOL bf_ReadFile(file_context_t* ctx, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { + struct buffer_file* pBF = (struct buffer_file*)ctx->m_HookData; + if (!(pBF->access & GENERIC_READ)) { + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + + if (ctx->m_Pointer.QuadPart > pBF->nBytes) { + *lpNumberOfBytesRead = 0; + return TRUE; + } + if (ctx->m_Pointer.QuadPart + nNumberOfBytesToRead > pBF->nBytes) { + nNumberOfBytesToRead = (pBF->nBytes - ctx->m_Pointer.QuadPart) & 0xffffffff; + } + *lpNumberOfBytesRead = nNumberOfBytesToRead; + memcpy(lpBuffer, pBF->buffer + ctx->m_Pointer.QuadPart, nNumberOfBytesToRead); + return TRUE; +} +BOOL bf_WriteFile(file_context_t* ctx, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { + struct buffer_file* pBF = (struct buffer_file*)ctx->m_HookData; + if (!(pBF->access & GENERIC_WRITE)) { + SetLastError(ERROR_ACCESS_DENIED); + return FALSE; + } + + if (ctx->m_Pointer.QuadPart > pBF->nBytes) { + *lpNumberOfBytesWritten = 0; + return TRUE; + } + if (ctx->m_Pointer.QuadPart + nNumberOfBytesToWrite > pBF->nBytes) { + nNumberOfBytesToWrite = (pBF->nBytes - ctx->m_Pointer.QuadPart) & 0xffffffff; + } + *lpNumberOfBytesWritten = nNumberOfBytesToWrite; + memcpy(pBF->buffer + ctx->m_Pointer.QuadPart, lpBuffer, nNumberOfBytesToWrite); + return TRUE; +} + +void hook_file_with_buffer(LPCWSTR filename, LPBYTE buffer, DWORD nBytes, DWORD access) { + file_hook_t* hook = new_file_hook(filename); + + struct buffer_file** ppBF = &((struct buffer_file*)hook->hook_data); + *ppBF = malloc(sizeof **ppBF); + (*ppBF)->buffer = buffer; + (*ppBF)->nBytes = nBytes; + (*ppBF)->access = access; + + hook->ReadFile = bf_ReadFile; + hook->WriteFile = bf_WriteFile; + + hook_file(hook); +} + drive_redirect_t DRIVE_REDIRECT_TABLE[] = { // Note: Had to create last_shime.log { .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" }, + { .drive = "E:\\", .path = "\\\\.\\E:" }, // {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"}, }; @@ -57,27 +117,6 @@ file_hook_t* find_hook(LPCWSTR lpFileName) { return NULL; }; -void make_dirs(char* path) { - int count = 0; - size_t i; - size_t len = strlen(path); - while (1) { - int n = 0; - for (i = 0; i < len; i++) { - if (path[i] == '\\' || path[i] == '/' || path[i] == '\0') { - if (n++ == count) { - path[i] = '\0'; - count++; - break; - } - path[i] = '\\'; - } - } - if (i == len) return; - CreateDirectory(path, NULL); - } -} - char WORKING_DIR[MAX_PATH + 1] = { 0 }; char get_gamedata_drive() { if (WORKING_DIR[0] == 0x00) { @@ -87,7 +126,7 @@ char get_gamedata_drive() { } inline char char_lower(char value) { - if ('A' <= value <= 'Z') return value - 'A' + 'a'; + if ('A' <= value && value <= 'Z') return value - 'A' + 'a'; return value; } @@ -114,13 +153,15 @@ BOOL redirect_path(LPCSTR path, LPCSTR* redirected) { } } + // Don't redirect local paths + GetCurrentDirectoryA(sizeof WORKING_DIR, WORKING_DIR); + if (strstr(path, WORKING_DIR) == path) { + puts("SKIP"); + return FALSE; + } + if ((('a' <= path[0] && path[0] <= 'z') || ('A' <= path[0] && path[0] <= 'Z')) && path[1] == ':' && (path[2] == '/' || path[2] == '\\')) { - // TODO: Ca - if (char_lower(path[0]) == char_lower(get_gamedata_drive())) { - return FALSE; - } - ZeroMemory(_redirected_path, sizeof _redirected_path); snprintf(_redirected_path, sizeof _redirected_path, "dev\\%c\\%s", char_lower(path[0]), path + 3); @@ -188,10 +229,13 @@ HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dw } BOOL WINAPI FakePathFileExistsA(LPCSTR pszPath) { + log_misc(HOOKS_LOGGER, "PathFileExists(%s)", pszPath); redirect_path(pszPath, &pszPath); - return TruePathFileExistsA(pszPath); + BOOL ret = TruePathFileExistsA(pszPath); + return ret; } BOOL WINAPI FakePathFileExistsW(LPCWSTR pszPath) { + log_misc(HOOKS_LOGGER, "PathFileExists(%ls)", pszPath); LPCSTR redirected; if (redirect_path_w(pszPath, &redirected)) { return TruePathFileExistsA(redirected); @@ -318,8 +362,10 @@ DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesT log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", file_hook->filename); return FALSE; } - return file_hook->WriteFile(&(pHData->ctx), lpBuffer, nNumberOfBytesToWrite, - lpNumberOfBytesWritten, lpOverlapped); + BOOL ret = file_hook->WriteFile(&(pHData->ctx), lpBuffer, nNumberOfBytesToWrite, + lpNumberOfBytesWritten, lpOverlapped); + if (ret) pHData->ctx.m_Pointer.QuadPart += *lpNumberOfBytesWritten; + return ret; } BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, @@ -328,6 +374,7 @@ BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRe return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); } + // log_misc(HOOKS_LOGGER, "ReadFile(%d) %d", hFile, nNumberOfBytesToRead); open_hook_t* pHData = GetDataForHandle(hFile, HDATA_FILE); if (pHData == NULL) { @@ -341,8 +388,10 @@ BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRe log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", file_hook->filename); return FALSE; } - return file_hook->ReadFile(&(pHData->ctx), lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, - lpOverlapped); + BOOL ret = file_hook->ReadFile(&(pHData->ctx), lpBuffer, nNumberOfBytesToRead, + lpNumberOfBytesRead, lpOverlapped); + if (ret) pHData->ctx.m_Pointer.QuadPart += *lpNumberOfBytesRead; + return ret; } BOOL WINAPI FakeCloseHandle(HANDLE hObject) { @@ -355,24 +404,48 @@ int WINAPIV Fake_stat64i32(const char* path, struct _stat64i32* buffer) { return True_stat64i32(path, buffer); }; -void hook_io() { - hook("Kernel32.dll", "DeviceIoControl", FakeDeviceIoControl, (void**)&TrueDeviceIoControl, 5); +DWORD WINAPI FakeGetFileAttributesA(LPCSTR lpFileName) { + // The game quits out if MiniDump is present! + if (strcmp(lpFileName, "Y:\\MiniDump\\") == 0) { + return 0; + } - hook("Kernel32.dll", "CreateFileA", FakeCreateFileA, (void**)&TrueCreateFileA, 6); - hook("Kernel32.dll", "CreateFileW", FakeCreateFileW, (void**)&TrueCreateFileW, 6); - - hook("Kernel32.dll", "CloseHandle", FakeCloseHandle, (void**)&TrueCloseHandle, 6); - hook("Kernel32.dll", "SetFilePointer", FakeSetFilePointer, (void**)&TrueSetFilePointer, 6); - hook("Kernel32.dll", "SetFilePointerEx", FakeSetFilePointerEx, (void**)&TrueSetFilePointerEx, - 6); - hook("Kernel32.dll", "WriteFile", FakeWriteFile, (void**)&TrueWriteFile, 6); - hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6); - hook("Kernel32.dll", "GetFileSizeEx", FakeGetFileSizeEx, (void**)&TrueGetFileSizeEx, 6); - - hook("Shlwapi.dll", "PathFileExistsA", FakePathFileExistsA, (void**)&TruePathFileExistsA, 5); - hook("Shlwapi.dll", "PathFileExistsW", FakePathFileExistsW, (void**)&TruePathFileExistsW, 5); - hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA, 7); - hook("Kernel32.dll", "DeleteFileW", FakeDeleteFileW, (void**)&TrueDeleteFileW, 7); - - hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32, 5); + LPCSTR redirected; + if (redirect_path(lpFileName, &redirected)) { + return TrueGetFileAttributesA(redirected); + } + return TrueGetFileAttributesA(lpFileName); +} +DWORD WINAPI FakeGetFileAttributesW(LPCWSTR lpFileName) { + LPCSTR redirected; + if (redirect_path_w(lpFileName, &redirected)) { + return TrueGetFileAttributesA(redirected); + } + return TrueGetFileAttributesW(lpFileName); +} + +void hook_io() { + hook("Kernel32.dll", "DeviceIoControl", FakeDeviceIoControl, (void**)&TrueDeviceIoControl); + + hook("Kernel32.dll", "CreateFileA", FakeCreateFileA, (void**)&TrueCreateFileA); + hook("Kernel32.dll", "CreateFileW", FakeCreateFileW, (void**)&TrueCreateFileW); + + hook("Kernel32.dll", "CloseHandle", FakeCloseHandle, (void**)&TrueCloseHandle); + hook("Kernel32.dll", "SetFilePointer", FakeSetFilePointer, (void**)&TrueSetFilePointer); + hook("Kernel32.dll", "SetFilePointerEx", FakeSetFilePointerEx, (void**)&TrueSetFilePointerEx); + hook("Kernel32.dll", "WriteFile", FakeWriteFile, (void**)&TrueWriteFile); + hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile); + hook("Kernel32.dll", "GetFileSizeEx", FakeGetFileSizeEx, (void**)&TrueGetFileSizeEx); + + hook("Shlwapi.dll", "PathFileExistsA", FakePathFileExistsA, (void**)&TruePathFileExistsA); + hook("Shlwapi.dll", "PathFileExistsW", FakePathFileExistsW, (void**)&TruePathFileExistsW); + hook("Kernel32.dll", "DeleteFileA", FakeDeleteFileA, (void**)&TrueDeleteFileA); + hook("Kernel32.dll", "DeleteFileW", FakeDeleteFileW, (void**)&TrueDeleteFileW); + + hook("Kernel32.dll", "GetFileAttributesA", FakeGetFileAttributesA, + (void**)&TrueGetFileAttributesA); + hook("Kernel32.dll", "GetFileAttributesW", FakeGetFileAttributesW, + (void**)&TrueGetFileAttributesW); + + hook("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32); } diff --git a/src/micetools/dll/hooks/files.h b/src/micetools/dll/hooks/files.h index 7ad5d58..ced9d87 100644 --- a/src/micetools/dll/hooks/files.h +++ b/src/micetools/dll/hooks/files.h @@ -38,6 +38,8 @@ _MICE_FILES BOOL(WINAPI* TruePathFileExistsA)(LPCSTR pszPath); _MICE_FILES BOOL(WINAPI* TruePathFileExistsW)(LPCWSTR pszPath); _MICE_FILES BOOL(WINAPI* TrueDeleteFileA)(LPCSTR lpFileName); _MICE_FILES BOOL(WINAPI* TrueDeleteFileW)(LPCWSTR lpFileName); +_MICE_FILES DWORD(WINAPI* TrueGetFileAttributesA)(LPCSTR lpFileName); +_MICE_FILES DWORD(WINAPI* TrueGetFileAttributesW)(LPCWSTR lpFileName); typedef struct { HANDLE m_Handle; @@ -70,6 +72,8 @@ static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer); #define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW) #define _CreateFileA (TrueCreateFileA ? TrueCreateFileA : CreateFileA) #define _SetFilePointer (TrueSetFilePointer ? TrueSetFilePointer : SetFilePointer) +#define _SetFilePointerEx (TrueSetFilePointerEx ? TrueSetFilePointerEx : SetFilePointerEx) +#define _PathFileExistsA (TruePathFileExistsA ? TruePathFileExistsA : PathFileExistsA) typedef struct drive_redirect { const CHAR* drive; @@ -108,3 +112,4 @@ extern file_hook_t* file_hook_list; file_hook_t* new_file_hook(LPCWSTR filename); void hook_file(file_hook_t* hook); void hook_io(); +void hook_file_with_buffer(LPCWSTR filename, LPBYTE buffer, DWORD nBytes, DWORD access); diff --git a/src/micetools/dll/hooks/gui.c b/src/micetools/dll/hooks/gui.c index bd253fd..25ed954 100644 --- a/src/micetools/dll/hooks/gui.c +++ b/src/micetools/dll/hooks/gui.c @@ -2,6 +2,8 @@ extern LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); +HWND mainWindow; + static HWND window; BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) { DWORD wndProcId; @@ -134,9 +136,11 @@ void post_win_create(HWND hWnd) { // Don't double-hook! if (TrueEndScene != NULL) return; + mainWindow = hWnd; + void* d3d9Device[119]; if (GetD3D9Device(d3d9Device, sizeof(d3d9Device))) { - *((PVOID*)&TrueEndScene) = CreateHook((PVOID)d3d9Device[42], (PVOID)hkEndScene, 7); + *((PVOID*)&TrueEndScene) = CreateHook32((PVOID)d3d9Device[42], (PVOID)hkEndScene); } if (hWnd && !SetWindowSubclass(hWnd, WndProc, (int)&WndProc, (DWORD_PTR)NULL)) { @@ -270,8 +274,8 @@ int WINAPI FakeGetSystemMetrics(int nIndex) { } void hook_gui() { - hook("User32.dll", "CreateWindowExA", FakeCreateWindowExA, (void**)&TrueCreateWindowExA, 7); - hook("User32.dll", "CreateWindowExW", FakeCreateWindowExW, (void**)&TrueCreateWindowExW, 7); - hook("User32.dll", "GetSystemMetrics", FakeGetSystemMetrics, (void**)&TrueGetSystemMetrics, 7); - hook("D3d9.dll", "Direct3DCreate9", FakeDirect3DCreate9, (void**)&TrueDirect3DCreate9, 5); + hook("User32.dll", "CreateWindowExA", FakeCreateWindowExA, (void**)&TrueCreateWindowExA); + hook("User32.dll", "CreateWindowExW", FakeCreateWindowExW, (void**)&TrueCreateWindowExW); + hook("User32.dll", "GetSystemMetrics", FakeGetSystemMetrics, (void**)&TrueGetSystemMetrics); + hook("D3d9.dll", "Direct3DCreate9", FakeDirect3DCreate9, (void**)&TrueDirect3DCreate9); } diff --git a/src/micetools/dll/hooks/gui.h b/src/micetools/dll/hooks/gui.h index 80da499..e2be0f8 100644 --- a/src/micetools/dll/hooks/gui.h +++ b/src/micetools/dll/hooks/gui.h @@ -29,3 +29,5 @@ end_scene_hook_t* end_scene_hook_list; void register_gui_hook(FnEndScene* end_scene); void hook_gui(); void setup_hud_gui(); + +extern HWND mainWindow; diff --git a/src/micetools/dll/hooks/logging.c b/src/micetools/dll/hooks/logging.c index dea79cd..a007e16 100644 --- a/src/micetools/dll/hooks/logging.c +++ b/src/micetools/dll/hooks/logging.c @@ -101,14 +101,14 @@ BOOL WINAPI FakeDeregisterEventSource(HANDLE hEventLog) { return TRUE; } // lpOutputString); } void hook_logging() { - hook("MSVCR90.DLL", "printf", Fakeprintf, (void**)&Trueprintf, 6); - hook("MSVCR90.DLL", "fprintf", Fakefprintf, (void**)&Truefprintf, 6); - hook("MSVCR90.DLL", "fprintf_s", Fakefprintf_s, (void**)&Truefprintf_s, 6); - hook("MSVCR90.DLL", "vfprintf_s", Fakevfprintf_s, (void**)&Truevfprintf_s, 6); + hook("MSVCR90.DLL", "printf", Fakeprintf, (void**)&Trueprintf); + hook("MSVCR90.DLL", "fprintf", Fakefprintf, (void**)&Truefprintf); + hook("MSVCR90.DLL", "fprintf_s", Fakefprintf_s, (void**)&Truefprintf_s); + hook("MSVCR90.DLL", "vfprintf_s", Fakevfprintf_s, (void**)&Truevfprintf_s); hook("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, - (void**)&TrueRegisterEventSourceA, 6); - hook("Advapi32.dll", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA, 6); + (void**)&TrueRegisterEventSourceA); + hook("Advapi32.dll", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA); hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource, - (void**)&TrueDeregisterEventSource, 6); + (void**)&TrueDeregisterEventSource); } diff --git a/src/micetools/dll/hooks/meson.build b/src/micetools/dll/hooks/meson.build index 7afce36..15ff970 100644 --- a/src/micetools/dll/hooks/meson.build +++ b/src/micetools/dll/hooks/meson.build @@ -9,6 +9,13 @@ hooks_files = files( 'setupapi.c', 'time.c', 'registry.c', - 'drive.c', 'system.c', -) \ No newline at end of file + + 'drive/drive.c', + 'drive/disks.c', + 'drive/hooks.c', + 'drive/physicalDrive.c', + + 'drivers/framework.c', + 'drivers/mxhwreset.c', +) diff --git a/src/micetools/dll/hooks/network.c b/src/micetools/dll/hooks/network.c index 4a137aa..ee690fc 100644 --- a/src/micetools/dll/hooks/network.c +++ b/src/micetools/dll/hooks/network.c @@ -4,14 +4,15 @@ int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) { ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr.S_un.S_addr); USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port); // Poorly exclude pcps. TODO: better - if (port < 40100 || port > 40120) { - log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff, - (addr >> 8) & 0xff, addr & 0xff, port); - } + // if (port < 40100 || port > 40120) { + log_misc("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff, + (addr >> 8) & 0xff, addr & 0xff, port); + // } return True_connect(s, name, namelen); } #define IF_INDEX 1 +// Sega prefix #define MAC_PREFIX_0 0xD8 #define MAC_PREFIX_1 0xBB #define MAC_PREFIX_2 0xC1 @@ -89,6 +90,8 @@ DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID if (ppQueryResults) { for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) { if (strcmp(pszName, INTERCEPT_DNS[i].name) == 0) { + printf("%08x\n", MiceConfig.network.naominet_jp); + log_info("dns", "Replacing %s with %08x", pszName, *INTERCEPT_DNS[i].address); // We only support replacing at most one address, but that's all we'll ever need to! @@ -111,10 +114,14 @@ INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily, log_misc("dns", "(WSA)DNS lookup for %s", AddressString); for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) { if (strcmp(AddressString, INTERCEPT_DNS[i].name) == 0) { - log_info("dns", "(WSA)Replacing %s with %08x", AddressString, INTERCEPT_DNS[i].address); + log_info("dns", "(WSA)Replacing %s with %08x", AddressString, + *INTERCEPT_DNS[i].address); lpAddress->sa_family = AF_INET; - memcpy(&lpAddress->sa_data, INTERCEPT_DNS[i].address, 4); + PULONG addr = &(((SOCKADDR_IN*)lpAddress)->sin_addr.S_un.S_addr); + *addr = _byteswap_ulong( + *INTERCEPT_DNS[i] + .address); //(192UL) | (168UL << 8) | (103UL << 16) | (200UL << 24); return ERROR_SUCCESS; } } @@ -124,9 +131,9 @@ INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily, } void hook_network() { - hook("Ws2_32.dll", "connect", Fake_connect, (void**)&True_connect, 5); + hook("Ws2_32.dll", "connect", Fake_connect, (void**)&True_connect); hook("Ws2_32.dll", "WSAStringToAddressA", FakeWSAStringToAddressA, - (void**)&TrueWSAStringToAddressA, 7); - hook("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable, 5); - hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A, 5); + (void**)&TrueWSAStringToAddressA); + hook("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable); + hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A); } diff --git a/src/micetools/dll/hooks/processes.c b/src/micetools/dll/hooks/processes.c index 8560cf0..9b5fe3a 100644 --- a/src/micetools/dll/hooks/processes.c +++ b/src/micetools/dll/hooks/processes.c @@ -34,31 +34,66 @@ BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, // log_error("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); // return FALSE; // #else - // log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); - log_info("spawn", "CreateProcessW %ls", lpApplicationName); + log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine); - lpProcessInformation->hThread = GetDummyHandle(); - return TRUE; + // log_info("spawn", "CreateProcessW %ls", lpApplicationName); + + // lpProcessInformation->hThread = GetDummyHandle(); + // return TRUE; CHAR applicationName[MAX_PATH + 1]; WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName, NULL, NULL); HANDLE child; + CHAR commandLine[MAX_PATH + 1]; + WCHAR commandLineW[MAX_PATH + 1]; + WCHAR micePathW[MAX_PATH + 1]; + GetModuleFileNameW(NULL, micePathW, MAX_PATH); + + HANDLE fake_evt = CreateEvent(NULL, TRUE, FALSE, NULL); + SetEvent(fake_evt); + + if (lpProcessInformation) { + lpProcessInformation->hProcess = fake_evt; + lpProcessInformation->hThread = GetDummyHandle(); + } + + return TRUE; + if (lpCommandLine != NULL) { - CHAR commandLine[MAX_PATH + 1]; - WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL, - NULL); - child = start_and_inject(applicationName, commandLine, MICELIB, false, 0, NULL); + log_error("process", "!!"); + return FALSE; + // WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL, + // NULL); + // child = start_and_inject(applicationName, commandLine, MICELIB, false, 0, NULL, + // CREATE_NEW_CONSOLE); } else { - child = start_and_inject(applicationName, NULL, MICELIB, false, 0, NULL); + dwCreationFlags |= CREATE_NEW_CONSOLE; + wsprintfW(commandLineW, L"mice86 -b %ls", lpApplicationName); + printf("%ls %ls\n", micePathW, commandLineW); + BOOL ret = + TrueCreateProcessW(L"mice86.cmd", commandLineW, lpProcessAttributes, lpThreadAttributes, + bInheritHandles, dwCreationFlags, lpEnvironment, lpCurrentDirectory, + lpStartupInfo, lpProcessInformation); + printf("%d\n", ret); + return ret; + // CHAR commandLine[] + // child = + // start_and_inject(applicationName, NULL, MICELIB, false, 0, NULL, CREATE_NEW_CONSOLE); } return !FAILED(child); // #endif } -void hook_processes() { - hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6); - hook("Kernel32.dll", "CreateProcessA", FakeCreateProcessA, (void**)&TrueCreateProcessA, 6); +BOOL WINAPI FakeGetExitCodeProcess(HANDLE hProcess, LPDWORD lpExitCode) { + *lpExitCode = 0; + return TRUE; +} + +void hook_processes() { + hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW); + hook("Kernel32.dll", "CreateProcessA", FakeCreateProcessA, (void**)&TrueCreateProcessA); + hook("Kernel32.dll", "GetExitCodeProcess", FakeGetExitCodeProcess, NULL); } diff --git a/src/micetools/dll/hooks/registry.c b/src/micetools/dll/hooks/registry.c index 1e453ce..e805dd5 100644 --- a/src/micetools/dll/hooks/registry.c +++ b/src/micetools/dll/hooks/registry.c @@ -33,12 +33,12 @@ LSTATUS WINAPI FakeRegEnumValueA(HKEY hKey, DWORD dwIndex, LPSTR lpValueName, } void hook_registry() { - hook("Advapi32.dll", "RegCloseKey", FakeRegCloseKey, (void**)&TrueRegCloseKey, 4); - hook("Advapi32.dll", "RegCreateKeyExA", FakeRegCreateKeyExA, (void**)&TrueRegCreateKeyExA, 6); - hook("Advapi32.dll", "RegDeleteKeyA", FakeRegDeleteKeyA, (void**)&TrueRegDeleteKeyA, 4); + hook("Advapi32.dll", "RegCloseKey", FakeRegCloseKey, (void**)&TrueRegCloseKey); + hook("Advapi32.dll", "RegCreateKeyExA", FakeRegCreateKeyExA, (void**)&TrueRegCreateKeyExA); + hook("Advapi32.dll", "RegDeleteKeyA", FakeRegDeleteKeyA, (void**)&TrueRegDeleteKeyA); hook("Advapi32.dll", "RegDeleteKeyValueA", FakeRegDeleteKeyValueA, - (void**)&TrueRegDeleteKeyValueA, 5); - hook("Advapi32.dll", "RegEnumKeyExA", FakeRegEnumKeyExA, (void**)&TrueRegEnumKeyExA, 5); + (void**)&TrueRegDeleteKeyValueA); + hook("Advapi32.dll", "RegEnumKeyExA", FakeRegEnumKeyExA, (void**)&TrueRegEnumKeyExA); // TODO: Passthrough - // hook("Advapi32.dll", "RegEnumValueA", FakeRegEnumValueA, (void**)&TrueRegEnumValueA, 5); + // hook("Advapi32.dll", "RegEnumValueA", FakeRegEnumValueA, (void**)&TrueRegEnumValueA); } diff --git a/src/micetools/dll/hooks/setupapi.c b/src/micetools/dll/hooks/setupapi.c index 0e5e4c3..22509d4 100644 --- a/src/micetools/dll/hooks/setupapi.c +++ b/src/micetools/dll/hooks/setupapi.c @@ -109,11 +109,11 @@ BOOL WINAPI FakeSetupDiDestroyDeviceInfoList(HDEVINFO DevicesInfoSet) { } void hook_setupapi() { - hook("Setupapi.DLL", "SetupDiGetClassDevsA", FakeSetupDiGetClassDevsA, (void**)&TrueSetupDiGetClassDevsA, 6); + hook("Setupapi.DLL", "SetupDiGetClassDevsA", FakeSetupDiGetClassDevsA, (void**)&TrueSetupDiGetClassDevsA); hook("Setupapi.DLL", "SetupDiEnumDeviceInterfaces", FakeSetupDiEnumDeviceInterfaces, - (void**)&TrueSetupDiEnumDeviceInterfaces, 7); + (void**)&TrueSetupDiEnumDeviceInterfaces); hook("Setupapi.DLL", "SetupDiGetDeviceInterfaceDetailA", FakeSetupDiGetDeviceInterfaceDetailA, - (void**)&TrueSetupDiGetDeviceInterfaceDetailA, 6); + (void**)&TrueSetupDiGetDeviceInterfaceDetailA); hook("Setupapi.DLL", "SetupDiDestroyDeviceInfoList", FakeSetupDiDestroyDeviceInfoList, - (void**)&TrueSetupDiDestroyDeviceInfoList, 7); + (void**)&TrueSetupDiDestroyDeviceInfoList); } diff --git a/src/micetools/dll/hooks/system.c b/src/micetools/dll/hooks/system.c index 1e88188..4ba7a8b 100644 --- a/src/micetools/dll/hooks/system.c +++ b/src/micetools/dll/hooks/system.c @@ -1,5 +1,7 @@ #include "system.h" +#include "./files.h" + // const char OS_VERSION[] = "Service Pack 3"; OSVERSIONINFOA OS_VERSION = { @@ -22,14 +24,18 @@ BOOL WINAPI FakeGetVolumeInformationW(LPCWSTR lpRootPathName, LPWSTR lpVolumeNam LPDWORD lpMaximumComponentLength, LPDWORD lpFileSystemFlags, LPWSTR lpFileSystemNameBuffer, DWORD nFileSystemNameSize) { log_trace("system", "GetVolumeInformationW"); - *lpVolumeSerialNumber = 0x1c0fd22b; + if (lpVolumeNameBuffer && nVolumeNameSize) lpVolumeNameBuffer[0] = '\0'; + if (lpVolumeSerialNumber) *lpVolumeSerialNumber = 0x00144db0; + if (lpMaximumComponentLength) *lpMaximumComponentLength = 0xff; + if (lpFileSystemFlags) *lpFileSystemFlags = 0x700ff; + if (lpFileSystemNameBuffer) wcsncpy_s(lpFileSystemNameBuffer, nFileSystemNameSize, L"NTFS", 5); return TRUE; -}; +} DWORD WINAPI FakeGetTempPathW(DWORD nBufferLength, LPWSTR lpBuffer) { memcpy(lpBuffer, TEMP_PATH, sizeof TEMP_PATH); return wcslen(TEMP_PATH); -}; +} HCURSOR WINAPI FakeLoadCursorFromFileA(LPCSTR lpFileName) { return (HANDLE)1; } BOOL FakeSetSystemCursor(HCURSOR hcur, DWORD id) { return TRUE; } @@ -42,14 +48,33 @@ LONG WINAPI FakeChangeDisplaySettingsExA(LPCSTR lpszDeviceName, DEVMODEA* lpDevM } void hook_system() { - hook("Kernel32.dll", "GetVolumeInformationW", FakeGetVolumeInformationW, NULL, 5); - hook("Kernel32.dll", "GetTempPathW", FakeGetTempPathW, NULL, 5); - hook("Kernel32.dll", "GetVersionExA", FakeGetVersionExA, NULL, 5); + // TODO: This should be part of drives/hooks.c + hook("Kernel32.dll", "GetVolumeInformationW", FakeGetVolumeInformationW, NULL); + hook("Kernel32.dll", "GetTempPathW", FakeGetTempPathW, NULL); + hook("Kernel32.dll", "GetVersionExA", FakeGetVersionExA, NULL); - hook("User32.dll", "ChangeDisplaySettingsA", FakeChangeDisplaySettingsA, NULL, 4); - hook("User32.dll", "ChangeDisplaySettingsExA", FakeChangeDisplaySettingsExA, NULL, 6); + hook("User32.dll", "ChangeDisplaySettingsA", FakeChangeDisplaySettingsA, NULL); + hook("User32.dll", "ChangeDisplaySettingsExA", FakeChangeDisplaySettingsExA, NULL); - // hook("User32.dll", "LoadCursorFromFileA", FakeLoadCursorFromFileA, NULL, 5); - // hook("User32.dll", "SetSystemCursor", FakeSetSystemCursor, NULL, 5); - // hook("User32.dll", "DeleteObject", FakeDeleteObject, NULL, 5); + // hook("User32.dll", "LoadCursorFromFileA", FakeLoadCursorFromFileA, NULL); + // hook("User32.dll", "SetSystemCursor", FakeSetSystemCursor, NULL); + // hook("User32.dll", "DeleteObject", FakeDeleteObject, NULL); + + const char* SystemVersion = "00691001\r\n"; + const char* UpdateVersion = "0000\r\n"; + + const char* RingmasterPub = + ("-----BEGIN PUBLIC KEY-----\r\n" + "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDH/y0LFuiVonnU+7fKLEOhfQoi\r\n" + "uElB6f9+MVc+VwLzCNV/xU05TWJgm82m/lsmtYwArrA9gHHCB7ExgkaH3kDmd4l6\r\n" + "FumWIRCO/7Z4pbIFSb9xvPYWn7GJJvtJKn2OU/t7zt4nP3MiR0J4lqtT88x6F4Ui\r\n" + "UeI3d2jT+Fw1dgRn7wIDAQAB\r\n" + "-----END PUBLIC KEY-----\r\n"); + + hook_file_with_buffer(L"C:\\System\\SystemVersion.txt", SystemVersion, + strlen(SystemVersion) + 1, GENERIC_READ); + hook_file_with_buffer(L"C:\\System\\UpdateVersion.txt", UpdateVersion, + strlen(UpdateVersion) + 1, GENERIC_READ); + hook_file_with_buffer(L"c:\\System\\Execute\\ringmaster_pub.pem", RingmasterPub, + strlen(RingmasterPub) + 1, GENERIC_READ); } diff --git a/src/micetools/dll/hooks/time.c b/src/micetools/dll/hooks/time.c index ddc21e6..6060772 100644 --- a/src/micetools/dll/hooks/time.c +++ b/src/micetools/dll/hooks/time.c @@ -9,18 +9,23 @@ BOOL WINAPI Fake_SetLocalTime(const SYSTEMTIME* lpSystemTime) { memcpy(&localTime, lpSystemTime, sizeof localTime); ltCache = TRUE; - log_info("time", "Not setting local time to: %04d-%02d-%02d %02d:%02d:%02d.%04d", lpSystemTime->wYear, - lpSystemTime->wMonth, lpSystemTime->wDay, lpSystemTime->wHour, lpSystemTime->wMinute, - lpSystemTime->wSecond, lpSystemTime->wMilliseconds); + log_info("time", "Not setting local time to: %04d-%02d-%02d %02d:%02d:%02d.%04d", + lpSystemTime->wYear, lpSystemTime->wMonth, lpSystemTime->wDay, lpSystemTime->wHour, + lpSystemTime->wMinute, lpSystemTime->wSecond, lpSystemTime->wMilliseconds); return TRUE; } BOOL WINAPI Fake_SetSystemTime(const SYSTEMTIME* lpSystemTime) { memcpy(&systemTime, lpSystemTime, sizeof systemTime); stCache = TRUE; - log_info("time", "Not setting system time to: %04d-%02d-%02d %02d:%02d:%02d.%04d", lpSystemTime->wYear, - lpSystemTime->wMonth, lpSystemTime->wDay, lpSystemTime->wHour, lpSystemTime->wMinute, - lpSystemTime->wSecond, lpSystemTime->wMilliseconds); + log_info("time", "Not setting system time to: %04d-%02d-%02d %02d:%02d:%02d.%04d", + lpSystemTime->wYear, lpSystemTime->wMonth, lpSystemTime->wDay, lpSystemTime->wHour, + lpSystemTime->wMinute, lpSystemTime->wSecond, lpSystemTime->wMilliseconds); + return TRUE; +} + +BOOL WINAPI Fake_SetTimeZoneInformation(const TIME_ZONE_INFORMATION* lpTimeZoneInformation) { + log_info("time", "Not setting timezone to: %d", lpTimeZoneInformation->Bias); return TRUE; } @@ -41,8 +46,9 @@ BOOL WINAPI Fake_GetSystemTime(SYSTEMTIME* lpSystemTime) { } void hook_time() { - hook("Kernel32.dll", "SetLocalTime", Fake_SetLocalTime, (void**)&TrueSetLocalTime, 6); - hook("Kernel32.dll", "SetSystemTime", Fake_SetSystemTime, (void**)&TrueSetSystemTime, 6); - hook("Kernel32.dll", "GetLocalTime", Fake_GetLocalTime, (void**)&TrueGetLocalTime, 6); - hook("Kernel32.dll", "GetSystemTime", Fake_GetSystemTime, (void**)&TrueGetSystemTime, 6); + hook("Kernel32.dll", "SetLocalTime", Fake_SetLocalTime, NULL); + hook("Kernel32.dll", "SetSystemTime", Fake_SetSystemTime, NULL); + hook("Kernel32.dll", "SetTimeZoneInformation", Fake_SetTimeZoneInformation, NULL); + hook("Kernel32.dll", "GetLocalTime", Fake_GetLocalTime, (void**)&TrueGetLocalTime); + hook("Kernel32.dll", "GetSystemTime", Fake_GetSystemTime, (void**)&TrueGetSystemTime); } diff --git a/src/micetools/dll/hooks/time.h b/src/micetools/dll/hooks/time.h index 23f3414..1421398 100644 --- a/src/micetools/dll/hooks/time.h +++ b/src/micetools/dll/hooks/time.h @@ -1,9 +1,7 @@ #pragma once #include "../common.h" -static BOOL(WINAPI* TrueSetLocalTime)(const SYSTEMTIME* lpSystemTime); static BOOL(WINAPI* TrueGetLocalTime)(SYSTEMTIME* lpSystemTime); -static BOOL(WINAPI* TrueSetSystemTime)(const SYSTEMTIME* lpSystemTime); static BOOL(WINAPI* TrueGetSystemTime)(SYSTEMTIME* lpSystemTime); void hook_time(); diff --git a/src/micetools/dll/meson.build b/src/micetools/dll/meson.build index bf45e64..7a8d8eb 100644 --- a/src/micetools/dll/meson.build +++ b/src/micetools/dll/meson.build @@ -25,6 +25,7 @@ shared_library( dmi_lib, mice_lib, amiTimer, + amiMd5, mxklib, ], include_directories: [ diff --git a/src/micetools/dll/smbus.h b/src/micetools/dll/smbus.h index 8de2e30..d780208 100644 --- a/src/micetools/dll/smbus.h +++ b/src/micetools/dll/smbus.h @@ -111,43 +111,15 @@ IOCTL_MXSUPERIO_READ: - W83627UHC (schematics, sheet 16) */ -// SMBUS Devices (+1 is implied for read addresses) -#define SMBUS_PCA9535 0x40 -#define SMBUS_DIMM_A1 0xA0 -#define SMBUS_DIMM_B1 0xA4 -#define SMBUS_EXIO 0xA8 -#define SMBUS_N2 0xAA -#define SMBUS_EEPROM 0xAE - // Keychip -#define DS_GET_EEPROM 0x40 -#define DS_GET_UNIQUE_NUMBER 0xA0 -#define DS_GET_STATUS 0xA8 -#define DS_STATUS_FLAG_BUSY 2 -#define DS_I2C_CHALLENGE_RESPONSE 0xB0 +// #define DS_REG_ID 0xA0 +// #define DS_REG_ID_END 0xA7 +// #define DS_REG_STATUS 0xA8 -#define EXIO_GET_BUSY 0x00 +// #define DS_STATUS_FLAG_BUSY 2 +// #define DS_I2C_CHALLENGE_RESPONSE 0xB0 -// Old -// TODO: Check for uses, then delete #pragma pack(push, 1) -typedef struct mxsmbus_request_packet_ { - BYTE status; - BYTE prt; - BYTE addr; - BYTE reg; - BYTE dlen; - BYTE data[32]; -} mxsmbus_request_packet; -typedef struct mxsmbus_i2c_packet_ { - BYTE status; - BYTE prt; - WORD addr; - WORD reg; - BYTE dlen; - BYTE data[32]; -} mxsmbus_i2c_packet; - typedef struct _MXSMBUS_REQUEST_PACKET { BYTE status; BYTE command; diff --git a/src/micetools/dll/util/_util.h b/src/micetools/dll/util/_util.h index 9aaebe2..25541dc 100644 --- a/src/micetools/dll/util/_util.h +++ b/src/micetools/dll/util/_util.h @@ -13,3 +13,6 @@ void SetDataForHandle(HANDLE hObject, DWORD type, PVOID pData, BOOL isHeap); BOOL RemoveDataForHandle(HANDLE hObject, DWORD type); HANDLE GetDummyHandle(); void BytesToHex(char* hex_buffer, BYTE* bytes, DWORD nbytes); +void PrintStack(void); + +void make_dirs(const char* path); diff --git a/src/micetools/dll/util/hook.c b/src/micetools/dll/util/hook.c index 7b3ad85..c756334 100644 --- a/src/micetools/dll/util/hook.c +++ b/src/micetools/dll/util/hook.c @@ -19,13 +19,12 @@ void append_hook(function_hook_t* hook) { while (hl->next != NULL) hl = hl->next; hl->next = hook; } -void hook(LPCSTR dll, LPCSTR name, void* patch, void** store, UINT length) { +void hook(LPCSTR dll, LPCSTR name, void* patch, void** store) { function_hook_t* hook = (function_hook_t*)malloc(sizeof(struct function_hook)); hook->dll = dll; hook->name = name; hook->patch = patch; hook->store = store; - hook->length = length; append_hook(hook); } @@ -55,11 +54,68 @@ BOOL Detour(PVOID src, PVOID dst, const intptr_t len) { return TRUE; } -void* CreateHook(PVOID src, PVOID dst, const intptr_t len) { - if (len < 5) return NULL; +void* Win32HotpatchHook(PVOID src, PVOID dst) { + LPBYTE bSrc = (LPBYTE)src; + + DWORD oldProt; + VirtualProtect(bSrc - 5, 7, PAGE_EXECUTE_READWRITE, &oldProt); + + // relative JMP to dst + bSrc[-5] = 0xE9; + DWORD relJump = (DWORD)dst - (DWORD)src; + bSrc[-1] = (relJump >> 24) & 0xff; + bSrc[-2] = (relJump >> 16) & 0xff; + bSrc[-3] = (relJump >> 8) & 0xff; + bSrc[-4] = relJump & 0xff; + // JMP $-5 + bSrc[0] = 0xEB; + bSrc[1] = 0xF9; + + VirtualProtect(bSrc - 5, 7, oldProt, &oldProt); + + // We don't need a gateway; we can just jump right in + return bSrc + 2; +} +void* CreateHook32(PVOID src, PVOID dst) { + LPBYTE bSrc = (LPBYTE)src; + + // If this DLL is hotpatchable, sieze the opportunity + if (bSrc[0] == 0x8b && bSrc[1] == 0xff && bSrc[-1] == 0xCC && bSrc[-2] == 0xCC && + bSrc[-3] == 0xCC && bSrc[-4] == 0xCC && bSrc[-5] == 0xCC) { + return Win32HotpatchHook(src, dst); + } + + intptr_t len = 5; + + // This is a very crude way to identify common instruction patterns + // to select or patch length. + if (bSrc[0] == 0xff && bSrc[1] == 0x25) { + // jmp DWORD PTR ds:0x........ + len = 6; + } else if (bSrc[0] == 0x6a && bSrc[2] == 0x68) { + // push 0x... (byte) + // push 0x... (dword) + len = 7; + } else if (bSrc[0] == 0x6a && bSrc[2] == 0xb8) { + // push 0x... (byte) + // mov eax,0x... (dword) + len = 7; + } else if (bSrc[0] == 0x68) { + // push 0x... (dword) + len = 5; + } else { + log_error(HOOKS_LOGGER, "Unable to identify gateway length! Function peek:"); + for (int i = 0; i < 16; i++) { + printf("%02x ", ((LPBYTE)src)[i]); + } + puts(""); + log_error(HOOKS_LOGGER, "Unsafely defaulting to 5!"); + len = 5; + } PVOID gateway = VirtualAlloc(0, len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); if (!gateway) return NULL; + memcpy(gateway, src, len); *(PCHAR)((int)gateway + len) = '\xE9'; @@ -91,9 +147,10 @@ void setup_hooks() { void* original = GetProcAddress(dll, hook->name); if (original == NULL) { - log_warning(HOOKS_LOGGER, "failed to get original %s", hook->name); + log_warning(HOOKS_LOGGER, "failed to get original %s (%03x)", hook->name, + GetLastError()); } else { - void* gateway = CreateHook(original, hook->patch, hook->length); + void* gateway = CreateHook32(original, hook->patch); if (hook->store != NULL) *hook->store = gateway; log_misc(HOOKS_LOGGER, "hooked %s", hook->name); } diff --git a/src/micetools/dll/util/hook.h b/src/micetools/dll/util/hook.h index 5513001..f464548 100644 --- a/src/micetools/dll/util/hook.h +++ b/src/micetools/dll/util/hook.h @@ -7,7 +7,6 @@ typedef struct function_hook { LPCSTR name; PVOID patch; PVOID* store; - UINT length; struct function_hook* next; } function_hook_t; @@ -15,9 +14,9 @@ static BOOL Detour(PVOID src, PVOID dst, const intptr_t len); void patch_at(PVOID addr, const char* patch, DWORD length); void clear_at(PVOID addr, BYTE clearVal, DWORD length); -void* CreateHook(PVOID src, PVOID dst, const intptr_t len); +void* CreateHook32(PVOID src, PVOID dst); static void append_hook(function_hook_t* hook); -void hook(LPCSTR dll, LPCSTR name, void* patch, void** store, UINT length); +void hook(LPCSTR dll, LPCSTR name, void* patch, void** store); void setup_hooks(); diff --git a/src/micetools/dll/util/log.c b/src/micetools/dll/util/log.c index 1285cce..13c3f7b 100644 --- a/src/micetools/dll/util/log.c +++ b/src/micetools/dll/util/log.c @@ -10,7 +10,7 @@ #include "../../lib/mice/config.h" #include "../hooks/logging.h" -extern WCHAR exePath[MAX_PATH + 1]; +extern WCHAR exeName[MAX_PATH + 1]; extern DWORD imageOffset; extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, @@ -79,11 +79,11 @@ DWORD* ppLogcb; int _do_log(BYTE log_level, const char* caller, const char* format, va_list args) { // TODO: These are all horrible bodges - if (wcscmp(exePath, L"mxnetwork.exe") == 0) { + if (wcscmp(exeName, L"mxnetwork.exe") == 0) { // *((DWORD*)(imageOffset + 0x004438e8)) = (DWORD)(&logcb); *((DWORD*)(imageOffset + 0x004438e8)) = 0x00000000; } - if (wcscmp(exePath, L"maimai_dump_.exe") == 0) { + if (wcscmp(exeName, L"maimai_dump_.exe") == 0) { *((DWORD*)(imageOffset + 0x00c820ec)) = 0x00000001; pLogcb = (DWORD)(&amLogCallback); ppLogcb = &pLogcb; @@ -134,7 +134,7 @@ int _do_log(BYTE log_level, const char* caller, const char* format, va_list args int vlog_trace(const char* caller, const char* format, va_list args) { return _do_log(LOG_TRACE, caller, format, args); } -int log_trace(const char* caller, const char* format, ...) { +int _log_trace(const char* caller, const char* format, ...) { va_list args; va_start(args, format); int ret = vlog_trace(caller, format, args); @@ -144,7 +144,7 @@ int log_trace(const char* caller, const char* format, ...) { int vlog_misc(const char* caller, const char* format, va_list args) { return _do_log(LOG_MISC, caller, format, args); } -int log_misc(const char* caller, const char* format, ...) { +int _log_misc(const char* caller, const char* format, ...) { va_list args; va_start(args, format); int ret = vlog_misc(caller, format, args); @@ -154,7 +154,7 @@ int log_misc(const char* caller, const char* format, ...) { int vlog_info(const char* caller, const char* format, va_list args) { return _do_log(LOG_INFO, caller, format, args); } -int log_info(const char* caller, const char* format, ...) { +int _log_info(const char* caller, const char* format, ...) { va_list args; va_start(args, format); int ret = vlog_info(caller, format, args); @@ -164,7 +164,7 @@ int log_info(const char* caller, const char* format, ...) { int vlog_warning(const char* caller, const char* format, va_list args) { return _do_log(LOG_WARNING, caller, format, args); } -int log_warning(const char* caller, const char* format, ...) { +int _log_warning(const char* caller, const char* format, ...) { va_list args; va_start(args, format); int ret = vlog_warning(caller, format, args); @@ -174,7 +174,7 @@ int log_warning(const char* caller, const char* format, ...) { int vlog_error(const char* caller, const char* format, va_list args) { return _do_log(LOG_ERROR, caller, format, args); } -int log_error(const char* caller, const char* format, ...) { +int _log_error(const char* caller, const char* format, ...) { va_list args; va_start(args, format); int ret = vlog_error(caller, format, args); @@ -184,7 +184,7 @@ int log_error(const char* caller, const char* format, ...) { int vlog_game(const char* caller, const char* format, va_list args) { return _do_log(LOG_GAME, caller, format, args); } -int log_game(const char* caller, const char* format, ...) { +int _log_game(const char* caller, const char* format, ...) { va_list args; va_start(args, format); int ret = vlog_game(caller, format, args); diff --git a/src/micetools/dll/util/log.h b/src/micetools/dll/util/log.h index 064a9e3..c5df5eb 100644 --- a/src/micetools/dll/util/log.h +++ b/src/micetools/dll/util/log.h @@ -16,12 +16,12 @@ extern CRITICAL_SECTION logger_lock; -int log_trace(const char* caller, const char* format, ...); -int log_misc(const char* caller, const char* format, ...); -int log_info(const char* caller, const char* format, ...); -int log_warning(const char* caller, const char* format, ...); -int log_error(const char* caller, const char* format, ...); -int log_game(const char* caller, const char* format, ...); +int _log_trace(const char* caller, const char* format, ...); +int _log_misc(const char* caller, const char* format, ...); +int _log_info(const char* caller, const char* format, ...); +int _log_warning(const char* caller, const char* format, ...); +int _log_error(const char* caller, const char* format, ...); +int _log_game(const char* caller, const char* format, ...); int vlog_trace(const char* caller, const char* format, va_list args); int vlog_misc(const char* caller, const char* format, va_list args); @@ -33,3 +33,42 @@ int vlog_game(const char* caller, const char* format, va_list args); void log_stack(const char* caller); void setup_logging(); + +// Disable some logging entirely at build time for speed +#define COMPILE_LOG_LEVEL 6 + +#if COMPILE_LOG_LEVEL >= 6 +#define log_trace _log_trace +#else +#define log_trace(...) +#endif + +#if COMPILE_LOG_LEVEL >= 5 +#define log_misc _log_misc +#else +#define log_misc(...) +#endif + +#if COMPILE_LOG_LEVEL >= 4 +#define log_info _log_info +#else +#define log_info(...) +#endif + +#if COMPILE_LOG_LEVEL >= 3 +#define log_warning _log_warning +#else +#define log_warning(...) +#endif + +#if COMPILE_LOG_LEVEL >= 2 +#define log_error _log_error +#else +#define log_error(...) +#endif + +#if COMPILE_LOG_LEVEL >= 1 +#define log_game _log_game +#else +#define log_game(...) +#endif diff --git a/src/micetools/dll/util/misc.c b/src/micetools/dll/util/misc.c index cafc1fe..f1b9870 100644 --- a/src/micetools/dll/util/misc.c +++ b/src/micetools/dll/util/misc.c @@ -1,7 +1,33 @@ +#define _WIN32_WINNT 0x0600 #include +#include #include "../hooks/files.h" +void PrintStack(void) { + unsigned int i; + void* stack[100]; + unsigned short frames; + SYMBOL_INFO* symbol; + HANDLE process; + + process = GetCurrentProcess(); + + SymInitialize(process, NULL, TRUE); + + frames = CaptureStackBackTrace(0, 100, stack, NULL); + symbol = (SYMBOL_INFO*)calloc(sizeof(SYMBOL_INFO) + 256 * sizeof(char), 1); + symbol->MaxNameLen = 255; + symbol->SizeOfStruct = sizeof(SYMBOL_INFO); + + for (i = 0; i < frames; i++) { + SymFromAddr(process, (DWORD64)(stack[i]), 0, symbol); + printf("%i: %s - 0x%0X\n", frames - i - 1, symbol->Name, symbol->Address); + } + + free(symbol); +} + BOOL FileExists(wchar_t* szPath) { DWORD dwAttrib = GetFileAttributesW(szPath); return (dwAttrib != INVALID_FILE_ATTRIBUTES && !(dwAttrib & FILE_ATTRIBUTE_DIRECTORY)); @@ -96,3 +122,29 @@ void BytesToHex(char* hex_buffer, BYTE* bytes, DWORD nbytes) { } hex_buffer[nbytes * 3] = '\0'; } + +void make_dirs(const char* path) { + int count = 0; + size_t i; + size_t len = strlen(path); + char* temp = malloc(len + 1); + memcpy(temp, path, len + 1); + + for (i = 0; i < len; i++) { + if (temp[i] == '/' || temp[i] == '\\') count++; + } + if (count == 0) { + free(temp); + return; + } + + for (i = 0; i < len && count; i++) { + if (temp[i] == '/' || temp[i] == '\\') { + temp[i] = '\0'; + CreateDirectory(temp, NULL); + temp[i] = '\\'; + count--; + } + } + free(temp); +} diff --git a/src/micetools/launcher/main.c b/src/micetools/launcher/main.c index 4d18ce1..101ba81 100644 --- a/src/micetools/launcher/main.c +++ b/src/micetools/launcher/main.c @@ -55,6 +55,11 @@ void parse_cmdline(int argc, char* argv[]) { int main(int argc, char* argv[]) { load_mice_config(); + fprintf(stderr, "Argc: %d\n", argc); + CHAR workDir[MAX_PATH + 1]; + GetCurrentDirectory(MAX_PATH, workDir); + fprintf(stderr, "Work dir: %s\n", workDir); + fprintf(stderr, "Micetools version: %s\n", MICE_VERSION); parse_cmdline(argc, argv); @@ -98,7 +103,7 @@ int main(int argc, char* argv[]) { char* extra_injections = MiceConfig.launcher.inject; HANDLE game_proc = - start_and_inject(exe_name, cmdline, micepath, debug_wait, boot_delay, extra_injections); + start_and_inject(exe_name, cmdline, micepath, debug_wait, boot_delay, extra_injections, 0); if (!game_proc) return -1; if (FAILED(WaitForSingleObject(game_proc, INFINITE))) { diff --git a/src/micetools/lib/am/amDongle.c b/src/micetools/lib/am/amDongle.c index 505052e..e9b3561 100644 --- a/src/micetools/lib/am/amDongle.c +++ b/src/micetools/lib/am/amDongle.c @@ -670,9 +670,9 @@ AM_DONGLE_STATUS amDongleRecvBinary(void) { uint bufferLength; switch (amDongle.requestCode) { - case AM_DONGLE_WTF_80: + case AM_DONGLE_APPBOOT_SEED: buffer = amDongle.valueBuffer; - bufferLength = 0x10; + bufferLength = 16; break; case AM_DONGLE_WTF_81: case AM_DONGLE_REQUEST_BILLING_GET_CA_CERT: @@ -999,7 +999,7 @@ AM_DONGLE_STATUS amDongleEncrypt(unsigned char *pt, unsigned char *ct, if (pt == NULL || ct == NULL) return AM_DONGLE_STATUS_ERR_INVALID_PARAM; - char ptHex[32]; + char ptHex[33]; bin_to_hex(ptHex, pt, 16); pcp_send_data_t *packet = pcpaSetSendPacket(&amDongle.pcpa, "keychip.encrypt", ptHex); if (packet == NULL && amDongleDebugLevel > 0) @@ -1020,7 +1020,8 @@ AM_DONGLE_STATUS amDongleDecrypt(unsigned char *ct, unsigned char *pt, if (ct == NULL || pt == NULL) return AM_DONGLE_STATUS_ERR_INVALID_PARAM; - char ctHex[32]; + char ctHex[33]; + ZeroMemory(ctHex, 33); bin_to_hex(ctHex, ct, 16); pcp_send_data_t *packet = pcpaSetSendPacket(&amDongle.pcpa, "keychip.decrypt", ctHex); if (packet == NULL && amDongleDebugLevel > 0) @@ -1119,7 +1120,51 @@ AM_DONGLE_STATUS amDongleBillingAddPlayCount(void *playCount, AM_DONGLE_BLOCKING amiDebugLog("Error: pcpaAddSendPacket return NULL"); } amDongle.valueBuffer = playCount; - amDongle.requestCode = 0xf; + amDongle.requestCode = AM_DONGLE_REQUEST_BILLING_ADD_PLAYCOUNT; + if (blocking == AM_DONGLE_BLOCK) { + return amDongleSendAndReceiveEx(); + } + return amDongleOpen(); +} + +AM_DONGLE_STATUS amDongleSetIv(AM_DONGLE_BLOCKING blocking) { + if (!amDongle.m_init) return AM_DONGLE_STATUS_ERR_NO_INIT; + if (!amDongle.auth_ready) return AM_DONGLE_STATUS_ERR_AUTH_READY; + if (!amDongle.done_init || !amDongle.available) return AM_DONGLE_STATUS_NG; + if (amDongle.seq != AM_DONGLE_SEQ_NONE) return AM_DONGLE_STATUS_BUSY; + + pcp_send_data_t *send_data = + pcpaSetSendPacket(&amDongle.pcpa, "keychip.setiv", "?"); + if (send_data == NULL && amDongleDebugLevel > 0) { + amiDebugLog("Error: pcpaSetSendPacket return NULL"); + } + + amDongle.requestCode = AM_DONGLE_REQUEST_SET_IV; + if (blocking == AM_DONGLE_BLOCK) { + return amDongleSendAndReceiveEx(); + } + return amDongleOpen(); +} + +AM_DONGLE_STATUS amDongleGetSeed(unsigned char* seed, AM_DONGLE_BLOCKING blocking) { + if (!amDongle.m_init) return AM_DONGLE_STATUS_ERR_NO_INIT; + if (!amDongle.auth_ready) return AM_DONGLE_STATUS_ERR_AUTH_READY; + if (!amDongle.done_init || !amDongle.available) return AM_DONGLE_STATUS_NG; + if (amDongle.seq != AM_DONGLE_SEQ_NONE) return AM_DONGLE_STATUS_BUSY; + if (seed == NULL) return AM_DONGLE_STATUS_ERR_INVALID_PARAM; + + pcp_send_data_t *send_data = + pcpaSetSendPacket(&amDongle.pcpa, "keychip.appboot.seed", "?"); + if (send_data == NULL && amDongleDebugLevel > 0) { + amiDebugLog("Error: pcpaSetSendPacket return NULL"); + } + send_data = pcpaAddSendPacket(&amDongle.pcpa, "cache", "1"); + if (send_data == NULL && amDongleDebugLevel > 0) { + amiDebugLog("Error: pcpaAddSendPacket return NULL"); + } + + amDongle.requestCode = AM_DONGLE_APPBOOT_SEED; + amDongle.valueBuffer = seed; if (blocking == AM_DONGLE_BLOCK) { return amDongleSendAndReceiveEx(); } diff --git a/src/micetools/lib/am/amDongle.h b/src/micetools/lib/am/amDongle.h index 674516a..60503a9 100644 --- a/src/micetools/lib/am/amDongle.h +++ b/src/micetools/lib/am/amDongle.h @@ -122,7 +122,7 @@ typedef enum { // 29 AM_DONGLE_REQUEST_GET_FORMAT_TYPE = 30, - AM_DONGLE_WTF_80 = 0x80 | 0, + AM_DONGLE_APPBOOT_SEED = 0x80 | 0, AM_DONGLE_WTF_81 = 0x80 | 1, AM_DONGLE_REQUEST_BILLING_GET_TRACEDATA = 0x80 | 2, AM_DONGLE_REQUEST_BILLING_GET_SIGNATURE_PK = 0x80 | 3, @@ -179,6 +179,8 @@ AM_DONGLE_STATUS amDongleBillingAddPlayCount(void *playCount, AM_DONGLE_BLOCKING AM_DONGLE_STATUS amDongleBillingGetNearfull(unsigned int *nearfull, AM_DONGLE_BLOCKING blocking); AM_DONGLE_STATUS amDongleEncrypt(unsigned char *pt, unsigned char *ct, AM_DONGLE_BLOCKING blocking); AM_DONGLE_STATUS amDongleDecrypt(unsigned char *ct, unsigned char *pt, AM_DONGLE_BLOCKING blocking); +AM_DONGLE_STATUS amDongleSetIv(AM_DONGLE_BLOCKING blocking); +AM_DONGLE_STATUS amDongleGetSeed(unsigned char* seed, AM_DONGLE_BLOCKING blocking); void amDongleBillingGetCaCertification(void); void amDongleBillingGetMainId(void); @@ -203,9 +205,7 @@ void amDongleGetDsMac(void); void amDongleGetDvdFlag(void); void amDongleGetFormatType(void); void amDongleGetResult(void); -void amDongleGetSeed(void); void amDongleGetSsdResponse(void); void amDongleRequestSsdHostProof(void); void amDongleSetAuthCondition(void); -void amDongleSetIv(void); void amDongleUpdate(void); diff --git a/src/micetools/lib/am/amPlatform.h b/src/micetools/lib/am/amPlatform.h index e30d74a..7afa9a0 100644 --- a/src/micetools/lib/am/amPlatform.h +++ b/src/micetools/lib/am/amPlatform.h @@ -99,7 +99,6 @@ void amPlatformGetGpuPstate(void); void amPlatformGetGraphicInfo(void); void amPlatformGetMemorySize(void); void amPlatformGetOsVersion(void); -void amPlatformGetOsVersion(void); void amPlatformGetPartitionInfo(void); void amPlatformGetPlatformIdEx(void); void amPlatformGetPortName(void); @@ -109,4 +108,4 @@ void amPlatformGetStorageInfo(void); void amPlatformNvapiInit(void); void amPlatformSetDisplayMode(void); void amPlatformSetDisplayResolution(void); -void amPlatformSetDisplayResolutionAndMode(void); \ No newline at end of file +void amPlatformSetDisplayResolutionAndMode(void); diff --git a/src/micetools/lib/am/amSerialId.c b/src/micetools/lib/am/amSerialId.c index 5c86a1c..19c4eb6 100644 --- a/src/micetools/lib/am/amSerialId.c +++ b/src/micetools/lib/am/amSerialId.c @@ -15,9 +15,7 @@ BOOL amSerialIdIsValid(char *id_string) { if (chr != '-') return FALSE; } else if (i < 8 || i > 15) { if (!isdigit(chr) && !isupper(chr)) return FALSE; - if (chr == 'I') return FALSE; - if (chr == 'O') return FALSE; } else { if (!isdigit(chr)) return FALSE; @@ -34,4 +32,4 @@ BOOL amSerialIdConvert(char *id_string, char *serial_id) { memcpy_s(serial_id, 17, id_string, 4); memcpy_s(serial_id + 4, 13, id_string + 5, 7); return TRUE; -} \ No newline at end of file +} diff --git a/src/micetools/lib/ami/amiCrc.h b/src/micetools/lib/ami/amiCrc.h index 754b5f1..5922ffc 100644 --- a/src/micetools/lib/ami/amiCrc.h +++ b/src/micetools/lib/ami/amiCrc.h @@ -13,12 +13,12 @@ void amiCrc32RCreateTable(unsigned int *table); unsigned int amiCrc32RGet(unsigned int *table, int length, unsigned char *data, unsigned int initial); -#define amCrc32RCreateTable() \ +#define amiCrc32RInit() \ do { \ if (!amiCrc.m_init) { \ amiCrc32RCreateTable(amiCrc.m_table); \ amiCrc.m_init = 1; \ } \ } while (0) -#define amCrc32RGet(length, data, initial) \ +#define amiCrc32RCalc(length, data, initial) \ amiCrc32RGet(amiCrc.m_table, (length), (data), (initial)) diff --git a/src/micetools/lib/ami/amiMd5.c b/src/micetools/lib/ami/amiMd5.c new file mode 100644 index 0000000..b8c5f78 --- /dev/null +++ b/src/micetools/lib/ami/amiMd5.c @@ -0,0 +1,129 @@ +#include "amiMd5.h" + +#include + +static unsigned char rtable[4][4] = { + { 7, 12, 17, 22 }, + { 5, 9, 14, 20 }, + { 4, 11, 16, 23 }, + { 6, 10, 15, 21 }, +}; +static unsigned int md5_init[4] = { + 0x67452301, + 0xefcdab89, + 0x98badcfe, + 0x10325476, +}; +static unsigned int sines[] = { + 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee, 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501, + 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be, 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821, + 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa, 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8, + 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed, 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a, + 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c, 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70, + 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05, 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665, + 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039, 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1, + 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1, 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391, +}; + +#define ROT_LEFT(x, n) (((x) << (n)) | ((x >> (32 - (n))))) +#define F(x, y, z) (((x) & (y)) | ((~x) & (z))) +#define G(x, y, z) (((x) & (z)) | ((y) & (~z))) +#define H(x, y, z) ((x) ^ (y) ^ (z)) +#define I(x, y, z) ((y) ^ ((x) | (~z))) + +void amiMd5Init(AmiMd5 *md5) { + ZeroMemory(md5, sizeof *md5); + md5->m_state[0] = md5_init[0]; + md5->m_state[1] = md5_init[1]; + md5->m_state[2] = md5_init[2]; + md5->m_state[3] = md5_init[3]; +} + +void amiMd5Transform(AmiMd5 *md5, unsigned char *buffer) { + unsigned int a = md5->m_state[0]; + unsigned int b = md5->m_state[1]; + unsigned int c = md5->m_state[2]; + unsigned int d = md5->m_state[3]; + + unsigned int *uBuffer = (unsigned int *)buffer; + + unsigned int tmp, i, j; + + for (i = 0; i < 16; i++) { + tmp = a + F(b, c, d) + uBuffer[i] + sines[i]; + tmp = ROT_LEFT(tmp, rtable[0][i & 3]) + b; + a = d; + d = c; + c = b; + b = tmp; + } + + for (i = 0, j = 1; i < 16; i++, j += 5) { + tmp = a + G(b, c, d) + uBuffer[j & 15] + sines[i + 16]; + tmp = ROT_LEFT(tmp, rtable[1][i & 3]) + b; + a = d; + d = c; + c = b; + b = tmp; + } + + for (i = 0, j = 5; i < 16; i++, j += 3) { + tmp = a + H(b, c, d) + uBuffer[j & 15] + sines[i + 32]; + tmp = ROT_LEFT(tmp, rtable[2][i & 3]) + b; + a = d; + d = c; + c = b; + b = tmp; + } + + for (i = 0, j = 0; i < 16; i++, j += 7) { + tmp = a + I(b, c, d) + uBuffer[j & 15] + sines[i + 48]; + tmp = ROT_LEFT(tmp, rtable[3][i & 3]) + b; + a = d; + d = c; + c = b; + b = tmp; + } + + md5->m_state[0] += a; + md5->m_state[1] += b; + md5->m_state[2] += c; + md5->m_state[3] += d; +} +void amiMd5Update(AmiMd5 *md5, unsigned int nBytes, unsigned char *buffer) { + int buflen = md5->m_length & 63; + md5->m_length += nBytes; + + if (buflen + nBytes < 64) { + memcpy(md5->m_buffer + buflen, buffer, nBytes); + buflen += nBytes; + return; + } + + memcpy(md5->m_buffer + buflen, buffer, 64 - buflen); + amiMd5Transform(md5, md5->m_buffer); + buffer += 64 - buflen; + nBytes -= 64 - buflen; + while (nBytes >= 64) { + amiMd5Transform(md5, buffer); + buffer += 64; + nBytes -= 64; + } + memcpy(md5->m_buffer, buffer, nBytes); +} + +void amiMd5Finalise(AmiMd5 *md5) { + int buflen = md5->m_length & 63; + md5->m_buffer[buflen++] = 0x80; + memset(md5->m_buffer + buflen, 0, 64 - buflen); + if (buflen > 56) { + amiMd5Transform(md5, md5->m_buffer); + memset(md5->m_buffer, 0, 64); + buflen = 0; + } + + *(unsigned int *)(md5->m_buffer + 56) = 8 * md5->m_length; + *(unsigned int *)(md5->m_buffer + 60) = 0; + amiMd5Transform(md5, md5->m_buffer); + for (int i = 0; i < 4; i++) ((unsigned int *)md5->m_digest)[i] = md5->m_state[i]; +} diff --git a/src/micetools/lib/ami/amiMd5.h b/src/micetools/lib/ami/amiMd5.h index e69de29..3f019bb 100644 --- a/src/micetools/lib/ami/amiMd5.h +++ b/src/micetools/lib/ami/amiMd5.h @@ -0,0 +1,15 @@ +typedef struct { + unsigned int m_state[4]; + unsigned int m_offset; + unsigned int m_block; + unsigned int m_blockOffset; + + unsigned int m_length; + + unsigned char m_buffer[256]; + unsigned char m_digest[16]; +} AmiMd5; + +void amiMd5Init(AmiMd5 *md5); +void amiMd5Update(AmiMd5 *md5, unsigned int nBytes, unsigned char *buffer); +void amiMd5Finalise(AmiMd5 *md5); diff --git a/src/micetools/lib/ami/amiTimer.c b/src/micetools/lib/ami/amiTimer.c index 11e4015..03b1396 100644 --- a/src/micetools/lib/ami/amiTimer.c +++ b/src/micetools/lib/ami/amiTimer.c @@ -23,7 +23,7 @@ amtime_t* amiTimerGet(amtime_t* time) { int amiTimerDiffSec(amtime_t* start, amtime_t* now) { if (start == NULL || now == NULL) return -1; - return (now->seconds - (now->microseconds < start->microseconds)) - start->seconds; + return (start->seconds - (start->microseconds < now->microseconds)) - now->seconds; } int amiTimerDiffMsec(amtime_t* start, amtime_t* now) { diff --git a/src/micetools/lib/ami/meson.build b/src/micetools/lib/ami/meson.build index 175e7c7..3ed0b16 100644 --- a/src/micetools/lib/ami/meson.build +++ b/src/micetools/lib/ami/meson.build @@ -18,3 +18,10 @@ amiDebug = static_library( 'amiDebug.c', ], ) + +amiMd5 = static_library( + 'amiMd5', + sources: [ + 'amiMd5.c', + ], +) diff --git a/src/micetools/lib/dmi/dmi.c b/src/micetools/lib/dmi/dmi.c index 59d204f..829edd0 100644 --- a/src/micetools/lib/dmi/dmi.c +++ b/src/micetools/lib/dmi/dmi.c @@ -6,7 +6,7 @@ LPBYTE dmi_table = NULL; WORD dmi_size = 0; WORD _dmi_max = 0; -DMI_BIOS deafult_dmi_bios = { +DMI_BIOS default_dmi_bios = { .Head.Type = DmiTypeBios, .Head.Length = 0x12, .Head.Handle = 0x0000, @@ -32,7 +32,7 @@ DMI_SYSTEM default_dmi_system = { .Serial = 0x04, // "To Be Filled By O.E.M." }; -DMI_STRING deafult_dmi_string = { +DMI_STRING default_dmi_string = { .Head.Type = DmiTypeString, .Head.Length = 0x05, .Head.Handle = 0x0002, @@ -80,7 +80,7 @@ static void dmi_append_with_strings(void* data, WORD size, int num_strings, ...) void dmi_build_default() { dmi_init(); - dmi_append_with_strings(&deafult_dmi_bios, sizeof deafult_dmi_bios, 3, + dmi_append_with_strings(&default_dmi_bios, sizeof default_dmi_bios, 3, "American Megatrends Inc.", "080015 ", "07/28/2011"); // Platform AAM: Board type one of "Supermicro"(=1) or "Advantech"(=2) @@ -89,9 +89,9 @@ void dmi_build_default() { "To Be Filled By O.E.M.", "To Be Filled By O.E.M.", "To Be Filled By O.E.M."); - deafult_dmi_string.NoStrings = 5; + default_dmi_string.NoStrings = 5; - dmi_append_with_strings(&deafult_dmi_string, sizeof deafult_dmi_string, + dmi_append_with_strings(&default_dmi_string, sizeof default_dmi_string, // OEM strings: // 0: ?? // 1: ?? diff --git a/src/micetools/lib/libpcp/pcpp.c b/src/micetools/lib/libpcp/pcpp.c index 9ed4846..277c421 100644 --- a/src/micetools/lib/libpcp/pcpp.c +++ b/src/micetools/lib/libpcp/pcpp.c @@ -1025,7 +1025,6 @@ e_pcpp_t pcppSendRequestMain(pcpp_t* stream, undefined4 param_2, timeout_t timeo e_pcpp_t pcppRecvBinary(pcpp_t* stream, unsigned char* recv_buf, size_t buf_len, uint param_4) { size_t* psVar1; - char** send_buf; int iVar2; e_pcpt_t eVar3; e_pcpp_t eVar4; @@ -1097,14 +1096,14 @@ e_pcpp_t pcppRecvBinary(pcpp_t* stream, unsigned char* recv_buf, size_t buf_len, stream->last_active = _amTimeMs(local_10); if (stream->recv_binary_buf_len < stream->field_0x1fc || stream->recv_binary_buf_len == stream->field_0x1fc) { - send_buf = (char**)&stream->send_buf; + unsigned char* send_buf = (unsigned char*)stream->send_buf; psVar1 = &stream->send_buf_len; stream->state = pcpp_state_send_binary_ack; - *send_buf[0] = PCP_CHAR_BINACK; + send_buf[0] = PCP_CHAR_BINACK; *psVar1 = 1; iVar2 = pcppGetBlockingTime(stream->field_0x20c, param_4, stream, _amTimeMs(now), &recvb_local); - eVar3 = pcptSend(&stream->sock, (unsigned char*)*send_buf, psVar1, stream->field_0x208, + eVar3 = pcptSend(&stream->sock, send_buf, psVar1, stream->field_0x208, recvb_local); eVar4 = _errT2P(eVar3); stream->err = eVar4; @@ -1126,7 +1125,7 @@ e_pcpp_t pcppRecvBinary(pcpp_t* stream, unsigned char* recv_buf, size_t buf_len, *psVar1 = PCP_SEND_BUF_MAX; ZERO(stream->send_buf); eVar3 = - pcptRecv(&stream->data_sock, (unsigned char*)*send_buf, psVar1, recvb_local); + pcptRecv(&stream->data_sock, send_buf, psVar1, recvb_local); eVar4 = _errT2P(eVar3); stream->err = eVar4; if ((iVar2 != 0) && (eVar4 == e_pcpp_to)) { diff --git a/src/micetools/lib/mice/config.c b/src/micetools/lib/mice/config.c index 2806a58..6510acf 100644 --- a/src/micetools/lib/mice/config.c +++ b/src/micetools/lib/mice/config.c @@ -93,6 +93,7 @@ int handler(void *user, const char *section, const char *name, const char *value #define CFG_int(s, n, default, comment) \ else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) { \ cfg->s.n = strtol(value, &end, 10); \ + printf("%s.%s:%d\n", #s, #n, cfg->s.n);\ if (end == value || *end != '\0' || errno == ERANGE) cfg->s.n = default; \ } #define CFG_hex(s, n, precision, default, comment) \ diff --git a/src/micetools/lib/mice/config.def b/src/micetools/lib/mice/config.def index becf652..1fa31de 100644 --- a/src/micetools/lib/mice/config.def +++ b/src/micetools/lib/mice/config.def @@ -34,8 +34,8 @@ CFG_str(sysconf, serial, "AASE-01A65646203", "") ENDSECTION(sysconf) SECTION(window, "Game window positioning settings") -CFG_bool(window, windowed, false, "Force games into windowed mode") -CFG_bool(window, borderless, true, "Should windowed games run borderless") +CFG_bool(window, windowed, true, "Force games into windowed mode") +CFG_bool(window, borderless, false, "Should windowed games run borderless") CFG_int(window, adaptor, 0, "Display adaptor to use") CFG_bool(window, centre, true, "Centre the window. X and Y are used otherwise") CFG_int(window, x, 0, "Window position X") diff --git a/src/micetools/lib/mice/exe.c b/src/micetools/lib/mice/exe.c index cdda1d6..9018197 100644 --- a/src/micetools/lib/mice/exe.c +++ b/src/micetools/lib/mice/exe.c @@ -72,7 +72,7 @@ bool inject_dll(HANDLE process, LPCSTR inject) { } HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wait, DWORD delay, - LPCSTR extra_injections) { + LPCSTR extra_injections, DWORD flags) { STARTUPINFOA startupInfo; PROCESS_INFORMATION processInformation = { 0 }; @@ -98,7 +98,8 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wa } // Start the binary - if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, + flags |= CREATE_SUSPENDED; + if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, flags, NULL, NULL, &startupInfo, &processInformation)) { fprintf(stderr, "Fatal: CreateProcessA failed: %03x\n", GetLastError()); goto abort; diff --git a/src/micetools/lib/mice/exe.h b/src/micetools/lib/mice/exe.h index 07650b1..f239a03 100644 --- a/src/micetools/lib/mice/exe.h +++ b/src/micetools/lib/mice/exe.h @@ -3,7 +3,7 @@ #include HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL debug_wait, DWORD delay, - LPCSTR extra_injections); + LPCSTR extra_injections, DWORD flags); #ifndef MICELIB #ifdef MICE_WIN32 diff --git a/src/micetools/lib/util/hex.c b/src/micetools/lib/util/hex.c index 08ce644..8cdc6f5 100644 --- a/src/micetools/lib/util/hex.c +++ b/src/micetools/lib/util/hex.c @@ -78,20 +78,18 @@ int hex_to_bin(char *hex, unsigned char *bin, int hex_len) { return 1; } void bin_to_hex(char *hex, unsigned char *bin, int nbytes) { - int hex_len = nbytes * 2; - while (nbytes--) { - if (bin[0] & 0x0f > 0x09) - hex[--hex_len] = (bin[0] & 0x0f) + 'a'; + for (int i = 0; i < nbytes; i++) { + if ((bin[i] & 0xf0) > 0x90) + hex[i * 2] = ((bin[i] & 0xf0) >> 4) - 0x0a + 'a'; else - hex[--hex_len] = (bin[0] & 0x0f) + '0'; + hex[i * 2] = ((bin[i] & 0xf0) >> 4) + '0'; - if (bin[0] & 0xf0 > 0x90) - hex[--hex_len] = ((bin[0] & 0xf0) >> 4) + 'a'; + if ((bin[i] & 0x0f) > 0x09) + hex[i * 2 + 1] = (bin[i] & 0x0f) - 0x0a + 'a'; else - hex[--hex_len] = ((bin[0] & 0xf0) >> 4) + '0'; - - bin++; + hex[i * 2 + 1] = (bin[i] & 0x0f) + '0'; } + hex[nbytes * 2] = '\0'; } int hex_to_int(unsigned int *value, char *hex) { diff --git a/src/micetools/micemaster/callbacks/foreground.c b/src/micetools/micemaster/callbacks/foreground.c index fbbe63b..596e691 100644 --- a/src/micetools/micemaster/callbacks/foreground.c +++ b/src/micetools/micemaster/callbacks/foreground.c @@ -165,8 +165,8 @@ void mxmPcpActiveFgprocess(pcpa_t* stream, MX_MASTER* mxMaster) { pcpaSetSendPacket(stream, MXM_FG_ACTIVE, "1"); mxMaster->m_current = mxMaster->m_next; mxMaster->m_next = 0; - mxMaster->m_field5_0x14 = 1; - mxMaster->m_field4_0x10 = 1; + mxMaster->m_changeIsSpawn = 1; + mxMaster->m_processStateChange = true; return; } @@ -179,19 +179,19 @@ void mxmPcpActiveFgprocess(pcpa_t* stream, MX_MASTER* mxMaster) { if (mxMaster->m_next != 0) { mxMaster->m_current = mxMaster->m_next; mxMaster->m_next = 0; - mxMaster->m_field4_0x10 = 1; + mxMaster->m_processStateChange = true; return; } mxMaster->m_fault = 1; mxMaster->m_current = 1; - mxMaster->m_field4_0x10 = 1; + mxMaster->m_processStateChange = true; return; } mxMaster->m_next = 0; mxMaster->m_current = 0; - mxMaster->m_field4_0x10 = 1; + mxMaster->m_processStateChange = true; return; } else { pcpaSetSendPacket(stream, MXM_FG_ACTIVE, mxMaster->m_current == 0 ? "0" : "1"); diff --git a/src/micetools/micemaster/callbacks/logs.c b/src/micetools/micemaster/callbacks/logs.c index e8e1801..63342db 100644 --- a/src/micetools/micemaster/callbacks/logs.c +++ b/src/micetools/micemaster/callbacks/logs.c @@ -1,145 +1,13 @@ -#include -#include - -#include "../../lib/am/amInstall.h" #include "../mxm.h" -#include "mxmEventLog.h" -bool mxmEventLogAccessGetMainStorageDeviceNum(int* devNum) { - if (devNum == NULL) { - amiDebugLog("Error : Invalid Argument"); - return false; - } - - char windir[256]; - if (!GetSystemWindowsDirectoryA(windir, sizeof windir)) { - amiDebugLog("Error : GetSystemWindowsDirectoryA error"); - *devNum = -1; - return false; - } - - char windirDos[256]; - sprintf_s(windirDos, sizeof windirDos, "\\\\.\\%c:", windir[0]); - HANDLE hDevice = - CreateFileA(windirDos, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL); - if (hDevice == INVALID_HANDLE_VALUE) { - amiDebugLog("Error : CreateFile error ErrorNum = %d", GetLastError()); - *devNum = -1; - return false; - } - - STORAGE_DEVICE_NUMBER ioctlBuf; - DWORD bytesReturned; - if (!DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &ioctlBuf, - sizeof ioctlBuf, &bytesReturned, NULL)) { - amiDebugLog("Error : DeviceIoControl error ErrorNum = %d", GetLastError()); - CloseHandle(hDevice); - *devNum = -1; - return false; - } - - CloseHandle(hDevice); - *devNum = ioctlBuf.DeviceNumber; - return true; -} - -#define LOG_OFFSET (2047 * 512) - -bool mxmEventLogAccessEraseEventLogData(int deviceNum, unsigned long long address) { - char drivePath[MAX_PATH]; - ZeroMemory(drivePath, sizeof drivePath); - sprintf_s(drivePath, sizeof drivePath, "\\\\.\\PhysicalDrive%d", deviceNum); - - HANDLE hFile = - CreateFileA(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL); - if (hFile == INVALID_HANDLE_VALUE) { - amiDebugLog("Error : CreateFile error"); - return false; - } - - char logBuffer[512]; - ZeroMemory(logBuffer, sizeof logBuffer); - - LARGE_INTEGER writeAddress; - writeAddress.QuadPart = address + LOG_OFFSET; - if (!SetFilePointerEx(hFile, writeAddress, NULL, 0)) { - CloseHandle(hFile); - amiDebugLog("SetFilePointerEx error"); - return false; - } - - DWORD bytesWritten; - if (!WriteFile(hFile, logBuffer, sizeof logBuffer, &bytesWritten, NULL)) { - CloseHandle(hFile); - amiDebugLog("WriteFile error %d", GetLastError()); - return false; - } - if (bytesWritten != sizeof logBuffer) { - CloseHandle(hFile); - amiDebugLog("Wriete Size Error"); - return false; - } - CloseHandle(hFile); - return true; -} - -bool mxmEventLogAccessLoadEpbr(AM_INSTALL_BOOT_RECORD* bootRecord) { - amtime_t start, now; - - if (amInstallInit() != AM_INSTALL_STATUS_OK) { - amiDebugLog("Error : amInstallInit."); - return false; - } - amiTimerGet(&start); - while (1) { - AM_INSTALL_STATUS err = amInstallGetBr(bootRecord, 0); - if (!((err == AM_INSTALL_STATUS_ERR_REQUEST) || - (err == AM_INSTALL_STATUS_ERR_UPDATE_STATUS) || - (err == AM_INSTALL_STATUS_ERR_GET_SEMAPHORE) || - (err == AM_INSTALL_STATUS_ERR_FORMAT) || (err == AM_INSTALL_STATUS_OK) || - (err == AM_INSTALL_STATUS_BUSY))) { - amiDebugLog("Error : amInstallGetBr error."); - amInstallExit(); - return false; - } - - amiTimerGet(&now); - if (amiTimerDiffSec(&start, &now) > 30) { - amiDebugLog("Error : amInstallGetBr time out error."); - amInstallExit(); - return false; - } - - if (err == AM_INSTALL_STATUS_OK) { - if (amInstallExit() == AM_INSTALL_STATUS_OK) return true; - - amiDebugLog("Error : amInstallExit."); - return false; - } - } -} - -bool mxmEventLogEraseLog() { - AM_INSTALL_BOOT_RECORD br; - ZeroMemory(&br, sizeof br); - int devNum = 0; - if (!mxmEventLogAccessGetMainStorageDeviceNum(&devNum)) return false; - if (!mxmEventLogAccessLoadEpbr(&br)) return false; - if (!mxmEventLogAccessEraseEventLogData(devNum, br.os)) return false; - return true; -} - -void mxmPcpLogAvailable(pcpa_t* stream, MX_MASTER* mxMaster) { - pcpaSetSendPacket(stream, MXM_LOG_AVAILALBE, mxMaster->m_loggingAvailable ? "1" : "0"); - - char* command = pcpaGetCommand(stream, MXM_LOG_AVAILALBE); +void mxmPcpLogAvailable(pcpa_t *stream, MX_MASTER *mxMaster) { + char *command = pcpaGetCommand(stream, MXM_LOG_AVAILALBE); if (command == NULL) { amiDebugLog("Error : Command is not set up."); pcpaSetSendPacket(stream, MXM_LOG_AVAILALBE, "?"); return; } + bool metadataChanged = false; if (strcmp(command, "?") != 0) { if (strcmp(command, "1") == 0) { @@ -176,7 +44,7 @@ void mxmPcpLogAvailable(pcpa_t* stream, MX_MASTER* mxMaster) { } char buffer[256]; - pcpaSetSendPacket(stream, MXM_LOG_AVAILALBE, mxMaster->m_loggingAvailable ? "1" : 0); + pcpaSetSendPacket(stream, MXM_LOG_AVAILALBE, mxMaster->m_loggingAvailable ? "1" : "0"); _itoa_s(mxMaster->m_backupCount, buffer, sizeof buffer, 10); pcpaAddSendPacket(stream, "backup_count", buffer); @@ -186,14 +54,99 @@ void mxmPcpLogAvailable(pcpa_t* stream, MX_MASTER* mxMaster) { pcpaAddSendPacket(stream, "interval", buffer); } -void mxmPcpOutputLog(pcpa_t* stream, MX_MASTER* mxMaster) { - // Only allowed: 0, 1, 2 - pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "0"); - pcpaAddSendPacket(stream, "path", ""); +void mxmPcpOutputLog(pcpa_t *stream, MX_MASTER *mxMaster) { + char logName[12]; + char path[260]; + ZeroMemory(path, sizeof path); + ZeroMemory(logName, sizeof logName); + + if (stream == NULL || mxMaster == NULL) { + amiDebugLog("Error : CallbackFuncOutputLog Invalid error"); + return; + } + + char *command = pcpaGetCommand(stream, pcpaGetKeyword(stream, 0)); + char *sType = pcpaGetCommand(stream, "type"); + + if (command == NULL || sType == NULL) { + amiDebugLog("Error : Command error"); + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "?") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL"); + if (pcpaAddSendPacket(stream, "code", "1") == NULL) + amiDebugLog("Error : pcpaAddSendPacket return NULL"); + return; + } + if (strlen(sType) == 0) { + amiDebugLog("Error : Command length error"); + + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "?") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL"); + + if (pcpaAddSendPacket(stream, "code", "1") == NULL) + amiDebugLog("Error : pcpaAddSendPacket return NULL"); + return; + } + + if (strcmp(command, "0") != 0) { + amiDebugLog("Error : Command type error"); + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "?") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL\n"); + if (pcpaAddSendPacket(stream, "code", "1") == NULL) + amiDebugLog("Error : pcpaAddSendPacket return NULL"); + return; + } + + if (strcmp(sType, "0") != 0 && strcmp(sType, "1") != 0) { + amiDebugLog("Error : Type error"); + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "?") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL\n"); + if (pcpaAddSendPacket(stream, "code", "1") == NULL) + amiDebugLog("Error : pcpaAddSendPacket return NULL"); + return; + } + + char *endPtr; + int nType = strtoul(sType, &endPtr, 10); + + bool logValid = false; + if (!mxmEventLogCheckLog(&logValid)) { + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "1") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL"); + return; + } + if (!logValid) { + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "2") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL"); + return; + } + + if (strcmp(sType, "0") == 0) { + strcpy_s(logName, sizeof logName, "application"); + } else if (strcmp(sType, "1") == 0) { + strcpy_s(logName, sizeof logName, "system"); + } + + if (!mxmEventLogGetTempPath(logName, path)) { + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "1") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL"); + return; + } + + if (!mxmEventLogAccessBackup(path, nType)) { + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "1") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL"); + return; + } + + if (pcpaSetSendPacket(stream, MXM_OUTPUT_LOG, "0") == NULL) + amiDebugLog("Error : pcpaSetSendPacket return NULL"); + + if (pcpaAddSendPacket(stream, "path", path) == NULL) + amiDebugLog("Error : pcpaAddSendPacket return NULL"); } -void mxmPcpEraseLog(pcpa_t* stream, MX_MASTER* mxMaster) { - char* command = pcpaGetCommand(stream, MXM_ERASE_LOG); +void mxmPcpEraseLog(pcpa_t *stream, MX_MASTER *mxMaster) { + char *command = pcpaGetCommand(stream, MXM_ERASE_LOG); if (command == NULL) { amiDebugLog("Error : Command error"); pcpaSetSendPacket(stream, MXM_ERASE_LOG, "1"); diff --git a/src/micetools/micemaster/main.c b/src/micetools/micemaster/main.c index d5d35b2..331ee53 100644 --- a/src/micetools/micemaster/main.c +++ b/src/micetools/micemaster/main.c @@ -1,22 +1,9 @@ #include #include "../lib/am/amInstall.h" +#include "../lib/ami/amiMd5.h" #include "mxm.h" -void mxMasterMakeCopy(char* filename) { - char dest[256]; - char src[256]; - - sprintf_s(src, sizeof src, "%s%s", Config.dir.system, filename); - sprintf_s(dest, sizeof dest, "%s%s", Config.dir.execute, filename); - - if (!PathFileExistsA(src)) { - amiDebugLog("Error copy %s not exist", src); - return; - } - if (!PathFileExistsA(dest)) CopyFileA(src, dest, 0); -} - bool mxMasterInitPcp(MX_MASTER* mxMaster) { if (mxMaster->m_pcpaHasInit) return true; @@ -55,27 +42,13 @@ bool mxMasterInitPcp(MX_MASTER* mxMaster) { return true; } -bool mxMasterOpen(MX_MASTER* mxMaster) { - e_pcpa_t err = pcpaOpenServerWithBinary(&mxMaster->m_pcp, mxMaster->m_openMode, - mxMaster->m_controlPort, mxMaster->m_dataPort, 60000); - if (err != e_pcpa_ok && err != e_pcpa_to) { - amiDebugLog("pcpaOpenServerWithBinary Error. Code %d", err); - return false; - } - - amiDebugLog("Listening on %s:%d (:%d)", - mxMaster->m_openMode == OPEN_MODE_GLOBAL ? "0.0.0.0" : "127.0.0.1", - mxMaster->m_controlPort, mxMaster->m_dataPort); - return true; -} - bool mxMasterInit(MX_MASTER* mxMaster) { mxMaster->m_develop = 0; mxMaster->m_fault = 0; mxMaster->m_current = 0; mxMaster->m_next = 0; - mxMaster->m_field5_0x14 = 0; - mxMaster->m_field4_0x10 = 0; + mxMaster->m_changeIsSpawn = false; + mxMaster->m_processStateChange = false; mxMaster->m_backupMetadataChanged = false; mxMaster->m_loggingAvailable = false; mxMaster->m_backupCount = 0; @@ -88,14 +61,14 @@ bool mxMasterInit(MX_MASTER* mxMaster) { mxMaster->m_binaryMessageLen = 0; ZeroMemory(mxMaster->m_binaryMessage, sizeof mxMaster->m_binaryMessage); - mxMasterMakeCopy("mxsegaboot.exe"); - mxMasterMakeCopy("mxauthdisc.exe"); - mxMasterMakeCopy("mxshellexecute.exe"); - mxMasterMakeCopy("ringmaster_pub.pem"); - mxMasterMakeCopy("develop_regset.txt"); - mxMasterMakeCopy("lockid.txt"); - mxMasterMakeCopy("d3dref9.dll"); - mxMasterMakeCopy("mxsegaboot_2052.dll"); + mxmCopySystemFile("mxsegaboot.exe"); + mxmCopySystemFile("mxauthdisc.exe"); + mxmCopySystemFile("mxshellexecute.exe"); + mxmCopySystemFile("ringmaster_pub.pem"); + mxmCopySystemFile("develop_regset.txt"); + mxmCopySystemFile("lockid.txt"); + mxmCopySystemFile("d3dref9.dll"); + mxmCopySystemFile("mxsegaboot_2052.dll"); return mxMasterInitPcp(mxMaster); } @@ -246,10 +219,10 @@ void mxMasterSysProcessesStart(MX_MASTER* mxMaster) { Sleep(2000); if (mxMasterLoadKeychipInfo(mxMaster)) { - mxMaster->m_current = 1; - mxMaster->m_kcReady = 0; + mxMaster->m_kcReady = true; } else { - mxMaster->m_kcReady = 1; + mxMaster->m_current = 1; + mxMaster->m_kcReady = false; } char mxinstaller[128]; @@ -275,7 +248,7 @@ void mxMasterFdcProcessesStart(MX_MASTER* mxMaster) { strcpy_s(startup[1], sizeof startup[1], Config.binary.mxgfetcher); strcpy_s(startup[2], sizeof startup[2], Config.binary.mxgdeliver); - if (mxMaster->m_kcReady != 0) { + if (mxMaster->m_kcReady) { char* format; char* networkAddr = inet_ntoa(mxMaster->m_networkAddr); @@ -353,19 +326,18 @@ void mxMasterMainLoop(MX_MASTER* mxMaster) { mxMaster->m_backupCount = 1; mxMaster->m_clearCount = 100; mxMaster->m_interval = 60; - // if (mxEventLog_0044e5d8.init == 0) { - // mxEventLog_0044e5d8.backup_count = 1; - // mxEventLog_0044e5d8.clear_count = 100; - // mxEventLog_0044e5d8.interval = 60; - // mxEventLog_0044e5d8.field1_0x4 = 0; - // mxEventLog_0044e5d8.field2_0x8 = 0; - // _memset(mxEventLog_0044e5d8.field6_0x18, 0, 0x330); - // mxEventLog_0044e5d8.init = 1; - // uVar5 = extraout_ECX; - // param_2 = extraout_EDX; - // } - e_pcpa_t err; + if (!MxmEventLog.m_init) { + MxmEventLog.m_backupCount = 1; + MxmEventLog.m_clearCount = 100; + MxmEventLog.m_interval = 60; + MxmEventLog.m_logDriveFound = false; + MxmEventLog.m_filenamesSet = false; + ZeroMemory(MxmEventLog.m_desinations, sizeof MxmEventLog.m_desinations); + MxmEventLog.m_init = true; + } + + e_pcpa_t err; do { err = pcpaOpenServerWithBinary(&mxMaster->m_pcp, mxMaster->m_openMode, mxMaster->m_controlPort, mxMaster->m_dataPort, 60000); @@ -378,13 +350,12 @@ void mxMasterMainLoop(MX_MASTER* mxMaster) { amiDebugLog("Error : Not Open Server. Code %d", err); } } while (err != e_pcpa_ok); - mxMaster->m_field23_0x3f4 = 1; + mxMaster->m_serverOpen = true; appLauncherAppInfo_t appInfo[3]; while (1) { err = pcpaServer(&mxMaster->m_pcp, 16); - if (err != e_pcpa_ok && err != e_pcpa_to && err != e_pcpa_closed) { if (mxMaster->m_pcpaHasInit) { pcpaClose(&mxMaster->m_pcp); @@ -407,22 +378,19 @@ void mxMasterMainLoop(MX_MASTER* mxMaster) { } appLauncher_t* appLauncher; - if (mxMaster->m_field4_0x10 != 0) { + if (mxMaster->m_processStateChange) { appLauncher = mxMaster->m_appLauncher; - if (appLauncher->m_createdThread) goto code_r0x004056a9; - goto LAB_004056db; - } + if (appLauncher->m_createdThread) { + if (WaitForSingleObject(appLauncher->m_hThread, 0) != WAIT_TIMEOUT) { + CloseHandle(appLauncher->m_hThread); + appLauncher->m_hThread = NULL; + appLauncher->m_createdThread = false; + } + } - goto LAB_0040574e; - code_r0x004056a9: - if (WaitForSingleObject(appLauncher->m_hThread, 0) != WAIT_TIMEOUT) { - CloseHandle(appLauncher->m_hThread); - appLauncher->m_hThread = NULL; - appLauncher->m_createdThread = false; - LAB_004056db: - if (!mxMaster->m_develop || mxMaster->m_field5_0x14) { + if (!mxMaster->m_develop || mxMaster->m_changeIsSpawn) { appInfo[0].m_mode = mxMaster->m_current; - mxMaster->m_field5_0x14 = 0; + mxMaster->m_changeIsSpawn = 0; if (appInfo[0].m_mode == 2) { sprintf_s(appInfo[0].m_path, sizeof appInfo[0].m_path, "%s", mxMaster->m_nextPath); @@ -444,36 +412,24 @@ void mxMasterMainLoop(MX_MASTER* mxMaster) { } appLauncherCreateThread(appInfo, mxMaster->m_appLauncher); } - mxMaster->m_field4_0x10 = 0; - LAB_0040574e: - if (mxMaster->m_backupMetadataChanged) { - // dVar3 = mxMaster->m_clearCount; - // dVar4 = mxMaster->m_interval; - // if (mxEventLog_0044e5d8.init != 0) { - // mxEventLog_0044e5d8.backup_count = mxMaster->backup_count; - // mxEventLog_0044e5d8.clear_count = dVar3; - // mxEventLog_0044e5d8.interval = dVar4; - // } - mxMaster->m_backupMetadataChanged = false; + mxMaster->m_processStateChange = false; + } + + if (mxMaster->m_backupMetadataChanged) { + if (MxmEventLog.m_init) { + MxmEventLog.m_backupCount = mxMaster->m_backupCount; + MxmEventLog.m_clearCount = mxMaster->m_clearCount; + MxmEventLog.m_interval = mxMaster->m_interval; + } + mxMaster->m_backupMetadataChanged = false; + } + + if (MxmEventLog.m_init && MxmEventLog.m_filenamesSet) { + for (int i = 0; i < NUM_LOGS; i++) { + if (mxmBackupEventlog(i) != 0) break; } - // if ((mxEventLog_0044e5d8.init != 0) && (mxEventLog_0044e5d8.field2_0x8 != 0)) { - // iVar5 = 0; - // do { - // uVar6 = mxmBackupEventlog(dVar3, dVar4, iVar5); - // dVar4 = (dword)((ulonglong)uVar6 >> 0x20); - // if ((int)uVar6 != 0) break; - // iVar5 += 1; - // dVar3 = extraout_ECX_03; - // } while (iVar5 < 3); - // } } } - - // mxMaster->m_serverState = 2; - // while (1) { - // err = mxmPcpServer(mxMaster); - // if (err != e_pcpp_ok) amiDebugLog("Server tick: %d", err); - // } } int main() { @@ -485,10 +441,12 @@ int main() { if (GetConsoleMode(hConsole, &dwMode)) SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING); + // Start WSA WSADATA wsaData; int err = WSAStartup(2, &wsaData); if (err) return -1; + // Initialise mxm structures MX_MASTER* mxMaster = malloc(sizeof *mxMaster); if (mxMaster == NULL) { amiDebugLog("Unable to allocate MX_MASTER"); @@ -497,10 +455,10 @@ int main() { ZeroMemory(mxMaster, sizeof *mxMaster); appLauncher_t appLauncher; ZeroMemory(&appLauncher, sizeof appLauncher); - pcpaInitStream(&appLauncher.m_pcp); appLauncher.m_appInfo.m_appLauncher = &appLauncher; mxMaster->m_appLauncher = &appLauncher; + // Startup if (!mxMasterInit(mxMaster)) { amiDebugLog("Error mxMasterInit"); return -1; @@ -509,11 +467,6 @@ int main() { mxMaster->m_dataPort = 40101; mxMaster->m_openMode = OPEN_MODE_LOCAL; - // if (!mxMasterOpen(mxMaster)) { - // amiDebugLog("Error mxMasterOpen"); - // return -1; - // } - mxMasterSysProcessesStart(mxMaster); mxMasterFdcProcessesStart(mxMaster); mxMasterFirstFgProcessesStart(mxMaster); diff --git a/src/micetools/micemaster/meson.build b/src/micetools/micemaster/meson.build index 900ef2d..27938d1 100644 --- a/src/micetools/micemaster/meson.build +++ b/src/micetools/micemaster/meson.build @@ -19,6 +19,8 @@ executable( amiDebug, amDongle, amInstall, + amiMd5, + amiCrc, ], include_directories: incdir, dependencies: [], diff --git a/src/micetools/micemaster/mxm.c b/src/micetools/micemaster/mxm.c index b2221c4..f87fe2b 100644 --- a/src/micetools/micemaster/mxm.c +++ b/src/micetools/micemaster/mxm.c @@ -1,42 +1,105 @@ #include "mxm.h" +#include + #define TICK_MS 16 -void mxmBeforeBinaryCallback(pcpa_t* stream, MX_MASTER* mxMaster) { +void mxmBeforeBinaryCallback(pcpa_t *stream, MX_MASTER *mxMaster) { pcpaSetSendBinaryBuffer(stream, mxMaster->m_binaryMessage, mxMaster->m_binaryMessageLen); } -void mxmAfterBinaryCallback(pcpa_t* stream, MX_MASTER* mxMaster) { +void mxmAfterBinaryCallback(pcpa_t *stream, MX_MASTER *mxMaster) { mxMaster->m_binaryMessage[0] = '\0'; mxMaster->m_binaryMessageLen = 0; } -int mxmInit(MX_MASTER* mxMaster) { +void mxmCopySystemFile(char *filename) { + char dest[256]; + char src[256]; + sprintf_s(src, sizeof src, "%s%s", Config.dir.system, filename); + sprintf_s(dest, sizeof dest, "%s%s", Config.dir.execute, filename); + + if (!PathFileExistsA(src)) { + amiDebugLog("Error copy %s not exist", src); + return; + } + if (!PathFileExistsA(dest)) CopyFileA(src, dest, 0); } -e_pcpa_t mxmPcpStreamInit(MX_MASTER* mxMaster) { return 0; } +int mxmBackupEventlog(int destination) { + if (!MxmEventLog.m_logDriveFound) return 0; -e_pcpa_t mxmPcpServer(MX_MASTER* mxMaster) { - int err; - if (mxMaster->m_serverState == 1) { - err = mxmPcpStreamInit(mxMaster); - if (err == 0) { - mxMaster->m_serverState = 2; - return err; - } + char *logs[3] = { + "Application", + "Security", + "System", + }; + HANDLE hEventLog = OpenEventLogA(NULL, logs[destination]); + if (hEventLog == INVALID_HANDLE_VALUE || hEventLog == NULL) { + amiDebugLog("Error OpenEventLog(%d). Code %d", destination, GetLastError()); + return -2; + } + + DWORD numberOfRecords = 0; + if (!GetNumberOfEventLogRecords(hEventLog, &numberOfRecords)) { + printf("%d\n", hEventLog); + amiDebugLog("Error GetNumberOf-EventLogRecords(%d). Code %d", destination, GetLastError()); + CloseEventLog(hEventLog); + return -3; + } + + bool clearLog = false; + if (MxmEventLog.m_clearCount < numberOfRecords) { + clearLog = true; } else { - if (mxMaster->m_serverState != 2) { - return (mxMaster->m_serverState == 0) ? e_pcpa_cannot_open : e_pcpa_not_open; - } - err = pcpaServer(&mxMaster->m_pcp, TICK_MS); - if (err == e_pcpa_to || err == e_pcpa_closed) err = e_pcpa_ok; - - if (err) { - amiDebugLog("Error pcpaServer. Code %d", err); - pcpaClose(&mxMaster->m_pcp); - mxMaster->m_serverState = 1; + amtime_t now; + amiTimerGet(&now); + unsigned int deltaT = + amiTimerDiffSec(&(MxmEventLog.m_desinations[destination].m_last), &now); + if (deltaT < MxmEventLog.m_interval) { + printf("Waiting: %d/%d\n", deltaT, MxmEventLog.m_interval); + CloseEventLog(hEventLog); + return 0; } } - return err; -} + if (MxmEventLog.m_backupCount <= + (numberOfRecords - MxmEventLog.m_desinations[destination].m_numRecords)) { + char *lpFileName = MxmEventLog.m_desinations[destination].m_filename; + + HANDLE hFile = CreateFileA(lpFileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, + FILE_SUPPORTS_REPARSE_POINTS, NULL); + if (hFile != INVALID_HANDLE_VALUE) { + CloseHandle(hFile); + if (!DeleteFileA(lpFileName)) { + amiDebugLog("Error DeleteFileA() : %d", GetLastError()); + CloseEventLog(hEventLog); + return -4; + } + } + + if (!clearLog) { + if (!BackupEventLogA(hEventLog, lpFileName)) { + amiDebugLog("Error BackupEventLogA() : %d", GetLastError()); + CloseEventLog(hEventLog); + return -3; + } + MxmEventLog.m_desinations[destination].m_numRecords = numberOfRecords; + } else { + if (!ClearEventLogA(hEventLog, lpFileName)) { + amiDebugLog("Error ClearEventLog() : %d", GetLastError()); + CloseEventLog(hEventLog); + return -3; + } + MxmEventLog.m_desinations[destination].m_numRecords = 0; + char name[8]; + strncpy_s(name, sizeof name, lpFileName, 3); + mxmEventLogSetDestination(name, destination); + } + + amiTimerGet(&(MxmEventLog.m_desinations[destination].m_last)); + } + + CloseEventLog(hEventLog); + return 0; +} \ No newline at end of file diff --git a/src/micetools/micemaster/mxm.h b/src/micetools/micemaster/mxm.h index cb1e20f..684133e 100644 --- a/src/micetools/micemaster/mxm.h +++ b/src/micetools/micemaster/mxm.h @@ -5,6 +5,7 @@ #include "config.h" #include "lib/am/amDongle.h" #include "lib/libpcp/libpcp.h" +#include "mxmEventLog.h" typedef enum { mxMasterStartType_0 = 0, @@ -25,9 +26,8 @@ typedef struct MX_MASTER_ { ushort m_dataPort; int m_openMode; - // TODO: What are these? - unsigned int m_field4_0x10; - unsigned int m_field5_0x14; + bool m_processStateChange; + bool m_changeIsSpawn; bool m_backupMetadataChanged; unsigned int m_current; @@ -36,9 +36,9 @@ typedef struct MX_MASTER_ { bool m_fault; bool m_loggingAvailable; - bool m_backupCount; - bool m_clearCount; - bool m_interval; + unsigned int m_backupCount; + unsigned int m_clearCount; + unsigned int m_interval; char m_nextPath[128]; char m_gameId[8]; char m_platformId[8]; @@ -51,13 +51,8 @@ typedef struct MX_MASTER_ { int m_countGameTest; unsigned char m_binaryMessage[512]; size_t m_binaryMessageLen; - - // TODO: What is this? - unsigned int m_field23_0x3f4; - - int m_serverState; // TODO: Remove once unneeded - - unsigned int m_kcReady; + bool m_serverOpen; + bool m_kcReady; bool m_pcpaHasInit; appLauncher_t* m_appLauncher; pcpa_cb_table_t m_pcpCallbacks[11]; @@ -67,8 +62,5 @@ typedef struct MX_MASTER_ { void mxmBeforeBinaryCallback(pcpa_t* stream, MX_MASTER* mxMaster); void mxmAfterBinaryCallback(pcpa_t* stream, MX_MASTER* mxMaster); - -// void mxmBinaryCallback(pcpa_t* stream, MX_MASTER* mxMaster); -int mxmInit(MX_MASTER* mxMaster); -e_pcpa_t mxmPcpStreamInit(MX_MASTER* mxMaster); -e_pcpa_t mxmPcpServer(MX_MASTER* mxMaster); +void mxmCopySystemFile(char* filename); +int mxmBackupEventlog(int destination); diff --git a/src/micetools/micemaster/mxmEventLog.c b/src/micetools/micemaster/mxmEventLog.c index 034af1e..d11f3d2 100644 --- a/src/micetools/micemaster/mxmEventLog.c +++ b/src/micetools/micemaster/mxmEventLog.c @@ -1,12 +1,26 @@ #include "mxmEventLog.h" +#include #include +#include + +#include "../lib/ami/amiMd5.h" mxmEventLog_t MxmEventLog; #define LOG_DRIVE "L:\\" #define LOG_VOLUME "\\\\.\\L:\\" #define LOG_DRIVE_NAME "SEGA_AM_LOG" +#define TEMP_PATH "C:\\WINDOWS\\TEMP\\" + +bool mxmEventLogGetTempPath(char *name, char *buffer) { + SYSTEMTIME now; + + GetLocalTime(&now); + _snprintf_s(buffer, 0x104, 0xffffffff, "%s%s%04d%02d%02d%02d%02d%02d.evt", TEMP_PATH, name, + now.wYear, now.wMonth, now.wDay, now.wHour, now.wMinute, now.wSecond); + return true; +} bool mxmEventLogGetLogDrive(char *logPath) { char volumeName[264]; @@ -20,14 +34,14 @@ bool mxmEventLogGetLogDrive(char *logPath) { } int mxmEventLogSetDestination(char *name, unsigned int which) { - char *type_names[3]; + char *type_names[NUM_LOGS]; SYSTEMTIME now; type_names[0] = "application"; type_names[1] = "security"; type_names[2] = "system"; - if (name == NULL || which >= 3) return -1; + if (name == NULL || which >= NUM_LOGS) return -1; GetLocalTime(&now); _snprintf_s(MxmEventLog.m_desinations[which].m_filename, MAX_PATH, _TRUNCATE, @@ -43,7 +57,377 @@ void mxmEventLogInit(void) { name[0] = '\0'; MxmEventLog.m_logDriveFound = mxmEventLogGetLogDrive(name); if (MxmEventLog.m_logDriveFound) { - for (int i = 0; i < 3; i++) mxmEventLogSetDestination(name, i); + for (int i = 0; i < NUM_LOGS; i++) mxmEventLogSetDestination(name, i); MxmEventLog.m_filenamesSet = true; } } + +bool mxmEventLogEraseLog(void) { + AM_INSTALL_BOOT_RECORD br; + ZeroMemory(&br, sizeof br); + int devNum = 0; + if (!mxmEventLogAccessGetMainStorageDeviceNum(&devNum)) return false; + if (!mxmEventLogAccessLoadEpbr(&br)) return false; + if (!mxmEventLogAccessEraseEventLogData(devNum, br.os)) return false; + return true; +} + +bool mxmEventLogCheckLog(bool *valid) { + if (valid == NULL) return false; + + AM_INSTALL_BOOT_RECORD br; + ZeroMemory(&br, sizeof br); + int devNum = 0; + + if (!mxmEventLogAccessGetMainStorageDeviceNum(&devNum)) return false; + if (!mxmEventLogAccessLoadEpbr(&br)) return false; + if (!mxmEventLogAccessCheckEventLogData(devNum, br.os, valid)) return false; + return true; +} + +bool mxmEventLogAccessGetMainStorageDeviceNum(int *devNum) { + if (devNum == NULL) { + amiDebugLog("Error : Invalid Argument"); + return false; + } + + char windir[256]; + if (!GetSystemWindowsDirectoryA(windir, sizeof windir)) { + amiDebugLog("Error : GetSystemWindowsDirectoryA error"); + *devNum = -1; + return false; + } + + char windirDos[256]; + sprintf_s(windirDos, sizeof windirDos, "\\\\.\\%c:", windir[0]); + HANDLE hDevice = + CreateFileA(windirDos, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL); + if (hDevice == INVALID_HANDLE_VALUE) { + amiDebugLog("Error : CreateFile error ErrorNum = %d", GetLastError()); + *devNum = -1; + return false; + } + + STORAGE_DEVICE_NUMBER ioctlBuf; + DWORD bytesReturned; + if (!DeviceIoControl(hDevice, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &ioctlBuf, + sizeof ioctlBuf, &bytesReturned, NULL)) { + amiDebugLog("Error : DeviceIoControl error ErrorNum = %d", GetLastError()); + CloseHandle(hDevice); + *devNum = -1; + return false; + } + + CloseHandle(hDevice); + *devNum = ioctlBuf.DeviceNumber; + return true; +} + +bool mxmEventLogAccessEraseEventLogData(int deviceNum, unsigned long long address) { + char drivePath[MAX_PATH]; + ZeroMemory(drivePath, sizeof drivePath); + sprintf_s(drivePath, sizeof drivePath, "\\\\.\\PhysicalDrive%d", deviceNum); + + HANDLE hFile = + CreateFileA(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + amiDebugLog("Error : CreateFile error"); + return false; + } + + char logBuffer[512]; + ZeroMemory(logBuffer, sizeof logBuffer); + + LARGE_INTEGER writeAddress; + writeAddress.QuadPart = address + LOG_OFFSET; + if (!SetFilePointerEx(hFile, writeAddress, NULL, FILE_BEGIN)) { + CloseHandle(hFile); + amiDebugLog("SetFilePointerEx error"); + return false; + } + + DWORD bytesWritten; + if (!WriteFile(hFile, logBuffer, sizeof logBuffer, &bytesWritten, NULL)) { + CloseHandle(hFile); + amiDebugLog("WriteFile error %d", GetLastError()); + return false; + } + if (bytesWritten != sizeof logBuffer) { + CloseHandle(hFile); + amiDebugLog("Wriete Size Error"); + return false; + } + CloseHandle(hFile); + return true; +} + +bool mxmEventLogAccessCheckEventLogData(int deviceNum, unsigned long long address, bool *valid) { + AM_EVENT_LOG_HEADER logHeader; + char drivePath[MAX_PATH]; + ZeroMemory(&logHeader, sizeof logHeader); + ZeroMemory(drivePath, sizeof drivePath); + + sprintf_s(drivePath, sizeof drivePath, "\\\\.\\PhysicalDrive%d", deviceNum); + + HANDLE hFile = + CreateFileA(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + amiDebugLog("Error : CreateFile error"); + return false; + } + + LARGE_INTEGER writeAddress; + writeAddress.QuadPart = address + LOG_OFFSET; + if (!SetFilePointerEx(hFile, writeAddress, NULL, FILE_BEGIN)) { + CloseHandle(hFile); + amiDebugLog("SetFilePointerEx error"); + return false; + } + + DWORD bytesRead; + if (!ReadFile(hFile, &logHeader, sizeof logHeader, &bytesRead, NULL)) { + CloseHandle(hFile); + amiDebugLog("ReadFile Header error"); + return false; + } + if (bytesRead != sizeof logHeader) { + CloseHandle(hFile); + amiDebugLog("Read Size Error"); + return false; + } + + amiCrc32RInit(); + unsigned int calcCrc = + amiCrc32RCalc(sizeof logHeader - 4, (unsigned char *)(&logHeader) + 4, 0); + *valid = logHeader.m_crc32 == calcCrc; + CloseHandle(hFile); + return true; +} + +bool mxmEventLogAccessLoadEpbr(AM_INSTALL_BOOT_RECORD *bootRecord) { + amtime_t start, now; + + AM_INSTALL_STATUS err = amInstallInit(); + if (err != AM_INSTALL_STATUS_OK && err != AM_INSTALL_STATUS_ERR_ALREADY_INIT) { + amiDebugLog("Error : amInstallInit. Code %d", err); + return false; + } + amiTimerGet(&start); + while (1) { + err = amInstallGetBr(bootRecord, 0); + if (!((err == AM_INSTALL_STATUS_ERR_REQUEST) || + (err == AM_INSTALL_STATUS_ERR_UPDATE_STATUS) || + (err == AM_INSTALL_STATUS_ERR_GET_SEMAPHORE) || + (err == AM_INSTALL_STATUS_ERR_FORMAT) || (err == AM_INSTALL_STATUS_OK) || + (err == AM_INSTALL_STATUS_BUSY))) { + amiDebugLog("Error : amInstallGetBr error."); + amInstallExit(); + return false; + } + + amiTimerGet(&now); + if (amiTimerDiffSec(&start, &now) > 30) { + amiDebugLog("Error : amInstallGetBr time out error."); + amInstallExit(); + return false; + } + + if (err == AM_INSTALL_STATUS_OK) { + if (amInstallExit() == AM_INSTALL_STATUS_OK) return true; + + amiDebugLog("Error : amInstallExit."); + return false; + } + } +} + +bool mxmEventLogAccessReadEventLogData(int deviceNum, unsigned long long address, + unsigned char *eventlog1, unsigned int *nBytes1, + unsigned char *eventlog2, unsigned int *nBytes2) { + if (nBytes1 == 0 || eventlog2 == NULL || nBytes2 == NULL) return false; + + AM_EVENT_LOG_HEADER eventLogHeader; + ZeroMemory(&eventLogHeader, sizeof eventLogHeader); + + char drivePath[256]; + ZeroMemory(&drivePath, sizeof drivePath); + sprintf_s(drivePath, sizeof drivePath, "\\\\.\\PhysicalDrive%d", deviceNum); + + HANDLE hFile = + CreateFileA(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_SUPPORTS_REPARSE_POINTS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + amiDebugLog("Error : CreateFile error"); + return false; + } + + LARGE_INTEGER readAddress; + readAddress.QuadPart = address + LOG_OFFSET; + if (!SetFilePointerEx(hFile, readAddress, NULL, 0)) { + CloseHandle(hFile); + amiDebugLog("SetFilePointerEx error"); + return false; + } + + DWORD bytesRead; + if (!ReadFile(hFile, &eventLogHeader, sizeof eventLogHeader, &bytesRead, NULL)) { + CloseHandle(hFile); + amiDebugLog("ReadFile Header error"); + return false; + } + if (bytesRead != sizeof eventLogHeader) { + CloseHandle(hFile); + amiDebugLog("Read Size error"); + return false; + } + + amiCrc32RInit(); + unsigned int calcCrc = + amiCrc32RCalc(sizeof eventLogHeader - 4, (unsigned char *)(&eventLogHeader) + 4, 0); + + if (calcCrc != eventLogHeader.m_crc32) { + CloseHandle(hFile); + return false; + } + + if (eventLogHeader.m_nBytes[0] > LOG_MAX_SIZE || eventLogHeader.m_nBytes[1] > LOG_MAX_SIZE) { + CloseHandle(hFile); + amiDebugLog("Buffer Size error"); + return false; + } + + unsigned char *readBuffer = malloc(LOG_MAX_SIZE); + if (readBuffer == NULL) { + CloseHandle(hFile); + return false; + } + ZeroMemory(readBuffer, LOG_MAX_SIZE); + + struct { + unsigned long long offset; + unsigned int srcSize; + unsigned int dstSize; + unsigned char *dst; + } readSetup[2] = { + { + .offset = LOG_1_OFFSET, + .dstSize = LOG_MAX_SIZE, + .dst = eventlog1, + }, + { + .offset = LOG_2_OFFSET, + .dstSize = LOG_MAX_SIZE, + .dst = eventlog2, + }, + }; + + for (int i = 0; i < 2; i++) { + readAddress.QuadPart = address + readSetup[i].offset; + if (!SetFilePointerEx(hFile, readAddress, NULL, 0)) { + free(readBuffer); + CloseHandle(hFile); + amiDebugLog("SetFilePointerEx error"); + return false; + } + + DWORD nRead = eventLogHeader.m_nBytes[i]; + if ((nRead & 0x1FF) != 0) nRead += 512 - (nRead & 0x1FF); + + if (!ReadFile(hFile, readBuffer, nRead, &bytesRead, NULL)) { + free(readBuffer); + CloseHandle(hFile); + amiDebugLog("ReadFile Evt error"); + return false; + } + if (nRead != bytesRead) { + free(readBuffer); + CloseHandle(hFile); + amiDebugLog("Read Size error"); + return false; + } + + AmiMd5 md5; + amiMd5Init(&md5); + amiMd5Update(&md5, nRead, readBuffer); + amiMd5Finalise(&md5); + + if (memcmp(md5.m_digest, eventLogHeader.m_md5[i], sizeof md5.m_digest) != 0) { + free(readBuffer); + CloseHandle(hFile); + amiDebugLog("Event Log is broken"); + return false; + } + + memcpy(readSetup[i].dst, readBuffer, readSetup[i].dstSize); + } + + free(readBuffer); + CloseHandle(hFile); + return true; +} + +DWORD mxmEventLogAccessWriteDataFile(char *filename, unsigned char *dataFile, unsigned int nBytes) { + HANDLE hFile = CreateFileA(filename, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, + CREATE_ALWAYS, FILE_SUPPORTS_REPARSE_POINTS, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + amiDebugLog("Error : CreateFile error"); + return (DWORD)-1; + } + + DWORD ret = (DWORD)-1; + DWORD bytesRead; + if (WriteFile(hFile, dataFile, nBytes, &bytesRead, NULL)) { + ret = bytesRead; + } + CloseHandle(hFile); + return ret; +} + +bool mxmEventLogAccessCopyIntoDataFile(int deviceNum, unsigned long long address, char *filename, + unsigned int type) { + unsigned int nBytes1; + unsigned char *eventLog1 = malloc(LOG_MAX_SIZE); + if (eventLog1 == NULL) return false; + unsigned int nBytes2; + unsigned char *eventLog2 = malloc(LOG_MAX_SIZE); + if (eventLog2 == NULL) { + free(eventLog1); + return false; + } + + if (!mxmEventLogAccessReadEventLogData(deviceNum, address, eventLog1, &nBytes1, eventLog2, + &nBytes2)) { + free(eventLog1); + free(eventLog2); + return false; + } + + bool success; + if (type == 0) { + success = mxmEventLogAccessWriteDataFile(filename, eventLog2, nBytes1); + } else if (type == 1) { + success = mxmEventLogAccessWriteDataFile(filename, eventLog2, nBytes2); + } else { + free(eventLog1); + free(eventLog2); + return false; + } + + free(eventLog1); + free(eventLog2); + if (success == (DWORD)-1) return false; + return true; +} + +bool mxmEventLogAccessBackup(char *filename, int type) { + AM_INSTALL_BOOT_RECORD br; + ZeroMemory(&br, sizeof br); + int devNum = 0; + if (!mxmEventLogAccessGetMainStorageDeviceNum(&devNum)) return false; + if (!mxmEventLogAccessLoadEpbr(&br)) return false; + if (!mxmEventLogAccessCopyIntoDataFile(devNum, br.os, filename, type)) return false; + return true; +} diff --git a/src/micetools/micemaster/mxmEventLog.h b/src/micetools/micemaster/mxmEventLog.h index 6f347c9..56615a9 100644 --- a/src/micetools/micemaster/mxmEventLog.h +++ b/src/micetools/micemaster/mxmEventLog.h @@ -1,13 +1,29 @@ #include #include +#include "../lib/am/amInstall.h" +#include "../lib/ami/amiTimer.h" + typedef struct { - unsigned int Rsv00; - unsigned int Rsv04; + amtime_t m_last; unsigned int m_numRecords; char m_filename[MAX_PATH]; } mxmEventLogDesination_t; +#pragma pack(push, 1) +typedef struct { + unsigned int m_crc32; + char m_gameId[4]; + unsigned char Rsv08[8]; + unsigned int m_nBytes[2]; + unsigned char Rsv18[8]; + unsigned char m_md5[2][16]; + unsigned char Rsv40[448]; +} AM_EVENT_LOG_HEADER; +#pragma pack(pop) + +#define NUM_LOGS 3 + typedef struct { bool m_init; bool m_logDriveFound; @@ -15,11 +31,31 @@ typedef struct { unsigned int m_backupCount; unsigned int m_clearCount; unsigned int m_interval; - mxmEventLogDesination_t m_desinations[3]; + mxmEventLogDesination_t m_desinations[NUM_LOGS]; } mxmEventLog_t; extern mxmEventLog_t MxmEventLog; +#define LOG_MAX_SIZE (1024 * 512) +// Offsets relative to [os] partition, in bytes +#define LOG_OFFSET (2047 * 512) +#define LOG_1_OFFSET (2048 * 512) +#define LOG_2_OFFSET (LOG_1_OFFSET + LOG_MAX_SIZE) + +bool mxmEventLogGetTempPath(char *name, char *buffer); bool mxmEventLogGetLogDrive(char *logPath); int mxmEventLogSetDestination(char *name, unsigned int which); void mxmEventLogInit(void); +bool mxmEventLogEraseLog(void); +bool mxmEventLogCheckLog(bool *valid); +bool mxmEventLogAccessGetMainStorageDeviceNum(int *devNum); +bool mxmEventLogAccessEraseEventLogData(int deviceNum, unsigned long long address); +bool mxmEventLogAccessCheckEventLogData(int deviceNum, unsigned long long address, bool *valid); +bool mxmEventLogAccessLoadEpbr(AM_INSTALL_BOOT_RECORD *bootRecord); +bool mxmEventLogAccessReadEventLogData(int deviceNum, unsigned long long address, + unsigned char *eventlog1, unsigned int *nBytes1, + unsigned char *eventlog2, unsigned int *nBytes2); +DWORD mxmEventLogAccessWriteDataFile(char *filename, unsigned char *dataFile, unsigned int nBytes); +bool mxmEventLogAccessCopyIntoDataFile(int deviceNum, unsigned long long address, char *filename, + unsigned int type); +bool mxmEventLogAccessBackup(char *filename, int type); diff --git a/src/micetools/sysconf.h b/src/micetools/sysconf.h new file mode 100644 index 0000000..bdc14e1 --- /dev/null +++ b/src/micetools/sysconf.h @@ -0,0 +1,14 @@ +// #define GAME_ID_0 'S' +// #define GAME_ID_1 'D' +// #define GAME_ID_2 'E' +// #define GAME_ID_3 'Y' +#define GAME_ID_0 'S' +#define GAME_ID_1 'D' +#define GAME_ID_2 'D' +#define GAME_ID_3 'K' +#define GAME_ID { GAME_ID_0, GAME_ID_1, GAME_ID_2, GAME_ID_3 } + +#define HW_ID { 'A', 'A', 'S' } + +#define MAIN_ID { 'A', 'A', 'S', 'E', '-', '0', '1', 'A', '6', '5', '6', '4' } +#define KEY_ID { 'A', '7', '2', 'E', '-', '0', '2', 'D', '1', '1', '2', '6', '1', '1', '1', '6' } diff --git a/src/micetools/util/dongleDecrypt.c b/src/micetools/util/dongleDecrypt.c new file mode 100644 index 0000000..a24dd7e --- /dev/null +++ b/src/micetools/util/dongleDecrypt.c @@ -0,0 +1,134 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../lib/am/amDongle.h" +#include "../lib/am/amSerialId.h" + +struct { + char keychipId[17]; + char keychipSid[12]; + char gameId[5]; + unsigned char systemflag; + unsigned char modelType; + unsigned char region; + char networkAddress[16]; +} amlibDongle; + +AM_DONGLE_STATUS amlib_init_dongle(void) { + AM_DONGLE_STATUS err; + if ((err = amDongleInit()) != AM_DONGLE_STATUS_OK) return err; + + do { + err = amDongleSetupKeychip(); + } while (err == AM_DONGLE_STATUS_PENDING); + if (err != AM_DONGLE_STATUS_OK) return err; + + if ((err = amDongleSetupKeychip()) != AM_DONGLE_STATUS_OK) return err; + if (!amDongleIsAvailable()) return AM_DONGLE_STATUS_NG; + if ((err = amDongleSetAuthConfig("toolmode")) != AM_DONGLE_STATUS_OK) return err; + if ((err = amDongleBillingGetKeychipId(amlibDongle.keychipId, AM_DONGLE_BLOCK)) != + AM_DONGLE_STATUS_OK) + return err; + if (!amSerialIdConvert(amlibDongle.keychipId, amlibDongle.keychipSid)) + return AM_DONGLE_STATUS_NG; + if ((err = amDongleGetGameId(amlibDongle.gameId, AM_DONGLE_BLOCK)) != AM_DONGLE_STATUS_OK) + return err; + if ((err = amDongleGetSystemFlag(&amlibDongle.systemflag, AM_DONGLE_BLOCK)) != + AM_DONGLE_STATUS_OK) + return err; + if ((err = amDongleGetModelType(&amlibDongle.modelType, AM_DONGLE_BLOCK)) != + AM_DONGLE_STATUS_OK) + return err; + if ((err = amDongleGetRegion(&amlibDongle.region, AM_DONGLE_BLOCK)) != AM_DONGLE_STATUS_OK) + return err; + + unsigned int iNetworkAddress; + if ((err = amDongleGetNetworkAddress(&iNetworkAddress, AM_DONGLE_BLOCK)) != AM_DONGLE_STATUS_OK) + return err; + + sprintf_s(amlibDongle.networkAddress, sizeof amlibDongle.networkAddress, "%d.%d.%d.%d", + iNetworkAddress & 0xff, (iNetworkAddress >> 8) & 0xff, (iNetworkAddress >> 16) & 0xff, + (iNetworkAddress >> 24) & 0xff); + + return AM_DONGLE_STATUS_OK; +} + +int main(int argc, char** argv) { + amDongleDebugLevel = 1; + + if (argc != 3) { + fprintf(stderr, "Usage: %s \n", argv[0]); + return -1; + } + if (!PathFileExistsA(argv[1])) { + fprintf(stderr, "%s: no such file or directory\n", argv[1]); + return -1; + } + // if (!PathFileExistsA(argv[2])) { + // fprintf(stderr, "%s: no such file or directory\n", argv[2]); + // return -1; + // } + + WSADATA wsaData; + if (WSAStartup(2, &wsaData)) { + puts("Failed to WSAStartup"); + return -1; + } + + puts("Waiting for dongle"); + AM_DONGLE_STATUS err; + err = amlib_init_dongle(); + if (err != AM_DONGLE_STATUS_OK) { + printf("Failed to init dongle:%d\n", err); + amDongleExit(); + return -1; + } + + printf("Dumping using dongle %s, for %s\n", amlibDongle.keychipId, amlibDongle.gameId); + + FILE* inFile; + FILE* outFile; + + if (fopen_s(&inFile, argv[1], "rb")) { + puts("Failed to open infile"); + amDongleExit(); + return -1; + } + if (fopen_s(&outFile, argv[2], "wb")) { + puts("Failed to open outfile"); + fclose(inFile); + amDongleExit(); + return -1; + } + + fseek(inFile, 0, 2); + size_t end = ftell(inFile); + fseek(inFile, 0, 0); + + unsigned char ct[16]; + unsigned char pt[16]; + uint i = 0; + amDongleSetIv(AM_DONGLE_BLOCK); + while (1) { + if (fread_s(ct, sizeof ct, 16, 1, inFile) != 1) break; + amDongleDecrypt(ct, pt, AM_DONGLE_BLOCK); + fwrite(pt, 16, 1, outFile); + + printf("\r%d/%d", i, end); + i += 16; + if (i % 512 == 0) fflush(outFile); + } + puts(""); + fclose(inFile); + fclose(outFile); + puts("Done!"); + + amDongleExit(); + return 0; +} diff --git a/src/micetools/util/exio_test.c b/src/micetools/util/exio_test.c new file mode 100644 index 0000000..b1d7af7 --- /dev/null +++ b/src/micetools/util/exio_test.c @@ -0,0 +1,341 @@ +#include +// +#include +#include +#include +#pragma comment(lib, "Setupapi.lib") + +#include "../lib/am/amEeprom.h" + +HANDLE mxkSmbusCreateDeviceFile() { + SP_DEVICE_INTERFACE_DATA interfaceData; + SP_DEVICE_INTERFACE_DETAIL_DATA_A interfaceDetail[204]; + + HDEVINFO DeviceInfoSet = + SetupDiGetClassDevsA(&MXSMBUS_GUID, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT); + if (DeviceInfoSet == INVALID_HANDLE_VALUE) { + return INVALID_HANDLE_VALUE; + } + + interfaceData.cbSize = 28; + BOOL s; + s = SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, &MXSMBUS_GUID, 0, &interfaceData); + if (!s) { + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + return INVALID_HANDLE_VALUE; + } + + interfaceDetail[0].cbSize = 5; + s = SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet, &interfaceData, interfaceDetail, + sizeof interfaceDetail, NULL, NULL); + if (!s) { + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + return INVALID_HANDLE_VALUE; + } + + char fileName[260]; + strcpy_s(fileName, sizeof fileName, interfaceDetail[0].DevicePath); + HANDLE device = + CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, OPEN_EXISTING, FILE_SUPPORTS_GHOSTING, NULL); + SetupDiDestroyDeviceInfoList(DeviceInfoSet); + return device; +} + +typedef unsigned char byte; +typedef unsigned int uint; + +#pragma pack(push, 1) +typedef struct { + unsigned char status; + unsigned char command; + unsigned short addr; + unsigned short command_code; + unsigned char nbytes; + unsigned char data[32]; +} i2c_packet; +typedef struct { + unsigned char status; + unsigned char command; + unsigned char addr; + unsigned char command_code; + unsigned char nbytes; + unsigned char data[32]; +} smb_packet; +#pragma pack(pop) + +HANDLE MXSMBUS; + +int smbusWriteI2C(byte addr, byte command, byte* buffer, byte nbytes) { + i2c_packet io_buf; + io_buf.addr = addr; + io_buf.command_code = (command << 8) | *buffer; + io_buf.nbytes = (char)nbytes - 1; + io_buf.status = 0; + io_buf.command = 8; + memcpy(io_buf.data, buffer + 1, (uint)io_buf.nbytes); + + byte bVar3; + for (bVar3 = 0; bVar3 < 5; bVar3++) { + DWORD bytesReturned; + BOOL success = DeviceIoControl(MXSMBUS, IOCTL_MXSMBUS_I2C, &io_buf, sizeof io_buf, &io_buf, + sizeof io_buf, &bytesReturned, NULL); + if (!success || bytesReturned != sizeof io_buf) { + return -9; + } + if (io_buf.status == 0) break; + if (io_buf.status != 24) return -9; + + Sleep(16); + } + return bVar3 == 5 ? -9 : 0; +} + +int dsReadByte(byte addr, byte* readByte, byte cmd_code) { + smb_packet buffer; + + buffer.command_code = cmd_code; + buffer.status = 0; + buffer.command = 5; + buffer.nbytes = 0; + buffer.data[0] = 0; + buffer.data[1] = 0; + buffer.addr = addr; + + DWORD bytesReturned; + BOOL success = DeviceIoControl(MXSMBUS, IOCTL_MXSMBUS_REQUEST, &buffer, sizeof buffer, &buffer, + sizeof buffer, &bytesReturned, NULL); + if (success && buffer.status == 0 && bytesReturned == sizeof buffer) { + *readByte = buffer.data[0]; + return 0; + } + return -8; +} + +bool mxkDsExioWaitNotBusy(void) { + while (true) { + byte val = 0; + if (dsReadByte(0x54, &val, 0) == 0) return true; + + Sleep(10); + } + return false; +} + +int mxkDsExioWriteInputBuffer(byte* buffer) { + uint offset = 0; + uint uVar1 = 0; + while (uVar1 < 64) { + uint nbytes; + if (64 - uVar1 < 9) { + nbytes = 64 - offset & 0xffff; + } else { + nbytes = 8; + } + + if (smbusWriteI2C(0x54, offset & 0xff, buffer, nbytes & 0xff) != 0) return -9; + if (!mxkDsExioWaitNotBusy()) return -10; + + offset += nbytes; + uVar1 = offset & 0xffff; + buffer += nbytes; + } + return 0; +} + +int smbusWriteByte(byte v_addr, byte command_code, byte data) { + smb_packet packet; + + packet.command_code = command_code; + packet.data[0] = data; + packet.status = 0; + packet.command = 4; + packet.nbytes = 0; + packet.data[1] = 0xff; + packet.addr = v_addr; + + DWORD bytesReturned; + BOOL success = DeviceIoControl(MXSMBUS, IOCTL_MXSMBUS_REQUEST, &packet, sizeof packet, &packet, + sizeof packet, &bytesReturned, NULL); + + if (!success) { + printf("DIO failed %03x\n", GetLastError()); + return -9; + } + if (packet.status != 0) { + printf("Packet status: %d\n", packet.status); + return -9; + } + if (bytesReturned != sizeof packet) return -9; + return 0; +} + +int mxkDsExioRequestComputeMac(void) { + if (smbusWriteByte(0x54, 0x5c, 0x94) != 0) return -9; + if (!mxkDsExioWaitNotBusy()) return -10; + + return 0; +} + +int mxkDsExioReadMacOutputBuffer(byte* macBuffer) { + byte cmd_code = 0x40; + for (int i = 0; i < 20; i++, cmd_code++) { + if (dsReadByte(0x54, &(macBuffer[i]), cmd_code) != 0) return -8; + } + return 0; +} + +int mxkDsKeychipReadEeprom(byte* pageData, byte page) { + if (page > 3) return -2; + + byte addr = page << 5; + for (int i = 0; i < 32; i++, addr++) { + if (dsReadByte(0x55, &(pageData[i]), addr) != 0) return -8; + } + return 0; +} + +byte INPUT_BUFFER[64] = { + // Random (0:4 bytes --> [takes the first 4 bytes of the secret]) + 0, + 0, + 0, + 0, + // Eeprom (4:32 bytes) + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + 0x00, + // Challenge low (36:4 bytes) + 0x76, + 0x76, + 0x76, + 0x76, + // Page (40:1 byte) + 0x43, + // ID (41:7 bytes) + 0x41, + 0x42, + 0x43, + 0x44, + 0x45, + 0x46, + 0x47, + // Random (48:4 bytes --> takes the last 4 bytes of the secret) + 0, + 0, + 0, + 0, + // Challenge high (52:3 bytes) + 0x77, + 0x77, + 0x77, + // Random (55:9 bytes) + 0, // --> takes value 0x80 + 0, // --> takes 0 + 0, // > ... + 0, // > ... + 0, // > ... + 0, // > ... + 0, // > ... + 0, // --> takes value 0x01 + 0, // --> takes value 0xB8 +}; + +/** + * Expected output: + * + * 1a e7 2d 24 8c b4 e3 40 fb 62 7d be 63 65 eb 25 70 5f d4 e3 + */ + +int exio_mac_test(byte* buffer) { + // puts("mxkDsExioWriteInputBuffer..."); + if (mxkDsExioWriteInputBuffer(buffer)) { + puts("mxkDsExioWriteInputBuffer failed"); + return -1; + } + // puts("mxkDsExioRequestComputeMac..."); + if (mxkDsExioRequestComputeMac()) { + puts("mxkDsExioRequestComputeMac failed"); + return -1; + } + byte mac[20]; + // puts("mxkDsExioReadMacOutputBuffer..."); + if (mxkDsExioReadMacOutputBuffer(mac)) { + puts("mxkDsExioReadMacOutputBuffer failed"); + return -1; + } + // puts("Output mac:"); + for (int i = 0; i < 20; i++) { + printf("%02x", mac[i]); + } + puts(""); + return 0; +} + +int keychip_ds_eeprom_dump(void) { + byte pageData[32]; + for (int page = 0; page < 4; page++) { + printf("Page %d\n", page); + if (mxkDsKeychipReadEeprom(pageData, page)) { + puts("Read failed"); + } + for (int i = 0; i < 32; i++) { + printf("%02x", pageData[i]); + } + puts(""); + } + return 0; +} + +int main(int argc, char** argv) { + MXSMBUS = mxkSmbusCreateDeviceFile(); + + if (MXSMBUS == INVALID_HANDLE_VALUE) { + puts("Unable to open smbus"); + return -1; + } + + byte buffer[sizeof INPUT_BUFFER]; + for (int i = 0; i < sizeof INPUT_BUFFER; i++) { + printf("%02d: ", i); + + memcpy(buffer, INPUT_BUFFER, sizeof INPUT_BUFFER); + buffer[i] = 0x69; + exio_mac_test(buffer); + } + + // keychip_ds_eeprom_dump(); + + CloseHandle(MXSMBUS); + + return 0; +} \ No newline at end of file diff --git a/src/micetools/util/meson.build b/src/micetools/util/meson.build index 8c6fa6f..fcf5c1d 100644 --- a/src/micetools/util/meson.build +++ b/src/micetools/util/meson.build @@ -43,3 +43,31 @@ executable( 'micemonitor.c', ], ) + +executable( + 'exio_test', + win_subsystem: subsystem, + sources: [ + 'exio_test.c', + ], +) + +executable( + 'dongleDecrypt', + win_subsystem: subsystem, + sources: [ + 'dongleDecrypt.c', + ], + link_with: [ + amDongle, + amSerialId, + ], +) + +executable( + 'testBin', + win_subsystem: subsystem, + sources: [ + 'test.c', + ], +) diff --git a/src/micetools/util/micedump/kc_mxkeychip.c b/src/micetools/util/micedump/kc_mxkeychip.c index 6e53719..90bd997 100644 --- a/src/micetools/util/micedump/kc_mxkeychip.c +++ b/src/micetools/util/micedump/kc_mxkeychip.c @@ -46,9 +46,9 @@ AM_DONGLE_STATUS amlib_init_dongle(void) { if ((err = amDongleGetNetworkAddress(&iNetworkAddress, AM_DONGLE_BLOCK)) != AM_DONGLE_STATUS_OK) return err; - sprintf(amlibDongle.networkAddress, "%d.%d.%d.%d", iNetworkAddress & 0xff, - (iNetworkAddress >> 8) & 0xff, (iNetworkAddress >> 16) & 0xff, - (iNetworkAddress >> 24) & 0xff); + sprintf_s(amlibDongle.networkAddress, sizeof amlibDongle.networkAddress, "%d.%d.%d.%d", + iNetworkAddress & 0xff, (iNetworkAddress >> 8) & 0xff, (iNetworkAddress >> 16) & 0xff, + (iNetworkAddress >> 24) & 0xff); return AM_DONGLE_STATUS_OK; } @@ -94,5 +94,18 @@ void miceDumpKCMxkeychip(void) { amDongleBillingGetNearfull(&billingData, AM_DONGLE_BLOCK); printf(" Nearfull: %08x\n", billingData); + unsigned char seed[16]; + amDongleGetSeed(seed, AM_DONGLE_BLOCK); + printf(" Seed: "); + for (int i = 0; i < sizeof seed; i++) printf("%02x", seed[i]); + puts(""); + + unsigned char keyfile[16]; + amDongleSetIv(AM_DONGLE_BLOCK); + amDongleEncrypt(seed, keyfile, AM_DONGLE_BLOCK); + printf(" Keyfile: "); + for (int i = 0; i < sizeof keyfile; i++) printf("%02x", keyfile[i]); + puts(""); + amDongleExit(); } diff --git a/src/micetools/util/micedump/platform.c b/src/micetools/util/micedump/platform.c index b2dc9d8..a5b1b31 100644 --- a/src/micetools/util/micedump/platform.c +++ b/src/micetools/util/micedump/platform.c @@ -3,6 +3,10 @@ #include "../lib/am/amPlatform.h" +static const char* sBoardType[] = { + "RingEdge", "RingWide (Spec 1)", "RingWide (Spec 2)", "RingEdge 2", "Unknown", +}; + void miceDumpPlatform(void) { fprintf(stderr, "Dumping platform information using %s\n", amPlatformVersion); @@ -11,6 +15,6 @@ void miceDumpPlatform(void) { AM_PLATFORM_PLATFORM_ID platformId; amPlatformGetPlatformId(&platformId); - printf("Board type: %d\n", boardType); + printf("Board type: %s\n", sBoardType[boardType]); printf("Platform ID: %s\n", platformId.strPlatformId); } \ No newline at end of file diff --git a/src/micetools/util/micetinker.c b/src/micetools/util/micetinker.c index 5a14329..40b74ca 100644 --- a/src/micetools/util/micetinker.c +++ b/src/micetools/util/micetinker.c @@ -32,8 +32,8 @@ BOOL change_region(BYTE region) { puts(""); data[12] = region; - amCrc32RCreateTable(); - ((DWORD*)data)[0] = amCrc32RGet(sizeof data - 4, data + 4, 0); + amiCrc32RInit(); + ((DWORD*)data)[0] = amiCrc32RCalc(sizeof data - 4, data + 4, 0); amEepromWrite(0, data, sizeof data); amEepromRead(0, data, sizeof data); diff --git a/src/micetools/util/test.c b/src/micetools/util/test.c new file mode 100644 index 0000000..765ba71 --- /dev/null +++ b/src/micetools/util/test.c @@ -0,0 +1,55 @@ +#include +#include + +char path[MAX_PATH * 1000]; +int main(int argc, char** argv) { + // printf("%d", QueryDosDeviceA(NULL, path, sizeof path)); + // printf(" %03x\n", GetLastError()); + + // char* pPath = path; + // while (1) { + // size_t len = strlen(pPath); + // if (!len) break; + // puts(pPath); + // pPath += len + 1; + // } + + DWORD volumeSerialNumber; + + // Crackproof-style call + BOOL ret = GetVolumeInformationA( + "C:\\", + NULL, + 0, + &volumeSerialNumber, + NULL, + NULL, + NULL, + 0 + ); + printf("volumeSerialNumber: %08x\n"); + + // Exhaustive call + CHAR volumeNameBuffer[MAX_PATH]; + DWORD maximumComponentLength; + DWORD fileSystemFlags; + CHAR fileSystemName[MAX_PATH]; + ret = GetVolumeInformationA( + "C:\\", + volumeNameBuffer, + sizeof volumeNameBuffer, + &volumeSerialNumber, + &maximumComponentLength, + &fileSystemFlags, + fileSystemName, + sizeof fileSystemName + ); + + printf("volumeNameBuffer: %s\n", volumeNameBuffer); + printf("volumeSerialNumber: %08x\n", volumeSerialNumber); + printf("maximumComponentLength: %08x\n", maximumComponentLength); + printf("fileSystemFlags: %08x\n", fileSystemFlags); + printf("fileSystemName: %s\n", fileSystemName); + + return 0; +} \ No newline at end of file diff --git a/src/patches/ALLNetProc_Win.patch b/src/patches/ALLNetProc_Win.patch new file mode 100644 index 0000000..61482cd --- /dev/null +++ b/src/patches/ALLNetProc_Win.patch @@ -0,0 +1,21 @@ +*00503de8: 00000000 > 01000000 # amBackupDebugLevel +*005052c0: 00000000 > 01000000 # amDipswDebugLevel +*00500990: 00000000 > 01000000 # amDongleDebugLevel +*00503de4: 00000000 > 01000000 # amEepromDebugLevel +*005057bc: 00000000 > 01000000 # amGcatcherDebugLevel +*00505cd4: 00000000 > 01000000 # amGdeliverDebugLevel +*0050674c: 00000000 > 01000000 # amGfetcherDebugLevel +*00504990: 00000000 > 01000000 # amHmDebugLevel +*00505d20: 00000000 > 01000000 # amInstallDebugLevel +*00500980: 00000000 > 01000000 # amiTimerDebugLevel +*005049a0: 00000000 > 01000000 # amMasterDebugLevel +*00504418: 00000000 > 01000000 # amNetworkDebugLevel +*00506798: 00000000 > 01000000 # amPlatformDebugLevel +*005041f8: 00000000 > 01000000 # amRtcDebugLevel +*00504410: 00000000 > 01000000 # amSramDebugLevel +*0050690c: 00000000 > 01000000 # libpcpDebugLevel + +*004f48bc: 01000000 > 05000000 # ALPB_DEBUG_PRINT::m_systemLogLevel +*00506eec: 00000000 > 00000000 # ALPB_DEBUG_PRINT::m_debugPrintLevel + + diff --git a/src/patches/nxAuth.patch b/src/patches/nxAuth.patch new file mode 100644 index 0000000..4584ce8 --- /dev/null +++ b/src/patches/nxAuth.patch @@ -0,0 +1,20 @@ +*0053bd94 : 00000000 > 01000000 # pcpDebugLevel +*0053bc18 : 00000000 > 01000000 # amEepromDebugLevel +*005376f8 : 00000000 > 01000000 # amDongleDebugLevel +*0053b068 : 00000000 > 01000000 # amHmDebugLevel +*0053b070 : 00000000 > 01000000 # amNetworkDebugLevel +*0053bc1c : 00000000 > 01000000 # amSramDebugLevel +*0053b5f0 : 00000000 > 01000000 # amBackupDebugLevel +*0053ba00 : 00000000 > 01000000 # amRtcDebugLevel +*0053b044 : 00000000 > 01000000 # amGcatcherDebugLevel +*005376e0 : 00000000 > 01000000 # amiTimerDebugLevel +*0053bc20 : 00000000 > 01000000 # amPlatformDebugLevel +*0040e284 : 896e08896c2424 > c7460801000000 # Manager debug level +*0040b9a0 : 895e08895c2418 > c7460801000000 # 1 +*0040daa0 : 895e08895c2418 > c7460801000000 # 2 +*0040e011 : 897e08897c241c > c7460801000000 # 3 +*0040cf02 : 895e08895c241c > c7460801000000 # 4 +*00410a52 : 897e08897c241c > c7460801000000 # 5 +*00410e81 : 895e08895c241c > c7460801000000 # 6 +*004115dd : c7460800000000 > c7460801000000 # 7 +*0040939b : 895e088b442420 > c7460801000000 # 8 \ No newline at end of file diff --git a/src/patches/patches.index b/src/patches/patches.index index c8ac3fc..9899879 100644 --- a/src/patches/patches.index +++ b/src/patches/patches.index @@ -9,4 +9,6 @@ ALLNetProc.exe: ALLNetProc.patch Game.exe: Game.patch mxnetwork.exe: mxnetwork.patch maimai_dump_.exe: maimai_dump_.patch -RingGame.exe: UnderNightInBirthExLate[st].patch \ No newline at end of file +RingGame.exe: UnderNightInBirthExLate[st].patch +nxAuth.exe: nxAuth.patch +ALLNetProc_Win.exe: ALLNetProc_Win.patch