1
0
mirror of synced 2024-11-27 15:00:49 +01:00

Quite a lot has happened; I lose track

This commit is contained in:
Bottersnike 2022-10-30 17:33:02 +00:00
parent 4464d9188f
commit f02db82030
88 changed files with 11499 additions and 5405 deletions

5
.gitignore vendored
View File

@ -3,8 +3,3 @@ build/
builddir/
srcdir/
.vscode/
# Don't distribute the libpcp sources
src/micetools/lib/libpcp/*.c
# And keep build artifacts out of git!
src/libpcp.lib

View File

@ -46,9 +46,13 @@ clean:
.PHONY: dist
dist:
@-mkdir $(DIST_DIR)
@-mkdir $(DIST_DIR) > NUL 2>&1
@-mkdir $(DIST_DIR)\util > NUL 2>&1
@-mkdir $(DIST_DIR)\Execute > NUL 2>&1
@-mkdir $(DIST_DIR)\Execute\Z > NUL 2>&1
@-mkdir $(DIST_DIR)\Execute\S > NUL 2>&1
@copy /Y "$(BUILD_DIR_32)/src/micetools/micekeychip\micekeychip.exe" "$(DIST_DIR)/micekeychip.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/micepatch.exe"
@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"
@ -58,6 +62,18 @@ dist:
# @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"
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\miceprestartup.exe" "$(DIST_DIR)/Execute/miceprestartup.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\micestartup.exe" "$(DIST_DIR)/Execute/micestartup.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\TrueCrypt.exe" "$(DIST_DIR)/Execute/TrueCrypt.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\mxmaster.exe" "$(DIST_DIR)/Execute/S/mxmaster.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/util/micepatch.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micedump.exe" "$(DIST_DIR)/util/micedump.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micetinker.exe" "$(DIST_DIR)/util/micetinker.exe"
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micemonitor.exe" "$(DIST_DIR)/util/micemonitor.exe"
@copy /Y "src/micetools/miceboot\TrueCrypt.cmd" "$(DIST_DIR)/Execute/TrueCrypt.cmd"
@xcopy /E /H /C /R /Q /Y src\system "$(DIST_DIR)\system/*"
@xcopy /E /H /C /R /Q /Y src\tools "$(DIST_DIR)\tools/*"
@xcopy /E /H /C /R /Q /Y src\patches "$(DIST_DIR)\patches/*"

62
assert_dd_blocks.py Normal file
View File

@ -0,0 +1,62 @@
MBR_LBA_GAP = 0x3f
BOOT_PARITION_SIZE = 0x300B85
RECOVER_PARTITION_SIZE = 0x300BC4
partitions = [
0x102d83,
0x403947,
0x403947,
0x48ed459,
0x20014aa,
]
ext_offset = 0
offsets = [0] * len(partitions)
extended_base = MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE
for i in range(len(partitions)):
offsets[i] = ext_offset + extended_base
ext_offset += partitions[i] + MBR_LBA_GAP
# (Start, end, data)
accounted_for = [
(0, 1, True), # MBR
(1, MBR_LBA_GAP, False),
(MBR_LBA_GAP, MBR_LBA_GAP + BOOT_PARITION_SIZE, True),
(MBR_LBA_GAP + BOOT_PARITION_SIZE, MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE, True),
]
for n, (i, j) in enumerate(zip(offsets, partitions)):
accounted_for.append((
i, i + 1, True
))
if n == 0:
# SBR
accounted_for.append((
i + 1, i + 4, True
))
accounted_for.append((
i + 4, i + MBR_LBA_GAP, False
))
else:
accounted_for.append((
i + 1, i + MBR_LBA_GAP, False
))
accounted_for.append((
i + MBR_LBA_GAP, i + MBR_LBA_GAP + j, True
))
assert accounted_for[-1][1] == 0x77fa1d7
last = 0
for i in accounted_for:
assert i[0] == last
last = i[1]
with open(r"G:\finale_dd\finale_dd.img", "rb") as finale_dd:
for i in accounted_for:
if i[2]:
continue
nbytes = i[1] - i[0]
finale_dd.seek(i[0] * 512)
print(f"Checking at {i[0] * 512:012x}-{i[1] * 512:012x}")
if any(finale_dd.read(nbytes * 512)):
print("!! FAIL")

View File

@ -1,8 +1,8 @@
project('micetools', 'c', default_options: [
'buildtype=minsize',
# ! Tobble /\ and \/ when building for XP (minsize=normal, static=XP)
# ! Toggle /\ and \/ when building for XP (minsize=normal, static=XP)
# 'b_vscrt=static_from_buildtype',
'warning_level=2',
'warning_level=3',
])
winxp = false
@ -15,6 +15,22 @@ 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
'/wd4706', # assignment within conditional expression
'/wd4214', # windns.h: nonstandard extension used: bit field types other than int
'/wd4201', # ewfapi.h: nameless struct/union
'/wd4200', # zero-sized arrays
'/wd4152', # hooks: function/data pointer conversion in expression
'/wd4100', # basically every hook causes "unreferenced formal parameter"
'/wd4206', # empty C files
'/wd4189', # lots of keychip functions aren't 100% implemented yet
'/we4047', # ... differs in levels of indirection from ...
'/we4057', # ... differs in levels of indirection (slightly) from ...
'/we4024', # ... different types for formal and actual paramter ...
'/we4013', # ... undefined; assuming extern returning int
language: 'c',
)
if winxp

159
mxinstaller.py Normal file
View File

@ -0,0 +1,159 @@
from pprint import pformat, pprint
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(("127.0.0.1", 12121))
slots = [
"original0",
"original1",
"patch0",
"patch1",
"os",
"app_data",
"originalf",
"originalb",
"patchf",
"patchb",
]
"""
slot 0: OS
os result=success&status=complete&id=AAS0&version=4524545&time=00000000000000&segcount=1745&segsize=262144&hw=AAS&instant=0&osver=4524545&ossegcount=0&orgtime=00000000000000&orgversion=4524545
slot 1: original0
original0 result=success&status=complete&id=SDEY&version=65633&time=20181029150736&segcount=65082&segsize=262144&hw=AAS&instant=0&osver=4524545&ossegcount=1745&orgtime=20181029150736&orgversion=65633
slot 2: ??
slot 3: ??
slot 4: ??
original1 result=error&status=error&code=40
patch0 result=success&status=empty
patch1 result=success&status=complete&id=SDEY&version=65634&time=20181116190448&segcount=173&segsize=262144&hw=AAS&instant=0&osver=0&ossegcount=0&orgtime=20181029150736&orgversion=65633
app_data result=invalid_parameter
originalf result=success&status=complete&id=SDEY&version=65633&time=20181029150736&segcount=65082&segsize=262144&hw=AAS&instant=0&osver=4524545&ossegcount=1745&orgtime=20181029150736&orgversion=65633
originalb result=error&status=error&code=40
patchf result=success&status=complete&id=SDEY&version=65634&time=20181116190448&segcount=173&segsize=262144&hw=AAS&instant=0&osver=0&ossegcount=0&orgtime=20181029150736&orgversion=65633
patchb result=success&status=empty
"""
def recv_pcp():
resp = s.recv(4096).decode().strip()
if resp == "?":
raise Exception("PCP Failed")
parts = resp.split("&")
return {i.split("=")[0]: i.split("=")[1] for i in parts}
def send_pcp(request, **kwargs):
req = f"request={request}"
if kwargs:
req += "&" + "&".join(f"{i}={kwargs[i]}" for i in kwargs)
assert s.recv(4096) == b">"
s.send(req.encode() + b"\r\n")
def pcp(request, **kwargs):
send_pcp(request, **kwargs)
ret = recv_pcp()
if ret["result"] != "success" or ret["response"] != request:
raise Exception(f"PCP Failed:\n{pformat(ret)}")
del ret["response"]
del ret["result"]
return ret
print("Query slots:")
for slot in slots:
assert s.recv(4096) == b">"
s.send(f"request=query_slot_status&slot={slot}\r\n".encode())
print(slot.ljust(20), s.recv(4096).decode().strip())
# assert s.recv(4096) == b">"
# s.send(f"request=check&slot={slot}\r\n".encode())
# print(slot.ljust(20), s.recv(4096).decode().strip())
print("-" * 10)
if pcp("query_semaphore_status")["semaphore"] != "1":
print("Unable to get semaphore!")
quit()
gsem = pcp("get_semaphore")
semid = gsem["semid"]
try:
spd = pcp("query_spd")
br = pcp("query_br")
bootslot = pcp("query_sbr_bootslot")
print("=== SPD ===")
order = spd.pop("order")
print(f"--- Order: {order}")
spd = list(spd.items())
spd.sort(key=lambda x: int(x[1]))
for i in spd:
# Values here are uk3 * block_size
print(f" - {(i[0] + ':').ljust(10)} {int(i[1]):016x}")
print(f"--- Bootslot: {bootslot['bootslot']}")
print("=== BR ===")
pprint(br)
quit()
assert s.recv(4096) == b">"
s.send((
b"request=check&"
b"slot=original0&"
b"segoffset=0&"
b"segcount=100000&"
b"force=1&"
b"semid=" + sem + b""
b"\r\n"
))
print(s.recv(4096).decode().strip())
assert s.recv(4096) == b">"
s.send((
b"request=release_semaphore&"
b"semid=" + sem + b""
b"\r\n"
))
print(s.recv(4096).decode().strip())
quit()
# assert s.recv(4096) == b">"
# s.send(b"request=set_sbr_bootslot&bootslot=cd\r\n")
# print(s.recv(4096).decode().strip())
assert s.recv(4096) == b">"
s.send(b"request=query_application_status\r\n")
print(s.recv(4096).decode().strip())
assert s.recv(4096) == b">"
s.send(b"request=query_br\r\n")
print(s.recv(4096).decode().strip())
assert s.recv(4096) == b">"
s.send((
b"request=appdata&"
b"slot=os&"
b"semid=" + sem + b"&"
b"\r\n"
))
# s.send((
# b"request=install&"
# b"slot=patch0&"
# b"segoffset=3&"
# b"id=SDEY&"
# b"version=010061&"
# b"time=20181029150736&"
# b"segcount=fe3a&"
# b"segsize=040000&"
# b"hw=AAS&"
# b"instant=3&"
# b"osver=450a01&"
# b"ossegcount=06d1&"
# b"orgtime=20181029150736&"
# b"orgversion=10061&"
# b"semid=" + sem + b"&"
# b"\r\n"
# ))
print(s.recv(4096).decode().strip())
finally:
pcp("release_semaphore", semid=semid)

View File

@ -36,16 +36,16 @@ BOOL DevClearCommError(void* data, LPDWORD lpErrors, LPCOMSTAT lpStat) {
return TRUE;
}
BOOL DevWriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped) {
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) {
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
@ -59,22 +59,99 @@ BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWOR
if (read != 0) {
// log_info("drf", "%d", read);
// for (int i = 0; i < read; i++) {
// printf("%02x ", ((unsigned char*)lpBuffer)[i]);
// printf("%02x ", ((LPBYTE)lpBuffer)[i]);
// }
// puts("");
}
return TRUE;
}
short comdev_read_blocking(com_device_t* com, unsigned char* buffer, short bytes) {
while (comdev_available(com) < bytes) SwitchToThread();
return ringbuf_read(&com->in, buffer, bytes);
}
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 comdev_write(com_device_t* com, const 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); }
BYTE comdev_peek(com_device_t* com) { return com->in.buffer[com->in.read]; }
BYTE one_byte;
// Read data from a com device, unescaping as we go
void comio_read(com_device_t* com, BYTE* data, BYTE len) {
for (; len; len--) {
comdev_read_blocking(com, &one_byte, 1);
if (one_byte == COMIO_MARK) {
comdev_read_blocking(com, &one_byte, 1);
one_byte++;
}
*(data++) = one_byte;
}
}
// Write data to a com device, escaping as we go
void comio_write(com_device_t* com, BYTE* data, BYTE len) {
for (; len; len--) {
one_byte = *(data++);
if (one_byte == COMIO_MARK || one_byte == COMIO_SYNC) {
BYTE mark = COMIO_MARK;
comdev_write(com, &mark, 1);
one_byte--;
}
comdev_write(com, &one_byte, 1);
}
}
void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) {
do {
if (comdev_available(com) < (sizeof *head + 1)) {
SwitchToThread();
continue;
}
comdev_read(com, &one_byte, 1);
if (one_byte != COMIO_SYNC) {
log_error("com", "Garbage on JVS: %02x", one_byte);
continue;
}
break;
} while (1);
comio_read(com, (LPBYTE)head, sizeof *head);
// TODO: Validate the sum? Do we care really?
comio_read(com, data, head->length);
unsigned char sum;
comio_read(com, &sum, 1);
}
void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len,
BYTE* data) {
one_byte = COMIO_SYNC;
comdev_write(com, &one_byte, 1);
comio_resp_head_t resp = {
.frame_length = len + sizeof resp,
.src = req->dst,
.seq = req->seq,
.status = status,
.op = req->op,
.length = len,
};
// Header
comio_write(com, (LPBYTE)&resp, sizeof resp);
// Payload
if (len) // If len == 0, we allow data to be null
comio_write(com, data, len);
// Checksum
one_byte = 0;
for (BYTE i = 0; i < sizeof resp; i++)
one_byte += ((LPBYTE)&resp)[i];
for (BYTE i = 0; i < len; i++)
one_byte += data[i];
comio_write(com, &one_byte, 1);
}
void com_device_thread(com_device_t* com, FnComDeviceThread* thread) {
com->thread = CreateThread(NULL, 0, thread, com, 0, NULL);
@ -109,8 +186,6 @@ com_device_t* new_com_device(BYTE port) {
hook_file(file);
hook_com(com);
free(com->virtual_handle);
com->virtual_handle = file->virtual_handle;
return hook;
}

View File

@ -1,6 +1,6 @@
#pragma once
#include "hooks/com.h"
#include "common.h"
#include "hooks/com.h"
#include "hooks/files.h"
typedef struct com_device {
@ -13,11 +13,42 @@ typedef struct com_device {
HANDLE thread;
} com_device_t;
typedef struct {
BYTE frame_length;
BYTE dst;
BYTE seq;
BYTE op;
BYTE length;
} comio_recv_head_t;
typedef struct {
BYTE frame_length;
BYTE src;
BYTE seq;
BYTE op;
BYTE status;
BYTE length;
} comio_resp_head_t;
#define COMIO_SYNC 0xE0
#define COMIO_MARK 0xD0
#define COMIO_STATUS_OK 0
#define COMIO_STATUS_NG 1
typedef DWORD(WINAPI FnComDeviceThread)(com_device_t* com);
short comdev_read_blocking(com_device_t* com, unsigned char* buffer, short bytes);
short comdev_read(com_device_t* com, unsigned char* buffer, short bytes);
bool comdev_write(com_device_t* com, unsigned char* buffer, short bytes);
bool comdev_write(com_device_t* com, const unsigned char* buffer, short bytes);
short comdev_available(com_device_t* com);
BYTE comdev_peek(com_device_t* com);
void comio_read(com_device_t* com, BYTE* data, BYTE len);
void comio_write(com_device_t* com, BYTE* data, BYTE len);
void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data);
void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, BYTE* data);
void com_device_thread(com_device_t* com, FnComDeviceThread* thread);
com_device_t* new_com_device(BYTE port);

View File

@ -15,6 +15,7 @@
#include <setupapi.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

View File

@ -3,4 +3,5 @@
void install_devices() {
install_led_bd();
install_touch_bd();
install_aime_bd();
}

View File

@ -4,5 +4,6 @@
void install_led_bd();
void install_touch_bd();
void install_aime_bd();
void install_devices();

View File

@ -0,0 +1,90 @@
#include "_devices.h"
static BYTE read_one(com_device_t* dev) {
while (!comdev_available(dev)) Sleep(50);
BYTE data;
comdev_read(dev, &data, 1);
return data;
}
BYTE extra[0xff];
#define GetFWVersion 0x30
#define GetHWVersion 0x32
#define RadioOn 0x40
#define RadioOff 0x41
#define Poll 0x2
#define MifareSelectTag 0x43
#define Unknown1 0x44 // Present in code, not seen used
#define SetKeyBana 0x50
#define Unknown2 0x51 // Present in code, not seen used
#define ReadBlock 0x52
#define SetKeyAime 0x54
#define Authenticate 0x55
#define Unknown3 0x60 // Present in code, not seen used
#define Unknown4 0x61 // Present in code, not seen used
#define Reset 0x62
#define Unknown5 0x70 // Present in code, not seen used
#define FelicaEncap 0x71
#define LedReset 0xf5
#define LedGetInfo 0xf0
#define LedSetColour 0x81
#define FWVer "TN32MSEC003S F/W Ver1.2"
#define HWVer "TN32MSEC003S H/W Ver3.0"
DWORD WINAPI aime_bd_thread(com_device_t* dev) {
log_warning("aime_bd", "%ls woke up", dev->com->wName);
while (1) {
comio_recv_head_t req;
comio_next_req(dev, &req, extra);
log_info("aime_bd", "(%d) %02x", req.dst, req.op);
if (req.dst == 0x00 || req.dst == 0x01) {
// Aime readers
switch (req.op) {
case Reset:
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
break;
case GetFWVersion:
comio_reply(dev, &req, COMIO_STATUS_OK, sizeof FWVer - 1, (LPBYTE)FWVer);
break;
case GetHWVersion:
comio_reply(dev, &req, COMIO_STATUS_OK, sizeof HWVer - 1, (LPBYTE)HWVer);
break;
case SetKeyAime:
log_info("aime_bd", "Aime key: %.*s", req.length, extra);
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
break;
case SetKeyBana:
log_info("aime_bd", "Bana key: %.*s", req.length, extra);
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
break;
}
} else if (req.dst == 0x08 || req.dst == 0x09) {
// LED sub-boards
switch (req.op) {
case LedReset:
comio_reply(dev, &req, COMIO_STATUS_OK, 0, NULL);
break;
case LedGetInfo:
// TODO: I'm not sure what this actually means.
// 838-15084 is probably a part number
comio_reply(dev, &req, COMIO_STATUS_OK, 9, (BYTE*)"15084\xff\x10\x00\x12");
break;
case LedSetColour:
// No response expected here!
break;
}
}
Sleep(50);
}
}
void install_aime_bd() {
com_device_t* aime = new_com_device(2);
com_device_thread(aime, aime_bd_thread);
}

View File

@ -73,6 +73,7 @@ typedef struct rs232c_recv_head {
BYTE op;
} rs232c_recv_head_t;
BYTE extra[0xff];
static DWORD WINAPI led_bd_thread(com_device_t* dev) {
log_warning("led_bd", "%ls woke up", dev->com->wName);
while (1) {
@ -81,9 +82,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
// Sleep(100);
continue;
}
comdev_read(dev, (char*)&head, sizeof head);
unsigned char* extra = malloc(head.length);
comdev_read(dev, (unsigned char*)&head, sizeof head);
comdev_read(dev, extra, head.length);
// log_info("led_bd", "Bound %02x->%02x", head.src, head.dst);
@ -91,13 +90,13 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
switch (head.op) {
case 0x01:
log_warning("led_bd", "01");
comdev_write(dev, "\xe0\x01\x11\x03\x01\x01\x01\x18", 8);
comdev_write(dev, (unsigned char*)"\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);
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x10\x01\x27", 8);
// syn dst src len sts op. rep chk
break;
@ -107,7 +106,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
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);
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x31\x01\x48", 8);
// syn dst src len sts op. rep chk
break;
case 0x32:
@ -120,13 +119,13 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
COLOURS[i][2] = extra[5];
}
comdev_write(dev, "\xe0\x01\x11\x03\x01\x32\x01\x49", 8);
comdev_write(dev, (unsigned char*)"\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);
comdev_write(dev, (unsigned char*)"\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]];
@ -135,7 +134,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
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);
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x39\x01\x50", 8);
// syn dst src len sts op. rep chk
COLOURS[9][0] = extra[0];
@ -144,18 +143,18 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
break;
case 0x3b:
log_warning("led_bd", "3b");
comdev_write(dev, "\xe0\x01\x11\x03\x01\x3b\x01\x52", 8);
comdev_write(dev, (unsigned char*)"\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);
comdev_write(dev, (unsigned char*)"\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);
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
// syn dst src len sts op. rep chk
break;
@ -163,14 +162,14 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
// 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);
comdev_write(dev, (unsigned char*)"\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);
// comdev_write(dev, (unsigned char*)"\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);
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x7b\x01\x92", 8);
// syn dst src len sts op. rep chk
break;
@ -178,8 +177,6 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
log_error("led_bd", "Unknown op %02x (%d)", head.op, head.length - 1);
break;
}
free(extra);
}
}
@ -200,13 +197,13 @@ void led_overlay(IDirect3DDevice9* dev) {
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);
// 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];
int x = (int)(rect.right * positions[i][0]);
int y = (int)(rect.bottom * positions[i][1]);
draw_rect(dev, x - 25, y - 25, 50, 50, COLOURS[i][0], COLOURS[i][1], COLOURS[i][2]);
}
}

View File

@ -2,4 +2,5 @@ devices_files = files(
'_devices.c',
'led_bd.c',
'touch_bd.c',
'aime_bd.c',
)

View File

@ -3,7 +3,7 @@
static BYTE read_one(com_device_t* dev) {
while (!comdev_available(dev)) Sleep(50);
BYTE data;
comdev_read(dev, (char*)&data, 1);
comdev_read(dev, &data, 1);
return data;
}
@ -21,7 +21,7 @@ DWORD WINAPI touch_bd_thread(com_device_t* dev) {
while (1) {
if (touch_is_enabled && !comdev_available(dev)) {
// Active mode!
comdev_write(dev, "(@@@@@@@@@@@@)", 14);
comdev_write(dev, (unsigned char*)"(@@@@@@@@@@@@)", 14);
Sleep(100);
continue;
}

View File

@ -39,12 +39,15 @@ void enable_traces() {
free_patches(&patches);
}
void prebind_hooks() {
hook_all();
install_devices();
// TODO: Figure out why we're needing to call this manually (medium priority)
if (wcscmp(exePath, L"ALLNetProc.exe") == 0) {
log_warning(BOOT_LOGGER, "Making explicit call to OPENSSL_add_all_algorithms_noconf");
// OPENSSL_add_all_algorithms_noconf
((void (*)(void))(0x00459770))();
}
@ -57,11 +60,17 @@ void init_injection() {
enable_traces();
// Columba: Driver-level memory access, used to read the DMI tables
setup_columba();
// MX SRAM: SRAM-based nv memory
setup_mxsram();
// MX SuperIO: Communicate with the HW monitor chip
setup_mxsuperio();
// MX JVS: Interacting with JVS-based devices
setup_mxjvs();
// MX HW Reset: Forcibly reboot the machine
setup_mxhwreset();
// MX SMBus: Communicate over the LPC bus. This contains the EEPROM, and PCA9535
setup_mxsmbus();
if (!add_fake_device(&PLATFORM_GUID, L"\\\\.\\platform")) {

View File

@ -12,14 +12,12 @@ typedef struct {
#define DMI_HEADER_START 0x000f0000
#define DMI_TABLES_START 0x000f1000
BOOL columba_DeviceIoControl(void* file, 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",
"DeviceIoControl(<columba>, <read dmi>, 0x%p, 0x%x, -, "
"0x%x, -, -)",
case IOCTL_COLUMBA_READ:
log_misc("columba", "DeviceIoControl(<columba>, <read>, 0x%p, 0x%x, -, 0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
columba_request* request = (columba_request*)lpInBuffer;
log_info("columba", "Physical read: 0x%04x %ss at %08X", request->bytes,
@ -50,12 +48,14 @@ BOOL columba_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
memcpy(lpOutBuffer, dmi_table, dmi_size);
if (lpBytesReturned) *lpBytesReturned = 0x10000;
} else {
log_error("columna", "Request to unmapped memory location: %08x", request->addr);
log_error("columba", "Request to unmapped memory location: %08x",
request->addr);
return FALSE;
}
break;
default:
// Observed: IOCTL_KSEC_RNG_REKEY
log_warning("columba", "unhandled 0x%08x", dwIoControlCode);
return FALSE;
}

View File

@ -1,6 +1,7 @@
#pragma once
#include "../hooks/_hooks.h"
#include "../common.h"
#include "../../lib/am/amEeprom.h"
FnDeviceIoControl mxhwreset_DeviceIoControl;
void setup_mxhwreset();
@ -22,6 +23,3 @@ 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);

View File

@ -50,7 +50,7 @@ int jvs_buttons[2][16] = {
},
};
short jvs_unpad(char* paddedData, short length, char* unpaddedData) {
short jvs_unpad(unsigned char* paddedData, short length, unsigned char* unpaddedData) {
short index = 0;
bool escape = false;
for (short i = 0; i < length; i++) {
@ -64,12 +64,13 @@ short jvs_unpad(char* paddedData, short length, char* unpaddedData) {
return index;
}
short jvs_pad(char* unpaddedData, short length, char* paddedData, short paddedMax) {
short jvs_pad(unsigned char* unpaddedData, short length, unsigned 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) {
if (i != 0 && (unpaddedData[i] == JVS_MARK || unpaddedData[i] == JVS_SYNC)) {
paddedData[index++] = JVS_MARK;
paddedData[index++] = unpaddedData[i] - 1;
} else {
@ -81,7 +82,8 @@ short jvs_pad(char* unpaddedData, short length, char* paddedData, short paddedMa
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) {
void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outData, short maxOut,
int* outCount) {
unsigned char* inData = malloc(inCount);
inCount = jvs_unpad(paddedIn, inCount, inData);
unsigned char* response = malloc(maxOut);
@ -105,7 +107,8 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
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]);
log_error("mxjvs", "Checksum failed. Computed 0x%02x, expected 0x%02x", sum,
inData[inCount - 1]);
status = JVS_STATUS_SUM;
goto jvs_exchange_error;
}
@ -202,7 +205,7 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
break;
case JVS_CMD_RECEIVE_MAIN_ID:
unsigned char tempRead = -1;
unsigned char tempRead = 0xff;
while (tempRead != 0) jvs_read(tempRead);
// TODO: Do we need to report here?
break;
@ -228,8 +231,10 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
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));
// 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;
@ -254,6 +259,16 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
break;
case JVS_CMD_READ_COIN:
jvs_write(JVS_REPORT_OK);
unsigned char coin_count;
jvs_read(coin_count);
for (; coin_count; coin_count--) {
jvs_write(0x00); // coin MSB
jvs_write(0x00); // coin LSB
}
break;
case JVS_CMD_READ_ANALOGS:
jvs_write(JVS_REPORT_OK);
// TODO: Actually emulate these (super low priority)
@ -276,7 +291,8 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
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_info("mxjvs", "Coin solenoid: %s",
coin_solenoid ? "Locked" : "Unlocked");
}
}
@ -300,7 +316,7 @@ jvs_exchange_error:
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[2] = (respIndex - 2) & 0xFF; // respIndex doesn't include SUM yet
response[3] = status;
// Compute and set the checksum
@ -319,17 +335,18 @@ jvs_exchange_complete:
free(inData);
}
BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped) {
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_misc("mxjvs",
log_trace("mxjvs",
"DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, "
"0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize, lpBytesReturned);
mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize & 0xFFFF,
(int*)lpBytesReturned);
break;
default:
@ -353,8 +370,8 @@ BOOL mxjvs_GetCommModemStatus(void* com, LPDWORD lpModelStat) {
BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) {
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]);
log_info("mxjvs", "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize,
PARITY[lpDCB->Parity], STOP[lpDCB->StopBits]);
return TRUE;
}
@ -362,7 +379,9 @@ void setup_mxjvs() {
file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs");
mxjvs->DeviceIoControl = &mxjvs_DeviceIoControl;
com_hook_t* jvscom = new_com_hook(-1);
com_hook_t* jvscom = new_com_hook(0);
wcscpy_s(jvscom->wName, sizeof jvscom->wName, L"\\\\.\\mxjvs");
wcscpy_s(jvscom->wDosName, sizeof jvscom->wDosName, L"\\\\.\\mxjvs");
jvscom->GetCommState = mxjvs_GetCommState;
jvscom->SetCommState = mxjvs_SetCommState;
jvscom->SetCommTimeouts = mxjvs_SetCommTimeouts;
@ -372,6 +391,4 @@ void setup_mxjvs() {
hook_file(mxjvs);
hook_com(jvscom);
free(jvscom->virtual_handle);
jvscom->virtual_handle = mxjvs->virtual_handle;
}

View File

@ -1,33 +1,8 @@
#include "../lib/dmi/dmi.h"
#include "../hooks/setupapi_.h"
#include "../lib/dmi/dmi.h"
#include "mx.h"
#include "smbus.h"
// PCA9535 (DIPSW)
#define PCA9535_WRITE 0x04
#define PCA9535_READ 0x05
#define PCA9535_IN0 0x00
#define PCA9535_IN1 0x01
#define PCA9535_OUT0 0x02
#define PCA9535_OUT1 0x03
#define PCA9535_INV0 0x04
#define PCA9535_INV1 0x05
#define PCA9535_CONF0 0x06
#define PCA9535_CONF1 0x07
#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 {
BYTE data[32];
@ -47,19 +22,26 @@ eeprom_bank_t EEPROM_DATA;
*/
void eeprom_dump() {
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
HANDLE dump =
_CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
if (dump == INVALID_HANDLE_VALUE) {
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed");
return;
} else {
log_info("eeprom", "Wrote eeprom to %s", EEPROM_DUMP);
}
_WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL);
FlushFileBuffers(dump);
_CloseHandle(dump);
}
void eeprom_restore() {
HANDLE dump =
_CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (dump == INVALID_HANDLE_VALUE) return;
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (dump == INVALID_HANDLE_VALUE) {
// Make the file, even though it'll probably be empty
eeprom_dump();
return;
}
DWORD read;
if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL))
log_error("eeprom", "failed to restore (%d)", GetLastError());
@ -77,16 +59,20 @@ DWORD eeprom_crc(BYTE reg) {
return crc32(28, EEPROM_DATA.reg[reg].data + 4, 0);
}
void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) {
log_game("eeprom", "EEPROM READ %d %d %d", reg, index, length);
eeprom_restore();
for (BYTE i = index; i < index + length; i++) {
if (i > 0x1f) break;
BYTE byte = EEPROM_DATA.reg[reg].data[i];
// TODO: Reg 1 and 17 in the EEPROM are system info. We should fake these!
// If register has a CRC
// if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg
// == 0x11 || reg == 0x12 || reg == 0x200) {
if (true) {
if (false) {
// Intercept the read and inject a CRC instead
if (i == 0x00 || i == 0x01 || i == 0x02 || i == 0x03) {
DWORD crc = eeprom_crc(reg);
@ -98,6 +84,8 @@ void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) {
}
}
void eeprom_write(BYTE reg, BYTE index, BYTE* data, BYTE length) {
log_game("eeprom", "EEPROM WRITE %d %d %d", reg, index, length);
for (BYTE i = index; i < index + length; i++) {
if (i > 0x1f) break;
EEPROM_DATA.reg[reg].data[i] = data[i - index];
@ -112,9 +100,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(void* file, 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;
@ -123,6 +111,8 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
BYTE dlen;
static uint16_t pca9535_config = 0xffff;
switch (dwIoControlCode) {
case IOCTL_MXSMBUS_GET_VERSION:
log_misc("mxsmbus",
@ -134,7 +124,7 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
if (lpBytesReturned) *lpBytesReturned = 4;
break;
case IOCTL_MXSMBUS_REQUEST: // dip r/w
log_misc("mxsmbus",
log_trace("mxsmbus",
"DeviceIoControl(<mxsmbus>, <request>, 0x%p, 0x%x, -, "
"0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
@ -171,22 +161,31 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
switch (i2c_packet->prt) {
case PCA9535_WRITE:
switch (i2c_packet->reg) {
case PCA9535_OUT0:
log_info("mxsmbus", "pca9535 OUT0: %02x", i2c_packet->data[0]);
break;
case PCA9535_OUT1:
log_info("mxsmbus", "pca9535 OUT1: %02x %02x", i2c_packet->data[0],
i2c_packet->data[1]);
log_info("mxsmbus", "pca9535 OUT1: %02x", i2c_packet->data[0]);
break;
case PCA9535_INV0:
log_info("mxsmbus", "pca9535 INV0: %02x %02x", i2c_packet->data[0],
i2c_packet->data[1]);
log_info("mxsmbus", "pca9535 INV0: %02x", i2c_packet->data[0]);
break;
case PCA9535_INV1:
log_info("mxsmbus", "pca9535 INV1: %02x %02x", i2c_packet->data[0],
i2c_packet->data[1]);
log_info("mxsmbus", "pca9535 INV1: %02x", i2c_packet->data[0]);
break;
case PCA9535_CONF0:
log_info("mxsmbus", "pca9535 CONF0: %02x", i2c_packet->data[0]);
pca9535_config =
(i2c_packet->data[0] << 8) | (pca9535_config & 0xff);
break;
case PCA9535_CONF1:
log_info("mxsmbus", "pca9535 CONF1: %02x", i2c_packet->data[0]);
pca9535_config =
i2c_packet->data[0] | (pca9535_config & 0xff00);
break;
default:
log_error("mxsmbux",
"(write) Undefined pca9535 "
"register: 0x%02x",
log_error("mxsmbus",
"(write) Undefined pca9535 register: 0x%02x",
i2c_packet->reg);
exit(1);
}
@ -194,28 +193,54 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
case PCA9535_READ:
switch (i2c_packet->reg) {
case PCA9535_IN0: // DIPSW
i2c_packet->data[0] = 0x00;
/*
0: ?
1: ?
2: ?
3: Orientation
4: / \
5: | Resolution |
6: \ /
7: game specific
0b00001000 = landscape
*/
puts("dipsw");
i2c_packet->data[0] = 0b00001000;
break;
case PCA9535_IN1: // SW1/2 + extras
/*
0: uk
1: uk
0: unk
1: unk
2: ¬test
3: ¬service
4: uk
5: uk
6: uk
7: uk
4: unk
5: unk
6: unk
7: unk
*/
i2c_packet->data[0] = 0x0c;
byte dip = 0x00;
if (GetAsyncKeyState('T') >= 0) {
dip |= 0x04;
}
if (GetAsyncKeyState('S') >= 0) {
dip |= 0x08;
}
i2c_packet->data[0] = dip;
break;
case PCA9535_INV0:
case PCA9535_INV1:
case PCA9535_OUT1: // LEDs, probably
i2c_packet->data[0] = 0x00;
break;
case PCA9535_CONF0:
i2c_packet->data[0] = pca9535_config >> 8;
break;
case PCA9535_CONF1:
i2c_packet->data[0] = pca9535_config & 0xff;
break;
default:
log_error("mxsmbux",
log_error("mxsmbus",
"(read) Undefined pca9535 "
"register: 0x%02x",
i2c_packet->reg);
@ -224,7 +249,8 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
i2c_packet->status = 0x00;
break;
default:
log_error("mxsmbux", "Unknown pca9535 command: 0x%02x", i2c_packet->prt);
log_error("mxsmbus", "Unknown pca9535 command: 0x%02x",
i2c_packet->prt);
exit(1);
}
break;
@ -235,7 +261,7 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
i2c_packet->status = 0;
break;
default:
log_error("mxsmbux", "Unknown eeprom command: 0x%02x", i2c_packet->prt);
log_error("mxsmbus", "Unknown eeprom command: 0x%02x", i2c_packet->prt);
exit(1);
}
break;
@ -253,8 +279,9 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
"-, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
log_misc("mxsmbus", "SMBus I2C request for %02x: 0x%02x (%02x bytes @ %02x)", request_packet->addr,
request_packet->prt, request_packet->dlen, request_packet->reg);
log_misc("mxsmbus", "SMBus I2C request for %02x: 0x%02x (%02x bytes @ %02x)",
request_packet->addr, request_packet->prt, request_packet->dlen,
request_packet->reg);
// log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[0],
// dwordInBuffer[1], dwordInBuffer[2], dwordInBuffer[3]);
// log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[4],
@ -301,13 +328,14 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
// for (int i = 0; i < dlen; i++) printf("%02x ",
// request_packet->data[i]); puts("");
eeprom_write(request_packet->reg >> 5, request_packet->reg & 0x1f, request_packet->data,
request_packet->dlen);
eeprom_write((request_packet->reg >> 5) & 0xff, request_packet->reg & 0x1f,
request_packet->data, request_packet->dlen);
request_out->status = 0;
} else if (i2c_packet->prt == 0x09) {
// Read
log_misc("mxsmbus", "eeprom read %02x (0x%04x)", dlen, request_packet->reg);
eeprom_read(request_packet->reg >> 5, request_packet->reg & 0x1f, request_out->data, dlen);
eeprom_read((request_packet->reg >> 5) & 0xff, request_packet->reg & 0x1f,
request_out->data, dlen);
// for (int i = 0; i < dlen; i++) printf("%02x ",
// request_out->data[i]); puts("");
request_out->status = 0;

View File

@ -28,7 +28,7 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped) {
DWORD SRAM_VERSION = 0x0001;
DWORD SRAM_SECTOR_SIZE = 0x100; // Max is 0x800
DWORD SRAM_SECTOR_SIZE = 4; // Max is 0x800
switch (dwIoControlCode) {
case IOCTL_MXSRAM_PING: // Get version
@ -48,11 +48,11 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
DISK_GEOMETRY out = *(PDISK_GEOMETRY)lpOutBuffer;
memset(&out, 0, sizeof(out));
out.Cylinders.QuadPart = 1;
out.Cylinders.QuadPart = 256;
out.MediaType = FixedMedia;
out.TracksPerCylinder = 224;
out.SectorsPerTrack = 32;
out.BytesPerSector = 1;
out.TracksPerCylinder = 24;
out.SectorsPerTrack = 8;
out.BytesPerSector = 512;
if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY);
break;
case IOCTL_MXSRAM_GET_SECTOR_SIZE:
@ -73,6 +73,7 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
}
DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
printf("MXSRSFP %08x\n", lDistanceToMove);
if (dwMoveMethod == FILE_BEGIN) {
SRAM_POINTER = lDistanceToMove;
} else if (dwMoveMethod == FILE_CURRENT) {

View File

@ -1,6 +1,7 @@
#include "mx.h"
#include "smbus.h"
#include "w83791d.h"
#include "w83627uhg.h"
BYTE w83791d_bank = 0x00;
BYTE w83791d_config = W83791D_CONFIG_START;
@ -13,9 +14,17 @@ BYTE w83791d_crit_t3 = 80; // C
BYTE w83791d_vbat_monitor_control = 0x00;
BOOL w83791d_4f_high = 0;
BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped) {
BYTE w83627uhg_fanconf = 0x01;
BYTE w83627uhg_fanconf_2 = 0x00;
BYTE w83627uhg_cpufanout_src_slct = 0x2d;
BYTE w83627uhg_sysfanout_src_slct = 0x00;
BYTE w83627uhg_systin_target = 0x00;
BYTE w83627uhg_cputin_target = 0x00;
BYTE w83627uhg_target_tolerance = 0x00;
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;
@ -29,42 +38,99 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
((LPDWORD)lpOutBuffer)[0] = 0x01000001;
if (lpBytesReturned) *lpBytesReturned = 4;
break;
case IOCTL_MXSUPERIO_READ:
log_misc("mxsuperio",
"DeviceIoControl(<mxsuperio>, <read>, 0x%p, 0x%x, -, "
"0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
case IOCTL_MXSUPERIO_READ: {
BYTE chip = ((LPBYTE)lpInBuffer)[0];
BYTE device = ((LPBYTE)lpInBuffer)[1];
BYTE index = ((LPBYTE)lpInBuffer)[2];
BYTE* data = &((LPBYTE)lpInBuffer)[3];
log_misc("mxsuperio", "read: chip:%d device:%d index:%02x", chip, device, index);
/*
BYTE chipId = 0|1
BYTE ?? = 0x0b
BYTE ?? = 0x20|0x21
BYTE ret = 0
{
IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e)
IN BYTE logical device (0 = FDC, 11 = HW mon)
IN BYTE index
OUT BYTE read value
}
The 846-5004D I have here is at base address 0x4e
*/
switch (((LPBYTE)lpInBuffer)[2]) {
/*
from micedump:
0.20: 00 0b 20 ff
0.21: 00 0b 21 ff
1.20: 01 0b 20 a2
1.21: 01 0b 21 32
*/
*data = 0xff;
if (chip == 1) {
if (device == 11) {
switch (index) {
case 0x20:
((LPBYTE)lpInBuffer)[3] = 0xa0;
*data = 0xa2;
break;
case 0x21:
((LPBYTE)lpInBuffer)[3] = 0x20;
break;
default:
((LPBYTE)lpInBuffer)[3] = 0x00;
*data = 0x32;
break;
}
}
}
if (lpBytesReturned) *lpBytesReturned = 4;
break;
}
case IOCTL_MXSUPERIO_WRITE:
log_misc("mxsuperio",
"DeviceIoControl(<mxsuperio>, <write>, 0x%p, 0x%x, -, "
"0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize);
/*
{
IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e)
IN BYTE logical device (0 = FPC, 11 = HW mon)
IN BYTE index
IN BYTE write value
}
*/
if (lpBytesReturned) *lpBytesReturned = 4;
break;
case IOCTL_MXSUPERIO_HWMONITOR_LPC_READ: {
// TODO: This code is all for W83791D, however W83627UHG is more appropriate in some
// cases. Is this an AAL vs AAM difference? Where was the W83791D usage derived from?
BYTE index = lpc_packet->index;
BYTE reg = lpc_packet->reg;
switch (w83791d_bank) {
case 0x00: {
switch (reg) {
case W83627UHG_REG_FAN_CONF:
lpc_out->data = w83627uhg_fanconf;
break;
case W83627UHG_REG_FAN_CONF_2:
lpc_out->data = w83627uhg_fanconf_2;
break;
case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT:
lpc_out->data = w83627uhg_cpufanout_src_slct;
break;
case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT:
lpc_out->data = w83627uhg_sysfanout_src_slct;
break;
case W83627UHG_REG_SYSTIN_TARGET_TEMP:
lpc_out->data = w83627uhg_systin_target;
break;
case W83627UHG_REG_CPUTIN_TARGET_TEMP:
lpc_out->data = w83627uhg_cputin_target;
break;
case W83627UHG_REG_TARGET_TEMP_TOLERANCE:
lpc_out->data = w83627uhg_target_tolerance;
break;
case W83791D_REG_WCHIPID:
lpc_out->data = 0x71;
lpc_out->data = 0x71; // Observed: c1
break;
case W83791D_REG_CHIPMAN:
if (w83791d_4f_high)
@ -73,7 +139,7 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
lpc_out->data = 0xa3; // Low byte
break;
case W83791D_REG_I2C_ADDR:
lpc_out->data = 0x11;
lpc_out->data = 0x11; // Observed: 2d
break;
case W83791D_REG_BANK:
lpc_out->data = w83791d_bank;
@ -84,16 +150,28 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
break;
case W83791D_REG_BEEP_CTRL_0:
lpc_out->data = 0xff; // All the beeps! (see main.h)
// No beeping :(
lpc_out->data = 0x00;
break;
// TODO: No idea how to read any of these. Pulled from real system
case W83791D_REG_TEMP1_0:
lpc_out->data = 0x00; // TODO: Figure out the temp val lol
lpc_out->data = 0x1a;
break;
case W83791D_RAM_VCOREA:
lpc_out->data = 0x76;
break;
case W83791D_RAM_VNIR0:
lpc_out->data = 0x86;
break;
case W83791D_RAM_VDD5:
lpc_out->data = 0x94;
break;
case W83791D_RAM_12VIN:
lpc_out->data = 0x00; // TODO: Figure out the batt val
lpc_out->data = 0xbe;
break;
case W83791D_RAM_N12VIN:
lpc_out->data = 0xd1;
break;
case W83791D_RAM_FAN1:
@ -103,9 +181,8 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
break;
case W83791D_VID_FAN_DIV:
// Boths fans divide by 2 (01), VDD 5 latched
// good.
lpc_out->data = 0b01011111; // Let's not /0!
// Boths fans divide by 2 (01)
lpc_out->data = 0b00000101;
break;
case W83791D_VBAT_MONITOR_CONTROL:
@ -113,8 +190,9 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
break;
default:
log_error("mxsuperio", "Unknown HM b0 register: 0x%02x", reg);
exit(1);
log_error("mxsuperio", "Unknown HM b0 register: read 0x%02x", reg);
return FALSE;
// exit(1);
}
} break;
case 0x01: {
@ -183,18 +261,48 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
// data > 0x0f, data < 0x70
// lpc_out->data = eeprom_read_one(reg, index);
log_misc("mxsuperio", "amHmLpcReadByte Index=0x%02x Reg=0x%02x Data=0x%02x", index, reg, lpc_out->data);
log_misc("mxsuperio", "amHmLpcReadByte Index=0x%02x Reg=0x%02x Data=0x%02x", index, reg,
lpc_out->data);
if (lpBytesReturned) *lpBytesReturned = sizeof(mxsuperio_lpc_packet);
} break;
case IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE: {
BYTE index = lpc_packet->index;
BYTE reg = lpc_packet->reg;
log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b", index, reg, lpc_packet->data);
log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b", index,
reg, lpc_packet->data);
switch (w83791d_bank) {
case 0x00: {
switch (reg) {
case W83627UHG_REG_FAN_CONF:
w83627uhg_fanconf = lpc_packet->data;
break;
case W83627UHG_REG_FAN_CONF_2:
w83627uhg_fanconf_2 = lpc_packet->data;
break;
case W83627UHG_REG_CPUFANOUT_VALUE_SELECT:
// Just no-op this
break;
case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT:
w83627uhg_cpufanout_src_slct = lpc_packet->data;
break;
case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT:
w83627uhg_sysfanout_src_slct = lpc_packet->data;
break;
case W83627UHG_REG_SYSTIN_TARGET_TEMP:
w83627uhg_systin_target = lpc_packet->data;
break;
case W83627UHG_REG_CPUTIN_TARGET_TEMP:
w83627uhg_cputin_target = lpc_packet->data;
break;
case W83627UHG_REG_TARGET_TEMP_TOLERANCE:
w83627uhg_target_tolerance = lpc_packet->data;
break;
case W83627UHG_REG_SYSFANOUT_STOP_VALUE:
case W83627UHG_REG_SYSFANOUT_START_VALUE:
break;
case W83791D_REG_BEEP_CTRL_0:
// Ignore for now
break;
@ -210,8 +318,8 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
w83791d_vbat_monitor_control = lpc_packet->data;
break;
default:
log_error("mxsuperio", "Unknown HM b0 register: 0x%02x", reg);
exit(1);
log_error("mxsuperio", "Unknown HM b0 register: write 0x%02x", reg);
// exit(1);
}
break;
}

View File

@ -0,0 +1,38 @@
# com.c
Generic hooks for com devices. The main COMs used are:
- COM 1: Camera
- COM 2: NFC
- COM 3: Touch
- COM 5-8: LEDs
These are defined in devices/
# files.c
Redirection hooks for files. These are used to redirect a number of locations to relative paths, and for `\\\\.\\driver` files.
# gui.c
Hooks for drawing over the game
# logging.c
Hooks for `[f]printf[_s]`, and event sources.
# network.c
Network hooks used to log when outbound TCP connections are made, and to redirect DNS.
# processes.c
(Disabled) hooks CreateProcess to re-inject ourself into any child processes too
# setupapi.c
Hooks the Setup API functions to inject fake devices (used for amPlatform and amEeprom)
# time.c
Hooks a handful of time-setting functions to NOP them

View File

@ -9,4 +9,6 @@ void hook_all() {
hook_processes();
hook_network();
hook_time();
hook_registry();
hook_drives();
}

View File

@ -8,5 +8,7 @@
#include "processes.h"
#include "setupapi_.h"
#include "time.h"
#include "registry.h"
#include "drive.h"
void hook_all();

View File

@ -1,5 +1,7 @@
#include "com.h"
#include "files.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);
@ -7,7 +9,8 @@ com_hook_t* new_com_hook(BYTE port) {
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);
swprintf(hook->wDosName, (sizeof hook->wDosName) / (sizeof hook->wDosName[0]), L"\\\\.\\COM%d",
port);
hook->com = port;
hook->GetCommState = NULL;
@ -21,7 +24,7 @@ com_hook_t* new_com_hook(BYTE port) {
hook->ClearCommError = NULL;
return hook;
};
}
void hook_com(com_hook_t* hook) {
hook->next = NULL;
@ -35,39 +38,33 @@ void hook_com(com_hook_t* hook) {
com_hook_t* hl = com_hook_list;
while (hl->next != NULL) hl = hl->next;
hl->next = hook;
};
}
BOOL WINAPI FakeGetCommState(HANDLE hFile, LPDCB lpDCB) {
log_misc(COMM_LOGGER, "GetCommState(0x%p, 0x%p)", hFile, lpDCB);
com_hook_t* hook = get_handle_com_hook(hFile);
log_misc(COMM_LOGGER, "GetCommState(0x%p, 0x%p) (%08x)", hFile, lpDCB, hook);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook != NULL) {
if (hook->GetCommState == NULL) {
log_error(COMM_LOGGER, "GetCommState(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->GetCommState(hook->data, lpDCB);
}
hook = hook->next;
}
return TrueGetCommState(hFile, lpDCB);
}
BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
log_misc(COMM_LOGGER, "SetCommState(0x%p, 0x%p)", hFile, lpDCB);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->SetCommState == NULL) {
log_error(COMM_LOGGER, "SetCommState(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->SetCommState(hook->data, lpDCB);
}
hook = hook->next;
}
return TrueSetCommState(hFile, lpDCB);
}
@ -75,119 +72,98 @@ BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
log_misc(COMM_LOGGER, "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->GetCommTimeouts == NULL) {
log_error(COMM_LOGGER, "GetCommTimeouts(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->GetCommTimeouts(hook->data, lpCommTimeouts);
}
hook = hook->next;
}
return TrueGetCommTimeouts(hFile, lpCommTimeouts);
}
BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
log_misc(COMM_LOGGER, "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->SetCommTimeouts == NULL) {
log_error(COMM_LOGGER, "SetCommTimeouts(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->SetCommTimeouts(hook->data, lpCommTimeouts);
}
hook = hook->next;
}
return TrueSetCommTimeouts(hFile, lpCommTimeouts);
}
BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) {
log_misc(COMM_LOGGER, "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->SetupComm == NULL) {
log_error(COMM_LOGGER, "SetupComm(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->SetupComm(hook->data, dwInQueue, dwOutQueue);
}
hook = hook->next;
}
return TrueSetupComm(hFile, dwInQueue, dwOutQueue);
}
BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) {
log_misc(COMM_LOGGER, "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->PurgeComm == NULL) {
log_error(COMM_LOGGER, "PurgeComm(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->PurgeComm(hook->data, dwFlags);
}
hook = hook->next;
}
return TruePurgeComm(hFile, dwFlags);
}
BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) {
log_misc(COMM_LOGGER, "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->GetCommModemStatus == NULL) {
log_error(COMM_LOGGER, "GetCommModemStatus(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->GetCommModemStatus(hook->data, lpModelStat);
}
hook = hook->next;
}
return TrueGetCommModemStatus(hFile, lpModelStat);
}
BOOL WINAPI FakeWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
log_misc(COMM_LOGGER, "WaitCommEvent");
log_misc(COMM_LOGGER, "WaitCommEvent(0x%p)", hFile);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->WaitCommEvent == NULL) {
log_error(COMM_LOGGER, "WaitCommEvent(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped);
}
hook = hook->next;
}
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped);
}
BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
log_misc(COMM_LOGGER, "ClearCommError");
log_trace(COMM_LOGGER, "ClearCommError(0x%p)", hFile);
com_hook_t* hook = com_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
com_hook_t* hook = get_handle_com_hook(hFile);
if (hook != NULL) {
if (hook->ClearCommError == NULL) {
log_error(COMM_LOGGER, "ClearCommError(%ls) unimplemented", hook->wName);
return FALSE;
}
return hook->ClearCommError(hook->data, lpErrors, lpStat);
}
hook = hook->next;
}
return TrueClearCommError(hFile, lpErrors, lpStat);
}
@ -198,7 +174,8 @@ void hook_commio() {
hook("Kernel32.dll", "SetCommTimeouts", FakeSetCommTimeouts, (void**)&TrueSetCommTimeouts, 6);
hook("Kernel32.dll", "SetupComm", FakeSetupComm, (void**)&TrueSetupComm, 6);
hook("Kernel32.dll", "PurgeComm", FakePurgeComm, (void**)&TruePurgeComm, 6);
hook("Kernel32.dll", "GetCommModemStatus", FakeGetCommModemStatus, (void**)&TrueGetCommModemStatus, 6);
hook("Kernel32.dll", "GetCommModemStatus", FakeGetCommModemStatus,
(void**)&TrueGetCommModemStatus, 6);
hook("Kernel32.dll", "WaitCommEvent", FakeWaitCommEvent, (void**)&TrueWaitCommEvent, 6);
hook("Kernel32.dll", "ClearCommError", FakeClearCommError, (void**)&TrueClearCommError, 6);
}

View File

@ -24,8 +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 wDosName[11]; // max is "\\\\.\\COM255"
WCHAR wName[16];
WCHAR wDosName[16];
BYTE com;
FnGetCommState* GetCommState;
@ -43,6 +43,8 @@ typedef struct com_hook {
struct com_hook* next;
} com_hook_t;
extern com_hook_t* com_hook_list;
com_hook_t* new_com_hook(BYTE port);
void hook_com(com_hook_t* hook);

View File

@ -0,0 +1,398 @@
#include "drive.h"
#include "./files.h"
BOOL c_drive_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
log_trace("C", "DeviceIOControl %08x", dwIoControlCode);
memset(lpOutBuffer, 0, nInBufferSize);
switch (dwIoControlCode) {
case IOCTL_STORAGE_GET_DEVICE_NUMBER:
((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceType = FILE_DEVICE_DISK;
((STORAGE_DEVICE_NUMBER*)lpOutBuffer)->DeviceNumber = 0;
return TRUE;
case IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS:
((VOLUME_DISK_EXTENTS*)lpOutBuffer)->NumberOfDiskExtents = 1;
((VOLUME_DISK_EXTENTS*)lpOutBuffer)->Extents[0].StartingOffset.QuadPart = 0;
DWORD a = (sizeof(*((VOLUME_DISK_EXTENTS*)lpOutBuffer)));
return TRUE;
default:
return FALSE;
}
}
LARGE_INTEGER pd0_file_pointer;
BOOL pd0_SetFilePointerEx(void* file, LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
log_trace("pd0", "Seek 0x%08x", liDistanceToMove.QuadPart);
if (dwMoveMethod == FILE_BEGIN)
pd0_file_pointer = liDistanceToMove;
else
pd0_file_pointer.QuadPart += liDistanceToMove.QuadPart;
if (lpNewFilePointer) lpNewFilePointer->QuadPart = pd0_file_pointer.QuadPart;
return TRUE;
}
DWORD pd0_SetFilePointer(void* file, LONG liDistanceToMove, PLONG lpDistanceToMoveHigh,
DWORD dwMoveMethod) {
if (lpDistanceToMoveHigh && *lpDistanceToMoveHigh)
log_trace("pd0", "Seek 0x%x%08x", *lpDistanceToMoveHigh, liDistanceToMove);
else
log_trace("pd0", "Seek 0x%08x", liDistanceToMove);
if (dwMoveMethod == FILE_BEGIN) {
if (lpDistanceToMoveHigh)
pd0_file_pointer.HighPart = *lpDistanceToMoveHigh;
else
pd0_file_pointer.HighPart = 0;
pd0_file_pointer.LowPart = liDistanceToMove;
} else {
pd0_file_pointer.QuadPart += liDistanceToMove;
if (lpDistanceToMoveHigh) pd0_file_pointer.HighPart += *lpDistanceToMoveHigh;
}
return pd0_file_pointer.LowPart;
}
void write_chs(BYTE* chs, WORD cylinder, BYTE head, BYTE sector) {
chs[0] = head;
chs[1] = sector | ((cylinder >> 8) << 6);
chs[2] = cylinder & 0xff;
}
#pragma pack(1)
typedef struct spd {
uint32_t crc;
uint8_t version;
uint8_t _[11];
#pragma pack(1)
struct {
/*
(BCD)
1.0 = original0
1.1 = original1
2.0 = patch0
2.1 = patch1
3.0 = os
4.0 = app_data
*/
spd_slot_t slot_content;
/*
Guess: Filesystem type
0: Encrypted FAT16
1: Decrypted NTFS
*/
uint8_t uk1;
uint16_t block_size;
uint32_t block_count;
uint8_t __[8];
} slots[31];
} spd_t;
#pragma pack(1)
typedef struct {
uint16_t year;
uint8_t mon;
uint8_t day;
uint8_t hour;
uint8_t min;
uint8_t sec;
uint8_t _;
} slot_time_t;
#pragma pack(1)
typedef struct {
char id[4];
slot_time_t time;
uint32_t version;
uint32_t _[2];
uint32_t segcount;
uint32_t segsize;
char hw[3];
uint8_t instant;
slot_time_t orgtime;
uint32_t orgversion;
uint32_t osver;
uint32_t ossegcount;
uint8_t __[8];
} sbr_slot_t;
#pragma pack(1)
enum {
Slot_Check = 0x00, // status=error
Slot_Install = 0x01, // status=install -> FAILED TO READ PREMADE BLOCK!!
Slot_Complete = 0x02, // status=complete
Slot_Empty = 0x03, // status=error
Slot_Error = 0x04, // status=error
Slot_Invalid = 0xff,
};
typedef uint8_t slot_status_t;
#pragma pack(1)
typedef struct {
uint32_t crc;
uint8_t version;
uint8_t _[11 + 16 + 32];
uint8_t bootslot;
uint8_t __[2];
slot_status_t slot_status[5];
uint8_t ___[8 + 16 + 32 + 64];
sbr_slot_t slot_os;
sbr_slot_t slot_original0;
sbr_slot_t slot_appdata;
sbr_slot_t slot_patch0;
sbr_slot_t slot_patch1;
} sbr_t;
sbr_t SegaBootRecord = {
.version = SBR_VERSION,
.bootslot = 0x02,
.slot_status = { Slot_Complete, Slot_Complete, Slot_Invalid, Slot_Check, Slot_Complete },
.slot_os = {
// Starts at 0xc5469400
// i.e. [partition 6] - (segcount * segsize)
// i.e. partition 5 = [dead space] [slot_os]
.id = {'A', 'A', 'S', '0'},
.time = { 0 },
.version = 0x450a01,
.segcount = 1745,
.segsize = 0x40000,
.hw = { 'A', 'A', 'S' },
.instant = 0,
.osver = 0x450a01,
.ossegcount = 0,
.orgtime = { 0 },
.orgversion = 0x450a01,
},
.slot_original0 = {
// Starts at 0xb065bae00
// i.e. [end of disk] - (segcount * segsize)
// i.e. partition 9 = [dead space] [slot_original0]
.id = {'S', 'D', 'E', 'Y'},
.time = { 2018, 10, 29, 15, 7, 36 },
.version = 0x10061,
.segcount = 65082,
.segsize = 0x40000,
.hw = { 'A', 'A', 'S' },
.instant = 0,
.osver = 0x450a01,
.ossegcount = 1745,
.orgtime = { 2018, 10, 29, 15, 7, 36 },
.orgversion = 0x10061,
},
.slot_appdata = { 0 },
.slot_patch0 = {
// Starts at 0x15e49a000
// i.e. [partition 7] - (segcount * segsize)
// i.e. partition 6 = [dead space] [something] [patch0]
.id = { 'S', 'D', 'D', 'Z' },
.time = { 2018, 6, 21, 13, 46, 24 },
.version = 0x10060,
.segcount = 173,
.segsize = 0x40000,
.hw = { 'A', 'A', 'S' },
.instant = 0,
.osver = 0,
.ossegcount = 0,
.orgtime = { 2018, 5, 16, 20, 7, 12 },
.orgversion = 0x01005f,
},
.slot_patch1 = {
// Starts at 0x1debcac00
// i.e. [partition 8] - (segcount * segsize)
// i.e. partition 7 = [dead space] [something] [patch0]
.id = { 'S', 'D', 'E', 'Y' },
.time = { 2018, 11, 16, 19, 4, 48},
.version = 0x10062,
.segcount = 173,
.segsize = 0x40000,
.hw = { 'A', 'A', 'S' },
.instant = 0,
.osver = 0,
.ossegcount = 0,
.orgtime = { 2018, 10, 29, 15, 7, 36 },
.orgversion = 0x10061,
},
};
#define BOOT_PARITION_SIZE 0x300B85 // 1.5GB
#define RECOVER_PARTITION_SIZE 0x300BC4 // 1.5GB
typedef struct {
uint32_t size;
uint8_t type;
spd_slot_t content;
} partition_t;
partition_t partitions[] = {
{ 0x102d83, MBR_FS_FAT16, SPD_OS }, // 512MB OS update
{ 0x403947, MBR_FS_FAT16, SPD_Patch0 }, // 2GB patch0
{ 0x403947, MBR_FS_FAT16, SPD_Patch1 }, // 2GB patch1
{ 0x48ed459, MBR_FS_NTFS, SPD_AppData }, // 40GB something
{ 0x20014aa, MBR_FS_FAT16, SPD_Original0 }, // 16GB game
};
#define NUM_PARITIONS (sizeof partitions / sizeof partitions[0])
#define MBR_LBA_GAP 0x3f // 1 track worth of sectors is claimed for the MBR
#define BLOCKSIZE 512ll
#define SPD_OFFSET ((extended_base * BLOCKSIZE) + sizeof(mbr_t))
#define SBR0_OFFSET (SPD_OFFSET + sizeof (spd_t))
#define SBR1_OFFSET (SBR0_OFFSET + sizeof SegaBootRecord)
BOOL pd0_ReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
log_info("pd0", "Read %d @ %llx", nNumberOfBytesToRead, pd0_file_pointer.QuadPart);
uint32_t ext_offset = 0;
uint32_t offsets[NUM_PARITIONS];
uint32_t extended_base = MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE;
for (int i = 0; i < NUM_PARITIONS; i++) {
offsets[i] = ext_offset;
ext_offset += partitions[i].size + MBR_LBA_GAP;
}
printf("%08x\n", offsets[0]);
printf("%08x\n", extended_base);
// MBR (C+Recover+Extend)
if (pd0_file_pointer.QuadPart == 0) {
mbr_t* mbr = (mbr_t*)lpBuffer;
memset(mbr, 0, sizeof *mbr);
mbr->sig[0] = 0x55;
mbr->sig[1] = 0xAA;
// 1.5GB C parition
mbr->partitions[0].status = MBR_FLAG_BOOTABLE;
mbr->partitions[0].type = MBR_FS_NTFS;
mbr->partitions[0].lba = MBR_LBA_GAP;
mbr->partitions[0].sectors = BOOT_PARITION_SIZE;
// 1.5GB Recovery
mbr->partitions[1].status = MBR_FLAG_NONE;
mbr->partitions[1].type = MBR_FS_NTFS;
mbr->partitions[1].lba = MBR_LBA_GAP + BOOT_PARITION_SIZE;
mbr->partitions[1].sectors = RECOVER_PARTITION_SIZE;
// Everything else is in an extended
mbr->partitions[2].status = MBR_FLAG_NONE;
mbr->partitions[2].type = MBR_FS_EXT_LBA;
mbr->partitions[2].lba = MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE;
mbr->partitions[2].sectors = ext_offset;
*lpNumberOfBytesRead = sizeof *mbr;
return TRUE;
}
// Extended partitions
for (int i = 0; i < NUM_PARITIONS; i++) {
if (pd0_file_pointer.QuadPart != ((extended_base + offsets[i]) * BLOCKSIZE)) continue;
mbr_t* mbr = (mbr_t*)lpBuffer;
memset(mbr, 0, sizeof *mbr);
mbr->sig[0] = 0x55;
mbr->sig[1] = 0xAA;
mbr->partitions[0].status = MBR_FLAG_NONE;
mbr->partitions[0].type = partitions[i].type;
mbr->partitions[0].lba = MBR_LBA_GAP;
mbr->partitions[0].sectors = partitions[i].size;
if (i != NUM_PARITIONS - 1) {
mbr->partitions[1].status = MBR_FLAG_NONE;
mbr->partitions[1].type = MBR_FS_EXT_CHS;
mbr->partitions[1].lba = offsets[i + 1];
mbr->partitions[1].sectors = partitions[i + 1].size + MBR_LBA_GAP;
}
*lpNumberOfBytesRead = sizeof *mbr;
return TRUE;
}
crc32_build_table();
SegaBootRecord.crc = crc32(sizeof SegaBootRecord - 4, &SegaBootRecord.version, 0);
// SEGA Partition Description
if (pd0_file_pointer.QuadPart == SPD_OFFSET) {
spd_t* spd = (spd_t*)lpBuffer;
spd->version = SPD_VERSION;
for (uint8_t i = 0; i < NUM_PARITIONS; i++) {
spd->slots[i].block_size = BLOCKSIZE;
spd->slots[i].block_count = partitions[i].size;
spd->slots[i].slot_content = partitions[i].content;
spd->slots[i].uk1 = partitions[i].type == MBR_FS_FAT16 ? 0 : 1;
}
spd->crc = crc32(sizeof *spd - 4, &(spd->version), 0);
*lpNumberOfBytesRead = sizeof *spd;
return TRUE;
}
// SEGA Boot Record 0 and 1. The two are a redundant copy of each other
if (pd0_file_pointer.QuadPart == SBR0_OFFSET || pd0_file_pointer.QuadPart == SBR1_OFFSET) {
memcpy(lpBuffer, &SegaBootRecord, sizeof SegaBootRecord);
*lpNumberOfBytesRead = sizeof SegaBootRecord;
return TRUE;
}
// Read within a partition
if (pd0_file_pointer.QuadPart < MBR_LBA_GAP * BLOCKSIZE) {
log_error("pd0", "Read performed within the first track of disk!");
} else if (pd0_file_pointer.QuadPart < (MBR_LBA_GAP + BOOT_PARITION_SIZE) * BLOCKSIZE) {
log_warning("pd0", "Game attempting to read windows partition!");
} else if (pd0_file_pointer.QuadPart <
(MBR_LBA_GAP + BOOT_PARITION_SIZE + RECOVER_PARTITION_SIZE) * BLOCKSIZE) {
log_warning("pd0", "Game attempting to read recovery partition!");
} else {
for (int i = 0; i < NUM_PARITIONS; i++) {
if (pd0_file_pointer.QuadPart <
(offsets[i] + MBR_LBA_GAP + extended_base) * BLOCKSIZE) {
log_error("pd0", "Read performed within the first track of partition %d!", i + 5);
goto warned;
} else if (pd0_file_pointer.QuadPart <
(offsets[i] + MBR_LBA_GAP + partitions[i].size + extended_base) *
BLOCKSIZE) {
log_warning("pd0", "Read performed within partition %d", i + 5);
goto warned;
}
}
log_error("pd0", "Read to unmapped address: %llx (%d bytes)", pd0_file_pointer.QuadPart,
nNumberOfBytesToRead);
warned:;
}
return FALSE;
}
BOOL pd0_WriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
log_warning("pd0", "Write %d @ %llx", nNumberOfBytesToWrite, pd0_file_pointer.QuadPart);
for (DWORD i = 0; i < nNumberOfBytesToWrite; i += 32) {
for (int j = 0; j < 32; j++) {
printf("%02x ", ((BYTE*)lpBuffer)[i + j]);
}
puts("");
}
*lpNumberOfBytesWritten = nNumberOfBytesToWrite;
return TRUE;
}
void hook_drives() {
file_hook_t* c_drive = new_file_hook(L"\\\\.\\C:");
c_drive->DeviceIoControl = &c_drive_DeviceIoControl;
hook_file(c_drive);
file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive0");
// file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive2063598201");
// file_hook_t* physical_drive_0 = new_file_hook(L"\\\\.\\PhysicalDrive1811939950");
physical_drive_0->SetFilePointerEx = pd0_SetFilePointerEx;
physical_drive_0->SetFilePointer = pd0_SetFilePointer;
physical_drive_0->ReadFile = pd0_ReadFile;
physical_drive_0->WriteFile = pd0_WriteFile;
hook_file(physical_drive_0);
}

View File

@ -0,0 +1,43 @@
#pragma once
#include "common.h"
void hook_drives();
// MBR
#define MBR_FLAG_NONE 0x00
#define MBR_FLAG_BOOTABLE 0x80
#define MBR_FS_NONE 0x00
#define MBR_FS_EXT_CHS 0x05
#define MBR_FS_FAT16 0x06
#define MBR_FS_NTFS 0x07
#define MBR_FS_EXT_LBA 0x0F
#pragma pack(1)
typedef struct mbr {
BYTE bootstrap_code[446];
#pragma pack(1)
struct {
BYTE status;
BYTE start_chs[3];
BYTE type;
BYTE end_chs[3];
DWORD lba;
DWORD sectors;
} partitions[4];
BYTE sig[2];
} mbr_t;
// SEGA
#define SPD_VERSION 1
#define SBR_VERSION 1
enum spd_slot {
SPD_Original0 = 0x10,
SPD_Original1 = 0x11,
SPD_Patch0 = 0x20,
SPD_Patch1 = 0x21,
SPD_OS = 0x30,
SPD_AppData = 0x40,
};
typedef uint8_t spd_slot_t;

View File

@ -1,11 +1,72 @@
#include "files.h"
HANDLE fake_handle = (HANDLE)0x10000000;
open_hook_t* open_hooks_list = NULL;
HANDLE open_hook(file_hook_t* file_hook, com_hook_t* com_hook) {
open_hook_t* opened = (open_hook_t*)malloc(sizeof(open_hook_t));
memset(opened, 0, sizeof *opened);
opened->file_hook = file_hook;
opened->com_hook = com_hook;
CHAR path[MAX_PATH];
GetModuleFileNameA(NULL, path, MAX_PATH);
HANDLE handle =
_CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
if (handle == INVALID_HANDLE_VALUE) {
log_error(HOOKS_LOGGER, "Failed to create dummy handle: %03x", GetLastError());
return INVALID_HANDLE_VALUE;
}
opened->handle = handle;
opened->next = open_hooks_list;
open_hooks_list = opened;
return handle;
}
void close_hook(HANDLE handle) {
if (handle == INVALID_HANDLE_VALUE) return;
_CloseHandle(handle);
open_hook_t* opened = NULL;
open_hook_t* root = open_hooks_list;
if (open_hooks_list->handle == handle) {
open_hook_t* next = open_hooks_list->next;
free(open_hooks_list);
open_hooks_list = next;
return;
}
while (root != NULL) {
if (root->next && root->next->handle == handle) {
opened = root->next;
root->next = opened->next;
free(opened);
return;
}
root = root->next;
}
}
file_hook_t* get_handle_file_hook(HANDLE handle) {
open_hook_t* root = open_hooks_list;
while (root != NULL) {
if (root->handle == handle) return root->file_hook;
root = root->next;
}
return NULL;
}
com_hook_t* get_handle_com_hook(HANDLE handle) {
open_hook_t* root = open_hooks_list;
while (root != NULL) {
if (root->handle == handle) return root->com_hook;
root = root->next;
}
return NULL;
}
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));
memset(hook, 0, sizeof *hook);
hook->filename = filename;
@ -13,8 +74,6 @@ file_hook_t* new_file_hook(LPCWSTR filename) {
}
void hook_file(file_hook_t* hook) {
hook->next = NULL;
hook->virtual_handle = (LPHANDLE)malloc(sizeof(HANDLE));
*hook->virtual_handle = NULL;
if (file_hook_list == NULL) {
file_hook_list = hook;
return;
@ -30,9 +89,12 @@ drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
// Note: Had tp create last_shime.log
{ .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" },
// {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"},
{ .drive = "C:\\\\Windows\\\\System32\\", .path = "Sys32" },
{ .drive = "C:\\\\WINDOWS\\\\system32\\", .path = "Sys32" },
};
char* redirect_path(char* path) {
LPCSTR redirect_path(LPCSTR path) {
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
drive_redirect_t row = DRIVE_REDIRECT_TABLE[i];
if (strstr(path, row.drive)) {
@ -45,7 +107,7 @@ char* redirect_path(char* path) {
char* dst = new_str + strlen(row.path);
size_t len = strlen(path) - strlen(row.drive);
char* src = path + strlen(row.drive);
const char* src = path + strlen(row.drive);
for (; len > 0; len--) (dst++)[0] = (src++)[0];
dst[0] = 0;
@ -55,66 +117,122 @@ char* redirect_path(char* path) {
}
return path;
}
LPCWSTR redirect_path_w(LPCWSTR path) {
return path;
// TODO: THIS!!
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
drive_redirect_t row = DRIVE_REDIRECT_TABLE[i];
if (wcsstr(path, row.drive)) {
log_misc(HOOKS_LOGGER, "Redirecting '%ls' to '%ls'", path, row.path);
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
HANDLE handle = NULL;
size_t new_len = wcslen(path) - wcslen(row.drive) + wcslen(row.path);
// TODO: Make this not leak memory!
wchar_t* new_str = (wchar_t*)malloc((new_len + 1) * 2);
wcscpy_s(new_str, new_len + 1, row.path);
file_hook_t* hook = file_hook_list;
while (hook != NULL) {
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)++;
wchar_t* dst = new_str + wcslen(row.path) * 2;
size_t len = wcslen(path) - wcslen(row.drive);
const wchar_t* src = path + wcslen(row.drive) * 2;
for (; len > 0; len--) {
(dst++)[0] = (src++)[0];
(dst++)[0] = (src++)[0];
}
handle = *hook->virtual_handle;
dst[0] = 0;
log_misc(HOOKS_LOGGER, "New filename: '%ls'", new_str);
return new_str;
}
}
return path;
}
log_info(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
void find_hooks(LPCWSTR lpFileName, file_hook_t** found_fh, com_hook_t** found_ch) {
file_hook_t* file_hook = file_hook_list;
while (file_hook != NULL) {
if (wcscmp(lpFileName, file_hook->filename) == 0 ||
(file_hook->altFilename != NULL && wcscmp(lpFileName, file_hook->altFilename) == 0)) {
*found_fh = file_hook;
break;
}
hook = hook->next;
file_hook = file_hook->next;
}
if (handle == NULL) {
handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
dwFlagsAndAttributes, hTemplateFile);
com_hook_t* com_hook = com_hook_list;
while (com_hook != NULL) {
if (wcscmp(lpFileName, com_hook->wName) == 0 ||
wcscmp(lpFileName, com_hook->wDosName) == 0) {
*found_ch = com_hook;
break;
}
com_hook = com_hook->next;
}
};
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile) {
file_hook_t* found_fh = NULL;
com_hook_t* found_ch = NULL;
find_hooks(lpFileName, &found_fh, &found_ch);
if (found_fh != NULL || found_ch != NULL) {
HANDLE handle = open_hook(found_fh, found_ch);
log_info(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
return handle;
}
lpFileName = redirect_path_w(lpFileName);
HANDLE handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
log_misc(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
return handle;
}
HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
lpFileName = redirect_path((char*)lpFileName);
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile) {
WCHAR wideFileName[MAX_PATH + 1];
MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, (LPWSTR)&wideFileName, MAX_PATH + 1);
HANDLE result = FakeCreateFileW((LPCWSTR)&wideFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
file_hook_t* found_fh = NULL;
com_hook_t* found_ch = NULL;
find_hooks(wideFileName, &found_fh, &found_ch);
if (found_fh != NULL || found_ch != NULL) {
HANDLE handle = open_hook(found_fh, found_ch);
log_info(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
return handle;
}
lpFileName = redirect_path(lpFileName);
HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
log_misc(HOOKS_LOGGER, "^-> CreateFileA(%s) -> 0x%p", lpFileName, result);
return result;
log_misc(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
return handle;
// lpFileName = redirect_path(lpFileName);
// HANDLE result =
// FakeCreateFileW((LPCWSTR)&wideFileName, dwDesiredAccess, dwShareMode,
// lpSecurityAttributes,
// dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
// log_trace(HOOKS_LOGGER, "^-> CreateFileA(%s) -> 0x%p", lpFileName, result);
// return result;
}
BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped) {
log_misc(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, 0x%p, 0x%x, -, 0x%x, 0, 0)", hDevice, dwIoControlCode,
lpInBuffer, nInBufferSize, nOutBufferSize);
file_hook_t* hook = file_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hDevice) {
BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
file_hook_t* hook = get_handle_file_hook(hDevice);
if (hook != NULL) {
if (hook->DeviceIoControl) {
// TODO: Less jank
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
BOOL ret = hook->DeviceIoControl(hook->data, 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;
}
@ -124,54 +242,49 @@ BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lp
return FALSE;
}
}
hook = hook->next;
}
// log_warning(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, -, -, -, -, 0, 0)", hDevice, dwIoControlCode);
log_trace(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, 0x%p, 0x%x, -, 0x%x, 0, 0)", hDevice,
dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize);
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize,
lpBytesReturned, lpOverlapped);
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
nOutBufferSize, lpBytesReturned, lpOverlapped);
}
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
file_hook_t* hook = file_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
DWORD dwMoveMethod) {
file_hook_t* hook = get_handle_file_hook(hFile);
if (hook != NULL) {
if (hook->SetFilePointer) {
return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh,
dwMoveMethod);
} else {
log_error(HOOKS_LOGGER, "SetFilePointer(%ls) unimplemented", hook->filename);
return FALSE;
}
}
hook = hook->next;
}
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) {
BOOL WINAPI FakeSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
file_hook_t* hook = get_handle_file_hook(hFile);
if (hook != NULL) {
if (hook->SetFilePointerEx) {
return hook->SetFilePointerEx(hook->data, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
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) {
file_hook_t* hook = get_handle_file_hook(hFile);
if (hook != NULL) {
if (hook->GetFileSizeEx) {
return hook->GetFileSizeEx(hook->data, lpFileSize);
} else {
@ -179,58 +292,53 @@ DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
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) {
DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
log_trace("file", "WriteFile(%08x)", hFile);
file_hook_t* hook = get_handle_file_hook(hFile);
if (hook != NULL) {
if (hook->WriteFile) {
return hook->WriteFile(hook->data, 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;
}
}
hook = hook->next;
}
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
return FALSE;
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
lpOverlapped);
}
BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped) {
file_hook_t* hook = file_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
file_hook_t* hook = get_handle_file_hook(hFile);
if (hook != NULL) {
if (hook->ReadFile) {
return hook->ReadFile(hook->data, 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;
}
}
hook = hook->next;
}
return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}
BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
file_hook_t* hook = file_hook_list;
while (hook != NULL) {
if (hObject != NULL && *hook->virtual_handle == hObject) {
file_hook_t* hook = get_handle_file_hook(hObject);
if (hook != NULL) {
log_misc("file", "close %08x", hObject);
close_hook(hObject);
return TRUE;
}
hook = hook->next;
}
return TrueCloseHandle(hObject);
}
@ -247,7 +355,8 @@ 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", "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);

View File

@ -1,55 +1,68 @@
#pragma once
#include "../common.h"
#include "com.h"
static HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
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);
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,
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);
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);
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 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,
typedef DWORD(FnSetFilePointer)(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
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(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);
typedef struct _stat64i32 _stat64i32_t;
static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer);
#define _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile)
#define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile)
#define _CloseHandle (TrueCloseHandle ? TrueCloseHandle : CloseHandle)
#define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW)
#define _CreateFileA (TrueCreateFileA ? TrueCreateFileA : CreateFileA)
typedef struct drive_redirect {
const CHAR* drive;
const CHAR* path;
} drive_redirect_t;
typedef struct drive_redirect_w {
const WCHAR* drive;
const WCHAR* path;
} drive_redirect_w_t;
typedef struct file_hook {
LPCWSTR filename;
LPCWSTR altFilename;
@ -67,6 +80,19 @@ typedef struct file_hook {
struct file_hook* next;
} file_hook_t;
typedef struct open_hook {
HANDLE handle;
file_hook_t* file_hook;
com_hook_t* com_hook;
struct open_hook* next;
} open_hook_t;
extern file_hook_t* file_hook_list;
file_hook_t* new_file_hook(LPCWSTR filename);
void hook_file(file_hook_t* hook);
void hook_io();
void close_hook(HANDLE handle);
file_hook_t* get_handle_file_hook(HANDLE handle);
com_hook_t* get_handle_com_hook(HANDLE handle);

View File

@ -19,7 +19,7 @@ char* trim_string(char* string) {
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);
size_t 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;
@ -31,11 +31,11 @@ int WINAPIV Fakeprintf(const char* _Format, ...) {
int ret = vlog_game("printf", _Format, args);
va_end(args);
return vlog_game("printf", _Format, args);
return ret;
}
int WINAPIV Fakefprintf(FILE* _File, const char* _Format, ...) {
int flen = strlen(_Format);
size_t 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;
@ -59,6 +59,9 @@ int WINAPIV Fakefprintf_s(FILE* _Stream, const char* _Format, ...) {
va_end(args);
return ret;
}
int WINAPIV Fakevfprintf_s(FILE* _Stream, const char* _Format, va_list _ArgList) {
return vlog_game("vfprintf_s", _Format, _ArgList);
}
HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { return (HANDLE)0xDEADBEEF; }
BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
@ -92,6 +95,7 @@ void hook_logging() {
hook("MSVCR90.DLL", "printf", Fakeprintf, (void**)&Trueprintf, 6);
hook("MSVCR90.DLL", "fprintf", Fakefprintf, (void**)&Truefprintf, 6);
hook("MSVCR90.DLL", "fprintf_s", Fakefprintf_s, (void**)&Truefprintf_s, 6);
hook("MSVCR90.DLL", "vfprintf_s", Fakevfprintf_s, (void**)&Truevfprintf_s, 6);
hook("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, (void**)&TrueRegisterEventSourceA, 6);
hook("Advapi32.dll", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA, 6);

View File

@ -12,5 +12,6 @@ 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, ...);
static int(WINAPIV* Truevfprintf_s)(FILE* _Stream, const char* _Format, va_list _ArgList);
void hook_logging();

View File

@ -8,4 +8,6 @@ hooks_files = files(
'processes.c',
'setupapi.c',
'time.c',
'registry.c',
'drive.c',
)

View File

@ -3,51 +3,94 @@
int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr.S_un.S_addr);
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port);
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff,
addr & 0xff, port);
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff,
(addr >> 8) & 0xff, addr & 0xff, port);
return True_connect(s, name, namelen);
}
static uint8_t spoof_mac[6] = { 0xD8, 0xBB, 0xC1, 0x0A, 0x2F, 0x1D };
#define IF_INDEX 1
DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) {
DWORD ret = TrueGetIfTable(pIfTable, pdwSize, bOrder);
if (ret == NO_ERROR) {
for (size_t i = 0; i < pIfTable->dwNumEntries; i++) {
pIfTable->table[i].bPhysAddr[0] = 0x00;
pIfTable->table[i].bPhysAddr[1] = 0xD0;
pIfTable->table[i].bPhysAddr[2] = 0xF1;
log_info("network", "Injecting fake IfTable");
MIB_IFROW* row;
uint32_t nbytes;
if (pdwSize == NULL) return ERROR_INVALID_PARAMETER;
nbytes = *pdwSize;
*pdwSize = sizeof(*row) + sizeof(DWORD);
if (pIfTable == NULL || nbytes < sizeof(*row) + sizeof(DWORD)) {
return ERROR_INSUFFICIENT_BUFFER;
}
}
return ret;
pIfTable->dwNumEntries = 1;
row = pIfTable->table;
memset(row, 0, sizeof(*row));
wcscpy_s(row->wszName, _countof(row->wszName), L"RING2 Ethernet");
row->dwIndex = IF_INDEX;
row->dwType = IF_TYPE_ETHERNET_CSMACD;
row->dwMtu = 4200;
row->dwSpeed = 1000000000;
row->dwPhysAddrLen = sizeof(spoof_mac);
memcpy(row->bPhysAddr, spoof_mac, sizeof(spoof_mac));
row->dwAdminStatus = 1;
row->dwOperStatus = IF_OPER_STATUS_OPERATIONAL;
return ERROR_SUCCESS;
// DWORD ret = TrueGetIfTable(pIfTable, pdwSize, bOrder);
// if (ret == NO_ERROR) {
// for (size_t i = 0; i < pIfTable->dwNumEntries; i++) {
// pIfTable->table[i].bPhysAddr[0] = 0x00;
// pIfTable->table[i].bPhysAddr[1] = 0xD0;
// pIfTable->table[i].bPhysAddr[2] = 0xF1;
// }
// }
// return ret;
}
const char* INTERCEPT_DNS[] = {
"naominet.jp", // Startup
"ib.naominet.jp", // Billing
"aime.naominet.jp", // Aime (duh)
"tenporouter.loc", // Routers
"bbrouter.loc", //
"mobirouter.loc", //
"dslrouter.loc", //
typedef struct {
char* name;
unsigned char address[4];
} dns;
dns INTERCEPT_DNS[] = {
// Startup
{ "naominet.jp", { 192, 168, 103, 254 } },
// Billing
{ "ib.naominet.jp", { 192, 168, 103, 254 } },
// Aime
{ "aime.naominet.jp", { 192, 168, 103, 254 } },
// Routers (ping targets)
{ "tenporouter.loc", { 192, 168, 103, 254 } },
{ "bbrouter.loc", { 192, 168, 103, 254 } }, // Must match tenporouter
{ "mobirouter.loc", { 192, 168, 103, 254 } },
{ "dslrouter.loc", { 192, 168, 103, 254 } },
};
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) {
DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra,
PDNS_RECORDA* ppQueryResults, PVOID* pReserved) {
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 %hhu.%hhu.%hhu.%hhu", pszName, SPOOF_IP[0], SPOOF_IP[1], SPOOF_IP[2],
SPOOF_IP[3]);
if (strcmp(pszName, INTERCEPT_DNS[i].name) == 0) {
#define spoof (INTERCEPT_DNS[i].address)
log_info("dns", "Replacing %s with %hhu.%hhu.%hhu.%hhu", pszName, spoof[0],
spoof[1], spoof[2], spoof[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 =
(SPOOF_IP[0]) | (SPOOF_IP[1] << 8) | (SPOOF_IP[2] << 16) | (SPOOF_IP[3] << 24);
(spoof[0]) | (spoof[1] << 8) | (spoof[2] << 16) | (spoof[3] << 24);
return ERROR_SUCCESS;
#undef spoof
}
}
}
@ -55,31 +98,36 @@ DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID
return TrueDnsQuery_A(pszName, wType, Options, pExtra, ppQueryResults, pReserved);
};
INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily, LPWSAPROTOCOL_INFOA lpProtocolInfo,
LPSOCKADDR lpAddress, LPINT lpAddressLength) {
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]);
if (strcmp(AddressString, INTERCEPT_DNS[i].name) == 0) {
#define spoof (INTERCEPT_DNS[i].address)
log_info("dns", "(WSA)Replacing %s with %hhu.%hhu.%hhu.%hhu", AddressString, spoof[0],
spoof[1], spoof[2], spoof[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];
lpAddress->sa_data[2] = spoof[0];
lpAddress->sa_data[3] = spoof[1];
lpAddress->sa_data[4] = spoof[2];
lpAddress->sa_data[5] = spoof[3];
return ERROR_SUCCESS;
#undef spoof
}
}
log_warning("dns", "(WSA)DNS passthrough for %s", AddressString);
return TrueWSAStringToAddressA(AddressString, AddressFamily, lpProtocolInfo, lpAddress, lpAddressLength);
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("Ws2_32.dll", "WSAStringToAddressA", FakeWSAStringToAddressA,
(void**)&TrueWSAStringToAddressA, 7);
hook("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable, 5);
hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A, 5);
}

