Quite a lot has happened; I lose track
This commit is contained in:
parent
4464d9188f
commit
f02db82030
5
.gitignore
vendored
5
.gitignore
vendored
@ -3,8 +3,3 @@ build/
|
||||
builddir/
|
||||
srcdir/
|
||||
.vscode/
|
||||
|
||||
# Don't distribute the libpcp sources
|
||||
src/micetools/lib/libpcp/*.c
|
||||
# And keep build artifacts out of git!
|
||||
src/libpcp.lib
|
||||
|
20
Makefile
20
Makefile
@ -46,9 +46,13 @@ clean:
|
||||
|
||||
.PHONY: dist
|
||||
dist:
|
||||
@-mkdir $(DIST_DIR)
|
||||
@-mkdir $(DIST_DIR) > NUL 2>&1
|
||||
@-mkdir $(DIST_DIR)\util > NUL 2>&1
|
||||
@-mkdir $(DIST_DIR)\Execute > NUL 2>&1
|
||||
@-mkdir $(DIST_DIR)\Execute\Z > NUL 2>&1
|
||||
@-mkdir $(DIST_DIR)\Execute\S > NUL 2>&1
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micekeychip\micekeychip.exe" "$(DIST_DIR)/micekeychip.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/micepatch.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/lib/libpcp\libpcp.lib" "$(DIST_DIR)/libpcp.lib"
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice86.exe"
|
||||
@ -58,6 +62,18 @@ dist:
|
||||
# @copy /Y "$(BUILD_DIR_64)/src/micetools/launcher\mice.exe" "$(DIST_DIR)/mice64.exe"
|
||||
# @copy /Y "$(BUILD_DIR_64)/src/micetools/dll\mice.dll" "$(DIST_DIR)/mice64.dll"
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\miceprestartup.exe" "$(DIST_DIR)/Execute/miceprestartup.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\micestartup.exe" "$(DIST_DIR)/Execute/micestartup.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\TrueCrypt.exe" "$(DIST_DIR)/Execute/TrueCrypt.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/miceboot\mxmaster.exe" "$(DIST_DIR)/Execute/S/mxmaster.exe"
|
||||
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/micepatch\micepatch.exe" "$(DIST_DIR)/util/micepatch.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micedump.exe" "$(DIST_DIR)/util/micedump.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micetinker.exe" "$(DIST_DIR)/util/micetinker.exe"
|
||||
@copy /Y "$(BUILD_DIR_32)/src/micetools/util\micemonitor.exe" "$(DIST_DIR)/util/micemonitor.exe"
|
||||
|
||||
@copy /Y "src/micetools/miceboot\TrueCrypt.cmd" "$(DIST_DIR)/Execute/TrueCrypt.cmd"
|
||||
|
||||
@xcopy /E /H /C /R /Q /Y src\system "$(DIST_DIR)\system/*"
|
||||
@xcopy /E /H /C /R /Q /Y src\tools "$(DIST_DIR)\tools/*"
|
||||
@xcopy /E /H /C /R /Q /Y src\patches "$(DIST_DIR)\patches/*"
|
||||
|
62
assert_dd_blocks.py
Normal file
62
assert_dd_blocks.py
Normal 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")
|
20
meson.build
20
meson.build
@ -1,8 +1,8 @@
|
||||
project('micetools', 'c', default_options: [
|
||||
'buildtype=minsize',
|
||||
# ! Tobble /\ and \/ when building for XP (minsize=normal, static=XP)
|
||||
# ! Toggle /\ and \/ when building for XP (minsize=normal, static=XP)
|
||||
# 'b_vscrt=static_from_buildtype',
|
||||
'warning_level=2',
|
||||
'warning_level=3',
|
||||
])
|
||||
|
||||
winxp = false
|
||||
@ -15,6 +15,22 @@ endif
|
||||
add_project_arguments(
|
||||
'/DWIN32_LEAN_AND_MEAN', # Strip out headers we don't really need
|
||||
'/D_WIN32_WINNT=_WIN32_WINNT_WINXP', # hahahahaha I hate it
|
||||
|
||||
'/wd4706', # assignment within conditional expression
|
||||
'/wd4214', # windns.h: nonstandard extension used: bit field types other than int
|
||||
'/wd4201', # ewfapi.h: nameless struct/union
|
||||
'/wd4200', # zero-sized arrays
|
||||
'/wd4152', # hooks: function/data pointer conversion in expression
|
||||
'/wd4100', # basically every hook causes "unreferenced formal parameter"
|
||||
'/wd4206', # empty C files
|
||||
|
||||
'/wd4189', # lots of keychip functions aren't 100% implemented yet
|
||||
|
||||
'/we4047', # ... differs in levels of indirection from ...
|
||||
'/we4057', # ... differs in levels of indirection (slightly) from ...
|
||||
'/we4024', # ... different types for formal and actual paramter ...
|
||||
'/we4013', # ... undefined; assuming extern returning int
|
||||
|
||||
language: 'c',
|
||||
)
|
||||
if winxp
|
||||
|
159
mxinstaller.py
Normal file
159
mxinstaller.py
Normal 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)
|
@ -36,16 +36,16 @@ BOOL DevClearCommError(void* data, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL DevWriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
BOOL DevWriteFile(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
||||
if (nNumberOfBytesToWrite > 0xffff) return FALSE;
|
||||
// Ignore overflow
|
||||
ringbuf_write(&((com_device_t*)file)->in, lpBuffer, nNumberOfBytesToWrite & 0xffff);
|
||||
if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = nNumberOfBytesToWrite;
|
||||
return TRUE;
|
||||
}
|
||||
BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
||||
if (nNumberOfBytesToRead > 0xffff) return FALSE;
|
||||
|
||||
// Make sure we have at least one byte to return
|
||||
@ -59,22 +59,99 @@ BOOL DevReadFile(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWOR
|
||||
if (read != 0) {
|
||||
// log_info("drf", "%d", read);
|
||||
// for (int i = 0; i < read; i++) {
|
||||
// printf("%02x ", ((unsigned char*)lpBuffer)[i]);
|
||||
// printf("%02x ", ((LPBYTE)lpBuffer)[i]);
|
||||
// }
|
||||
// puts("");
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
short comdev_read_blocking(com_device_t* com, unsigned char* buffer, short bytes) {
|
||||
while (comdev_available(com) < bytes) SwitchToThread();
|
||||
return ringbuf_read(&com->in, buffer, bytes);
|
||||
}
|
||||
short comdev_read(com_device_t* com, unsigned char* buffer, short bytes) {
|
||||
return ringbuf_read(&com->in, buffer, bytes);
|
||||
}
|
||||
bool comdev_write(com_device_t* com, unsigned char* buffer, short bytes) {
|
||||
bool comdev_write(com_device_t* com, const unsigned char* buffer, short bytes) {
|
||||
bool ret = ringbuf_write(&com->out, buffer, bytes);
|
||||
SetEvent(com->event);
|
||||
return ret;
|
||||
}
|
||||
short comdev_available(com_device_t* com) { return ringbuf_available(&com->in); }
|
||||
BYTE comdev_peek(com_device_t* com) { return com->in.buffer[com->in.read]; }
|
||||
|
||||
BYTE one_byte;
|
||||
// Read data from a com device, unescaping as we go
|
||||
void comio_read(com_device_t* com, BYTE* data, BYTE len) {
|
||||
for (; len; len--) {
|
||||
comdev_read_blocking(com, &one_byte, 1);
|
||||
if (one_byte == COMIO_MARK) {
|
||||
comdev_read_blocking(com, &one_byte, 1);
|
||||
one_byte++;
|
||||
}
|
||||
*(data++) = one_byte;
|
||||
}
|
||||
}
|
||||
// Write data to a com device, escaping as we go
|
||||
void comio_write(com_device_t* com, BYTE* data, BYTE len) {
|
||||
for (; len; len--) {
|
||||
one_byte = *(data++);
|
||||
if (one_byte == COMIO_MARK || one_byte == COMIO_SYNC) {
|
||||
BYTE mark = COMIO_MARK;
|
||||
comdev_write(com, &mark, 1);
|
||||
one_byte--;
|
||||
}
|
||||
comdev_write(com, &one_byte, 1);
|
||||
}
|
||||
}
|
||||
void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data) {
|
||||
do {
|
||||
if (comdev_available(com) < (sizeof *head + 1)) {
|
||||
SwitchToThread();
|
||||
continue;
|
||||
}
|
||||
comdev_read(com, &one_byte, 1);
|
||||
if (one_byte != COMIO_SYNC) {
|
||||
log_error("com", "Garbage on JVS: %02x", one_byte);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
comio_read(com, (LPBYTE)head, sizeof *head);
|
||||
|
||||
// TODO: Validate the sum? Do we care really?
|
||||
comio_read(com, data, head->length);
|
||||
unsigned char sum;
|
||||
comio_read(com, &sum, 1);
|
||||
}
|
||||
void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len,
|
||||
BYTE* data) {
|
||||
one_byte = COMIO_SYNC;
|
||||
comdev_write(com, &one_byte, 1);
|
||||
|
||||
comio_resp_head_t resp = {
|
||||
.frame_length = len + sizeof resp,
|
||||
.src = req->dst,
|
||||
.seq = req->seq,
|
||||
.status = status,
|
||||
.op = req->op,
|
||||
.length = len,
|
||||
};
|
||||
// Header
|
||||
comio_write(com, (LPBYTE)&resp, sizeof resp);
|
||||
// Payload
|
||||
if (len) // If len == 0, we allow data to be null
|
||||
comio_write(com, data, len);
|
||||
// Checksum
|
||||
one_byte = 0;
|
||||
for (BYTE i = 0; i < sizeof resp; i++)
|
||||
one_byte += ((LPBYTE)&resp)[i];
|
||||
for (BYTE i = 0; i < len; i++)
|
||||
one_byte += data[i];
|
||||
comio_write(com, &one_byte, 1);
|
||||
}
|
||||
|
||||
void com_device_thread(com_device_t* com, FnComDeviceThread* thread) {
|
||||
com->thread = CreateThread(NULL, 0, thread, com, 0, NULL);
|
||||
@ -109,8 +186,6 @@ com_device_t* new_com_device(BYTE port) {
|
||||
|
||||
hook_file(file);
|
||||
hook_com(com);
|
||||
free(com->virtual_handle);
|
||||
com->virtual_handle = file->virtual_handle;
|
||||
|
||||
return hook;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
#pragma once
|
||||
#include "hooks/com.h"
|
||||
#include "common.h"
|
||||
#include "hooks/com.h"
|
||||
#include "hooks/files.h"
|
||||
|
||||
typedef struct com_device {
|
||||
@ -13,11 +13,42 @@ typedef struct com_device {
|
||||
HANDLE thread;
|
||||
} com_device_t;
|
||||
|
||||
typedef struct {
|
||||
BYTE frame_length;
|
||||
BYTE dst;
|
||||
BYTE seq;
|
||||
BYTE op;
|
||||
BYTE length;
|
||||
} comio_recv_head_t;
|
||||
|
||||
typedef struct {
|
||||
BYTE frame_length;
|
||||
BYTE src;
|
||||
BYTE seq;
|
||||
BYTE op;
|
||||
BYTE status;
|
||||
BYTE length;
|
||||
} comio_resp_head_t;
|
||||
|
||||
#define COMIO_SYNC 0xE0
|
||||
#define COMIO_MARK 0xD0
|
||||
|
||||
#define COMIO_STATUS_OK 0
|
||||
#define COMIO_STATUS_NG 1
|
||||
|
||||
typedef DWORD(WINAPI FnComDeviceThread)(com_device_t* com);
|
||||
|
||||
short comdev_read_blocking(com_device_t* com, unsigned char* buffer, short bytes);
|
||||
short comdev_read(com_device_t* com, unsigned char* buffer, short bytes);
|
||||
bool comdev_write(com_device_t* com, unsigned char* buffer, short bytes);
|
||||
bool comdev_write(com_device_t* com, const unsigned char* buffer, short bytes);
|
||||
short comdev_available(com_device_t* com);
|
||||
BYTE comdev_peek(com_device_t* com);
|
||||
|
||||
void comio_read(com_device_t* com, BYTE* data, BYTE len);
|
||||
void comio_write(com_device_t* com, BYTE* data, BYTE len);
|
||||
|
||||
void comio_next_req(com_device_t* com, comio_recv_head_t* head, BYTE* data);
|
||||
void comio_reply(com_device_t* com, comio_recv_head_t* req, BYTE status, BYTE len, BYTE* data);
|
||||
|
||||
void com_device_thread(com_device_t* com, FnComDeviceThread* thread);
|
||||
com_device_t* new_com_device(BYTE port);
|
@ -15,6 +15,7 @@
|
||||
#include <setupapi.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -3,4 +3,5 @@
|
||||
void install_devices() {
|
||||
install_led_bd();
|
||||
install_touch_bd();
|
||||
install_aime_bd();
|
||||
}
|
||||
|
@ -4,5 +4,6 @@
|
||||
|
||||
void install_led_bd();
|
||||
void install_touch_bd();
|
||||
void install_aime_bd();
|
||||
|
||||
void install_devices();
|
90
src/micetools/dll/devices/aime_bd.c
Normal file
90
src/micetools/dll/devices/aime_bd.c
Normal 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);
|
||||
}
|
@ -73,6 +73,7 @@ typedef struct rs232c_recv_head {
|
||||
BYTE op;
|
||||
} rs232c_recv_head_t;
|
||||
|
||||
BYTE extra[0xff];
|
||||
static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
log_warning("led_bd", "%ls woke up", dev->com->wName);
|
||||
while (1) {
|
||||
@ -81,9 +82,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
// Sleep(100);
|
||||
continue;
|
||||
}
|
||||
comdev_read(dev, (char*)&head, sizeof head);
|
||||
|
||||
unsigned char* extra = malloc(head.length);
|
||||
comdev_read(dev, (unsigned char*)&head, sizeof head);
|
||||
comdev_read(dev, extra, head.length);
|
||||
|
||||
// log_info("led_bd", "Bound %02x->%02x", head.src, head.dst);
|
||||
@ -91,13 +90,13 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
switch (head.op) {
|
||||
case 0x01:
|
||||
log_warning("led_bd", "01");
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x01\x01\x18", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x01\x01\x18", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
case 0x10:
|
||||
log_warning("led_bd", "10");
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x10\x01\x27", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x10\x01\x27", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
@ -107,7 +106,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
COLOURS[extra[0]][2] = extra[3];
|
||||
|
||||
log_warning("led_bd", "31: %02x = (%02x %02x %02x)", extra[0], extra[1], extra[2], extra[3]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x31\x01\x48", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x31\x01\x48", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x32:
|
||||
@ -120,13 +119,13 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
COLOURS[i][2] = extra[5];
|
||||
}
|
||||
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x32\x01\x49", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x32\x01\x49", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x33:
|
||||
log_warning("led_bd", "33: %02x %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
||||
extra[4], extra[5], extra[6], extra[7]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x33\x01\x4a", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x33\x01\x4a", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
COLOURS[extra[0]][0] = extra[extra[5]];
|
||||
COLOURS[extra[0]][1] = extra[extra[6]];
|
||||
@ -135,7 +134,7 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
|
||||
case 0x39:
|
||||
log_warning("led_bd", "39: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x39\x01\x50", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x39\x01\x50", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
|
||||
COLOURS[9][0] = extra[0];
|
||||
@ -144,18 +143,18 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
break;
|
||||
case 0x3b:
|
||||
log_warning("led_bd", "3b");
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x3b\x01\x52", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3b\x01\x52", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3c:
|
||||
log_warning("led_bd", "3c (I am %ls)", dev->com->wName);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x3c\x01\x53", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3c\x01\x53", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
case 0x3f:
|
||||
log_warning("led_bd", "3f: %02x %02x %02x %02x %02x %02x", extra[0], extra[1], extra[2], extra[3],
|
||||
extra[4], extra[5], extra[6]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x3f\x01\x56", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
@ -163,14 +162,14 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
// extra[0] goes from 0 to 7
|
||||
// Could this be some sort of calibration for the buttons?
|
||||
log_warning("led_bd", "7c: %02x", extra[0]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x04\x01\x7c\x01\x00\x94", 9);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x00\x94", 9);
|
||||
// \/ causes 7b to be used
|
||||
// comdev_write(dev, "\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9);
|
||||
// comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x04\x01\x7c\x01\x10\xa4", 9);
|
||||
// syn dst src len sts op. rep --- chk
|
||||
break;
|
||||
case 0x7b:
|
||||
log_warning("led_bd", "7b: %02x %02x %02x", extra[0], extra[1], extra[2]);
|
||||
comdev_write(dev, "\xe0\x01\x11\x03\x01\x7b\x01\x92", 8);
|
||||
comdev_write(dev, (unsigned char*)"\xe0\x01\x11\x03\x01\x7b\x01\x92", 8);
|
||||
// syn dst src len sts op. rep chk
|
||||
break;
|
||||
|
||||
@ -178,8 +177,6 @@ static DWORD WINAPI led_bd_thread(com_device_t* dev) {
|
||||
log_error("led_bd", "Unknown op %02x (%d)", head.op, head.length - 1);
|
||||
break;
|
||||
}
|
||||
|
||||
free(extra);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,13 +197,13 @@ void led_overlay(IDirect3DDevice9* dev) {
|
||||
GetCursorPos(&cursor);
|
||||
|
||||
// log_info("led_overlay", "x: %d, y: %d", cursor.x, cursor.y);
|
||||
log_info("led_overlay", "x%: %f, y%: %f", (float)cursor.x / (float)rect.right,
|
||||
(float)(cursor.y - 26) / (float)rect.bottom);
|
||||
// log_info("led_overlay", "x%: %f, y%: %f", (float)cursor.x / (float)rect.right,
|
||||
// (float)(cursor.y - 26) / (float)rect.bottom);
|
||||
}
|
||||
|
||||
for (unsigned char i = 0; i < 10; i++) {
|
||||
int x = rect.right * positions[i][0];
|
||||
int y = rect.bottom * positions[i][1];
|
||||
int x = (int)(rect.right * positions[i][0]);
|
||||
int y = (int)(rect.bottom * positions[i][1]);
|
||||
draw_rect(dev, x - 25, y - 25, 50, 50, COLOURS[i][0], COLOURS[i][1], COLOURS[i][2]);
|
||||
}
|
||||
}
|
||||
|
@ -2,4 +2,5 @@ devices_files = files(
|
||||
'_devices.c',
|
||||
'led_bd.c',
|
||||
'touch_bd.c',
|
||||
'aime_bd.c',
|
||||
)
|
@ -3,7 +3,7 @@
|
||||
static BYTE read_one(com_device_t* dev) {
|
||||
while (!comdev_available(dev)) Sleep(50);
|
||||
BYTE data;
|
||||
comdev_read(dev, (char*)&data, 1);
|
||||
comdev_read(dev, &data, 1);
|
||||
return data;
|
||||
}
|
||||
|
||||
@ -21,7 +21,7 @@ DWORD WINAPI touch_bd_thread(com_device_t* dev) {
|
||||
while (1) {
|
||||
if (touch_is_enabled && !comdev_available(dev)) {
|
||||
// Active mode!
|
||||
comdev_write(dev, "(@@@@@@@@@@@@)", 14);
|
||||
comdev_write(dev, (unsigned char*)"(@@@@@@@@@@@@)", 14);
|
||||
Sleep(100);
|
||||
continue;
|
||||
}
|
||||
|
@ -39,12 +39,15 @@ void enable_traces() {
|
||||
free_patches(&patches);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void prebind_hooks() {
|
||||
hook_all();
|
||||
install_devices();
|
||||
|
||||
// TODO: Figure out why we're needing to call this manually (medium priority)
|
||||
if (wcscmp(exePath, L"ALLNetProc.exe") == 0) {
|
||||
log_warning(BOOT_LOGGER, "Making explicit call to OPENSSL_add_all_algorithms_noconf");
|
||||
|
||||
// OPENSSL_add_all_algorithms_noconf
|
||||
((void (*)(void))(0x00459770))();
|
||||
}
|
||||
@ -57,11 +60,17 @@ void init_injection() {
|
||||
|
||||
enable_traces();
|
||||
|
||||
// Columba: Driver-level memory access, used to read the DMI tables
|
||||
setup_columba();
|
||||
// MX SRAM: SRAM-based nv memory
|
||||
setup_mxsram();
|
||||
// MX SuperIO: Communicate with the HW monitor chip
|
||||
setup_mxsuperio();
|
||||
// MX JVS: Interacting with JVS-based devices
|
||||
setup_mxjvs();
|
||||
// MX HW Reset: Forcibly reboot the machine
|
||||
setup_mxhwreset();
|
||||
// MX SMBus: Communicate over the LPC bus. This contains the EEPROM, and PCA9535
|
||||
setup_mxsmbus();
|
||||
|
||||
if (!add_fake_device(&PLATFORM_GUID, L"\\\\.\\platform")) {
|
||||
|
@ -12,14 +12,12 @@ typedef struct {
|
||||
#define DMI_HEADER_START 0x000f0000
|
||||
#define DMI_TABLES_START 0x000f1000
|
||||
|
||||
BOOL columba_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
BOOL columba_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_COLUMBA_READ_DMI:
|
||||
log_misc("columba",
|
||||
"DeviceIoControl(<columba>, <read dmi>, 0x%p, 0x%x, -, "
|
||||
"0x%x, -, -)",
|
||||
case IOCTL_COLUMBA_READ:
|
||||
log_misc("columba", "DeviceIoControl(<columba>, <read>, 0x%p, 0x%x, -, 0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
columba_request* request = (columba_request*)lpInBuffer;
|
||||
log_info("columba", "Physical read: 0x%04x %ss at %08X", request->bytes,
|
||||
@ -50,12 +48,14 @@ BOOL columba_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
memcpy(lpOutBuffer, dmi_table, dmi_size);
|
||||
if (lpBytesReturned) *lpBytesReturned = 0x10000;
|
||||
} else {
|
||||
log_error("columna", "Request to unmapped memory location: %08x", request->addr);
|
||||
log_error("columba", "Request to unmapped memory location: %08x",
|
||||
request->addr);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
// Observed: IOCTL_KSEC_RNG_REKEY
|
||||
log_warning("columba", "unhandled 0x%08x", dwIoControlCode);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "../hooks/_hooks.h"
|
||||
#include "../common.h"
|
||||
#include "../../lib/am/amEeprom.h"
|
||||
|
||||
FnDeviceIoControl mxhwreset_DeviceIoControl;
|
||||
void setup_mxhwreset();
|
||||
@ -22,6 +23,3 @@ void setup_mxsuperio();
|
||||
|
||||
FnDeviceIoControl columba_DeviceIoControl;
|
||||
void setup_columba();
|
||||
|
||||
DEFINE_GUID(MXSMBUS_GUID, 0x5C49E1FE, 0x3FEC, 0x4B8D, 0xA4, 0xB5, 0x76, 0xBE, 0x70, 0x25, 0xD8, 0x42);
|
||||
DEFINE_GUID(PLATFORM_GUID, 0x86E0D1E0, 0x8089, 0x11D0, 0x9C, 0xE4, 0x08, 0x00, 0x3e, 0x30, 0x1F, 0x73);
|
||||
|
@ -50,7 +50,7 @@ int jvs_buttons[2][16] = {
|
||||
},
|
||||
};
|
||||
|
||||
short jvs_unpad(char* paddedData, short length, char* unpaddedData) {
|
||||
short jvs_unpad(unsigned char* paddedData, short length, unsigned char* unpaddedData) {
|
||||
short index = 0;
|
||||
bool escape = false;
|
||||
for (short i = 0; i < length; i++) {
|
||||
@ -64,12 +64,13 @@ short jvs_unpad(char* paddedData, short length, char* unpaddedData) {
|
||||
return index;
|
||||
}
|
||||
|
||||
short jvs_pad(char* unpaddedData, short length, char* paddedData, short paddedMax) {
|
||||
short jvs_pad(unsigned char* unpaddedData, short length, unsigned char* paddedData,
|
||||
short paddedMax) {
|
||||
short index = 0;
|
||||
for (short i = 0; i < length; i++) {
|
||||
if (i > paddedMax) return -1;
|
||||
|
||||
if (unpaddedData[i] == JVS_MARK || unpaddedData[i] == JVS_SYNC) {
|
||||
if (i != 0 && (unpaddedData[i] == JVS_MARK || unpaddedData[i] == JVS_SYNC)) {
|
||||
paddedData[index++] = JVS_MARK;
|
||||
paddedData[index++] = unpaddedData[i] - 1;
|
||||
} else {
|
||||
@ -81,7 +82,8 @@ short jvs_pad(char* unpaddedData, short length, char* paddedData, short paddedMa
|
||||
|
||||
const char JVS_ID[] = "SEGA ENTERPRISES,LTD.;I/O BD JVS;837-13551 ;Ver1.00;98/10";
|
||||
|
||||
void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, int* outCount) {
|
||||
void mxjvs_exchange(unsigned char* paddedIn, short inCount, unsigned char* outData, short maxOut,
|
||||
int* outCount) {
|
||||
unsigned char* inData = malloc(inCount);
|
||||
inCount = jvs_unpad(paddedIn, inCount, inData);
|
||||
unsigned char* response = malloc(maxOut);
|
||||
@ -105,7 +107,8 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
|
||||
unsigned char sum = 0;
|
||||
for (int i = 1; i < inCount - 1; i++) sum += inData[i];
|
||||
if (sum != inData[inCount - 1]) {
|
||||
log_error("mxjvs", "Checksum failed. Computed 0x%02x, expected 0x%02x", sum, inData[inCount - 1]);
|
||||
log_error("mxjvs", "Checksum failed. Computed 0x%02x, expected 0x%02x", sum,
|
||||
inData[inCount - 1]);
|
||||
status = JVS_STATUS_SUM;
|
||||
goto jvs_exchange_error;
|
||||
}
|
||||
@ -202,7 +205,7 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
|
||||
|
||||
break;
|
||||
case JVS_CMD_RECEIVE_MAIN_ID:
|
||||
unsigned char tempRead = -1;
|
||||
unsigned char tempRead = 0xff;
|
||||
while (tempRead != 0) jvs_read(tempRead);
|
||||
// TODO: Do we need to report here?
|
||||
break;
|
||||
@ -228,8 +231,10 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
int scancode = jvs_buttons[i][j * 8 + bit];
|
||||
|
||||
// Buttons on maimai use beam interrupt sensors, so logical high = unpressed.
|
||||
bool invert = ((j == 0 && (bit == 0 || bit == 2 || bit == 3)) || (j == 1 && bit >= 3));
|
||||
// Buttons on maimai use beam interrupt sensors, so logical high =
|
||||
// unpressed.
|
||||
bool invert = ((j == 0 && (bit == 0 || bit == 2 || bit == 3)) ||
|
||||
(j == 1 && bit >= 3));
|
||||
|
||||
if (invert)
|
||||
buttons |= (GetAsyncKeyState(scancode) >= 0) << bit;
|
||||
@ -254,6 +259,16 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
|
||||
|
||||
break;
|
||||
|
||||
case JVS_CMD_READ_COIN:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
unsigned char coin_count;
|
||||
jvs_read(coin_count);
|
||||
for (; coin_count; coin_count--) {
|
||||
jvs_write(0x00); // coin MSB
|
||||
jvs_write(0x00); // coin LSB
|
||||
}
|
||||
break;
|
||||
|
||||
case JVS_CMD_READ_ANALOGS:
|
||||
jvs_write(JVS_REPORT_OK);
|
||||
// TODO: Actually emulate these (super low priority)
|
||||
@ -276,7 +291,8 @@ void mxjvs_exchange(char* paddedIn, short inCount, char* outData, int maxOut, in
|
||||
if (i == 0) {
|
||||
if (!!(gpio_value & 0x80) != coin_solenoid) {
|
||||
coin_solenoid = !!(gpio_value & 0x80);
|
||||
log_info("mxjvs", "Coin solenoid: %s", coin_solenoid ? "Locked" : "Unlocked");
|
||||
log_info("mxjvs", "Coin solenoid: %s",
|
||||
coin_solenoid ? "Locked" : "Unlocked");
|
||||
}
|
||||
}
|
||||
|
||||
@ -300,7 +316,7 @@ jvs_exchange_error:
|
||||
respIndex = 4; // As if we've just written status, but nothing else
|
||||
|
||||
jvs_exchange_complete:
|
||||
response[2] = respIndex - 2; // respIndex doesn't include SUM yet
|
||||
response[2] = (respIndex - 2) & 0xFF; // respIndex doesn't include SUM yet
|
||||
response[3] = status;
|
||||
|
||||
// Compute and set the checksum
|
||||
@ -319,17 +335,18 @@ jvs_exchange_complete:
|
||||
free(inData);
|
||||
}
|
||||
|
||||
BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
BOOL mxjvs_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_MXJVS_EXCHANGE:
|
||||
log_misc("mxjvs",
|
||||
log_trace("mxjvs",
|
||||
"DeviceIoControl(<mxjvs>, <exchange>, 0x%p, 0x%x, -, "
|
||||
"0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize, lpBytesReturned);
|
||||
mxjvs_exchange(lpInBuffer, nInBufferSize & 0xffff, lpOutBuffer, nOutBufferSize & 0xFFFF,
|
||||
(int*)lpBytesReturned);
|
||||
|
||||
break;
|
||||
default:
|
||||
@ -353,8 +370,8 @@ BOOL mxjvs_GetCommModemStatus(void* com, LPDWORD lpModelStat) {
|
||||
BOOL mxjvs_SetCommState(void* com, LPDCB lpDCB) {
|
||||
char PARITY[] = { 'N', 'O', 'E', 'M', 'S' };
|
||||
char* STOP[] = { "1", "1.5", "2" };
|
||||
log_info("mxjvs", "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize, PARITY[lpDCB->Parity],
|
||||
STOP[lpDCB->StopBits]);
|
||||
log_info("mxjvs", "Switching to %d baud (%d%c%s)", lpDCB->BaudRate, lpDCB->ByteSize,
|
||||
PARITY[lpDCB->Parity], STOP[lpDCB->StopBits]);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@ -362,7 +379,9 @@ void setup_mxjvs() {
|
||||
file_hook_t* mxjvs = new_file_hook(L"\\\\.\\mxjvs");
|
||||
mxjvs->DeviceIoControl = &mxjvs_DeviceIoControl;
|
||||
|
||||
com_hook_t* jvscom = new_com_hook(-1);
|
||||
com_hook_t* jvscom = new_com_hook(0);
|
||||
wcscpy_s(jvscom->wName, sizeof jvscom->wName, L"\\\\.\\mxjvs");
|
||||
wcscpy_s(jvscom->wDosName, sizeof jvscom->wDosName, L"\\\\.\\mxjvs");
|
||||
jvscom->GetCommState = mxjvs_GetCommState;
|
||||
jvscom->SetCommState = mxjvs_SetCommState;
|
||||
jvscom->SetCommTimeouts = mxjvs_SetCommTimeouts;
|
||||
@ -372,6 +391,4 @@ void setup_mxjvs() {
|
||||
|
||||
hook_file(mxjvs);
|
||||
hook_com(jvscom);
|
||||
free(jvscom->virtual_handle);
|
||||
jvscom->virtual_handle = mxjvs->virtual_handle;
|
||||
}
|
||||
|
@ -1,33 +1,8 @@
|
||||
#include "../lib/dmi/dmi.h"
|
||||
#include "../hooks/setupapi_.h"
|
||||
#include "../lib/dmi/dmi.h"
|
||||
#include "mx.h"
|
||||
#include "smbus.h"
|
||||
|
||||
// PCA9535 (DIPSW)
|
||||
#define PCA9535_WRITE 0x04
|
||||
#define PCA9535_READ 0x05
|
||||
|
||||
#define PCA9535_IN0 0x00
|
||||
#define PCA9535_IN1 0x01
|
||||
#define PCA9535_OUT0 0x02
|
||||
#define PCA9535_OUT1 0x03
|
||||
#define PCA9535_INV0 0x04
|
||||
#define PCA9535_INV1 0x05
|
||||
#define PCA9535_CONF0 0x06
|
||||
#define PCA9535_CONF1 0x07
|
||||
|
||||
#define SMBUS_PCA9535 0x20
|
||||
#define SMBUS_EEPROM 0x57 // Doesn't line up with manual!
|
||||
|
||||
#define SMBUS_DDR2_DIMM_A1 0x000 // what does 0xA0 mean?
|
||||
#define SMBUS_DDR2_DIMM_B1 0x010 // what does 0xA4 mean?
|
||||
#define SMBUS_EEPROM_ 0x0AE // = AT24C64AN
|
||||
#define SMBUS_ICS9LPRS908 0xfff // Unknown
|
||||
#define SMBUS_W83627UHG 0xfff // Unknown; hwmon. Possibly 0x2e or 0x4e
|
||||
#define SMBUS_UPI_UP6261BM8 0xfff // Unknown; vref
|
||||
#define SMBUS_UPI_ISL6322CR 0xfff // Unknown; vrm
|
||||
// SMBUS is send onto the mezzanine board!
|
||||
|
||||
#define EEPROM_DUMP L"dev/eeprom.bin"
|
||||
typedef struct eeprom_reg {
|
||||
BYTE data[32];
|
||||
@ -47,19 +22,26 @@ eeprom_bank_t EEPROM_DATA;
|
||||
*/
|
||||
|
||||
void eeprom_dump() {
|
||||
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
HANDLE dump =
|
||||
_CreateFileW(EEPROM_DUMP, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
log_error("eeprom", "CreateFileA(EEPROM_DUMP) failed");
|
||||
return;
|
||||
} else {
|
||||
log_info("eeprom", "Wrote eeprom to %s", EEPROM_DUMP);
|
||||
}
|
||||
_WriteFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, NULL, NULL);
|
||||
FlushFileBuffers(dump);
|
||||
_CloseHandle(dump);
|
||||
}
|
||||
void eeprom_restore() {
|
||||
HANDLE dump =
|
||||
_CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) return;
|
||||
HANDLE dump = _CreateFileW(EEPROM_DUMP, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING,
|
||||
FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (dump == INVALID_HANDLE_VALUE) {
|
||||
// Make the file, even though it'll probably be empty
|
||||
eeprom_dump();
|
||||
return;
|
||||
}
|
||||
DWORD read;
|
||||
if (!_ReadFile(dump, &EEPROM_DATA, sizeof EEPROM_DATA, &read, NULL))
|
||||
log_error("eeprom", "failed to restore (%d)", GetLastError());
|
||||
@ -77,16 +59,20 @@ DWORD eeprom_crc(BYTE reg) {
|
||||
return crc32(28, EEPROM_DATA.reg[reg].data + 4, 0);
|
||||
}
|
||||
void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) {
|
||||
log_game("eeprom", "EEPROM READ %d %d %d", reg, index, length);
|
||||
|
||||
eeprom_restore();
|
||||
for (BYTE i = index; i < index + length; i++) {
|
||||
if (i > 0x1f) break;
|
||||
|
||||
BYTE byte = EEPROM_DATA.reg[reg].data[i];
|
||||
|
||||
// TODO: Reg 1 and 17 in the EEPROM are system info. We should fake these!
|
||||
|
||||
// If register has a CRC
|
||||
// if (reg == 0x00 || reg == 0x01 || reg == 0x02 || reg == 0x10 || reg
|
||||
// == 0x11 || reg == 0x12 || reg == 0x200) {
|
||||
if (true) {
|
||||
if (false) {
|
||||
// Intercept the read and inject a CRC instead
|
||||
if (i == 0x00 || i == 0x01 || i == 0x02 || i == 0x03) {
|
||||
DWORD crc = eeprom_crc(reg);
|
||||
@ -98,6 +84,8 @@ void eeprom_read(BYTE reg, BYTE index, BYTE* data, BYTE length) {
|
||||
}
|
||||
}
|
||||
void eeprom_write(BYTE reg, BYTE index, BYTE* data, BYTE length) {
|
||||
log_game("eeprom", "EEPROM WRITE %d %d %d", reg, index, length);
|
||||
|
||||
for (BYTE i = index; i < index + length; i++) {
|
||||
if (i > 0x1f) break;
|
||||
EEPROM_DATA.reg[reg].data[i] = data[i - index];
|
||||
@ -112,9 +100,9 @@ BYTE eeprom_read_one(BYTE reg, BYTE index) {
|
||||
}
|
||||
void eeprom_write_one(BYTE reg, BYTE index, BYTE data) { eeprom_write(reg, index, &data, 1); }
|
||||
|
||||
BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
mxsmbus_i2c_packet* i2c_packet = (mxsmbus_i2c_packet*)lpInBuffer;
|
||||
mxsmbus_i2c_packet* i2c_out = (mxsmbus_i2c_packet*)lpOutBuffer;
|
||||
|
||||
@ -123,6 +111,8 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
|
||||
BYTE dlen;
|
||||
|
||||
static uint16_t pca9535_config = 0xffff;
|
||||
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_MXSMBUS_GET_VERSION:
|
||||
log_misc("mxsmbus",
|
||||
@ -134,7 +124,7 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||
break;
|
||||
case IOCTL_MXSMBUS_REQUEST: // dip r/w
|
||||
log_misc("mxsmbus",
|
||||
log_trace("mxsmbus",
|
||||
"DeviceIoControl(<mxsmbus>, <request>, 0x%p, 0x%x, -, "
|
||||
"0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
@ -171,22 +161,31 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
switch (i2c_packet->prt) {
|
||||
case PCA9535_WRITE:
|
||||
switch (i2c_packet->reg) {
|
||||
case PCA9535_OUT0:
|
||||
log_info("mxsmbus", "pca9535 OUT0: %02x", i2c_packet->data[0]);
|
||||
break;
|
||||
case PCA9535_OUT1:
|
||||
log_info("mxsmbus", "pca9535 OUT1: %02x %02x", i2c_packet->data[0],
|
||||
i2c_packet->data[1]);
|
||||
log_info("mxsmbus", "pca9535 OUT1: %02x", i2c_packet->data[0]);
|
||||
break;
|
||||
case PCA9535_INV0:
|
||||
log_info("mxsmbus", "pca9535 INV0: %02x %02x", i2c_packet->data[0],
|
||||
i2c_packet->data[1]);
|
||||
log_info("mxsmbus", "pca9535 INV0: %02x", i2c_packet->data[0]);
|
||||
break;
|
||||
case PCA9535_INV1:
|
||||
log_info("mxsmbus", "pca9535 INV1: %02x %02x", i2c_packet->data[0],
|
||||
i2c_packet->data[1]);
|
||||
log_info("mxsmbus", "pca9535 INV1: %02x", i2c_packet->data[0]);
|
||||
break;
|
||||
case PCA9535_CONF0:
|
||||
log_info("mxsmbus", "pca9535 CONF0: %02x", i2c_packet->data[0]);
|
||||
pca9535_config =
|
||||
(i2c_packet->data[0] << 8) | (pca9535_config & 0xff);
|
||||
break;
|
||||
case PCA9535_CONF1:
|
||||
log_info("mxsmbus", "pca9535 CONF1: %02x", i2c_packet->data[0]);
|
||||
pca9535_config =
|
||||
i2c_packet->data[0] | (pca9535_config & 0xff00);
|
||||
break;
|
||||
default:
|
||||
log_error("mxsmbux",
|
||||
"(write) Undefined pca9535 "
|
||||
"register: 0x%02x",
|
||||
log_error("mxsmbus",
|
||||
"(write) Undefined pca9535 register: 0x%02x",
|
||||
i2c_packet->reg);
|
||||
exit(1);
|
||||
}
|
||||
@ -194,28 +193,54 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
case PCA9535_READ:
|
||||
switch (i2c_packet->reg) {
|
||||
case PCA9535_IN0: // DIPSW
|
||||
i2c_packet->data[0] = 0x00;
|
||||
/*
|
||||
0: ?
|
||||
1: ?
|
||||
2: ?
|
||||
3: Orientation
|
||||
4: / \
|
||||
5: | Resolution |
|
||||
6: \ /
|
||||
7: game specific
|
||||
|
||||
0b00001000 = landscape
|
||||
*/
|
||||
puts("dipsw");
|
||||
i2c_packet->data[0] = 0b00001000;
|
||||
break;
|
||||
case PCA9535_IN1: // SW1/2 + extras
|
||||
/*
|
||||
0: uk
|
||||
1: uk
|
||||
0: unk
|
||||
1: unk
|
||||
2: ¬test
|
||||
3: ¬service
|
||||
4: uk
|
||||
5: uk
|
||||
6: uk
|
||||
7: uk
|
||||
4: unk
|
||||
5: unk
|
||||
6: unk
|
||||
7: unk
|
||||
*/
|
||||
i2c_packet->data[0] = 0x0c;
|
||||
byte dip = 0x00;
|
||||
if (GetAsyncKeyState('T') >= 0) {
|
||||
dip |= 0x04;
|
||||
}
|
||||
if (GetAsyncKeyState('S') >= 0) {
|
||||
dip |= 0x08;
|
||||
}
|
||||
i2c_packet->data[0] = dip;
|
||||
break;
|
||||
case PCA9535_INV0:
|
||||
case PCA9535_INV1:
|
||||
case PCA9535_OUT1: // LEDs, probably
|
||||
i2c_packet->data[0] = 0x00;
|
||||
break;
|
||||
case PCA9535_CONF0:
|
||||
i2c_packet->data[0] = pca9535_config >> 8;
|
||||
break;
|
||||
case PCA9535_CONF1:
|
||||
i2c_packet->data[0] = pca9535_config & 0xff;
|
||||
break;
|
||||
default:
|
||||
log_error("mxsmbux",
|
||||
log_error("mxsmbus",
|
||||
"(read) Undefined pca9535 "
|
||||
"register: 0x%02x",
|
||||
i2c_packet->reg);
|
||||
@ -224,7 +249,8 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
i2c_packet->status = 0x00;
|
||||
break;
|
||||
default:
|
||||
log_error("mxsmbux", "Unknown pca9535 command: 0x%02x", i2c_packet->prt);
|
||||
log_error("mxsmbus", "Unknown pca9535 command: 0x%02x",
|
||||
i2c_packet->prt);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
@ -235,7 +261,7 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
i2c_packet->status = 0;
|
||||
break;
|
||||
default:
|
||||
log_error("mxsmbux", "Unknown eeprom command: 0x%02x", i2c_packet->prt);
|
||||
log_error("mxsmbus", "Unknown eeprom command: 0x%02x", i2c_packet->prt);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
@ -253,8 +279,9 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
"-, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
log_misc("mxsmbus", "SMBus I2C request for %02x: 0x%02x (%02x bytes @ %02x)", request_packet->addr,
|
||||
request_packet->prt, request_packet->dlen, request_packet->reg);
|
||||
log_misc("mxsmbus", "SMBus I2C request for %02x: 0x%02x (%02x bytes @ %02x)",
|
||||
request_packet->addr, request_packet->prt, request_packet->dlen,
|
||||
request_packet->reg);
|
||||
// log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[0],
|
||||
// dwordInBuffer[1], dwordInBuffer[2], dwordInBuffer[3]);
|
||||
// log_warning("eeprom", "%08x %08x %08x %08x", dwordInBuffer[4],
|
||||
@ -301,13 +328,14 @@ BOOL mxsmbus_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffe
|
||||
// for (int i = 0; i < dlen; i++) printf("%02x ",
|
||||
// request_packet->data[i]); puts("");
|
||||
|
||||
eeprom_write(request_packet->reg >> 5, request_packet->reg & 0x1f, request_packet->data,
|
||||
request_packet->dlen);
|
||||
eeprom_write((request_packet->reg >> 5) & 0xff, request_packet->reg & 0x1f,
|
||||
request_packet->data, request_packet->dlen);
|
||||
request_out->status = 0;
|
||||
} else if (i2c_packet->prt == 0x09) {
|
||||
// Read
|
||||
log_misc("mxsmbus", "eeprom read %02x (0x%04x)", dlen, request_packet->reg);
|
||||
eeprom_read(request_packet->reg >> 5, request_packet->reg & 0x1f, request_out->data, dlen);
|
||||
eeprom_read((request_packet->reg >> 5) & 0xff, request_packet->reg & 0x1f,
|
||||
request_out->data, dlen);
|
||||
// for (int i = 0; i < dlen; i++) printf("%02x ",
|
||||
// request_out->data[i]); puts("");
|
||||
request_out->status = 0;
|
||||
|
@ -28,7 +28,7 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
DWORD SRAM_VERSION = 0x0001;
|
||||
DWORD SRAM_SECTOR_SIZE = 0x100; // Max is 0x800
|
||||
DWORD SRAM_SECTOR_SIZE = 4; // Max is 0x800
|
||||
|
||||
switch (dwIoControlCode) {
|
||||
case IOCTL_MXSRAM_PING: // Get version
|
||||
@ -48,11 +48,11 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
|
||||
|
||||
DISK_GEOMETRY out = *(PDISK_GEOMETRY)lpOutBuffer;
|
||||
memset(&out, 0, sizeof(out));
|
||||
out.Cylinders.QuadPart = 1;
|
||||
out.Cylinders.QuadPart = 256;
|
||||
out.MediaType = FixedMedia;
|
||||
out.TracksPerCylinder = 224;
|
||||
out.SectorsPerTrack = 32;
|
||||
out.BytesPerSector = 1;
|
||||
out.TracksPerCylinder = 24;
|
||||
out.SectorsPerTrack = 8;
|
||||
out.BytesPerSector = 512;
|
||||
if (lpBytesReturned) *lpBytesReturned = sizeof(DISK_GEOMETRY);
|
||||
break;
|
||||
case IOCTL_MXSRAM_GET_SECTOR_SIZE:
|
||||
@ -73,6 +73,7 @@ BOOL mxsram_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer
|
||||
}
|
||||
|
||||
DWORD mxsram_SetFilePointer(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||
printf("MXSRSFP %08x\n", lDistanceToMove);
|
||||
if (dwMoveMethod == FILE_BEGIN) {
|
||||
SRAM_POINTER = lDistanceToMove;
|
||||
} else if (dwMoveMethod == FILE_CURRENT) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include "mx.h"
|
||||
#include "smbus.h"
|
||||
#include "w83791d.h"
|
||||
#include "w83627uhg.h"
|
||||
|
||||
BYTE w83791d_bank = 0x00;
|
||||
BYTE w83791d_config = W83791D_CONFIG_START;
|
||||
@ -13,9 +14,17 @@ BYTE w83791d_crit_t3 = 80; // C
|
||||
BYTE w83791d_vbat_monitor_control = 0x00;
|
||||
BOOL w83791d_4f_high = 0;
|
||||
|
||||
BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
BYTE w83627uhg_fanconf = 0x01;
|
||||
BYTE w83627uhg_fanconf_2 = 0x00;
|
||||
BYTE w83627uhg_cpufanout_src_slct = 0x2d;
|
||||
BYTE w83627uhg_sysfanout_src_slct = 0x00;
|
||||
BYTE w83627uhg_systin_target = 0x00;
|
||||
BYTE w83627uhg_cputin_target = 0x00;
|
||||
BYTE w83627uhg_target_tolerance = 0x00;
|
||||
|
||||
BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
mxsuperio_lpc_packet* lpc_packet = (mxsuperio_lpc_packet*)lpInBuffer;
|
||||
mxsuperio_lpc_packet* lpc_out = (mxsuperio_lpc_packet*)lpOutBuffer;
|
||||
|
||||
@ -29,42 +38,99 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
|
||||
((LPDWORD)lpOutBuffer)[0] = 0x01000001;
|
||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||
break;
|
||||
case IOCTL_MXSUPERIO_READ:
|
||||
log_misc("mxsuperio",
|
||||
"DeviceIoControl(<mxsuperio>, <read>, 0x%p, 0x%x, -, "
|
||||
"0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
case IOCTL_MXSUPERIO_READ: {
|
||||
BYTE chip = ((LPBYTE)lpInBuffer)[0];
|
||||
BYTE device = ((LPBYTE)lpInBuffer)[1];
|
||||
BYTE index = ((LPBYTE)lpInBuffer)[2];
|
||||
BYTE* data = &((LPBYTE)lpInBuffer)[3];
|
||||
|
||||
log_misc("mxsuperio", "read: chip:%d device:%d index:%02x", chip, device, index);
|
||||
|
||||
/*
|
||||
BYTE chipId = 0|1
|
||||
BYTE ?? = 0x0b
|
||||
BYTE ?? = 0x20|0x21
|
||||
BYTE ret = 0
|
||||
{
|
||||
IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e)
|
||||
IN BYTE logical device (0 = FDC, 11 = HW mon)
|
||||
IN BYTE index
|
||||
OUT BYTE read value
|
||||
}
|
||||
|
||||
The 846-5004D I have here is at base address 0x4e
|
||||
*/
|
||||
|
||||
switch (((LPBYTE)lpInBuffer)[2]) {
|
||||
/*
|
||||
from micedump:
|
||||
0.20: 00 0b 20 ff
|
||||
0.21: 00 0b 21 ff
|
||||
1.20: 01 0b 20 a2
|
||||
1.21: 01 0b 21 32
|
||||
*/
|
||||
|
||||
*data = 0xff;
|
||||
if (chip == 1) {
|
||||
if (device == 11) {
|
||||
switch (index) {
|
||||
case 0x20:
|
||||
((LPBYTE)lpInBuffer)[3] = 0xa0;
|
||||
*data = 0xa2;
|
||||
break;
|
||||
case 0x21:
|
||||
((LPBYTE)lpInBuffer)[3] = 0x20;
|
||||
break;
|
||||
default:
|
||||
((LPBYTE)lpInBuffer)[3] = 0x00;
|
||||
*data = 0x32;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||
break;
|
||||
}
|
||||
case IOCTL_MXSUPERIO_WRITE:
|
||||
log_misc("mxsuperio",
|
||||
"DeviceIoControl(<mxsuperio>, <write>, 0x%p, 0x%x, -, "
|
||||
"0x%x, -, -)",
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
/*
|
||||
{
|
||||
IN BYTE chip select (0 = base 0x2e, 1 = base 0x4e)
|
||||
IN BYTE logical device (0 = FPC, 11 = HW mon)
|
||||
IN BYTE index
|
||||
IN BYTE write value
|
||||
}
|
||||
*/
|
||||
if (lpBytesReturned) *lpBytesReturned = 4;
|
||||
break;
|
||||
case IOCTL_MXSUPERIO_HWMONITOR_LPC_READ: {
|
||||
// TODO: This code is all for W83791D, however W83627UHG is more appropriate in some
|
||||
// cases. Is this an AAL vs AAM difference? Where was the W83791D usage derived from?
|
||||
BYTE index = lpc_packet->index;
|
||||
BYTE reg = lpc_packet->reg;
|
||||
|
||||
switch (w83791d_bank) {
|
||||
case 0x00: {
|
||||
switch (reg) {
|
||||
case W83627UHG_REG_FAN_CONF:
|
||||
lpc_out->data = w83627uhg_fanconf;
|
||||
break;
|
||||
case W83627UHG_REG_FAN_CONF_2:
|
||||
lpc_out->data = w83627uhg_fanconf_2;
|
||||
break;
|
||||
case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT:
|
||||
lpc_out->data = w83627uhg_cpufanout_src_slct;
|
||||
break;
|
||||
case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT:
|
||||
lpc_out->data = w83627uhg_sysfanout_src_slct;
|
||||
break;
|
||||
case W83627UHG_REG_SYSTIN_TARGET_TEMP:
|
||||
lpc_out->data = w83627uhg_systin_target;
|
||||
break;
|
||||
case W83627UHG_REG_CPUTIN_TARGET_TEMP:
|
||||
lpc_out->data = w83627uhg_cputin_target;
|
||||
break;
|
||||
case W83627UHG_REG_TARGET_TEMP_TOLERANCE:
|
||||
lpc_out->data = w83627uhg_target_tolerance;
|
||||
break;
|
||||
|
||||
case W83791D_REG_WCHIPID:
|
||||
lpc_out->data = 0x71;
|
||||
lpc_out->data = 0x71; // Observed: c1
|
||||
break;
|
||||
case W83791D_REG_CHIPMAN:
|
||||
if (w83791d_4f_high)
|
||||
@ -73,7 +139,7 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
|
||||
lpc_out->data = 0xa3; // Low byte
|
||||
break;
|
||||
case W83791D_REG_I2C_ADDR:
|
||||
lpc_out->data = 0x11;
|
||||
lpc_out->data = 0x11; // Observed: 2d
|
||||
break;
|
||||
case W83791D_REG_BANK:
|
||||
lpc_out->data = w83791d_bank;
|
||||
@ -84,16 +150,28 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
|
||||
break;
|
||||
|
||||
case W83791D_REG_BEEP_CTRL_0:
|
||||
lpc_out->data = 0xff; // All the beeps! (see main.h)
|
||||
// No beeping :(
|
||||
lpc_out->data = 0x00;
|
||||
break;
|
||||
|
||||
// TODO: No idea how to read any of these. Pulled from real system
|
||||
case W83791D_REG_TEMP1_0:
|
||||
lpc_out->data = 0x00; // TODO: Figure out the temp val lol
|
||||
lpc_out->data = 0x1a;
|
||||
break;
|
||||
case W83791D_RAM_VCOREA:
|
||||
lpc_out->data = 0x76;
|
||||
break;
|
||||
case W83791D_RAM_VNIR0:
|
||||
lpc_out->data = 0x86;
|
||||
break;
|
||||
case W83791D_RAM_VDD5:
|
||||
lpc_out->data = 0x94;
|
||||
break;
|
||||
case W83791D_RAM_12VIN:
|
||||
lpc_out->data = 0x00; // TODO: Figure out the batt val
|
||||
lpc_out->data = 0xbe;
|
||||
break;
|
||||
case W83791D_RAM_N12VIN:
|
||||
lpc_out->data = 0xd1;
|
||||
break;
|
||||
|
||||
case W83791D_RAM_FAN1:
|
||||
@ -103,9 +181,8 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
|
||||
break;
|
||||
|
||||
case W83791D_VID_FAN_DIV:
|
||||
// Boths fans divide by 2 (01), VDD 5 latched
|
||||
// good.
|
||||
lpc_out->data = 0b01011111; // Let's not /0!
|
||||
// Boths fans divide by 2 (01)
|
||||
lpc_out->data = 0b00000101;
|
||||
break;
|
||||
|
||||
case W83791D_VBAT_MONITOR_CONTROL:
|
||||
@ -113,8 +190,9 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
|
||||
break;
|
||||
|
||||
default:
|
||||
log_error("mxsuperio", "Unknown HM b0 register: 0x%02x", reg);
|
||||
exit(1);
|
||||
log_error("mxsuperio", "Unknown HM b0 register: read 0x%02x", reg);
|
||||
return FALSE;
|
||||
// exit(1);
|
||||
}
|
||||
} break;
|
||||
case 0x01: {
|
||||
@ -183,18 +261,48 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
|
||||
// data > 0x0f, data < 0x70
|
||||
|
||||
// lpc_out->data = eeprom_read_one(reg, index);
|
||||
log_misc("mxsuperio", "amHmLpcReadByte Index=0x%02x Reg=0x%02x Data=0x%02x", index, reg, lpc_out->data);
|
||||
log_misc("mxsuperio", "amHmLpcReadByte Index=0x%02x Reg=0x%02x Data=0x%02x", index, reg,
|
||||
lpc_out->data);
|
||||
|
||||
if (lpBytesReturned) *lpBytesReturned = sizeof(mxsuperio_lpc_packet);
|
||||
} break;
|
||||
case IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE: {
|
||||
BYTE index = lpc_packet->index;
|
||||
BYTE reg = lpc_packet->reg;
|
||||
log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b", index, reg, lpc_packet->data);
|
||||
log_misc("mxsuperio", "amHmLpcWriteByte Index=0x%02x Reg=0x%02x Data=0x%02b", index,
|
||||
reg, lpc_packet->data);
|
||||
|
||||
switch (w83791d_bank) {
|
||||
case 0x00: {
|
||||
switch (reg) {
|
||||
case W83627UHG_REG_FAN_CONF:
|
||||
w83627uhg_fanconf = lpc_packet->data;
|
||||
break;
|
||||
case W83627UHG_REG_FAN_CONF_2:
|
||||
w83627uhg_fanconf_2 = lpc_packet->data;
|
||||
break;
|
||||
case W83627UHG_REG_CPUFANOUT_VALUE_SELECT:
|
||||
// Just no-op this
|
||||
break;
|
||||
case W83627UHG_REG_CPUFANOUT_TEMP_SRC_SLCT:
|
||||
w83627uhg_cpufanout_src_slct = lpc_packet->data;
|
||||
break;
|
||||
case W83627UHG_REG_SYSFANOUT_TEMP_SRC_SLCT:
|
||||
w83627uhg_sysfanout_src_slct = lpc_packet->data;
|
||||
break;
|
||||
case W83627UHG_REG_SYSTIN_TARGET_TEMP:
|
||||
w83627uhg_systin_target = lpc_packet->data;
|
||||
break;
|
||||
case W83627UHG_REG_CPUTIN_TARGET_TEMP:
|
||||
w83627uhg_cputin_target = lpc_packet->data;
|
||||
break;
|
||||
case W83627UHG_REG_TARGET_TEMP_TOLERANCE:
|
||||
w83627uhg_target_tolerance = lpc_packet->data;
|
||||
break;
|
||||
case W83627UHG_REG_SYSFANOUT_STOP_VALUE:
|
||||
case W83627UHG_REG_SYSFANOUT_START_VALUE:
|
||||
break;
|
||||
|
||||
case W83791D_REG_BEEP_CTRL_0:
|
||||
// Ignore for now
|
||||
break;
|
||||
@ -210,8 +318,8 @@ BOOL mxsuperio_DeviceIoControl(void* file, DWORD dwIoControlCode, LPVOID lpInBuf
|
||||
w83791d_vbat_monitor_control = lpc_packet->data;
|
||||
break;
|
||||
default:
|
||||
log_error("mxsuperio", "Unknown HM b0 register: 0x%02x", reg);
|
||||
exit(1);
|
||||
log_error("mxsuperio", "Unknown HM b0 register: write 0x%02x", reg);
|
||||
// exit(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
38
src/micetools/dll/hooks/README.md
Normal file
38
src/micetools/dll/hooks/README.md
Normal 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
|
@ -9,4 +9,6 @@ void hook_all() {
|
||||
hook_processes();
|
||||
hook_network();
|
||||
hook_time();
|
||||
hook_registry();
|
||||
hook_drives();
|
||||
}
|
||||
|
@ -8,5 +8,7 @@
|
||||
#include "processes.h"
|
||||
#include "setupapi_.h"
|
||||
#include "time.h"
|
||||
#include "registry.h"
|
||||
#include "drive.h"
|
||||
|
||||
void hook_all();
|
||||
|
@ -1,5 +1,7 @@
|
||||
#include "com.h"
|
||||
|
||||
#include "files.h"
|
||||
|
||||
com_hook_t* com_hook_list = NULL;
|
||||
com_hook_t* new_com_hook(BYTE port) {
|
||||
com_hook_t* hook = (com_hook_t*)malloc(sizeof *hook);
|
||||
@ -7,7 +9,8 @@ com_hook_t* new_com_hook(BYTE port) {
|
||||
memset(hook->wName, 0, sizeof hook->wName);
|
||||
swprintf(hook->wName, (sizeof hook->wName) / (sizeof hook->wName[0]), L"COM%d", port);
|
||||
memset(hook->wDosName, 0, sizeof hook->wDosName);
|
||||
swprintf(hook->wDosName, (sizeof hook->wDosName) / (sizeof hook->wDosName[0]), L"\\\\.\\COM%d", port);
|
||||
swprintf(hook->wDosName, (sizeof hook->wDosName) / (sizeof hook->wDosName[0]), L"\\\\.\\COM%d",
|
||||
port);
|
||||
hook->com = port;
|
||||
|
||||
hook->GetCommState = NULL;
|
||||
@ -21,7 +24,7 @@ com_hook_t* new_com_hook(BYTE port) {
|
||||
hook->ClearCommError = NULL;
|
||||
|
||||
return hook;
|
||||
};
|
||||
}
|
||||
|
||||
void hook_com(com_hook_t* hook) {
|
||||
hook->next = NULL;
|
||||
@ -35,39 +38,33 @@ void hook_com(com_hook_t* hook) {
|
||||
com_hook_t* hl = com_hook_list;
|
||||
while (hl->next != NULL) hl = hl->next;
|
||||
hl->next = hook;
|
||||
};
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeGetCommState(HANDLE hFile, LPDCB lpDCB) {
|
||||
log_misc(COMM_LOGGER, "GetCommState(0x%p, 0x%p)", hFile, lpDCB);
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
log_misc(COMM_LOGGER, "GetCommState(0x%p, 0x%p) (%08x)", hFile, lpDCB, hook);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
if (hook != NULL) {
|
||||
if (hook->GetCommState == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommState(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->GetCommState(hook->data, lpDCB);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueGetCommState(hFile, lpDCB);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
|
||||
log_misc(COMM_LOGGER, "SetCommState(0x%p, 0x%p)", hFile, lpDCB);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetCommState == NULL) {
|
||||
log_error(COMM_LOGGER, "SetCommState(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->SetCommState(hook->data, lpDCB);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueSetCommState(hFile, lpDCB);
|
||||
}
|
||||
@ -75,119 +72,98 @@ BOOL WINAPI FakeSetCommState(HANDLE hFile, LPDCB lpDCB) {
|
||||
BOOL WINAPI FakeGetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
||||
log_misc(COMM_LOGGER, "GetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->GetCommTimeouts == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommTimeouts(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->GetCommTimeouts(hook->data, lpCommTimeouts);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueGetCommTimeouts(hFile, lpCommTimeouts);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) {
|
||||
log_misc(COMM_LOGGER, "SetCommTimeouts(0x%p, 0x%p)", hFile, lpCommTimeouts);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetCommTimeouts == NULL) {
|
||||
log_error(COMM_LOGGER, "SetCommTimeouts(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->SetCommTimeouts(hook->data, lpCommTimeouts);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueSetCommTimeouts(hFile, lpCommTimeouts);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetupComm(HANDLE hFile, DWORD dwInQueue, DWORD dwOutQueue) {
|
||||
log_misc(COMM_LOGGER, "SetupCom(0x%p, 0x%08x, 0x%08x)", hFile, dwInQueue, dwOutQueue);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetupComm == NULL) {
|
||||
log_error(COMM_LOGGER, "SetupComm(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->SetupComm(hook->data, dwInQueue, dwOutQueue);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueSetupComm(hFile, dwInQueue, dwOutQueue);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakePurgeComm(HANDLE hFile, DWORD dwFlags) {
|
||||
log_misc(COMM_LOGGER, "PurgeComm(0x%p, 0x%08x)", hFile, dwFlags);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->PurgeComm == NULL) {
|
||||
log_error(COMM_LOGGER, "PurgeComm(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->PurgeComm(hook->data, dwFlags);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TruePurgeComm(hFile, dwFlags);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeGetCommModemStatus(HANDLE hFile, LPDWORD lpModelStat) {
|
||||
log_misc(COMM_LOGGER, "GetCommModemStatus(0x%p, 0x%p)", hFile, lpModelStat);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->GetCommModemStatus == NULL) {
|
||||
log_error(COMM_LOGGER, "GetCommModemStatus(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->GetCommModemStatus(hook->data, lpModelStat);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueGetCommModemStatus(hFile, lpModelStat);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeWaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) {
|
||||
log_misc(COMM_LOGGER, "WaitCommEvent");
|
||||
log_misc(COMM_LOGGER, "WaitCommEvent(0x%p)", hFile);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->WaitCommEvent == NULL) {
|
||||
log_error(COMM_LOGGER, "WaitCommEvent(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->WaitCommEvent(hook->data, lpEvtMask, lpOverlapped);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueWaitCommEvent(hFile, lpEvtMask, lpOverlapped);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) {
|
||||
log_misc(COMM_LOGGER, "ClearCommError");
|
||||
log_trace(COMM_LOGGER, "ClearCommError(0x%p)", hFile);
|
||||
|
||||
com_hook_t* hook = com_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
com_hook_t* hook = get_handle_com_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->ClearCommError == NULL) {
|
||||
log_error(COMM_LOGGER, "ClearCommError(%ls) unimplemented", hook->wName);
|
||||
return FALSE;
|
||||
}
|
||||
return hook->ClearCommError(hook->data, lpErrors, lpStat);
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueClearCommError(hFile, lpErrors, lpStat);
|
||||
}
|
||||
|
||||
@ -198,7 +174,8 @@ void hook_commio() {
|
||||
hook("Kernel32.dll", "SetCommTimeouts", FakeSetCommTimeouts, (void**)&TrueSetCommTimeouts, 6);
|
||||
hook("Kernel32.dll", "SetupComm", FakeSetupComm, (void**)&TrueSetupComm, 6);
|
||||
hook("Kernel32.dll", "PurgeComm", FakePurgeComm, (void**)&TruePurgeComm, 6);
|
||||
hook("Kernel32.dll", "GetCommModemStatus", FakeGetCommModemStatus, (void**)&TrueGetCommModemStatus, 6);
|
||||
hook("Kernel32.dll", "GetCommModemStatus", FakeGetCommModemStatus,
|
||||
(void**)&TrueGetCommModemStatus, 6);
|
||||
hook("Kernel32.dll", "WaitCommEvent", FakeWaitCommEvent, (void**)&TrueWaitCommEvent, 6);
|
||||
hook("Kernel32.dll", "ClearCommError", FakeClearCommError, (void**)&TrueClearCommError, 6);
|
||||
}
|
@ -24,8 +24,8 @@ typedef BOOL(FnClearCommError)(void* com, LPDWORD lpErrors, LPCOMSTAT lpStat);
|
||||
|
||||
typedef struct com_hook {
|
||||
LPHANDLE virtual_handle;
|
||||
WCHAR wName[7]; // max is "COM255"
|
||||
WCHAR wDosName[11]; // max is "\\\\.\\COM255"
|
||||
WCHAR wName[16];
|
||||
WCHAR wDosName[16];
|
||||
BYTE com;
|
||||
|
||||
FnGetCommState* GetCommState;
|
||||
@ -43,6 +43,8 @@ typedef struct com_hook {
|
||||
struct com_hook* next;
|
||||
} com_hook_t;
|
||||
|
||||
extern com_hook_t* com_hook_list;
|
||||
|
||||
com_hook_t* new_com_hook(BYTE port);
|
||||
void hook_com(com_hook_t* hook);
|
||||
|
||||
|
398
src/micetools/dll/hooks/drive.c
Normal file
398
src/micetools/dll/hooks/drive.c
Normal 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);
|
||||
}
|
43
src/micetools/dll/hooks/drive.h
Normal file
43
src/micetools/dll/hooks/drive.h
Normal 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;
|
@ -1,11 +1,72 @@
|
||||
#include "files.h"
|
||||
|
||||
HANDLE fake_handle = (HANDLE)0x10000000;
|
||||
open_hook_t* open_hooks_list = NULL;
|
||||
HANDLE open_hook(file_hook_t* file_hook, com_hook_t* com_hook) {
|
||||
open_hook_t* opened = (open_hook_t*)malloc(sizeof(open_hook_t));
|
||||
memset(opened, 0, sizeof *opened);
|
||||
|
||||
opened->file_hook = file_hook;
|
||||
opened->com_hook = com_hook;
|
||||
|
||||
CHAR path[MAX_PATH];
|
||||
GetModuleFileNameA(NULL, path, MAX_PATH);
|
||||
HANDLE handle =
|
||||
_CreateFileA(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (handle == INVALID_HANDLE_VALUE) {
|
||||
log_error(HOOKS_LOGGER, "Failed to create dummy handle: %03x", GetLastError());
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
opened->handle = handle;
|
||||
opened->next = open_hooks_list;
|
||||
open_hooks_list = opened;
|
||||
|
||||
return handle;
|
||||
}
|
||||
void close_hook(HANDLE handle) {
|
||||
if (handle == INVALID_HANDLE_VALUE) return;
|
||||
|
||||
_CloseHandle(handle);
|
||||
|
||||
open_hook_t* opened = NULL;
|
||||
open_hook_t* root = open_hooks_list;
|
||||
if (open_hooks_list->handle == handle) {
|
||||
open_hook_t* next = open_hooks_list->next;
|
||||
free(open_hooks_list);
|
||||
open_hooks_list = next;
|
||||
return;
|
||||
}
|
||||
|
||||
while (root != NULL) {
|
||||
if (root->next && root->next->handle == handle) {
|
||||
opened = root->next;
|
||||
root->next = opened->next;
|
||||
free(opened);
|
||||
return;
|
||||
}
|
||||
root = root->next;
|
||||
}
|
||||
}
|
||||
file_hook_t* get_handle_file_hook(HANDLE handle) {
|
||||
open_hook_t* root = open_hooks_list;
|
||||
while (root != NULL) {
|
||||
if (root->handle == handle) return root->file_hook;
|
||||
root = root->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
com_hook_t* get_handle_com_hook(HANDLE handle) {
|
||||
open_hook_t* root = open_hooks_list;
|
||||
while (root != NULL) {
|
||||
if (root->handle == handle) return root->com_hook;
|
||||
root = root->next;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file_hook_t* file_hook_list = NULL;
|
||||
file_hook_t* new_file_hook(LPCWSTR filename) {
|
||||
file_hook_t* hook = (file_hook_t*)malloc(sizeof(file_hook_t));
|
||||
memset(hook, 0, sizeof(file_hook_t));
|
||||
memset(hook, 0, sizeof *hook);
|
||||
|
||||
hook->filename = filename;
|
||||
|
||||
@ -13,8 +74,6 @@ file_hook_t* new_file_hook(LPCWSTR filename) {
|
||||
}
|
||||
void hook_file(file_hook_t* hook) {
|
||||
hook->next = NULL;
|
||||
hook->virtual_handle = (LPHANDLE)malloc(sizeof(HANDLE));
|
||||
*hook->virtual_handle = NULL;
|
||||
if (file_hook_list == NULL) {
|
||||
file_hook_list = hook;
|
||||
return;
|
||||
@ -30,9 +89,12 @@ drive_redirect_t DRIVE_REDIRECT_TABLE[] = {
|
||||
// Note: Had tp create last_shime.log
|
||||
{ .drive = "C:\\Documents and Settings\\AppUser\\temp\\", .path = ".\\dev\\temp\\" },
|
||||
// {.drive = "C:\\ProgramData/boost_interprocess/", .path = "\\\\.\\ipc\\"},
|
||||
|
||||
{ .drive = "C:\\\\Windows\\\\System32\\", .path = "Sys32" },
|
||||
{ .drive = "C:\\\\WINDOWS\\\\system32\\", .path = "Sys32" },
|
||||
};
|
||||
|
||||
char* redirect_path(char* path) {
|
||||
LPCSTR redirect_path(LPCSTR path) {
|
||||
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
|
||||
drive_redirect_t row = DRIVE_REDIRECT_TABLE[i];
|
||||
if (strstr(path, row.drive)) {
|
||||
@ -45,7 +107,7 @@ char* redirect_path(char* path) {
|
||||
|
||||
char* dst = new_str + strlen(row.path);
|
||||
size_t len = strlen(path) - strlen(row.drive);
|
||||
char* src = path + strlen(row.drive);
|
||||
const char* src = path + strlen(row.drive);
|
||||
|
||||
for (; len > 0; len--) (dst++)[0] = (src++)[0];
|
||||
dst[0] = 0;
|
||||
@ -55,66 +117,122 @@ char* redirect_path(char* path) {
|
||||
}
|
||||
return path;
|
||||
}
|
||||
LPCWSTR redirect_path_w(LPCWSTR path) {
|
||||
return path;
|
||||
// TODO: THIS!!
|
||||
for (int i = 0; i < sizeof DRIVE_REDIRECT_TABLE / sizeof DRIVE_REDIRECT_TABLE[0]; i++) {
|
||||
drive_redirect_t row = DRIVE_REDIRECT_TABLE[i];
|
||||
if (wcsstr(path, row.drive)) {
|
||||
log_misc(HOOKS_LOGGER, "Redirecting '%ls' to '%ls'", path, row.path);
|
||||
|
||||
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
HANDLE handle = NULL;
|
||||
size_t new_len = wcslen(path) - wcslen(row.drive) + wcslen(row.path);
|
||||
// TODO: Make this not leak memory!
|
||||
wchar_t* new_str = (wchar_t*)malloc((new_len + 1) * 2);
|
||||
wcscpy_s(new_str, new_len + 1, row.path);
|
||||
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (wcscmp(lpFileName, hook->filename) == 0 ||
|
||||
(hook->altFilename != NULL && wcscmp(lpFileName, hook->altFilename) == 0)) {
|
||||
if (*hook->virtual_handle == NULL) {
|
||||
// TODO: Assign handles better!
|
||||
*hook->virtual_handle = fake_handle;
|
||||
((size_t)fake_handle)++;
|
||||
wchar_t* dst = new_str + wcslen(row.path) * 2;
|
||||
size_t len = wcslen(path) - wcslen(row.drive);
|
||||
const wchar_t* src = path + wcslen(row.drive) * 2;
|
||||
|
||||
for (; len > 0; len--) {
|
||||
(dst++)[0] = (src++)[0];
|
||||
(dst++)[0] = (src++)[0];
|
||||
}
|
||||
handle = *hook->virtual_handle;
|
||||
dst[0] = 0;
|
||||
log_misc(HOOKS_LOGGER, "New filename: '%ls'", new_str);
|
||||
return new_str;
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
log_info(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
|
||||
void find_hooks(LPCWSTR lpFileName, file_hook_t** found_fh, com_hook_t** found_ch) {
|
||||
file_hook_t* file_hook = file_hook_list;
|
||||
while (file_hook != NULL) {
|
||||
if (wcscmp(lpFileName, file_hook->filename) == 0 ||
|
||||
(file_hook->altFilename != NULL && wcscmp(lpFileName, file_hook->altFilename) == 0)) {
|
||||
*found_fh = file_hook;
|
||||
break;
|
||||
}
|
||||
hook = hook->next;
|
||||
file_hook = file_hook->next;
|
||||
}
|
||||
|
||||
if (handle == NULL) {
|
||||
handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition,
|
||||
dwFlagsAndAttributes, hTemplateFile);
|
||||
com_hook_t* com_hook = com_hook_list;
|
||||
while (com_hook != NULL) {
|
||||
if (wcscmp(lpFileName, com_hook->wName) == 0 ||
|
||||
wcscmp(lpFileName, com_hook->wDosName) == 0) {
|
||||
*found_ch = com_hook;
|
||||
break;
|
||||
}
|
||||
com_hook = com_hook->next;
|
||||
}
|
||||
};
|
||||
|
||||
HANDLE WINAPI FakeCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile) {
|
||||
file_hook_t* found_fh = NULL;
|
||||
com_hook_t* found_ch = NULL;
|
||||
find_hooks(lpFileName, &found_fh, &found_ch);
|
||||
if (found_fh != NULL || found_ch != NULL) {
|
||||
HANDLE handle = open_hook(found_fh, found_ch);
|
||||
log_info(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
lpFileName = redirect_path_w(lpFileName);
|
||||
|
||||
HANDLE handle = TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
log_misc(HOOKS_LOGGER, "CreateFileW(%ls) -> 0x%p", lpFileName, handle);
|
||||
return handle;
|
||||
}
|
||||
HANDLE WINAPI FakeCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
|
||||
lpFileName = redirect_path((char*)lpFileName);
|
||||
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile) {
|
||||
WCHAR wideFileName[MAX_PATH + 1];
|
||||
MultiByteToWideChar(CP_ACP, 0, lpFileName, -1, (LPWSTR)&wideFileName, MAX_PATH + 1);
|
||||
|
||||
HANDLE result = FakeCreateFileW((LPCWSTR)&wideFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
file_hook_t* found_fh = NULL;
|
||||
com_hook_t* found_ch = NULL;
|
||||
find_hooks(wideFileName, &found_fh, &found_ch);
|
||||
if (found_fh != NULL || found_ch != NULL) {
|
||||
HANDLE handle = open_hook(found_fh, found_ch);
|
||||
log_info(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
|
||||
return handle;
|
||||
}
|
||||
|
||||
lpFileName = redirect_path(lpFileName);
|
||||
|
||||
HANDLE handle = TrueCreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
log_misc(HOOKS_LOGGER, "^-> CreateFileA(%s) -> 0x%p", lpFileName, result);
|
||||
return result;
|
||||
log_misc(HOOKS_LOGGER, "CreateFileA(%s) -> 0x%p", lpFileName, handle);
|
||||
return handle;
|
||||
|
||||
// lpFileName = redirect_path(lpFileName);
|
||||
|
||||
// HANDLE result =
|
||||
// FakeCreateFileW((LPCWSTR)&wideFileName, dwDesiredAccess, dwShareMode,
|
||||
// lpSecurityAttributes,
|
||||
// dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
// log_trace(HOOKS_LOGGER, "^-> CreateFileA(%s) -> 0x%p", lpFileName, result);
|
||||
// return result;
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
log_misc(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, 0x%p, 0x%x, -, 0x%x, 0, 0)", hDevice, dwIoControlCode,
|
||||
lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hDevice) {
|
||||
BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped) {
|
||||
file_hook_t* hook = get_handle_file_hook(hDevice);
|
||||
if (hook != NULL) {
|
||||
if (hook->DeviceIoControl) {
|
||||
// TODO: Less jank
|
||||
if (lpOverlapped != NULL) SetEvent(lpOverlapped->hEvent);
|
||||
|
||||
BOOL ret = hook->DeviceIoControl(hook->data, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
|
||||
nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
BOOL ret =
|
||||
hook->DeviceIoControl(hook->data, dwIoControlCode, lpInBuffer, nInBufferSize,
|
||||
lpOutBuffer, nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
if (ret && lpOverlapped && lpBytesReturned) {
|
||||
lpOverlapped->InternalHigh = *lpBytesReturned;
|
||||
}
|
||||
@ -124,54 +242,49 @@ BOOL WINAPI FakeDeviceIoControl(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lp
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
// log_warning(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, -, -, -, -, 0, 0)", hDevice, dwIoControlCode);
|
||||
log_trace(HOOKS_LOGGER, "DeviceIoControl(0x%p, 0x%08x, 0x%p, 0x%x, -, 0x%x, 0, 0)", hDevice,
|
||||
dwIoControlCode, lpInBuffer, nInBufferSize, nOutBufferSize);
|
||||
|
||||
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer, nOutBufferSize,
|
||||
lpBytesReturned, lpOverlapped);
|
||||
return TrueDeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, lpOutBuffer,
|
||||
nOutBufferSize, lpBytesReturned, lpOverlapped);
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
DWORD WINAPI FakeSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetFilePointer) {
|
||||
return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||
return hook->SetFilePointer(hook->data, lDistanceToMove, lpDistanceToMoveHigh,
|
||||
dwMoveMethod);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "SetFilePointer(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
DWORD dwMoveMethod) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
BOOL WINAPI FakeSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
|
||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->SetFilePointerEx) {
|
||||
return hook->SetFilePointerEx(hook->data, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
|
||||
return hook->SetFilePointerEx(hook->data, liDistanceToMove, lpNewFilePointer,
|
||||
dwMoveMethod);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "SetFilePointerEx(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->GetFileSizeEx) {
|
||||
return hook->GetFileSizeEx(hook->data, lpFileSize);
|
||||
} else {
|
||||
@ -179,58 +292,53 @@ DWORD WINAPI FakeGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueGetFileSizeEx(hFile, lpFileSize);
|
||||
}
|
||||
|
||||
DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
DWORD WINAPI FakeWriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) {
|
||||
log_trace("file", "WriteFile(%08x)", hFile);
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->WriteFile) {
|
||||
return hook->WriteFile(hook->data, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||
lpOverlapped);
|
||||
return hook->WriteFile(hook->data, lpBuffer, nNumberOfBytesToWrite,
|
||||
lpNumberOfBytesWritten, lpOverlapped);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "WriteFile(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten, lpOverlapped);
|
||||
return FALSE;
|
||||
|
||||
return TrueWriteFile(hFile, lpBuffer, nNumberOfBytesToWrite, lpNumberOfBytesWritten,
|
||||
lpOverlapped);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (*hook->virtual_handle == hFile) {
|
||||
BOOL WINAPI FakeReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
|
||||
file_hook_t* hook = get_handle_file_hook(hFile);
|
||||
if (hook != NULL) {
|
||||
if (hook->ReadFile) {
|
||||
return hook->ReadFile(hook->data, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
|
||||
return hook->ReadFile(hook->data, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead,
|
||||
lpOverlapped);
|
||||
} else {
|
||||
log_error(HOOKS_LOGGER, "ReadFile(%ls) unimplemented", hook->filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
|
||||
return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
|
||||
}
|
||||
|
||||
BOOL WINAPI FakeCloseHandle(HANDLE hObject) {
|
||||
file_hook_t* hook = file_hook_list;
|
||||
while (hook != NULL) {
|
||||
if (hObject != NULL && *hook->virtual_handle == hObject) {
|
||||
file_hook_t* hook = get_handle_file_hook(hObject);
|
||||
if (hook != NULL) {
|
||||
log_misc("file", "close %08x", hObject);
|
||||
close_hook(hObject);
|
||||
return TRUE;
|
||||
}
|
||||
hook = hook->next;
|
||||
}
|
||||
return TrueCloseHandle(hObject);
|
||||
}
|
||||
|
||||
@ -247,7 +355,8 @@ void hook_io() {
|
||||
|
||||
hook("Kernel32.dll", "CloseHandle", FakeCloseHandle, (void**)&TrueCloseHandle, 6);
|
||||
hook("Kernel32.dll", "SetFilePointer", FakeSetFilePointer, (void**)&TrueSetFilePointer, 6);
|
||||
hook("Kernel32.dll", "SetFilePointerEx", FakeSetFilePointerEx, (void**)&TrueSetFilePointerEx, 6);
|
||||
hook("Kernel32.dll", "SetFilePointerEx", FakeSetFilePointerEx, (void**)&TrueSetFilePointerEx,
|
||||
6);
|
||||
hook("Kernel32.dll", "WriteFile", FakeWriteFile, (void**)&TrueWriteFile, 6);
|
||||
hook("Kernel32.dll", "ReadFile", FakeReadFile, (void**)&TrueReadFile, 6);
|
||||
hook("Kernel32.dll", "GetFileSizeEx", FakeGetFileSizeEx, (void**)&TrueGetFileSizeEx, 6);
|
||||
|
@ -1,55 +1,68 @@
|
||||
#pragma once
|
||||
#include "../common.h"
|
||||
#include "com.h"
|
||||
|
||||
static HANDLE(WINAPI* TrueCreateFileA)(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
static HANDLE(WINAPI* TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
|
||||
DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
|
||||
HANDLE hTemplateFile);
|
||||
|
||||
static BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
static BOOL(WINAPI* TrueDeviceIoControl)(HANDLE hDevice, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer,
|
||||
DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
|
||||
static DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod);
|
||||
static BOOL(WINAPI* TrueSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
DWORD dwMoveMethod);
|
||||
static DWORD(WINAPI* TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove,
|
||||
PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
static BOOL(WINAPI* TrueSetFilePointerEx)(HANDLE hFile, LARGE_INTEGER liDistanceToMove,
|
||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
|
||||
// logging needs access to WriteFile, so we can't static it!
|
||||
BOOL(WINAPI* TrueWriteFile)(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
BOOL(WINAPI* TrueWriteFile)
|
||||
(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||
static BOOL(WINAPI* TrueGetFileSizeEx)(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||
static BOOL(WINAPI* TrueCloseHandle)(HANDLE hObject);
|
||||
|
||||
typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer, DWORD nInBufferSize,
|
||||
LPVOID lpOutBuffer, DWORD nOutBufferSize, LPDWORD lpBytesReturned,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnDeviceIoControl)(void* file, DWORD dwIoControlCode, LPVOID lpInBuffer,
|
||||
DWORD nInBufferSize, LPVOID lpOutBuffer, DWORD nOutBufferSize,
|
||||
LPDWORD lpBytesReturned, LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef DWORD(FnSetFilePointer)(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||
typedef BOOL(FnSetFilePointerEx)(void* file, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer,
|
||||
typedef DWORD(FnSetFilePointer)(void* file, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh,
|
||||
DWORD dwMoveMethod);
|
||||
typedef BOOL(FnWriteFile)(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, LPDWORD lpNumberOfBytesWritten,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnReadFile)(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead,
|
||||
LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnSetFilePointerEx)(void* file, LARGE_INTEGER liDistanceToMove,
|
||||
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
|
||||
typedef BOOL(FnWriteFile)(void* file, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
|
||||
LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped);
|
||||
typedef BOOL(FnReadFile)(void* file, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
|
||||
LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped);
|
||||
|
||||
typedef BOOL(FnGetFileSizeEx)(void* file, PLARGE_INTEGER lpFileSize);
|
||||
|
||||
static int(WINAPIV* True_stat64i32)(const char* path, struct _stat64i32* buffer);
|
||||
typedef struct _stat64i32 _stat64i32_t;
|
||||
static int(WINAPIV* True_stat64i32)(const char* path, _stat64i32_t* buffer);
|
||||
|
||||
#define _WriteFile (TrueWriteFile ? TrueWriteFile : WriteFile)
|
||||
#define _ReadFile (TrueReadFile ? TrueReadFile : ReadFile)
|
||||
#define _CloseHandle (TrueCloseHandle ? TrueCloseHandle : CloseHandle)
|
||||
#define _CreateFileW (TrueCreateFileW ? TrueCreateFileW : CreateFileW)
|
||||
#define _CreateFileA (TrueCreateFileA ? TrueCreateFileA : CreateFileA)
|
||||
|
||||
typedef struct drive_redirect {
|
||||
const CHAR* drive;
|
||||
const CHAR* path;
|
||||
} drive_redirect_t;
|
||||
|
||||
typedef struct drive_redirect_w {
|
||||
const WCHAR* drive;
|
||||
const WCHAR* path;
|
||||
} drive_redirect_w_t;
|
||||
|
||||
typedef struct file_hook {
|
||||
LPCWSTR filename;
|
||||
LPCWSTR altFilename;
|
||||
@ -67,6 +80,19 @@ typedef struct file_hook {
|
||||
struct file_hook* next;
|
||||
} file_hook_t;
|
||||
|
||||
typedef struct open_hook {
|
||||
HANDLE handle;
|
||||
file_hook_t* file_hook;
|
||||
com_hook_t* com_hook;
|
||||
struct open_hook* next;
|
||||
} open_hook_t;
|
||||
|
||||
extern file_hook_t* file_hook_list;
|
||||
|
||||
file_hook_t* new_file_hook(LPCWSTR filename);
|
||||
void hook_file(file_hook_t* hook);
|
||||
void hook_io();
|
||||
|
||||
void close_hook(HANDLE handle);
|
||||
file_hook_t* get_handle_file_hook(HANDLE handle);
|
||||
com_hook_t* get_handle_com_hook(HANDLE handle);
|
||||
|
@ -19,7 +19,7 @@ char* trim_string(char* string) {
|
||||
char format_buf[WORK_FORMAT_MAX]; // Will do. We guard against overflow in Fake[f]printf
|
||||
|
||||
int WINAPIV Fakeprintf(const char* _Format, ...) {
|
||||
int flen = strlen(_Format);
|
||||
size_t flen = strlen(_Format);
|
||||
if (flen == strcspn(_Format, "\n") + 1 && flen < (sizeof format_buf)) {
|
||||
strcpy_s(format_buf, WORK_FORMAT_MAX, _Format);
|
||||
format_buf[flen - 1] = 0;
|
||||
@ -31,11 +31,11 @@ int WINAPIV Fakeprintf(const char* _Format, ...) {
|
||||
int ret = vlog_game("printf", _Format, args);
|
||||
|
||||
va_end(args);
|
||||
return vlog_game("printf", _Format, args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int WINAPIV Fakefprintf(FILE* _File, const char* _Format, ...) {
|
||||
int flen = strlen(_Format);
|
||||
size_t flen = strlen(_Format);
|
||||
if (flen == strcspn(_Format, "\n") + 1 && flen < (sizeof format_buf)) {
|
||||
strcpy_s(format_buf, WORK_FORMAT_MAX, _Format);
|
||||
format_buf[flen - 1] = 0;
|
||||
@ -59,6 +59,9 @@ int WINAPIV Fakefprintf_s(FILE* _Stream, const char* _Format, ...) {
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int WINAPIV Fakevfprintf_s(FILE* _Stream, const char* _Format, va_list _ArgList) {
|
||||
return vlog_game("vfprintf_s", _Format, _ArgList);
|
||||
}
|
||||
HANDLE WINAPI FakeRegisterEventSourceA(LPCSTR lpUNCServerName, LPCSTR lpSourceName) { return (HANDLE)0xDEADBEEF; }
|
||||
|
||||
BOOL WINAPI FakeReportEventA(HANDLE hEventLog, WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid,
|
||||
@ -92,6 +95,7 @@ void hook_logging() {
|
||||
hook("MSVCR90.DLL", "printf", Fakeprintf, (void**)&Trueprintf, 6);
|
||||
hook("MSVCR90.DLL", "fprintf", Fakefprintf, (void**)&Truefprintf, 6);
|
||||
hook("MSVCR90.DLL", "fprintf_s", Fakefprintf_s, (void**)&Truefprintf_s, 6);
|
||||
hook("MSVCR90.DLL", "vfprintf_s", Fakevfprintf_s, (void**)&Truevfprintf_s, 6);
|
||||
|
||||
hook("Advapi32.dll", "RegisterEventSourceA", FakeRegisterEventSourceA, (void**)&TrueRegisterEventSourceA, 6);
|
||||
hook("Advapi32.dll", "ReportEventA", FakeReportEventA, (void**)&TrueReportEventA, 6);
|
||||
|
@ -12,5 +12,6 @@ static BOOL(WINAPI* TrueDeregisterEventSource)(HANDLE hEventLog);
|
||||
int(WINAPIV* Trueprintf)(const char* _Format, ...);
|
||||
static int(WINAPIV* Truefprintf)(FILE* _File, const char* _Format, ...);
|
||||
static int(WINAPIV* Truefprintf_s)(FILE* _Stream, const char* _Format, ...);
|
||||
static int(WINAPIV* Truevfprintf_s)(FILE* _Stream, const char* _Format, va_list _ArgList);
|
||||
|
||||
void hook_logging();
|
||||
|
@ -8,4 +8,6 @@ hooks_files = files(
|
||||
'processes.c',
|
||||
'setupapi.c',
|
||||
'time.c',
|
||||
'registry.c',
|
||||
'drive.c',
|
||||
)
|
@ -3,51 +3,94 @@
|
||||
int WINAPI Fake_connect(SOCKET s, const SOCKADDR* name, int namelen) {
|
||||
ULONG addr = _byteswap_ulong(((SOCKADDR_IN*)name)->sin_addr.S_un.S_addr);
|
||||
USHORT port = _byteswap_ushort(((SOCKADDR_IN*)name)->sin_port);
|
||||
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff, (addr >> 8) & 0xff,
|
||||
addr & 0xff, port);
|
||||
log_info("connect", "%hhu.%hhu.%hhu.%hhu:%hu", (addr >> 24) & 0xff, (addr >> 16) & 0xff,
|
||||
(addr >> 8) & 0xff, addr & 0xff, port);
|
||||
return True_connect(s, name, namelen);
|
||||
}
|
||||
|
||||
static uint8_t spoof_mac[6] = { 0xD8, 0xBB, 0xC1, 0x0A, 0x2F, 0x1D };
|
||||
#define IF_INDEX 1
|
||||
DWORD WINAPI FakeGetIfTable(PMIB_IFTABLE pIfTable, PULONG pdwSize, BOOL bOrder) {
|
||||
DWORD ret = TrueGetIfTable(pIfTable, pdwSize, bOrder);
|
||||
if (ret == NO_ERROR) {
|
||||
for (size_t i = 0; i < pIfTable->dwNumEntries; i++) {
|
||||
pIfTable->table[i].bPhysAddr[0] = 0x00;
|
||||
pIfTable->table[i].bPhysAddr[1] = 0xD0;
|
||||
pIfTable->table[i].bPhysAddr[2] = 0xF1;
|
||||
log_info("network", "Injecting fake IfTable");
|
||||
|
||||
MIB_IFROW* row;
|
||||
uint32_t nbytes;
|
||||
|
||||
if (pdwSize == NULL) return ERROR_INVALID_PARAMETER;
|
||||
|
||||
nbytes = *pdwSize;
|
||||
*pdwSize = sizeof(*row) + sizeof(DWORD);
|
||||
|
||||
if (pIfTable == NULL || nbytes < sizeof(*row) + sizeof(DWORD)) {
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
pIfTable->dwNumEntries = 1;
|
||||
|
||||
row = pIfTable->table;
|
||||
memset(row, 0, sizeof(*row));
|
||||
|
||||
wcscpy_s(row->wszName, _countof(row->wszName), L"RING2 Ethernet");
|
||||
row->dwIndex = IF_INDEX;
|
||||
row->dwType = IF_TYPE_ETHERNET_CSMACD;
|
||||
row->dwMtu = 4200;
|
||||
row->dwSpeed = 1000000000;
|
||||
row->dwPhysAddrLen = sizeof(spoof_mac);
|
||||
memcpy(row->bPhysAddr, spoof_mac, sizeof(spoof_mac));
|
||||
row->dwAdminStatus = 1;
|
||||
row->dwOperStatus = IF_OPER_STATUS_OPERATIONAL;
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
|
||||
// DWORD ret = TrueGetIfTable(pIfTable, pdwSize, bOrder);
|
||||
// if (ret == NO_ERROR) {
|
||||
// for (size_t i = 0; i < pIfTable->dwNumEntries; i++) {
|
||||
// pIfTable->table[i].bPhysAddr[0] = 0x00;
|
||||
// pIfTable->table[i].bPhysAddr[1] = 0xD0;
|
||||
// pIfTable->table[i].bPhysAddr[2] = 0xF1;
|
||||
// }
|
||||
// }
|
||||
// return ret;
|
||||
}
|
||||
const char* INTERCEPT_DNS[] = {
|
||||
"naominet.jp", // Startup
|
||||
"ib.naominet.jp", // Billing
|
||||
"aime.naominet.jp", // Aime (duh)
|
||||
"tenporouter.loc", // Routers
|
||||
"bbrouter.loc", //
|
||||
"mobirouter.loc", //
|
||||
"dslrouter.loc", //
|
||||
|
||||
typedef struct {
|
||||
char* name;
|
||||
unsigned char address[4];
|
||||
} dns;
|
||||
dns INTERCEPT_DNS[] = {
|
||||
// Startup
|
||||
{ "naominet.jp", { 192, 168, 103, 254 } },
|
||||
// Billing
|
||||
{ "ib.naominet.jp", { 192, 168, 103, 254 } },
|
||||
// Aime
|
||||
{ "aime.naominet.jp", { 192, 168, 103, 254 } },
|
||||
// Routers (ping targets)
|
||||
{ "tenporouter.loc", { 192, 168, 103, 254 } },
|
||||
{ "bbrouter.loc", { 192, 168, 103, 254 } }, // Must match tenporouter
|
||||
{ "mobirouter.loc", { 192, 168, 103, 254 } },
|
||||
{ "dslrouter.loc", { 192, 168, 103, 254 } },
|
||||
};
|
||||
|
||||
DNS_RECORDA dummy_record;
|
||||
|
||||
unsigned char SPOOF_IP[4] = { 10, 0, 0, 4 };
|
||||
DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra, PDNS_RECORDA* ppQueryResults,
|
||||
PVOID* pReserved) {
|
||||
DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID pExtra,
|
||||
PDNS_RECORDA* ppQueryResults, PVOID* pReserved) {
|
||||
if (ppQueryResults) {
|
||||
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
|
||||
if (strcmp(pszName, INTERCEPT_DNS[i]) == 0) {
|
||||
log_info("dns", "Replacing %s with %hhu.%hhu.%hhu.%hhu", pszName, SPOOF_IP[0], SPOOF_IP[1], SPOOF_IP[2],
|
||||
SPOOF_IP[3]);
|
||||
if (strcmp(pszName, INTERCEPT_DNS[i].name) == 0) {
|
||||
#define spoof (INTERCEPT_DNS[i].address)
|
||||
log_info("dns", "Replacing %s with %hhu.%hhu.%hhu.%hhu", pszName, spoof[0],
|
||||
spoof[1], spoof[2], spoof[3]);
|
||||
|
||||
// We only support replacing at most one address, but that's all we'll ever need to!
|
||||
(*ppQueryResults) = &dummy_record;
|
||||
(*ppQueryResults)->pNext = NULL;
|
||||
(*ppQueryResults)->wType = DNS_TYPE_A;
|
||||
(*ppQueryResults)->Data.A.IpAddress =
|
||||
(SPOOF_IP[0]) | (SPOOF_IP[1] << 8) | (SPOOF_IP[2] << 16) | (SPOOF_IP[3] << 24);
|
||||
(spoof[0]) | (spoof[1] << 8) | (spoof[2] << 16) | (spoof[3] << 24);
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
#undef spoof
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -55,31 +98,36 @@ DNS_STATUS WINAPI FakeDnsQuery_A(PCSTR pszName, WORD wType, DWORD Options, PVOID
|
||||
return TrueDnsQuery_A(pszName, wType, Options, pExtra, ppQueryResults, pReserved);
|
||||
};
|
||||
|
||||
INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily, LPWSAPROTOCOL_INFOA lpProtocolInfo,
|
||||
LPSOCKADDR lpAddress, LPINT lpAddressLength) {
|
||||
INT WSAAPI FakeWSAStringToAddressA(LPSTR AddressString, INT AddressFamily,
|
||||
LPWSAPROTOCOL_INFOA lpProtocolInfo, LPSOCKADDR lpAddress,
|
||||
LPINT lpAddressLength) {
|
||||
log_misc("dns", "(WSA)DNS lookup for %s", AddressString);
|
||||
for (size_t i = 0; i < sizeof INTERCEPT_DNS / sizeof INTERCEPT_DNS[0]; i++) {
|
||||
if (strcmp(AddressString, INTERCEPT_DNS[i]) == 0) {
|
||||
log_info("dns", "(WSA)Replacing %s with %hhu.%hhu.%hhu.%hhu", AddressString, SPOOF_IP[0], SPOOF_IP[1],
|
||||
SPOOF_IP[2], SPOOF_IP[3]);
|
||||
if (strcmp(AddressString, INTERCEPT_DNS[i].name) == 0) {
|
||||
#define spoof (INTERCEPT_DNS[i].address)
|
||||
log_info("dns", "(WSA)Replacing %s with %hhu.%hhu.%hhu.%hhu", AddressString, spoof[0],
|
||||
spoof[1], spoof[2], spoof[3]);
|
||||
|
||||
lpAddress->sa_family = AF_INET;
|
||||
// ... :)
|
||||
lpAddress->sa_data[2] = SPOOF_IP[0];
|
||||
lpAddress->sa_data[3] = SPOOF_IP[1];
|
||||
lpAddress->sa_data[4] = SPOOF_IP[2];
|
||||
lpAddress->sa_data[5] = SPOOF_IP[3];
|
||||
lpAddress->sa_data[2] = spoof[0];
|
||||
lpAddress->sa_data[3] = spoof[1];
|
||||
lpAddress->sa_data[4] = spoof[2];
|
||||
lpAddress->sa_data[5] = spoof[3];
|
||||
|
||||
return ERROR_SUCCESS;
|
||||
#undef spoof
|
||||
}
|
||||
}
|
||||
log_warning("dns", "(WSA)DNS passthrough for %s", AddressString);
|
||||
return TrueWSAStringToAddressA(AddressString, AddressFamily, lpProtocolInfo, lpAddress, lpAddressLength);
|
||||
return TrueWSAStringToAddressA(AddressString, AddressFamily, lpProtocolInfo, lpAddress,
|
||||
lpAddressLength);
|
||||
}
|
||||
|
||||
void hook_network() {
|
||||
hook("Ws2_32.dll", "connect", Fake_connect, (void**)&True_connect, 5);
|
||||
hook("Ws2_32.dll", "WSAStringToAddressA", FakeWSAStringToAddressA, (void**)&TrueWSAStringToAddressA, 5);
|
||||
hook("Ws2_32.dll", "WSAStringToAddressA", FakeWSAStringToAddressA,
|
||||
(void**)&TrueWSAStringToAddressA, 7);
|
||||
hook("Iphlpapi.dll", "GetIfTable", FakeGetIfTable, (void**)&TrueGetIfTable, 5);
|
||||
hook("Dnsapi.dll", "DnsQuery_A", FakeDnsQuery_A, (void**)&TrueDnsQuery_A, 5);
|
||||
}
|
||||
|
@ -6,28 +6,38 @@ const wchar_t* HOOK_BINARIES[] = {
|
||||
L"app\\GmSync.exe",
|
||||
};
|
||||
|
||||
#define DISABLE_PROC_SPAWNING
|
||||
|
||||
BOOL WINAPI FakeCreateProcessW(LPCWSTR lpApplicationName, LPWSTR lpCommandLine,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes,
|
||||
BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment,
|
||||
LPSECURITY_ATTRIBUTES lpProcessAttributes,
|
||||
LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles,
|
||||
DWORD dwCreationFlags, LPVOID lpEnvironment,
|
||||
LPCWSTR lpCurrentDirectory, LPSTARTUPINFOW lpStartupInfo,
|
||||
LPPROCESS_INFORMATION lpProcessInformation) {
|
||||
// #ifdef DISABLE_PROC_SPAWNING
|
||||
// log_error("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
||||
// return FALSE;
|
||||
// #else
|
||||
log_info("spawn", "CreateProcessW %ls %ls", lpApplicationName, lpCommandLine);
|
||||
|
||||
CHAR applicationName[MAX_PATH + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName, NULL, NULL);
|
||||
WideCharToMultiByte(CP_ACP, 0, lpApplicationName, -1, applicationName, sizeof applicationName,
|
||||
NULL, NULL);
|
||||
|
||||
HANDLE child;
|
||||
if (lpCommandLine != NULL) {
|
||||
CHAR commandLine[MAX_PATH + 1];
|
||||
WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL, NULL);
|
||||
WideCharToMultiByte(CP_ACP, 0, lpCommandLine, -1, commandLine, sizeof commandLine, NULL,
|
||||
NULL);
|
||||
child = start_and_inject(applicationName, commandLine, MICELIB, false);
|
||||
} else {
|
||||
child = start_and_inject(applicationName, NULL, MICELIB, false);
|
||||
}
|
||||
|
||||
return child != NULL;
|
||||
return !FAILED(child);
|
||||
// #endif
|
||||
}
|
||||
|
||||
void hook_processes() {
|
||||
// hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6);
|
||||
hook("Kernel32.dll", "CreateProcessW", FakeCreateProcessW, (void**)&TrueCreateProcessW, 6);
|
||||
}
|
||||
|
5
src/micetools/dll/hooks/registry.c
Normal file
5
src/micetools/dll/hooks/registry.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include "registry.h"
|
||||
|
||||
void hook_registry() {
|
||||
|
||||
}
|
4
src/micetools/dll/hooks/registry.h
Normal file
4
src/micetools/dll/hooks/registry.h
Normal file
@ -0,0 +1,4 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
void hook_registry();
|
@ -21,5 +21,6 @@ shared_library(
|
||||
link_with: [
|
||||
dmi_lib,
|
||||
mice_lib,
|
||||
amlib,
|
||||
]
|
||||
)
|
||||
|
@ -1,6 +1,31 @@
|
||||
#pragma once
|
||||
#include "common.h"
|
||||
|
||||
// PCA9535 (DIPSW)
|
||||
#define PCA9535_WRITE 0x04
|
||||
#define PCA9535_READ 0x05
|
||||
|
||||
#define PCA9535_IN0 0x00
|
||||
#define PCA9535_IN1 0x01
|
||||
#define PCA9535_OUT0 0x02
|
||||
#define PCA9535_OUT1 0x03
|
||||
#define PCA9535_INV0 0x04
|
||||
#define PCA9535_INV1 0x05
|
||||
#define PCA9535_CONF0 0x06
|
||||
#define PCA9535_CONF1 0x07
|
||||
|
||||
#define SMBUS_PCA9535 0x20
|
||||
#define SMBUS_EEPROM 0x57 // Doesn't line up with manual!
|
||||
|
||||
#define SMBUS_DDR2_DIMM_A1 0x000 // what does 0xA0 mean?
|
||||
#define SMBUS_DDR2_DIMM_B1 0x010 // what does 0xA4 mean?
|
||||
#define SMBUS_EEPROM_ 0x0AE // = AT24C64AN
|
||||
#define SMBUS_ICS9LPRS908 0xfff // Unknown
|
||||
#define SMBUS_W83627UHG 0xfff // Unknown; hwmon. Possibly 0x2e or 0x4e
|
||||
#define SMBUS_UPI_UP6261BM8 0xfff // Unknown; vref
|
||||
#define SMBUS_UPI_ISL6322CR 0xfff // Unknown; vrm
|
||||
// SMBUS is send onto the mezzanine board!
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct mxsmbus_request_packet_ {
|
||||
BYTE status;
|
||||
|
@ -28,25 +28,50 @@ HANDLE LOG_FILE = NULL;
|
||||
VOID trace_hook(char* output);
|
||||
CRITICAL_SECTION logger_lock;
|
||||
|
||||
int _do_log(const char* caller, const char* level, const char* format, va_list args, bool toStdout, char* colour) {
|
||||
char* log_colours[] = {
|
||||
"", // Always
|
||||
"\033[96m", // Game
|
||||
"\033[91m", // Error
|
||||
"\033[33m", // Warning
|
||||
"\033[97m", // Info
|
||||
"\033[90m", // Misc
|
||||
"\033[90m", // Trace
|
||||
};
|
||||
#define LOG_PREFIXES "!GEWIMT"
|
||||
|
||||
void logcb(LPCSTR param_1) { log_error("logcb", param_1); }
|
||||
|
||||
extern WCHAR exePath[MAX_PATH + 1];
|
||||
int _do_log(BYTE log_level, const char* caller, const char* format, va_list args) {
|
||||
if (wcscmp(exePath, L"mxnetwork.exe") == 0) {
|
||||
// *((DWORD*)(0x004438e8)) = (DWORD)(&logcb);
|
||||
*((DWORD*)(0x004438e8)) = 0x00000000;
|
||||
}
|
||||
|
||||
char prefix = LOG_PREFIXES[log_level];
|
||||
|
||||
EnterCriticalSection(&logger_lock);
|
||||
int len = snprintf(NULL, 0, "%s%s:%s:", log_prelude(), level, caller) + vsnprintf(NULL, 0, format, args);
|
||||
int len = snprintf(NULL, 0, "%s%c:%s:", log_prelude(), prefix, caller) +
|
||||
vsnprintf(NULL, 0, format, args);
|
||||
char* buf = (char*)malloc(len + 2);
|
||||
if (!buf) {
|
||||
LeaveCriticalSection(&logger_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int wrote_a = snprintf(buf, len, "%s%s:%s:", log_prelude(), level, caller);
|
||||
int wrote_a = snprintf(buf, len, "%s%c:%s:", log_prelude(), prefix, caller);
|
||||
int wrote_b = vsnprintf(buf + wrote_a, len - wrote_a + 1, format, args);
|
||||
buf[len] = '\n';
|
||||
buf[len + 1] = '\0';
|
||||
|
||||
// No +1 here to not get the \n
|
||||
if (toStdout) {
|
||||
if (LOG_LEVEL >= log_level) {
|
||||
HANDLE sout = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
if (HAS_COLOUR) (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, colour, strlen(colour), NULL, NULL);
|
||||
if (sout != INVALID_HANDLE_VALUE) (TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL);
|
||||
if (HAS_COLOUR)
|
||||
(TrueWriteFile ? TrueWriteFile : WriteFile)(sout, log_colours[log_level],
|
||||
strlen(log_colours[log_level]), NULL, NULL);
|
||||
if (sout != INVALID_HANDLE_VALUE)
|
||||
(TrueWriteFile ? TrueWriteFile : WriteFile)(sout, buf, len, NULL, NULL);
|
||||
puts(HAS_COLOUR ? "\033[0m" : "");
|
||||
}
|
||||
#ifdef LOG_TO_FILE
|
||||
@ -59,8 +84,18 @@ int _do_log(const char* caller, const char* level, const char* format, va_list a
|
||||
LeaveCriticalSection(&logger_lock);
|
||||
return wrote_b;
|
||||
}
|
||||
int vlog_trace(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(LOG_TRACE, caller, format, args);
|
||||
}
|
||||
int log_trace(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
int ret = vlog_trace(caller, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
int vlog_misc(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "M", format, args, LOG_MISC, "\033[90m");
|
||||
return _do_log(LOG_MISC, caller, format, args);
|
||||
}
|
||||
int log_misc(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
@ -70,7 +105,7 @@ int log_misc(const char* caller, const char* format, ...) {
|
||||
return ret;
|
||||
}
|
||||
int vlog_info(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "I", format, args, LOG_INFO, "\033[97m");
|
||||
return _do_log(LOG_INFO, caller, format, args);
|
||||
}
|
||||
int log_info(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
@ -80,7 +115,7 @@ int log_info(const char* caller, const char* format, ...) {
|
||||
return ret;
|
||||
}
|
||||
int vlog_warning(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "W", format, args, LOG_WARNING, "\033[33m");
|
||||
return _do_log(LOG_WARNING, caller, format, args);
|
||||
}
|
||||
int log_warning(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
@ -90,7 +125,7 @@ int log_warning(const char* caller, const char* format, ...) {
|
||||
return ret;
|
||||
}
|
||||
int vlog_error(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "E", format, args, LOG_ERROR, "\033[91m");
|
||||
return _do_log(LOG_ERROR, caller, format, args);
|
||||
}
|
||||
int log_error(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
@ -100,7 +135,7 @@ int log_error(const char* caller, const char* format, ...) {
|
||||
return ret;
|
||||
}
|
||||
int vlog_game(const char* caller, const char* format, va_list args) {
|
||||
return _do_log(caller, "G", format, args, LOG_GAME, "\033[96m");
|
||||
return _do_log(LOG_GAME, caller, format, args);
|
||||
}
|
||||
int log_game(const char* caller, const char* format, ...) {
|
||||
va_list args;
|
||||
@ -117,19 +152,23 @@ VOID trace_hook(char* output) {
|
||||
|
||||
void setup_logging() {
|
||||
// Force stdio even for GUI applications
|
||||
// TODO: Is there a more robust way to check if we have a proper stdio?
|
||||
AttachConsole(ATTACH_PARENT_PROCESS);
|
||||
if (GetStdHandle(STD_ERROR_HANDLE) > (HANDLE)0x10) {
|
||||
FILE* newstream;
|
||||
if (GetStdHandle(STD_INPUT_HANDLE)) {
|
||||
freopen("CONIN$", "r", stdin);
|
||||
freopen_s(&newstream, "CONIN$", "r", stdin);
|
||||
setvbuf(stdin, NULL, _IONBF, 0);
|
||||
}
|
||||
if (GetStdHandle(STD_OUTPUT_HANDLE)) {
|
||||
freopen("CONOUT$", "w", stdout);
|
||||
freopen_s(&newstream, "CONOUT$", "w", stdout);
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
}
|
||||
if (GetStdHandle(STD_ERROR_HANDLE)) {
|
||||
freopen("CONOUT$", "w", stderr);
|
||||
freopen_s(&newstream, "CONOUT$", "w", stderr);
|
||||
setvbuf(stderr, NULL, _IONBF, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Enable colour in CMD
|
||||
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
@ -139,6 +178,9 @@ void setup_logging() {
|
||||
|
||||
InitializeCriticalSection(&logger_lock);
|
||||
|
||||
#ifdef LOG_TO_FILE
|
||||
if (LOG_FILE == NULL)
|
||||
LOG_FILE = CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
LOG_FILE =
|
||||
CreateFileA("log.txt", GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, 0, NULL);
|
||||
#endif
|
||||
}
|
||||
|
@ -3,11 +3,14 @@
|
||||
#include <Windows.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define LOG_MISC FALSE
|
||||
#define LOG_INFO TRUE
|
||||
#define LOG_WARNING TRUE
|
||||
#define LOG_ERROR TRUE
|
||||
#define LOG_GAME TRUE
|
||||
#define LOG_GAME 1
|
||||
#define LOG_ERROR 2
|
||||
#define LOG_WARNING 3
|
||||
#define LOG_INFO 4
|
||||
#define LOG_MISC 5
|
||||
#define LOG_TRACE 6
|
||||
|
||||
#define LOG_LEVEL LOG_TRACE
|
||||
|
||||
// #define LOG_TO_FILE
|
||||
|
||||
@ -17,12 +20,14 @@
|
||||
|
||||
extern CRITICAL_SECTION logger_lock;
|
||||
|
||||
int log_trace(const char* caller, const char* format, ...);
|
||||
int log_misc(const char* caller, const char* format, ...);
|
||||
int log_info(const char* caller, const char* format, ...);
|
||||
int log_warning(const char* caller, const char* format, ...);
|
||||
int log_error(const char* caller, const char* format, ...);
|
||||
int log_game(const char* caller, const char* format, ...);
|
||||
|
||||
int vlog_trace(const char* caller, const char* format, va_list args);
|
||||
int vlog_misc(const char* caller, const char* format, va_list args);
|
||||
int vlog_info(const char* caller, const char* format, va_list args);
|
||||
int vlog_warning(const char* caller, const char* format, va_list args);
|
||||
|
46
src/micetools/dll/w83627uhg.h
Normal file
46
src/micetools/dll/w83627uhg.h
Normal 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
|
@ -8,14 +8,21 @@ const char* VERSION = "0.0-pre";
|
||||
|
||||
bool boot_delay = false;
|
||||
bool gametest = false;
|
||||
bool designviewer = false;
|
||||
bool spriteviewer = false;
|
||||
bool noisetest = false;
|
||||
char exe_name[MAX_PATH + 1] = "";
|
||||
char commandline[MAX_PATH + 1] = "";
|
||||
|
||||
void print_help(char* exe) {
|
||||
fprintf(stderr, "Usage: %s [-h] [-t] [-b executable.exe] [-d]\n", exe);
|
||||
fprintf(stderr, " -h: Print this help message and exit\n");
|
||||
fprintf(stderr, " -t: Start the game in test mode\n");
|
||||
fprintf(stderr, " -b: Specify the game binary to use\n");
|
||||
fprintf(stderr, " -d: Wait for a debugger to attach when starting\n");
|
||||
fprintf(stderr, " -t: Start the game in test mode\n");
|
||||
fprintf(stderr, " -dv: Start the game in design viewer mode\n");
|
||||
fprintf(stderr, " -sv: Start the game in sprite viewer mode\n");
|
||||
fprintf(stderr, " -nt: Start the game in noisetest mode\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
@ -27,10 +34,21 @@ void parse_cmdline(int argc, char* argv[]) {
|
||||
if (i + 1 == argc) print_help(argv[0]);
|
||||
char* val = argv[++i];
|
||||
memcpy(exe_name, val, strlen(val) + 1);
|
||||
} else if (strcmp(argv[i], "-d") == 0) {
|
||||
} else if (strcmp(argv[i], "--mice-d") == 0) {
|
||||
boot_delay = true;
|
||||
} else if (strcmp(argv[i], "-t") == 0) {
|
||||
gametest = true;
|
||||
} else if (strcmp(argv[i], "-dv") == 0) {
|
||||
designviewer = true;
|
||||
} else if (strcmp(argv[i], "-sv") == 0) {
|
||||
spriteviewer = true;
|
||||
} else if (strcmp(argv[i], "-nt") == 0) {
|
||||
noisetest = true;
|
||||
} else {
|
||||
if (commandline[0] == 0)
|
||||
strncpy_s(commandline, strlen(argv[i]), argv[i], sizeof commandline);
|
||||
else
|
||||
snprintf(commandline, sizeof commandline, "%s %s", commandline, argv[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -53,7 +71,16 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
char* cmdline = gametest ? ". gametest" : "";
|
||||
char* cmdline_mode = gametest ? ". gametest"
|
||||
: designviewer ? ". designviewer"
|
||||
: spriteviewer ? ". spriteviewer"
|
||||
: noisetest ? ". noisetest"
|
||||
: "";
|
||||
char cmdline[MAX_PATH + 1];
|
||||
if (commandline[0] == 0)
|
||||
snprintf(cmdline, sizeof cmdline, "%s", cmdline_mode);
|
||||
else
|
||||
snprintf(cmdline, sizeof cmdline, "%s %s", cmdline_mode, commandline);
|
||||
fprintf(stderr, "exec: %s %s\n", exe_name, cmdline);
|
||||
|
||||
char micepath[MAX_PATH + 1];
|
||||
|
88
src/micetools/lib/am/amEeprom.c
Normal file
88
src/micetools/lib/am/amEeprom.c
Normal 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;
|
||||
}
|
13
src/micetools/lib/am/amEeprom.h
Normal file
13
src/micetools/lib/am/amEeprom.h
Normal 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);
|
@ -1,4 +1,4 @@
|
||||
#include <amtimer.h>
|
||||
#include <amTimer.h>
|
||||
|
||||
int frequency_loaded = 0;
|
||||
LARGE_INTEGER frequency;
|
||||
@ -13,7 +13,7 @@ amtime_t* amiTimerGet(amtime_t* time) {
|
||||
frequency_loaded = 1;
|
||||
}
|
||||
QueryPerformanceCounter(&counter);
|
||||
time->microseconds = (counter.QuadPart * 1000000) / frequency.QuadPart;
|
||||
time->seconds = counter.QuadPart / frequency.QuadPart;
|
||||
time->microseconds = (unsigned int)((counter.QuadPart * 1000000) / frequency.QuadPart);
|
||||
time->seconds = (unsigned int)(counter.QuadPart / frequency.QuadPart);
|
||||
return time;
|
||||
}
|
||||
|
@ -1,6 +1,10 @@
|
||||
amlib = static_library(
|
||||
'am',
|
||||
sources: [
|
||||
'amtimer.c',
|
||||
'amTimer.c',
|
||||
'amEeprom.c',
|
||||
],
|
||||
link_with: [
|
||||
mice_lib
|
||||
],
|
||||
)
|
||||
|
@ -4,29 +4,32 @@
|
||||
|
||||
LPBYTE dmi_table = NULL;
|
||||
WORD dmi_size = 0;
|
||||
size_t _dmi_max = 0;
|
||||
WORD _dmi_max = 0;
|
||||
|
||||
DMI_BIOS deafult_dmi_bios = {
|
||||
.Head.Type = 0x00,
|
||||
.Head.Length = 0x12,
|
||||
.Head.Handle = 0x0000,
|
||||
.Vendor = 0x00,
|
||||
.Version = 0x00,
|
||||
.StartSegment = 0x0000,
|
||||
.ReleaseDate = 0x00,
|
||||
.ROMSize = 0x00,
|
||||
.Chars = 0x04,
|
||||
.Vendor = 0x01, // "American Megatrends Inc."
|
||||
.Version = 0x02, // "080015 "
|
||||
.StartSegment = 0x0000, // '00 f0'h
|
||||
.ReleaseDate = 0x03, // "07/28/2011"
|
||||
.ROMSize = 0x00, // 03h
|
||||
.Chars = 0x1f, // '1F 90 DA 8B'h
|
||||
.VerMajor = 0x08,
|
||||
.VerMinor = 0x0f,
|
||||
.ECVerMajor = 0xff,
|
||||
.ECVerMinor = 0xff,
|
||||
};
|
||||
|
||||
DMI_SYSTEM default_dmi_system = {
|
||||
.Head.Type = 0x01,
|
||||
.Head.Length = 0x08,
|
||||
.Head.Handle = 0x0001,
|
||||
// TODO: Are these used?
|
||||
.Manufacturer = 0x00,
|
||||
.ProductName = 0x00,
|
||||
.Version = 0x00,
|
||||
.Serial = 0x00,
|
||||
.Manufacturer = 0x01, // "NEC"
|
||||
.ProductName = 0x02, // "To Be Filled By O.E.M."
|
||||
.Version = 0x03, // "To Be Filled By O.E.M."
|
||||
.Serial = 0x04, // "To Be Filled By O.E.M."
|
||||
};
|
||||
|
||||
DMI_STRING deafult_dmi_string = {
|
||||
@ -44,7 +47,7 @@ static void dmi_init(void) {
|
||||
dmi_size = 0;
|
||||
}
|
||||
|
||||
static void dmi_append(void* data, size_t size) {
|
||||
static void dmi_append(void* data, WORD size) {
|
||||
if (!dmi_table) return;
|
||||
while (dmi_size + (size + 1) >= _dmi_max) {
|
||||
LPBYTE new_table = (LPBYTE)realloc(dmi_table, _dmi_max += 0xff);
|
||||
@ -57,7 +60,7 @@ static void dmi_append(void* data, size_t size) {
|
||||
dmi_table[dmi_size++] = 0;
|
||||
}
|
||||
|
||||
static void dmi_append_with_strings(void* data, size_t size, int num_strings, ...) {
|
||||
static void dmi_append_with_strings(void* data, WORD size, int num_strings, ...) {
|
||||
va_list args;
|
||||
va_start(args, num_strings);
|
||||
|
||||
@ -65,7 +68,7 @@ static void dmi_append_with_strings(void* data, size_t size, int num_strings, ..
|
||||
dmi_size -= 2;
|
||||
for (int i = 0; i < num_strings; i++) {
|
||||
char* str = va_arg(args, char*);
|
||||
int len = strlen(str);
|
||||
WORD len = strlen(str) & 0xffff;
|
||||
memcpy((char*)dmi_table + dmi_size, str, len + 1);
|
||||
dmi_size += len + 1;
|
||||
dmi_table[dmi_size - 1] = 0;
|
||||
@ -77,13 +80,16 @@ static void dmi_append_with_strings(void* data, size_t size, int num_strings, ..
|
||||
|
||||
void dmi_build_default() {
|
||||
dmi_init();
|
||||
dmi_append(&deafult_dmi_bios, sizeof deafult_dmi_bios);
|
||||
dmi_append_with_strings(&deafult_dmi_bios, sizeof deafult_dmi_bios, 3,
|
||||
"American Megatrends Inc.", "080015 ", "07/28/2011");
|
||||
|
||||
// Platform AAM: Board type one of "Supermicro"(=1) or "Advantech"(=2)
|
||||
// Platform AAL: Board type one of "NEC"(=0) or "AAL2"(=3)
|
||||
dmi_append_with_strings(&default_dmi_system, sizeof default_dmi_system, 4, "NEC",
|
||||
"To Be Filled By O.E.M.", "To Be Filled By O.E.M.",
|
||||
"To Be Filled By O.E.M.");
|
||||
|
||||
dmi_append_with_strings(&default_dmi_system, sizeof default_dmi_system, 1, "Supermicro");
|
||||
|
||||
deafult_dmi_string.NoStrings = 3;
|
||||
deafult_dmi_string.NoStrings = 5;
|
||||
|
||||
dmi_append_with_strings(&deafult_dmi_string, sizeof deafult_dmi_string,
|
||||
// OEM strings:
|
||||
@ -100,7 +106,8 @@ void dmi_build_default() {
|
||||
// AAM = 4
|
||||
// Supermicro = 4
|
||||
// Advantech = 4
|
||||
5, ".", ".", "AAM", ".", "AAL");
|
||||
// These values are pulled from an 846-5004D
|
||||
5, "DAC-BJ02", "DAC-BJ02", "AAL", "Advantech", "AAL2");
|
||||
}
|
||||
|
||||
BYTE dmi_calc_checksum(const char* buf, int len) {
|
||||
|
@ -33,6 +33,10 @@ typedef struct {
|
||||
BYTE ReleaseDate;
|
||||
BYTE ROMSize;
|
||||
uint64_t Chars;
|
||||
BYTE VerMajor;
|
||||
BYTE VerMinor;
|
||||
BYTE ECVerMajor;
|
||||
BYTE ECVerMinor;
|
||||
} DMI_BIOS;
|
||||
|
||||
#pragma pack(1)
|
||||
@ -51,8 +55,8 @@ typedef struct {
|
||||
} DMI_STRING;
|
||||
|
||||
static void dmi_init(void);
|
||||
static void dmi_append(void* data, size_t size);
|
||||
static void dmi_append_with_strings(void* data, size_t size, int num_strings, ...);
|
||||
static void dmi_append(void* data, WORD size);
|
||||
static void dmi_append_with_strings(void* data, WORD size, int num_strings, ...);
|
||||
|
||||
void dmi_build_default(void);
|
||||
BYTE dmi_calc_checksum(const char* buf, int len);
|
||||
|
@ -43,7 +43,7 @@
|
||||
|
||||
typedef unsigned int json_uchar;
|
||||
|
||||
const struct _json_value json_value_none;
|
||||
const struct _json_value json_value_none = { 0 };
|
||||
|
||||
static int would_overflow(json_int_t value, json_char b) { return ((JSON_INT_MAX - (b - '0')) / 10) < value; }
|
||||
|
||||
@ -263,8 +263,8 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
if (state.first_pass)
|
||||
string_length += 2;
|
||||
else {
|
||||
string[string_length++] = 0xC0 | (uchar >> 6);
|
||||
string[string_length++] = 0x80 | (uchar & 0x3F);
|
||||
string[string_length++] = (char)(0xC0 | (uchar >> 6));
|
||||
string[string_length++] = (char)(0x80 | (uchar & 0x3F));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -274,9 +274,9 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
if (state.first_pass)
|
||||
string_length += 3;
|
||||
else {
|
||||
string[string_length++] = 0xE0 | (uchar >> 12);
|
||||
string[string_length++] = 0x80 | ((uchar >> 6) & 0x3F);
|
||||
string[string_length++] = 0x80 | (uchar & 0x3F);
|
||||
string[string_length++] = 0xE0 | (char)((uchar >> 12));
|
||||
string[string_length++] = 0x80 | (char)(((uchar >> 6) & 0x3F));
|
||||
string[string_length++] = 0x80 | (char)((uchar & 0x3F));
|
||||
}
|
||||
|
||||
break;
|
||||
@ -285,10 +285,10 @@ json_value *json_parse_ex(json_settings *settings, const json_char *json, size_t
|
||||
if (state.first_pass)
|
||||
string_length += 4;
|
||||
else {
|
||||
string[string_length++] = 0xF0 | (uchar >> 18);
|
||||
string[string_length++] = 0x80 | ((uchar >> 12) & 0x3F);
|
||||
string[string_length++] = 0x80 | ((uchar >> 6) & 0x3F);
|
||||
string[string_length++] = 0x80 | (uchar & 0x3F);
|
||||
string[string_length++] = 0xF0 | (char)((uchar >> 18));
|
||||
string[string_length++] = 0x80 | (char)(((uchar >> 12) & 0x3F));
|
||||
string[string_length++] = 0x80 | (char)(((uchar >> 6) & 0x3F));
|
||||
string[string_length++] = 0x80 | (char)((uchar & 0x3F));
|
||||
}
|
||||
|
||||
break;
|
||||
|
1
src/micetools/lib/libpcp/libpcp.c
Normal file
1
src/micetools/lib/libpcp/libpcp.c
Normal file
@ -0,0 +1 @@
|
||||
#include "libpcp.h"
|
3
src/micetools/lib/libpcp/pcp.c
Normal file
3
src/micetools/lib/libpcp/pcp.c
Normal 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";
|
@ -5,6 +5,7 @@
|
||||
#define ZERO_BUF(x) memset((x), 0, sizeof(*x))
|
||||
|
||||
#include <Winsock2.h>
|
||||
#include <ws2ipdef.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@ -29,7 +30,7 @@ typedef unsigned char byte;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned int uint;
|
||||
|
||||
typedef int timeout_t;
|
||||
typedef unsigned int timeout_t;
|
||||
|
||||
#define PCP_BUF_MAX 256
|
||||
#define PCP_CMDS_MAX 64
|
||||
@ -43,7 +44,7 @@ typedef struct pcp_parse_data {
|
||||
uint cmd_count;
|
||||
} pcp_parse_data_t;
|
||||
typedef struct pcp_send_data {
|
||||
char data[PCP_BUF_MAX];
|
||||
unsigned char data[PCP_BUF_MAX];
|
||||
size_t length;
|
||||
} pcp_send_data_t;
|
||||
|
||||
@ -63,8 +64,9 @@ typedef enum binary_mode {
|
||||
#define PCPT_SO_LINGER 2
|
||||
#define PCPT_TCP_NODELAY 3
|
||||
|
||||
#define SOCKET_INVAL ((SOCKET)-1)
|
||||
#define HANDLE_INVAL -1
|
||||
#define TIMEOUT_NONE -1
|
||||
#define TIMEOUT_NONE ((DWORD)-1)
|
||||
|
||||
#define PCPT_CLOSED 0
|
||||
#define PCPT_LISTENING 1
|
||||
|
630
src/micetools/lib/libpcp/pcpa.c
Normal file
630
src/micetools/lib/libpcp/pcpa.c
Normal 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);
|
||||
}
|
@ -39,9 +39,9 @@ typedef struct pcpa {
|
||||
pcpa_cb_table_t* callback_table;
|
||||
uint callback_max;
|
||||
uint callback_count;
|
||||
char* recv_buffer;
|
||||
unsigned char* recv_buffer;
|
||||
size_t recv_buffer_len;
|
||||
char* send_buffer;
|
||||
unsigned char* send_buffer;
|
||||
size_t send_buffer_len;
|
||||
binary_mode_t binary_mode;
|
||||
pcpa_callback* binary_mode_before_cb;
|
||||
|
1758
src/micetools/lib/libpcp/pcpp.c
Normal file
1758
src/micetools/lib/libpcp/pcpp.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -19,6 +19,14 @@ typedef enum e_pcpp {
|
||||
e_pcpp_inval_addr = -15,
|
||||
e_pcpp_wsa_noinit = -16,
|
||||
e_pcpp_unknown = -17,
|
||||
|
||||
e_pcpp_uk1 = -14,
|
||||
e_pcpp_uk2 = -13,
|
||||
e_pcpp_uk3 = -11,
|
||||
e_pcpp_uk4 = -9,
|
||||
e_pcpp_uk5 = -8,
|
||||
e_pcpp_uk6 = -7,
|
||||
e_pcpp_uk7 = -4,
|
||||
} e_pcpp_t;
|
||||
|
||||
e_pcpp_t _pcppGetErrorFromPcpt(e_pcpt_t err);
|
||||
@ -32,17 +40,17 @@ typedef struct pcpp {
|
||||
uint state;
|
||||
e_pcpp_t err;
|
||||
pcp_parse_data_t* recv_data_buffer;
|
||||
char read_bytes_buf[PCP_BUF_MAX];
|
||||
unsigned char read_bytes_buf[PCP_BUF_MAX];
|
||||
uint read_bytes_size;
|
||||
uint read_bytes_num;
|
||||
pcp_send_data_t* resp_buffer;
|
||||
uint resp_buffer_len;
|
||||
char send_buf[PCP_SEND_BUF_MAX];
|
||||
unsigned char send_buf[PCP_SEND_BUF_MAX];
|
||||
size_t send_buf_len;
|
||||
uint field_0x1e8;
|
||||
char* send_binary_buf;
|
||||
unsigned char* send_binary_buf;
|
||||
uint field_0x1f0;
|
||||
char* recv_binary_buf;
|
||||
unsigned char* recv_binary_buf;
|
||||
size_t field_0x1f8;
|
||||
uint field_0x1fc;
|
||||
size_t recv_binary_buf_len;
|
||||
@ -56,13 +64,13 @@ typedef struct pcpp {
|
||||
} pcpp_t;
|
||||
|
||||
pcp_send_data_t* pcppAddSendPacket(pcp_send_data_t* stream, char* key, char* value);
|
||||
pcp_parse_data_t* pcppChangeRequest(pcpp_t* stream, int* lenout);
|
||||
pcp_parse_data_t* pcppChangeRequest(pcpp_t* stream, uint* lenout);
|
||||
bool pcppCheckPrompt(pcpp_t* stream);
|
||||
e_pcpp_t pcppCheckRecvMsg(char* recv_data, size_t buf_len, int param_3);
|
||||
uint pcppCheckStr(char* param_1, uint* pcp_len, int* pcp_overflow);
|
||||
e_pcpp_t pcppCheckRecvMsg(unsigned char* recv_data, size_t buf_len, int param_3);
|
||||
uint pcppCheckStr(unsigned char* param_1, uint* pcp_len, int* pcp_overflow);
|
||||
void pcppClose(pcpp_t* stream);
|
||||
void pcppCloseBinary(pcpp_t* stream);
|
||||
e_pcpp_t pcppGetBlockingTime(uint param_1, int param_2, pcpp_t* stream, int param_4, uint* blocking_time);
|
||||
e_pcpp_t pcppGetBlockingTime(uint param_1, timeout_t param_2, pcpp_t* stream, int param_4, uint* blocking_time);
|
||||
char* pcppGetCommand(pcp_parse_data_t* pcpa, char* command);
|
||||
char* pcppGetKeyword(pcp_parse_data_t* recvData, uint keyword_num);
|
||||
SOCKET pcppGetServerSocket(pcpp_t* stream, int which);
|
||||
@ -71,17 +79,17 @@ e_pcpp_t pcppIsBusy(pcpp_t* stream, timeout_t timeout);
|
||||
e_pcpp_t pcppOpenBinaryServer(pcpp_t* stream, int open_mode, ushort port);
|
||||
e_pcpp_t pcppOpenServer(pcpp_t* stream, int open_mode, ushort port, undefined4 param_4);
|
||||
e_pcpp_t pcppRecvAllMsg(uint param_1, pcpp_t* stream, bool* bReRecv);
|
||||
e_pcpp_t pcppRecvBinary(pcpp_t* stream, char* recv_buf, size_t buf_len, uint param_4);
|
||||
uint pcppRecvCheck(char* buf, int* found_at);
|
||||
e_pcpp_t pcppRecvBinary(pcpp_t* stream, unsigned char* recv_buf, size_t buf_len, uint param_4);
|
||||
uint pcppRecvCheck(unsigned char* buf, int* found_at);
|
||||
e_pcpp_t pcppRecvPrompt(pcpp_t* stream, undefined4 param_2, int param_3);
|
||||
e_pcpp_t pcppRecvRequest(pcpp_t* stream, pcp_parse_data_t* recv_data, timeout_t timeout);
|
||||
e_pcpp_t pcppRecvRequestMain(pcpp_t* stream, bool* bReRecv, undefined4 param_3);
|
||||
e_pcpp_t pcppSendBinary(pcpp_t* stream, char* send_binary_buffer, size_t param_3, uint param_4);
|
||||
e_pcpp_t pcppSendPrompt(pcpp_t* stream, uint param_2, int param_3);
|
||||
e_pcpp_t pcppSendRequestMain(pcpp_t* stream, undefined4 param_2, int param_3);
|
||||
e_pcpp_t pcppSendBinary(pcpp_t* stream, unsigned char* send_binary_buffer, size_t param_3, uint param_4);
|
||||
e_pcpp_t pcppSendPrompt(pcpp_t* stream, uint param_2, timeout_t timeout_ms);
|
||||
e_pcpp_t pcppSendRequestMain(pcpp_t* stream, undefined4 param_2, timeout_t timeout_ms);
|
||||
e_pcpp_t pcppSendResponse(pcpp_t* stream, pcp_send_data_t* resp_buffer, size_t buf_len, timeout_t timeout_ms);
|
||||
e_pcpp_t pcppSendResponseTable(pcpp_t* stream, pcp_send_data_t* data, timeout_t timeout_ms);
|
||||
pcp_send_data_t* pcppSetSendPacket(pcp_send_data_t* send_data, char* keyword, char* value);
|
||||
e_pcpp_t pcpp_something(amtime_t* now, timeout_t timeout, pcpp_t* stream, pcpt_t* sock, char* send_buf,
|
||||
e_pcpp_t pcpp_something(amtime_t* now, timeout_t timeout, pcpp_t* stream, pcpt_t* sock, unsigned char* send_buf,
|
||||
size_t* send_len, undefined4 param_7, undefined4 param_8, e_pcpp_t fallback_err);
|
||||
void pcppResetRead(pcpp_t* param_1);
|
||||
|
758
src/micetools/lib/libpcp/pcpt.c
Normal file
758
src/micetools/lib/libpcp/pcpt.c
Normal 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;
|
||||
}
|
@ -40,9 +40,9 @@ typedef struct pcpt {
|
||||
uint tcp_nodelay;
|
||||
WSAEVENT client_event;
|
||||
WSAEVENT server_event;
|
||||
char* send_buf;
|
||||
unsigned char* send_buf;
|
||||
size_t* send_buf_count;
|
||||
char* recv_buf;
|
||||
unsigned char* recv_buf;
|
||||
size_t* recv_buf_count;
|
||||
uint field_0x40;
|
||||
SOCKADDR client_addr;
|
||||
@ -59,7 +59,7 @@ e_pcpt_t pcptCheckEvent(HANDLE event, timeout_t timeout_ms, SOCKET socket, uint
|
||||
e_pcpt_t pcptIsBusy(pcpt_t* sock, timeout_t timeout_ms);
|
||||
e_pcpt_t pcptOpenDataSockServer(pcpt_t* sock, timeout_t timeout_ms);
|
||||
e_pcpt_t pcptOpenServer(pcpt_t* sock, int open_mode, ushort port);
|
||||
e_pcpt_t pcptRecv(pcpt_t* sock, char* recv_buf, size_t* recv_buf_len, timeout_t timeout_ms);
|
||||
e_pcpt_t pcptSend(pcpt_t* sock, char* send_buf, size_t* send_len, uint param_4, timeout_t timeout_ms);
|
||||
e_pcpt_t pcptRecv(pcpt_t* sock, unsigned char* recv_buf, size_t* recv_buf_len, timeout_t timeout_ms);
|
||||
e_pcpt_t pcptSend(pcpt_t* sock, unsigned char* send_buf, size_t* send_len, uint param_4, timeout_t timeout_ms);
|
||||
e_pcpt_t pcptSendAllMsg(pcpt_t* sock, timeout_t timeout_ms);
|
||||
void pcptSetConfig(pcpt_t* sock, uint config, uint value);
|
||||
|
87
src/micetools/lib/libpcp/util.c
Normal file
87
src/micetools/lib/libpcp/util.c
Normal 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("");
|
||||
}
|
||||
}
|
@ -1,16 +1,8 @@
|
||||
subdir('util') # This is the only lib that should ever be link_with'd by another lib
|
||||
subdir('json')
|
||||
subdir('am')
|
||||
subdir('dmi')
|
||||
subdir('mice')
|
||||
subdir('am')
|
||||
|
||||
fs = import('fs')
|
||||
# Handle the fact we aren't distributing the libpcp source
|
||||
if fs.exists('libpcp/libpcp.c')
|
||||
subdir('libpcp')
|
||||
libpcp_is_static = true
|
||||
else
|
||||
libpcp = meson.get_compiler('c').find_library('libpcp', dirs: libs_dir, required: false)
|
||||
assert(libpcp.found(), 'Unable to locate libpcp.lib. Make sure to place it in the src/ folder prior to building.')
|
||||
libpcp_is_static = false
|
||||
endif
|
||||
subdir('libpcp')
|
||||
|
@ -69,7 +69,7 @@ bool inject_dll(HANDLE process, LPCSTR inject) {
|
||||
|
||||
HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||
STARTUPINFOA startupInfo;
|
||||
PROCESS_INFORMATION processInformation;
|
||||
PROCESS_INFORMATION processInformation = { 0 };
|
||||
|
||||
memset(&startupInfo, 0, sizeof(startupInfo));
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
@ -78,16 +78,23 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||
// snprintf(real_inject_path, MAX_PATH + 1, ".\\%s", inject);
|
||||
// GetFullPathNameA(real_inject_path, MAX_PATH + 1, &real_inject_path, NULL);
|
||||
|
||||
// Validate that we're not about to try something insane
|
||||
DWORD found = SearchPathA(NULL, inject, NULL, 0, NULL, NULL);
|
||||
DWORD found;
|
||||
// Does the exe we're starting exist?
|
||||
found = SearchPathA(NULL, path, NULL, 0, NULL, NULL);
|
||||
if (found == 0) {
|
||||
fprintf(stderr, "Fatal: Cannot inject %s: not found: %03x\n", inject, GetLastError());
|
||||
fprintf(stderr, "Fatal: Cannot start %s: not found\n", path);
|
||||
goto abort;
|
||||
}
|
||||
// Does the DLL we want to inject exist?
|
||||
found = SearchPathA(NULL, inject, NULL, 0, NULL, NULL);
|
||||
if (found == 0) {
|
||||
fprintf(stderr, "Fatal: Cannot inject %s: not found\n", inject);
|
||||
goto abort;
|
||||
}
|
||||
|
||||
// Start the binary
|
||||
if (FAILED(CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo,
|
||||
&processInformation))) {
|
||||
if (!CreateProcessA(path, cmdline, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &startupInfo,
|
||||
&processInformation)) {
|
||||
fprintf(stderr, "Fatal: CreateProcessA failed: %03x\n", GetLastError());
|
||||
goto abort;
|
||||
}
|
||||
@ -107,16 +114,16 @@ HANDLE start_and_inject(LPCSTR path, LPSTR cmdline, LPCSTR inject, BOOL delay) {
|
||||
|
||||
abort:
|
||||
if (processInformation.hProcess) {
|
||||
if (FAILED(CloseHandle(processInformation.hThread)))
|
||||
if (!CloseHandle(processInformation.hThread))
|
||||
fprintf(stderr, "Fatal: CloseHandle(hProcess) failed: %03x\n", GetLastError());
|
||||
|
||||
if (FAILED(TerminateProcess(processInformation.hProcess, 1)))
|
||||
if (!TerminateProcess(processInformation.hProcess, 1))
|
||||
fprintf(stderr, "Fatal: TerminateProcess failed: %03x\n", GetLastError());
|
||||
}
|
||||
if (processInformation.hThread) {
|
||||
if (FAILED(CloseHandle(processInformation.hThread)))
|
||||
if (!CloseHandle(processInformation.hThread))
|
||||
fprintf(stderr, "Fatal: CloseHandle(hThread) failed: %03x\n", GetLastError());
|
||||
}
|
||||
|
||||
return NULL;
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
@ -5,8 +5,10 @@
|
||||
// amSramInit
|
||||
#define IOCTL_MXSRAM_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
// amSramInit
|
||||
#define IOCTL_MXSRAM_GET_SECTOR_SIZE CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXSRAM_GET_VERSION CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXSRAM_GET_SECTOR_SIZE \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXSRAM_GET_VERSION \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
// EEPROM uses MXSMBUS_GUID device class
|
||||
// DIPSW uses MXSMBUS_GUID device class
|
||||
@ -25,11 +27,13 @@
|
||||
#define IOCTL_MXSUPERIO_PING CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
// amHmGetLPCChipId
|
||||
#define IOCTL_MXSUPERIO_READ CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MXSUPERIO_UNKNOWN CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXSUPERIO_WRITE CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
// amHmLpcReadByte
|
||||
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_READ CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_READ \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
// amHmLpcWriteByte
|
||||
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXSUPERIO_HWMONITOR_LPC_WRITE \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
|
||||
#define IOCTL_MXJVS_EXCHANGE CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
@ -37,20 +41,29 @@
|
||||
// amHmI2CReadByte,amHmI2CWriteByte,amEepromWait
|
||||
#define IOCTL_MXSMBUS_REQUEST CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
// amEepromGetDriverVerision
|
||||
#define IOCTL_MXSMBUS_GET_VERSION CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXSMBUS_GET_VERSION \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
// amEepromI2CReadBlock,amEepromI2CWriteBlock,amHmGetLPCChipId
|
||||
#define IOCTL_MXSMBUS_I2C CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#define IOCTL_MXSMBUS_IDK CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_COLUMBA_READ_DMI CTL_CODE(FILE_DEVICE_SEGA, 0x841, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_COLUMBA_READ CTL_CODE(FILE_DEVICE_SEGA, 0x841, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
||||
#define IOCTL_MXHWRESET_RESET CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
|
||||
#define IOCTL_MXPARALLEL_WRITE_DATA CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_DATA CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_WRITE_STATUS CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_STATUS CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_WRITE_CTRL_PORT CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_CTRL_PORT CTL_CODE(FILE_DEVICE_SEGA, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_WRITE_FLAGS CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_FLAGS CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_WRITE_DATA \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x800, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_DATA \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x801, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_WRITE_STATUS \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x802, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_STATUS \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x803, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_WRITE_CTRL_PORT \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x804, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_CTRL_PORT \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x805, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_WRITE_FLAGS \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x806, METHOD_BUFFERED, FILE_WRITE_ACCESS)
|
||||
#define IOCTL_MXPARALLEL_READ_FLAGS \
|
||||
CTL_CODE(FILE_DEVICE_SEGA, 0x807, METHOD_BUFFERED, FILE_READ_ACCESS)
|
||||
|
@ -25,7 +25,7 @@ bool fetch_int(json_value* object, char* name, size_t* value) {
|
||||
json_value* fetched;
|
||||
if (!fetch(object, name, &fetched)) return false;
|
||||
if (fetched->type != json_integer) return false;
|
||||
*value = fetched->u.integer;
|
||||
*value = (size_t)fetched->u.integer;
|
||||
return true;
|
||||
}
|
||||
bool fetch_bool(json_value* object, char* name, bool* value) {
|
||||
@ -39,7 +39,7 @@ void free_patches(patches_t* patches) {
|
||||
if (patches->nopatchsets == 0) return;
|
||||
for (int i = patches->nopatchsets - 1; i >= 0; i--) {
|
||||
if (patches->patchsets[i] != NULL) {
|
||||
for (int j = 0; j < patches->patchsets[i]->nopatches; j++) {
|
||||
for (size_t j = 0; j < patches->patchsets[i]->nopatches; j++) {
|
||||
if (patches->patchsets[i]->patches[j].from != NULL) free(patches->patchsets[i]->patches[j].from);
|
||||
if (patches->patchsets[i]->patches[j].to != NULL) free(patches->patchsets[i]->patches[j].to);
|
||||
}
|
||||
@ -181,8 +181,8 @@ bool parse_patches(patches_t* patches, json_value** set_json, int set_count, cha
|
||||
snprintf(error, json_error_max, "invalid hex string in patch %s[%d]", name, j);
|
||||
goto failed;
|
||||
}
|
||||
char* bin_from = patchset->patches[j].from = (char*)malloc(size / 2);
|
||||
char* bin_to = patchset->patches[j].to = (char*)malloc(size / 2);
|
||||
unsigned char* bin_from = patchset->patches[j].from = (unsigned char*)malloc(size / 2);
|
||||
unsigned char* bin_to = patchset->patches[j].to = (unsigned char*)malloc(size / 2);
|
||||
if (!hex_to_bin(from, bin_from, size)) {
|
||||
snprintf(error, json_error_max, "invalid hex string in patch %s[%d].from", name, j);
|
||||
goto failed;
|
||||
|
@ -4,5 +4,5 @@ subdir('micepatch')
|
||||
subdir('micekeychip')
|
||||
subdir('launcher')
|
||||
subdir('dll')
|
||||
|
||||
subdir('micetest')
|
||||
subdir('miceboot')
|
||||
subdir('util')
|
||||
|
4
src/micetools/miceboot/TrueCrypt.cmd
Normal file
4
src/micetools/miceboot/TrueCrypt.cmd
Normal file
@ -0,0 +1,4 @@
|
||||
@echo off
|
||||
@REM "C:\Program Files (x86)\TrueCrypt\TrueCrypt.exe" %*
|
||||
echo %*
|
||||
pause
|
150
src/micetools/miceboot/ewfapi.h
Normal file
150
src/micetools/miceboot/ewfapi.h
Normal 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__
|
31
src/micetools/miceboot/meson.build
Normal file
31
src/micetools/miceboot/meson.build
Normal 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',
|
||||
],
|
||||
)
|
105
src/micetools/miceboot/mice_ewfapi.h
Normal file
105
src/micetools/miceboot/mice_ewfapi.h
Normal 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);
|
8
src/micetools/miceboot/mxmaster.c
Normal file
8
src/micetools/miceboot/mxmaster.c
Normal 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);
|
||||
}
|
216
src/micetools/miceboot/mxprestartup.c
Normal file
216
src/micetools/miceboot/mxprestartup.c
Normal 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;
|
||||
}
|
410
src/micetools/miceboot/mxstartup.c
Normal file
410
src/micetools/miceboot/mxstartup.c
Normal 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); }
|
5
src/micetools/miceboot/truecrypt.c
Normal file
5
src/micetools/miceboot/truecrypt.c
Normal file
@ -0,0 +1,5 @@
|
||||
#include <stdio.h>
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
puts("TrueCrypt.exe dummy hit");
|
||||
}
|
@ -72,6 +72,6 @@ void mxkPcpAbSeed(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, AB_SEED, "0");
|
||||
pcpaAddSendPacket(stream, "port", "40107");
|
||||
char sSize[16]; // todo: nicer lol
|
||||
_itoa(SEED_BUF_LEN, sSize, 10);
|
||||
_itoa_s(SEED_BUF_LEN, sSize, sizeof sSize, 10);
|
||||
pcpaAddSendPacket(stream, "size", sSize);
|
||||
}
|
||||
|
@ -106,6 +106,6 @@ void mxkPcpPbCaCertification(pcpa_t* stream, void* data) {
|
||||
pcpaSetSendPacket(stream, BIL_CACERT, "0");
|
||||
pcpaAddSendPacket(stream, "port", "40107");
|
||||
char sSize[16]; // todo: nicer lol
|
||||
_itoa(CA_CERT_LEN, sSize, 10);
|
||||
_itoa_s(CA_CERT_LEN, sSize, sizeof sSize, 10);
|
||||
pcpaAddSendPacket(stream, "size", sSize);
|
||||
}
|
||||
|
@ -1,14 +1,6 @@
|
||||
dependencies = []
|
||||
link_with = [inih.get_variable('lib_inih')]
|
||||
link_with = [inih.get_variable('lib_inih'), libpcp]
|
||||
|
||||
# Depending on how we're getting access to libpcp, we need some extra work here
|
||||
if libpcp_is_static
|
||||
link_with += libpcp
|
||||
else
|
||||
link_with += amlib
|
||||
dependencies += libpcp
|
||||
dependencies += meson.get_compiler('c').find_library('ws2_32')
|
||||
endif
|
||||
|
||||
rc = import('windows').compile_resources('micekeychip.rc', depend_files: micekeychip_ico)
|
||||
executable(
|
||||
|
@ -22,7 +22,8 @@ int mxkInit() {
|
||||
}
|
||||
|
||||
void log_callback(struct pcpa* stream, void* data) {
|
||||
FILE* log_file = fopen("pcp.log", "a");
|
||||
FILE* log_file;
|
||||
fopen_s(&log_file, "pcp.log", "a");
|
||||
if (log_file != NULL) {
|
||||
fprintf(log_file, "%s\n", (char*)data);
|
||||
fclose(log_file);
|
||||
|
@ -2,7 +2,7 @@
|
||||
#include "string.h"
|
||||
|
||||
void print_patches(patches_t* patches, char* filename) {
|
||||
for (int i = 0; i < patches->nopatchsets; i++) {
|
||||
for (size_t i = 0; i < patches->nopatchsets; i++) {
|
||||
patchset_t* patchset = patches->patchsets[i];
|
||||
|
||||
bool skip = patchset->name != NULL && strcmp(patchset->name, filename) != 0;
|
||||
@ -10,8 +10,8 @@ void print_patches(patches_t* patches, char* filename) {
|
||||
printf("Patch: %s (%s)\n", patchset->name, skip ? "skipped" : patchset->apply ? "applied" : "unapplied");
|
||||
printf("- %s\n", patchset->description);
|
||||
if (!skip) {
|
||||
for (int i = 0; i < patchset->nopatches; i++) {
|
||||
printf(":: %d bytes at %08x\n", patchset->patches[i].count, patchset->patches[i].offset);
|
||||
for (size_t j = 0; j < patchset->nopatches; j++) {
|
||||
printf(":: %d bytes at %08x\n", patchset->patches[j].count, patchset->patches[j].offset);
|
||||
}
|
||||
}
|
||||
puts("======================");
|
||||
@ -29,14 +29,14 @@ void apply_patches(patches_t* patches, char* filename) {
|
||||
fseek(fp, 0L, SEEK_END);
|
||||
size_t sz = ftell(fp);
|
||||
|
||||
for (int i = 0; i < patches->nopatchsets; i++) {
|
||||
for (size_t i = 0; i < patches->nopatchsets; i++) {
|
||||
patchset_t* patchset = patches->patchsets[i];
|
||||
|
||||
if (patchset->name != NULL && strcmp(patchset->name, filename) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (int j = 0; j < patchset->nopatches; j++) {
|
||||
for (size_t j = 0; j < patchset->nopatches; j++) {
|
||||
patch_t patch = patchset->patches[j];
|
||||
if (patch.offset + patch.count > sz) {
|
||||
fprintf(stderr, "E: Patch %s[%d] outside file bounds\n", patchset->name, j);
|
||||
@ -45,15 +45,15 @@ void apply_patches(patches_t* patches, char* filename) {
|
||||
fseek(fp, patch.offset, SEEK_SET);
|
||||
bool matches_from = true;
|
||||
bool matches_to = true;
|
||||
for (int i = 0; i < patch.count; i++) {
|
||||
for (size_t k = 0; k < patch.count; k++) {
|
||||
unsigned char seen;
|
||||
if (!fread(&seen, 1, 1, fp)) {
|
||||
matches_from = false;
|
||||
matches_to = false;
|
||||
break;
|
||||
}
|
||||
if (seen != patch.from[i]) matches_from = false;
|
||||
if (seen != patch.to[i]) matches_to = false;
|
||||
if (seen != patch.from[k]) matches_from = false;
|
||||
if (seen != patch.to[k]) matches_to = false;
|
||||
if (!(matches_from || matches_to)) break;
|
||||
}
|
||||
|
||||
|
@ -1,6 +0,0 @@
|
||||
#include "stdio.h"
|
||||
|
||||
int main() {
|
||||
puts("Hello world");
|
||||
return 0;
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
executable(
|
||||
'micetest',
|
||||
win_subsystem: subsystem,
|
||||
sources: [
|
||||
'main.c',
|
||||
],
|
||||
)
|
29
src/micetools/util/meson.build
Normal file
29
src/micetools/util/meson.build
Normal 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',
|
||||
],
|
||||
)
|
271
src/micetools/util/micedump.c
Normal file
271
src/micetools/util/micedump.c
Normal 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;
|
||||
}
|
14
src/micetools/util/micemonitor.c
Normal file
14
src/micetools/util/micemonitor.c
Normal 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;
|
||||
}
|
57
src/micetools/util/micetinker.c
Normal file
57
src/micetools/util/micetinker.c
Normal 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;
|
||||
}
|
9
src/patches/mxgfetcher.patch.json
Normal file
9
src/patches/mxgfetcher.patch.json
Normal file
@ -0,0 +1,9 @@
|
||||
[
|
||||
{
|
||||
"name": "LOG_EN_AMSRAM",
|
||||
"at": "00465e54",
|
||||
"from": "00000000",
|
||||
"to": "01000000",
|
||||
"count": 4
|
||||
}
|
||||
]
|
@ -47,5 +47,12 @@
|
||||
"binary_name": "ORIG_mxsegaboot.exe",
|
||||
"apply": true,
|
||||
"patches_file": "mxsegaboot.patch.json"
|
||||
},
|
||||
{
|
||||
"name": "mxgfetcher logs",
|
||||
"description": "Enable logging facilities",
|
||||
"binary_name": "mxgfetcher.exe",
|
||||
"apply": true,
|
||||
"patches_file": "mxgfetcher.patch.json"
|
||||
}
|
||||
]
|
Loading…
Reference in New Issue
Block a user