Too much for one commit message
This commit is contained in:
parent
cc705ed0d4
commit
4464d9188f
21
Makefile
21
Makefile
@ -3,13 +3,18 @@ BUILD_DIR_32 := $(BUILD_DIR)/build32
|
||||
BUILD_DIR_64 := $(BUILD_DIR)/build64
|
||||
DIST_DIR := dist
|
||||
|
||||
BUILD_DRIVE = M:
|
||||
BUILD_DRIVE := M:
|
||||
|
||||
MICE_32 = "$(BUILD_DIR_32)/src\mice.exe"
|
||||
MICE_64 = "$(BUILD_DIR_64)/src\mice.exe"
|
||||
MICE_32 := "$(BUILD_DIR_32)/src\mice.exe"
|
||||
MICE_64 := "$(BUILD_DIR_64)/src\mice.exe"
|
||||
|
||||
VCVARS_32 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat"
|
||||
VCVARS_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat"
|
||||
|
||||
# For windows XP:
|
||||
# VCVARS_32 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat" -vcvars_ver=14.16
|
||||
# VCVARS_64 := "C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat" -vcvars_ver=14.16
|
||||
|
||||
VCVARS_32 = C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars32.bat
|
||||
VCVARS_64 = C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\Community\\VC\\Auxiliary\\Build\\vcvars64.bat
|
||||
|
||||
.ONESHELL:
|
||||
|
||||
@ -19,7 +24,7 @@ all: mice86 dist
|
||||
mice86:
|
||||
-@subst $(BUILD_DRIVE) .
|
||||
@cd /D $(BUILD_DRIVE) \
|
||||
& "$(VCVARS_32)" \
|
||||
& $(VCVARS_32) \
|
||||
& meson setup --cross cross-32.ini $(BUILD_DRIVE)\$(BUILD_DIR_32) \
|
||||
& meson compile -C $(BUILD_DRIVE)\$(BUILD_DIR_32)
|
||||
@subst $(BUILD_DRIVE) /D
|
||||
@ -27,7 +32,7 @@ mice86:
|
||||
mice64:
|
||||
-@subst $(BUILD_DRIVE) .
|
||||
@cd $(BUILD_DRIVE) \
|
||||
& "$(VCVARS_64)" \
|
||||
& $(VCVARS_64) \
|
||||
& meson setup --cross cross-64.ini $(BUILD_DRIVE)\$(BUILD_DIR_64) \
|
||||
& meson compile -C $(BUILD_DRIVE)\$(BUILD_DIR_64)
|
||||
@subst $(BUILD_DRIVE) /D
|
||||
@ -47,6 +52,8 @@ dist:
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/lib/libpcp\libpcp.lib" "$(DIST_DIR)/libpcp.lib"
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice86.exe"
|
||||
# @copy /Y "$(BUILD_DIR_32)/src/micetools/launcher\mice.pdb" "$(DIST_DIR)/mice86.pdb"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/dll\mice.pdb" "$(DIST_DIR)/mice86.pdb"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/dll\mice.dll" "$(DIST_DIR)/mice86.dll"
|
||||
# @copy /Y "$(BUILD_DIR_64)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice64.exe"
|
||||
# @copy /Y "$(BUILD_DIR_64)/src/micetools/dll\mice.dll" "$(DIST_DIR)/mice64.dll"
|
||||
|
23
meson.build
23
meson.build
@ -1,15 +1,30 @@
|
||||
project('micetools', 'c')
|
||||
project('micetools', 'c', default_options: [
|
||||
'buildtype=minsize',
|
||||
# ! Tobble /\ and \/ when building for XP (minsize=normal, static=XP)
|
||||
# 'b_vscrt=static_from_buildtype',
|
||||
'warning_level=2',
|
||||
])
|
||||
|
||||
winxp = false
|
||||
subsystem = 'console,5.01'
|
||||
|
||||
if (host_machine.cpu_family() == 'x86')
|
||||
add_project_arguments('-DMICE_WIN32', language: 'c')
|
||||
endif
|
||||
|
||||
add_project_arguments(
|
||||
'-DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need
|
||||
'-D_WIN32_WINNT=_WIN32_WINNT_WINXP', # hahahahaha I hate it
|
||||
# '/O1', # Optimise size
|
||||
'/DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need
|
||||
'/D_WIN32_WINNT=_WIN32_WINNT_WINXP', # hahahahaha I hate it
|
||||
language: 'c',
|
||||
)
|
||||
if winxp
|
||||
add_project_arguments(
|
||||
'/D_USING_V140_SDK71_',
|
||||
'/DSFML_STATIC',
|
||||
'/DYNAMICBASE:NO',
|
||||
language: 'c',
|
||||
)
|
||||
endif
|
||||
|
||||
subdir('assets')
|
||||
subdir('src')
|
||||
|
@ -6,7 +6,8 @@ BOOL DevGetCommTimeouts(void* data, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE
|
||||
BOOL DevSetCommTimeouts(void* data, LPCOMMTIMEOUTS lpCommTimeouts) { return TRUE; }
|
||||
BOOL DevSetupComm(void* data, DWORD dwInQueue, DWORD dwOutQueue) { return TRUE; }
|
||||
BOOL DevPurgeComm(void* data, DWORD dwFlags) {
|
||||
if (dwFlags & PURGE_RXCLEAR) ((com_device_t*)data)->filled = 0;
|
||||
if (dwFlags & PURGE_RXCLEAR) ringbuf_purge(&((com_device_t*)data)->out);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevGetCommModemStatus(void* data, LPDWORD lpModelStat) {
|
||||
@ -18,13 +19,76 @@ BOOL DevWaitCommEvent(void* data, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped)
|
||||
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevClearCommError(void* data, LPDWORD lpErrors, LPCOMSTAT lpStat) { return TRUE; }
|
||||
BOOL DevClearCommError(void* data, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||
if (lpErrors != NULL) *lpErrors = 0;
|
||||
if (lpStat != NULL) {
|
||||
lpStat->fCtsHold = FALSE;
|
||||
lpStat->fDsrHold = FALSE;
|
||||
lpStat->fRlsdHold = FALSE;
|
||||
lpStat->fXoffHold = FALSE;
|
||||
lpStat->fXoffSent = FALSE;
|
||||
lpStat->fEof = FALSE;
|
||||
lpStat->fTxim = FALSE;
|
||||
lpStat->fReserved = 0;
|
||||
lpStat->cbInQue = ringbuf_available(&((com_device_t*)data)->out);
|
||||
lpStat->cbOutQue = ringbuf_available(&((com_device_t*)data)->in);
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DevWriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
if (nNumberOfBytesToWrite > 0xffff) return FALSE;
|
||||
// Ignore overflow
|
||||
ringbuf_write(&((com_device_t*)file)->in, lpBuffer, nNumberOfBytesToWrite & 0xffff);
|
||||
if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nNumberOfBytesToWrite;
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
if (nNumberOfBytesToRead > 0xffff) return FALSE;
|
||||
|
||||
// Make sure we have at least one byte to return
|
||||
// while (!ringbuf_available(&((com_device_t*)file)->out)) {
|
||||
// WaitForSingleObject(((com_device_t*)file)->event, INFINITE);
|
||||
// }
|
||||
|
||||
short read = ringbuf_read(&((com_device_t*)file)->out, lpBuffer, nNumberOfBytesToRead & 0xffff);
|
||||
if (lpNumberOfBytesRead) *lpNumberOfBytesRead = read;
|
||||
|
||||
if (read != 0) {
|
||||
// log_info("drf", "%d", read);
|
||||
// for (int i = 0; i < read; i++) {
|
||||
// printf("%02x ", ((unsigned char*)lpBuffer)[i]);
|
||||
// }
|
||||
// puts("");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
short comdev_read(com_device_t* com, unsigned char* buffer, short bytes) {
|
||||
return ringbuf_read(&com->in, buffer, bytes);
|
||||
}
|
||||
bool comdev_write(com_device_t* com, unsigned char* buffer, short bytes) {
|
||||
bool ret = ringbuf_write(&com->out, buffer, bytes);
|
||||
SetEvent(com->event);
|
||||
return ret;
|
||||
}
|
||||
short comdev_available(com_device_t* com) { return ringbuf_available(&com->in); }
|
||||
|
||||
void com_device_thread(com_device_t* com, FnComDeviceThread* thread) {
|
||||
com->thread = CreateThread(NULL, 0, thread, com, 0, NULL);
|
||||
}
|
||||
|
||||
com_device_t* new_com_device(BYTE port) {
|
||||
com_device_t* hook = (com_device_t*)malloc(sizeof *hook);
|
||||
com_hook_t* com = new_com_hook(port);
|
||||
file_hook_t* file = new_file_hook(com->wName);
|
||||
file->altFilename = com->wDosName;
|
||||
com->data = hook;
|
||||
file->data = hook;
|
||||
hook->com = com;
|
||||
hook->file = file;
|
||||
|
||||
com->GetCommState = DevGetCommState;
|
||||
com->SetCommState = DevSetCommState;
|
||||
@ -36,9 +100,17 @@ com_device_t* new_com_device(BYTE port) {
|
||||
com->WaitCommEvent = DevWaitCommEvent;
|
||||
com->ClearCommError = DevClearCommError;
|
||||
|
||||
hook->filled = 0;
|
||||
file->ReadFile = DevReadFile;
|
||||
file->WriteFile = DevWriteFile;
|
||||
|
||||
ringbuf_purge(&hook->in);
|
||||
ringbuf_purge(&hook->out);
|
||||
hook->event = CreateEventW(NULL, TRUE, FALSE, hook->com->wName);
|
||||
hook->com = com;
|
||||
|
||||
hook_file(file);
|
||||
hook_com(com);
|
||||
free(com->virtual_handle);
|
||||
com->virtual_handle = file->virtual_handle;
|
||||
|
||||
return hook;
|
||||
}
|
||||
|
@ -1,11 +1,23 @@
|
||||
#include "com.h"
|
||||
#include "files.h"
|
||||
#pragma once
|
||||
#include "hooks/com.h"
|
||||
#include "common.h"
|
||||
#include "hooks/files.h"
|
||||
|
||||
typedef struct com_device {
|
||||
com_hook_t* com;
|
||||
file_hook_t* file;
|
||||
|
||||
BYTE queue[2048];
|
||||
DWORD filled;
|
||||
ring_buffer_t in;
|
||||
ring_buffer_t out;
|
||||
HANDLE event;
|
||||
HANDLE thread;
|
||||
} com_device_t;
|
||||
|
||||
typedef DWORD(WINAPI FnComDeviceThread)(com_device_t* com);
|
||||
|
||||
short comdev_read(com_device_t* com, unsigned char* buffer, short bytes);
|
||||
bool comdev_write(com_device_t* com, unsigned char* buffer, short bytes);
|
||||
short comdev_available(com_device_t* com);
|
||||
|
||||
void com_device_thread(com_device_t* com, FnComDeviceThread* thread);
|
||||
com_device_t* new_com_device(BYTE port);
|
24
src/micetools/dll/common.h
Normal file
24
src/micetools/dll/common.h
Normal file
@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <Winsock2.h>
|
||||
#include <initguid.h>
|
||||
#include <windns.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "d3d9.lib")
|
||||
#include <d3d9.h>
|
||||
#pragma comment(lib, "comctl32.lib")
|
||||
#include <Iphlpapi.h>
|
||||
#include <commctrl.h>
|
||||
#include <memory.h>
|
||||
#include <setupapi.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "./util/_util.h"
|
6
src/micetools/dll/devices/_devices.c
Normal file
6
src/micetools/dll/devices/_devices.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "_devices.h"
|
||||
|
||||
void install_devices() {
|
||||
install_led_bd();
|
||||
install_touch_bd();
|
||||
}
|
8
src/micetools/dll/devices/_devices.h
Normal file
8
src/micetools/dll/devices/_devices.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include "../comdevice.h"
|
||||
#include "../common.h"
|
||||
|
||||
void install_led_bd();
|
||||
void install_touch_bd();
|
||||
|
||||
void install_devices();
|
225
src/micetools/dll/devices/led_bd.c
Normal file
225
src/micetools/dll/devices/led_bd.c
Normal file
@ -0,0 +1,225 @@
|
||||
#include "../hooks/gui.h"
|
||||
#include "_devices.h"
|
||||
|
||||
/*
|
||||
[0] = e0
|
||||
[1] = dest?
|
||||
[2] = dst?
|
||||
[3] = length
|
||||
[4] = op code
|
||||
[...] length-1 bytes
|
||||
[.] = sum
|
||||
|
||||
[0] = e0
|
||||
[2] = dst?
|
||||
[1] = dest?
|
||||
[3] = length
|
||||
[4] = status
|
||||
[5] = op
|
||||
[6] = report
|
||||
[...]
|
||||
[.] = sum
|
||||
|
||||
OP codes:
|
||||
3c: FUN_005735c0 (1)
|
||||
|
||||
10: FUN_00580c00 (1)
|
||||
7c: FUN_00580c00 (2)
|
||||
3c: FUN_00580c00 (1)
|
||||
39: FUN_00580c00 (4)
|
||||
3b: FUN_00580c00 (1)
|
||||
|
||||
31: FUN_00581350 (5)
|
||||
32: FUN_005813b0 (8)
|
||||
33: FUN_00581430 (8) -> something at [16]??
|
||||
39: FUN_005814b0 (4)
|
||||
3f: FUN_00581220 (7)
|
||||
|
||||
7b: FUN_005812a0 (3)
|
||||
7c: FUN_00581310 (2)
|
||||
|
||||
01: was this just an error?
|
||||
10:
|
||||
|
||||
31: Set button. [button] [r] [g] [b]
|
||||
0-7 = buttons
|
||||
8 = woofer
|
||||
9 = center
|
||||
32: Set multiple. [00] [idx hi] [idx lo] [r] [g] [b]
|
||||
33: Fade multiple?. [09] [?] [?] [r] [g] [b]
|
||||
39: Set body light. [intensity] [-] [-]
|
||||
3b:
|
||||
3c: Commit?
|
||||
3f:
|
||||
|
||||
7c:
|
||||
7b:
|
||||
|
||||
initial setup: 7c 0-7, 32, 3c, 39, 3f, 3b
|
||||
*/
|
||||
|
||||
unsigned char COLOURS[10][3];
|
||||
double positions[10][2] = {
|
||||
{ 0.337963, 0.470833 }, { 0.469444, 0.619792 }, { 0.469444, 0.828125 }, { 0.337037, 0.977083 },
|
||||
{ 0.152778, 0.976042 }, { 0.020370, 0.828125 }, { 0.020370, 0.618750 }, { 0.151852, 0.472917 },
|
||||
{ 0.5, 0.75 }, { 0.5, 0.5 },
|
||||
};
|
||||
|
||||
typedef struct rs232c_recv_head {
|
||||
BYTE sync;
|
||||
BYTE src;
|
||||
BYTE dst;
|
||||
BYTE length;
|
||||
BYTE op;
|
||||
} rs232c_recv_head_t;
|
||||
|
||||
static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
log_warning("led_bd", "%ls woke up", dev->com->wName);
|
||||
while (1) {
|
||||
rs232c_recv_head_t head;
|
||||
if (comdev_available(dev) < sizeof head) {
|
||||
// Sleep(100);
|
||||
continue;
|
||||
}
|
||||
comdev_read(dev, (char*)&head, sizeof head);
|
||||
|
||||
unsigned char* extra = malloc(head.length);
|
||||
comdev_read(dev, extra, head.length);
|
||||
|
||||
// log_info("led_bd", "Bound %02x->%02x", head.src, head.dst);
|
||||
|
||||
switch (head.op) {
|
||||
case 0x01:
|
||||
log_warning("led_bd", "01");
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x01\x01\x18", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
log_warning("led_bd", "10");
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x10\x01\x27", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x31:
|
||||
COLOURS[extra[0]][0] = extra[1];
|
||||
COLOURS[extra[0]][1] = extra[2];
|
||||
COLOURS[extra[0]][2] = extra[3];
|
||||
|
||||
log_warning("led_bd", "31: %02x = (%02x %02x %02x)", extra[0], extra[1], extra[2], extra[3]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x31\x01\x48", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x32:
|
||||
log_warning("led_bd", "32: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
||||
extra[4], extra[5], extra[6], extra[7]);
|
||||
|
||||
for (unsigned char i = extra[2] - 1; i < extra[1]; i++) {
|
||||
COLOURS[i][0] = extra[3];
|
||||
COLOURS[i][1] = extra[4];
|
||||
COLOURS[i][2] = extra[5];
|
||||
}
|
||||
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x32\x01\x49", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x33:
|
||||
log_warning("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
||||
extra[4], extra[5], extra[6], extra[7]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x33\x01\x4a", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
COLOURS[extra[0]][0] = extra[extra[5]];
|
||||
COLOURS[extra[0]][1] = extra[extra[6]];
|
||||
COLOURS[extra[0]][2] = extra[extra[7]];
|
||||
break;
|
||||
|
||||
case 0x39:
|
||||
log_warning("led_bd", "39: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x39\x01\x50", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
|
||||
COLOURS[9][0] = extra[0];
|
||||
COLOURS[9][1] = extra[0];
|
||||
COLOURS[9][2] = extra[0];
|
||||
break;
|
||||
case 0x3b:
|
||||
log_warning("led_bd", "3b");
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x3b\x01\x52", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3c:
|
||||
log_warning("led_bd", "3c (I am %ls)", dev->com->wName);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x3c\x01\x53", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3f:
|
||||
log_warning("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
||||
extra[4], extra[5], extra[6]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x7c:
|
||||
// extra[0] goes from 0 to 7
|
||||
// Could this be some sort of calibration for the buttons?
|
||||
log_warning("led_bd", "7c: %02x", extra[0]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x04\x01\x7c\x01\x00\x94", 9);
|
||||
// \/ causes 7b to be used
|
||||
// comdev_write(dev, "\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9);
|
||||
// syn dst src len sts op. rep --- chk
|
||||
break;
|
||||
case 0x7b:
|
||||
log_warning("led_bd", "7b: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x7b\x01\x92", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("led_bd", "Unknown op %02x (%d)", head.op, head.length - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
free(extra);
|
||||
}
|
||||
}
|
||||
|
||||
static DWORD WINAPI led_null_thread(com_device_t* dev) {
|
||||
while (1) Sleep(10000000);
|
||||
}
|
||||
|
||||
void led_overlay(IDirect3DDevice9* dev) {
|
||||
ShowCursor(true);
|
||||
D3DDEVICE_CREATION_PARAMETERS cparams;
|
||||
RECT rect;
|
||||
|
||||
dev->lpVtbl->GetCreationParameters(dev, &cparams);
|
||||
GetClientRect(cparams.hFocusWindow, &rect);
|
||||
|
||||
if (GetAsyncKeyState(VK_LBUTTON) & 1) {
|
||||
POINT cursor;
|
||||
GetCursorPos(&cursor);
|
||||
|
||||
// log_info("led_overlay", "x: %d, y: %d", cursor.x, cursor.y);
|
||||
log_info("led_overlay", "x%: %f, y%: %f", (float)cursor.x / (float)rect.right,
|
||||
(float)(cursor.y - 26) / (float)rect.bottom);
|
||||
}
|
||||
|
||||
for (unsigned char i = 0; i < 10; i++) {
|
||||
int x = rect.right * positions[i][0];
|
||||
int y = rect.bottom * positions[i][1];
|
||||
draw_rect(dev, x - 25, y - 25, 50, 50, COLOURS[i][0], COLOURS[i][1], COLOURS[i][2]);
|
||||
}
|
||||
}
|
||||
|
||||
void install_led_bd() {
|
||||
register_gui_hook(&led_overlay);
|
||||
|
||||
com_device_t* com5 = new_com_device(5);
|
||||
com_device_thread(com5, led_null_thread);
|
||||
com_device_t* leds_1p = new_com_device(6);
|
||||
com_device_thread(leds_1p, led_bd_thread);
|
||||
com_device_t* com7 = new_com_device(7);
|
||||
com_device_thread(com7, led_null_thread);
|
||||
com_device_t* leds_2p = new_com_device(8);
|
||||
com_device_thread(leds_2p, led_bd_thread);
|
||||
}
|
5
src/micetools/dll/devices/meson.build
Normal file
5
src/micetools/dll/devices/meson.build
Normal file
@ -0,0 +1,5 @@
|
||||
devices_files = files(
|
||||
'_devices.c',
|
||||
'led_bd.c',
|
||||
'touch_bd.c',
|
||||
)
|
84
src/micetools/dll/devices/touch_bd.c
Normal file
84
src/micetools/dll/devices/touch_bd.c
Normal file
@ -0,0 +1,84 @@
|
||||
#include "_devices.h"
|
||||
|
||||
static BYTE read_one(com_device_t* dev) {
|
||||
while (!comdev_available(dev)) Sleep(50);
|
||||
BYTE data;
|
||||
comdev_read(dev, (char*)&data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
const BYTE TOUCH_ID_LUT[] = "ABCD\0EFGH\0IJKL\0MNOPQRSTU\0VWXY\0";
|
||||
static BYTE get_touch_id(BYTE id) {
|
||||
for (BYTE i = 0; i < sizeof(TOUCH_ID_LUT); i++) {
|
||||
if (TOUCH_ID_LUT[i] == id) return i;
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
BOOL touch_is_enabled = false;
|
||||
BYTE thresh = 0x00; // Lazy caching of single value
|
||||
DWORD WINAPI touch_bd_thread(com_device_t* dev) {
|
||||
while (1) {
|
||||
if (touch_is_enabled && !comdev_available(dev)) {
|
||||
// Active mode!
|
||||
comdev_write(dev, "(@@@@@@@@@@@@)", 14);
|
||||
Sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
||||
while (read_one(dev) != '{') continue;
|
||||
while (comdev_available(dev) < 5) {
|
||||
log_info("touch", "<. .>");
|
||||
Sleep(50);
|
||||
}
|
||||
BYTE command[5];
|
||||
comdev_read(dev, command, 5);
|
||||
BYTE response[6];
|
||||
memcpy(response, "( )", 6);
|
||||
|
||||
if (memcmp(command, "HALT}", 5) == 0) {
|
||||
if (touch_is_enabled)
|
||||
log_info("touch", "Touchscreen left active mode");
|
||||
else
|
||||
log_misc("touch", "Touchscreen not in active mode");
|
||||
touch_is_enabled = false;
|
||||
} else if (memcmp(command, "STAT}", 5) == 0) {
|
||||
if (!touch_is_enabled)
|
||||
log_info("touch", "Touchscreen entered active mode");
|
||||
else
|
||||
log_misc("touch", "Touchscreen already in active mode");
|
||||
touch_is_enabled = true;
|
||||
} else if (command[2] == 'k' && command[4] == '}') {
|
||||
BYTE sensor = get_touch_id(command[1]);
|
||||
|
||||
log_misc("touch", "k-command recieved: %d >=%d", sensor, command[3]);
|
||||
// Sensor == '@': failed
|
||||
// ( <L/R> <sensor> <> <> )
|
||||
response[1] = command[0];
|
||||
response[2] = command[1];
|
||||
thresh = command[3];
|
||||
|
||||
comdev_write(dev, response, 6);
|
||||
} else if (command[2] == 't' && command[3] == 'h' && command[4] == '}') {
|
||||
BYTE sensor = get_touch_id(command[1]);
|
||||
|
||||
// { <L/R> <sensor> t h }
|
||||
log_misc("touch", "th-command recieved: %d", sensor);
|
||||
|
||||
// Sensor == '@': failed
|
||||
// ( <L/R> <sensor> <> <threshold> )
|
||||
response[1] = command[0]; // 'L' or 'R'
|
||||
response[2] = command[1]; // Sensor
|
||||
response[4] = thresh;
|
||||
|
||||
comdev_write(dev, response, 6);
|
||||
} else {
|
||||
log_error("touch", "Unhandled: {%.*s", 5, command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void install_touch_bd() {
|
||||
com_device_t* touch = new_com_device(3);
|
||||
com_device_thread(touch, touch_bd_thread);
|
||||
}
|
@ -1,15 +1,7 @@
|
||||
#include <Windows.h>
|
||||
#include <Winsock2.h>
|
||||
#include <shlwapi.h>
|
||||
#pragma comment(lib, "Shlwapi.lib")
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "common.h"
|
||||
#include "devices/_devices.h"
|
||||
#include "drivers/mx.h"
|
||||
#include "micesetupapi.h"
|
||||
#include "network.h"
|
||||
#include "processes.h"
|
||||
#include "hooks/_hooks.h"
|
||||
|
||||
WCHAR exePath[MAX_PATH + 1];
|
||||
|
||||
@ -22,7 +14,7 @@ void enable_traces() {
|
||||
char exePathC[MAX_PATH + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, exePath, -1, exePathC, sizeof exePathC, NULL, NULL);
|
||||
|
||||
for (int i = 0; i < patches.nopatchsets; i++) {
|
||||
for (size_t i = 0; i < patches.nopatchsets; i++) {
|
||||
patchset_t* patchset = patches.patchsets[i];
|
||||
|
||||
// Require the binary explicitly named
|
||||
@ -31,7 +23,7 @@ void enable_traces() {
|
||||
}
|
||||
if (!patchset->apply) continue;
|
||||
|
||||
for (int j = 0; j < patchset->nopatches; j++) {
|
||||
for (size_t j = 0; j < patchset->nopatches; j++) {
|
||||
patch_t patch = patchset->patches[j];
|
||||
|
||||
if (memcmp(patch.from, (void*)patch.offset, patch.count) != 0) {
|
||||
@ -48,11 +40,14 @@ void enable_traces() {
|
||||
}
|
||||
|
||||
void prebind_hooks() {
|
||||
hook_setupapi();
|
||||
hook_commio();
|
||||
hook_io();
|
||||
hook_processes();
|
||||
hook_network();
|
||||
hook_all();
|
||||
install_devices();
|
||||
|
||||
// TODO: Figure out why we're needing to call this manually (medium priority)
|
||||
if (wcscmp(exePath, L"ALLNetProc.exe") == 0) {
|
||||
// OPENSSL_add_all_algorithms_noconf
|
||||
((void (*)(void))(0x00459770))();
|
||||
}
|
||||
}
|
||||
|
||||
void init_injection() {
|
||||
|
@ -1,8 +1,5 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../lib/dmi/dmi.h"
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "files.h"
|
||||
#include "mx.h"
|
||||
|
||||
// Much easier than pulling in winddk.h
|
||||
typedef LARGE_INTEGER PHYSICAL_ADDRESS, *PPHYSICAL_ADDRESS;
|
||||
@ -15,8 +12,9 @@ typedef struct {
|
||||
#define DMI_HEADER_START 0x000f0000
|
||||
#define DMI_TABLES_START 0x000f1000
|
||||
|
||||
BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
BOOL columba_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_COLUMBA_READ_DMI:
|
||||
log_misc("columba",
|
||||
@ -36,7 +34,7 @@ BOOL columba_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
||||
|
||||
if (request->addr.QuadPart == DMI_HEADER_START) {
|
||||
DMI_HEADER dmi = {
|
||||
.Signature = {'_', 'D', 'M', 'I', '_'},
|
||||
.Signature = { '_', 'D', 'M', 'I', '_' },
|
||||
.Checksum = 0,
|
||||
.StructLength = dmi_size,
|
||||
.StructAddr = DMI_TABLES_START,
|
||||
|
82
src/micetools/dll/drivers/jvs.h
Normal file
82
src/micetools/dll/drivers/jvs.h
Normal file
@ -0,0 +1,82 @@
|
||||
#define JVS_MARK 0xd0
|
||||
#define JVS_SYNC 0xe0
|
||||
#define JVS_NODE_MASTER 0x00
|
||||
#define JVS_NODE_BROADCAST 0xff
|
||||
|
||||
#define JVS_VERSION_CMD 0x13 // A real board reports 1.1, but we support 1.3
|
||||
#define JVS_VERSION_JVS 0x20
|
||||
#define JVS_VERSION_COMM 0x10
|
||||
|
||||
#define JVS_STATUS_OK 0x01
|
||||
#define JVS_STATUS_UKCOM 0x02
|
||||
#define JVS_STATUS_SUM 0x03
|
||||
#define JVS_STATUS_OVERFLOW 0x04
|
||||
#define JVS_STATUS_UNKNOWN 0xff // Not a spec-compliant status, but there's none for this!
|
||||
|
||||
#define JVS_REPORT_OK 0x01
|
||||
#define JVS_REPORT_PARAM_NODATA 0x02
|
||||
#define JVS_REPORT_PARAM_INVALID 0x03
|
||||
#define JVS_REPORT_BUSY 0x04
|
||||
|
||||
#define JVS_FEATURE_PAD 0x00
|
||||
#define JVS_FEATURE_EOF 0x00
|
||||
#define JVS_FEATURE_PLAYERS 0x01
|
||||
#define JVS_FEATURE_COINS 0x02
|
||||
#define JVS_FEATURE_ANALOG 0x03
|
||||
#define JVS_FEATURE_ROTARY 0x04
|
||||
#define JVS_FEATURE_KEYCODE 0x05
|
||||
#define JVS_FEATURE_SCREEN_POS 0x06
|
||||
#define JVS_FEATURE_MISC_SWITCH 0x07
|
||||
#define JVS_FEATURE_CARDS 0x10
|
||||
#define JVS_FEATURE_MEDAL_HOPPER 0x11
|
||||
#define JVS_FEATURE_GPIO 0x12
|
||||
#define JVS_FEATURE_ANALOG_OUT 0x13
|
||||
#define JVS_FEATURE_CHAR_OUT 0x14
|
||||
#define JVS_FEATURE_BACKUP 0x15
|
||||
|
||||
#define JVS_CHARTYPE_UNKNOWN 0x00
|
||||
#define JVS_CHARTYPE_NUMBER 0x01
|
||||
#define JVS_CHARTYPE_ALNUM 0x02
|
||||
#define JVS_CHARTYPE_ALNUM_KATAKANA 0x03
|
||||
#define JVS_CHARTYPE_SHIFTJIS 0x04
|
||||
|
||||
#define JVS_COINSLOT_NORMAL 0x00
|
||||
#define JVS_COINSLOT_JAM 0x01
|
||||
#define JVS_COINSLOT_COUNTER_DISCON 0x02
|
||||
#define JVS_COINSLOT_BUSY 0x03
|
||||
|
||||
// Mandatory JVS commands
|
||||
#define JVS_CMD_RESET 0xf0
|
||||
#define JVS_CMD_RESET_ASSERT 0xd9
|
||||
#define JVS_CMD_ASSIGN_ADDR 0xf1
|
||||
#define JVS_CMD_CHANGE_COMMS 0xf2
|
||||
|
||||
#define JVS_CMD_READ_ID 0x10
|
||||
#define JVS_CMD_GET_CMD_VERSION 0x11
|
||||
#define JVS_CMD_GET_JVS_VERSION 0x12
|
||||
#define JVS_CMD_GET_COMM_VERSION 0x13
|
||||
#define JVS_CMD_GET_FEATURES 0x14
|
||||
|
||||
#define JVS_CMD_REQUEST_RETRANSMIT 0x2f
|
||||
|
||||
// Optional JVS commands
|
||||
#define JVS_CMD_RECEIVE_MAIN_ID 0x15
|
||||
|
||||
#define JVS_CMD_READ_SW 0x20
|
||||
#define JVS_CMD_READ_COIN 0x21
|
||||
#define JVS_CMD_READ_ANALOGS 0x22
|
||||
#define JVS_CMD_READ_ROTARY 0x23
|
||||
#define JVS_CMD_READ_KEYCODE 0x24
|
||||
#define JVS_CMD_READ_SCREEN_POS 0x25
|
||||
#define JVS_CMD_READ_MISC_SWITCH 0x26
|
||||
#define JVS_CMD_REMAINING_PAYOUT 0x2e
|
||||
|
||||
#define JVS_CMD_COIN_DECREASE 0x30
|
||||
#define JVS_CMD_PAYOUT_INCREASE 0x31
|
||||
#define JVS_CMD_WRITE_GPIO1 0x32
|
||||
#define JVS_CMD_WRITE_ANALOG 0x33
|
||||
#define JVS_CMD_WRITE_CHARACTER 0x34
|
||||
#define JVS_CMD_COIN_INCREASE 0x35
|
||||
#define JVS_CMD_PAYOUT_DECREATE 0x36
|
||||
#define JVS_CMD_WRITE_GPIO2 0x37
|
||||
#define JVS_CMD_WRITE_GPIO3 0x38
|
9
src/micetools/dll/drivers/meson.build
Normal file
9
src/micetools/dll/drivers/meson.build
Normal file
@ -0,0 +1,9 @@
|
||||
drivers_files = files(
|
||||
'columba.c',
|
||||
'mxhwreset.c',
|
||||
'mxjvs.c',
|
||||
'mxparallel.c',
|
||||
'mxsmbus.c',
|
||||
'mxsram.c',
|
||||
'mxsuperio.c',
|
||||
)
|
@ -1,6 +1,6 @@
|
||||
#include "../com.h"
|
||||
#include "../files.h"
|
||||
#include <initguid.h>
|
||||
#pragma once
|
||||
#include "../hooks/_hooks.h"
|
||||
#include "../common.h"
|
||||
|
||||
FnDeviceIoControl mxhwreset_DeviceIoControl;
|
||||
void setup_mxhwreset();
|
||||
@ -20,5 +20,8 @@ void setup_mxsram();
|
||||
FnDeviceIoControl mxsuperio_DeviceIoControl;
|
||||
void setup_mxsuperio();
|
||||
|
||||
FnDeviceIoControl columba_DeviceIoControl;
|
||||
void setup_columba();
|
||||
|
||||
DEFINE_GUID(MXSMBUS_GUID, 0x5C49E1FE, 0x3FEC, 0x4B8D, 0xA4, 0xB5, 0x76, 0xBE, 0x70, 0x25, 0xD8, 0x42);
|
||||
DEFINE_GUID(PLATFORM_GUID, 0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3e, 0x30, 0x1F, 0x73);
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "mx.h"
|
||||
|
||||
BOOL mxhwreset_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
BOOL mxhwreset_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_MXHWRESET_RESET:
|
||||
if (lpBytesReturned) *lpBytesReturned = 0;
|
||||
|
@ -1,25 +1,336 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "../common.h"
|
||||
#include "jvs.h"
|
||||
#include "mx.h"
|
||||
|
||||
BOOL JVS_SENSE = false;
|
||||
BOOL coin_solenoid = false;
|
||||
BOOL test_btn = false;
|
||||
|
||||
BOOL mxjvs_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
// #define SCAN_COIN 0x70
|
||||
#define SCAN_TEST VK_OEM_4 // [{
|
||||
// 2 Players, 16 buttons each
|
||||
int jvs_buttons[2][16] = {
|
||||
{
|
||||
'C', // *1P3
|
||||
'P', // NC
|
||||
'E', // *1P1
|
||||
'D', // *1P2
|
||||
'P', // NC
|
||||
'P', // NC
|
||||
'1', // *1P Service
|
||||
'P', // NC
|
||||
'P', // --
|
||||
'P', // --
|
||||
'P', // --
|
||||
'W', // *1P8
|
||||
'Q', // *1P7
|
||||
'A', // *1P6
|
||||
'Z', // *1P5
|
||||
'X', // *1P4
|
||||
},
|
||||
{
|
||||
VK_OEM_PERIOD, // *2P3
|
||||
'P', // NC
|
||||
'O', // *2P1
|
||||
'L', // *2P2
|
||||
'P', // NC
|
||||
'P', // NC
|
||||
'2', // *2P Service
|
||||
'P', // NC
|
||||
'P', // --
|
||||
'P', // --
|
||||
'P', // --
|
||||
'I', // *2P8
|
||||
'U', // *2P7
|
||||
'J', // *2P6
|
||||
'M', // *2P5
|
||||
VK_OEM_COMMA, // *2P4
|
||||
},
|
||||
};
|
||||
|
||||
short jvs_unpad(char* paddedData, short length, char* unpaddedData) {
|
||||
short index = 0;
|
||||
bool escape = false;
|
||||
for (short i = 0; i < length; i++) {
|
||||
if (escape)
|
||||
unpaddedData[index++] = paddedData[i] + 1;
|
||||
else if (paddedData[i] == JVS_MARK)
|
||||
escape = true;
|
||||
else
|
||||
unpaddedData[index++] = paddedData[i];
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
short jvs_pad(char* unpaddedData, short length, char* paddedData, short paddedMax) {
|
||||
short index = 0;
|
||||
for (short i = 0; i < length; i++) {
|
||||
if (i > paddedMax) return -1;
|
||||
|
||||
if (unpaddedData[i] == JVS_MARK || unpaddedData[i] == JVS_SYNC) {
|
||||
paddedData[index++] = JVS_MARK;
|
||||
paddedData[index++] = unpaddedData[i] - 1;
|
||||
} else {
|
||||
paddedData[index++] = unpaddedData[i];
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
const char JVS_ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10";
|
||||
|
||||
void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, int* outCount) {
|
||||
unsigned char* inData = malloc(inCount);
|
||||
inCount = jvs_unpad(paddedIn, inCount, inData);
|
||||
unsigned char* response = malloc(maxOut);
|
||||
|
||||
unsigned char status = JVS_STATUS_OK;
|
||||
|
||||
// JVS frame is 4 bytes in total
|
||||
if (inCount < 4) {
|
||||
log_error("mxjvs", "inCount impossibly small: %d", inCount);
|
||||
status = JVS_STATUS_UNKNOWN;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
// This isn't a JVS packet
|
||||
if (inData[0] != JVS_SYNC) {
|
||||
log_error("mxjvs", "SYNC missing. Saw 0x%02x", inData[0]);
|
||||
status = JVS_STATUS_UNKNOWN;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
|
||||
// Validate the checksum before proceeding
|
||||
unsigned char sum = 0;
|
||||
for (int i = 1; i < inCount - 1; i++) sum += inData[i];
|
||||
if (sum != inData[inCount - 1]) {
|
||||
log_error("mxjvs", "Checksum failed. Computed 0x%02x, expected 0x%02x", sum, inData[inCount - 1]);
|
||||
status = JVS_STATUS_SUM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
|
||||
unsigned char destination = inData[1];
|
||||
unsigned char length = inData[2];
|
||||
// length 0 is nonsensical because there's a checksum!
|
||||
if (length == 0) {
|
||||
status = JVS_STATUS_SUM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
short jvsIndex = 3; // D0
|
||||
|
||||
response[0] = JVS_SYNC;
|
||||
response[1] = JVS_NODE_MASTER;
|
||||
short respIndex = 4; // D0
|
||||
#define jvs_read(x) \
|
||||
if (jvsIndex - 2 >= length) { \
|
||||
status = JVS_STATUS_OVERFLOW; \
|
||||
goto jvs_exchange_error; \
|
||||
} else { \
|
||||
(x) = inData[jvsIndex++]; \
|
||||
}
|
||||
#define jvs_write(x) response[respIndex++] = (x);
|
||||
|
||||
while (jvsIndex - 2 < length) {
|
||||
unsigned char cmd;
|
||||
jvs_read(cmd);
|
||||
// log_info("jvs", "jvs cmd: %02x", cmd);
|
||||
switch (cmd) {
|
||||
case JVS_CMD_RESET:
|
||||
unsigned char reset_assert;
|
||||
jvs_read(reset_assert);
|
||||
if (reset_assert != JVS_CMD_RESET_ASSERT) {
|
||||
status = JVS_STATUS_UKCOM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
JVS_SENSE = true;
|
||||
// Special case
|
||||
*outCount = 0;
|
||||
return;
|
||||
case JVS_CMD_CHANGE_COMMS:
|
||||
// Special case
|
||||
*outCount = 0;
|
||||
return;
|
||||
|
||||
case JVS_CMD_ASSIGN_ADDR:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
JVS_SENSE = false;
|
||||
// we don't bother remembering the address because at the moment we only simulate
|
||||
// a single board in the JVS chain.
|
||||
unsigned char _;
|
||||
jvs_read(_);
|
||||
break;
|
||||
|
||||
case JVS_CMD_READ_ID:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
for (int i = 0; i < sizeof JVS_ID; i++) jvs_write(JVS_ID[i]);
|
||||
break;
|
||||
case JVS_CMD_GET_CMD_VERSION:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
jvs_write(JVS_VERSION_CMD);
|
||||
break;
|
||||
case JVS_CMD_GET_JVS_VERSION:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
jvs_write(JVS_VERSION_JVS);
|
||||
break;
|
||||
case JVS_CMD_GET_COMM_VERSION:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
jvs_write(JVS_VERSION_COMM);
|
||||
break;
|
||||
|
||||
case JVS_CMD_GET_FEATURES:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
|
||||
jvs_write(JVS_FEATURE_PLAYERS);
|
||||
jvs_write(2);
|
||||
jvs_write(13);
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_COINS);
|
||||
jvs_write(2);
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_ANALOG);
|
||||
jvs_write(8); // 8 ADC channels
|
||||
jvs_write(JVS_FEATURE_PAD); // ?? (was "10" prior)
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_GPIO);
|
||||
jvs_write(6); // 6 ports
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
jvs_write(JVS_FEATURE_PAD);
|
||||
|
||||
jvs_write(JVS_FEATURE_EOF);
|
||||
|
||||
break;
|
||||
case JVS_CMD_RECEIVE_MAIN_ID:
|
||||
unsigned char tempRead = -1;
|
||||
while (tempRead != 0) jvs_read(tempRead);
|
||||
// TODO: Do we need to report here?
|
||||
break;
|
||||
|
||||
case JVS_CMD_READ_SW:
|
||||
unsigned char players;
|
||||
unsigned char switch_bytes;
|
||||
jvs_read(players);
|
||||
jvs_read(switch_bytes);
|
||||
if (players > 2 || switch_bytes != 2) {
|
||||
jvs_write(JVS_REPORT_PARAM_INVALID);
|
||||
break;
|
||||
}
|
||||
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
unsigned char buttons = 0x00;
|
||||
if (GetAsyncKeyState(SCAN_TEST) < 0) buttons |= 0x80;
|
||||
jvs_write(buttons);
|
||||
|
||||
for (int i = 0; i < players; i++) {
|
||||
for (int j = 0; j < switch_bytes; j++) {
|
||||
buttons = 0x00;
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
int scancode = jvs_buttons[i][j * 8 + bit];
|
||||
|
||||
// Buttons on maimai use beam interrupt sensors, so logical high = unpressed.
|
||||
bool invert = ((j == 0 && (bit == 0 || bit == 2 || bit == 3)) || (j == 1 && bit >= 3));
|
||||
|
||||
if (invert)
|
||||
buttons |= (GetAsyncKeyState(scancode) >= 0) << bit;
|
||||
else
|
||||
buttons |= (GetAsyncKeyState(scancode) < 0) << bit;
|
||||
|
||||
// JAMMA does **NOT** do any of this lol
|
||||
// Service is pull-down for some reason
|
||||
// bool pulse = (j == 0) && (bit == 6);
|
||||
// // JAMMA uses the falling edge of a pull-up switch
|
||||
// if (pulse) {
|
||||
// buttons |= (GetAsyncKeyState(scancode) >= 0) << bit;
|
||||
// buttons |= (!(GetAsyncKeyState(scancode) & 1)) << bit;
|
||||
// } else {
|
||||
// buttons |= (GetAsyncKeyState(scancode) < 0) << bit;
|
||||
// buttons |= (GetAsyncKeyState(scancode) & 1) << bit;
|
||||
// }
|
||||
}
|
||||
jvs_write(buttons);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case JVS_CMD_READ_ANALOGS:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
// TODO: Actually emulate these (super low priority)
|
||||
unsigned char analog_count;
|
||||
jvs_read(analog_count);
|
||||
for (int i = analog_count; i > 0; i--) {
|
||||
jvs_write(0xde);
|
||||
jvs_write(0xad);
|
||||
}
|
||||
break;
|
||||
|
||||
case JVS_CMD_WRITE_GPIO1:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
unsigned char gpio_bytes;
|
||||
jvs_read(gpio_bytes);
|
||||
for (int i = 0; i < gpio_bytes; i++) {
|
||||
unsigned char gpio_value;
|
||||
jvs_read(gpio_value);
|
||||
|
||||
if (i == 0) {
|
||||
if (!!(gpio_value & 0x80) != coin_solenoid) {
|
||||
coin_solenoid = !!(gpio_value & 0x80);
|
||||
log_info("mxjvs", "Coin solenoid: %s", coin_solenoid ? "Locked" : "Unlocked");
|
||||
}
|
||||
}
|
||||
|
||||
// log_warning("mxjvs", "Unhandled GPIO write: *(%d) = %02x", i, gpio_value);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("mxjvs", "Unknown command: 0x%02x", cmd);
|
||||
|
||||
status = JVS_STATUS_UKCOM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
}
|
||||
#undef jvs_read
|
||||
#undef jvs_write
|
||||
|
||||
goto jvs_exchange_complete;
|
||||
jvs_exchange_error:
|
||||
log_error("mxjvs", "JVS status: 0x%02x", status);
|
||||
respIndex = 4; // As if we've just written status, but nothing else
|
||||
|
||||
jvs_exchange_complete:
|
||||
response[2] = respIndex - 2; // respIndex doesn't include SUM yet
|
||||
response[3] = status;
|
||||
|
||||
// Compute and set the checksum
|
||||
sum = 0;
|
||||
for (int i = 1; i < respIndex; i++) sum += response[i];
|
||||
response[respIndex++] = sum;
|
||||
|
||||
short paddedLength = jvs_pad(response, respIndex, outData, maxOut);
|
||||
// We failed hard. It's not worth sending an overflow response
|
||||
if (paddedLength == -1)
|
||||
*outCount = 0;
|
||||
else
|
||||
*outCount = 0x00000000 | paddedLength;
|
||||
|
||||
free(response);
|
||||
free(inData);
|
||||
}
|
||||
|
||||
BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_MXJVS_EXCHANGE:
|
||||
log_error("mxjvs",
|
||||
log_misc("mxjvs",
|
||||
"DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, "
|
||||
"0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
// mxjvsDevice->exchange(
|
||||
// lpbyte(lpInBuffer), nInBufferSize & 0xFFFF,
|
||||
// lpbyte(lpOutBuffer), lpBytesReturned
|
||||
// );
|
||||
mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize, lpBytesReturned);
|
||||
|
||||
if (lpBytesReturned) *lpBytesReturned = 0;
|
||||
break;
|
||||
default:
|
||||
log_warning("mxjvs", "unhandled 0x%08x", dwIoControlCode);
|
||||
@ -35,13 +346,13 @@ BOOL mxjvs_GetCommState(void* com, LPDCB lpDCB) { return TRUE; }
|
||||
BOOL mxjvs_SetCommTimeouts(void* com, LPCOMMTIMEOUTS lpDCB) { return TRUE; }
|
||||
|
||||
BOOL mxjvs_GetCommModemStatus(void* com, LPDWORD lpModelStat) {
|
||||
*lpModelStat = JVS_SENSE ? MS_DSR_ON : 0;
|
||||
*lpModelStat = !JVS_SENSE ? MS_DSR_ON : 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) {
|
||||
char PARITY[] = {'N', 'O', 'E', 'M', 'S'};
|
||||
char* STOP[] = {"1", "1.5", "2"};
|
||||
char PARITY[] = { 'N', 'O', 'E', 'M', 'S' };
|
||||
char* STOP[] = { "1", "1.5", "2" };
|
||||
log_info("mxjvs", "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize, PARITY[lpDCB->Parity],
|
||||
STOP[lpDCB->StopBits]);
|
||||
return TRUE;
|
||||
|
@ -1,7 +1,5 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../lib/dmi/dmi.h"
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "../hooks/setupapi_.h"
|
||||
#include "mx.h"
|
||||
#include "smbus.h"
|
||||
|
||||
@ -18,8 +16,17 @@
|
||||
#define PCA9535_CONF0 0x06
|
||||
#define PCA9535_CONF1 0x07
|
||||
|
||||
#define PCA9535 0x20
|
||||
#define EEPROM 0x57
|
||||
#define SMBUS_PCA9535 0x20
|
||||
#define SMBUS_EEPROM 0x57 // Doesn't line up with manual!
|
||||
|
||||
#define SMBUS_DDR2_DIMM_A1 0x000 // what does 0xA0 mean?
|
||||
#define SMBUS_DDR2_DIMM_B1 0x010 // what does 0xA4 mean?
|
||||
#define SMBUS_EEPROM_ 0x0AE // = AT24C64AN
|
||||
#define SMBUS_ICS9LPRS908 0xfff // Unknown
|
||||
#define SMBUS_W83627UHG 0xfff // Unknown; hwmon. Possibly 0x2e or 0x4e
|
||||
#define SMBUS_UPI_UP6261BM8 0xfff // Unknown; vref
|
||||
#define SMBUS_UPI_ISL6322CR 0xfff // Unknown; vrm
|
||||
// SMBUS is send onto the mezzanine board!
|
||||
|
||||
#define EEPROM_DUMP L"dev/eeprom.bin"
|
||||
typedef struct eeprom_reg {
|
||||
@ -39,53 +46,6 @@ eeprom_bank_t EEPROM_DATA;
|
||||
* - Reg 0x0e: Stores
|
||||
*/
|
||||
|
||||
typedef uint_fast32_t crc_t;
|
||||
|
||||
static const crc_t crc_table[256] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832,
|
||||
0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a,
|
||||
0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3,
|
||||
0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab,
|
||||
0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4,
|
||||
0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074,
|
||||
0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525,
|
||||
0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615,
|
||||
0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76,
|
||||
0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6,
|
||||
0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7,
|
||||
0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7,
|
||||
0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278,
|
||||
0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330,
|
||||
0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
||||
#define CRC_ALGO_TABLE_DRIVEN 1
|
||||
static inline crc_t crc_init(void) { return 0xffffffff; }
|
||||
crc_t crc_update(crc_t crc, const void* data, size_t data_len) {
|
||||
const unsigned char* d = (const unsigned char*)data;
|
||||
unsigned int tbl_idx;
|
||||
|
||||
while (data_len--) {
|
||||
tbl_idx = (crc ^ *d) & 0xff;
|
||||
crc = (crc_table[tbl_idx] ^ (crc >> 8)) & 0xffffffff;
|
||||
d++;
|
||||
}
|
||||
return crc & 0xffffffff;
|
||||
}
|
||||
static inline crc_t crc_finalize(crc_t crc) { return crc ^ 0xffffffff; }
|
||||
|
||||
void eeprom_dump() {
|
||||
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
@ -107,11 +67,14 @@ void eeprom_restore() {
|
||||
}
|
||||
|
||||
DWORD eeprom_crc(BYTE reg) {
|
||||
if (reg == 0x80 || reg == 0x280) {
|
||||
if (reg == 0x04 || reg == 0x14 || reg == 0x80 || reg == 0x280) {
|
||||
// Some registers are only treated as 16 byte values
|
||||
return crc_finalize(crc_update(crc_init(), EEPROM_DATA.reg[reg].data + 4, 12));
|
||||
crc32_build_table();
|
||||
return crc32(12, EEPROM_DATA.reg[reg].data + 4, 0);
|
||||
}
|
||||
return crc_finalize(crc_update(crc_init(), EEPROM_DATA.reg[reg].data + 4, 28));
|
||||
|
||||
crc32_build_table();
|
||||
return crc32(28, EEPROM_DATA.reg[reg].data + 4, 0);
|
||||
}
|
||||
void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) {
|
||||
eeprom_restore();
|
||||
@ -149,8 +112,9 @@ BYTE eeprom_read_one(BYTE reg, BYTE index) {
|
||||
}
|
||||
void eeprom_write_one(BYTE reg, BYTE index, BYTE data) { eeprom_write(reg, index, &data, 1); }
|
||||
|
||||
BOOL mxsmbus_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
BOOL mxsmbus_DeviceIoControl(void* file, 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;
|
||||
|
||||
@ -203,7 +167,7 @@ BOOL mxsmbus_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
||||
// 48: addr 0x00: amHmGetLPCChipId
|
||||
|
||||
switch (i2c_packet->addr) {
|
||||
case PCA9535:
|
||||
case SMBUS_PCA9535:
|
||||
switch (i2c_packet->prt) {
|
||||
case PCA9535_WRITE:
|
||||
switch (i2c_packet->reg) {
|
||||
@ -232,12 +196,22 @@ BOOL mxsmbus_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
||||
case PCA9535_IN0: // DIPSW
|
||||
i2c_packet->data[0] = 0x00;
|
||||
break;
|
||||
case PCA9535_IN1: // What's this one?
|
||||
i2c_packet->data[0] = 0x00;
|
||||
case PCA9535_IN1: // SW1/2 + extras
|
||||
/*
|
||||
0: uk
|
||||
1: uk
|
||||
2: ¬test
|
||||
3: ¬service
|
||||
4: uk
|
||||
5: uk
|
||||
6: uk
|
||||
7: uk
|
||||
*/
|
||||
i2c_packet->data[0] = 0x0c;
|
||||
break;
|
||||
case PCA9535_INV0:
|
||||
case PCA9535_INV1:
|
||||
case PCA9535_OUT1:
|
||||
case PCA9535_OUT1: // LEDs, probably
|
||||
i2c_packet->data[0] = 0x00;
|
||||
break;
|
||||
default:
|
||||
@ -254,7 +228,7 @@ BOOL mxsmbus_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case EEPROM:
|
||||
case SMBUS_EEPROM:
|
||||
switch (i2c_packet->prt) {
|
||||
case 3: // Wait
|
||||
// 0x18 = wait, 0x00 = done
|
||||
@ -311,7 +285,7 @@ BOOL mxsmbus_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nIn
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (request_packet->addr != EEPROM) {
|
||||
if (request_packet->addr != SMBUS_EEPROM) {
|
||||
log_error("mxsmbus", "Unexpected I2C device: 0x%02x", request_packet->addr);
|
||||
exit(1);
|
||||
}
|
||||
|
@ -1,6 +1,3 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "mx.h"
|
||||
|
||||
#define SRAM_DUMP L"dev/sram.bin"
|
||||
@ -27,8 +24,9 @@ void sram_restore() {
|
||||
_CloseHandle(dump);
|
||||
}
|
||||
|
||||
BOOL mxsram_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
DWORD SRAM_VERSION = 0x0001;
|
||||
DWORD SRAM_SECTOR_SIZE = 0x100; // Max is 0x800
|
||||
|
||||
@ -74,7 +72,7 @@ BOOL mxsram_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInB
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
DWORD mxsram_SetFilePointer(LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||
DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||
if (dwMoveMethod == FILE_BEGIN) {
|
||||
SRAM_POINTER = lDistanceToMove;
|
||||
} else if (dwMoveMethod == FILE_CURRENT) {
|
||||
@ -83,7 +81,7 @@ DWORD mxsram_SetFilePointer(LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DW
|
||||
return SRAM_POINTER;
|
||||
}
|
||||
|
||||
BOOL mxsram_WriteFile(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
BOOL mxsram_WriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
log_misc("mxsram", "sram write 0x%08x (0x%04x bytes)", SRAM_POINTER, nNumberOfBytesToWrite);
|
||||
if (SRAM_POINTER + nNumberOfBytesToWrite >= SRAM_SIZE) {
|
||||
@ -95,7 +93,7 @@ BOOL mxsram_WriteFile(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpN
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL mxsram_ReadFile(LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
BOOL mxsram_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
log_misc("mxsram", "sram read 0x%08x (0x%04x bytes)", SRAM_POINTER, nNumberOfBytesToRead);
|
||||
if (SRAM_POINTER + nNumberOfBytesToRead >= SRAM_SIZE) {
|
||||
|
@ -1,6 +1,3 @@
|
||||
#include <Windows.h>
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#include "mx.h"
|
||||
#include "smbus.h"
|
||||
#include "w83791d.h"
|
||||
@ -16,8 +13,9 @@ BYTE w83791d_crit_t3 = 80; // C
|
||||
BYTE w83791d_vbat_monitor_control = 0x00;
|
||||
BOOL w83791d_4f_high = 0;
|
||||
|
||||
BOOL mxsuperio_DeviceIoControl(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
mxsuperio_lpc_packet* lpc_packet = (mxsuperio_lpc_packet*)lpInBuffer;
|
||||
mxsuperio_lpc_packet* lpc_out = (mxsuperio_lpc_packet*)lpOutBuffer;
|
||||
|
||||
|
@ -1,64 +0,0 @@
|
||||
#pragma once
|
||||
#include <Windows.h>
|
||||
|
||||
static HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
static HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess,
|
||||
DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
|
||||
static BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
static DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove,
|
||||
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
static BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||
|
||||
static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject);
|
||||
|
||||
typedef BOOL(FnDeviceIoControl)(DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef DWORD(FnSetFilePointer)(LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod);
|
||||
typedef BOOL(FnWriteFile)(LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnReadFile)(LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
static int(WINAPIV *True_stat64i32)(const char* path, struct _stat64i32* buffer);
|
||||
|
||||
#define _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile)
|
||||
#define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile)
|
||||
#define _CloseHandle (TrueCloseHandle ? TrueCloseHandle : CloseHandle)
|
||||
#define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW)
|
||||
|
||||
typedef struct drive_redirect {
|
||||
const CHAR* drive;
|
||||
const CHAR* path;
|
||||
} drive_redirect_t;
|
||||
|
||||
typedef struct file_hook {
|
||||
LPCWSTR filename;
|
||||
|
||||
FnDeviceIoControl* DeviceIoControl;
|
||||
FnSetFilePointer* SetFilePointer;
|
||||
FnWriteFile* WriteFile;
|
||||
FnReadFile* ReadFile;
|
||||
|
||||
LPHANDLE virtual_handle;
|
||||
struct file_hook* next;
|
||||
} file_hook_t;
|
||||
|
||||
file_hook_t* new_file_hook(LPCWSTR filename);
|
||||
void hook_file(file_hook_t* hook);
|
||||
void hook_io();
|
12
src/micetools/dll/hooks/_hooks.c
Normal file
12
src/micetools/dll/hooks/_hooks.c
Normal file
@ -0,0 +1,12 @@
|
||||
#include "_hooks.h"
|
||||
|
||||
void hook_all() {
|
||||
hook_logging();
|
||||
hook_gui();
|
||||
hook_setupapi();
|
||||
hook_commio();
|
||||
hook_io();
|
||||
hook_processes();
|
||||
hook_network();
|
||||
hook_time();
|
||||
}
|
12
src/micetools/dll/hooks/_hooks.h
Normal file
12
src/micetools/dll/hooks/_hooks.h
Normal file
@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "com.h"
|
||||
#include "files.h"
|
||||
#include "gui.h"
|
||||
#include "logging.h"
|
||||
#include "network.h"
|
||||
#include "processes.h"
|
||||
#include "setupapi_.h"
|
||||
#include "time.h"
|
||||
|
||||
void hook_all();
|
@ -1,12 +1,13 @@
|
||||
#include "com.h"
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
|
||||
com_hook_t* com_hook_list = NULL;
|
||||
com_hook_t* new_com_hook(BYTE port) {
|
||||
com_hook_t* hook = (com_hook_t*)malloc(sizeof *hook);
|
||||
|
||||
memset(hook->wName, 0, sizeof hook->wName);
|
||||
swprintf(hook->wName, (sizeof hook->wName) / (sizeof hook->wName[0]), L"COM%d", port);
|
||||
memset(hook->wDosName, 0, sizeof hook->wDosName);
|
||||
swprintf(hook->wDosName, (sizeof hook->wDosName) / (sizeof hook->wDosName[0]), L"\\\\.\\COM%d", port);
|
||||
hook->com = port;
|
||||
|
||||
hook->GetCommState = NULL;
|
@ -1,6 +1,6 @@
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#pragma once
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
static BOOL(WINAPI* TrueGetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
static BOOL(WINAPI* TrueSetCommState)(HANDLE hFile, LPDCB lpDCB);
|
||||
@ -24,7 +24,8 @@ typedef BOOL(FnClearCommError)(void* com, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
||||
|
||||
typedef struct com_hook {
|
||||
LPHANDLE virtual_handle;
|
||||
WCHAR wName[7]; // max is COM255
|
||||
WCHAR wName[7]; // max is "COM255"
|
||||
WCHAR wDosName[11]; // max is "\\\\.\\COM255"
|
||||
BYTE com;
|
||||
|
||||
FnGetCommState* GetCommState;
|
||||
@ -44,4 +45,5 @@ typedef struct com_hook {
|
||||
|
||||
com_hook_t* new_com_hook(BYTE port);
|
||||
void hook_com(com_hook_t* hook);
|
||||
void hook_com();
|
||||
|
||||
void hook_commio();
|
@ -1,20 +1,14 @@
|
||||
#include "files.h"
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
|
||||
HANDLE fake_handle = (HANDLE)0x10000000;
|
||||
|
||||
file_hook_t* file_hook_list = NULL;
|
||||
file_hook_t* new_file_hook(LPCWSTR filename) {
|
||||
file_hook_t* hook = (file_hook_t*)malloc(sizeof(file_hook_t));
|
||||
memset(hook, 0, sizeof(file_hook_t));
|
||||
|
||||
hook->filename = filename;
|
||||
|
||||
hook->DeviceIoControl = NULL;
|
||||
hook->SetFilePointer = NULL;
|
||||
hook->WriteFile = NULL;
|
||||
hook->ReadFile = NULL;
|
||||
|
||||
return hook;
|
||||
}
|
||||
void hook_file(file_hook_t* hook) {
|
||||
@ -32,8 +26,11 @@ void hook_file(file_hook_t* hook) {
|
||||
};
|
||||
|
||||
drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
|
||||
{.drive = "Y:\\", .path = ".\\dev\\Y\\"},
|
||||
{.drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\"}};
|
||||
{ .drive = "Y:\\", .path = ".\\dev\\Y\\" },
|
||||
// Note: Had tp create last_shime.log
|
||||
{ .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" },
|
||||
// {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"},
|
||||
};
|
||||
|
||||
char* redirect_path(char* path) {
|
||||
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
|
||||
@ -66,13 +63,16 @@ HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD d
|
||||
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (wcscmp(lpFileName, hook->filename) == 0) {
|
||||
if (wcscmp(lpFileName, hook->filename) == 0 ||
|
||||
(hook->altFilename != NULL && wcscmp(lpFileName, hook->altFilename) == 0)) {
|
||||
if (*hook->virtual_handle == NULL) {
|
||||
// TODO: Assign handles better!
|
||||
*hook->virtual_handle = fake_handle;
|
||||
((size_t)fake_handle)++;
|
||||
}
|
||||
handle = *hook->virtual_handle;
|
||||
|
||||
log_info(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
|
||||
break;
|
||||
}
|
||||
hook = hook->next;
|
||||
@ -113,8 +113,12 @@ BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lp
|
||||
// TODO: Less jank
|
||||
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
|
||||
|
||||
return hook->DeviceIoControl(dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize,
|
||||
lpBytesReturned, lpOverlapped);
|
||||
BOOL ret = hook->DeviceIoControl(hook->data, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
|
||||
nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
if (ret && lpOverlapped && lpBytesReturned) {
|
||||
lpOverlapped->InternalHigh = *lpBytesReturned;
|
||||
}
|
||||
return ret;
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "DeviceIoControl(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
@ -134,7 +138,7 @@ DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDist
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
if (hook->SetFilePointer) {
|
||||
return hook->SetFilePointer(lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||
return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "SetFilePointer(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
@ -146,13 +150,49 @@ DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDist
|
||||
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
DWORD dwMoveMethod) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
if (hook->SetFilePointerEx) {
|
||||
return hook->SetFilePointerEx(hook->data, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "SetFilePointerEx(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
if (hook->GetFileSizeEx) {
|
||||
return hook->GetFileSizeEx(hook->data, lpFileSize);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "GetFileSizeEx(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueGetFileSizeEx(hFile, lpFileSize);
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
if (hook->WriteFile) {
|
||||
return hook->WriteFile(lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
|
||||
return hook->WriteFile(hook->data, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||
lpOverlapped);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
@ -170,7 +210,7 @@ BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRe
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
if (hook->ReadFile) {
|
||||
return hook->ReadFile(lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
|
||||
return hook->ReadFile(hook->data, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
@ -185,7 +225,8 @@ BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRe
|
||||
BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (hook->virtual_handle == hObject) {
|
||||
if (hObject != NULL && *hook->virtual_handle == hObject) {
|
||||
log_misc("file", "close %08x", hObject);
|
||||
return TRUE;
|
||||
}
|
||||
hook = hook->next;
|
||||
@ -206,8 +247,10 @@ void hook_io() {
|
||||
|
||||
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("MSVCR90.DLL", "_stat64i32", Fake_stat64i32, (void**)&True_stat64i32, 5);
|
||||
}
|
72
src/micetools/dll/hooks/files.h
Normal file
72
src/micetools/dll/hooks/files.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
#include "../common.h"
|
||||
|
||||
static HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
static HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
|
||||
static BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
static DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod);
|
||||
static BOOL(WINAPI* TrueSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
DWORD dwMoveMethod);
|
||||
// logging needs access to WriteFile, so we can't static it!
|
||||
BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||
static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject);
|
||||
|
||||
typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef DWORD(FnSetFilePointer)(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
typedef BOOL(FnSetFilePointerEx)(void* file, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
DWORD dwMoveMethod);
|
||||
typedef BOOL(FnWriteFile)(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnReadFile)(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef BOOL(FnGetFileSizeEx)(void* file, PLARGE_INTEGER lpFileSize);
|
||||
|
||||
static int(WINAPIV* True_stat64i32)(const char* path, struct _stat64i32* buffer);
|
||||
|
||||
#define _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile)
|
||||
#define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile)
|
||||
#define _CloseHandle (TrueCloseHandle ? TrueCloseHandle : CloseHandle)
|
||||
#define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW)
|
||||
|
||||
typedef struct drive_redirect {
|
||||
const CHAR* drive;
|
||||
const CHAR* path;
|
||||
} drive_redirect_t;
|
||||
|
||||
typedef struct file_hook {
|
||||
LPCWSTR filename;
|
||||
LPCWSTR altFilename;
|
||||
|
||||
FnDeviceIoControl* DeviceIoControl;
|
||||
FnSetFilePointer* SetFilePointer;
|
||||
FnSetFilePointerEx* SetFilePointerEx;
|
||||
FnWriteFile* WriteFile;
|
||||
FnReadFile* ReadFile;
|
||||
FnGetFileSizeEx* GetFileSizeEx;
|
||||
|
||||
void* data;
|
||||
|
||||
LPHANDLE virtual_handle;
|
||||
struct file_hook* next;
|
||||
} file_hook_t;
|
||||
|
||||
file_hook_t* new_file_hook(LPCWSTR filename);
|
||||
void hook_file(file_hook_t* hook);
|
||||
void hook_io();
|
111
src/micetools/dll/hooks/gui.c
Normal file
111
src/micetools/dll/hooks/gui.c
Normal file
@ -0,0 +1,111 @@
|
||||
#include "gui.h"
|
||||
|
||||
static HWND window;
|
||||
BOOL CALLBACK EnumWindowsCallback(HWND handle, LPARAM lParam) {
|
||||
DWORD wndProcId;
|
||||
GetWindowThreadProcessId(handle, &wndProcId);
|
||||
|
||||
if (GetCurrentProcessId() != wndProcId) return TRUE;
|
||||
|
||||
window = handle;
|
||||
return FALSE;
|
||||
}
|
||||
HWND GetProcessWindow() {
|
||||
window = NULL;
|
||||
EnumWindows(EnumWindowsCallback, 0);
|
||||
return window;
|
||||
}
|
||||
BOOL GetD3D9Device(void** pTable, size_t Size) {
|
||||
if (!pTable) return false;
|
||||
|
||||
IDirect3D9* pD3D = Direct3DCreate9(D3D_SDK_VERSION);
|
||||
if (!pD3D) return false;
|
||||
|
||||
IDirect3DDevice9* pDummyDevice = NULL;
|
||||
D3DPRESENT_PARAMETERS d3dpp = { 0 };
|
||||
d3dpp.Windowed = false;
|
||||
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
|
||||
d3dpp.hDeviceWindow = GetProcessWindow();
|
||||
|
||||
HRESULT dummyDeviceCreated =
|
||||
pD3D->lpVtbl->CreateDevice(pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);
|
||||
|
||||
if (dummyDeviceCreated != S_OK) {
|
||||
d3dpp.Windowed = !d3dpp.Windowed;
|
||||
|
||||
dummyDeviceCreated = pD3D->lpVtbl->CreateDevice(pD3D, D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, d3dpp.hDeviceWindow,
|
||||
D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pDummyDevice);
|
||||
if (dummyDeviceCreated != S_OK) {
|
||||
pD3D->lpVtbl->Release(pD3D);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
memcpy(pTable, *(void***)pDummyDevice, Size);
|
||||
|
||||
pDummyDevice->lpVtbl->Release(pDummyDevice);
|
||||
pD3D->lpVtbl->Release(pD3D);
|
||||
return true;
|
||||
}
|
||||
|
||||
static HRESULT(WINAPI* TrueEndScene)(IDirect3DDevice9*);
|
||||
|
||||
void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g, unsigned char b) {
|
||||
D3DCOLOR rectColor = D3DCOLOR_XRGB(r, g, b);
|
||||
D3DRECT BarRect = { x, y, x + w, y + h };
|
||||
|
||||
dev->lpVtbl->Clear(dev, 1, &BarRect, D3DCLEAR_TARGET | D3DCLEAR_TARGET, rectColor, 0, 0);
|
||||
}
|
||||
|
||||
HRESULT __stdcall hkEndScene(IDirect3DDevice9* pDevice) {
|
||||
static bool showMenu = false;
|
||||
|
||||
end_scene_hook_t* head = end_scene_hook_list;
|
||||
while (head != NULL) {
|
||||
head->hook(pDevice);
|
||||
head = head->next;
|
||||
}
|
||||
return TrueEndScene(pDevice);
|
||||
}
|
||||
|
||||
void register_gui_hook(FnEndScene* end_scene) {
|
||||
end_scene_hook_t** head = &end_scene_hook_list;
|
||||
while (*head != NULL) {
|
||||
head = &((*head)->next);
|
||||
}
|
||||
end_scene_hook_t* hook = malloc(sizeof(end_scene_hook_t));
|
||||
hook->hook = end_scene;
|
||||
hook->next = NULL;
|
||||
*head = hook;
|
||||
}
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass,
|
||||
DWORD_PTR dwRefData) {
|
||||
// ImGui_ImplWin32_WndProcHandler(hWnd, uMsg, wParam, lParam);
|
||||
|
||||
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
|
||||
}
|
||||
HWND WINAPI FakeCreateWindowExA(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X, int Y,
|
||||
int nWidth, int nHeight, HWND hWndParent, HMENU hMenu, HINSTANCE hInstance,
|
||||
LPVOID lpParam) {
|
||||
HWND hWnd = TrueCreateWindowExA(dwExStyle, lpClassName, lpWindowName, dwStyle, X, Y, nWidth, nHeight, hWndParent,
|
||||
hMenu, hInstance, lpParam);
|
||||
|
||||
void* d3d9Device[119];
|
||||
|
||||
if (GetD3D9Device(d3d9Device, sizeof(d3d9Device))) {
|
||||
*((PVOID*)&TrueEndScene) = CreateHook((PVOID)d3d9Device[42], (PVOID)hkEndScene, 7);
|
||||
}
|
||||
|
||||
if (hWnd && !SetWindowSubclass(hWnd, WndProc, (int)&WndProc, (DWORD_PTR)NULL)) {
|
||||
log_error("gui", "failed to SetWindowSubclass(%d)", GetLastError());
|
||||
}
|
||||
|
||||
return hWnd;
|
||||
}
|
||||
|
||||
void hook_gui() {
|
||||
//
|
||||
hook("User32.dll", "CreateWindowExA", FakeCreateWindowExA, (void**)&TrueCreateWindowExA, 7);
|
||||
}
|
20
src/micetools/dll/hooks/gui.h
Normal file
20
src/micetools/dll/hooks/gui.h
Normal file
@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
|
||||
static HWND(WINAPI* TrueCreateWindowExA)(DWORD dwExStyle, LPCSTR lpClassName, LPCSTR lpWindowName, DWORD dwStyle, int X,
|
||||
int Y, int nWidth, int nHeight, HWND hWndParent, HMENU hMenu,
|
||||
HINSTANCE hInstance, LPVOID lpParam);
|
||||
|
||||
void draw_rect(IDirect3DDevice9* dev, int x, int y, int w, int h, unsigned char r, unsigned char g, unsigned char b);
|
||||
|
||||
typedef VOID(FnEndScene)(IDirect3DDevice9* dev);
|
||||
|
||||
typedef struct end_scene_hook {
|
||||
FnEndScene* hook;
|
||||
struct end_scene_hook* next;
|
||||
} end_scene_hook_t;
|
||||
end_scene_hook_t* end_scene_hook_list;
|
||||
|
||||
void register_gui_hook(FnEndScene* end_scene);
|
||||
void hook_gui();
|
99
src/micetools/dll/hooks/logging.c
Normal file
99
src/micetools/dll/hooks/logging.c
Normal file
@ -0,0 +1,99 @@
|
||||
#include "../util/_util.h"
|
||||
#include "logging.h"
|
||||
|
||||
char* trim_string(char* string) {
|
||||
size_t len = strlen(string) - 1;
|
||||
|
||||
DWORD oldProt;
|
||||
while (len > 0 && (string[len] == '\n' || string[len] == '\r')) {
|
||||
// TODO: Reassess this. Suspect it may be causing issues.
|
||||
// Make sure we can write! This is a terrible hack, but it does work.
|
||||
VirtualProtect(string + len, 1, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
string[len--] = '\0';
|
||||
VirtualProtect(string + len + 1, 1, oldProt, &oldProt);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
#define WORK_FORMAT_MAX 1024
|
||||
char format_buf[WORK_FORMAT_MAX]; // Will do. We guard against overflow in Fake[f]printf
|
||||
|
||||
int WINAPIV Fakeprintf(const char* _Format, ...) {
|
||||
int flen = strlen(_Format);
|
||||
if (flen == strcspn(_Format, "\n") + 1 && flen < (sizeof format_buf)) {
|
||||
strcpy_s(format_buf, WORK_FORMAT_MAX, _Format);
|
||||
format_buf[flen - 1] = 0;
|
||||
_Format = format_buf;
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, _Format);
|
||||
|
||||
int ret = vlog_game("printf", _Format, args);
|
||||
|
||||
va_end(args);
|
||||
return vlog_game("printf", _Format, args);
|
||||
}
|
||||
|
||||
int WINAPIV Fakefprintf(FILE* _File, const char* _Format, ...) {
|
||||
int flen = strlen(_Format);
|
||||
if (flen == strcspn(_Format, "\n") + 1 && flen < (sizeof format_buf)) {
|
||||
strcpy_s(format_buf, WORK_FORMAT_MAX, _Format);
|
||||
format_buf[flen - 1] = 0;
|
||||
_Format = format_buf;
|
||||
}
|
||||
va_list args;
|
||||
va_start(args, _Format);
|
||||
|
||||
int ret = vlog_game("fprintf", _Format, args);
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WINAPIV Fakefprintf_s(FILE* _Stream, const char* _Format, ...) {
|
||||
va_list args;
|
||||
va_start(args, _Format);
|
||||
|
||||
int ret = vlog_game("fprintf_s", _Format, args);
|
||||
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { return (HANDLE)0xDEADBEEF; }
|
||||
|
||||
BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
||||
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData) {
|
||||
switch (wType) {
|
||||
case EVENTLOG_SUCCESS:
|
||||
case EVENTLOG_AUDIT_SUCCESS:
|
||||
for (int i = 0; i < wNumStrings; i++) log_misc("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
case EVENTLOG_AUDIT_FAILURE:
|
||||
case EVENTLOG_ERROR_TYPE:
|
||||
for (int i = 0; i < wNumStrings; i++) log_error("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
case EVENTLOG_WARNING_TYPE:
|
||||
for (int i = 0; i < wNumStrings; i++) log_warning("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
case EVENTLOG_INFORMATION_TYPE:
|
||||
default:
|
||||
for (int i = 0; i < wNumStrings; i++) log_info("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
BOOL WINAPI FakeDeregisterEventSource(HANDLE hEventLog) { return TRUE; }
|
||||
|
||||
// static VOID(WINAPI* TrueOutputDebugStringA)(LPCSTR lpOutputString);
|
||||
// VOID WINAPI FakeOutputDebugStringA(LPCSTR lpOutputString) { log_info("debug", "%s", 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("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, (void**)&TrueRegisterEventSourceA, 6);
|
||||
hook("Advapi32.dll", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA, 6);
|
||||
hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource, (void**)&TrueDeregisterEventSource, 6);
|
||||
}
|
16
src/micetools/dll/hooks/logging.h
Normal file
16
src/micetools/dll/hooks/logging.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
// #include "../common.h"
|
||||
#include <Windows.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static HANDLE(WINAPI* TrueRegisterEventSourceA)(LPCSTR lpUNCServerName, LPCSTR lpSourceName);
|
||||
static BOOL(WINAPI* TrueReportEventA)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
||||
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData);
|
||||
static BOOL(WINAPI* TrueDeregisterEventSource)(HANDLE hEventLog);
|
||||
|
||||
int(WINAPIV* Trueprintf)(const char* _Format, ...);
|
||||
static int(WINAPIV* Truefprintf)(FILE* _File, const char* _Format, ...);
|
||||
static int(WINAPIV* Truefprintf_s)(FILE* _Stream, const char* _Format, ...);
|
||||
|
||||
void hook_logging();
|
11
src/micetools/dll/hooks/meson.build
Normal file
11
src/micetools/dll/hooks/meson.build
Normal file
@ -0,0 +1,11 @@
|
||||
hooks_files = files(
|
||||
'_hooks.c',
|
||||
'com.c',
|
||||
'files.c',
|
||||
'gui.c',
|
||||
'logging.c',
|
||||
'network.c',
|
||||
'processes.c',
|
||||
'setupapi.c',
|
||||
'time.c',
|
||||
)
|
@ -1,9 +1,7 @@
|
||||
#include "network.h"
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
|
||||
int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
|
||||
ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr);
|
||||
ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr.S_un.S_addr);
|
||||
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port);
|
||||
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff,
|
||||
addr & 0xff, port);
|
||||
@ -33,29 +31,55 @@ const char* INTERCEPT_DNS[] = {
|
||||
|
||||
DNS_RECORDA dummy_record;
|
||||
|
||||
unsigned char SPOOF_IP[4] = { 10, 0, 0, 4 };
|
||||
DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra, PDNS_RECORDA* ppQueryResults,
|
||||
PVOID* pReserved) {
|
||||
log_misc("dns", "DNS lookup for %s", pszName);
|
||||
if (ppQueryResults) {
|
||||
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
|
||||
if (strcmp(pszName, INTERCEPT_DNS[i]) == 0) {
|
||||
log_info("dns", "Replacing %s with 10.0.0.4", pszName);
|
||||
log_info("dns", "Replacing %s with %hhu.%hhu.%hhu.%hhu", pszName, SPOOF_IP[0], SPOOF_IP[1], SPOOF_IP[2],
|
||||
SPOOF_IP[3]);
|
||||
|
||||
// We only support replacing at most one address, but that's all we'll ever need to!
|
||||
(*ppQueryResults) = &dummy_record;
|
||||
(*ppQueryResults)->pNext = NULL;
|
||||
(*ppQueryResults)->wType = DNS_TYPE_A;
|
||||
(*ppQueryResults)->Data.A.IpAddress = 0x0400000a;
|
||||
(*ppQueryResults)->Data.A.IpAddress =
|
||||
(SPOOF_IP[0]) | (SPOOF_IP[1] << 8) | (SPOOF_IP[2] << 16) | (SPOOF_IP[3] << 24);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
log_warning("dns", "DNS passthrough for %s", pszName);
|
||||
return TrueDnsQuery_A(pszName, wType, Options, pExtra, ppQueryResults, pReserved);
|
||||
};
|
||||
|
||||
INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily, LPWSAPROTOCOL_INFOA lpProtocolInfo,
|
||||
LPSOCKADDR lpAddress, LPINT lpAddressLength) {
|
||||
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]) == 0) {
|
||||
log_info("dns", "(WSA)Replacing %s with %hhu.%hhu.%hhu.%hhu", AddressString, SPOOF_IP[0], SPOOF_IP[1],
|
||||
SPOOF_IP[2], SPOOF_IP[3]);
|
||||
|
||||
lpAddress->sa_family = AF_INET;
|
||||
// ... :)
|
||||
lpAddress->sa_data[2] = SPOOF_IP[0];
|
||||
lpAddress->sa_data[3] = SPOOF_IP[1];
|
||||
lpAddress->sa_data[4] = SPOOF_IP[2];
|
||||
lpAddress->sa_data[5] = SPOOF_IP[3];
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
}
|
||||
log_warning("dns", "(WSA)DNS passthrough for %s", AddressString);
|
||||
return TrueWSAStringToAddressA(AddressString, AddressFamily, lpProtocolInfo, lpAddress, lpAddressLength);
|
||||
}
|
||||
|
||||
void hook_network() {
|
||||
hook("Ws2_32.dll", "connect", Fake_connect, (void**)&True_connect, 5);
|
||||
hook("Ws2_32.dll", "WSAStringToAddressA", FakeWSAStringToAddressA, (void**)&TrueWSAStringToAddressA, 5);
|
||||
hook("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable, 5);
|
||||
hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A, 5);
|
||||
}
|
@ -1,8 +1,5 @@
|
||||
#include <Winsock2.h>
|
||||
#include <Windows.h>
|
||||
#include <iphlpapi.h>
|
||||
#include <windns.h>
|
||||
|
||||
#pragma once
|
||||
#include "../common.h"
|
||||
|
||||
static int(WINAPI* True_connect)(SOCKET s, const SOCKADDR* name, int namelen);
|
||||
|
||||
@ -11,4 +8,7 @@ static DWORD(WINAPI* TrueGetIfTable)(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL
|
||||
static DNS_STATUS(WINAPI* TrueDnsQuery_A)(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra,
|
||||
PDNS_RECORDA* ppQueryResults, PVOID* pReserved);
|
||||
|
||||
static INT(WSAAPI* TrueWSAStringToAddressA)(LPSTR AddressString, INT AddressFamily, LPWSAPROTOCOL_INFOA lpProtocolInfo,
|
||||
LPSOCKADDR lpAddress, LPINT lpAddressLength);
|
||||
|
||||
void hook_network();
|
@ -1,7 +1,5 @@
|
||||
#include "processes.h"
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
|
||||
const wchar_t* HOOK_BINARIES[] = {
|
||||
L"app\\ALLNetProc.exe",
|
||||
L"app\\CameraUploader.exe",
|
||||
@ -17,11 +15,19 @@ BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||
|
||||
CHAR applicationName[MAX_PATH + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName, NULL, NULL);
|
||||
|
||||
HANDLE child;
|
||||
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);
|
||||
} else {
|
||||
child = start_and_inject(applicationName, NULL, MICELIB, false);
|
||||
}
|
||||
|
||||
HANDLE child = start_and_inject(applicationName, commandLine, MICELIB, false);
|
||||
return child != NULL;
|
||||
}
|
||||
|
||||
void hook_processes() { hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6); }
|
||||
void hook_processes() {
|
||||
// hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6);
|
||||
}
|
@ -1,6 +1,5 @@
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#pragma once
|
||||
#include "../common.h"
|
||||
|
||||
static BOOL(WINAPI* TrueCreateProcessW)(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
@ -1,4 +1,4 @@
|
||||
#include "micesetupapi.h"
|
||||
#include "setupapi_.h"
|
||||
|
||||
FAKE_DEVICE* fake_devices = NULL;
|
||||
|
@ -1,8 +1,5 @@
|
||||
#include <Windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "../lib/mice/mice.h"
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
static HDEVINFO(WINAPI* TrueSetupDiGetClassDevsA)(const GUID* ClassGuid, PCWSTR Enumerator, HWND hwndParent,
|
||||
DWORD Flags);
|
48
src/micetools/dll/hooks/time.c
Normal file
48
src/micetools/dll/hooks/time.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include "time.h"
|
||||
|
||||
SYSTEMTIME localTime;
|
||||
BOOL ltCache = FALSE;
|
||||
SYSTEMTIME systemTime;
|
||||
BOOL stCache = FALSE;
|
||||
|
||||
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);
|
||||
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);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
// TODO: Store deltas instead
|
||||
BOOL WINAPI Fake_GetLocalTime(SYSTEMTIME* lpSystemTime) {
|
||||
if (ltCache) {
|
||||
memcpy(lpSystemTime, &localTime, sizeof localTime);
|
||||
return TRUE;
|
||||
}
|
||||
return TrueGetLocalTime(lpSystemTime);
|
||||
}
|
||||
BOOL WINAPI Fake_GetSystemTime(SYSTEMTIME* lpSystemTime) {
|
||||
if (stCache) {
|
||||
memcpy(lpSystemTime, &systemTime, sizeof systemTime);
|
||||
return TRUE;
|
||||
}
|
||||
return TrueGetSystemTime(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);
|
||||
}
|
9
src/micetools/dll/hooks/time.h
Normal file
9
src/micetools/dll/hooks/time.h
Normal file
@ -0,0 +1,9 @@
|
||||
#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();
|
@ -1,24 +1,25 @@
|
||||
subdir('drivers')
|
||||
subdir('devices')
|
||||
subdir('hooks')
|
||||
|
||||
shared_library(
|
||||
'mice',
|
||||
name_prefix: '',
|
||||
vs_module_defs: 'mice.def',
|
||||
sources: [
|
||||
'dllmain.c',
|
||||
'files.c',
|
||||
'drivers/columba.c',
|
||||
'drivers/mxsram.c',
|
||||
'drivers/mxsuperio.c',
|
||||
'drivers/mxjvs.c',
|
||||
'drivers/mxsmbus.c',
|
||||
'drivers/mxhwreset.c',
|
||||
'setupapi.c',
|
||||
'com.c',
|
||||
'util/log.c',
|
||||
'util/hook.c',
|
||||
|
||||
drivers_files,
|
||||
devices_files,
|
||||
hooks_files,
|
||||
|
||||
'comdevice.c',
|
||||
'processes.c',
|
||||
'network.c',
|
||||
|
||||
'dllmain.c',
|
||||
],
|
||||
link_with: [
|
||||
dmi_lib,
|
||||
mice_lib,
|
||||
],
|
||||
]
|
||||
)
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <Windows.h>
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct mxsmbus_request_packet_ {
|
||||
|
4
src/micetools/dll/util/_util.h
Normal file
4
src/micetools/dll/util/_util.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
|
||||
#include "log.h"
|
||||
#include "hook.h"
|
@ -1,4 +1,8 @@
|
||||
#include "hook.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <memory.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
function_hook_t* hook_list = NULL;
|
||||
|
||||
@ -36,8 +40,8 @@ void clear_at(PVOID addr, BYTE clearVal, DWORD length) {
|
||||
VirtualProtect(addr, length, oldProt, &oldProt);
|
||||
}
|
||||
|
||||
bool Detour(PVOID src, PVOID dst, const intptr_t len) {
|
||||
if (len < 5) return false;
|
||||
BOOL Detour(PVOID src, PVOID dst, const intptr_t len) {
|
||||
if (len < 5) return FALSE;
|
||||
|
||||
DWORD oldProt;
|
||||
VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
@ -46,7 +50,7 @@ bool Detour(PVOID src, PVOID dst, const intptr_t len) {
|
||||
*(PINT)((int)src + 1) = (int)dst - (int)src - 5;
|
||||
|
||||
VirtualProtect(src, len, oldProt, &oldProt);
|
||||
return true;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void* CreateHook(PVOID src, PVOID dst, const intptr_t len) {
|
||||
@ -78,6 +82,7 @@ void setup_hooks() {
|
||||
HMODULE dll = LoadLibraryA(hook->dll);
|
||||
if (dll == NULL) {
|
||||
log_error(HOOKS_LOGGER, "failed to load dll %s. %s skipped", hook->dll, hook->name);
|
||||
hook = hook->next;
|
||||
continue;
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
#include "./mice.h"
|
||||
|
||||
typedef struct function_hook {
|
||||
LPCSTR dll;
|
||||
LPCSTR name;
|
||||
@ -13,10 +11,13 @@ typedef struct function_hook {
|
||||
struct function_hook* next;
|
||||
} function_hook_t;
|
||||
|
||||
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);
|
||||
|
||||
static void append_hook(function_hook_t* hook);
|
||||
void hook(LPCSTR dll, LPCSTR name, void* patch, void** store, UINT length);
|
||||
|
||||
void setup_hooks();
|
144
src/micetools/dll/util/log.c
Normal file
144
src/micetools/dll/util/log.c
Normal file
@ -0,0 +1,144 @@
|
||||
#include "log.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../hooks/logging.h"
|
||||
|
||||
extern BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
|
||||
BOOL HAS_COLOUR = FALSE;
|
||||
|
||||
char _log_prelude[64];
|
||||
char* log_prelude() {
|
||||
time_t rawtime;
|
||||
struct tm timeinfo;
|
||||
|
||||
time(&rawtime);
|
||||
localtime_s(&timeinfo, &rawtime);
|
||||
|
||||
strftime(_log_prelude, sizeof _log_prelude, "[%Y/%m/%d %H:%M:%S] ", &timeinfo);
|
||||
return _log_prelude;
|
||||
}
|
||||
|
||||
HANDLE LOG_FILE = NULL;
|
||||
VOID trace_hook(char* output);
|
||||
CRITICAL_SECTION logger_lock;
|
||||
|
||||
int _do_log(const char* caller, const char* level, const char* format, va_list args, bool toStdout, char* colour) {
|
||||
EnterCriticalSection(&logger_lock);
|
||||
int len = snprintf(NULL, 0, "%s%s:%s:", log_prelude(), level, caller) + vsnprintf(NULL, 0, format, args);
|
||||
char* buf = (char*)malloc(len + 2);
|
||||
if (!buf) {
|
||||
LeaveCriticalSection(&logger_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wrote_a = snprintf(buf, len, "%s%s:%s:", log_prelude(), level, caller);
|
||||
int wrote_b = vsnprintf(buf + wrote_a, len - wrote_a + 1, format, args);
|
||||
buf[len] = '\n';
|
||||
buf[len + 1] = '\0';
|
||||
|
||||
// No +1 here to not get the \n
|
||||
if (toStdout) {
|
||||
HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (HAS_COLOUR) (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, colour, strlen(colour), NULL, NULL);
|
||||
if (sout != INVALID_HANDLE_VALUE) (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL);
|
||||
puts(HAS_COLOUR ? "\033[0m" : "");
|
||||
}
|
||||
#ifdef LOG_TO_FILE
|
||||
if (LOG_FILE && LOG_FILE != INVALID_HANDLE_VALUE)
|
||||
(TrueWriteFile ? TrueWriteFile : WriteFile)(LOG_FILE, buf, len + 1, NULL, NULL);
|
||||
#endif
|
||||
|
||||
free(buf);
|
||||
|
||||
LeaveCriticalSection(&logger_lock);
|
||||
return wrote_b;
|
||||
}
|
||||
int vlog_misc(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "M", format, args, LOG_MISC, "\033[90m");
|
||||
}
|
||||
int log_misc(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_misc(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_info(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "I", format, args, LOG_INFO, "\033[97m");
|
||||
}
|
||||
int log_info(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_info(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_warning(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "W", format, args, LOG_WARNING, "\033[33m");
|
||||
}
|
||||
int log_warning(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_warning(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_error(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "E", format, args, LOG_ERROR, "\033[91m");
|
||||
}
|
||||
int log_error(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_error(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_game(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "G", format, args, LOG_GAME, "\033[96m");
|
||||
}
|
||||
int log_game(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_game(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
VOID trace_hook(char* output) {
|
||||
output[strcspn(output, "\n")] = 0;
|
||||
log_error("trace", output);
|
||||
}
|
||||
|
||||
void setup_logging() {
|
||||
// Force stdio even for GUI applications
|
||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
if (GetStdHandle(STD_INPUT_HANDLE)) {
|
||||
freopen("CONIN$", "r", stdin);
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
}
|
||||
if (GetStdHandle(STD_OUTPUT_HANDLE)) {
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
}
|
||||
if (GetStdHandle(STD_ERROR_HANDLE)) {
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
|
||||
// Enable colour in CMD
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(hConsole, &dwMode))
|
||||
HAS_COLOUR = SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
|
||||
InitializeCriticalSection(&logger_lock);
|
||||
|
||||
if (LOG_FILE == NULL)
|
||||
LOG_FILE = CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
}
|
@ -1,17 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
static HANDLE(WINAPI* TrueRegisterEventSourceA)(LPCSTR lpUNCServerName, LPCSTR lpSourceName);
|
||||
static BOOL(WINAPI* TrueReportEventA)(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
||||
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData);
|
||||
static BOOL(WINAPI* TrueDeregisterEventSource)(HANDLE hEventLog);
|
||||
#define LOG_MISC FALSE
|
||||
#define LOG_INFO TRUE
|
||||
#define LOG_WARNING TRUE
|
||||
#define LOG_ERROR TRUE
|
||||
#define LOG_GAME TRUE
|
||||
|
||||
// #define LOG_MISC
|
||||
#define LOG_INFO
|
||||
#define LOG_WARNING
|
||||
#define LOG_ERROR
|
||||
// #define LOG_TO_FILE
|
||||
|
||||
#define COMM_LOGGER "comm"
|
||||
#define HOOKS_LOGGER "hooks"
|
||||
@ -23,10 +21,12 @@ 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_misc(const char* caller, const char* format, va_list args);
|
||||
int vlog_info(const char* caller, const char* format, va_list args);
|
||||
int vlog_warning(const char* caller, const char* format, va_list args);
|
||||
int vlog_error(const char* caller, const char* format, va_list args);
|
||||
int vlog_game(const char* caller, const char* format, va_list args);
|
||||
|
||||
void setup_logging();
|
@ -12,7 +12,7 @@ bool locate_file(char* path, size_t len, const char* exe) {
|
||||
HANDLE hFind = NULL;
|
||||
|
||||
char work_path[2048];
|
||||
sprintf(work_path, ".\\*.*");
|
||||
snprintf(work_path, sizeof work_path, ".\\*.*");
|
||||
|
||||
if ((hFind = FindFirstFile(work_path, &fdFile)) == INVALID_HANDLE_VALUE) return false;
|
||||
|
||||
|
@ -6,3 +6,4 @@
|
||||
|
||||
bool locate_exe(char* path, size_t len, const char* exe);
|
||||
bool locate_game(char* path, size_t len);
|
||||
bool locate_library(char* path, size_t len);
|
||||
|
@ -11,11 +11,11 @@ bool gametest = false;
|
||||
char exe_name[MAX_PATH + 1] = "";
|
||||
|
||||
void print_help(char* exe) {
|
||||
log_info(BOOT_LOGGER, "Usage: %s [-h] [-t] [-b executable.exe] [-d]", exe);
|
||||
log_info(BOOT_LOGGER, " -h: Print this help message and exit");
|
||||
log_info(BOOT_LOGGER, " -t: Start the game in test mode");
|
||||
log_info(BOOT_LOGGER, " -b: Specify the game binary to use");
|
||||
log_info(BOOT_LOGGER, " -d: Wait for a debugger to attach when starting");
|
||||
fprintf(stderr, "Usage: %s [-h] [-t] [-b executable.exe] [-d]\n", exe);
|
||||
fprintf(stderr, " -h: Print this help message and exit\n");
|
||||
fprintf(stderr, " -t: Start the game in test mode\n");
|
||||
fprintf(stderr, " -b: Specify the game binary to use\n");
|
||||
fprintf(stderr, " -d: Wait for a debugger to attach when starting\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -25,7 +25,8 @@ void parse_cmdline(int argc, char* argv[]) {
|
||||
print_help(argv[0]);
|
||||
} else if (strcmp(argv[i], "-b") == 0) {
|
||||
if (i + 1 == argc) print_help(argv[0]);
|
||||
strcpy(exe_name, argv[++i]);
|
||||
char* val = argv[++i];
|
||||
memcpy(exe_name, val, strlen(val) + 1);
|
||||
} else if (strcmp(argv[i], "-d") == 0) {
|
||||
boot_delay = true;
|
||||
} else if (strcmp(argv[i], "-t") == 0) {
|
||||
@ -35,30 +36,29 @@ void parse_cmdline(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
setup_logging();
|
||||
|
||||
log_info(BOOT_LOGGER, "Micetools version: %s", VERSION);
|
||||
fprintf(stderr, "Micetools version: %s\n", VERSION);
|
||||
|
||||
parse_cmdline(argc, argv);
|
||||
|
||||
if (exe_name[0] == '\0') {
|
||||
if (!locate_game(exe_name, MAX_PATH + 1)) {
|
||||
log_error(BOOT_LOGGER, "Failed to locate a game");
|
||||
fprintf(stderr, "Fatal: Failed to locate a game\n");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
DWORD dwAttrib = GetFileAttributes(exe_name);
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES || dwAttrib & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
log_error(BOOT_LOGGER, "%s: no such file found", exe_name);
|
||||
fprintf(stderr, "Fatal: %s: no such file found\n", exe_name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char* cmdline = gametest ? "gametest" : "";
|
||||
log_info(BOOT_LOGGER, "%s %s", exe_name, cmdline);
|
||||
char* cmdline = gametest ? ". gametest" : "";
|
||||
fprintf(stderr, "exec: %s %s\n", exe_name, cmdline);
|
||||
|
||||
char micepath[MAX_PATH + 1];
|
||||
if (!locate_library(micepath, MAX_PATH + 1)) {
|
||||
log_error(BOOT_LOGGER, "Failed to locate micelib");
|
||||
fprintf(stderr, "Fatal: Failed to locate micelib\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -66,9 +66,9 @@ int main(int argc, char* argv[]) {
|
||||
if (!game_proc) return -1;
|
||||
|
||||
if (FAILED(WaitForSingleObject(game_proc, INFINITE))) {
|
||||
log_error(BOOT_LOGGER, "WaitForSingleObject failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: WaitForSingleObject failed: %03x\n", GetLastError());
|
||||
} else {
|
||||
log_info(BOOT_LOGGER, "Shutting down");
|
||||
fprintf(stderr, "Shutting down\n");
|
||||
CloseHandle(game_proc);
|
||||
}
|
||||
return 0;
|
||||
|
@ -1,7 +1,7 @@
|
||||
rc = import('windows').compile_resources('mice.rc', depend_files: mice_ico)
|
||||
executable(
|
||||
'mice',
|
||||
win_subsystem: 'console',
|
||||
win_subsystem: subsystem,
|
||||
sources: [
|
||||
'locate.c',
|
||||
'main.c',
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "dmi.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
LPBYTE dmi_table = NULL;
|
||||
WORD dmi_size = 0;
|
||||
size_t _dmi_max = 0;
|
||||
@ -64,7 +66,7 @@ static void dmi_append_with_strings(void* data, size_t size, int num_strings, ..
|
||||
for (int i = 0; i < num_strings; i++) {
|
||||
char* str = va_arg(args, char*);
|
||||
int len = strlen(str);
|
||||
strcpy((char*)dmi_table + dmi_size, str);
|
||||
memcpy((char*)dmi_table + dmi_size, str, len + 1);
|
||||
dmi_size += len + 1;
|
||||
dmi_table[dmi_size - 1] = 0;
|
||||
}
|
||||
|
@ -28,7 +28,6 @@
|
||||
*/
|
||||
|
||||
#include "json.h"
|
||||
#include "../util/hex.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <limits.h>
|
||||
@ -38,6 +37,8 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../util/hex.h"
|
||||
|
||||
#define JSON_INT_MAX 9223372036854775807LL
|
||||
|
||||
typedef unsigned int json_uchar;
|
||||
@ -194,7 +195,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
|
||||
if (flags & flag_string) {
|
||||
if (!b) {
|
||||
sprintf(error, "%u:%u: Unexpected EOF in string", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Unexpected EOF in string", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -225,7 +226,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
(uc_b2 = hex_value(*++state.ptr)) == 0xFF ||
|
||||
(uc_b3 = hex_value(*++state.ptr)) == 0xFF ||
|
||||
(uc_b4 = hex_value(*++state.ptr)) == 0xFF) {
|
||||
sprintf(error, "%u:%u: Invalid character value `%c`", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Invalid character value `%c`", line_and_col, b);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -241,7 +242,8 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
(uc_b2 = hex_value(*++state.ptr)) == 0xFF ||
|
||||
(uc_b3 = hex_value(*++state.ptr)) == 0xFF ||
|
||||
(uc_b4 = hex_value(*++state.ptr)) == 0xFF) {
|
||||
sprintf(error, "%u:%u: Invalid character value `%c`", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Invalid character value `%c`", line_and_col,
|
||||
b);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -354,7 +356,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
|
||||
if (flags & flag_block_comment) {
|
||||
if (!b) {
|
||||
sprintf(error, "%u:%u: Unexpected EOF in block comment", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Unexpected EOF in block comment", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -367,12 +369,12 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
}
|
||||
} else if (b == '/') {
|
||||
if (!(flags & (flag_seek_value | flag_done)) && top->type != json_object) {
|
||||
sprintf(error, "%u:%u: Comment not allowed here", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Comment not allowed here", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
if (++state.ptr == end) {
|
||||
sprintf(error, "%u:%u: EOF unexpected", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: EOF unexpected", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -386,7 +388,8 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
continue;
|
||||
|
||||
default:
|
||||
sprintf(error, "%u:%u: Unexpected `%c` in comment opening sequence", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Unexpected `%c` in comment opening sequence",
|
||||
line_and_col, b);
|
||||
goto e_failed;
|
||||
};
|
||||
}
|
||||
@ -400,7 +403,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
continue;
|
||||
|
||||
default:
|
||||
sprintf(error, "%u:%u: Trailing garbage: `%c`", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Trailing garbage: `%c`", line_and_col, b);
|
||||
goto e_failed;
|
||||
};
|
||||
}
|
||||
@ -414,7 +417,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
if (top && top->type == json_array)
|
||||
flags = (flags & ~(flag_need_comma | flag_seek_value)) | flag_next;
|
||||
else {
|
||||
sprintf(error, "%u:%u: Unexpected `]`", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Unexpected `]`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -426,7 +429,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
flags &= ~flag_need_comma;
|
||||
continue;
|
||||
} else {
|
||||
sprintf(error, "%u:%u: Expected `,` before `%c`", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Expected `,` before `%c`", line_and_col, b);
|
||||
|
||||
goto e_failed;
|
||||
}
|
||||
@ -437,7 +440,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
flags &= ~flag_need_colon;
|
||||
continue;
|
||||
} else {
|
||||
sprintf(error, "%u:%u: Expected `:` before `%c`", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Expected `:` before `%c`", line_and_col, b);
|
||||
|
||||
goto e_failed;
|
||||
}
|
||||
@ -535,7 +538,8 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
flags |= flag_num_negative;
|
||||
continue;
|
||||
} else {
|
||||
sprintf(error, "%u:%u: Unexpected `%c` when seeking value", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Unexpected `%c` when seeking value",
|
||||
line_and_col, b);
|
||||
goto e_failed;
|
||||
}
|
||||
};
|
||||
@ -548,7 +552,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
continue;
|
||||
case '"':
|
||||
if (flags & flag_need_comma) {
|
||||
sprintf(error, "%u:%u: Expected `,` before `\"`", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Expected `,` before `\"`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -570,7 +574,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
} /* FALLTHRU */
|
||||
|
||||
default:
|
||||
sprintf(error, "%u:%u: Unexpected `%c` in object", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Unexpected `%c` in object", line_and_col, b);
|
||||
goto e_failed;
|
||||
};
|
||||
break;
|
||||
@ -583,7 +587,8 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
if (top->type == json_integer || flags & flag_num_e) {
|
||||
if (!(flags & flag_num_e)) {
|
||||
if (flags & flag_num_zero) {
|
||||
sprintf(error, "%u:%u: Unexpected `0` before `%c`", line_and_col, b);
|
||||
snprintf(error, json_error_max, "%u:%u: Unexpected `0` before `%c`",
|
||||
line_and_col, b);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -627,7 +632,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
json_int_t integer = top->u.integer;
|
||||
|
||||
if (!num_digits) {
|
||||
sprintf(error, "%u:%u: Expected digit before `.`", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Expected digit before `.`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -642,7 +647,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
if (!(flags & flag_num_e)) {
|
||||
if (top->type == json_double) {
|
||||
if (!num_digits) {
|
||||
sprintf(error, "%u:%u: Expected digit after `.`", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Expected digit after `.`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -665,7 +670,7 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
}
|
||||
} else {
|
||||
if (!num_digits) {
|
||||
sprintf(error, "%u:%u: Expected digit after `e`", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Expected digit after `e`", line_and_col);
|
||||
goto e_failed;
|
||||
}
|
||||
|
||||
@ -731,23 +736,23 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
return root;
|
||||
|
||||
e_unknown_value:
|
||||
sprintf(error, "%u:%u: Unknown value", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Unknown value", line_and_col);
|
||||
goto e_failed;
|
||||
|
||||
e_alloc_failure:
|
||||
strcpy(error, "Memory allocation failure");
|
||||
snprintf(error, json_error_max, "Memory allocation failure");
|
||||
goto e_failed;
|
||||
|
||||
e_overflow:
|
||||
sprintf(error, "%u:%u: Too long (caught overflow)", line_and_col);
|
||||
snprintf(error, json_error_max, "%u:%u: Too long (caught overflow)", line_and_col);
|
||||
goto e_failed;
|
||||
|
||||
e_failed:
|
||||
if (error_buf) {
|
||||
if (*error)
|
||||
strcpy(error_buf, error);
|
||||
memcpy(error_buf, error, json_error_max);
|
||||
else
|
||||
strcpy(error_buf, "Unknown error");
|
||||
snprintf(error_buf, json_error_max, "Unknown error");
|
||||
}
|
||||
|
||||
if (state.first_pass) alloc = root;
|
||||
|
@ -51,6 +51,9 @@ typedef struct pcpa {
|
||||
// char* field_0x254;
|
||||
pcp_parse_data_t recv_data;
|
||||
pcp_send_data_t send_data;
|
||||
|
||||
// Our additions
|
||||
pcpa_callback* before_cb;
|
||||
} pcpa_t;
|
||||
|
||||
void pcpaClose(pcpa_t* stream);
|
||||
|
29
src/micetools/lib/mice/crc.c
Normal file
29
src/micetools/lib/mice/crc.c
Normal file
@ -0,0 +1,29 @@
|
||||
unsigned int CRC_TABLE[256];
|
||||
unsigned int CTC_TABLE_BUILT = 0;
|
||||
|
||||
#define CRC32_POLYNOMIAL 0xedb88320
|
||||
|
||||
void crc32_build_table() {
|
||||
if (CTC_TABLE_BUILT) return;
|
||||
CTC_TABLE_BUILT = 1;
|
||||
|
||||
for (int i = 0; i < 256; i++) {
|
||||
unsigned int value = (~i & 1) - 1 & CRC32_POLYNOMIAL;
|
||||
value = (((int)i >> 1 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = (((int)i >> 2 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = (((int)i >> 3 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = (((int)i >> 4 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = (((int)i >> 5 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
value = (((int)i >> 6 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
CRC_TABLE[i] = (((int)i >> 7 ^ ~value) & 1) - 1 & CRC32_POLYNOMIAL ^ value >> 1;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int crc32(int length, unsigned char *data, unsigned int initial) {
|
||||
unsigned int value = ~initial;
|
||||
while (length--) {
|
||||
value = value >> 8 ^ CRC_TABLE[(*data ^ value) & 0xff];
|
||||
data++;
|
||||
}
|
||||
return ~value;
|
||||
}
|
2
src/micetools/lib/mice/crc.h
Normal file
2
src/micetools/lib/mice/crc.h
Normal file
@ -0,0 +1,2 @@
|
||||
void crc32_build_table();
|
||||
unsigned int crc32(int length, unsigned char *data, unsigned int initial);
|
@ -1,18 +1,17 @@
|
||||
#include "exe.h"
|
||||
#include "log.h"
|
||||
|
||||
bool inject_debug_wait(HANDLE process) {
|
||||
BOOL present;
|
||||
|
||||
log_info(BOOT_LOGGER, "Waiting for debugger to attach.");
|
||||
fprintf(stderr, "Waiting for debugger to attach.\n");
|
||||
do {
|
||||
Sleep(1000);
|
||||
if (FAILED(CheckRemoteDebuggerPresent(process, &present))) {
|
||||
log_error(BOOT_LOGGER, "CheckRemoteDebuggerPresent failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: CheckRemoteDebuggerPresent failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
} while (!present);
|
||||
log_info(BOOT_LOGGER, "Debugger attached, resuming");
|
||||
fprintf(stderr, "Debugger attached, resuming\n");
|
||||
return true;
|
||||
}
|
||||
bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) {
|
||||
@ -20,33 +19,33 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) {
|
||||
|
||||
LPVOID arg_addr = VirtualAllocEx(process, NULL, nchars + 1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
|
||||
if (arg_addr == NULL) {
|
||||
log_error(BOOT_LOGGER, "VirtualAllocEx failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: VirtualAllocEx failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (FAILED(WriteProcessMemory(process, arg_addr, argument, nchars + 1, NULL))) {
|
||||
log_error(BOOT_LOGGER, "WriteProcessMemory failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: WriteProcessMemory failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
HANDLE remote_thread = CreateRemoteThread(process, NULL, 0, (LPTHREAD_START_ROUTINE)function, arg_addr, 0, NULL);
|
||||
if (remote_thread == NULL) {
|
||||
log_error(BOOT_LOGGER, "CreateRemoteThread failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: CreateRemoteThread failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (WaitForSingleObject(remote_thread, INFINITE) != WAIT_OBJECT_0) {
|
||||
log_error(BOOT_LOGGER, "WaitForSingleObject failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: WaitForSingleObject failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD result;
|
||||
if (FAILED(GetExitCodeThread(remote_thread, &result))) {
|
||||
log_error(BOOT_LOGGER, "GetExitCodeThread failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: GetExitCodeThread failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
if (result == 0) {
|
||||
log_error(BOOT_LOGGER, "GetExitCodeThread failed: result == 0");
|
||||
fprintf(stderr, "Fatal: GetExitCodeThread failed: result == 0\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -55,13 +54,13 @@ bool remote_call(HANDLE process, LPVOID function, LPCSTR argument) {
|
||||
bool inject_dll(HANDLE process, LPCSTR inject) {
|
||||
HMODULE kernel32 = GetModuleHandleA("kernel32.dll");
|
||||
if (kernel32 == NULL) {
|
||||
log_error(BOOT_LOGGER, "GetModuleHandleA failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: GetModuleHandleA failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
LPVOID addr_LoadLibraryA = (LPVOID)GetProcAddress(kernel32, "LoadLibraryA");
|
||||
if (addr_LoadLibraryA == NULL) {
|
||||
log_error(BOOT_LOGGER, "GetProcAddress failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: GetProcAddress failed: %03x\n", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -69,7 +68,6 @@ bool inject_dll(HANDLE process, LPCSTR inject) {
|
||||
}
|
||||
|
||||
HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||
log_misc(BOOT_LOGGER, "Using %s for hooks", inject);
|
||||
STARTUPINFOA startupInfo;
|
||||
PROCESS_INFORMATION processInformation;
|
||||
|
||||
@ -83,14 +81,14 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||
// Validate that we're not about to try something insane
|
||||
DWORD found = SearchPathA(NULL, inject, NULL, 0, NULL, NULL);
|
||||
if (found == 0) {
|
||||
log_error(BOOT_LOGGER, "Cannot inject %s: not found: %03x", inject, GetLastError());
|
||||
fprintf(stderr, "Fatal: Cannot inject %s: not found: %03x\n", inject, GetLastError());
|
||||
goto abort;
|
||||
}
|
||||
|
||||
// Start the binary
|
||||
if (FAILED(CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo,
|
||||
&processInformation))) {
|
||||
log_error(BOOT_LOGGER, "CreateProcessA failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: CreateProcessA failed: %03x\n", GetLastError());
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@ -101,7 +99,7 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||
|
||||
// Injection completed, let the program continue execution
|
||||
if (FAILED(ResumeThread(processInformation.hThread))) {
|
||||
log_error(BOOT_LOGGER, "ResumeThread failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: ResumeThread failed: %03x\n", GetLastError());
|
||||
goto abort;
|
||||
}
|
||||
|
||||
@ -110,14 +108,14 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||
abort:
|
||||
if (processInformation.hProcess) {
|
||||
if (FAILED(CloseHandle(processInformation.hThread)))
|
||||
log_error(BOOT_LOGGER, "CloseHandle(hProcess) failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: CloseHandle(hProcess) failed: %03x\n", GetLastError());
|
||||
|
||||
if (FAILED(TerminateProcess(processInformation.hProcess, 1)))
|
||||
log_error(BOOT_LOGGER, "TerminateProcess failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: TerminateProcess failed: %03x\n", GetLastError());
|
||||
}
|
||||
if (processInformation.hThread) {
|
||||
if (FAILED(CloseHandle(processInformation.hThread)))
|
||||
log_error(BOOT_LOGGER, "CloseHandle(hThread) failed: %03x", GetLastError());
|
||||
fprintf(stderr, "Fatal: CloseHandle(hThread) failed: %03x\n", GetLastError());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include <Windows.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
|
||||
HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay);
|
||||
|
||||
|
@ -1,212 +0,0 @@
|
||||
#include "log.h"
|
||||
|
||||
BOOL HAS_COLOUR = FALSE;
|
||||
|
||||
char _log_prelude[32];
|
||||
char* log_prelude() {
|
||||
time_t rawtime;
|
||||
struct tm* timeinfo;
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(_log_prelude, 32, "[%Y/%m/%d %H:%M:%S] ", timeinfo);
|
||||
return _log_prelude;
|
||||
}
|
||||
|
||||
HANDLE LOG_FILE = NULL;
|
||||
VOID trace_hook(char* output);
|
||||
CRITICAL_SECTION logger_lock;
|
||||
|
||||
int _do_log(const char* caller, const char* level, const char* format, va_list args, bool toStdout) {
|
||||
EnterCriticalSection(&logger_lock);
|
||||
|
||||
int len = snprintf(NULL, 0, "%s%s:%s:", log_prelude(), level, caller) + vsnprintf(NULL, 0, format, args);
|
||||
char* buf = (char*)malloc(len + 2);
|
||||
if (!buf) {
|
||||
LeaveCriticalSection(&logger_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wrote_a = snprintf(buf, len, "%s%s:%s:", log_prelude(), level, caller);
|
||||
int wrote_b = vsnprintf(buf + wrote_a, len - wrote_a + 1, format, args);
|
||||
buf[len] = '\n';
|
||||
buf[len + 1] = '\0';
|
||||
|
||||
// No +1 here to not get the \n
|
||||
if (toStdout) WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), buf, len, NULL, NULL);
|
||||
#ifdef LOG_TO_FILE
|
||||
if (LOG_FILE && LOG_FILE != INVALID_HANDLE_VALUE) WriteFile(LOG_FILE, buf, len + 1, NULL, NULL);
|
||||
#endif
|
||||
|
||||
free(buf);
|
||||
|
||||
LeaveCriticalSection(&logger_lock);
|
||||
return wrote_b;
|
||||
}
|
||||
int vlog_misc(const char* caller, const char* format, va_list args) {
|
||||
#ifdef LOG_MISC
|
||||
if (HAS_COLOUR) WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\033[90m", 5, NULL, NULL);
|
||||
int ret = _do_log(caller, "M", format, args, true);
|
||||
puts(HAS_COLOUR ? "\033[0m" : "");
|
||||
return ret;
|
||||
#else
|
||||
return _do_log(caller, "M", format, args, false);
|
||||
#endif
|
||||
}
|
||||
int log_misc(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_misc(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_info(const char* caller, const char* format, va_list args) {
|
||||
#ifdef LOG_INFO
|
||||
if (HAS_COLOUR) WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\033[97m", 5, NULL, NULL);
|
||||
int ret = _do_log(caller, "I", format, args, true);
|
||||
puts(HAS_COLOUR ? "\033[0m" : "");
|
||||
return ret;
|
||||
#else
|
||||
return _do_log(caller, "I", format, args, false);
|
||||
#endif
|
||||
}
|
||||
int log_info(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_info(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_warning(const char* caller, const char* format, va_list args) {
|
||||
#ifdef LOG_WARNING
|
||||
if (HAS_COLOUR) WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\033[33m", 5, NULL, NULL);
|
||||
int ret = _do_log(caller, "W", format, args, true);
|
||||
puts(HAS_COLOUR ? "\033[0m" : "");
|
||||
return ret;
|
||||
#else
|
||||
return _do_log(caller, "W", format, args, false);
|
||||
#endif
|
||||
}
|
||||
int log_warning(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_warning(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_error(const char* caller, const char* format, va_list args) {
|
||||
#ifdef LOG_ERROR
|
||||
if (HAS_COLOUR) WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), "\033[91m", 5, NULL, NULL);
|
||||
int ret = _do_log(caller, "E", format, args, true);
|
||||
puts(HAS_COLOUR ? "\033[0m" : "");
|
||||
return ret;
|
||||
#else
|
||||
return _do_log(caller, "E", format, args, false);
|
||||
#endif
|
||||
}
|
||||
int log_error(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_error(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// char format_buf[1024]; // Will do. We guard against overflow in
|
||||
// Fake[f]printf int WINAPIV Fakeprintf(const char* _Format, ...) { int
|
||||
// flen = strlen(_Format); if (flen == strcspn(_Format, "\n") + 1 && flen
|
||||
// < (sizeof format_buf)) { strcpy_s(format_buf, flen, _Format);
|
||||
// format_buf[flen - 1] = 0; _Format = format_buf;
|
||||
// }
|
||||
// va_list args;
|
||||
// va_start(args, _Format);
|
||||
// int ret = vlog_info("printf", _Format, args);
|
||||
// va_end(args);
|
||||
// return ret;
|
||||
// };
|
||||
// int WINAPIV Fakefprintf(FILE* _File, const char* _Format, ...) {
|
||||
// int flen = strlen(_Format);
|
||||
// if (flen == strcspn(_Format, "\n") + 1 && flen < (sizeof format_buf))
|
||||
// { strcpy_s(format_buf, flen, _Format); format_buf[flen
|
||||
// - 1] = 0; _Format = format_buf;
|
||||
// }
|
||||
// va_list args;
|
||||
// va_start(args, _Format);
|
||||
// int ret = vlog_error("fprintf", _Format, args);
|
||||
// va_end(args);
|
||||
// return ret;
|
||||
// };
|
||||
|
||||
// int WINAPIV Fakefprintf_s(FILE* _Stream, const char* _Format, ...) {
|
||||
// va_list args;
|
||||
// va_start(args, _Format);
|
||||
// int ret = vlog_error("fprintf_s", _Format, args);
|
||||
// va_end(args);
|
||||
// return ret;
|
||||
// };
|
||||
|
||||
char* trim_string(char* string) {
|
||||
size_t len = strlen(string) - 1;
|
||||
|
||||
DWORD oldProt;
|
||||
while (len > 0 && (string[len] == '\n' || string[len] == '\r')) {
|
||||
// TODO: Reassess this. Suspect it may be causing issues.
|
||||
// Make sure we can write! This is a terrible hack, but it does work.
|
||||
VirtualProtect(string + len, 1, PAGE_EXECUTE_READWRITE, &oldProt);
|
||||
string[len--] = '\0';
|
||||
VirtualProtect(string + len + 1, 1, oldProt, &oldProt);
|
||||
}
|
||||
return string;
|
||||
}
|
||||
|
||||
HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { return (HANDLE)0xDEADBEEF; }
|
||||
|
||||
BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
||||
WORD wNumStrings, DWORD dwDataSize, LPCSTR* lpStrings, LPVOID lpRawData) {
|
||||
switch (wType) {
|
||||
case EVENTLOG_SUCCESS:
|
||||
case EVENTLOG_AUDIT_SUCCESS:
|
||||
for (int i = 0; i < wNumStrings; i++) log_misc("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
case EVENTLOG_AUDIT_FAILURE:
|
||||
case EVENTLOG_ERROR_TYPE:
|
||||
for (int i = 0; i < wNumStrings; i++) log_error("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
case EVENTLOG_WARNING_TYPE:
|
||||
for (int i = 0; i < wNumStrings; i++) log_warning("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
case EVENTLOG_INFORMATION_TYPE:
|
||||
default:
|
||||
for (int i = 0; i < wNumStrings; i++) log_info("evtlog", trim_string((char*)lpStrings[i]));
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
};
|
||||
|
||||
BOOL WINAPI FakeDeregisterEventSource(HANDLE hEventLog) { return TRUE; }
|
||||
|
||||
static VOID(WINAPI* TrueOutputDebugStringA)(LPCSTR lpOutputString);
|
||||
VOID WINAPI FakeOutputDebugStringA(LPCSTR lpOutputString) { log_info("debug", "%s", lpOutputString); }
|
||||
|
||||
VOID trace_hook(char* output) {
|
||||
output[strcspn(output, "\n")] = 0;
|
||||
log_error("trace", output);
|
||||
}
|
||||
|
||||
void setup_logging() {
|
||||
// Enable colour in CMD
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(hConsole, &dwMode))
|
||||
HAS_COLOUR = SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
|
||||
InitializeCriticalSection(&logger_lock);
|
||||
|
||||
if (LOG_FILE == NULL)
|
||||
LOG_FILE = CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
|
||||
hook("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, &TrueRegisterEventSourceA);
|
||||
hook("Advapi32.dll", "ReportEventA", FakeReportEventA, &TrueReportEventA);
|
||||
hook("Advapi32.dll", "DeregisterEventSource", FakeDeregisterEventSource, &TrueDeregisterEventSource);
|
||||
}
|
@ -1,10 +1,10 @@
|
||||
mice_lib = static_library(
|
||||
'mice',
|
||||
sources: [
|
||||
'hook.c',
|
||||
'log.c',
|
||||
'exe.c',
|
||||
'patch.c',
|
||||
'crc.c',
|
||||
'ringbuf.c',
|
||||
],
|
||||
link_with: [
|
||||
json_lib,
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include "hook.h"
|
||||
#include <Windows.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "ioctl.h"
|
||||
#include "log.h"
|
||||
#include "exe.h"
|
||||
#include "patch.h"
|
||||
#include "crc.h"
|
||||
#include "ringbuf.h"
|
||||
|
@ -1,5 +1,8 @@
|
||||
#include "patch.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
bool fetch(json_value* object, char* name, json_value** value) {
|
||||
if (object->type != json_object) return false;
|
||||
for (size_t j = 0; j < object->u.object.length; j++) {
|
||||
@ -47,9 +50,10 @@ void free_patches(patches_t* patches) {
|
||||
}
|
||||
|
||||
json_value* load_json_from_file(char* path, char* error) {
|
||||
FILE* fp = fopen(path, "r");
|
||||
FILE* fp;
|
||||
fopen_s(&fp, path, "r");
|
||||
if (fp == NULL) {
|
||||
if (error != NULL) sprintf(error, "Failed to open patch file");
|
||||
if (error != NULL) snprintf(error, json_error_max, "Failed to open patch file");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -59,18 +63,18 @@ json_value* load_json_from_file(char* path, char* error) {
|
||||
|
||||
char* json_buf = (char*)malloc(sz);
|
||||
if (json_buf == NULL) {
|
||||
if (error != NULL) sprintf(error, "Failed to allocate file buffer");
|
||||
if (error != NULL) snprintf(error, json_error_max, "Failed to allocate file buffer");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
if (!(sz = fread(json_buf, 1, sz, fp))) {
|
||||
if (error != NULL) sprintf(error, "Failed to read file");
|
||||
if (error != NULL) snprintf(error, json_error_max, "Failed to read file");
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
};
|
||||
fclose(fp);
|
||||
|
||||
json_settings settings = {0};
|
||||
json_settings settings = { 0 };
|
||||
return json_parse_ex(&settings, json_buf, sz, error);
|
||||
}
|
||||
|
||||
@ -112,11 +116,11 @@ bool parse_patches(patches_t* patches, json_value** set_json, int set_count, cha
|
||||
char load_error[json_error_max];
|
||||
set_patches = load_json_from_file(patches_file_path, load_error);
|
||||
if (set_patches == NULL) {
|
||||
log_warning("patcher", "Failed to load '%s': %s", patches_file_path, load_error);
|
||||
fprintf(stderr, "W: patcher: Failed to load '%s': %s\n", patches_file_path, load_error);
|
||||
continue;
|
||||
}
|
||||
if (set_patches->type != json_array) {
|
||||
log_warning("patcher", "Failed to load '%s': not an array", patches_file_path);
|
||||
fprintf(stderr, "W: patcher: Failed to load '%s': not an array\n", patches_file_path);
|
||||
continue;
|
||||
}
|
||||
} else {
|
||||
@ -214,7 +218,7 @@ bool load_patches(patches_t* patches, char* path, char* error) {
|
||||
loaded_patches = 1;
|
||||
patches_json = &parsed;
|
||||
} else {
|
||||
sprintf(error, "Patch file format error");
|
||||
snprintf(error, json_error_max, "Patch file format error");
|
||||
json_value_free(parsed);
|
||||
return false;
|
||||
}
|
||||
|
58
src/micetools/lib/mice/ringbuf.c
Normal file
58
src/micetools/lib/mice/ringbuf.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include "ringbuf.h"
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
void ringbuf_purge(ring_buffer_t* ring) {
|
||||
ring->read = 0;
|
||||
ring->write = 0;
|
||||
}
|
||||
|
||||
short ringbuf_available(ring_buffer_t* ring) {
|
||||
short populated = ring->write - ring->read;
|
||||
if (populated < 0) populated += RING_BUFFER_SIZE;
|
||||
return populated;
|
||||
}
|
||||
|
||||
bool ringbuf_write(ring_buffer_t* ring, unsigned const char* data, short bytes) {
|
||||
short unpopulated = ring->read - ring->write;
|
||||
if (unpopulated < 0) unpopulated += RING_BUFFER_SIZE;
|
||||
bool overflow = unpopulated < bytes;
|
||||
|
||||
while (bytes > 0) {
|
||||
short chunk;
|
||||
if (bytes + ring->write > RING_BUFFER_SIZE)
|
||||
chunk = RING_BUFFER_SIZE - ring->write;
|
||||
else
|
||||
chunk = bytes;
|
||||
|
||||
memcpy(ring->buffer + ring->write, data, chunk);
|
||||
data += chunk;
|
||||
bytes -= chunk;
|
||||
ring->write = (ring->write + chunk) % RING_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
return overflow;
|
||||
}
|
||||
|
||||
short ringbuf_read(ring_buffer_t* ring, unsigned char* data, short bytes) {
|
||||
short populated = ring->write - ring->read;
|
||||
if (populated < 0) populated += RING_BUFFER_SIZE;
|
||||
// Underflow
|
||||
if (populated < bytes) bytes = populated;
|
||||
|
||||
short left = bytes;
|
||||
while (left > 0) {
|
||||
short chunk;
|
||||
if (left + ring->read > RING_BUFFER_SIZE)
|
||||
chunk = RING_BUFFER_SIZE - ring->read;
|
||||
else
|
||||
chunk = left;
|
||||
|
||||
memcpy(data, ring->buffer + ring->read, chunk);
|
||||
data += chunk;
|
||||
left -= chunk;
|
||||
ring->read = (ring->read + chunk) % RING_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
return bytes;
|
||||
}
|
16
src/micetools/lib/mice/ringbuf.h
Normal file
16
src/micetools/lib/mice/ringbuf.h
Normal file
@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
#include <stdbool.h>
|
||||
|
||||
// We use shorts for indexes so the max allowed here is 0x7fff
|
||||
#define RING_BUFFER_SIZE 2048
|
||||
|
||||
typedef struct ring_buffer {
|
||||
unsigned char buffer[RING_BUFFER_SIZE];
|
||||
short read;
|
||||
short write;
|
||||
} ring_buffer_t;
|
||||
|
||||
bool ringbuf_write(ring_buffer_t* ring, unsigned const char* data, short bytes);
|
||||
short ringbuf_read(ring_buffer_t* ring, unsigned char* data, short bytes);
|
||||
short ringbuf_available(ring_buffer_t* ring);
|
||||
void ringbuf_purge(ring_buffer_t* ring);
|
@ -1,3 +1,5 @@
|
||||
#include <ctype.h>
|
||||
|
||||
unsigned char hex_value(char c) {
|
||||
if (isdigit((unsigned char)c)) return c - '0';
|
||||
|
||||
|
@ -4,3 +4,5 @@ subdir('micepatch')
|
||||
subdir('micekeychip')
|
||||
subdir('launcher')
|
||||
subdir('dll')
|
||||
|
||||
subdir('micetest')
|
||||
|
@ -1,9 +1,8 @@
|
||||
#include "../config.h"
|
||||
#include "../lib/libpcp/libpcp.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
void mxkPcpAbGameId(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, AB_GAMEID, Config.appboot_gameid);
|
||||
}
|
||||
void mxkPcpAbGameId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, AB_GAMEID, Config.appboot_gameid); }
|
||||
void mxkPcpAbSystemFlag(pcpa_t* stream, void* data) {
|
||||
char sf[3];
|
||||
snprintf(sf, 3, "%02X", Config.appboot_systemflag);
|
||||
@ -11,17 +10,17 @@ void mxkPcpAbSystemFlag(pcpa_t* stream, void* data) {
|
||||
}
|
||||
void mxkPcpAbModelType(pcpa_t* stream, void* data) {
|
||||
char mt[16];
|
||||
snprintf(mt, 16, "%d", Config.appboot_modeltype);
|
||||
snprintf(mt, 16, "%02X", Config.appboot_modeltype);
|
||||
pcpaSetSendPacket(stream, AB_MODELTYPE, mt);
|
||||
}
|
||||
void mxkPcpAbFormatType(pcpa_t* stream, void* data) {
|
||||
char ft[16];
|
||||
snprintf(ft, 16, "%d", Config.appboot_formattype);
|
||||
snprintf(ft, 16, "%02X", Config.appboot_formattype);
|
||||
pcpaSetSendPacket(stream, AB_FORMATTYPE, ft);
|
||||
}
|
||||
void mxkPcpAbRegion(pcpa_t* stream, void* data) {
|
||||
char rg[16];
|
||||
snprintf(rg, 16, "%d", Config.appboot_region);
|
||||
snprintf(rg, 16, "%02X", Config.appboot_region);
|
||||
pcpaSetSendPacket(stream, AB_REGION, rg);
|
||||
}
|
||||
void mxkPcpAbPlatformId(pcpa_t* stream, void* data) {
|
||||
@ -32,7 +31,7 @@ void mxkPcpAbNetworkAddress(pcpa_t* stream, void* data) {
|
||||
}
|
||||
void mxkPcpAbDvd(pcpa_t* stream, void* data) {
|
||||
char dvd[16];
|
||||
snprintf(dvd, 16, "%d", Config.appboot_dvdflag);
|
||||
snprintf(dvd, 16, "%02X", Config.appboot_dvdflag);
|
||||
pcpaSetSendPacket(stream, AB_DVD, dvd);
|
||||
}
|
||||
|
||||
@ -41,7 +40,8 @@ byte SEED_BUF[SEED_BUF_MAX];
|
||||
int SEED_BUF_LEN = 0;
|
||||
void mxkPcpAbSeed(pcpa_t* stream, void* data) {
|
||||
if (SEED_BUF_LEN == 0) {
|
||||
FILE* fCert = fopen(Config.appboot_seed, "r");
|
||||
FILE* fCert;
|
||||
fopen_s(&fCert, Config.appboot_seed, "r");
|
||||
if (fCert == NULL)
|
||||
SEED_BUF_LEN = -1;
|
||||
else {
|
||||
@ -72,6 +72,6 @@ void mxkPcpAbSeed(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, AB_SEED, "0");
|
||||
pcpaAddSendPacket(stream, "port", "40107");
|
||||
char sSize[16]; // todo: nicer lol
|
||||
itoa(SEED_BUF_LEN, sSize, 10);
|
||||
_itoa(SEED_BUF_LEN, sSize, 10);
|
||||
pcpaAddSendPacket(stream, "size", sSize);
|
||||
}
|
||||
|
@ -1,12 +1,9 @@
|
||||
#include "../config.h"
|
||||
#include "../lib/libpcp/libpcp.h"
|
||||
#include "callbacks.h"
|
||||
|
||||
void mxkPcpPbKeyId(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, BIL_KEYID, Config.billing_keyid);
|
||||
}
|
||||
void mxkPcpPbMainId(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, BIL_MAINID, Config.billing_mainid);
|
||||
}
|
||||
void mxkPcpPbKeyId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, BIL_KEYID, Config.billing_keyid); }
|
||||
void mxkPcpPbMainId(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, BIL_MAINID, Config.billing_mainid); }
|
||||
void mxkPcpPbPlayCount(pcpa_t* stream, void* data) {
|
||||
char pc[9];
|
||||
snprintf(pc, sizeof pc, "%08X", Config.billing_playcount);
|
||||
@ -36,7 +33,8 @@ byte PUBKEY_BUF[PUBKEY_BUF_MAX];
|
||||
int PUBKEY_LEN = 0;
|
||||
void mxkPcpPbSignaturePubKey(pcpa_t* stream, void* data) {
|
||||
if (PUBKEY_LEN == 0) {
|
||||
FILE* fPubkey = fopen(Config.billing_pubkey, "r");
|
||||
FILE* fPubkey;
|
||||
fopen_s(&fPubkey, Config.billing_pubkey, "r");
|
||||
if (fPubkey == NULL)
|
||||
PUBKEY_LEN = -1;
|
||||
else {
|
||||
@ -76,7 +74,8 @@ byte CA_CERTIFICATION[CA_CERT_BUF_MAX];
|
||||
int CA_CERT_LEN = 0;
|
||||
void mxkPcpPbCaCertification(pcpa_t* stream, void* data) {
|
||||
if (CA_CERT_LEN == 0) {
|
||||
FILE* fCert = fopen(Config.billing_cacert, "r");
|
||||
FILE* fCert;
|
||||
fopen_s(&fCert, Config.billing_cacert, "r");
|
||||
if (fCert == NULL)
|
||||
CA_CERT_LEN = -1;
|
||||
else {
|
||||
@ -107,6 +106,6 @@ void mxkPcpPbCaCertification(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, BIL_CACERT, "0");
|
||||
pcpaAddSendPacket(stream, "port", "40107");
|
||||
char sSize[16]; // todo: nicer lol
|
||||
itoa(CA_CERT_LEN, sSize, 10);
|
||||
_itoa(CA_CERT_LEN, sSize, 10);
|
||||
pcpaAddSendPacket(stream, "size", sSize);
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
#include "callbacks.h"
|
||||
|
||||
void mxkPcpDsCompute(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, "code", "54");
|
||||
}
|
||||
void mxkPcpSsdProof(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, "code", "54");
|
||||
}
|
||||
void mxkPcpDsCompute(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); }
|
||||
void mxkPcpSsdProof(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, "code", "54"); }
|
||||
void mxkPcpSsdHostProof(pcpa_t* stream, void* data) {}
|
||||
void mkxPcpEncrypt(pcpa_t* stream, void* data) {}
|
||||
void mxkPcpDecrypt(pcpa_t* stream, void* data) {}
|
||||
void mxkPcpSetIv(pcpa_t* stream, void* data) {}
|
||||
void mkxPcpEncrypt(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, KC_ENCRYPT, "B6787E941C3956EAC70095D6A91E635C");
|
||||
}
|
||||
void mxkPcpDecrypt(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, KC_DECRYPT, "68271898FB92ABFB49321FAF72F04FF1");
|
||||
}
|
||||
void mxkPcpSetIv(pcpa_t* stream, void* data) { pcpaSetSendPacket(stream, KC_SETIV, "1"); }
|
||||
|
@ -9,7 +9,8 @@ config_t Config = {
|
||||
._keep_linter_happy = true};
|
||||
|
||||
void make_default_config() {
|
||||
FILE *config_file = fopen(CONFIG_PATH, "w");
|
||||
FILE *config_file;
|
||||
fopen_s(&config_file, CONFIG_PATH, "w");
|
||||
if (config_file == NULL) {
|
||||
puts("Failed to create config file!");
|
||||
return;
|
||||
@ -23,8 +24,7 @@ void make_default_config() {
|
||||
|
||||
#define CFG_bool(s, n, default, comment) \
|
||||
if (strlen(comment) != 0) fprintf(config_file, "; %s\n", comment); \
|
||||
fprintf(config_file, "; (bool) default = %s\n", \
|
||||
default ? "true" : "false"); \
|
||||
fprintf(config_file, "; (bool) default = %s\n", default ? "true" : "false"); \
|
||||
fprintf(config_file, "%s = %s\n", #n, default ? "true" : "false");
|
||||
|
||||
#define CFG_int(s, n, default, comment) \
|
||||
@ -34,8 +34,7 @@ void make_default_config() {
|
||||
|
||||
#define CFG_hex(s, n, precision, default, comment) \
|
||||
if (strlen(comment) != 0) fprintf(config_file, "; %s\n", comment); \
|
||||
fprintf(config_file, "; (hex) default = %.*X\n", precision, \
|
||||
0x##default); \
|
||||
fprintf(config_file, "; (hex) default = %.*X\n", precision, 0x##default); \
|
||||
fprintf(config_file, "%s = %.*X\n", #n, precision, 0x##default);
|
||||
|
||||
#define SECTION(s, comment) \
|
||||
@ -53,8 +52,7 @@ void make_default_config() {
|
||||
fclose(config_file);
|
||||
}
|
||||
|
||||
int handler(void *user, const char *section, const char *name,
|
||||
const char *value) {
|
||||
int handler(void *user, const char *section, const char *name, const char *value) {
|
||||
config_t *cfg = (config_t *)user;
|
||||
|
||||
char *end;
|
||||
@ -62,22 +60,18 @@ int handler(void *user, const char *section, const char *name,
|
||||
if (false)
|
||||
;
|
||||
#define CFG_str(s, n, default, comment) \
|
||||
else if (stricmp(section, #s) == 0 && stricmp(name, #n) == 0) \
|
||||
cfg->s##_##n = strdup(value);
|
||||
else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) cfg->s##_##n = _strdup(value);
|
||||
#define CFG_bool(s, n, default, comment) \
|
||||
else if (stricmp(section, #s) == 0 && stricmp(name, #n) == 0) \
|
||||
cfg->s##_##n = strcmp(value, "true") == 0;
|
||||
else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) cfg->s##_##n = strcmp(value, "true") == 0;
|
||||
#define CFG_int(s, n, default, comment) \
|
||||
else if (stricmp(section, #s) == 0 && stricmp(name, #n) == 0) { \
|
||||
else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) { \
|
||||
cfg->s##_##n = strtol(value, &end, 10); \
|
||||
if (end == value || *end != '\0' || errno == ERANGE) \
|
||||
cfg->s##_##n = default; \
|
||||
if (end == value || *end != '\0' || errno == ERANGE) cfg->s##_##n = default; \
|
||||
}
|
||||
#define CFG_hex(s, n, precision, default, comment) \
|
||||
else if (stricmp(section, #s) == 0 && stricmp(name, #n) == 0) { \
|
||||
else if (_stricmp(section, #s) == 0 && _stricmp(name, #n) == 0) { \
|
||||
cfg->s##_##n = strtol(value, &end, 16); \
|
||||
if (end == value || *end != '\0' || errno == ERANGE) \
|
||||
cfg->s##_##n = 0x##default; \
|
||||
if (end == value || *end != '\0' || errno == ERANGE) cfg->s##_##n = 0x##default; \
|
||||
}
|
||||
|
||||
#include "config.def"
|
||||
@ -86,15 +80,12 @@ int handler(void *user, const char *section, const char *name,
|
||||
}
|
||||
|
||||
void load_config() {
|
||||
if (ini_parse(CONFIG_PATH, handler, &Config) < 0)
|
||||
printf("Can't load '%s', using defaults\n", CONFIG_PATH);
|
||||
if (ini_parse(CONFIG_PATH, handler, &Config) < 0) printf("Can't load '%s', using defaults\n", CONFIG_PATH);
|
||||
}
|
||||
|
||||
int main() {
|
||||
DWORD dwAttrib = GetFileAttributes(CONFIG_PATH);
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES ||
|
||||
(dwAttrib & FILE_ATTRIBUTE_DIRECTORY))
|
||||
make_default_config();
|
||||
if (dwAttrib == INVALID_FILE_ATTRIBUTES || (dwAttrib & FILE_ATTRIBUTE_DIRECTORY)) make_default_config();
|
||||
|
||||
load_config();
|
||||
|
||||
|
@ -13,7 +13,7 @@ endif
|
||||
rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico)
|
||||
executable(
|
||||
'micekeychip',
|
||||
win_subsystem: 'console',
|
||||
win_subsystem: subsystem,
|
||||
sources: [
|
||||
'main.c',
|
||||
'mxk.c',
|
||||
|
@ -7,16 +7,13 @@ pcpa_cb_table_t CALLBACK_FUNCTION_BUFFER[40];
|
||||
byte BINARY_DATA[4096];
|
||||
size_t BINARY_DATA_LEN;
|
||||
|
||||
void mxkBinaryCallback(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendBinaryBuffer(stream, BINARY_DATA, BINARY_DATA_LEN);
|
||||
}
|
||||
void mxkBinaryCallback(pcpa_t* stream, void* data) { pcpaSetSendBinaryBuffer(stream, BINARY_DATA, BINARY_DATA_LEN); }
|
||||
|
||||
int mxkInit() {
|
||||
// Enable colour
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
DWORD dwMode = 0;
|
||||
if (GetConsoleMode(hConsole, &dwMode))
|
||||
SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
if (GetConsoleMode(hConsole, &dwMode)) SetConsoleMode(hConsole, dwMode | ENABLE_VIRTUAL_TERMINAL_PROCESSING);
|
||||
|
||||
WSADATA wsaData;
|
||||
int err = WSAStartup(2, &wsaData);
|
||||
@ -24,9 +21,19 @@ int mxkInit() {
|
||||
return err;
|
||||
}
|
||||
|
||||
void log_callback(struct pcpa* stream, void* data) {
|
||||
FILE* log_file = fopen("pcp.log", "a");
|
||||
if (log_file != NULL) {
|
||||
fprintf(log_file, "%s\n", (char*)data);
|
||||
fclose(log_file);
|
||||
}
|
||||
}
|
||||
|
||||
e_pcpa_t mxkPcpStreamInit() {
|
||||
e_pcpa_t err;
|
||||
|
||||
PCP.before_cb = log_callback;
|
||||
|
||||
err = pcpaInitStream(&PCP);
|
||||
if (err != e_pcpa_ok) {
|
||||
printf("pcpaInitStream Error. Code:%d\n", err);
|
||||
@ -34,8 +41,7 @@ e_pcpa_t mxkPcpStreamInit() {
|
||||
}
|
||||
|
||||
err = pcpaSetCallbackFuncBuffer(&PCP, CALLBACK_FUNCTION_BUFFER,
|
||||
(sizeof CALLBACK_FUNCTION_BUFFER) /
|
||||
(sizeof CALLBACK_FUNCTION_BUFFER[0]));
|
||||
(sizeof CALLBACK_FUNCTION_BUFFER) / (sizeof CALLBACK_FUNCTION_BUFFER[0]));
|
||||
if (err != e_pcpa_ok) {
|
||||
printf("pcpaSetCallBackFuncBuffer Error. Code:%d\n", err);
|
||||
return err;
|
||||
@ -58,8 +64,7 @@ e_pcpa_t mxkPcpStreamInit() {
|
||||
pcpaSetCallbackFunc(&PCP, AB_FORMATTYPE, mxkPcpAbFormatType, NULL);
|
||||
pcpaSetCallbackFunc(&PCP, AB_REGION, mxkPcpAbRegion, NULL);
|
||||
pcpaSetCallbackFunc(&PCP, AB_PLATFORMID, mxkPcpAbPlatformId, NULL);
|
||||
pcpaSetCallbackFunc(&PCP, AB_NETWORKADDRESS, mxkPcpAbNetworkAddress,
|
||||
NULL);
|
||||
pcpaSetCallbackFunc(&PCP, AB_NETWORKADDRESS, mxkPcpAbNetworkAddress, NULL);
|
||||
pcpaSetCallbackFunc(&PCP, AB_DVD, mxkPcpAbDvd, NULL);
|
||||
pcpaSetCallbackFunc(&PCP, AB_SEED, mxkPcpAbSeed, NULL);
|
||||
// Billing
|
||||
@ -101,21 +106,20 @@ e_pcpa_t mxkPcpStreamInit() {
|
||||
}
|
||||
int open_mode = Config.pcp_bind_global ? OPEN_MODE_GLOBAL : OPEN_MODE_1;
|
||||
|
||||
err = pcpaOpenServerWithBinary(&PCP, open_mode, text_port, binary_port,
|
||||
300000);
|
||||
err = pcpaOpenServerWithBinary(&PCP, open_mode, text_port & 0xffff, binary_port & 0xffff, 300000);
|
||||
if (err != e_pcpa_ok && err != e_pcpa_to) {
|
||||
printf("pcpaOpenServerWithBinary Error. Code %d\n", err);
|
||||
return e_pcpa_not_open;
|
||||
}
|
||||
if (open_mode == OPEN_MODE_GLOBAL)
|
||||
printf("Listening on 0.0.0.0:%d (:%d)\n", text_port, binary_port);
|
||||
printf("Listening on 0.0.0.0:%d (:%d)\n", text_port & 0xffff, binary_port & 0xffff);
|
||||
else
|
||||
printf("Listening on 127.0.0.1:%d (:%d)\n", text_port, binary_port);
|
||||
printf("Listening on 127.0.0.1:%d (:%d)\n", text_port & 0xffff, binary_port & 0xffff);
|
||||
return e_pcpa_ok;
|
||||
}
|
||||
|
||||
#define TICK_MS 16
|
||||
#define PRINT_DEBUG
|
||||
// #define PRINT_DEBUG
|
||||
#ifdef PRINT_DEBUG
|
||||
// Larger TICK_MS for testing
|
||||
#undef TICK_MS
|
||||
|
@ -19,7 +19,8 @@ void print_patches(patches_t* patches, char* filename) {
|
||||
}
|
||||
|
||||
void apply_patches(patches_t* patches, char* filename) {
|
||||
FILE* fp = fopen(filename, "r+b");
|
||||
FILE* fp;
|
||||
fopen_s(&fp, filename, "r+b");
|
||||
if (fp == NULL) {
|
||||
fprintf(stderr, "Failed to open %s for modification\n", filename);
|
||||
return;
|
||||
@ -98,7 +99,7 @@ int main(int argc, char** argv) {
|
||||
char error[json_error_max];
|
||||
patches_t all_patches;
|
||||
if (!load_patches(&all_patches, argv[1], error)) {
|
||||
fprintf(stderr, "%s", error);
|
||||
fprintf(stderr, "%s\n", error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
rc = import('windows').compile_resources('micepatch.rc', depend_files: micepatch_ico)
|
||||
micepatch = executable(
|
||||
'micepatch',
|
||||
win_subsystem: 'console',
|
||||
win_subsystem: subsystem,
|
||||
sources: [
|
||||
'main.c',
|
||||
rc,
|
||||
|
6
src/micetools/micetest/main.c
Normal file
6
src/micetools/micetest/main.c
Normal file
@ -0,0 +1,6 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
puts("Hello world");
|
||||
return 0;
|
||||
}
|
7
src/micetools/micetest/meson.build
Normal file
7
src/micetools/micetest/meson.build
Normal file
@ -0,0 +1,7 @@
|
||||
executable(
|
||||
'micetest',
|
||||
win_subsystem: subsystem,
|
||||
sources: [
|
||||
'main.c',
|
||||
],
|
||||
)
|
Loading…
Reference in New Issue
Block a user