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/ builddir/
srcdir/ srcdir/
.vscode/ .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 .PHONY: dist
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/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/lib/libpcp\libpcp.lib" "$(DIST_DIR)/libpcp.lib"
@copy /Y "$(BUILD_DIR_32)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice86.exe" @copy /Y "$(BUILD_DIR_32)/src/micetools/launcher\mice.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/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_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\system "$(DIST_DIR)\system/*"
@xcopy /E /H /C /R /Q /Y src\tools "$(DIST_DIR)\tools/*" @xcopy /E /H /C /R /Q /Y src\tools "$(DIST_DIR)\tools/*"
@xcopy /E /H /C /R /Q /Y src\patches "$(DIST_DIR)\patches/*" @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: [ project('micetools', 'c', default_options: [
'buildtype=minsize', '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', # 'b_vscrt=static_from_buildtype',
'warning_level=2', 'warning_level=3',
]) ])
winxp = false winxp = false
@ -15,6 +15,22 @@ endif
add_project_arguments( add_project_arguments(
'/DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need '/DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need
'/D_WIN32_WINNT=_WIN32_WINNT_WINXP', # hahahahaha I hate it '/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', language: 'c',
) )
if winxp 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; return TRUE;
} }
BOOL DevWriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, BOOL DevWriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPOVERLAPPED lpOverlapped) { LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
if (nNumberOfBytesToWrite > 0xffff) return FALSE; if (nNumberOfBytesToWrite > 0xffff) return FALSE;
// Ignore overflow // Ignore overflow
ringbuf_write(&((com_device_t*)file)->in, lpBuffer, nNumberOfBytesToWrite & 0xffff); ringbuf_write(&((com_device_t*)file)->in, lpBuffer, nNumberOfBytesToWrite & 0xffff);
if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nNumberOfBytesToWrite; if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nNumberOfBytesToWrite;
return TRUE; return TRUE;
} }
BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPOVERLAPPED lpOverlapped) { LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
if (nNumberOfBytesToRead > 0xffff) return FALSE; if (nNumberOfBytesToRead > 0xffff) return FALSE;
// Make sure we have at least one byte to return // 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) { if (read != 0) {
// log_info("drf", "%d", read); // log_info("drf", "%d", read);
// for (int i = 0; i < read; i++) { // for (int i = 0; i < read; i++) {
// printf("%02x ", ((unsigned char*)lpBuffer)[i]); // printf("%02x ", ((LPBYTE)lpBuffer)[i]);
// } // }
// puts(""); // puts("");
} }
return TRUE; 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) { short comdev_read(com_device_t* com, unsigned char* buffer, short bytes) {
return ringbuf_read(&com->in, buffer, 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); bool ret = ringbuf_write(&com->out, buffer, bytes);
SetEvent(com->event); SetEvent(com->event);
return ret; return ret;
} }
short comdev_available(com_device_t* com) { return ringbuf_available(&com->in); } 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) { void com_device_thread(com_device_t* com, FnComDeviceThread* thread) {
com->thread = CreateThread(NULL, 0, thread, com, 0, NULL); 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_file(file);
hook_com(com); hook_com(com);
free(com->virtual_handle);
com->virtual_handle = file->virtual_handle;
return hook; return hook;
} }

View File

@ -1,6 +1,6 @@
#pragma once #pragma once
#include "hooks/com.h"
#include "common.h" #include "common.h"
#include "hooks/com.h"
#include "hooks/files.h" #include "hooks/files.h"
typedef struct com_device { typedef struct com_device {
@ -13,11 +13,42 @@ typedef struct com_device {
HANDLE thread; HANDLE thread;
} com_device_t; } 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); 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); 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); 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); void com_device_thread(com_device_t* com, FnComDeviceThread* thread);
com_device_t* new_com_device(BYTE port); com_device_t* new_com_device(BYTE port);

View File

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

View File

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

View File

@ -4,5 +4,6 @@
void install_led_bd(); void install_led_bd();
void install_touch_bd(); void install_touch_bd();
void install_aime_bd();
void install_devices(); 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; BYTE op;
} rs232c_recv_head_t; } rs232c_recv_head_t;
BYTE extra[0xff];
static DWORD WINAPI led_bd_thread(com_device_t* dev) { static DWORD WINAPI led_bd_thread(com_device_t* dev) {
log_warning("led_bd", "%ls woke up", dev->com->wName); log_warning("led_bd", "%ls woke up", dev->com->wName);
while (1) { while (1) {
@ -81,9 +82,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
// Sleep(100); // Sleep(100);
continue; continue;
} }
comdev_read(dev, (char*)&head, sizeof head); comdev_read(dev, (unsigned char*)&head, sizeof head);
unsigned char* extra = malloc(head.length);
comdev_read(dev, extra, head.length); comdev_read(dev, extra, head.length);
// log_info("led_bd", "Bound %02x->%02x", head.src, head.dst); // 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) { switch (head.op) {
case 0x01: case 0x01:
log_warning("led_bd", "01"); 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 // syn dst src len sts op. rep chk
break; break;
case 0x10: case 0x10:
log_warning("led_bd", "10"); 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 // syn dst src len sts op. rep chk
break; break;
@ -107,7 +106,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
COLOURS[extra[0]][2] = extra[3]; COLOURS[extra[0]][2] = extra[3];
log_warning("led_bd", "31: %02x = (%02x %02x %02x)", extra[0], extra[1], extra[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 // syn dst src len sts op. rep chk
break; break;
case 0x32: case 0x32:
@ -120,13 +119,13 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
COLOURS[i][2] = extra[5]; 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 // syn dst src len sts op. rep chk
break; break;
case 0x33: case 0x33:
log_warning("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3], 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]); 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 // syn dst src len sts op. rep chk
COLOURS[extra[0]][0] = extra[extra[5]]; COLOURS[extra[0]][0] = extra[extra[5]];
COLOURS[extra[0]][1] = extra[extra[6]]; COLOURS[extra[0]][1] = extra[extra[6]];
@ -135,7 +134,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
case 0x39: case 0x39:
log_warning("led_bd", "39: %02x %02x %02x", extra[0], extra[1], extra[2]); 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 // syn dst src len sts op. rep chk
COLOURS[9][0] = extra[0]; COLOURS[9][0] = extra[0];
@ -144,18 +143,18 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
break; break;
case 0x3b: case 0x3b:
log_warning("led_bd", "3b"); 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 // syn dst src len sts op. rep chk
break; break;
case 0x3c: case 0x3c:
log_warning("led_bd", "3c (I am %ls)", dev->com->wName); 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 // syn dst src len sts op. rep chk
break; break;
case 0x3f: case 0x3f:
log_warning("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3], 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]); 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 // syn dst src len sts op. rep chk
break; break;
@ -163,14 +162,14 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
// extra[0] goes from 0 to 7 // extra[0] goes from 0 to 7
// Could this be some sort of calibration for the buttons? // Could this be some sort of calibration for the buttons?
log_warning("led_bd", "7c: %02x", extra[0]); 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 // \/ 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 // syn dst src len sts op. rep --- chk
break; break;
case 0x7b: case 0x7b:
log_warning("led_bd", "7b: %02x %02x %02x", extra[0], extra[1], extra[2]); 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 // syn dst src len sts op. rep chk
break; 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); log_error("led_bd", "Unknown op %02x (%d)", head.op, head.length - 1);
break; break;
} }
free(extra);
} }
} }
@ -200,13 +197,13 @@ void led_overlay(IDirect3DDevice9* dev) {
GetCursorPos(&cursor); GetCursorPos(&cursor);
// log_info("led_overlay", "x: %d, y: %d", cursor.x, cursor.y); // 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, // log_info("led_overlay", "x%: %f, y%: %f", (float)cursor.x / (float)rect.right,
(float)(cursor.y - 26) / (float)rect.bottom); // (float)(cursor.y - 26) / (float)rect.bottom);
} }
for (unsigned char i = 0; i < 10; i++) { for (unsigned char i = 0; i < 10; i++) {
int x = rect.right * positions[i][0]; int x = (int)(rect.right * positions[i][0]);
int y = rect.bottom * positions[i][1]; 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]); 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', '_devices.c',
'led_bd.c', 'led_bd.c',
'touch_bd.c', 'touch_bd.c',
'aime_bd.c',
) )

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "../hooks/_hooks.h" #include "../hooks/_hooks.h"
#include "../common.h" #include "../common.h"
#include "../../lib/am/amEeprom.h"
FnDeviceIoControl mxhwreset_DeviceIoControl; FnDeviceIoControl mxhwreset_DeviceIoControl;
void setup_mxhwreset(); void setup_mxhwreset();
@ -22,6 +23,3 @@ void setup_mxsuperio();
FnDeviceIoControl columba_DeviceIoControl; FnDeviceIoControl columba_DeviceIoControl;
void setup_columba(); 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; short index = 0;
bool escape = false; bool escape = false;
for (short i = 0; i < length; i++) { for (short i = 0; i < length; i++) {
@ -64,12 +64,13 @@ short jvs_unpad(char* paddedData, short length, char* unpaddedData) {
return index; 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; short index = 0;
for (short i = 0; i < length; i++) { for (short i = 0; i < length; i++) {
if (i > paddedMax) return -1; 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++] = JVS_MARK;
paddedData[index++] = unpaddedData[i] - 1; paddedData[index++] = unpaddedData[i] - 1;
} else { } 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"; 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); unsigned char* inData = malloc(inCount);
inCount = jvs_unpad(paddedIn, inCount, inData); inCount = jvs_unpad(paddedIn, inCount, inData);
unsigned char* response = malloc(maxOut); 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; unsigned char sum = 0;
for (int i = 1; i < inCount - 1; i++) sum += inData[i]; for (int i = 1; i < inCount - 1; i++) sum += inData[i];
if (sum != inData[inCount - 1]) { 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; status = JVS_STATUS_SUM;
goto jvs_exchange_error; goto jvs_exchange_error;
} }
@ -202,7 +205,7 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
break; break;
case JVS_CMD_RECEIVE_MAIN_ID: case JVS_CMD_RECEIVE_MAIN_ID:
unsigned char tempRead = -1; unsigned char tempRead = 0xff;
while (tempRead != 0) jvs_read(tempRead); while (tempRead != 0) jvs_read(tempRead);
// TODO: Do we need to report here? // TODO: Do we need to report here?
break; break;
@ -228,8 +231,10 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
for (int bit = 0; bit < 8; bit++) { for (int bit = 0; bit < 8; bit++) {
int scancode = jvs_buttons[i][j * 8 + bit]; int scancode = jvs_buttons[i][j * 8 + bit];
// Buttons on maimai use beam interrupt sensors, so logical high = unpressed. // Buttons on maimai use beam interrupt sensors, so logical high =
bool invert = ((j == 0 && (bit == 0 || bit == 2 || bit == 3)) || (j == 1 && bit >= 3)); // unpressed.
bool invert = ((j == 0 && (bit == 0 || bit == 2 || bit == 3)) ||
(j == 1 && bit >= 3));
if (invert) if (invert)
buttons |= (GetAsyncKeyState(scancode) >= 0) << bit; buttons |= (GetAsyncKeyState(scancode) >= 0) << bit;
@ -254,6 +259,16 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
break; 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: case JVS_CMD_READ_ANALOGS:
jvs_write(JVS_REPORT_OK); jvs_write(JVS_REPORT_OK);
// TODO: Actually emulate these (super low priority) // 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 (i == 0) {
if (!!(gpio_value & 0x80) != coin_solenoid) { if (!!(gpio_value & 0x80) != coin_solenoid) {
coin_solenoid = !!(gpio_value & 0x80); 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 respIndex = 4; // As if we've just written status, but nothing else
jvs_exchange_complete: 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; response[3] = status;
// Compute and set the checksum // Compute and set the checksum
@ -319,17 +335,18 @@ jvs_exchange_complete:
free(inData); free(inData);
} }
BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPOVERLAPPED lpOverlapped) { LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
switch (dwIoControlCode) { switch (dwIoControlCode) {
case IOCTL_MXJVS_EXCHANGE: case IOCTL_MXJVS_EXCHANGE:
log_misc("mxjvs", log_trace("mxjvs",
"DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, " "DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, "
"0x%x, -, -)", "0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize); lpInBuffer, nInBufferSize, nOutBufferSize);
mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize, lpBytesReturned); mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize & 0xFFFF,
(int*)lpBytesReturned);
break; break;
default: default:
@ -353,8 +370,8 @@ BOOL mxjvs_GetCommModemStatus(void* com, LPDWORD lpModelStat) {
BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) { BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) {
char PARITY[] = { 'N', 'O', 'E', 'M', 'S' }; char PARITY[] = { 'N', 'O', 'E', 'M', 'S' };
char* STOP[] = { "1", "1.5", "2" }; char* STOP[] = { "1", "1.5", "2" };
log_info("mxjvs", "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize, PARITY[lpDCB->Parity], log_info("mxjvs", "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize,
STOP[lpDCB->StopBits]); PARITY[lpDCB->Parity], STOP[lpDCB->StopBits]);
return TRUE; return TRUE;
} }
@ -362,7 +379,9 @@ void setup_mxjvs() {
file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs"); file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs");
mxjvs->DeviceIoControl = &mxjvs_DeviceIoControl; 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->GetCommState = mxjvs_GetCommState;
jvscom->SetCommState = mxjvs_SetCommState; jvscom->SetCommState = mxjvs_SetCommState;
jvscom->SetCommTimeouts = mxjvs_SetCommTimeouts; jvscom->SetCommTimeouts = mxjvs_SetCommTimeouts;
@ -372,6 +391,4 @@ void setup_mxjvs() {
hook_file(mxjvs); hook_file(mxjvs);
hook_com(jvscom); 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 "../hooks/setupapi_.h"
#include "../lib/dmi/dmi.h"
#include "mx.h" #include "mx.h"
#include "smbus.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" #define EEPROM_DUMP L"dev/eeprom.bin"
typedef struct eeprom_reg { typedef struct eeprom_reg {
BYTE data[32]; BYTE data[32];
@ -47,19 +22,26 @@ eeprom_bank_t EEPROM_DATA;
*/ */
void eeprom_dump() { 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) { if (dump == INVALID_HANDLE_VALUE) {
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed"); log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed");
return; return;
} else {
log_info("eeprom", "Wrote eeprom to %s", EEPROM_DUMP);
} }
_WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL); _WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL);
FlushFileBuffers(dump); FlushFileBuffers(dump);
_CloseHandle(dump); _CloseHandle(dump);
} }
void eeprom_restore() { void eeprom_restore() {
HANDLE dump = HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
_CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); FILE_ATTRIBUTE_NORMAL, NULL);
if (dump == INVALID_HANDLE_VALUE) return; if (dump == INVALID_HANDLE_VALUE) {
// Make the file, even though it'll probably be empty
eeprom_dump();
return;
}
DWORD read; DWORD read;
if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL)) if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL))
log_error("eeprom", "failed to restore (%d)", GetLastError()); 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); return crc32(28, EEPROM_DATA.reg[reg].data + 4, 0);
} }
void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) { void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) {
log_game("eeprom", "EEPROM READ %d %d %d", reg, index, length);
eeprom_restore(); eeprom_restore();
for (BYTE i = index; i < index + length; i++) { for (BYTE i = index; i < index + length; i++) {
if (i > 0x1f) break; if (i > 0x1f) break;
BYTE byte = EEPROM_DATA.reg[reg].data[i]; 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 register has a CRC
// if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg // if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg
// == 0x11 || reg == 0x12 || reg == 0x200) { // == 0x11 || reg == 0x12 || reg == 0x200) {
if (true) { if (false) {
// Intercept the read and inject a CRC instead // Intercept the read and inject a CRC instead
if (i == 0x00 || i == 0x01 || i == 0x02 || i == 0x03) { if (i == 0x00 || i == 0x01 || i == 0x02 || i == 0x03) {
DWORD crc = eeprom_crc(reg); 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) { 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++) { for (BYTE i = index; i < index + length; i++) {
if (i > 0x1f) break; if (i > 0x1f) break;
EEPROM_DATA.reg[reg].data[i] = data[i - index]; 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); } 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, BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPOVERLAPPED lpOverlapped) { LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
mxsmbus_i2c_packet* i2c_packet = (mxsmbus_i2c_packet*)lpInBuffer; mxsmbus_i2c_packet* i2c_packet = (mxsmbus_i2c_packet*)lpInBuffer;
mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer; mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer;
@ -123,6 +111,8 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
BYTE dlen; BYTE dlen;
static uint16_t pca9535_config = 0xffff;
switch (dwIoControlCode) { switch (dwIoControlCode) {
case IOCTL_MXSMBUS_GET_VERSION: case IOCTL_MXSMBUS_GET_VERSION:
log_misc("mxsmbus", log_misc("mxsmbus",
@ -134,7 +124,7 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
if (lpBytesReturned) *lpBytesReturned = 4; if (lpBytesReturned) *lpBytesReturned = 4;
break; break;
case IOCTL_MXSMBUS_REQUEST: // dip r/w case IOCTL_MXSMBUS_REQUEST: // dip r/w
log_misc("mxsmbus", log_trace("mxsmbus",
"DeviceIoControl(<mxsmbus>, <request>, 0x%p, 0x%x, -, " "DeviceIoControl(<mxsmbus>, <request>, 0x%p, 0x%x, -, "
"0x%x, -, -)", "0x%x, -, -)",
lpInBuffer, nInBufferSize, nOutBufferSize); lpInBuffer, nInBufferSize, nOutBufferSize);
@ -171,22 +161,31 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
switch (i2c_packet->prt) { switch (i2c_packet->prt) {
case PCA9535_WRITE: case PCA9535_WRITE:
switch (i2c_packet->reg) { switch (i2c_packet->reg) {
case PCA9535_OUT0:
log_info("mxsmbus", "pca9535 OUT0: %02x", i2c_packet->data[0]);
break;
case PCA9535_OUT1: case PCA9535_OUT1:
log_info("mxsmbus", "pca9535 OUT1: %02x %02x", i2c_packet->data[0], log_info("mxsmbus", "pca9535 OUT1: %02x", i2c_packet->data[0]);
i2c_packet->data[1]);
break; break;
case PCA9535_INV0: case PCA9535_INV0:
log_info("mxsmbus", "pca9535 INV0: %02x %02x", i2c_packet->data[0], log_info("mxsmbus", "pca9535 INV0: %02x", i2c_packet->data[0]);
i2c_packet->data[1]);
break; break;
case PCA9535_INV1: case PCA9535_INV1:
log_info("mxsmbus", "pca9535 INV1: %02x %02x", i2c_packet->data[0], log_info("mxsmbus", "pca9535 INV1: %02x", i2c_packet->data[0]);
i2c_packet->data[1]); 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; break;
default: default:
log_error("mxsmbux", log_error("mxsmbus",
"(write) Undefined pca9535 " "(write) Undefined pca9535 register: 0x%02x",
"register: 0x%02x",
i2c_packet->reg); i2c_packet->reg);
exit(1); exit(1);
} }
@ -194,28 +193,54 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
case PCA9535_READ: case PCA9535_READ:
switch (i2c_packet->reg) { switch (i2c_packet->reg) {
case PCA9535_IN0: // DIPSW 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; break;
case PCA9535_IN1: // SW1/2 + extras case PCA9535_IN1: // SW1/2 + extras
/* /*
0: uk 0: unk
1: uk 1: unk
2: ¬test 2: ¬test
3: ¬service 3: ¬service
4: uk 4: unk
5: uk 5: unk
6: uk 6: unk
7: uk 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; break;
case PCA9535_INV0: case PCA9535_INV0:
case PCA9535_INV1: case PCA9535_INV1:
case PCA9535_OUT1: // LEDs, probably case PCA9535_OUT1: // LEDs, probably
i2c_packet->data[0] = 0x00; i2c_packet->data[0] = 0x00;
break; break;
case PCA9535_CONF0:
i2c_packet->data[0] = pca9535_config >> 8;
break;
case PCA9535_CONF1:
i2c_packet->data[0] = pca9535_config & 0xff;
break;
default: default:
log_error("mxsmbux", log_error("mxsmbus",
"(read) Undefined pca9535 " "(read) Undefined pca9535 "
"register: 0x%02x", "register: 0x%02x",
i2c_packet->reg); i2c_packet->reg);
@ -224,7 +249,8 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
i2c_packet->status = 0x00; i2c_packet->status = 0x00;
break; break;
default: 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); exit(1);
} }
break; break;
@ -235,7 +261,7 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
i2c_packet->status = 0; i2c_packet->status = 0;
break; break;
default: 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); exit(1);
} }
break; break;
@ -253,8 +279,9 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
"-, -)", "-, -)",
lpInBuffer, nInBufferSize, nOutBufferSize); lpInBuffer, nInBufferSize, nOutBufferSize);
log_misc("mxsmbus", "SMBus I2C request for %02x: 0x%02x (%02x bytes @ %02x)", request_packet->addr, log_misc("mxsmbus", "SMBus I2C request for %02x: 0x%02x (%02x bytes @ %02x)",
request_packet->prt, request_packet->dlen, request_packet->reg); request_packet->addr, request_packet->prt, request_packet->dlen,
request_packet->reg);
// log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[0], // log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[0],
// dwordInBuffer[1], dwordInBuffer[2], dwordInBuffer[3]); // dwordInBuffer[1], dwordInBuffer[2], dwordInBuffer[3]);
// log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[4], // 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 ", // for (int i = 0; i < dlen; i++) printf("%02x ",
// request_packet->data[i]); puts(""); // request_packet->data[i]); puts("");
eeprom_write(request_packet->reg >> 5, request_packet->reg & 0x1f, request_packet->data, eeprom_write((request_packet->reg >> 5) & 0xff, request_packet->reg & 0x1f,
request_packet->dlen); request_packet->data, request_packet->dlen);
request_out->status = 0; request_out->status = 0;
} else if (i2c_packet->prt == 0x09) { } else if (i2c_packet->prt == 0x09) {
// Read // Read
log_misc("mxsmbus", "eeprom read %02x (0x%04x)", dlen, request_packet->reg); 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 ", // for (int i = 0; i < dlen; i++) printf("%02x ",
// request_out->data[i]); puts(""); // request_out->data[i]); puts("");
request_out->status = 0; 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, LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped) { LPOVERLAPPED lpOverlapped) {
DWORD SRAM_VERSION = 0x0001; DWORD SRAM_VERSION = 0x0001;
DWORD SRAM_SECTOR_SIZE = 0x100; // Max is 0x800 DWORD SRAM_SECTOR_SIZE = 4; // Max is 0x800
switch (dwIoControlCode) { switch (dwIoControlCode) {
case IOCTL_MXSRAM_PING: // Get version 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; DISK_GEOMETRY out = *(PDISK_GEOMETRY)lpOutBuffer;
memset(&out, 0, sizeof(out)); memset(&out, 0, sizeof(out));
out.Cylinders.QuadPart = 1; out.Cylinders.QuadPart = 256;
out.MediaType = FixedMedia; out.MediaType = FixedMedia;
out.TracksPerCylinder = 224; out.TracksPerCylinder = 24;
out.SectorsPerTrack = 32; out.SectorsPerTrack = 8;
out.BytesPerSector = 1; out.BytesPerSector = 512;
if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY); if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY);
break; break;
case IOCTL_MXSRAM_GET_SECTOR_SIZE: 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) { DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
printf("MXSRSFP %08x\n", lDistanceToMove);
if (dwMoveMethod == FILE_BEGIN) { if (dwMoveMethod == FILE_BEGIN) {
SRAM_POINTER = lDistanceToMove; SRAM_POINTER = lDistanceToMove;
} else if (dwMoveMethod == FILE_CURRENT) { } else if (dwMoveMethod == FILE_CURRENT) {

View File

@ -1,6 +1,7 @@
#include "mx.h" #include "mx.h"
#include "smbus.h" #include "smbus.h"
#include "w83791d.h" #include "w83791d.h"
#include "w83627uhg.h"
BYTE w83791d_bank = 0x00; BYTE w83791d_bank = 0x00;
BYTE w83791d_config = W83791D_CONFIG_START; BYTE w83791d_config = W83791D_CONFIG_START;
@ -13,9 +14,17 @@ BYTE w83791d_crit_t3 = 80; // C
BYTE w83791d_vbat_monitor_control = 0x00; BYTE w83791d_vbat_monitor_control = 0x00;
BOOL w83791d_4f_high = 0; BOOL w83791d_4f_high = 0;
BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, BYTE w83627uhg_fanconf = 0x01;
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, BYTE w83627uhg_fanconf_2 = 0x00;
LPOVERLAPPED lpOverlapped) { 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_packet = (mxsuperio_lpc_packet*)lpInBuffer;
mxsuperio_lpc_packet* lpc_out = (mxsuperio_lpc_packet*)lpOutBuffer; 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; ((LPDWORD)lpOutBuffer)[0] = 0x01000001;
if (lpBytesReturned) *lpBytesReturned = 4; if (lpBytesReturned) *lpBytesReturned = 4;
break; break;
case IOCTL_MXSUPERIO_READ: case IOCTL_MXSUPERIO_READ: {
log_misc("mxsuperio", BYTE chip = ((LPBYTE)lpInBuffer)[0];
"DeviceIoControl(<mxsuperio>, <read>, 0x%p, 0x%x, -, " BYTE device = ((LPBYTE)lpInBuffer)[1];
"0x%x, -, -)", BYTE index = ((LPBYTE)lpInBuffer)[2];
lpInBuffer, nInBufferSize, nOutBufferSize); BYTE* data = &((LPBYTE)lpInBuffer)[3];
log_misc("mxsuperio", "read: chip:%d device:%d index:%02x", chip, device, index);
/* /*
BYTE chipId = 0|1 {
BYTE ?? = 0x0b IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e)
BYTE ?? = 0x20|0x21 IN BYTE logical device (0 = FDC, 11 = HW mon)
BYTE ret = 0 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: case 0x20:
((LPBYTE)lpInBuffer)[3] = 0xa0; *data = 0xa2;
break; break;
case 0x21: case 0x21:
((LPBYTE)lpInBuffer)[3] = 0x20; *data = 0x32;
break;
default:
((LPBYTE)lpInBuffer)[3] = 0x00;
break; 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; if (lpBytesReturned) *lpBytesReturned = 4;
break; break;
case IOCTL_MXSUPERIO_HWMONITOR_LPC_READ: { 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 index = lpc_packet->index;
BYTE reg = lpc_packet->reg; BYTE reg = lpc_packet->reg;
switch (w83791d_bank) { switch (w83791d_bank) {
case 0x00: { case 0x00: {
switch (reg) { 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: case W83791D_REG_WCHIPID:
lpc_out->data = 0x71; lpc_out->data = 0x71; // Observed: c1
break; break;
case W83791D_REG_CHIPMAN: case W83791D_REG_CHIPMAN:
if (w83791d_4f_high) if (w83791d_4f_high)
@ -73,7 +139,7 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
lpc_out->data = 0xa3; // Low byte lpc_out->data = 0xa3; // Low byte
break; break;
case W83791D_REG_I2C_ADDR: case W83791D_REG_I2C_ADDR:
lpc_out->data = 0x11; lpc_out->data = 0x11; // Observed: 2d
break; break;
case W83791D_REG_BANK: case W83791D_REG_BANK:
lpc_out->data = w83791d_bank; lpc_out->data = w83791d_bank;
@ -84,16 +150,28 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
break; break;
case W83791D_REG_BEEP_CTRL_0: case W83791D_REG_BEEP_CTRL_0:
lpc_out->data = 0xff; // All the beeps! (see main.h) // No beeping :(
lpc_out->data = 0x00;
break; break;
// TODO: No idea how to read any of these. Pulled from real system
case W83791D_REG_TEMP1_0: case W83791D_REG_TEMP1_0:
lpc_out->data = 0x00; // TODO: Figure out the temp val lol lpc_out->data = 0x1a;
break; break;
case W83791D_RAM_VCOREA: case W83791D_RAM_VCOREA:
lpc_out->data = 0x76;
break;
case W83791D_RAM_VNIR0: case W83791D_RAM_VNIR0:
lpc_out->data = 0x86;
break;
case W83791D_RAM_VDD5:
lpc_out->data = 0x94;
break;
case W83791D_RAM_12VIN: 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; break;
case W83791D_RAM_FAN1: case W83791D_RAM_FAN1:
@ -103,9 +181,8 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
break; break;
case W83791D_VID_FAN_DIV: case W83791D_VID_FAN_DIV:
// Boths fans divide by 2 (01), VDD 5 latched // Boths fans divide by 2 (01)
// good. lpc_out->data = 0b00000101;
lpc_out->data = 0b01011111; // Let's not /0!
break; break;
case W83791D_VBAT_MONITOR_CONTROL: case W83791D_VBAT_MONITOR_CONTROL:
@ -113,8 +190,9 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
break; break;
default: default:
log_error("mxsuperio", "Unknown HM b0 register: 0x%02x", reg); log_error("mxsuperio", "Unknown HM b0 register: read 0x%02x", reg);
exit(1); return FALSE;
// exit(1);
} }
} break; } break;
case 0x01: { case 0x01: {
@ -183,18 +261,48 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
// data > 0x0f, data < 0x70 // data > 0x0f, data < 0x70
// lpc_out->data = eeprom_read_one(reg, index); // 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); if (lpBytesReturned) *lpBytesReturned = sizeof(mxsuperio_lpc_packet);
} break; } break;
case IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE: { case IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE: {
BYTE index = lpc_packet->index; BYTE index = lpc_packet->index;
BYTE reg = lpc_packet->reg; 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) { switch (w83791d_bank) {
case 0x00: { case 0x00: {
switch (reg) { 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: case W83791D_REG_BEEP_CTRL_0:
// Ignore for now // Ignore for now
break; break;
@ -210,8 +318,8 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
w83791d_vbat_monitor_control = lpc_packet->data; w83791d_vbat_monitor_control = lpc_packet->data;
break; break;
default: default:
log_error("mxsuperio", "Unknown HM b0 register: 0x%02x", reg); log_error("mxsuperio", "Unknown HM b0 register: write 0x%02x", reg);
exit(1); // exit(1);
} }
break; 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_processes();
hook_network(); hook_network();
hook_time(); hook_time();
hook_registry();
hook_drives();
} }

View File

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

View File

@ -1,5 +1,7 @@
#include "com.h" #include "com.h"
#include "files.h"
com_hook_t* com_hook_list = NULL; com_hook_t* com_hook_list = NULL;
com_hook_t* new_com_hook(BYTE port) { com_hook_t* new_com_hook(BYTE port) {
com_hook_t* hook = (com_hook_t*)malloc(sizeof *hook); 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); memset(hook->wName, 0, sizeof hook->wName);
swprintf(hook->wName, (sizeof hook->wName) / (sizeof hook->wName[0]), L"COM%d", port); swprintf(hook->wName, (sizeof hook->wName) / (sizeof hook->wName[0]), L"COM%d", port);
memset(hook->wDosName, 0, sizeof hook->wDosName); 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->com = port;
hook->GetCommState = NULL; hook->GetCommState = NULL;
@ -21,7 +24,7 @@ com_hook_t* new_com_hook(BYTE port) {
hook->ClearCommError = NULL; hook->ClearCommError = NULL;
return hook; return hook;
}; }
void hook_com(com_hook_t* hook) { void hook_com(com_hook_t* hook) {
hook->next = NULL; hook->next = NULL;
@ -35,39 +38,33 @@ void hook_com(com_hook_t* hook) {
com_hook_t* hl = com_hook_list; com_hook_t* hl = com_hook_list;
while (hl->next != NULL) hl = hl->next; while (hl->next != NULL) hl = hl->next;
hl->next = hook; hl->next = hook;
}; }
BOOL WINAPI FakeGetCommState(HANDLE hFile, LPDCB lpDCB) { 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; if (hook != NULL) {
while (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->GetCommState == NULL) { if (hook->GetCommState == NULL) {
log_error(COMM_LOGGER, "GetCommState(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "GetCommState(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->GetCommState(hook->data, lpDCB); return hook->GetCommState(hook->data, lpDCB);
} }
hook = hook->next;
}
return TrueGetCommState(hFile, lpDCB); return TrueGetCommState(hFile, lpDCB);
} }
BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) { BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
log_misc(COMM_LOGGER, "SetCommState(0x%p, 0x%p)", hFile, lpDCB); log_misc(COMM_LOGGER, "SetCommState(0x%p, 0x%p)", hFile, lpDCB);
com_hook_t* hook = com_hook_list; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->SetCommState == NULL) { if (hook->SetCommState == NULL) {
log_error(COMM_LOGGER, "SetCommState(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "SetCommState(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->SetCommState(hook->data, lpDCB); return hook->SetCommState(hook->data, lpDCB);
} }
hook = hook->next;
}
return TrueSetCommState(hFile, lpDCB); return TrueSetCommState(hFile, lpDCB);
} }
@ -75,119 +72,98 @@ BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
log_misc(COMM_LOGGER, "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts); log_misc(COMM_LOGGER, "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
com_hook_t* hook = com_hook_list; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->GetCommTimeouts == NULL) { if (hook->GetCommTimeouts == NULL) {
log_error(COMM_LOGGER, "GetCommTimeouts(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "GetCommTimeouts(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->GetCommTimeouts(hook->data, lpCommTimeouts); return hook->GetCommTimeouts(hook->data, lpCommTimeouts);
} }
hook = hook->next;
}
return TrueGetCommTimeouts(hFile, lpCommTimeouts); return TrueGetCommTimeouts(hFile, lpCommTimeouts);
} }
BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
log_misc(COMM_LOGGER, "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts); log_misc(COMM_LOGGER, "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
com_hook_t* hook = com_hook_list; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->SetCommTimeouts == NULL) { if (hook->SetCommTimeouts == NULL) {
log_error(COMM_LOGGER, "SetCommTimeouts(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "SetCommTimeouts(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->SetCommTimeouts(hook->data, lpCommTimeouts); return hook->SetCommTimeouts(hook->data, lpCommTimeouts);
} }
hook = hook->next;
}
return TrueSetCommTimeouts(hFile, lpCommTimeouts); return TrueSetCommTimeouts(hFile, lpCommTimeouts);
} }
BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) { BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) {
log_misc(COMM_LOGGER, "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue); log_misc(COMM_LOGGER, "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue);
com_hook_t* hook = com_hook_list; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->SetupComm == NULL) { if (hook->SetupComm == NULL) {
log_error(COMM_LOGGER, "SetupComm(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "SetupComm(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->SetupComm(hook->data, dwInQueue, dwOutQueue); return hook->SetupComm(hook->data, dwInQueue, dwOutQueue);
} }
hook = hook->next;
}
return TrueSetupComm(hFile, dwInQueue, dwOutQueue); return TrueSetupComm(hFile, dwInQueue, dwOutQueue);
} }
BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) { BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) {
log_misc(COMM_LOGGER, "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags); log_misc(COMM_LOGGER, "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags);
com_hook_t* hook = com_hook_list; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->PurgeComm == NULL) { if (hook->PurgeComm == NULL) {
log_error(COMM_LOGGER, "PurgeComm(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "PurgeComm(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->PurgeComm(hook->data, dwFlags); return hook->PurgeComm(hook->data, dwFlags);
} }
hook = hook->next;
}
return TruePurgeComm(hFile, dwFlags); return TruePurgeComm(hFile, dwFlags);
} }
BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) { BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) {
log_misc(COMM_LOGGER, "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat); log_misc(COMM_LOGGER, "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat);
com_hook_t* hook = com_hook_list; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->GetCommModemStatus == NULL) { if (hook->GetCommModemStatus == NULL) {
log_error(COMM_LOGGER, "GetCommModemStatus(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "GetCommModemStatus(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->GetCommModemStatus(hook->data, lpModelStat); return hook->GetCommModemStatus(hook->data, lpModelStat);
} }
hook = hook->next;
}
return TrueGetCommModemStatus(hFile, lpModelStat); return TrueGetCommModemStatus(hFile, lpModelStat);
} }
BOOL WINAPI FakeWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) { 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; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->WaitCommEvent == NULL) { if (hook->WaitCommEvent == NULL) {
log_error(COMM_LOGGER, "WaitCommEvent(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "WaitCommEvent(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped); return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped);
} }
hook = hook->next;
}
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped); return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped);
} }
BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) { 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; com_hook_t* hook = get_handle_com_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->ClearCommError == NULL) { if (hook->ClearCommError == NULL) {
log_error(COMM_LOGGER, "ClearCommError(%ls) unimplemented", hook->wName); log_error(COMM_LOGGER, "ClearCommError(%ls) unimplemented", hook->wName);
return FALSE; return FALSE;
} }
return hook->ClearCommError(hook->data, lpErrors, lpStat); return hook->ClearCommError(hook->data, lpErrors, lpStat);
} }
hook = hook->next;
}
return TrueClearCommError(hFile, lpErrors, lpStat); return TrueClearCommError(hFile, lpErrors, lpStat);
} }
@ -198,7 +174,8 @@ void hook_commio() {
hook("Kernel32.dll", "SetCommTimeouts", FakeSetCommTimeouts, (void**)&TrueSetCommTimeouts, 6); hook("Kernel32.dll", "SetCommTimeouts", FakeSetCommTimeouts, (void**)&TrueSetCommTimeouts, 6);
hook("Kernel32.dll", "SetupComm", FakeSetupComm, (void**)&TrueSetupComm, 6); hook("Kernel32.dll", "SetupComm", FakeSetupComm, (void**)&TrueSetupComm, 6);
hook("Kernel32.dll", "PurgeComm", FakePurgeComm, (void**)&TruePurgeComm, 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", "WaitCommEvent", FakeWaitCommEvent, (void**)&TrueWaitCommEvent, 6);
hook("Kernel32.dll", "ClearCommError", FakeClearCommError, (void**)&TrueClearCommError, 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 { typedef struct com_hook {
LPHANDLE virtual_handle; LPHANDLE virtual_handle;
WCHAR wName[7]; // max is "COM255" WCHAR wName[16];
WCHAR wDosName[11]; // max is "\\\\.\\COM255" WCHAR wDosName[16];
BYTE com; BYTE com;
FnGetCommState* GetCommState; FnGetCommState* GetCommState;
@ -43,6 +43,8 @@ typedef struct com_hook {
struct com_hook* next; struct com_hook* next;
} com_hook_t; } com_hook_t;
extern com_hook_t* com_hook_list;
com_hook_t* new_com_hook(BYTE port); com_hook_t* new_com_hook(BYTE port);
void hook_com(com_hook_t* hook); 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" #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* file_hook_list = NULL;
file_hook_t* new_file_hook(LPCWSTR filename) { file_hook_t* new_file_hook(LPCWSTR filename) {
file_hook_t* hook = (file_hook_t*)malloc(sizeof(file_hook_t)); 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; hook->filename = filename;
@ -13,8 +74,6 @@ file_hook_t* new_file_hook(LPCWSTR filename) {
} }
void hook_file(file_hook_t* hook) { void hook_file(file_hook_t* hook) {
hook->next = NULL; hook->next = NULL;
hook->virtual_handle = (LPHANDLE)malloc(sizeof(HANDLE));
*hook->virtual_handle = NULL;
if (file_hook_list == NULL) { if (file_hook_list == NULL) {
file_hook_list = hook; file_hook_list = hook;
return; return;
@ -30,9 +89,12 @@ drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
// Note: Had tp create last_shime.log // Note: Had tp create last_shime.log
{ .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" }, { .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" },
// {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"}, // {.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++) { for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
drive_redirect_t row = DRIVE_REDIRECT_TABLE[i]; drive_redirect_t row = DRIVE_REDIRECT_TABLE[i];
if (strstr(path, row.drive)) { if (strstr(path, row.drive)) {
@ -45,7 +107,7 @@ char* redirect_path(char* path) {
char* dst = new_str + strlen(row.path); char* dst = new_str + strlen(row.path);
size_t len = strlen(path) - strlen(row.drive); 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]; for (; len > 0; len--) (dst++)[0] = (src++)[0];
dst[0] = 0; dst[0] = 0;
@ -55,66 +117,122 @@ char* redirect_path(char* path) {
} }
return 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, size_t new_len = wcslen(path) - wcslen(row.drive) + wcslen(row.path);
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, // TODO: Make this not leak memory!
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { wchar_t* new_str = (wchar_t*)malloc((new_len + 1) * 2);
HANDLE handle = NULL; wcscpy_s(new_str, new_len + 1, row.path);
file_hook_t* hook = file_hook_list; wchar_t* dst = new_str + wcslen(row.path) * 2;
while (hook != NULL) { size_t len = wcslen(path) - wcslen(row.drive);
if (wcscmp(lpFileName, hook->filename) == 0 || const wchar_t* src = path + wcslen(row.drive) * 2;
(hook->altFilename != NULL && wcscmp(lpFileName, hook->altFilename) == 0)) {
if (*hook->virtual_handle == NULL) { for (; len > 0; len--) {
// TODO: Assign handles better! (dst++)[0] = (src++)[0];
*hook->virtual_handle = fake_handle; (dst++)[0] = (src++)[0];
((size_t)fake_handle)++;
} }
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; break;
} }
hook = hook->next; file_hook = file_hook->next;
} }
if (handle == NULL) { com_hook_t* com_hook = com_hook_list;
handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, while (com_hook != NULL) {
dwFlagsAndAttributes, hTemplateFile); 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); log_misc(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
return handle; return handle;
} }
HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) { DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
lpFileName = redirect_path((char*)lpFileName); HANDLE hTemplateFile) {
WCHAR wideFileName[MAX_PATH + 1]; WCHAR wideFileName[MAX_PATH + 1];
MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, (LPWSTR)&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); dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
log_misc(HOOKS_LOGGER, "^-> CreateFileA(%s) -> 0x%p", lpFileName, result); log_misc(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
return result; 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, BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPOVERLAPPED lpOverlapped) { LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
log_misc(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, 0x%p, 0x%x, -, 0x%x, 0, 0)", hDevice, dwIoControlCode, file_hook_t* hook = get_handle_file_hook(hDevice);
lpInBuffer, nInBufferSize, nOutBufferSize); if (hook != NULL) {
file_hook_t* hook = file_hook_list;
while (hook != NULL) {
if (*hook->virtual_handle == hDevice) {
if (hook->DeviceIoControl) { if (hook->DeviceIoControl) {
// TODO: Less jank // TODO: Less jank
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent); if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
BOOL ret = hook->DeviceIoControl(hook->data, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, BOOL ret =
nOutBufferSize, lpBytesReturned, lpOverlapped); hook->DeviceIoControl(hook->data, dwIoControlCode, lpInBuffer, nInBufferSize,
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
if (ret && lpOverlapped && lpBytesReturned) { if (ret && lpOverlapped && lpBytesReturned) {
lpOverlapped->InternalHigh = *lpBytesReturned; lpOverlapped->InternalHigh = *lpBytesReturned;
} }
@ -124,54 +242,49 @@ BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lp
return FALSE; 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, return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
lpBytesReturned, lpOverlapped); nOutBufferSize, lpBytesReturned, lpOverlapped);
} }
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
file_hook_t* hook = file_hook_list; DWORD dwMoveMethod) {
while (hook != NULL) { file_hook_t* hook = get_handle_file_hook(hFile);
if (*hook->virtual_handle == hFile) { if (hook != NULL) {
if (hook->SetFilePointer) { if (hook->SetFilePointer) {
return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod); return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh,
dwMoveMethod);
} else { } else {
log_error(HOOKS_LOGGER, "SetFilePointer(%ls) unimplemented", hook->filename); log_error(HOOKS_LOGGER, "SetFilePointer(%ls) unimplemented", hook->filename);
return FALSE; return FALSE;
} }
} }
hook = hook->next;
}
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod); return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
} }
BOOL WINAPI FakeSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, BOOL WINAPI FakeSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
DWORD dwMoveMethod) { PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
file_hook_t* hook = file_hook_list; file_hook_t* hook = get_handle_file_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->SetFilePointerEx) { if (hook->SetFilePointerEx) {
return hook->SetFilePointerEx(hook->data, liDistanceToMove, lpNewFilePointer, dwMoveMethod); return hook->SetFilePointerEx(hook->data, liDistanceToMove, lpNewFilePointer,
dwMoveMethod);
} else { } else {
log_error(HOOKS_LOGGER, "SetFilePointerEx(%ls) unimplemented", hook->filename); log_error(HOOKS_LOGGER, "SetFilePointerEx(%ls) unimplemented", hook->filename);
return FALSE; return FALSE;
} }
} }
hook = hook->next;
}
return TrueSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod); return TrueSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
} }
DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) { DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
file_hook_t* hook = file_hook_list; file_hook_t* hook = get_handle_file_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->GetFileSizeEx) { if (hook->GetFileSizeEx) {
return hook->GetFileSizeEx(hook->data, lpFileSize); return hook->GetFileSizeEx(hook->data, lpFileSize);
} else { } else {
@ -179,58 +292,53 @@ DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
return FALSE; return FALSE;
} }
} }
hook = hook->next;
}
return TrueGetFileSizeEx(hFile, lpFileSize); return TrueGetFileSizeEx(hFile, lpFileSize);
} }
DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPOVERLAPPED lpOverlapped) { LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
file_hook_t* hook = file_hook_list; log_trace("file", "WriteFile(%08x)", hFile);
while (hook != NULL) { file_hook_t* hook = get_handle_file_hook(hFile);
if (*hook->virtual_handle == hFile) { if (hook != NULL) {
if (hook->WriteFile) { if (hook->WriteFile) {
return hook->WriteFile(hook->data, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, return hook->WriteFile(hook->data, lpBuffer, nNumberOfBytesToWrite,
lpOverlapped); lpNumberOfBytesWritten, lpOverlapped);
} else { } else {
log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", hook->filename); log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", hook->filename);
return FALSE; 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, BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPOVERLAPPED lpOverlapped) { LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
file_hook_t* hook = file_hook_list; file_hook_t* hook = get_handle_file_hook(hFile);
while (hook != NULL) { if (hook != NULL) {
if (*hook->virtual_handle == hFile) {
if (hook->ReadFile) { if (hook->ReadFile) {
return hook->ReadFile(hook->data, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); return hook->ReadFile(hook->data, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
lpOverlapped);
} else { } else {
log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", hook->filename); log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", hook->filename);
return FALSE; return FALSE;
} }
} }
hook = hook->next;
}
return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped); return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
} }
BOOL WINAPI FakeCloseHandle(HANDLE hObject) { BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
file_hook_t* hook = file_hook_list; file_hook_t* hook = get_handle_file_hook(hObject);
while (hook != NULL) { if (hook != NULL) {
if (hObject != NULL && *hook->virtual_handle == hObject) {
log_misc("file", "close %08x", hObject); log_misc("file", "close %08x", hObject);
close_hook(hObject);
return TRUE; return TRUE;
} }
hook = hook->next;
}
return TrueCloseHandle(hObject); return TrueCloseHandle(hObject);
} }
@ -247,7 +355,8 @@ void hook_io() {
hook("Kernel32.dll", "CloseHandle", FakeCloseHandle, (void**)&TrueCloseHandle, 6); hook("Kernel32.dll", "CloseHandle", FakeCloseHandle, (void**)&TrueCloseHandle, 6);
hook("Kernel32.dll", "SetFilePointer", FakeSetFilePointer, (void**)&TrueSetFilePointer, 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", "WriteFile", FakeWriteFile, (void**)&TrueWriteFile, 6);
hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6); hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6);
hook("Kernel32.dll", "GetFileSizeEx", FakeGetFileSizeEx, (void**)&TrueGetFileSizeEx, 6); hook("Kernel32.dll", "GetFileSizeEx", FakeGetFileSizeEx, (void**)&TrueGetFileSizeEx, 6);

View File

@ -1,55 +1,68 @@
#pragma once #pragma once
#include "../common.h" #include "../common.h"
#include "com.h"
static HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, static HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, static HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile);
static BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, static BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, DWORD nInBufferSize, LPVOID lpOutBuffer,
DWORD nOutBufferSize, LPDWORD lpBytesReturned,
LPOVERLAPPED lpOverlapped); LPOVERLAPPED lpOverlapped);
static DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, static DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove,
DWORD dwMoveMethod); PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
static BOOL(WINAPI* TrueSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, static BOOL(WINAPI* TrueSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
DWORD dwMoveMethod); PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
// logging needs access to WriteFile, so we can't static it! // logging needs access to WriteFile, so we can't static it!
BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, BOOL(WINAPI* TrueWriteFile)
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped); (HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped);
static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped); LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize); static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize);
static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject); static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject);
typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize, typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned, DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
LPOVERLAPPED lpOverlapped); LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
typedef DWORD(FnSetFilePointer)(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); typedef DWORD(FnSetFilePointer)(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
typedef BOOL(FnSetFilePointerEx)(void* file, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
DWORD dwMoveMethod); DWORD dwMoveMethod);
typedef BOOL(FnWriteFile)(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten, typedef BOOL(FnSetFilePointerEx)(void* file, LARGE_INTEGER liDistanceToMove,
LPOVERLAPPED lpOverlapped); PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
typedef BOOL(FnReadFile)(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, typedef BOOL(FnWriteFile)(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
LPOVERLAPPED lpOverlapped); 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); 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 _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile)
#define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile) #define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile)
#define _CloseHandle (TrueCloseHandle ? TrueCloseHandle : CloseHandle) #define _CloseHandle (TrueCloseHandle ? TrueCloseHandle : CloseHandle)
#define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW) #define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW)
#define _CreateFileA (TrueCreateFileA ? TrueCreateFileA : CreateFileA)
typedef struct drive_redirect { typedef struct drive_redirect {
const CHAR* drive; const CHAR* drive;
const CHAR* path; const CHAR* path;
} drive_redirect_t; } drive_redirect_t;
typedef struct drive_redirect_w {
const WCHAR* drive;
const WCHAR* path;
} drive_redirect_w_t;
typedef struct file_hook { typedef struct file_hook {
LPCWSTR filename; LPCWSTR filename;
LPCWSTR altFilename; LPCWSTR altFilename;
@ -67,6 +80,19 @@ typedef struct file_hook {
struct file_hook* next; struct file_hook* next;
} file_hook_t; } 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); file_hook_t* new_file_hook(LPCWSTR filename);
void hook_file(file_hook_t* hook); void hook_file(file_hook_t* hook);
void hook_io(); 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 char format_buf[WORK_FORMAT_MAX]; // Will do. We guard against overflow in Fake[f]printf
int WINAPIV Fakeprintf(const char* _Format, ...) { 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)) { if (flen == strcspn(_Format, "\n") + 1 && flen < (sizeof format_buf)) {
strcpy_s(format_buf, WORK_FORMAT_MAX, _Format); strcpy_s(format_buf, WORK_FORMAT_MAX, _Format);
format_buf[flen - 1] = 0; format_buf[flen - 1] = 0;
@ -31,11 +31,11 @@ int WINAPIV Fakeprintf(const char* _Format, ...) {
int ret = vlog_game("printf", _Format, args); int ret = vlog_game("printf", _Format, args);
va_end(args); va_end(args);
return vlog_game("printf", _Format, args); return ret;
} }
int WINAPIV Fakefprintf(FILE* _File, const char* _Format, ...) { 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)) { if (flen == strcspn(_Format, "\n") + 1 && flen < (sizeof format_buf)) {
strcpy_s(format_buf, WORK_FORMAT_MAX, _Format); strcpy_s(format_buf, WORK_FORMAT_MAX, _Format);
format_buf[flen - 1] = 0; format_buf[flen - 1] = 0;
@ -59,6 +59,9 @@ int WINAPIV Fakefprintf_s(FILE* _Stream, const char* _Format, ...) {
va_end(args); va_end(args);
return ret; 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; } HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { return (HANDLE)0xDEADBEEF; }
BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, 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", "printf", Fakeprintf, (void**)&Trueprintf, 6);
hook("MSVCR90.DLL", "fprintf", Fakefprintf, (void**)&Truefprintf, 6); hook("MSVCR90.DLL", "fprintf", Fakefprintf, (void**)&Truefprintf, 6);
hook("MSVCR90.DLL", "fprintf_s", Fakefprintf_s, (void**)&Truefprintf_s, 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", "RegisterEventSourceA", FakeRegisterEventSourceA, (void**)&TrueRegisterEventSourceA, 6);
hook("Advapi32.dll", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA, 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, ...); int(WINAPIV* Trueprintf)(const char* _Format, ...);
static int(WINAPIV* Truefprintf)(FILE* _File, 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* Truefprintf_s)(FILE* _Stream, const char* _Format, ...);
static int(WINAPIV* Truevfprintf_s)(FILE* _Stream, const char* _Format, va_list _ArgList);
void hook_logging(); void hook_logging();

View File

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

View File

@ -3,51 +3,94 @@
int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) { int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr.S_un.S_addr); ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr.S_un.S_addr);
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port); 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, log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff,
addr & 0xff, port); (addr >> 8) & 0xff, addr & 0xff, port);
return True_connect(s, name, namelen); 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 WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) {
DWORD ret = TrueGetIfTable(pIfTable, pdwSize, bOrder); log_info("network", "Injecting fake IfTable");
if (ret == NO_ERROR) {
for (size_t i = 0; i < pIfTable->dwNumEntries; i++) { MIB_IFROW* row;
pIfTable->table[i].bPhysAddr[0] = 0x00; uint32_t nbytes;
pIfTable->table[i].bPhysAddr[1] = 0xD0;
pIfTable->table[i].bPhysAddr[2] = 0xF1; 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 typedef struct {
"ib.naominet.jp", // Billing char* name;
"aime.naominet.jp", // Aime (duh) unsigned char address[4];
"tenporouter.loc", // Routers } dns;
"bbrouter.loc", // dns INTERCEPT_DNS[] = {
"mobirouter.loc", // // Startup
"dslrouter.loc", // { "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; 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,
DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra, PDNS_RECORDA* ppQueryResults, PDNS_RECORDA* ppQueryResults, PVOID* pReserved) {
PVOID* pReserved) {
if (ppQueryResults) { if (ppQueryResults) {
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) { for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
if (strcmp(pszName, INTERCEPT_DNS[i]) == 0) { if (strcmp(pszName, INTERCEPT_DNS[i].name) == 0) {
log_info("dns", "Replacing %s with %hhu.%hhu.%hhu.%hhu", pszName, SPOOF_IP[0], SPOOF_IP[1], SPOOF_IP[2], #define spoof (INTERCEPT_DNS[i].address)
SPOOF_IP[3]); 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! // We only support replacing at most one address, but that's all we'll ever need to!
(*ppQueryResults) = &dummy_record; (*ppQueryResults) = &dummy_record;
(*ppQueryResults)->pNext = NULL; (*ppQueryResults)->pNext = NULL;
(*ppQueryResults)->wType = DNS_TYPE_A; (*ppQueryResults)->wType = DNS_TYPE_A;
(*ppQueryResults)->Data.A.IpAddress = (*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; 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); return TrueDnsQuery_A(pszName, wType, Options, pExtra, ppQueryResults, pReserved);
}; };
INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily, LPWSAPROTOCOL_INFOA lpProtocolInfo, INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily,
LPSOCKADDR lpAddress, LPINT lpAddressLength) { LPWSAPROTOCOL_INFOA lpProtocolInfo, LPSOCKADDR lpAddress,
LPINT lpAddressLength) {
log_misc("dns", "(WSA)DNS lookup for %s", AddressString); log_misc("dns", "(WSA)DNS lookup for %s", AddressString);
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) { for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
if (strcmp(AddressString, INTERCEPT_DNS[i]) == 0) { if (strcmp(AddressString, INTERCEPT_DNS[i].name) == 0) {
log_info("dns", "(WSA)Replacing %s with %hhu.%hhu.%hhu.%hhu", AddressString, SPOOF_IP[0], SPOOF_IP[1], #define spoof (INTERCEPT_DNS[i].address)
SPOOF_IP[2], SPOOF_IP[3]); 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_family = AF_INET;
// ... :) // ... :)
lpAddress->sa_data[2] = SPOOF_IP[0]; lpAddress->sa_data[2] = spoof[0];
lpAddress->sa_data[3] = SPOOF_IP[1]; lpAddress->sa_data[3] = spoof[1];
lpAddress->sa_data[4] = SPOOF_IP[2]; lpAddress->sa_data[4] = spoof[2];
lpAddress->sa_data[5] = SPOOF_IP[3]; lpAddress->sa_data[5] = spoof[3];
return ERROR_SUCCESS; return ERROR_SUCCESS;
#undef spoof
} }
} }
log_warning("dns", "(WSA)DNS passthrough for %s", AddressString); 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() { void hook_network() {
hook("Ws2_32.dll", "connect", Fake_connect, (void**)&True_connect, 5); 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("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable, 5);
hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A, 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", L"app\\GmSync.exe",
}; };
#define DISABLE_PROC_SPAWNING
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine, BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, LPSECURITY_ATTRIBUTES lpProcessAttributes,
BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
DWORD dwCreationFlags, LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo, LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation) { 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); log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
CHAR applicationName[MAX_PATH + 1]; 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; HANDLE child;
if (lpCommandLine != NULL) { if (lpCommandLine != NULL) {
CHAR commandLine[MAX_PATH + 1]; 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); child = start_and_inject(applicationName, commandLine, MICELIB, false);
} else { } else {
child = start_and_inject(applicationName, NULL, MICELIB, false); child = start_and_inject(applicationName, NULL, MICELIB, false);
} }
return child != NULL; return !FAILED(child);
// #endif
} }
void hook_processes() { 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: [ link_with: [
dmi_lib, dmi_lib,
mice_lib, mice_lib,
amlib,
] ]
) )

View File

@ -1,6 +1,31 @@
#pragma once #pragma once
#include "common.h" #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) #pragma pack(1)
typedef struct mxsmbus_request_packet_ { typedef struct mxsmbus_request_packet_ {
BYTE status; BYTE status;

View File

@ -28,25 +28,50 @@ HANDLE LOG_FILE = NULL;
VOID trace_hook(char* output); VOID trace_hook(char* output);
CRITICAL_SECTION logger_lock; 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); 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); char* buf = (char*)malloc(len + 2);
if (!buf) { if (!buf) {
LeaveCriticalSection(&logger_lock); LeaveCriticalSection(&logger_lock);
return 0; 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); int wrote_b = vsnprintf(buf + wrote_a, len - wrote_a + 1, format, args);
buf[len] = '\n'; buf[len] = '\n';
buf[len + 1] = '\0'; buf[len + 1] = '\0';
// No +1 here to not get the \n // No +1 here to not get the \n
if (toStdout) { if (LOG_LEVEL >= log_level) {
HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE);
if (HAS_COLOUR) (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, colour, strlen(colour), NULL, NULL); if (HAS_COLOUR)
if (sout != INVALID_HANDLE_VALUE) (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL); (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" : ""); puts(HAS_COLOUR ? "\033[0m" : "");
} }
#ifdef LOG_TO_FILE #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); LeaveCriticalSection(&logger_lock);
return wrote_b; 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) { 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, ...) { int log_misc(const char* caller, const char* format, ...) {
va_list args; va_list args;
@ -70,7 +105,7 @@ int log_misc(const char* caller, const char* format, ...) {
return ret; return ret;
} }
int vlog_info(const char* caller, const char* format, va_list args) { 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, ...) { int log_info(const char* caller, const char* format, ...) {
va_list args; va_list args;
@ -80,7 +115,7 @@ int log_info(const char* caller, const char* format, ...) {
return ret; return ret;
} }
int vlog_warning(const char* caller, const char* format, va_list args) { 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, ...) { int log_warning(const char* caller, const char* format, ...) {
va_list args; va_list args;
@ -90,7 +125,7 @@ int log_warning(const char* caller, const char* format, ...) {
return ret; return ret;
} }
int vlog_error(const char* caller, const char* format, va_list args) { 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, ...) { int log_error(const char* caller, const char* format, ...) {
va_list args; va_list args;
@ -100,7 +135,7 @@ int log_error(const char* caller, const char* format, ...) {
return ret; return ret;
} }
int vlog_game(const char* caller, const char* format, va_list args) { 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, ...) { int log_game(const char* caller, const char* format, ...) {
va_list args; va_list args;
@ -117,19 +152,23 @@ VOID trace_hook(char* output) {
void setup_logging() { void setup_logging() {
// Force stdio even for GUI applications // 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); AttachConsole(ATTACH_PARENT_PROCESS);
if (GetStdHandle(STD_ERROR_HANDLE) > (HANDLE)0x10) {
FILE* newstream;
if (GetStdHandle(STD_INPUT_HANDLE)) { if (GetStdHandle(STD_INPUT_HANDLE)) {
freopen("CONIN$", "r", stdin); freopen_s(&newstream, "CONIN$", "r", stdin);
setvbuf(stdin, NULL, _IONBF, 0); setvbuf(stdin, NULL, _IONBF, 0);
} }
if (GetStdHandle(STD_OUTPUT_HANDLE)) { if (GetStdHandle(STD_OUTPUT_HANDLE)) {
freopen("CONOUT$", "w", stdout); freopen_s(&newstream, "CONOUT$", "w", stdout);
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);
} }
if (GetStdHandle(STD_ERROR_HANDLE)) { if (GetStdHandle(STD_ERROR_HANDLE)) {
freopen("CONOUT$", "w", stderr); freopen_s(&newstream, "CONOUT$", "w", stderr);
setvbuf(stderr, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0);
} }
}
// Enable colour in CMD // Enable colour in CMD
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
@ -139,6 +178,9 @@ void setup_logging() {
InitializeCriticalSection(&logger_lock); InitializeCriticalSection(&logger_lock);
#ifdef LOG_TO_FILE
if (LOG_FILE == NULL) 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 <Windows.h>
#include <stdio.h> #include <stdio.h>
#define LOG_MISC FALSE #define LOG_GAME 1
#define LOG_INFO TRUE #define LOG_ERROR 2
#define LOG_WARNING TRUE #define LOG_WARNING 3
#define LOG_ERROR TRUE #define LOG_INFO 4
#define LOG_GAME TRUE #define LOG_MISC 5
#define LOG_TRACE 6
#define LOG_LEVEL LOG_TRACE
// #define LOG_TO_FILE // #define LOG_TO_FILE
@ -17,12 +20,14 @@
extern CRITICAL_SECTION logger_lock; 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_misc(const char* caller, const char* format, ...);
int log_info(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_warning(const char* caller, const char* format, ...);
int log_error(const char* caller, const char* format, ...); int log_error(const char* caller, const char* format, ...);
int log_game(const char* caller, const char* format, ...); int log_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_misc(const char* caller, const char* format, va_list args);
int vlog_info(const char* caller, const char* format, va_list args); int vlog_info(const char* caller, const char* format, va_list args);
int vlog_warning(const char* caller, const char* format, va_list args); int vlog_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 boot_delay = false;
bool gametest = false; bool gametest = false;
bool designviewer = false;
bool spriteviewer = false;
bool noisetest = false;
char exe_name[MAX_PATH + 1] = ""; char exe_name[MAX_PATH + 1] = "";
char commandline[MAX_PATH + 1] = "";
void print_help(char* exe) { void print_help(char* exe) {
fprintf(stderr, "Usage: %s [-h] [-t] [-b executable.exe] [-d]\n", 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, " -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, " -b: Specify the game binary to use\n");
fprintf(stderr, " -d: Wait for a debugger to attach when starting\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); exit(0);
} }
@ -27,10 +34,21 @@ void parse_cmdline(int argc, char* argv[]) {
if (i + 1 == argc) print_help(argv[0]); if (i + 1 == argc) print_help(argv[0]);
char* val = argv[++i]; char* val = argv[++i];
memcpy(exe_name, val, strlen(val) + 1); 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; boot_delay = true;
} else if (strcmp(argv[i], "-t") == 0) { } else if (strcmp(argv[i], "-t") == 0) {
gametest = true; 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); fprintf(stderr, "exec: %s %s\n", exe_name, cmdline);
char micepath[MAX_PATH + 1]; 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; int frequency_loaded = 0;
LARGE_INTEGER frequency; LARGE_INTEGER frequency;
@ -13,7 +13,7 @@ amtime_t* amiTimerGet(amtime_t* time) {
frequency_loaded = 1; frequency_loaded = 1;
} }
QueryPerformanceCounter(&counter); QueryPerformanceCounter(&counter);
time->microseconds = (counter.QuadPart * 1000000) / frequency.QuadPart; time->microseconds = (unsigned int)((counter.QuadPart * 1000000) / frequency.QuadPart);
time->seconds = counter.QuadPart / frequency.QuadPart; time->seconds = (unsigned int)(counter.QuadPart / frequency.QuadPart);
return time; return time;
} }

View File

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

View File

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

View File

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

View File

@ -43,7 +43,7 @@
typedef unsigned int json_uchar; 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; } 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) if (state.first_pass)
string_length += 2; string_length += 2;
else { else {
string[string_length++] = 0xC0 | (uchar >> 6); string[string_length++] = (char)(0xC0 | (uchar >> 6));
string[string_length++] = 0x80 | (uchar & 0x3F); string[string_length++] = (char)(0x80 | (uchar & 0x3F));
} }
break; break;
@ -274,9 +274,9 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
if (state.first_pass) if (state.first_pass)
string_length += 3; string_length += 3;
else { else {
string[string_length++] = 0xE0 | (uchar >> 12); string[string_length++] = 0xE0 | (char)((uchar >> 12));
string[string_length++] = 0x80 | ((uchar >> 6) & 0x3F); string[string_length++] = 0x80 | (char)(((uchar >> 6) & 0x3F));
string[string_length++] = 0x80 | (uchar & 0x3F); string[string_length++] = 0x80 | (char)((uchar & 0x3F));
} }
break; break;
@ -285,10 +285,10 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
if (state.first_pass) if (state.first_pass)
string_length += 4; string_length += 4;
else { else {
string[string_length++] = 0xF0 | (uchar >> 18); string[string_length++] = 0xF0 | (char)((uchar >> 18));
string[string_length++] = 0x80 | ((uchar >> 12) & 0x3F); string[string_length++] = 0x80 | (char)(((uchar >> 12) & 0x3F));
string[string_length++] = 0x80 | ((uchar >> 6) & 0x3F); string[string_length++] = 0x80 | (char)(((uchar >> 6) & 0x3F));
string[string_length++] = 0x80 | (uchar & 0x3F); string[string_length++] = 0x80 | (char)((uchar & 0x3F));
} }
break; 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)) #define ZERO_BUF(x) memset((x), 0, sizeof(*x))
#include <Winsock2.h> #include <Winsock2.h>
#include <ws2ipdef.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -29,7 +30,7 @@ typedef unsigned char byte;
typedef unsigned short ushort; typedef unsigned short ushort;
typedef unsigned int uint; typedef unsigned int uint;
typedef int timeout_t; typedef unsigned int timeout_t;
#define PCP_BUF_MAX 256 #define PCP_BUF_MAX 256
#define PCP_CMDS_MAX 64 #define PCP_CMDS_MAX 64
@ -43,7 +44,7 @@ typedef struct pcp_parse_data {
uint cmd_count; uint cmd_count;
} pcp_parse_data_t; } pcp_parse_data_t;
typedef struct pcp_send_data { typedef struct pcp_send_data {
char data[PCP_BUF_MAX]; unsigned char data[PCP_BUF_MAX];
size_t length; size_t length;
} pcp_send_data_t; } pcp_send_data_t;
@ -63,8 +64,9 @@ typedef enum binary_mode {
#define PCPT_SO_LINGER 2 #define PCPT_SO_LINGER 2
#define PCPT_TCP_NODELAY 3 #define PCPT_TCP_NODELAY 3
#define SOCKET_INVAL ((SOCKET)-1)
#define HANDLE_INVAL -1 #define HANDLE_INVAL -1
#define TIMEOUT_NONE -1 #define TIMEOUT_NONE ((DWORD)-1)
#define PCPT_CLOSED 0 #define PCPT_CLOSED 0
#define PCPT_LISTENING 1 #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; pcpa_cb_table_t* callback_table;
uint callback_max; uint callback_max;
uint callback_count; uint callback_count;
char* recv_buffer; unsigned char* recv_buffer;
size_t recv_buffer_len; size_t recv_buffer_len;
char* send_buffer; unsigned char* send_buffer;
size_t send_buffer_len; size_t send_buffer_len;
binary_mode_t binary_mode; binary_mode_t binary_mode;
pcpa_callback* binary_mode_before_cb; 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_inval_addr = -15,
e_pcpp_wsa_noinit = -16, e_pcpp_wsa_noinit = -16,
e_pcpp_unknown = -17, 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;
e_pcpp_t _pcppGetErrorFromPcpt(e_pcpt_t err); e_pcpp_t _pcppGetErrorFromPcpt(e_pcpt_t err);
@ -32,17 +40,17 @@ typedef struct pcpp {
uint state; uint state;
e_pcpp_t err; e_pcpp_t err;
pcp_parse_data_t* recv_data_buffer; 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_size;
uint read_bytes_num; uint read_bytes_num;
pcp_send_data_t* resp_buffer; pcp_send_data_t* resp_buffer;
uint resp_buffer_len; uint resp_buffer_len;
char send_buf[PCP_SEND_BUF_MAX]; unsigned char send_buf[PCP_SEND_BUF_MAX];
size_t send_buf_len; size_t send_buf_len;
uint field_0x1e8; uint field_0x1e8;
char* send_binary_buf; unsigned char* send_binary_buf;
uint field_0x1f0; uint field_0x1f0;
char* recv_binary_buf; unsigned char* recv_binary_buf;
size_t field_0x1f8; size_t field_0x1f8;
uint field_0x1fc; uint field_0x1fc;
size_t recv_binary_buf_len; size_t recv_binary_buf_len;
@ -56,13 +64,13 @@ typedef struct pcpp {
} pcpp_t; } pcpp_t;
pcp_send_data_t* pcppAddSendPacket(pcp_send_data_t* stream, char* key, char* value); 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); bool pcppCheckPrompt(pcpp_t* stream);
e_pcpp_t pcppCheckRecvMsg(char* recv_data, size_t buf_len, int param_3); e_pcpp_t pcppCheckRecvMsg(unsigned char* recv_data, size_t buf_len, int param_3);
uint pcppCheckStr(char* param_1, uint* pcp_len, int* pcp_overflow); uint pcppCheckStr(unsigned char* param_1, uint* pcp_len, int* pcp_overflow);
void pcppClose(pcpp_t* stream); void pcppClose(pcpp_t* stream);
void pcppCloseBinary(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* pcppGetCommand(pcp_parse_data_t* pcpa, char* command);
char* pcppGetKeyword(pcp_parse_data_t* recvData, uint keyword_num); char* pcppGetKeyword(pcp_parse_data_t* recvData, uint keyword_num);
SOCKET pcppGetServerSocket(pcpp_t* stream, int which); 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 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 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 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); e_pcpp_t pcppRecvBinary(pcpp_t* stream, unsigned char* recv_buf, size_t buf_len, uint param_4);
uint pcppRecvCheck(char* buf, int* found_at); uint pcppRecvCheck(unsigned char* buf, int* found_at);
e_pcpp_t pcppRecvPrompt(pcpp_t* stream, undefined4 param_2, int param_3); 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 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 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 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, int param_3); e_pcpp_t pcppSendPrompt(pcpp_t* stream, uint param_2, timeout_t timeout_ms);
e_pcpp_t pcppSendRequestMain(pcpp_t* stream, undefined4 param_2, int param_3); 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 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); 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); 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); size_t* send_len, undefined4 param_7, undefined4 param_8, e_pcpp_t fallback_err);
void pcppResetRead(pcpp_t* param_1); 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; uint tcp_nodelay;
WSAEVENT client_event; WSAEVENT client_event;
WSAEVENT server_event; WSAEVENT server_event;
char* send_buf; unsigned char* send_buf;
size_t* send_buf_count; size_t* send_buf_count;
char* recv_buf; unsigned char* recv_buf;
size_t* recv_buf_count; size_t* recv_buf_count;
uint field_0x40; uint field_0x40;
SOCKADDR client_addr; 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 pcptIsBusy(pcpt_t* sock, timeout_t timeout_ms);
e_pcpt_t pcptOpenDataSockServer(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 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 pcptRecv(pcpt_t* sock, unsigned 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 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); e_pcpt_t pcptSendAllMsg(pcpt_t* sock, timeout_t timeout_ms);
void pcptSetConfig(pcpt_t* sock, uint config, uint value); 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('util') # This is the only lib that should ever be link_with'd by another lib
subdir('json') subdir('json')
subdir('am')
subdir('dmi') subdir('dmi')
subdir('mice') subdir('mice')
subdir('am')
fs = import('fs') fs = import('fs')
# Handle the fact we aren't distributing the libpcp source subdir('libpcp')
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

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

View File

@ -5,8 +5,10 @@
// amSramInit // amSramInit
#define IOCTL_MXSRAM_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_MXSRAM_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
// amSramInit // amSramInit
#define IOCTL_MXSRAM_GET_SECTOR_SIZE CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) #define IOCTL_MXSRAM_GET_SECTOR_SIZE \
#define IOCTL_MXSRAM_GET_VERSION CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS) 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 // EEPROM uses MXSMBUS_GUID device class
// DIPSW 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) #define IOCTL_MXSUPERIO_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
// amHmGetLPCChipId // amHmGetLPCChipId
#define IOCTL_MXSUPERIO_READ CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) #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 // 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 // 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) #define IOCTL_MXJVS_EXCHANGE CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
@ -37,20 +41,29 @@
// amHmI2CReadByte,amHmI2CWriteByte,amEepromWait // amHmI2CReadByte,amHmI2CWriteByte,amEepromWait
#define IOCTL_MXSMBUS_REQUEST CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_MXSMBUS_REQUEST CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
// amEepromGetDriverVerision // 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 // amEepromI2CReadBlock,amEepromI2CWriteBlock,amHmGetLPCChipId
#define IOCTL_MXSMBUS_I2C CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS) #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_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_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_WRITE_DATA \
#define IOCTL_MXPARALLEL_READ_DATA CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS) CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_STATUS CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define IOCTL_MXPARALLEL_READ_DATA \
#define IOCTL_MXPARALLEL_READ_STATUS CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS) CTL_CODE(FILE_DEVICE_SEGA, 0x801, 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_WRITE_STATUS \
#define IOCTL_MXPARALLEL_READ_CTRL_PORT CTL_CODE(FILE_DEVICE_SEGA, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS) CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
#define IOCTL_MXPARALLEL_WRITE_FLAGS CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS) #define IOCTL_MXPARALLEL_READ_STATUS \
#define IOCTL_MXPARALLEL_READ_FLAGS CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS) 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; json_value* fetched;
if (!fetch(object, name, &fetched)) return false; if (!fetch(object, name, &fetched)) return false;
if (fetched->type != json_integer) return false; if (fetched->type != json_integer) return false;
*value = fetched->u.integer; *value = (size_t)fetched->u.integer;
return true; return true;
} }
bool fetch_bool(json_value* object, char* name, bool* value) { 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; if (patches->nopatchsets == 0) return;
for (int i = patches->nopatchsets - 1; i >= 0; i--) { for (int i = patches->nopatchsets - 1; i >= 0; i--) {
if (patches->patchsets[i] != NULL) { 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].from != NULL) free(patches->patchsets[i]->patches[j].from);
if (patches->patchsets[i]->patches[j].to != NULL) free(patches->patchsets[i]->patches[j].to); 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); snprintf(error, json_error_max, "invalid hex string in patch %s[%d]", name, j);
goto failed; goto failed;
} }
char* bin_from = patchset->patches[j].from = (char*)malloc(size / 2); unsigned char* bin_from = patchset->patches[j].from = (unsigned char*)malloc(size / 2);
char* bin_to = patchset->patches[j].to = (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)) { if (!hex_to_bin(from, bin_from, size)) {
snprintf(error, json_error_max, "invalid hex string in patch %s[%d].from", name, j); snprintf(error, json_error_max, "invalid hex string in patch %s[%d].from", name, j);
goto failed; goto failed;

View File

@ -4,5 +4,5 @@ subdir('micepatch')
subdir('micekeychip') subdir('micekeychip')
subdir('launcher') subdir('launcher')
subdir('dll') subdir('dll')
subdir('miceboot')
subdir('micetest') 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"); pcpaSetSendPacket(stream, AB_SEED, "0");
pcpaAddSendPacket(stream, "port", "40107"); pcpaAddSendPacket(stream, "port", "40107");
char sSize[16]; // todo: nicer lol 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); pcpaAddSendPacket(stream, "size", sSize);
} }

View File

@ -106,6 +106,6 @@ void mxkPcpPbCaCertification(pcpa_t* stream, void* data) {
pcpaSetSendPacket(stream, BIL_CACERT, "0"); pcpaSetSendPacket(stream, BIL_CACERT, "0");
pcpaAddSendPacket(stream, "port", "40107"); pcpaAddSendPacket(stream, "port", "40107");
char sSize[16]; // todo: nicer lol 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); pcpaAddSendPacket(stream, "size", sSize);
} }

View File

@ -1,14 +1,6 @@
dependencies = [] 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) rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico)
executable( executable(

View File

@ -22,7 +22,8 @@ int mxkInit() {
} }
void log_callback(struct pcpa* stream, void* data) { 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) { if (log_file != NULL) {
fprintf(log_file, "%s\n", (char*)data); fprintf(log_file, "%s\n", (char*)data);
fclose(log_file); fclose(log_file);

View File

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