View File

@ -6,28 +6,38 @@ const wchar_t* HOOK_BINARIES[] = {
L"app\\GmSync.exe",
};
#define DISABLE_PROC_SPAWNING
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation) {
// #ifdef DISABLE_PROC_SPAWNING
// log_error("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
// return FALSE;
// #else
log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
CHAR applicationName[MAX_PATH + 1];
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName, NULL, NULL);
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);
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);
}
return child != NULL;
return !FAILED(child);
// #endif
}
void hook_processes() {
// hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6);
hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6);
}

View File

@ -0,0 +1,5 @@
#include "registry.h"
void hook_registry() {
}

View File

@ -0,0 +1,4 @@
#pragma once
#include "common.h"
void hook_registry();

View File

@ -21,5 +21,6 @@ shared_library(
link_with: [
dmi_lib,
mice_lib,
amlib,
]
)

View File

@ -1,6 +1,31 @@
#pragma once
#include "common.h"
// PCA9535 (DIPSW)
#define PCA9535_WRITE 0x04
#define PCA9535_READ 0x05
#define PCA9535_IN0 0x00
#define PCA9535_IN1 0x01
#define PCA9535_OUT0 0x02
#define PCA9535_OUT1 0x03
#define PCA9535_INV0 0x04
#define PCA9535_INV1 0x05
#define PCA9535_CONF0 0x06
#define PCA9535_CONF1 0x07
#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!
#pragma pack(1)
typedef struct mxsmbus_request_packet_ {
BYTE status;

View File

@ -28,25 +28,50 @@ 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) {
char* log_colours[] = {
"", // Always
"\033[96m", // Game
"\033[91m", // Error
"\033[33m", // Warning
"\033[97m", // Info
"\033[90m", // Misc
"\033[90m", // Trace
};
#define LOG_PREFIXES "!GEWIMT"
void logcb(LPCSTR param_1) { log_error("logcb", param_1); }
extern WCHAR exePath[MAX_PATH + 1];
int _do_log(BYTE log_level, const char* caller, const char* format, va_list args) {
if (wcscmp(exePath, L"mxnetwork.exe") == 0) {
// *((DWORD*)(0x004438e8)) = (DWORD)(&logcb);
*((DWORD*)(0x004438e8)) = 0x00000000;
}
char prefix = LOG_PREFIXES[log_level];
EnterCriticalSection(&logger_lock);
int len = snprintf(NULL, 0, "%s%s:%s:", log_prelude(), level, caller) + vsnprintf(NULL, 0, format, args);
int len = snprintf(NULL, 0, "%s%c:%s:", log_prelude(), prefix, 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_a = snprintf(buf, len, "%s%c:%s:", log_prelude(), prefix, 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) {
if (LOG_LEVEL >= log_level) {
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);
if (HAS_COLOUR)
(TrueWriteFile ? TrueWriteFile : WriteFile)(sout, log_colours[log_level],
strlen(log_colours[log_level]), NULL, NULL);
if (sout != INVALID_HANDLE_VALUE)
(TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL);
puts(HAS_COLOUR ? "\033[0m" : "");
}
#ifdef LOG_TO_FILE
@ -59,8 +84,18 @@ int _do_log(const char* caller, const char* level, const char* format, va_list a
LeaveCriticalSection(&logger_lock);
return wrote_b;
}
int vlog_trace(const char* caller, const char* format, va_list args) {
return _do_log(LOG_TRACE, caller, format, args);
}
int log_trace(const char* caller, const char* format, ...) {
va_list args;
va_start(args, format);
int ret = vlog_trace(caller, format, args);
va_end(args);
return ret;
}
int vlog_misc(const char* caller, const char* format, va_list args) {
return _do_log(caller, "M", format, args, LOG_MISC, "\033[90m");
return _do_log(LOG_MISC, caller, format, args);
}
int log_misc(const char* caller, const char* format, ...) {
va_list args;
@ -70,7 +105,7 @@ int log_misc(const char* caller, const char* format, ...) {
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");
return _do_log(LOG_INFO, caller, format, args);
}
int log_info(const char* caller, const char* format, ...) {
va_list args;
@ -80,7 +115,7 @@ int log_info(const char* caller, const char* format, ...) {
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");
return _do_log(LOG_WARNING, caller, format, args);
}
int log_warning(const char* caller, const char* format, ...) {
va_list args;
@ -90,7 +125,7 @@ int log_warning(const char* caller, const char* format, ...) {
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");
return _do_log(LOG_ERROR, caller, format, args);
}
int log_error(const char* caller, const char* format, ...) {
va_list args;
@ -100,7 +135,7 @@ int log_error(const char* caller, const char* format, ...) {
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");
return _do_log(LOG_GAME, caller, format, args);
}
int log_game(const char* caller, const char* format, ...) {
va_list args;
@ -117,19 +152,23 @@ VOID trace_hook(char* output) {
void setup_logging() {
// Force stdio even for GUI applications
// TODO: Is there a more robust way to check if we have a proper stdio?
AttachConsole(ATTACH_PARENT_PROCESS);
if (GetStdHandle(STD_ERROR_HANDLE) > (HANDLE)0x10) {
FILE* newstream;
if (GetStdHandle(STD_INPUT_HANDLE)) {
freopen("CONIN$", "r", stdin);
freopen_s(&newstream, "CONIN$", "r", stdin);
setvbuf(stdin, NULL, _IONBF, 0);
}
if (GetStdHandle(STD_OUTPUT_HANDLE)) {
freopen("CONOUT$", "w", stdout);
freopen_s(&newstream, "CONOUT$", "w", stdout);
setvbuf(stdout, NULL, _IONBF, 0);
}
if (GetStdHandle(STD_ERROR_HANDLE)) {
freopen("CONOUT$", "w", stderr);
freopen_s(&newstream, "CONOUT$", "w", stderr);
setvbuf(stderr, NULL, _IONBF, 0);
}
}
// Enable colour in CMD
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
@ -139,6 +178,9 @@ void setup_logging() {
InitializeCriticalSection(&logger_lock);
#ifdef LOG_TO_FILE
if (LOG_FILE == NULL)
LOG_FILE = CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
LOG_FILE =
CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
#endif
}

View File

@ -3,11 +3,14 @@
#include <Windows.h>
#include <stdio.h>
#define LOG_MISC FALSE
#define LOG_INFO TRUE
#define LOG_WARNING TRUE
#define LOG_ERROR TRUE
#define LOG_GAME TRUE
#define LOG_GAME 1
#define LOG_ERROR 2
#define LOG_WARNING 3
#define LOG_INFO 4
#define LOG_MISC 5
#define LOG_TRACE 6
#define LOG_LEVEL LOG_TRACE
// #define LOG_TO_FILE
@ -17,12 +20,14 @@
extern CRITICAL_SECTION logger_lock;
int log_trace(const char* caller, const char* format, ...);
int log_misc(const char* caller, const char* format, ...);
int log_info(const char* caller, const char* format, ...);
int log_warning(const char* caller, const char* format, ...);
int log_error(const char* caller, const char* format, ...);
int log_game(const char* caller, const char* format, ...);
int vlog_trace(const char* caller, const char* format, va_list args);
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);

View File

@ -0,0 +1,46 @@
#define W83627UHG_REG_SYSFANOUT_FREQUENCY 0x00
#define W83627UHG_REG_SYSFANOUT_VALUE_SELECT 0x01
#define W83627UHG_REG_CPUFANOUT_FREQUENCY 0x02
#define W83627UHG_REG_CPUFANOUT_VALUE_SELECT 0x03
#define W83627UHG_REG_FAN_CONF 0x04
#define W83627UHG_REG_SYSTIN_TARGET_TEMP 0x05
#define W83627UHG_REG_CPUTIN_TARGET_TEMP 0x06
#define W83627UHG_REG_TARGET_TEMP_TOLERANCE 0x07
#define W83627UHG_REG_SYSFANOUT_STOP_VALUE 0x08
#define W83627UHG_REG_CPUFANOUT_STOP_VALUE 0x09
#define W83627UHG_REG_SYSFANOUT_START_VALUE 0x0a
#define W83627UHG_REG_CPUFANOUT_START_VALUE 0x0b
#define W83627UHG_REG_SYSFANOUT_STOP_TIME 0x0c
#define W83627UHG_REG_CPUFANOUT_STOP_TIME 0x0d
#define W83627UHG_REG_FANOUT_STEPDOWN_TIME 0x0e
#define W83627UHG_REG_FANOUT_STEPUP_TIME 0x0f
#define W83627UHG_REG_FAN_CONF_2 0x12
#define W83627UHG_REG_OVT_CONF 0x18
#define W83627UHG_REG_CONFIG 0x40
#define W83627UHG_REG_ISR_1 0x41
#define W83627UHG_REG_ISR_2 0x42
#define W83627UHG_REG_SMI_MASK_1 0x43
#define W83627UHG_REG_SMI_MASK_2 0x44
#define W83627UHG_REG_SMI_MASK_3 0x46
#define W83627UHG_REG_FAN_DIVISOR 0x47
#define W83627UHG_REG_SERIAL_BUS_ADDR 0x48
#define W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT 0x49
#define W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT 0x4a
#define W83627UHG_REG_FAN_DIVISOR_2 0x4b
#define W83627UHG_REG_SMI_OVT_CTRL 0x4c
#define W83627UHG_REG_FAN_IN_OUT_CTRL 0x4d
#define W83627UHG_REG_WINBOND_ID 0x4f
#define W83627UHG_REG_BEEP_CTRL_1 0x56
#define W83627UHG_REG_BEEP_CTRL_2 0x57
#define W83627UHG_REG_CHIP_ID 0x58
#define W83627UHG_REG_DIODE_SELECT_REG 0x59
#define W83627UHG_REG_VBAT_MON_CTRL 0x5d
#define W83627UHG_REG_CRIT_TEMP_EN 0x5e
#define W83627UHG_REG_CPUFANOUT_MAX_OUT 0x67
#define W83627UHG_REG_CPUFANOUT_OUT_STEP 0x68
#define W83627UHG_REG_SYSFANOUT_CRIT_TEMP 0x6b
#define W83627UHG_REG_CPUFANOUT_CRIT_TEMP 0x6c

View File

@ -8,14 +8,21 @@ const char* VERSION = "0.0-pre";
bool boot_delay = false;
bool gametest = false;
bool designviewer = false;
bool spriteviewer = false;
bool noisetest = false;
char exe_name[MAX_PATH + 1] = "";
char commandline[MAX_PATH + 1] = "";
void print_help(char* exe) {
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");
fprintf(stderr, " -t: Start the game in test mode\n");
fprintf(stderr, " -dv: Start the game in design viewer mode\n");
fprintf(stderr, " -sv: Start the game in sprite viewer mode\n");
fprintf(stderr, " -nt: Start the game in noisetest mode\n");
exit(0);
}
@ -27,10 +34,21 @@ void parse_cmdline(int argc, char* argv[]) {
if (i + 1 == argc) print_help(argv[0]);
char* val = argv[++i];
memcpy(exe_name, val, strlen(val) + 1);
} else if (strcmp(argv[i], "-d") == 0) {
} else if (strcmp(argv[i], "--mice-d") == 0) {
boot_delay = true;
} else if (strcmp(argv[i], "-t") == 0) {
gametest = true;
} else if (strcmp(argv[i], "-dv") == 0) {
designviewer = true;
} else if (strcmp(argv[i], "-sv") == 0) {
spriteviewer = true;
} else if (strcmp(argv[i], "-nt") == 0) {
noisetest = true;
} else {
if (commandline[0] == 0)
strncpy_s(commandline, strlen(argv[i]), argv[i], sizeof commandline);
else
snprintf(commandline, sizeof commandline, "%s %s", commandline, argv[i]);
}
}
}
@ -53,7 +71,16 @@ int main(int argc, char* argv[]) {
}
}
char* cmdline = gametest ? ". gametest" : "";
char* cmdline_mode = gametest ? ". gametest"
: designviewer ? ". designviewer"
: spriteviewer ? ". spriteviewer"
: noisetest ? ". noisetest"
: "";
char cmdline[MAX_PATH + 1];
if (commandline[0] == 0)
snprintf(cmdline, sizeof cmdline, "%s", cmdline_mode);
else
snprintf(cmdline, sizeof cmdline, "%s %s", cmdline_mode, commandline);
fprintf(stderr, "exec: %s %s\n", exe_name, cmdline);
char micepath[MAX_PATH + 1];

View File

@ -0,0 +1,88 @@
#include "amEeprom.h"
#include "../mice/crc.h"
HANDLE amEepromCreateDeviceFile(const GUID *guid, LPCSTR resource, DWORD member_index) {
SP_DEVICE_INTERFACE_DATA interface_data;
SP_DEVICE_INTERFACE_DETAIL_DATA_A interface_detail[204];
if (!guid) return INVALID_HANDLE_VALUE;
HDEVINFO DeviceInfoSet =
SetupDiGetClassDevsA(guid, NULL, NULL, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT);
if (DeviceInfoSet == INVALID_HANDLE_VALUE) return INVALID_HANDLE_VALUE;
interface_data.cbSize = 0x1c;
BOOL s;
s = SetupDiEnumDeviceInterfaces(DeviceInfoSet, NULL, guid, member_index, &interface_data);
if (!s) goto fail;
interface_detail[0].cbSize = 5;
s = SetupDiGetDeviceInterfaceDetailA(DeviceInfoSet, &interface_data, interface_detail,
sizeof interface_detail, NULL, NULL);
if (!s) goto fail;
char device_path[260];
strcpy_s(device_path, sizeof device_path, interface_detail[0].DevicePath);
if (resource != NULL) {
strcat_s(device_path, 4, "\\");
strcat_s(device_path, 4, resource);
}
printf("Using device located at %s\n", device_path);
HANDLE device =
CreateFileA(device_path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_SUPPORTS_GHOSTING, NULL);
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return device;
fail:
SetupDiDestroyDeviceInfoList(DeviceInfoSet);
return INVALID_HANDLE_VALUE;
}
BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
mxsmbus_request_packet smbus_req = {
.status = 0,
.prt = 0x09,
.addr = SMBUS_EEPROM,
.reg = reg << 5,
.dlen = len,
.data = { 0 },
};
DWORD _dummy;
BOOL s = DeviceIoControl(mxsmbus, (DWORD)IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req,
&smbus_req, sizeof smbus_req, &_dummy, NULL);
if (!s) return FALSE;
if (smbus_req.status) return FALSE;
memcpy(data, smbus_req.data, len);
return TRUE;
}
BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data) {
mxsmbus_request_packet smbus_req = {
.status = 0,
.prt = 0x08,
.addr = SMBUS_EEPROM,
.reg = reg << 5,
.dlen = len,
.data = { 0 },
};
memcpy(smbus_req.data, data, sizeof smbus_req.data);
DWORD _dummy;
BOOL s = DeviceIoControl(mxsmbus, (DWORD)IOCTL_MXSMBUS_I2C, &smbus_req, sizeof smbus_req,
&smbus_req, sizeof smbus_req, &_dummy, NULL);
if (!s) return FALSE;
if (smbus_req.status) return FALSE;
memcpy(data, smbus_req.data, len);
return TRUE;
}
void amEepromRepairChecksum(BYTE *data) {
crc32_build_table();
DWORD check = crc32(28, data + 4, 0);
((DWORD*)data)[0] = check;
}

View File

@ -0,0 +1,13 @@
#include <Windows.h>
#include "../../dll/smbus.h"
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);
HANDLE amEepromCreateDeviceFile(const GUID *guid, LPCSTR resource, DWORD member_index);
BOOL amEepromReadBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data);
BOOL amEepromWriteBlock(HANDLE mxsmbus, BYTE reg, BYTE len, BYTE *data);
void amEepromRepairChecksum(BYTE* data);

View File

@ -1,4 +1,4 @@
#include <amtimer.h>
#include <amTimer.h>
int frequency_loaded = 0;
LARGE_INTEGER frequency;
@ -13,7 +13,7 @@ amtime_t* amiTimerGet(amtime_t* time) {
frequency_loaded = 1;
}
QueryPerformanceCounter(&counter);
time->microseconds = (counter.QuadPart * 1000000) / frequency.QuadPart;
time->seconds = counter.QuadPart / frequency.QuadPart;
time->microseconds = (unsigned int)((counter.QuadPart * 1000000) / frequency.QuadPart);
time->seconds = (unsigned int)(counter.QuadPart / frequency.QuadPart);
return time;
}

View File

@ -1,6 +1,10 @@
amlib = static_library(
'am',
sources: [
'amtimer.c',
'amTimer.c',
'amEeprom.c',
],
link_with: [
mice_lib
],
)

View File

@ -4,29 +4,32 @@
LPBYTE dmi_table = NULL;
WORD dmi_size = 0;
size_t _dmi_max = 0;
WORD _dmi_max = 0;
DMI_BIOS deafult_dmi_bios = {
.Head.Type = 0x00,
.Head.Length = 0x12,
.Head.Handle = 0x0000,
.Vendor = 0x00,
.Version = 0x00,
.StartSegment = 0x0000,
.ReleaseDate = 0x00,
.ROMSize = 0x00,
.Chars = 0x04,
.Vendor = 0x01, // "American Megatrends Inc."
.Version = 0x02, // "080015 "
.StartSegment = 0x0000, // '00 f0'h
.ReleaseDate = 0x03, // "07/28/2011"
.ROMSize = 0x00, // 03h
.Chars = 0x1f, // '1F 90 DA 8B'h
.VerMajor = 0x08,
.VerMinor = 0x0f,
.ECVerMajor = 0xff,
.ECVerMinor = 0xff,
};
DMI_SYSTEM default_dmi_system = {
.Head.Type = 0x01,
.Head.Length = 0x08,
.Head.Handle = 0x0001,
// TODO: Are these used?
.Manufacturer = 0x00,
.ProductName = 0x00,
.Version = 0x00,
.Serial = 0x00,
.Manufacturer = 0x01, // "NEC"
.ProductName = 0x02, // "To Be Filled By O.E.M."
.Version = 0x03, // "To Be Filled By O.E.M."
.Serial = 0x04, // "To Be Filled By O.E.M."
};
DMI_STRING deafult_dmi_string = {
@ -44,7 +47,7 @@ static void dmi_init(void) {
dmi_size = 0;
}
static void dmi_append(void* data, size_t size) {
static void dmi_append(void* data, WORD size) {
if (!dmi_table) return;
while (dmi_size + (size + 1) >= _dmi_max) {
LPBYTE new_table = (LPBYTE)realloc(dmi_table, _dmi_max += 0xff);
@ -57,7 +60,7 @@ static void dmi_append(void* data, size_t size) {
dmi_table[dmi_size++] = 0;
}
static void dmi_append_with_strings(void* data, size_t size, int num_strings, ...) {
static void dmi_append_with_strings(void* data, WORD size, int num_strings, ...) {
va_list args;
va_start(args, num_strings);
@ -65,7 +68,7 @@ static void dmi_append_with_strings(void* data, size_t size, int num_strings, ..
dmi_size -= 2;
for (int i = 0; i < num_strings; i++) {
char* str = va_arg(args, char*);
int len = strlen(str);
WORD len = strlen(str) & 0xffff;
memcpy((char*)dmi_table + dmi_size, str, len + 1);
dmi_size += len + 1;
dmi_table[dmi_size - 1] = 0;
@ -77,13 +80,16 @@ static void dmi_append_with_strings(void* data, size_t size, int num_strings, ..
void dmi_build_default() {
dmi_init();
dmi_append(&deafult_dmi_bios, sizeof deafult_dmi_bios);
dmi_append_with_strings(&deafult_dmi_bios, sizeof deafult_dmi_bios, 3,
"American Megatrends Inc.", "080015 ", "07/28/2011");
// Platform AAM: Board type one of "Supermicro"(=1) or "Advantech"(=2)
// Platform AAL: Board type one of "NEC"(=0) or "AAL2"(=3)
dmi_append_with_strings(&default_dmi_system, sizeof default_dmi_system, 4, "NEC",
"To Be Filled By O.E.M.", "To Be Filled By O.E.M.",
"To Be Filled By O.E.M.");
dmi_append_with_strings(&default_dmi_system, sizeof default_dmi_system, 1, "Supermicro");
deafult_dmi_string.NoStrings = 3;
deafult_dmi_string.NoStrings = 5;
dmi_append_with_strings(&deafult_dmi_string, sizeof deafult_dmi_string,
// OEM strings:
@ -100,7 +106,8 @@ void dmi_build_default() {
// AAM = 4
// Supermicro = 4
// Advantech = 4
5, ".", ".", "AAM", ".", "AAL");
// These values are pulled from an 846-5004D
5, "DAC-BJ02", "DAC-BJ02", "AAL", "Advantech", "AAL2");
}
BYTE dmi_calc_checksum(const char* buf, int len) {

View File

@ -33,6 +33,10 @@ typedef struct {
BYTE ReleaseDate;
BYTE ROMSize;
uint64_t Chars;
BYTE VerMajor;
BYTE VerMinor;
BYTE ECVerMajor;
BYTE ECVerMinor;
} DMI_BIOS;
#pragma pack(1)
@ -51,8 +55,8 @@ typedef struct {
} DMI_STRING;
static void dmi_init(void);
static void dmi_append(void* data, size_t size);
static void dmi_append_with_strings(void* data, size_t size, int num_strings, ...);
static void dmi_append(void* data, WORD size);
static void dmi_append_with_strings(void* data, WORD size, int num_strings, ...);
void dmi_build_default(void);
BYTE dmi_calc_checksum(const char* buf, int len);

View File

@ -43,7 +43,7 @@
typedef unsigned int json_uchar;
const struct _json_value json_value_none;
const struct _json_value json_value_none = { 0 };
static int would_overflow(json_int_t value, json_char b) { return ((JSON_INT_MAX - (b - '0')) / 10) < value; }
@ -263,8 +263,8 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
if (state.first_pass)
string_length += 2;
else {
string[string_length++] = 0xC0 | (uchar >> 6);
string[string_length++] = 0x80 | (uchar & 0x3F);
string[string_length++] = (char)(0xC0 | (uchar >> 6));
string[string_length++] = (char)(0x80 | (uchar & 0x3F));
}
break;
@ -274,9 +274,9 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
if (state.first_pass)
string_length += 3;
else {
string[string_length++] = 0xE0 | (uchar >> 12);
string[string_length++] = 0x80 | ((uchar >> 6) & 0x3F);
string[string_length++] = 0x80 | (uchar & 0x3F);
string[string_length++] = 0xE0 | (char)((uchar >> 12));
string[string_length++] = 0x80 | (char)(((uchar >> 6) & 0x3F));
string[string_length++] = 0x80 | (char)((uchar & 0x3F));
}
break;
@ -285,10 +285,10 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
if (state.first_pass)
string_length += 4;
else {
string[string_length++] = 0xF0 | (uchar >> 18);
string[string_length++] = 0x80 | ((uchar >> 12) & 0x3F);
string[string_length++] = 0x80 | ((uchar >> 6) & 0x3F);
string[string_length++] = 0x80 | (uchar & 0x3F);
string[string_length++] = 0xF0 | (char)((uchar >> 18));
string[string_length++] = 0x80 | (char)(((uchar >> 12) & 0x3F));
string[string_length++] = 0x80 | (char)(((uchar >> 6) & 0x3F));
string[string_length++] = 0x80 | (char)((uchar & 0x3F));
}
break;

View File

@ -0,0 +1 @@
#include "libpcp.h"

View File

@ -0,0 +1,3 @@
#include "pcp.h"
char* LIBPCP_VERSION = "\nlibpcp Ver.1.08 Build:Aug 12 2012 00:13:32 (micetools bootleg)\n";

View File

@ -5,6 +5,7 @@
#define ZERO_BUF(x) memset((x), 0, sizeof(*x))
#include <Winsock2.h>
#include <ws2ipdef.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@ -29,7 +30,7 @@ typedef unsigned char byte;
typedef unsigned short ushort;
typedef unsigned int uint;
typedef int timeout_t;
typedef unsigned int timeout_t;
#define PCP_BUF_MAX 256
#define PCP_CMDS_MAX 64
@ -43,7 +44,7 @@ typedef struct pcp_parse_data {
uint cmd_count;
} pcp_parse_data_t;
typedef struct pcp_send_data {
char data[PCP_BUF_MAX];
unsigned char data[PCP_BUF_MAX];
size_t length;
} pcp_send_data_t;
@ -63,8 +64,9 @@ typedef enum binary_mode {
#define PCPT_SO_LINGER 2
#define PCPT_TCP_NODELAY 3
#define SOCKET_INVAL ((SOCKET)-1)
#define HANDLE_INVAL -1
#define TIMEOUT_NONE -1
#define TIMEOUT_NONE ((DWORD)-1)
#define PCPT_CLOSED 0
#define PCPT_LISTENING 1

View File

@ -0,0 +1,630 @@
#include "pcpa.h"
e_pcpa_t _pcpaGetErrorFromPcpp(e_pcpp_t err) {
switch (err) {
case e_pcpp_ok:
return e_pcpa_ok;
case e_pcpp_to:
return e_pcpa_to;
case e_pcpp_closed:
return e_pcpa_closed;
case e_pcpp_no_client:
return e_pcpa_no_client;
case e_pcpp_wsa_noinit:
return e_pcpa_wsa_noinit;
case e_pcpp_inval_addr:
return e_pcpa_inval_addr;
case -14:
return (e_pcpa_t)-16;
case -13:
return (e_pcpa_t)-15;
case e_pcpp_timeout_open:
return e_pcpa_timeout_open;
case -11:
return (e_pcpa_t)-13;
case e_pcpp_recv_unset:
return e_pcpa_cb_table_full;
case -9:
return (e_pcpa_t)-7;
case -8:
return (e_pcpa_t)-6;
case -7:
return (e_pcpa_t)-3;
case e_pcpp_timeout_closed:
return e_pcpa_timeout_closed;
case e_pcpp_param_invalid:
return e_pcpa_param_invalid;
case -4:
return (e_pcpa_t)-8;
case e_pcpp_already_open:
return e_pcpa_already_open;
case e_pcpp_cannot_open:
return e_pcpa_cannot_open;
case e_pcpp_not_open:
return e_pcpa_not_open;
default:
return e_pcpa_closed;
}
}
void pcpaCloseBinary(pcpa_t *stream) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn't set\n");
return;
}
stream->binary_mode = binary_mode_none;
pcppCloseBinary(&stream->pcpp);
}
void pcpaClose(pcpa_t *stream) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return;
}
pcppClose(&stream->pcpp);
stream->err = e_pcpa_unknown;
stream->state = 0;
stream->callback_table = NULL;
stream->callback_max = 0;
stream->callback_count = 0;
stream->recv_buffer = NULL;
stream->recv_buffer_len = 0;
stream->send_buffer = NULL;
stream->send_buffer_len = 0;
stream->binary_mode = binary_mode_none;
stream->binary_mode_before_cb = NULL;
stream->binary_mode_after_cb = NULL;
stream->binary_mode_before_data = NULL;
stream->binary_mode_after_data = NULL;
memset(&stream->send_data, 0, sizeof stream->send_data);
(stream->send_data).length = 0;
}
e_pcpa_t pcpaInitStream(pcpa_t *stream) {
if (LIBPCP_VERSION == NULL) {
PCP_LOG("error PCPA version isn\'t set\n");
return e_pcpa_generic;
}
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
e_pcpp_t err = pcppInitStream(&stream->pcpp);
if (err != e_pcpp_ok) {
return err == e_pcpp_wsa_noinit ? e_pcpa_wsa_noinit : e_pcpa_param_invalid;
}
stream->err = e_pcpa_unknown;
stream->state = 0;
stream->callback_table = NULL;
stream->callback_max = 0;
stream->callback_count = 0;
stream->recv_buffer = NULL;
stream->recv_buffer_len = 0;
stream->send_buffer = NULL;
stream->send_buffer_len = 0;
stream->binary_mode = binary_mode_none;
stream->binary_mode_before_cb = NULL;
stream->binary_mode_after_cb = NULL;
stream->binary_mode_before_data = NULL;
stream->binary_mode_after_data = NULL;
ZERO(stream->recv_data);
ZERO(stream->send_data);
return e_pcpa_ok;
}
e_pcpa_t pcpaOpenServerWithBinary(pcpa_t *stream, int open_mode, u_short port, u_short binary_port,
undefined4 param_5) {
e_pcpa_t err;
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
switch (open_mode) {
case 0:
stream->err = err = _errP2A(pcppOpenServer(&stream->pcpp, 0, port, param_5));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenServer\n");
return err;
}
stream->err = err = _errP2A(pcppOpenBinaryServer(&stream->pcpp, 0, binary_port));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenBinaryServer\n");
return err;
}
break;
case 1:
stream->err = err = _errP2A(pcppOpenServer(&stream->pcpp, 1, port, param_5));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenServer\n");
return err;
}
stream->err = err = _errP2A(pcppOpenBinaryServer(&stream->pcpp, 1, binary_port));
if (err != e_pcpa_ok) {
PCP_LOG("error pcppOpenBinaryServer\n");
return err;
}
break;
default:
PCP_LOG("error Open Mode isn\'t set\n");
return stream->err = e_pcpa_generic;
}
stream->state = 0;
return e_pcpa_ok;
}
e_pcpa_t pcpaSetCallbackFunc(pcpa_t *stream, char *keyword, pcpa_callback *callback, void *data) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
if (keyword == NULL) {
PCP_LOG("error keyword isn\'t set\n");
return e_pcpa_generic;
}
if (callback == NULL) {
PCP_LOG("error Callback func isn\'t set\n");
return e_pcpa_generic;
}
if (stream->callback_table == NULL) {
PCP_LOG("error Callback_table buffer isn\'t set\n");
return e_pcpa_cb_table_unset;
}
if (strnlen(keyword, PCP_KEYWORD_MAX + 1) > PCP_KEYWORD_MAX) {
PCP_LOG("error a keyword is too long\n");
return e_pcpa_generic;
}
if (stream->callback_count >= stream->callback_max) return e_pcpa_cb_table_full;
sprintf_s(stream->callback_table[stream->callback_count].keyword, PCP_KEYWORD_MAX, "%s", keyword);
stream->callback_table[stream->callback_count].callback = callback;
stream->callback_table[stream->callback_count].data = data;
stream->callback_count++;
return stream->err = e_pcpa_ok;
}
e_pcpa_t pcpaSetCallbackFuncBuffer(pcpa_t *stream, pcpa_cb_table_t *callback_table, uint callbacks_max) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
if (callback_table == NULL || callbacks_max == 0) return e_pcpa_timeout_closed;
stream->callback_max = callbacks_max;
stream->callback_table = callback_table;
stream->callback_count = 0;
stream->err = e_pcpa_ok;
return e_pcpa_ok;
}
pcp_send_data_t *pcpaSetSendPacket(pcpa_t *stream, char *keyword, char *value) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return NULL;
}
return pcppSetSendPacket(&stream->send_data, keyword, value);
}
char *pcpaGetCommand(pcpa_t *pcpa, char *command) {
if (pcpa == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return NULL;
}
return pcppGetCommand(&pcpa->recv_data, command);
}
e_pcpa_t pcpaServer(pcpa_t *stream, timeout_t timeout_ms) {
byte bVar1;
pcpa_callback *callback;
char *pbVar3;
int iVar3;
e_pcpa_t eVar4;
char *pbVar4;
uint ms;
e_pcpp_t iVar5;
bool bVar6;
uint local_14;
amtime_t time;
amtime_t time_start;
int timeout;
local_14 = timeout_ms;
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
amiTimerGet(&time_start);
timeout = timeout_ms;
do {
ms = 0;
switch (stream->state) {
case 0:
amiTimerGet(&time);
ms = _amTimeDelta(time, time_start);
if (timeout_ms != -1) {
if (ms < (uint)timeout_ms) {
timeout = timeout_ms - ms;
local_14 = timeout;
} else {
timeout = 0;
local_14 = timeout;
}
}
stream->state = 3;
iVar5 = pcppRecvRequest(&stream->pcpp, &stream->recv_data, timeout);
eVar4 = _errP2A(iVar5);
stream->err = eVar4;
timeout = local_14;
if (eVar4 != e_pcpa_to) {
if (eVar4 == e_pcpa_ok) {
stream->state = 10;
amiTimerGet(&time);
if (timeout_ms != -1) {
ms = _amTimeDelta(time, time_start);
goto joined_r0x00454a58;
}
} else {
stream->state = 0;
}
}
break;
default:
stream->err = e_pcpa_unknown;
goto LAB_00454d84;
case 3:
case 4:
case 9:
amiTimerGet(&time);
ms = _amTimeDelta(time, time_start);
if (timeout_ms != -1) {
if (ms < (uint)timeout_ms) {
timeout = timeout_ms - ms;
local_14 = timeout;
} else {
timeout = 0;
local_14 = timeout;
}
}
iVar5 = pcppIsBusy(&stream->pcpp, timeout);
eVar4 = _errP2A(iVar5);
stream->err = eVar4;
timeout = local_14;
if (eVar4 != e_pcpa_to) {
if (stream->state == 4) {
memset(&stream->send_data, 0, PCP_BUF_MAX);
(stream->send_data).length = 0;
}
if (stream->err == e_pcpa_ok) {
if (stream->binary_mode == binary_mode_none) {
stream->state = (stream->state != 3) - 1 & 10;
amiTimerGet(&time);
if (timeout_ms != -1) {
ms = _amTimeDelta(time, time_start);
joined_r0x00454a58:
if ((uint)timeout_ms <= ms) {
stream->err = e_pcpa_to;
return stream->err;
}
}
} else {
pcpaCloseBinary(stream);
stream->state = 0;
stream->binary_mode = binary_mode_none;
if (stream->binary_mode_after_cb != NULL) {
(*stream->binary_mode_after_cb)(stream, stream->binary_mode_after_data);
stream->binary_mode_after_cb = NULL;
}
amiTimerGet(&time);
if (timeout_ms != -1) {
ms = _amTimeDelta(time, time_start);
goto joined_r0x00454a58;
}
}
} else {
if ((stream->state == 9) && (stream->binary_mode != binary_mode_none)) {
pcpaCloseBinary(stream);
if (stream->binary_mode_after_cb != NULL) {
(*stream->binary_mode_after_cb)(stream, stream->binary_mode_after_data);
stream->binary_mode_after_cb = NULL;
}
stream->binary_mode = binary_mode_none;
}
stream->state = 0;
}
}
break;
case 7:
callback = stream->binary_mode_before_cb;
(stream->pcpp).last_active = _amTimeMs(time_start);
if (callback != NULL) {
(*callback)(stream, stream->binary_mode_before_data);
stream->binary_mode_before_cb = NULL;
}
amiTimerGet(&time);
ms = _amTimeDelta(time, time_start);
if (timeout_ms != -1) {
if (ms < (uint)timeout_ms) {
timeout = timeout_ms - ms;
local_14 = timeout;
} else {
timeout = 0;
local_14 = timeout;
}
}
eVar4 = pcpaSendBinary(stream, timeout);
stream->err = eVar4;
if (eVar4 == e_pcpa_to) {
stream->state = 9;
} else {
pcpaCloseBinary(stream);
if (stream->binary_mode_after_cb != NULL) {
(*stream->binary_mode_after_cb)(stream, stream->binary_mode_after_data);
stream->binary_mode_after_cb = NULL;
}
stream->binary_mode = binary_mode_none;
stream->state = 0;
if (stream->err == e_pcpa_ok) {
LAB_00454a1a:
amiTimerGet(&time);
if (timeout_ms != -1) {
ms = _amTimeDelta(time, time_start);
goto joined_r0x00454a58;
}
} else {
PCP_LOG("error pcpaSendBinary\n");
}
}
break;
case 8:
callback = stream->binary_mode_before_cb;
(stream->pcpp).last_active = _amTimeMs(time_start);
if (callback != NULL) {
(*callback)(stream, stream->binary_mode_before_data);
stream->binary_mode_before_cb = NULL;
}
amiTimerGet(&time);
ms = _amTimeDelta(time, time_start);
if (timeout_ms != -1) {
if (ms < (uint)timeout_ms) {
timeout = timeout_ms - ms;
local_14 = timeout;
} else {
timeout = 0;
local_14 = timeout;
}
}
eVar4 = pcpaRecvBinary(stream, timeout);
stream->err = eVar4;
if (eVar4 == e_pcpa_to) {
stream->state = 9;
} else {
pcpaCloseBinary(stream);
if (stream->binary_mode_after_cb != NULL) {
(*stream->binary_mode_after_cb)(stream, stream->binary_mode_after_data);
stream->binary_mode_after_cb = NULL;
}
stream->binary_mode = binary_mode_none;
stream->state = 0;
if (stream->err == e_pcpa_ok) goto LAB_00454a1a;
PCP_LOG("error pcpaRecvBinary\n");
}
break;
case 10:
if (stream->before_cb != NULL) {
stream->before_cb(stream, stream->pcpp.sock.recv_buf);
}
if (stream->callback_table == NULL) {
PCP_LOG("error Callback_table buffer isn\'t set\n");
stream->err = e_pcpa_cb_table_unset;
return stream->err;
}
if (stream->callback_count != 0) {
iVar5 = 0;
do {
pbVar3 = pcppGetKeyword(&stream->recv_data, 0);
pbVar4 = stream->callback_table->keyword + iVar5;
do {
bVar1 = *pbVar3;
bVar6 = bVar1 < (byte)*pbVar4;
if (bVar1 != *pbVar4) {
LAB_004547c8:
iVar3 = (1 - (uint)bVar6) - (uint)(bVar6 != 0);
goto LAB_004547cd;
}
if (bVar1 == 0) break;
bVar1 = ((byte *)pbVar3)[1];
bVar6 = bVar1 < ((byte *)pbVar4)[1];
if (bVar1 != ((byte *)pbVar4)[1]) goto LAB_004547c8;
pbVar3 = (char *)((byte *)pbVar3 + 2);
pbVar4 = (char *)((byte *)pbVar4 + 2);
} while (bVar1 != 0);
iVar3 = 0;
LAB_004547cd:
if (iVar3 == 0) {
(stream->callback_table[ms].callback)(stream, stream->callback_table[ms].data);
goto LAB_004547f1;
}
ms = ms + 1;
iVar5 = iVar5 + 40;
} while (ms < stream->callback_count);
}
pcppSetSendPacket(&stream->send_data, "?", 0);
LAB_004547f1:
amiTimerGet(&time);
ms = _amTimeDelta(time, time_start);
if (timeout_ms != -1) {
if (ms < (uint)timeout_ms) {
local_14 = timeout_ms - ms;
} else {
local_14 = 0;
}
}
iVar5 = pcppSendResponseTable(&stream->pcpp, &stream->send_data, local_14);
eVar4 = _errP2A(iVar5);
stream->err = eVar4;
if (eVar4 == e_pcpa_to) {
stream->state = 4;
} else {
memset(&stream->send_data, 0, PCP_BUF_MAX);
(stream->send_data).length = 0;
stream->state = 0;
}
if (stream->binary_mode != binary_mode_none) {
stream->state = (stream->binary_mode == binary_mode_send) ? 7 : 8;
}
amiTimerGet(&time);
timeout = local_14;
if (timeout_ms != TIMEOUT_NONE) {
ms = _amTimeDelta(time, time_start);
goto joined_r0x00454a58;
}
}
} while (stream->err == e_pcpa_ok);
LAB_00454d84:
return stream->err;
}
e_pcpa_t pcpaRecvBinary(pcpa_t *stream, uint something) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
if (stream->recv_buffer == NULL) {
PCP_LOG("error Recv buffer isn\'t set\n");
pcpaCloseBinary(stream);
pcpaClose(stream);
return stream->err = e_pcpa_cb_table_full;
}
stream->state = 8;
e_pcpa_t err;
stream->err = err = _errP2A(pcppRecvBinary(&stream->pcpp, stream->recv_buffer, stream->recv_buffer_len, something));
if (err != e_pcpa_to) stream->state = 0;
return err;
}
e_pcpa_t pcpaSendBinary(pcpa_t *stream, uint param_2) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
if (stream->send_buffer == NULL) {
PCP_LOG("error Send buffer isn\'t set\n");
stream->err = e_pcpa_cb_table_full;
pcpaCloseBinary(stream);
pcpaClose(stream);
return stream->err;
}
stream->state = 7;
e_pcpa_t err;
stream->err = err = _errP2A(pcppSendBinary(&stream->pcpp, stream->send_buffer, stream->send_buffer_len, param_2));
if (err != e_pcpa_to) stream->state = 0;
return err;
}
e_pcpa_t pcpaSetSendBinaryBuffer(pcpa_t *stream, byte *send_buffer, size_t len) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
if (send_buffer == NULL) {
PCP_LOG("error Send Buffer isn\'t set\n");
return e_pcpa_timeout_closed;
}
stream->send_buffer = send_buffer;
stream->send_buffer_len = len;
stream->err = e_pcpa_ok;
return e_pcpa_ok;
}
e_pcpa_t pcpaSetBeforeBinaryModeCallBackFunc(pcpa_t *stream, pcpa_callback *callback, void *data) {
if (stream == NULL) {
PCP_LOG("error don\'t set stream\n");
return e_pcpa_stream_unset;
}
if (callback == NULL) {
PCP_LOG("error Binary mode callback func isn\'t set\n");
return e_pcpa_generic;
}
stream->binary_mode_before_cb = callback;
stream->binary_mode_before_data = data;
stream->err = e_pcpa_ok;
return e_pcpa_ok;
}
e_pcpa_t pcpaSetAfterBinaryModeCallBackFunc(pcpa_t *stream, pcpa_callback *callback, void *data) {
if (stream == NULL) {
PCP_LOG("error don\'t set stream\n");
return e_pcpa_stream_unset;
}
if (callback == NULL) {
PCP_LOG("error Binary mode callback func isn\'t set\n");
return e_pcpa_generic;
}
stream->binary_mode_after_cb = callback;
stream->binary_mode_after_data = data;
stream->err = e_pcpa_ok;
return e_pcpa_ok;
}
e_pcpa_t pcpaSetBinaryMode(pcpa_t *stream, binary_mode_t binary_mode) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
if (pcppGetServerSocket(&stream->pcpp, 1) == HANDLE_INVAL) {
return stream->err = -19;
}
stream->binary_mode = binary_mode;
stream->err = e_pcpa_ok;
return e_pcpa_ok;
}
e_pcpa_t pcpaSetRecvBinaryBuffer(pcpa_t *stream, byte *recv_buffer, size_t len) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return e_pcpa_stream_unset;
}
if (recv_buffer == NULL) {
PCP_LOG("error Recv Buffer isn\'t set\n");
return e_pcpa_timeout_closed;
}
stream->recv_buffer = recv_buffer;
stream->recv_buffer_len = len;
stream->err = e_pcpa_ok;
return e_pcpa_ok;
}
pcp_send_data_t *pcpaAddSendPacket(pcpa_t *stream, char *keyword, char *value) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return NULL;
}
return pcppAddSendPacket(&stream->send_data, keyword, value);
}
char *pcpaGetKeyword(pcpa_t *stream, uint keyword_num) {
if (stream == NULL) {
PCP_LOG("error PCPA stream isn\'t set\n");
return NULL;
}
return pcppGetKeyword(&stream->recv_data, keyword_num);
}

View File

@ -39,9 +39,9 @@ typedef struct pcpa {
pcpa_cb_table_t* callback_table;
uint callback_max;
uint callback_count;
char* recv_buffer;
unsigned char* recv_buffer;
size_t recv_buffer_len;
char* send_buffer;
unsigned char* send_buffer;
size_t send_buffer_len;
binary_mode_t binary_mode;
pcpa_callback* binary_mode_before_cb;

File diff suppressed because it is too large Load Diff

View File

@ -19,6 +19,14 @@ typedef enum e_pcpp {
e_pcpp_inval_addr = -15,
e_pcpp_wsa_noinit = -16,
e_pcpp_unknown = -17,
e_pcpp_uk1 = -14,
e_pcpp_uk2 = -13,
e_pcpp_uk3 = -11,
e_pcpp_uk4 = -9,
e_pcpp_uk5 = -8,
e_pcpp_uk6 = -7,
e_pcpp_uk7 = -4,
} e_pcpp_t;
e_pcpp_t _pcppGetErrorFromPcpt(e_pcpt_t err);
@ -32,17 +40,17 @@ typedef struct pcpp {
uint state;
e_pcpp_t err;
pcp_parse_data_t* recv_data_buffer;
char read_bytes_buf[PCP_BUF_MAX];
unsigned char read_bytes_buf[PCP_BUF_MAX];
uint read_bytes_size;
uint read_bytes_num;
pcp_send_data_t* resp_buffer;
uint resp_buffer_len;
char send_buf[PCP_SEND_BUF_MAX];
unsigned char send_buf[PCP_SEND_BUF_MAX];
size_t send_buf_len;
uint field_0x1e8;
char* send_binary_buf;
unsigned char* send_binary_buf;
uint field_0x1f0;
char* recv_binary_buf;
unsigned char* recv_binary_buf;
size_t field_0x1f8;
uint field_0x1fc;
size_t recv_binary_buf_len;
@ -56,13 +64,13 @@ typedef struct pcpp {
} pcpp_t;
pcp_send_data_t* pcppAddSendPacket(pcp_send_data_t* stream, char* key, char* value);
pcp_parse_data_t* pcppChangeRequest(pcpp_t* stream, int* lenout);
pcp_parse_data_t* pcppChangeRequest(pcpp_t* stream, uint* lenout);
bool pcppCheckPrompt(pcpp_t* stream);
e_pcpp_t pcppCheckRecvMsg(char* recv_data, size_t buf_len, int param_3);
uint pcppCheckStr(char* param_1, uint* pcp_len, int* pcp_overflow);
e_pcpp_t pcppCheckRecvMsg(unsigned char* recv_data, size_t buf_len, int param_3);
uint pcppCheckStr(unsigned char* param_1, uint* pcp_len, int* pcp_overflow);
void pcppClose(pcpp_t* stream);
void pcppCloseBinary(pcpp_t* stream);
e_pcpp_t pcppGetBlockingTime(uint param_1, int param_2, pcpp_t* stream, int param_4, uint* blocking_time);
e_pcpp_t pcppGetBlockingTime(uint param_1, timeout_t param_2, pcpp_t* stream, int param_4, uint* blocking_time);
char* pcppGetCommand(pcp_parse_data_t* pcpa, char* command);
char* pcppGetKeyword(pcp_parse_data_t* recvData, uint keyword_num);
SOCKET pcppGetServerSocket(pcpp_t* stream, int which);
@ -71,17 +79,17 @@ e_pcpp_t pcppIsBusy(pcpp_t* stream, timeout_t timeout);
e_pcpp_t pcppOpenBinaryServer(pcpp_t* stream, int open_mode, ushort port);
e_pcpp_t pcppOpenServer(pcpp_t* stream, int open_mode, ushort port, undefined4 param_4);
e_pcpp_t pcppRecvAllMsg(uint param_1, pcpp_t* stream, bool* bReRecv);
e_pcpp_t pcppRecvBinary(pcpp_t* stream, char* recv_buf, size_t buf_len, uint param_4);
uint pcppRecvCheck(char* buf, int* found_at);
e_pcpp_t pcppRecvBinary(pcpp_t* stream, unsigned char* recv_buf, size_t buf_len, uint param_4);
uint pcppRecvCheck(unsigned char* buf, int* found_at);
e_pcpp_t pcppRecvPrompt(pcpp_t* stream, undefined4 param_2, int param_3);
e_pcpp_t pcppRecvRequest(pcpp_t* stream, pcp_parse_data_t* recv_data, timeout_t timeout);
e_pcpp_t pcppRecvRequestMain(pcpp_t* stream, bool* bReRecv, undefined4 param_3);
e_pcpp_t pcppSendBinary(pcpp_t* stream, char* send_binary_buffer, size_t param_3, uint param_4);
e_pcpp_t pcppSendPrompt(pcpp_t* stream, uint param_2, int param_3);
e_pcpp_t pcppSendRequestMain(pcpp_t* stream, undefined4 param_2, int param_3);
e_pcpp_t pcppSendBinary(pcpp_t* stream, unsigned char* send_binary_buffer, size_t param_3, uint param_4);
e_pcpp_t pcppSendPrompt(pcpp_t* stream, uint param_2, timeout_t timeout_ms);
e_pcpp_t pcppSendRequestMain(pcpp_t* stream, undefined4 param_2, timeout_t timeout_ms);
e_pcpp_t pcppSendResponse(pcpp_t* stream, pcp_send_data_t* resp_buffer, size_t buf_len, timeout_t timeout_ms);
e_pcpp_t pcppSendResponseTable(pcpp_t* stream, pcp_send_data_t* data, timeout_t timeout_ms);
pcp_send_data_t* pcppSetSendPacket(pcp_send_data_t* send_data, char* keyword, char* value);
e_pcpp_t pcpp_something(amtime_t* now, timeout_t timeout, pcpp_t* stream, pcpt_t* sock, char* send_buf,
e_pcpp_t pcpp_something(amtime_t* now, timeout_t timeout, pcpp_t* stream, pcpt_t* sock, unsigned char* send_buf,
size_t* send_len, undefined4 param_7, undefined4 param_8, e_pcpp_t fallback_err);
void pcppResetRead(pcpp_t* param_1);

View File

@ -0,0 +1,758 @@
#include "pcpt.h"
e_pcpt_t _pcptGetErrorFromWin(int err) {
switch (err) {
case WSAEBADF:
case WSAEINVAL:
case WSAENOTSOCK:
case WSAEISCONN:
return e_pcpt_wsa2_generic;
case WSAEMFILE:
return e_pcpt_cannot_open;
case WSAEWOULDBLOCK:
case WSAETIMEDOUT:
return e_pcpt_to;
case WSAEADDRNOTAVAIL:
return e_pcpt_inval_addr;
case WSAECONNABORTED:
case WSAECONNRESET:
return e_pcpt_closed;
case WSAENOBUFS:
return e_pcpt_nobufs;
case WSANOTINITIALISED:
return e_pcpt_wsa_noinit;
default:
return e_pcpt_unknown;
}
}
e_pcpt_t pcptInitStream(pcpt_t *sock) {
SOCKET s;
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
s = socket(AF_INET, SOCK_STREAM, 0);
if (s == SOCKET_INVAL) return _errW2T(WSAGetLastError());
closesocket(s);
sock->client_open = 0;
sock->open = PCPT_CLOSED;
sock->client_event = NULL;
sock->server_event = NULL;
sock->send_buf = NULL;
sock->send_buf_count = NULL;
sock->recv_buf_count = NULL;
sock->recv_buf = NULL;
sock->server_sock = SOCKET_INVAL;
sock->client_sock = SOCKET_INVAL;
sock->err = e_pcpt_unknown;
memset(&sock->client_addr, 0, sizeof sock->client_addr);
sock->field_0x58 = 0;
sock->tcp_nodelay = 0;
sock->config_0 = 12000;
sock->config_1 = 5;
sock->so_linger = 1;
return e_pcpt_ok;
}
void pcptClose(pcpt_t *sock) {
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return;
}
if (sock->server_sock != SOCKET_INVAL) {
WSAEventSelect(sock->server_sock, 0, 0);
WSACloseEvent(sock->server_event);
sock->server_event = NULL;
closesocket(sock->server_sock);
sock->server_sock = SOCKET_INVAL;
}
if (sock->client_sock != SOCKET_INVAL) {
WSAEventSelect(sock->client_sock, 0, 0);
WSACloseEvent(sock->client_event);
sock->client_event = NULL;
closesocket(sock->client_sock);
sock->client_sock = SOCKET_INVAL;
}
sock->client_open = 0;
sock->open = PCPT_CLOSED;
sock->err = e_pcpt_unknown;
if (sock->client_event != NULL) {
WSACloseEvent(sock->client_event);
sock->client_event = NULL;
}
if (sock->server_event != NULL) {
WSACloseEvent(sock->server_event);
sock->server_event = NULL;
}
sock->send_buf = NULL;
sock->send_buf_count = NULL;
sock->recv_buf_count = NULL;
sock->recv_buf = NULL;
memset(&sock->client_addr, 0, sizeof sock->client_addr);
sock->field_0x58 = 0;
}
void pcptCloseDataSock(pcpt_t *sock) {
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return;
}
if (sock->field_0x58 != 0) {
sock->open = PCPT_LISTENING;
}
sock->client_open = 0;
if (sock->client_sock != SOCKET_INVAL) {
WSAEventSelect(sock->client_sock, 0, 0);
WSACloseEvent(sock->client_event);
sock->client_event = NULL;
closesocket(sock->client_sock);
sock->client_sock = SOCKET_INVAL;
}
}
e_pcpt_t pcptAcceptServer(pcpt_t *stream, timeout_t timeout_ms) {
if (stream == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
e_pcpt_t err = pcptCheckEvent(stream->server_event, timeout_ms, stream->server_sock, FD_ACCEPT);
if (err != e_pcpt_ok) return err;
int addrlen = 16;
SOCKET client = accept(stream->server_sock, &stream->client_addr, &addrlen);
stream->client_sock = client;
if (client == SOCKET_INVAL) return _errW2T(GetLastError());
WSAEVENT event = WSACreateEvent();
stream->client_event = event;
if (event == NULL) {
closesocket(stream->client_sock);
stream->client_sock = SOCKET_INVAL;
return e_pcpt_unknown;
}
WSAEventSelect(stream->client_sock, event, FD_READ | FD_WRITE | FD_CLOSE);
uint so_linger = (uint)(!!stream->so_linger);
setsockopt(stream->client_sock, SOL_SOCKET, SO_LINGER, (void *)&so_linger, sizeof so_linger);
uint nodelay = (uint)(!stream->tcp_nodelay);
setsockopt(stream->client_sock, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof nodelay);
return e_pcpt_ok;
}
e_pcpt_t pcptCheckConnectAble(pcpt_t *stream, timeout_t timeout_ms) {
DWORD DVar1;
uint uVar3;
HANDLE event;
bool bVar5;
e_pcpt_t local_44;
u_long local_40;
amtime_t now;
amtime_t start;
if (stream == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
amiTimerGet(&start);
DVar1 = timeout_ms;
if (timeout_ms == TIMEOUT_NONE) DVar1 = TIMEOUT_NONE;
while (DVar1 = WaitForSingleObject(stream->client_event, DVar1), DVar1 == WAIT_TIMEOUT) {
LAB_004589c8:
amiTimerGet(&now);
uVar3 = _amTimeDelta(now, start);
if (timeout_ms <= uVar3) return e_pcpt_to;
DVar1 = timeout_ms - uVar3;
}
if (DVar1 == 0) {
WSANETWORKEVENTS net_events;
if (FAILED(WSAEnumNetworkEvents(stream->client_sock, stream->client_event, &net_events))) {
bVar5 = WSAGetLastError() == WSAEWOULDBLOCK;
} else {
if ((net_events.lNetworkEvents & 0x10) != 0 &&
net_events.iErrorCode[FD_CONNECT_BIT] == 0) {
local_44 = e_pcpt_ok;
goto LAB_00458a1e;
}
if (WSAGetLastError() == WSAEWOULDBLOCK) goto LAB_004589c8;
bVar5 = net_events.iErrorCode[FD_CONNECT_BIT] == WSAECONNREFUSED;
}
if (bVar5) goto LAB_004589c8;
}
local_44 = e_pcpt_wsa2_generic;
LAB_00458a1e:
local_40 = 0;
WSAEventSelect(stream->client_sock, 0, 0);
WSACloseEvent(stream->client_event);
stream->client_event = NULL;
if (local_44 != e_pcpt_ok) {
closesocket(stream->client_sock);
stream->client_sock = SOCKET_INVAL;
return local_44;
}
ioctlsocket(stream->client_sock, FIONBIO, &local_40);
event = WSACreateEvent();
stream->client_event = event;
if (event != NULL) {
WSAEventSelect(stream->client_sock, event, FD_READ | FD_WRITE | FD_CLOSE);
return e_pcpt_ok;
}
closesocket(stream->client_sock);
stream->client_sock = SOCKET_INVAL;
return e_pcpt_unknown;
}
e_pcpt_t pcptCheckEvent(HANDLE event, timeout_t timeout_ms, SOCKET socket, uint event_mask) {
amtime_t now;
amtime_t start;
WSANETWORKEVENTS networkEvents;
amiTimerGet(&start);
now.seconds = start.seconds;
now.microseconds = start.microseconds;
DWORD wait_timeout = timeout_ms;
if (timeout_ms == TIMEOUT_NONE) wait_timeout = TIMEOUT_NONE;
if (event == NULL) {
PCP_LOG("Error : EVENT HANDLE error\n");
return e_pcpt_pointer_unset;
}
event_mask &= 0xffffffdf;
while (1) {
DWORD err = WaitForSingleObject(event, wait_timeout);
if ((err != WAIT_TIMEOUT && err != 0) || FAILED(err)) {
return e_pcpt_wsa2_generic;
}
if (err != WAIT_TIMEOUT) {
if (FAILED(WSAEnumNetworkEvents(socket, event, &networkEvents)))
return e_pcpt_wsa2_generic;
if ((networkEvents.lNetworkEvents & 0x20) != 0) return e_pcpt_closed;
if ((event_mask & networkEvents.lNetworkEvents) != 0) return e_pcpt_ok;
}
if (timeout_ms != TIMEOUT_NONE) {
amiTimerGet(&now);
uint elapsed = _amTimeDelta(now, start);
if ((uint)timeout_ms <= elapsed) return e_pcpt_to;
wait_timeout = timeout_ms - elapsed;
}
}
}
e_pcpt_t pcptOpenDataSockServer(pcpt_t *sock, timeout_t timeout_ms) {
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
if (sock->open == PCPT_CONNECTED) return e_pcpt_already_open;
if (sock->open == PCPT_CLOSED) return e_pcpt_not_open;
if ((sock->client_sock == SOCKET_INVAL)) {
e_pcpt_t err = pcptAcceptServer(sock, timeout_ms);
if (err != e_pcpt_ok) return err;
}
sock->open = PCPT_CONNECTED;
return e_pcpt_ok;
}
e_pcpt_t pcptOpenServer(pcpt_t *stream, int open_mode, ushort port) {
e_pcpt_t err;
if (stream == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
if (stream->server_sock != SOCKET_INVAL || stream->client_sock != SOCKET_INVAL)
return stream->err = e_pcpt_already_open;
amtime_t start;
amiTimerGet(&start);
stream->field_0x58 = 1;
stream->open = PCPT_CLOSED;
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
stream->server_sock = s;
if (s == SOCKET_INVAL) return stream->err = _errW2T(GetLastError());
uint reuseaddr = 1;
if (FAILED(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&reuseaddr, 4))) {
err = _errW2T(GetLastError());
closesocket(stream->server_sock);
stream->server_sock = SOCKET_INVAL;
return stream->err = err;
}
SOCKADDR_IN addr = { .sin_family = AF_INET,
.sin_port = ntohs(port),
.sin_addr.s_addr = ntohl(0) };
if (open_mode != OPEN_MODE_GLOBAL) {
INT len = sizeof &addr.sin_addr.s_addr;
WSAStringToAddressW(L"127.0.0.1", AF_INET, NULL, (LPSOCKADDR)&addr.sin_addr.s_addr, &len);
}
if (FAILED(bind(stream->server_sock, (SOCKADDR *)&addr, sizeof addr))) {
err = _errW2T(GetLastError());
closesocket(stream->server_sock);
stream->server_sock = SOCKET_INVAL;
return stream->err = err;
}
if (FAILED(listen(stream->server_sock, 128))) {
err = _errW2T(GetLastError());
closesocket(stream->server_sock);
stream->server_sock = SOCKET_INVAL;
return stream->err = err;
}
WSAEVENT event = WSACreateEvent();
stream->server_event = event;
if (event != NULL) {
WSAEventSelect(stream->server_sock, event, FD_CLOSE | FD_ACCEPT);
stream->open = PCPT_LISTENING;
stream->client_open = 0;
return stream->err = e_pcpt_ok;
}
closesocket(stream->server_sock);
stream->server_sock = SOCKET_INVAL;
return stream->err = e_pcpt_unknown;
}
e_pcpt_t pcptRecv(pcpt_t *sock, unsigned char *recv_buf, size_t *recv_buf_len,
timeout_t timeout_ms) {
e_pcpt_t err;
amtime_t now;
amtime_t start;
if (sock == NULL || recv_buf == NULL || recv_buf_len == NULL) {
printf("%p %p %p\n", sock, recv_buf, recv_buf_len);
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
if (sock->open == PCPT_CLOSED) return sock->err = e_pcpt_not_open;
if (sock->client_open != 0) return sock->err = e_pcpt_already_connected;
sock->recv_buf = recv_buf;
sock->recv_buf_count = recv_buf_len;
sock->client_open = 3;
if (sock->open == PCPT_LISTENING && sock->field_0x58 != 0) {
amiTimerGet(&start);
sock->err = err = pcptOpenDataSockServer(sock, timeout_ms);
if (err == e_pcpt_to) return e_pcpt_to;
if (err != e_pcpt_ok) {
pcptCloseDataSock(sock);
return sock->err;
}
if (timeout_ms != TIMEOUT_NONE) {
amiTimerGet(&now);
uint elapsed = _amTimeDelta(now, start);
if (elapsed < timeout_ms)
timeout_ms = timeout_ms - elapsed;
else
timeout_ms = 0;
}
}
sock->err = err = pcptCheckEvent(sock->client_event, timeout_ms, sock->client_sock, FD_READ);
if (err == e_pcpt_to) return e_pcpt_to;
sock->client_open = 0;
if (err == e_pcpt_ok) {
size_t recv_count =
recv(sock->client_sock, (char *)sock->recv_buf, *sock->recv_buf_count, 0);
if (0 < (int)recv_count) {
*recv_buf_len = recv_count;
sock->err = e_pcpt_ok;
return e_pcpt_ok;
}
if (recv_count == 0) {
pcptCloseDataSock(sock);
return sock->err = e_pcpt_closed;
}
sock->err = _errW2T(GetLastError());
}
pcptCloseDataSock(sock);
return sock->err;
}
e_pcpt_t pcptSend(pcpt_t *sock, unsigned char *send_buf, size_t *send_len, uint param_4,
timeout_t timeout_ms) {
e_pcpt_t err;
amtime_t now;
amtime_t start_time;
if (sock == NULL || send_buf == NULL || send_len == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
if (sock->open == PCPT_CLOSED) return sock->err = e_pcpt_not_open;
if (sock->client_open != 0) return sock->err = e_pcpt_already_connected;
sock->send_buf_count = send_len;
sock->send_buf = send_buf;
sock->client_open = 2;
sock->field_0x14 = param_4;
sock->field_0x54 = 0;
if (sock->open == PCPT_LISTENING && sock->field_0x58 != 0) {
amiTimerGet(&start_time);
err = pcptOpenDataSockServer(sock, timeout_ms);
sock->err = err;
if (err == e_pcpt_to) return e_pcpt_to;
if (err == e_pcpt_ok) {
amiTimerGet(&now);
uint elapsed = _amTimeDelta(now, start_time);
if (timeout_ms != TIMEOUT_NONE) {
if (elapsed < timeout_ms)
timeout_ms = timeout_ms - elapsed;
else
timeout_ms = 0;
}
goto LAB_0045930e;
}
} else {
LAB_0045930e:
err = pcptSendAllMsg(sock, timeout_ms);
sock->err = err;
if (err == e_pcpt_to) {
return e_pcpt_to;
}
sock->client_open = 0;
if (err == e_pcpt_ok) return err;
}
pcptCloseDataSock(sock);
return sock->err;
}
e_pcpt_t pcptSendAllMsg(pcpt_t *sock, timeout_t timeout_ms) {
size_t sVar1;
bool bVar2;
e_pcpt_t err;
bool bVar3;
amtime_t now;
amtime_t start;
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
if (sock->send_buf == NULL || sock->send_buf_count == NULL) {
PCP_LOG("error send buffer isn\'t set\n");
return e_pcpt_pointer_unset;
}
bVar3 = sock->field_0x54 == 0;
amiTimerGet(&start);
sVar1 = *sock->send_buf_count;
while (1) {
if (sVar1 == 0) {
sock->field_0x54 = 0;
return e_pcpt_ok;
}
bVar2 = false;
amiTimerGet(&now);
uint elapsed = _amTimeDelta(now, start);
if (timeout_ms != TIMEOUT_NONE && timeout_ms < elapsed) return e_pcpt_to;
uint wait_time;
if (bVar3) {
wait_time = timeout_ms;
if (timeout_ms != TIMEOUT_NONE) wait_time = timeout_ms - elapsed;
} else {
if ((timeout_ms == TIMEOUT_NONE) ||
(wait_time = timeout_ms - elapsed,
sock->field_0x14 <= wait_time && wait_time != sock->field_0x14)) {
wait_time = sock->field_0x14;
bVar2 = true;
}
}
int sent = send(sock->client_sock, (char *)sock->send_buf, *sock->send_buf_count, 0);
if (sent == -1) {
err = _errW2T(GetLastError());
if (err != e_pcpt_to) return err;
err = pcptCheckEvent(sock->client_event, wait_time, sock->client_sock, FD_WRITE);
if (err == e_pcpt_to) {
if (!bVar2) return e_pcpt_to;
sock->field_0x54 = 0;
return e_pcpt_NO_IDEA_WHAT_THIS_IS;
}
if (err != e_pcpt_ok) return err;
} else {
sock->send_buf = sock->send_buf + sent;
sock->field_0x54 = 1;
*sock->send_buf_count = *sock->send_buf_count - sent;
}
bVar3 = false;
sVar1 = *sock->send_buf_count;
}
}
void pcptSetConfig(pcpt_t *stream, uint config, uint value) {
if (stream == NULL) {
PCP_LOG("error don\'t set stream\n");
return;
}
switch (config) {
case PCPT_CONFIG_0:
stream->config_0 = value;
break;
case PCPT_CONFIG_1:
stream->config_1 = value;
break;
case PCPT_SO_LINGER:
stream->so_linger = value;
break;
case PCPT_TCP_NODELAY:
stream->tcp_nodelay = value;
break;
}
}
// TODO: TIDY
e_pcpt_t pcptIsBusy(pcpt_t *sock, timeout_t timeout_ms) {
bool bVar1;
bool bVar2;
uint uVar3;
uint uVar4;
SOCKET SVar5;
WSAEVENT event;
int iVar7;
e_pcpt_t eVar8;
u_long timeout_ms_00;
uint uVar10;
amtime_t local_18;
amtime_t local_10;
amtime_t local_8;
timeout_ms_00 = timeout_ms;
if (sock == NULL) {
PCP_LOG("error PCP stream isn\'t set\n");
return e_pcpt_pointer_unset;
}
switch (sock->client_open) {
case 0:
sock->err = e_pcpt_no_client;
return sock->err;
case 1:
if (sock->open != PCPT_CLOSED) {
sock->err = e_pcpt_cannot_open;
sock->client_open = 0;
return sock->err;
}
amiTimerGet(&local_10);
uVar10 = timeout_ms_00;
do {
bVar1 = false;
bVar2 = false;
amiTimerGet(&local_18);
if (uVar10 != TIMEOUT_NONE) {
uVar3 = _amTimeDelta(local_18, local_10);
if (uVar3 < uVar10) {
timeout_ms_00 = uVar10 - uVar3;
} else {
bVar2 = true;
timeout_ms_00 = 0;
}
}
amiTimerGet(&local_18);
uVar4 = _amTimeMs(local_18) - sock->field_0x40;
uVar3 = sock->config_0;
if (uVar3 < uVar4) {
timeout_ms_00 = 0;
LAB_00459626:
bVar1 = true;
} else {
if ((uVar10 == TIMEOUT_NONE) || (uVar3 < timeout_ms_00)) {
timeout_ms_00 = uVar3 - uVar4;
goto LAB_00459626;
}
}
eVar8 = pcptCheckConnectAble(sock, timeout_ms_00);
sock->err = eVar8;
if (eVar8 != e_pcpt_to) {
sock->client_open = 0;
if (eVar8 == e_pcpt_ok) {
sock->open = PCPT_CONNECTED;
return sock->err;
}
break;
}
if (bVar1) {
WSAEventSelect(sock->client_sock, 0, 0);
WSACloseEvent(sock->client_event);
sock->client_event = NULL;
closesocket(sock->client_sock);
sock->client_sock = SOCKET_INVAL;
SVar5 = socket(2, 1, 0);
sock->client_sock = SVar5;
if (SVar5 == SOCKET_INVAL) goto LAB_004599cf;
event = WSACreateEvent();
sock->client_event = event;
if (event == NULL) {
closesocket(sock->client_sock);
sock->err = e_pcpt_unknown;
sock->client_sock = SOCKET_INVAL;
return sock->err;
}
WSAEventSelect(sock->client_sock, event, FD_CONNECT | FD_CLOSE);
iVar7 = connect(sock->client_sock, &sock->client_addr, 16);
if (iVar7 != -1) {
WSAEventSelect(sock->client_sock, 0, 0);
WSACloseEvent(sock->client_event);
sock->client_event = NULL;
timeout_ms = 0;
ioctlsocket(sock->client_sock, FIONBIO, (u_long *)&timeout_ms);
event = WSACreateEvent();
sock->client_event = event;
if (event != NULL) {
WSAEventSelect(sock->client_sock, event, FD_READ | FD_WRITE | FD_CLOSE);
sock->err = e_pcpt_ok;
sock->client_open = 0;
sock->open = PCPT_CONNECTED;
return e_pcpt_ok;
}
closesocket(sock->client_sock);
sock->err = e_pcpt_unknown;
sock->client_sock = SOCKET_INVAL;
return sock->err;
}
amiTimerGet(&local_8);
sock->field_0x40 = _amTimeMs(local_8);
} else {
if (bVar2) {
sock->err = e_pcpt_to;
return e_pcpt_to;
}
}
uVar10 = timeout_ms;
} while (sock->err == e_pcpt_to);
break;
case 2:
if (sock->open == PCPT_CLOSED) {
sock->err = e_pcpt_not_open;
return e_pcpt_not_open;
}
if ((sock->open == PCPT_LISTENING) && (sock->field_0x58 != 0)) {
amiTimerGet(&local_10);
eVar8 = pcptOpenDataSockServer(sock, timeout_ms_00);
sock->err = eVar8;
if (eVar8 == e_pcpt_to) {
return e_pcpt_to;
}
if (eVar8 != e_pcpt_ok) {
LAB_0045997d:
pcptCloseDataSock(sock);
return sock->err;
}
amiTimerGet(&local_18);
if (timeout_ms_00 != TIMEOUT_NONE) {
iVar7 = (local_18.microseconds - local_10.microseconds) / 1000;
if (timeout_ms_00 <
(uint)((local_18.seconds - local_10.seconds) * 1000 + iVar7)) {
timeout_ms_00 =
((local_10.seconds - local_18.seconds) * 1000 - iVar7) + timeout_ms_00;
} else {
timeout_ms_00 = 0;
}
}
}
eVar8 = pcptSendAllMsg(sock, timeout_ms_00);
sock->err = eVar8;
if (eVar8 != e_pcpt_to) {
if (eVar8 != e_pcpt_ok) {
pcptCloseDataSock(sock);
}
sock->client_open = 0;
return sock->err;
}
break;
case 3:
if (sock->open == PCPT_CLOSED) {
sock->err = e_pcpt_not_open;
return sock->err;
}
if ((sock->open == PCPT_LISTENING) && (sock->field_0x58 != 0)) {
amiTimerGet(&local_10);
eVar8 = pcptOpenDataSockServer(sock, timeout_ms_00);
sock->err = eVar8;
if (eVar8 == e_pcpt_to) {
return e_pcpt_to;
}
if (eVar8 != e_pcpt_ok) goto LAB_0045997d;
amiTimerGet(&local_18);
if (timeout_ms_00 != TIMEOUT_NONE) {
iVar7 = (local_18.microseconds - local_10.microseconds) / 1000;
if (timeout_ms_00 <
(uint)((local_18.seconds - local_10.seconds) * 1000 + iVar7)) {
timeout_ms_00 =
((local_10.seconds - local_18.seconds) * 1000 - iVar7) + timeout_ms_00;
} else {
timeout_ms_00 = 0;
}
}
}
eVar8 = pcptCheckEvent(sock->client_event, timeout_ms_00, sock->client_sock, 1);
sock->err = eVar8;
if (eVar8 == e_pcpt_to) break;
sock->client_open = 0;
if (eVar8 != e_pcpt_ok) goto LAB_0045997d;
if (sock->recv_buf == NULL || sock->recv_buf_count == NULL) {
PCP_LOG("error Recv buffer isn\'t set\n");
return sock->err = e_pcpt_recv_unset;
}
size_t received =
recv(sock->client_sock, (char *)sock->recv_buf, *sock->recv_buf_count, 0);
if (received < 1) {
pcptCloseDataSock(sock);
if (received == 0) {
sock->err = e_pcpt_closed;
return e_pcpt_closed;
}
LAB_004599cf:
return sock->err = _errW2T(GetLastError());
}
*sock->recv_buf_count = received;
default:
sock->err = e_pcpt_ok;
}
return sock->err;
}

View File

@ -40,9 +40,9 @@ typedef struct pcpt {
uint tcp_nodelay;
WSAEVENT client_event;
WSAEVENT server_event;
char* send_buf;
unsigned char* send_buf;
size_t* send_buf_count;
char* recv_buf;
unsigned char* recv_buf;
size_t* recv_buf_count;
uint field_0x40;
SOCKADDR client_addr;
@ -59,7 +59,7 @@ e_pcpt_t pcptCheckEvent(HANDLE event, timeout_t timeout_ms, SOCKET socket, uint
e_pcpt_t pcptIsBusy(pcpt_t* sock, timeout_t timeout_ms);
e_pcpt_t pcptOpenDataSockServer(pcpt_t* sock, timeout_t timeout_ms);
e_pcpt_t pcptOpenServer(pcpt_t* sock, int open_mode, ushort port);
e_pcpt_t pcptRecv(pcpt_t* sock, char* recv_buf, size_t* recv_buf_len, timeout_t timeout_ms);
e_pcpt_t pcptSend(pcpt_t* sock, char* send_buf, size_t* send_len, uint param_4, timeout_t timeout_ms);
e_pcpt_t pcptRecv(pcpt_t* sock, unsigned char* recv_buf, size_t* recv_buf_len, timeout_t timeout_ms);
e_pcpt_t pcptSend(pcpt_t* sock, unsigned char* send_buf, size_t* send_len, uint param_4, timeout_t timeout_ms);
e_pcpt_t pcptSendAllMsg(pcpt_t* sock, timeout_t timeout_ms);
void pcptSetConfig(pcpt_t* sock, uint config, uint value);

View File

@ -0,0 +1,87 @@
#include "pcpa.h"
void pcptPrint(pcpt_t* stream, char* name) {
printf(" PCPT %s STATUS\n", name);
printf(" Current errno: %d\n", stream->err);
printf(" Server socket: %08X (%d)\n", stream->server_sock, stream->open);
printf(" Client socket: %08X (%d)\n", stream->client_sock, stream->client_open);
if (stream->send_buf)
printf(" Send buffer: %.*s\n", *stream->send_buf_count, stream->send_buf);
else
puts(" Send buffer: -");
if (stream->recv_buf)
printf(" Recv buffer: %.*s\n", *stream->recv_buf_count, stream->recv_buf);
else
puts(" Recv buffer: -");
}
void pcppPrint(pcpp_t* stream) {
puts("PCPP STATUS");
printf(" Current errno: %d state: %d\n", stream->err, stream->state);
printf(" Open: %d at %d\n", stream->open, stream->last_active);
printf(" Read buf: %.*s\n", stream->read_bytes_num, stream->read_bytes_buf);
printf(" Send buf: %.*s\n", stream->send_buf_len, stream->send_buf);
printf(" Send binary: %p (%d[?])\n", stream->send_binary_buf, stream->field_0x1f8);
printf(" Recv binary: %p (%d)\n", stream->recv_binary_buf, stream->recv_binary_buf_len);
pcptPrint(&stream->sock, "TEXT");
pcptPrint(&stream->data_sock, "BINARY");
}
void pcpaPrint(pcpa_t* stream) {
puts("PCPA STATUS");
amtime_t now;
amiTimerGet(&now);
printf("Now: %d\n", _amTimeMs(now));
printf("Current errno: %d\n", stream->err);
printf("%d/%d callbacks registered at %p\n", stream->callback_count, stream->callback_max, stream->callback_table);
printf("Binary mode: %d (%p/%p)\n", stream->binary_mode, stream->binary_mode_before_cb,
stream->binary_mode_after_cb);
if (stream->recv_buffer)
printf("Recv buffer: %.*s\n", stream->recv_buffer_len, stream->recv_buffer);
else
puts("Recv buffer: -");
if (stream->send_buffer)
printf("Send buffer: %.*s\n", stream->send_buffer_len, stream->send_buffer);
else
puts("Send buffer: -");
pcppPrint(&stream->pcpp);
printf("Send data: %.*s\n", stream->send_data.length, stream->send_data.data);
puts("Parse data:");
printf(" %d commands:\n", stream->recv_data.cmd_count);
for (size_t i = 0; i < stream->recv_data.cmd_count; i++) {
byte kwd = stream->recv_data.keywords[i];
if (kwd != 0) kwd++;
printf(" & %02d '%s'\n", kwd, stream->recv_data.strings + kwd);
byte value = stream->recv_data.values[i];
if (value != 0) value++;
printf(" = %02d '%s'\n", value, stream->recv_data.strings + value);
if (stream->recv_data.strings[kwd] == 0) break;
}
puts(" Raw strings table:");
for (size_t i = 0; i < PCP_BUF_MAX; i = i + 32) {
printf(" ");
for (size_t j = i; j < i + 32; j++) {
printf("%02X ", stream->recv_data.strings[j]);
if (j % 16 == 15)
printf(" ");
else if (j % 8 == 7)
printf(" ");
}
printf(" ");
for (size_t j = i; j < i + 32; j++) {
char chr = stream->recv_data.strings[j];
if (' ' <= chr && chr <= '~')
printf("%c", chr);
else
printf(".");
if (j % 16 == 15) printf(" ");
}
puts("");
}
}

View File

@ -1,16 +1,8 @@
subdir('util') # This is the only lib that should ever be link_with'd by another lib
subdir('json')
subdir('am')
subdir('dmi')
subdir('mice')
subdir('am')
fs = import('fs')
# Handle the fact we aren't distributing the libpcp source
if fs.exists('libpcp/libpcp.c')
subdir('libpcp')
libpcp_is_static = true
else
libpcp = meson.get_compiler('c').find_library('libpcp', dirs: libs_dir, required: false)
assert(libpcp.found(), 'Unable to locate libpcp.lib. Make sure to place it in the src/ folder prior to building.')
libpcp_is_static = false
endif
subdir('libpcp')

View File

@ -69,7 +69,7 @@ bool inject_dll(HANDLE process, LPCSTR inject) {
HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
STARTUPINFOA startupInfo;
PROCESS_INFORMATION processInformation;
PROCESS_INFORMATION processInformation = { 0 };
memset(&startupInfo, 0, sizeof(startupInfo));
startupInfo.cb = sizeof(startupInfo);
@ -78,16 +78,23 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
// snprintf(real_inject_path, MAX_PATH + 1, ".\\%s", inject);
// GetFullPathNameA(real_inject_path, MAX_PATH + 1, &real_inject_path, NULL);
// Validate that we're not about to try something insane
DWORD found = SearchPathA(NULL, inject, NULL, 0, NULL, NULL);
DWORD found;
// Does the exe we're starting exist?
found = SearchPathA(NULL, path, NULL, 0, NULL, NULL);
if (found == 0) {
fprintf(stderr, "Fatal: Cannot inject %s: not found: %03x\n", inject, GetLastError());
fprintf(stderr, "Fatal: Cannot start %s: not found\n", path);
goto abort;
}
// Does the DLL we want to inject exist?
found = SearchPathA(NULL, inject, NULL, 0, NULL, NULL);
if (found == 0) {
fprintf(stderr, "Fatal: Cannot inject %s: not found\n", inject);
goto abort;
}
// Start the binary
if (FAILED(CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo,
&processInformation))) {
if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo,
&processInformation)) {
fprintf(stderr, "Fatal: CreateProcessA failed: %03x\n", GetLastError());
goto abort;
}
@ -107,16 +114,16 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
abort:
if (processInformation.hProcess) {
if (FAILED(CloseHandle(processInformation.hThread)))
if (!CloseHandle(processInformation.hThread))
fprintf(stderr, "Fatal: CloseHandle(hProcess) failed: %03x\n", GetLastError());
if (FAILED(TerminateProcess(processInformation.hProcess, 1)))
if (!TerminateProcess(processInformation.hProcess, 1))
fprintf(stderr, "Fatal: TerminateProcess failed: %03x\n", GetLastError());
}
if (processInformation.hThread) {
if (FAILED(CloseHandle(processInformation.hThread)))
if (!CloseHandle(processInformation.hThread))
fprintf(stderr, "Fatal: CloseHandle(hThread) failed: %03x\n", GetLastError());
}
return NULL;
return INVALID_HANDLE_VALUE;
}

View File

@ -5,8 +5,10 @@
// amSramInit
#define IOCTL_MXSRAM_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
// amSramInit
#define IOCTL_MXSRAM_GET_SECTOR_SIZE CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXSRAM_GET_VERSION CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXSRAM_GET_SECTOR_SIZE \
CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXSRAM_GET_VERSION \
CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
// EEPROM uses MXSMBUS_GUID device class
// DIPSW uses MXSMBUS_GUID device class
@ -25,11 +27,13 @@
#define IOCTL_MXSUPERIO_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
// amHmGetLPCChipId
#define IOCTL_MXSUPERIO_READ CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MXSUPERIO_UNKNOWN CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXSUPERIO_WRITE CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
// amHmLpcReadByte
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_READ CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_READ \
CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
// amHmLpcWriteByte
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE \
CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXJVS_EXCHANGE CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
@ -37,20 +41,29 @@
// amHmI2CReadByte,amHmI2CWriteByte,amEepromWait
#define IOCTL_MXSMBUS_REQUEST CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
// amEepromGetDriverVerision
#define IOCTL_MXSMBUS_GET_VERSION CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXSMBUS_GET_VERSION \
CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
// amEepromI2CReadBlock,amEepromI2CWriteBlock,amHmGetLPCChipId
#define IOCTL_MXSMBUS_I2C CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MXSMBUS_IDK CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_COLUMBA_READ_DMI CTL_CODE(FILE_DEVICE_SEGA, 0x841, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_COLUMBA_READ CTL_CODE(FILE_DEVICE_SEGA, 0x841, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXHWRESET_RESET CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_DATA CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_DATA CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_STATUS CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_STATUS CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_CTRL_PORT CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_CTRL_PORT CTL_CODE(FILE_DEVICE_SEGA, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_FLAGS CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_FLAGS CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_DATA \
CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_DATA \
CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_STATUS \
CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_STATUS \
CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_CTRL_PORT \
CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_CTRL_PORT \
CTL_CODE(FILE_DEVICE_SEGA, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_FLAGS \
CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_READ_FLAGS \
CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)

View File

@ -25,7 +25,7 @@ bool fetch_int(json_value* object, char* name, size_t* value) {
json_value* fetched;
if (!fetch(object, name, &fetched)) return false;
if (fetched->type != json_integer) return false;
*value = fetched->u.integer;
*value = (size_t)fetched->u.integer;
return true;
}
bool fetch_bool(json_value* object, char* name, bool* value) {
@ -39,7 +39,7 @@ void free_patches(patches_t* patches) {
if (patches->nopatchsets == 0) return;
for (int i = patches->nopatchsets - 1; i >= 0; i--) {
if (patches->patchsets[i] != NULL) {
for (int j = 0; j < patches->patchsets[i]->nopatches; j++) {
for (size_t j = 0; j < patches->patchsets[i]->nopatches; j++) {
if (patches->patchsets[i]->patches[j].from != NULL) free(patches->patchsets[i]->patches[j].from);
if (patches->patchsets[i]->patches[j].to != NULL) free(patches->patchsets[i]->patches[j].to);
}
@ -181,8 +181,8 @@ bool parse_patches(patches_t* patches, json_value** set_json, int set_count, cha
snprintf(error, json_error_max, "invalid hex string in patch %s[%d]", name, j);
goto failed;
}
char* bin_from = patchset->patches[j].from = (char*)malloc(size / 2);
char* bin_to = patchset->patches[j].to = (char*)malloc(size / 2);
unsigned char* bin_from = patchset->patches[j].from = (unsigned char*)malloc(size / 2);
unsigned char* bin_to = patchset->patches[j].to = (unsigned char*)malloc(size / 2);
if (!hex_to_bin(from, bin_from, size)) {
snprintf(error, json_error_max, "invalid hex string in patch %s[%d].from", name, j);
goto failed;

View File

@ -4,5 +4,5 @@ subdir('micepatch')
subdir('micekeychip')
subdir('launcher')
subdir('dll')
subdir('micetest')
subdir('miceboot')
subdir('util')

View File

@ -0,0 +1,4 @@
@echo off
@REM "C:\Program Files (x86)\TrueCrypt\TrueCrypt.exe" %*
echo %*
pause

View File

@ -0,0 +1,150 @@
/****************************************************************************
Copyright (c) 2003 Microsoft Corporation
Module Name: ewfapi.h
Abstract: Defines the EWF APIs
Environment: User mode
Revision History:
****************************************************************************/
#ifndef __EWFAPI_H__
#define __EWFAPI_H__
#ifdef __cplusplus
extern "C" {
#endif
#ifndef EWFIMP
#define EWFIMP __declspec(dllimport)
#endif
typedef struct _EWF_VOLUME_NAME_ENTRY {
struct _EWF_VOLUME_NAME_ENTRY* Next;
WCHAR Name[1];
} EWF_VOLUME_NAME_ENTRY, *PEWF_VOLUME_NAME_ENTRY;
typedef enum {
EWF_NO_CMD = 0, // no pending command
EWF_ENABLE, // overlay will be enabled
EWF_DISABLE, // overlay will be disabled
EWF_SET_LEVEL, // overlay level will be set
EWF_COMMIT // current level will be committed to the protected volume
} EWF_CMD;
typedef enum {
EWF_ENABLED, // The overlay is enabled on the volume
EWF_DISABLED // The overlay is disabled on the volume
} EWF_STATE;
typedef enum {
EWF_DISK, // DISK overlay
EWF_RAM, // RAM overlay, with an associated overlay volume store
EWF_RAM_REG, // RAM overlay, without an associated overlay volume store
} EWF_TYPE,
*PEWF_TYPE;
#define EWF_MAX_DEVICE_NAME_LENGTH (256)
#define EWF_VOLUME_ID_SIZE (16)
typedef struct _EWF_VOLUME_DESC {
WCHAR DeviceName[EWF_MAX_DEVICE_NAME_LENGTH]; // Device name of the volume
UCHAR VolumeID[EWF_VOLUME_ID_SIZE]; // 16 byte volume identifier
} EWF_VOLUME_DESC, *PEWF_VOLUME_DESC;
//
// This is a variable size structure depending on how many protected overlay
// volumes there are.
//
typedef struct _EWF_OVERLAY_STORE_CONFIG {
ULONG FormatVersion; // Version of Overlay-Store format
LONGLONG VolumeSize; // Size of the overlay volume in bytes
ULONG NumSegments; // Number of segments that the volume is divided into
ULONG FreeSegments; // Number of segments that are free
ULONG SegmentSize; // Size of each segment in bytes
ULONG MaxVolumes; // Maximum number of protected volumes
ULONG NumVolumes; // Number of currently protected volumes
USHORT MaxLevels; // Maximum number of overlay levels
EWF_VOLUME_DESC VolumeDescArray[1];
// The array holds NumVolume count volume descriptions
} EWF_OVERLAY_STORE_CONFIG, *PEWF_OVERLAY_STORE_CONFIG;
typedef struct _EWF_COMMAND {
EWF_CMD Command; // ENABLE, DISABLE, etc..
ULONG Param1; // command first parameter.
ULONG Param2; // command second parameter.
} EWF_COMMAND, *PEWF_COMMAND;
#define EWF_MAX_LEVEL_NAME_LENGTH (64)
typedef struct _EWF_LEVEL_DESC {
WCHAR LevelName[EWF_MAX_LEVEL_NAME_LENGTH];
// friendly name of the level
// If the length is equal to EWF_MAX_LEVEL_NAME_LENGTH
// then no null terminator is stored.
FILETIME LevelEndTime; // time at which the level was ended
LONGLONG LevelDataSize; // Size of the data in the level in bytes
} EWF_LEVEL_DESC, *PEWF_LEVEL_DESC;
#define EWF_MAX_PERSISTENT_DATA (32) // maximum number of bytes that can be persisted
typedef struct _EWF_VOLUME_CONFIG {
EWF_TYPE Type; // Type of overlay for this volume
EWF_STATE State; // state of the overlay for this volume, ENABLED or DISABLED
EWF_COMMAND BootCommand; // Command to execute on next restart
// Small amount of persistent data that survives a restore
UCHAR PersistentData[EWF_MAX_PERSISTENT_DATA];
USHORT MaxLevels; // Maximum number of checkpoint levels for this volume
ULONG ClumpSize; // 512 bytes
USHORT CurrentLevel; // Current checkpoint level
union {
struct {
LONGLONG DiskMapSize; // Size of the mapping data on disk
LONGLONG DiskDataSize; // Size of the data stored on disk for this protected volume
} DiskOverlay;
struct {
LONGLONG RamDataSize; // Size of the data stored in RAM for this protected volume
} RamOverlay;
};
ULONG MemMapSize; // Size of the mapping data in memory
EWF_VOLUME_DESC VolumeDesc; // volume device name, and volume ID
EWF_LEVEL_DESC LevelDescArray[1]; // Level descripton and end time, and level data size
} EWF_VOLUME_CONFIG, *PEWF_VOLUME_CONFIG;
EWFIMP WCHAR WINAPI EwfMgrGetDriveLetterFromVolumeName(IN LPCWSTR lpVolumeName);
EWFIMP BOOL WINAPI EwfMgrVolumeNameListIsEmpty(IN PEWF_VOLUME_NAME_ENTRY pVolumeNameList);
EWFIMP VOID WINAPI EwfMgrVolumeNameEntryPop(IN PEWF_VOLUME_NAME_ENTRY* ppVolumeNameList);
EWFIMP VOID WINAPI EwfMgrVolumeNameListDelete(IN PEWF_VOLUME_NAME_ENTRY pVolumeNameList);
EWFIMP HANDLE WINAPI EwfMgrOpenProtected(IN LPCWSTR lpVolume);
EWFIMP BOOL WINAPI EwfMgrClose(IN HANDLE hDevice);
EWFIMP BOOL WINAPI EwfMgrClearCommand(IN HANDLE hDevice);
EWFIMP BOOL WINAPI EwfMgrSetPersistentData(IN HANDLE hDevice, IN LPBYTE lpPersistentData, IN DWORD cbPersistentData);
EWFIMP BOOL WINAPI EwfMgrGetPersistentData(IN HANDLE hDevice, OUT LPBYTE lpPersistentData, IN DWORD cbPersistentData);
EWFIMP BOOL WINAPI EwfMgrCheckpoint(IN HANDLE hDevice, IN OPTIONAL LPCWSTR lpDescription);
EWFIMP BOOL WINAPI EwfMgrRestore(IN HANDLE hDevice);
EWFIMP BOOL WINAPI EwfMgrDisable(IN HANDLE hDevice, IN BOOL fCommit);
EWFIMP BOOL WINAPI EwfMgrEnable(IN HANDLE hDevice);
EWFIMP BOOL WINAPI EwfMgrCommit(IN HANDLE hDevice);
EWFIMP BOOL WINAPI EwfMgrCommitAndDisableLive(IN HANDLE hDevice);
EWFIMP BOOL WINAPI EwfMgrCommitFile(IN HANDLE hDevice, IN LPWSTR lpFile);
EWFIMP BOOL WINAPI EwfMgrSetLevel(IN HANDLE hDevice, IN OPTIONAL LPCWSTR lpDescription, IN int Level,
IN BOOL fDeleteLevel);
EWFIMP PEWF_VOLUME_CONFIG WINAPI EwfMgrGetProtectedVolumeConfig(IN HANDLE hDevice);
EWFIMP PEWF_VOLUME_NAME_ENTRY WINAPI EwfMgrGetProtectedVolumeList(VOID);
EWFIMP HANDLE WINAPI EwfMgrOpenOverlayStore(IN BOOL fOpenForAsyncIO);
EWFIMP PEWF_OVERLAY_STORE_CONFIG WINAPI EwfMgrGetOverlayStoreConfig(IN HANDLE hDevice);
EWFIMP BOOL WINAPI EwfMgrRegisterLowSpaceNotification(IN HANDLE hDevice, IN LONGLONG FreeBytesRemaining,
IN LPOVERLAPPED lpOverlapped);
#ifdef __cplusplus
}
#endif
#endif // __EWFAPI_H__

View File

@ -0,0 +1,31 @@
executable(
'miceprestartup',
win_subsystem: subsystem,
sources: [
'mxprestartup.c',
],
)
executable(
'micestartup',
win_subsystem: subsystem,
sources: [
'mxstartup.c',
],
)
executable(
'truecrypt',
win_subsystem: subsystem,
sources: [
'truecrypt.c',
],
)
executable(
'mxmaster',
win_subsystem: subsystem,
sources: [
'mxmaster.c',
],
)

View File

@ -0,0 +1,105 @@
#include <Windows.h>
typedef struct __EWF_LEVEL_DESC {
WCHAR
LevelName[EWF_MAX_LEVEL_NAME_LENGTH];
FILETIME
LevelEndTime;
LONGLONG
LevelDataSize;
} EWF_LEVEL_DESC, *PEWF_LEVEL_DESC;
typedef struct _EWF_OVERLAY_STORE_CONFIG {
ULONG
FormatVersion;
LONGLONG
VolumeSize;
ULONG
NumSegments;
ULONG
FreeSegments;
ULONG
SegmentSize;
ULONG
MaxVolumes;
ULONG
NumVolumes;
USHORT
MaxLevels;
EWF_VOLUME_DESC
VolumeDescArray[1];
} EWF_OVERLAY_STORE_CONFIG, *PEWF_OVERLAY_STORE_CONFIG;
typedef struct _EWF_VOLUME_CONFIG {
EWF_TYPE
Type;
EWF_STATE
State;
EWF_COMMAND
BootCommand;
UCHAR
PersistentData[EWF_MAX_PERSISTENT_DATA];
USHORT
MaxLevels;
ULONG
ClumpSize;
USHORT
CurrentLevel;
union {
struct {
LONGLONG
DiskMapSize;
LONGLONG
DiskDataSize;
} DiskOverlay;
struct {
LONGLONG
RamDataSize;
} RamOverlay;
};
ULONG
MemMapSize;
EWF_VOLUME_DESC
VolumeDesc;
EWF_LEVEL_DESC
LevelDescArray[1];
} EWF_VOLUME_CONFIG, *PEWF_VOLUME_CONFIG;
typedef struct _EWF_VOLUME_DESC {
WCHAR _ DeviceName[EWF_MAX_DEVICE_NAME_LENGTH];
UCHAR
VolumeID[EWF_VOLUME_ID_SIZE];
} EWF_VOLUME_DESC, *PEWF_VOLUME_DESC;
typedef struct _EWF_VOLUME_NAME_ENTRY {
struct _EWF_VOLUME_NAME_ENTRY* Next;
WCHAR
Name[1];
} EWF_VOLUME_NAME_ENTRY, *PEWF_VOLUME_NAME_ENTRY;
HRESULT WINAPI ConfigureEwf(VOID);
BOOL EwfMgrActivateHorm(HANDLE hDevice);
BOOL EwfMgrCheckpoint(HANDLE hDevice, OPTIONAL LPCWSTR lpDescription);
BOOL EwfMgrClearCommand(HANDLE hDevice);
BOOL EwfMgrClose(HANDLE hDevice);
BOOL EwfMgrCommit(HANDLE hDevice);
BOOL WINAPI EwfMgrCommitAndDisableLive(IN HANDLE hDevice, );
BOOL WINAPI EwfMgrCommitFile(IN HANDLE hDevice, IN LPWSTR lpFile);
BOOL EwfMgrDeactivateHorm(HANDLE hDevice);
BOOL EwfMgrDisable(HANDLE hDevice, BOOLfCommit);
BOOL EwfMgrEnable(HANDLE hDevice);
WCHAR EwfMgrGetDriveLetterFromVolumeName(LPCWSTR lpVolumeName);
PEWF_OVERLAY_STORE_CONFIG EwfMgrGetOverlayStoreConfig(HANDLE hDevice);
BOOL EwfMgrGetPeristentData(HANDLE hDevice, LPBYTElpPersistentData, DWORDcbPersistentData);
PEWF_VOLUME_CONFIG EwfMgrGetProtectedVolumeConfig(HANDLE hDevice);
PEWF_VOLUME_NAME_ENTRY EwfMgrGetProtectedVolumeList(VOID);
BOOL EwfMgrIsHormActivated(HANDLE hDevice);
HANDLE EwfMgrOpenOverlayStore(BOOL fOpenForAsyncIO);
HANDLE EwfMgrOpenProtected(LPCWSTR lpVolume);
BOOL EwfMgrRegisterLowSpaceNotification(HANDLE hDevice, LONGLONGFreeBytesRemaining, LPOVERLAPPEDlpOverlapped);
BOOL EwfMgrRestore(HANDLE hDevice);
BOOL EwfMgrSetLevel(HANDLE hDevice, OPTIONAL LPCWSTRlpDescription, intLevel, BOOLfDeleteLevel);
BOOL EwfMgrSetPeristentData(HANDLE hDevice, LPBYTE lpPersistentData, DWORD cbPersistentData);
VOID EwfMgrVolumeNameEntryPop(PEWF_VOLUME_NAME_ENTRY* ppVolumeNameList);
VOID EwfMgrVolumeNameListDelete(PEWF_VOLUME_NAME_ENTRY pVolumeNameList);
BOOL EwfMgrVolumeNameListIsEmpty(PEWF_VOLUME_NAME_ENTRY pVolumeNameList);

View File

@ -0,0 +1,8 @@
#include <Windows.h>
#include <stdio.h>
int main(int argc, char** argv) {
puts("mxmaster.exe dummy hit");
while (1) Sleep(1000);
}

View File

@ -0,0 +1,216 @@
/*
Currently unimplemented:
- Changing the screen resoltuion to something very small (lol)
- The UI that shows "NOW LOADING"
*/
#include <Windows.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#define SYSTEM_USER "SystemUser"
#define MXSTARTUP "C:\\System\\Execute\\mxstartup.exe"
#define RETRIES 100
#define STR_INDIR(x) #x
#define STR(x) STR_INDIR(x)
/*
No debugger:
153815264b5839090b0d1c1a423c02241633130673071a1e38443912410b47380f213c1d
+ 2e0247311e162b666c6640393737724157001f56045b4b4f24333457335a26381f4c3349
= 'C:\Windows\System32\wbem\wmitemp.mof'
270a2a053b29042b261d1b22070d140c (wmitemp.mof)
+ 152c05381a141f494a48060223260d29 (key)
= '<6/=U=#tpe!$*3!5'
Has debugger:
d0b1c034a32243340505a343659517c121f0319583d205c593a690719604846000e062a6
+ 63f10541f0c201c0703022f332a13094b542f130c25491a1c280a65440831296e2563590
% 255 (not 256!)
= 34a3c57594e444f47535c53797374756d63323c546279667562737c5d68796f6e2379737
flip nibbles of each byte
= 'C:\\WINDOWS\\system32\\drivers\\mxio.sys'
9160e5c22392918371e43573f2b095b1 (mxio.sys)
+ 43368004f2a34211f4f12120b1b57151
% 255
= d49666c61636d39466d65693a4660703
flip nibbles of each byte
= 'Miflac=Ifme9Jfp0'
*/
#define PERFECT_RECREATION
#ifdef PERFECT_RECREATION
// C:\Windows\System32\wbem\wmitemp.mof (contains 270a2a053b29042b261d1b22070d140c)
// NOTE: On 64 bit windows this is going to be redirected to syswow64
#define PATH_NODEBUG_1 "153815264b5839090b0d1c1a423c02241633130673071a1e38443912410b47380f213c1d"
#define PATH_NODEBUG_2 "2e0247311e162b666c6640393737724157001f56045b4b4f24333457335a26381f4c3349"
// C:\WINDOWS\system32\drivers\mxio.sys (contains 9160e5c22392918371e43573f2b095b1)
// NOTE: On 64 bit windows this is going to be redirected to syswow64
#define PATH_DEBUG_1 "d0b1c034a32243340505a343659517c121f0319583d205c593a690719604846000e062a6"
#define PATH_DEBUG_2 "63f10541f0c201c0703022f332a13094b542f130c25491a1c280a65440831296e2563590"
#define NODEBUG_PSK "152c05381a141f494a48060223260d29"
#define DEBUG_PSK "43368004f2a34211f4f12120b1b57151"
#else
#define PASS_NODEBUG "Miflac=Ifme9Jfp0"
#define PASS_DEBUG "<6/=U=#tpe!$*3!5"
#endif
void reboot() {
puts("Starting the next hop failed.");
puts("We're not going to reboot, but mxprestartup normally would at this point.");
exit(1);
}
char* load_password(const char* path1, const char* path2, const char* psk, bool flip) {
char path[37];
path[36] = '\0';
char temp1[3] = { 0 };
char temp2[3] = { 0 };
char* pEnd;
for (int i = 0; i < 72; i += 2) {
temp1[0] = path1[i];
temp1[1] = path1[i + 1];
temp2[0] = path2[i];
temp2[1] = path2[i + 1];
uint8_t value = (strtol(temp1, &pEnd, 16) + strtol(temp2, &pEnd, 16)) % 0xff;
if (flip)
path[i >> 1] = ((value & 0xf0) >> 4) | ((value & 0x0f) << 4);
else
path[i >> 1] = value;
}
printf("Attempting to read key from %s\n", path);
FILE* key_file;
fopen_s(&key_file, path, "r");
if (!key_file) {
printf("! Failed to read file: %d\n", GetLastError());
return NULL;
}
char key2[32];
fread(key2, 1, 32, key_file);
fclose(key_file);
char* password = malloc(17);
password[16] = '\0';
for (int i = 0; i < 32; i += 2) {
temp1[0] = psk[i];
temp1[1] = psk[i + 1];
temp2[0] = key2[i];
temp2[1] = key2[i + 1];
uint8_t value = (strtol(temp1, &pEnd, 16) + strtol(temp2, &pEnd, 16)) % 0xff;
if (flip)
password[i >> 1] = ((value & 0xf0) >> 4) | ((value & 0x0f) << 4);
else
password[i >> 1] = value;
}
return password;
}
char* get_password() {
if (IsDebuggerPresent()) {
#ifdef PERFECT_RECREATION
return load_password(PATH_DEBUG_1, PATH_DEBUG_2, DEBUG_PSK, true);
#else
return PASS_DEBUG;
#endif
}
#ifdef PERFECT_RECREATION
return load_password(PATH_NODEBUG_1, PATH_NODEBUG_2, NODEBUG_PSK, false);
#else
return PASS_NODEBUG;
#endif
}
int main(int argc, char** argv) {
if (argc > 4) {
puts("Usage:");
printf(" %s\n", argv[0]);
printf(" %s <mxstartup.exe>\n", argv[0]);
printf(" %s <username> <password>\n", argv[0]);
printf(" %s <mxstartup.exe> <username> <password>\n", argv[0]);
exit(0);
}
PVOID old = NULL;
Wow64DisableWow64FsRedirection(&old);
BOOL spawned = FALSE;
STARTUPINFOW startup_info = {
.cb = 68,
.wShowWindow = SW_SHOW,
.dwFlags = STARTF_USESHOWWINDOW,
};
PROCESS_INFORMATION process = { 0 };
for (int i = 0; i < RETRIES; i++) {
char* password = argc == 3 ? argv[2] : argc == 4 ? argv[3] : get_password();
if (password) {
char* username = argc == 3 ? argv[1] : argc == 4 ? argv[2] : SYSTEM_USER;
char* binary = (argc == 2 || argc == 4) ? argv[1] : MXSTARTUP;
printf("Username: %s\n", username);
printf("Password: %s\n", password);
printf("Next hop: %s\n", binary);
size_t _;
wchar_t* wPassword = malloc((strlen(password) + 1) * (sizeof(wchar_t)));
wchar_t* wUser = malloc((strlen(username) + 1) * (sizeof(wchar_t)));
wchar_t* wBinary = malloc((strlen(binary) + 1) * (sizeof(wchar_t)));
mbstowcs_s(&_, wPassword, strlen(password) + 1, password, _TRUNCATE);
mbstowcs_s(&_, wUser, strlen(username) + 1, username, _TRUNCATE);
mbstowcs_s(&_, wBinary, strlen(binary) + 1, binary, _TRUNCATE);
spawned = CreateProcessWithLogonW(wUser, NULL, wPassword, 0, NULL, wBinary, HIGH_PRIORITY_CLASS, NULL, NULL,
&startup_info, &process);
free(wPassword);
if (spawned)
break;
else
puts("Failed to start next hop");
if (process.hProcess != NULL) {
CloseHandle(process.hProcess);
process.hProcess = NULL;
}
} else {
puts("Failed to get password");
}
Sleep(1000);
puts("------------------------");
printf("Retry %d\n", i + 1);
puts("------------------------");
}
if (process.hProcess != NULL) {
CloseHandle(process.hProcess);
process.hProcess = NULL;
}
if (!spawned) {
reboot();
}
return 0;
}

View File

@ -0,0 +1,410 @@
#include <Windows.h>
#include <shellapi.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include "ewfapi.h"
typedef enum {
MxError_Unknown = -1,
MxError_None = 0,
MxError_Ewf = 501,
MxError_Version = 502,
MxError_NoKeyFile = 503,
MxError_DiskAccessPrivilege = 504,
MxError_SystemMount = 505,
MxError_MxMaster = 507,
MxError_SBR = 511,
MxError_SysKeyDelete = 512,
} MxError_t;
typedef enum {
Init = 0,
CheckEwf = 1,
EwfDisabled = 2,
GetSBR = 3,
NormalBoot = 4,
SystemUpdate2 = 5,
SystemUpdate3 = 6,
Done = 7,
} StartupStep_t;
#define VERSION_BUFFER 256
#define VERSION_FILE "C:\\System\\SystemVersion.txt"
#define DEFAULT_VERSION_FILE "C:\\System\\DefaultSystemVersion.txt"
#define SYSTEM_KEY_FILE "Z:\\SystemKeyFile"
#define OS_UPDATE_KEY_FILE "Z:\\UpdateKeyFile"
#define SYSTEM_VOLUME "C:\\System\\Execute\\System"
#define SYSTEM_MOUNT "S:"
#define NEXT_HOP_CWD SYSTEM_MOUNT "\\"
#define NEXT_HOP_MXMASTER NEXT_HOP_CWD "mxmaster.exe"
#define CACLS_REMPERM_EXECUTE "cacls c:\\system\\execute /t /e /p AppUser:N"
#define CACLS_REMPERM_Z "cacls z:\\ /t /e /p appuser:N"
#define CACLS_REMPERM_S "cacls s:\\ /t /e /p appuser:N"
// Rather than implement these sums in code, we're just going to use the
// presummed versions, because we have nothing to gain by obfuscating this.
// These two sum to TC_PASSWORD
#define TC_PASSWORD_1 "3d550a335d2557055d2b3d1444153348"
#define TC_PASSWORD_2 "36105d2e0b3c1b5f1336365f335a3f1c"
#define TC_PASSWORD "segahardpassword"
// These two sum to SYSTEM_KEYFILE_ADS
#define SYSTEM_KEYFILE_1 "041443255b204a3f054d1b4c352a22292f211b29440e1237591f2e49375d093967614d"
#define SYSTEM_KEYFILE_2 "3f26192e1e532a26680f2a2c3039534b363b2923082c41421a5537241408700d020b18"
#define SYSTEM_KEYFILE_ADS "C:\\System\\Execute\\DLL:SystemKeyFile"
// These two sum to OS_UPDATE_ADS
#define OS_UPDATE_KEYFILE_1 "4019582c56283006300b40042110143d603b3d3b1d012b5c0d5423152235163f624a43"
#define OS_UPDATE_KEYFILE_2 "03210427234b445f3d51057444536137052107112f392a14570d515029306307072222"
#define OS_UPDATE_KEYFILE_ADS "C:\\System\\Execute\\DLL:UpdateKeyFile"
int LOG_EN_PLATFORM = 0;
#define MX_LOG(...) log(__FUNCTION__, __LINE__, __VA_ARGS__)
void log(char* function, unsigned int line_number, char* fmt, ...) {
va_list args;
va_start(args, fmt);
printf("%s: Line%d ", function, line_number);
vprintf(fmt, args);
va_end(args);
}
// TODO: These two
bool InitGraphics() { return true; }
bool PopulateEventInfo() { return true; }
// TODO: These three
void AppendAsterisk(void){};
void setStrForStep2(void){};
void setStrForStep3(void){};
int osuExecProcess(char* command) {
PROCESS_INFORMATION processInformation = { 0 };
STARTUPINFOA startupInfo = {
.cb = 68,
.dwFlags = STARTF_USESHOWWINDOW,
.wShowWindow = SW_HIDE,
};
if (command == NULL) return -150;
BOOL spanwed = CreateProcessA(NULL, command, NULL, NULL, 0, 0, NULL, NULL, &startupInfo, &processInformation);
DWORD wait = WaitForSingleObject(processInformation.hProcess, INFINITE);
int ret;
if (!spanwed) {
ret = -140;
} else if (wait == WAIT_OBJECT_0) {
DWORD exitCode;
GetExitCodeProcess(processInformation.hProcess, &exitCode);
ret = exitCode == 0 ? 0 : -141;
} else {
ret = -141;
}
CloseHandle(processInformation.hProcess);
CloseHandle(processInformation.hThread);
return ret;
}
/* Read a version from a text file */
bool GetVersionText(char* version, char* path) {
char buffer[VERSION_BUFFER];
FILE* file;
memset(buffer, 0, sizeof buffer);
if (fopen_s(&file, path, "r") || file == NULL) {
MX_LOG("Error : GetVersionText error path = %s\n", path);
return false;
}
fgets(buffer, sizeof buffer, file);
fclose(file);
strncpy_s(version, VERSION_BUFFER, buffer, VERSION_BUFFER);
return true;
}
/* Get the currently running version of the system */
bool GetCurrentVersion(char* version) { return GetVersionText(version, VERSION_FILE); }
/* Get the default version of the system */
bool GetDefaultVersion(char* version) { return GetVersionText(version, DEFAULT_VERSION_FILE); }
/* Mount the system volume */
bool MountSystemVolume(void) {
char command[256];
snprintf(command, sizeof command, "TrueCrypt /p %s /k %s /v %s /l %s /w /s /q", TC_PASSWORD, SYSTEM_KEY_FILE,
SYSTEM_VOLUME, SYSTEM_MOUNT);
int ret = osuExecProcess(command);
if (ret == 0) return true;
MX_LOG("Error : osuExecProcess error. ret = %d\n", ret);
return false;
};
/* Try to mount the system volume with up to 100 retries */
bool TryMountSystemVolume(void) {
for (int i = 0; i < 100; i++) {
if (MountSystemVolume()) return true;
Sleep(200);
}
return false;
}
/* Copies the file at src to dst */
bool GetKeyFile(LPCSTR src, LPCSTR dst) {
HANDLE file_1 = CreateFileA(src, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
if (file_1 == INVALID_HANDLE_VALUE) {
MX_LOG("CreaterFile Src error\n");
return false;
}
HANDLE file_2 = CreateFileA(dst, GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file_2 == INVALID_HANDLE_VALUE) {
CloseHandle(file_1);
MX_LOG("Error : CreateFile Dst error\n");
return false;
}
CHAR readBuffer[260];
DWORD bytesRead;
if (!ReadFile(file_1, readBuffer, 255, &bytesRead, NULL)) {
CloseHandle(file_1);
CloseHandle(file_2);
MX_LOG("Error : ReadFile error\n");
return false;
}
readBuffer[bytesRead] = '\0';
DWORD written;
bool ret = WriteFile(file_2, readBuffer, strlen(readBuffer), &written, NULL) != 0;
if (!ret) MX_LOG("Error : WriteFile error\n");
CloseHandle(file_1);
CloseHandle(file_2);
return ret;
}
bool GetSystemKeyFile() { return GetKeyFile(SYSTEM_KEYFILE_ADS, SYSTEM_KEY_FILE); };
bool GetOOUpdateKeyFile() { return GetKeyFile(OS_UPDATE_KEYFILE_ADS, OS_UPDATE_KEY_FILE); };
bool SetDiskAccessPrivilege() {
int i;
for (i = 0; i < 100; i++) {
if (osuExecProcess(CACLS_REMPERM_EXECUTE) != -140) break;
Sleep(200);
}
if (i == 100) {
MX_LOG("Error : osuExecProcess error\n");
return false;
}
for (i = 0; i < 100; i++) {
if (osuExecProcess(CACLS_REMPERM_Z) != -140) break;
Sleep(200);
}
if (i == 100) {
MX_LOG("Error : osuExecProcess error\n");
return false;
}
for (i = 0; i < 100; i++) {
if (osuExecProcess(CACLS_REMPERM_S) != -140) break;
Sleep(200);
}
if (i == 100) {
MX_LOG("Error : osuExecProcess error\n");
return false;
}
return true;
};
bool ExecuteMxMaster() {
HINSTANCE ret = ShellExecuteA(NULL, NULL, NEXT_HOP_MXMASTER, NULL, NEXT_HOP_CWD, 0);
if ((int)ret < 33) {
MX_LOG("Error : ShellExecute ret = %d\n", ret);
return false;
}
return true;
};
bool MxInitStartup(int* diskNumber) { return false; }
bool CheckEwfState(EWF_STATE* state) {
// TODO: Consider a better implementation of this!
*state = EWF_ENABLED; // Nothing to do, boot the system
// *state = EWF_DISABLED; // We're in the middle of an update, so finish
return true;
}
bool GetSBRSlotOSState(int diskNumber, int* updateState) { return false; };
bool SystemUpdateStep2(int diskNumber) { return false; }
bool SystemUpdateStep3(int diskNumber) { return false; }
MxError_t NormalBootStep(void) {
AppendAsterisk();
if (!GetSystemKeyFile()) return MxError_NoKeyFile;
AppendAsterisk();
if (!TryMountSystemVolume()) return MxError_SystemMount;
AppendAsterisk();
if (!DeleteFileA(SYSTEM_KEY_FILE)) return MxError_SysKeyDelete;
AppendAsterisk();
if (!SetDiskAccessPrivilege()) return MxError_DiskAccessPrivilege;
AppendAsterisk();
if (!ExecuteMxMaster()) return MxError_MxMaster;
return MxError_None;
}
int DoStartup() {
StartupStep_t step = Init;
MxError_t error = MxError_None;
int diskNumber = 0;
while (step != Done) {
printf("Step: %d (%d)\n", step, error);
switch (step) {
case Init:
if (!MxInitStartup(&diskNumber))
step = CheckEwf;
else
step = Done;
break;
case CheckEwf: {
AppendAsterisk();
EWF_STATE state;
if (!CheckEwfState(&state)) {
error = MxError_Ewf;
step = Done;
break;
}
if (state == EWF_ENABLED)
step = NormalBoot;
else
step = EwfDisabled;
break;
}
case EwfDisabled: {
char versionString[VERSION_BUFFER];
char defaultVersionString[VERSION_BUFFER];
if (!GetCurrentVersion(versionString) || !GetDefaultVersion(defaultVersionString)) {
error = MxError_Version;
step = Done;
break;
}
if (strcmp(versionString, defaultVersionString) == 0)
step = GetSBR;
else
step = SystemUpdate3;
break;
}
case GetSBR: {
int updateState;
AppendAsterisk();
if (!GetSBRSlotOSState(diskNumber, &updateState)) {
error = MxError_SBR;
step = Done;
break;
}
if (updateState == 2)
step = SystemUpdate2;
else
step = SystemUpdate3;
break;
}
case NormalBoot:
error = NormalBootStep();
step = Done;
break;
case SystemUpdate2:
setStrForStep2();
error = SystemUpdateStep2(diskNumber);
step = Done;
break;
case SystemUpdate3:
setStrForStep3();
error = SystemUpdateStep3(diskNumber);
step = Done;
break;
default:
error = MxError_Unknown;
step = Done;
break;
}
}
return error;
}
int setEventSource(char** source) {
// if (WIN_EVENT->ready == 0) {
// return -3;
// }
// if (source == (char**)0x0) {
// return -2;
// }
// _memcpy_s(&WIN_EVENT->eventSource, 16, source, 16);
return 0;
}
void setLogFn(void* log_fn) {
// LOG_FUN = log_fn;
return;
}
int __cdecl logToEventlog(LPCSTR msg) {
//
return 0;
}
bool ExitGraphics(void) {
// int iVar1;
// iVar1 = FUN_0040b9e0((int)&hInstance);
// return iVar1 != 0;
return true;
}
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) {
PVOID old = NULL;
Wow64DisableWow64FsRedirection(&old);
if (!InitGraphics(hInstance, nShowCmd)) {
MX_LOG("Error : InitGraphics failed.\n");
}
if (!PopulateEventInfo()) {
LOG_EN_PLATFORM = 1;
char* mxstartup = "mxstartup";
setEventSource(&mxstartup);
setLogFn(logToEventlog);
}
MxError_t err = DoStartup();
if (!err) {
if (!ExitGraphics()) {
MX_LOG("Error : ExitGraphics failed.\n");
}
// FUN_00408810();#
Sleep(1000000);
return 0;
}
printf("Fatal: %04d\n", err);
// while (1) {
// FUN_00424640();
// Sleep(100000);
//}
return 0;
}
int main() { return WinMain(NULL, NULL, NULL, 0); }

View File

@ -0,0 +1,5 @@
#include <stdio.h>
int main(int argc, char** argv) {
puts("TrueCrypt.exe dummy hit");
}

View File

@ -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_s(SEED_BUF_LEN, sSize, sizeof sSize, 10);
pcpaAddSendPacket(stream, "size", sSize);
}

View File

@ -106,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_s(CA_CERT_LEN, sSize, sizeof sSize, 10);
pcpaAddSendPacket(stream, "size", sSize);
}

View File

@ -1,14 +1,6 @@
dependencies = []
link_with = [inih.get_variable('lib_inih')]
link_with = [inih.get_variable('lib_inih'), libpcp]
# Depending on how we're getting access to libpcp, we need some extra work here
if libpcp_is_static
link_with += libpcp
else
link_with += amlib
dependencies += libpcp
dependencies += meson.get_compiler('c').find_library('ws2_32')
endif
rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico)
executable(

View File

@ -22,7 +22,8 @@ int mxkInit() {
}
void log_callback(struct pcpa* stream, void* data) {
FILE* log_file = fopen("pcp.log", "a");
FILE* log_file;
fopen_s(&log_file, "pcp.log", "a");
if (log_file != NULL) {
fprintf(log_file, "%s\n", (char*)data);
fclose(log_file);

View File

@ -2,7 +2,7 @@
#include "string.h"
void print_patches(patches_t* patches, char* filename) {
for (int i = 0; i < patches->nopatchsets; i++) {
for (size_t i = 0; i < patches->nopatchsets; i++) {
patchset_t* patchset = patches->patchsets[i];
bool skip = patchset->name != NULL && strcmp(patchset->name, filename) != 0;
@ -10,8 +10,8 @@ void print_patches(patches_t* patches, char* filename) {
printf("Patch: %s (%s)\n", patchset->name, skip ? "skipped" : patchset->apply ? "applied" : "unapplied");
printf("- %s\n", patchset->description);
if (!skip) {
for (int i = 0; i < patchset->nopatches; i++) {
printf(":: %d bytes at %08x\n", patchset->patches[i].count, patchset->patches[i].offset);
for (size_t j = 0; j < patchset->nopatches; j++) {
printf(":: %d bytes at %08x\n", patchset->patches[j].count, patchset->patches[j].offset);
}
}
puts("======================");
@ -29,14 +29,14 @@ void apply_patches(patches_t* patches, char* filename) {
fseek(fp, 0L, SEEK_END);
size_t sz = ftell(fp);
for (int i = 0; i < patches->nopatchsets; i++) {
for (size_t i = 0; i < patches->nopatchsets; i++) {
patchset_t* patchset = patches->patchsets[i];
if (patchset->name != NULL && strcmp(patchset->name, filename) != 0) {
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 (patch.offset + patch.count > sz) {
fprintf(stderr, "E: Patch %s[%d] outside file bounds\n", patchset->name, j);
@ -45,15 +45,15 @@ void apply_patches(patches_t* patches, char* filename) {
fseek(fp, patch.offset, SEEK_SET);
bool matches_from = true;
bool matches_to = true;
for (int i = 0; i < patch.count; i++) {
for (size_t k = 0; k < patch.count; k++) {
unsigned char seen;
if (!fread(&seen, 1, 1, fp)) {
matches_from = false;
matches_to = false;
break;
}
if (seen != patch.from[i]) matches_from = false;
if (seen != patch.to[i]) matches_to = false;
if (seen != patch.from[k]) matches_from = false;
if (seen != patch.to[k]) matches_to = false;
if (!(matches_from || matches_to)) break;
}

View File

@ -1,6 +0,0 @@
#include "stdio.h"
int main() {
puts("Hello world");
return 0;
}

View File

@ -1,7 +0,0 @@
executable(
'micetest',
win_subsystem: subsystem,
sources: [
'main.c',
],
)

View File

@ -0,0 +1,29 @@
executable(
'micedump',
win_subsystem: subsystem,
sources: [
'micedump.c',
],
link_with: [
amlib
],
)
executable(
'micetinker',
win_subsystem: subsystem,
sources: [
'micetinker.c',
],
link_with: [
amlib
],
)
executable(
'micemonitor',
win_subsystem: subsystem,
sources: [
'micemonitor.c',
],
)

View File

@ -0,0 +1,271 @@
#include <Windows.h>
#include <setupapi.h>
#include <shellapi.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "Setupapi.lib")
#include "../lib/am/amEeprom.h"
#define OpenDriver(x) \
CreateFileA("\\\\.\\" x, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)
#define RULE "-----------------------------------------"
#define SECTION_HEAD(x) \
puts(""); \
puts(RULE); \
puts(x); \
puts(RULE); \
puts("");
typedef struct {
uint64_t physAddr;
DWORD dType;
DWORD size;
} columba_request_t;
void scan_for_dmi(HANDLE columba, DWORD *stable_addr) {
DWORD bytesOut;
// short *stable_len;
columba_request_t request;
unsigned char readBuf[0x8010];
uint64_t search_addr = 0xf0000;
while (1) {
request.physAddr = search_addr;
request.dType = 1;
request.size = sizeof readBuf;
BOOL succ = DeviceIoControl(columba, (DWORD)IOCTL_COLUMBA_READ, &request,
sizeof request, &readBuf, sizeof readBuf, &bytesOut, NULL);
if (succ && bytesOut == sizeof readBuf) {
for (unsigned int offset = 0; offset < 0x8008; offset++) {
if (readBuf[offset] == '_' && readBuf[offset + 1] == 'D' &&
readBuf[offset + 2] == 'M' && readBuf[offset + 3] == 'I' &&
readBuf[offset + 4] == '_') {
*stable_addr = *(DWORD *)&readBuf[offset + 8];
return;
}
}
}
search_addr += 0x7ff0;
if (search_addr > 0xfffdf) return;
}
}
BOOL dump_columba() {
SECTION_HEAD("columba");
HANDLE columba = OpenDriver("columba");
if (columba == INVALID_HANDLE_VALUE) return FALSE;
DWORD stable_addr = 0;
scan_for_dmi(columba, &stable_addr);
if (stable_addr == 0) {
CloseHandle(columba);
return FALSE;
}
columba_request_t request;
unsigned char readBuf[0x10000];
printf("Found DMI at: %d\n", stable_addr);
request.physAddr = stable_addr;
request.dType = 1;
if (stable_addr + 0x10000 < 0x100001) {
request.size = 0x10000;
} else {
request.size = 0x100000 - stable_addr;
}
DWORD bytesReturned;
BOOL s = DeviceIoControl(columba, (DWORD)IOCTL_COLUMBA_READ, &request, sizeof request,
readBuf, sizeof readBuf, &bytesReturned, NULL);
if (!s || bytesReturned != sizeof readBuf) {
CloseHandle(columba);
return FALSE;
}
puts("DMI read sucessful.");
FILE *dmi;
fopen_s(&dmi, "dmi.bin", "wb");
fwrite(readBuf, 1, sizeof readBuf, dmi);
fclose(dmi);
puts(" -> Written to dmi.bin");
CloseHandle(columba);
return TRUE;
}
BOOL dump_eeprom() {
SECTION_HEAD("mxSMBus");
HANDLE mxsmbus = amEepromCreateDeviceFile(&MXSMBUS_GUID, NULL, 0);
if (mxsmbus == INVALID_HANDLE_VALUE) return FALSE;
DWORD _dummy;
DWORD version;
DeviceIoControl(mxsmbus, (DWORD)IOCTL_MXSMBUS_GET_VERSION, NULL, 0, &version, sizeof version,
&_dummy, NULL);
printf("mxSMBus version: %08x\n", version);
BYTE data[0x20];
for (WORD reg = 0; reg < 256; reg++) {
if (!amEepromReadBlock(mxsmbus, reg & 0xFF, 0x20, data)) continue;
printf("%02x: ", reg);
for (int i = 0; i < 0x20; i++) printf("%02x ", data[i]);
puts("");
}
CloseHandle(mxsmbus);
return TRUE;
}
unsigned char sram_buf[1024 * 2048];
BOOL dump_sram() {
SECTION_HEAD("mxSRAM");
HANDLE mxsram = OpenDriver("mxsram");
if (mxsram == INVALID_HANDLE_VALUE) return FALSE;
DWORD _dummy;
BOOL s;
DWORD version;
s = DeviceIoControl(mxsram, (DWORD)IOCTL_MXSRAM_PING, NULL, 0, &version, sizeof version,
&_dummy, NULL);
if (!s) {
CloseHandle(mxsram);
return FALSE;
}
printf("mxSRAM version: %04x\n", version);
DISK_GEOMETRY geom;
s = DeviceIoControl(mxsram, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &geom, sizeof geom, &_dummy,
NULL);
if (!s) {
CloseHandle(mxsram);
return FALSE;
}
puts("mxSRAM geometry:");
printf(":: Cylinders: %lld\n", geom.Cylinders.QuadPart);
printf(":: MediaType: %d\n", geom.MediaType);
printf(":: TracksPerCylinder: %d\n", geom.TracksPerCylinder);
printf(":: SectorsPerTrack: %d\n", geom.SectorsPerTrack);
printf(":: BytesPerSector: %d\n", geom.BytesPerSector);
DWORD ssize;
s = DeviceIoControl(mxsram, (DWORD)IOCTL_MXSRAM_GET_SECTOR_SIZE, NULL, 0, &ssize, sizeof ssize,
&_dummy, NULL);
if (!s) {
CloseHandle(mxsram);
return FALSE;
}
printf(":: Sector Size: %d\n", ssize);
DWORD read;
if (!ReadFile(mxsram, sram_buf, sizeof sram_buf, &read, NULL)) {
CloseHandle(mxsram);
return FALSE;
}
printf("Read %d bytes\n", read);
if (read != sizeof sram_buf) puts("W: incomplete");
FILE *sram;
fopen_s(&sram, "sram.bin", "wb");
fwrite(sram_buf, 1, sizeof sram_buf, sram);
fclose(sram);
puts(" -> Written to sram.bin");
CloseHandle(mxsram);
return TRUE;
}
BYTE superio_read(HANDLE mxsuperio, BYTE chip, BYTE device, BYTE index) {
DWORD _dummy;
BYTE payload[4] = { chip, device, index, 0 };
DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_READ, payload, sizeof payload, payload,
sizeof payload, &_dummy, NULL);
return payload[3];
}
#define SUPERIO_LD_FDC 0
#define SUPERIO_LD_PARALLEL 1
#define SUPERIO_LD_UART_A 2
#define SUPERIO_LD_UART_B 3
#define SUPERIO_LD_KEYBOARD 5
#define SUPERIO_LD_UART_C 6
#define SUPERIO_LD_GPIO34 7
#define SUPERIO_LD_WDTO_PLED_GPIO56 8
#define SUPERIO_LD_GPIO12_SUSLED 9
#define SUPERIO_LD_ACPI 10
#define SUPERIO_LD_HWMON 11
#define SUPERIO_LD_PECI_SST 12
#define SUPERIO_LD_UART_D 13
#define SUPERIO_LD_UART_E 14
#define SUPERIO_LD_UART_F 15
BOOL dump_superio() {
SECTION_HEAD("mxSuperIO");
HANDLE mxsuperio = OpenDriver("mxsuperio");
if (mxsuperio == INVALID_HANDLE_VALUE) return FALSE;
BOOL s;
DWORD _dummy;
DWORD version;
s = DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_PING, NULL, 0, &version, sizeof version,
&_dummy, NULL);
if (!s) {
CloseHandle(mxsuperio);
return FALSE;
}
printf("mxSuperIO version: %08x\n", version);
BYTE ver_msb;
ver_msb = superio_read(mxsuperio, 0, SUPERIO_LD_FDC, 0x20);
if (ver_msb != 0xff) {
puts(":: Chip 0 present");
printf(" -> Version: %02x%02x\n", ver_msb,
superio_read(mxsuperio, 0, SUPERIO_LD_FDC, 0x21));
} else
puts(":: Chip 0 unpopulated");
ver_msb = superio_read(mxsuperio, 1, SUPERIO_LD_FDC, 0x20);
if (ver_msb != 0xff) {
puts(":: Chip 1 present");
printf(" -> Version: %02x%02x\n", ver_msb,
superio_read(mxsuperio, 1, SUPERIO_LD_FDC, 0x21));
} else
puts(":: Chip 1 unpopulated");
puts(":: Super lazy dump of chip 1, bank 0:");
for (uint8_t reg = 0; reg < 0xff; reg++) {
unsigned char packet[3] = { 1, reg, 0 };
DeviceIoControl(mxsuperio, (DWORD)IOCTL_MXSUPERIO_HWMONITOR_LPC_READ, &packet,
sizeof packet, &packet, sizeof packet, &_dummy, NULL);
printf(" -> %02x: %02x\n", reg, packet[2]);
}
CloseHandle(mxsuperio);
return TRUE;
}
int main() {
// if (!dump_columba()) {
// printf("Failed to dump DMI: %03x\n", GetLastError());
// }
if (!dump_eeprom()) {
printf("Failed to dump EEPROM: %03x\n", GetLastError());
}
// if (!dump_sram()) {
// printf("Failed to dump SRAM: %03x\n", GetLastError());
// }
// if (!dump_superio()) {
// printf("Failed to dump SuperIO: %03x\n", GetLastError());
// }
return 0;
}

View File

@ -0,0 +1,14 @@
#include <Windows.h>
#include <stdio.h>
#define P2A_PATH "C:\\ProgramData\\boost_interprocess\\ALLNetComP2A"
#define A2P_PATH "C:\\ProgramData\\boost_interprocess\\ALLNetComA2P"
int main(int argc, char* argv) {
FILE* f;
fopen_s(&f, "./test.txt", "w");
fprintf(f, "count: %d", argc);
fclose(f);
return 0;
}

View File

@ -0,0 +1,57 @@
#include <Windows.h>
#include <setupapi.h>
#include <shellapi.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#pragma comment(lib, "Setupapi.lib")
#include "../lib/am/amEeprom.h"
BOOL change_region(BYTE region) {
HANDLE mxsmbus = amEepromCreateDeviceFile(&MXSMBUS_GUID, NULL, 0);
if (mxsmbus == INVALID_HANDLE_VALUE) return FALSE;
BYTE data[0x20];
if (!amEepromReadBlock(mxsmbus, 0, sizeof data, data)) {
printf("Failed to read block 0");
goto fail;
}
puts("Original content:");
for (int i = 0; i < 0x20; i++) printf("%02x ", data[i]);
puts("");
data[12] = region;
amEepromRepairChecksum(data);
amEepromWriteBlock(mxsmbus, 0, sizeof data, data);
amEepromReadBlock(mxsmbus, 0, sizeof data, data);
puts("Tinkered content:");
for (int i = 0; i < 0x20; i++) printf("%02x ", data[i]);
puts("");
CloseHandle(mxsmbus);
return TRUE;
fail:
CloseHandle(mxsmbus);
return FALSE;
}
int main(int argc, char** argv) {
if (argc != 2) {
printf("Usage: %s <region>\n", argv[0]);
return -1;
}
BYTE region = argv[1][0] - '0';
printf("Changing to region: %d\n", region);
if (!change_region(region)) {
printf("Failed to change region: %03x", GetLastError());
} else {
printf("Region changed!");
}
return 0;
}

View File

@ -0,0 +1,9 @@
[
{
"name": "LOG_EN_AMSRAM",
"at": "00465e54",
"from": "00000000",
"to": "01000000",
"count": 4
}
]

View File

@ -47,5 +47,12 @@
"binary_name": "ORIG_mxsegaboot.exe",
"apply": true,
"patches_file": "mxsegaboot.patch.json"
},
{
"name": "mxgfetcher logs",
"description": "Enable logging facilities",
"binary_name": "mxgfetcher.exe",
"apply": true,
"patches_file": "mxgfetcher.patch.json"
}
]