refactor all common parts and games

This commit is contained in:
Dniel97
2025-04-17 20:04:17 +02:00
parent a6126bf290
commit 66a53dd2de
496 changed files with 233 additions and 344 deletions
+86
View File
@@ -0,0 +1,86 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stddef.h>
#include "hooklib/config.h"
#include "hooklib/dvd.h"
void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"dvd", L"enable", 1, filename);
}
void touch_screen_config_load(struct touch_screen_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
cfg->enable = GetPrivateProfileIntW(L"touch", L"enable", 1, filename);
cfg->remap = GetPrivateProfileIntW(L"touch", L"remap", 1, filename);
cfg->cursor = GetPrivateProfileIntW(L"touch", L"cursor", 1, filename);
}
void printer_config_load(struct printer_config *cfg, const wchar_t *filename)
{
assert(cfg != NULL);
assert(filename != NULL);
wchar_t tmpstr[16];
cfg->enable = GetPrivateProfileIntW(L"printer", L"enable", 0, filename);
cfg->rotate_180 = GetPrivateProfileIntW(L"printer", L"rotate180", 0, filename);
GetPrivateProfileStringW(
L"printer",
L"serial_no",
L"5A-A123",
tmpstr,
_countof(tmpstr),
filename);
size_t n = wcstombs(cfg->serial_no, tmpstr, sizeof(cfg->serial_no));
for (int i = n; i < sizeof(cfg->serial_no); i++)
{
cfg->serial_no[i] = '\0';
}
GetPrivateProfileStringW(
L"printer",
L"mainFwPath",
L"DEVICE\\printer_main_fw.bin",
cfg->main_fw_path,
_countof(cfg->main_fw_path),
filename);
GetPrivateProfileStringW(
L"printer",
L"dspFwPath",
L"DEVICE\\printer_dsp_fw.bin",
cfg->dsp_fw_path,
_countof(cfg->dsp_fw_path),
filename);
GetPrivateProfileStringW(
L"printer",
L"paramFwPath",
L"DEVICE\\printer_param_fw.bin",
cfg->param_fw_path,
_countof(cfg->param_fw_path),
filename);
GetPrivateProfileStringW(
L"printer",
L"printerOutPath",
L"DEVICE\\print",
cfg->printer_out_path,
_countof(cfg->printer_out_path),
filename);
cfg->wait_time = GetPrivateProfileIntW(L"printer", L"waitTime", 0, filename);
}
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <stddef.h>
#include "hooklib/dvd.h"
#include "hooklib/touch.h"
#include "hooklib/printer.h"
void dvd_config_load(struct dvd_config *cfg, const wchar_t *filename);
void touch_screen_config_load(struct touch_screen_config *cfg, const wchar_t *filename);
void printer_config_load(struct printer_config *cfg, const wchar_t *filename);
+258
View File
@@ -0,0 +1,258 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "hook/table.h"
#include "hooklib/createprocess.h"
#include "util/dprintf.h"
void createprocess_hook_init();
static BOOL WINAPI my_CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
BOOL my_CreateProcessW(
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
static BOOL (WINAPI *next_CreateProcessA)(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
static BOOL (WINAPI *next_CreateProcessW)(
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
);
static const struct hook_symbol win32_hooks[] = {
{
.name = "CreateProcessA",
.patch = my_CreateProcessA,
.link = (void **) &next_CreateProcessA
},
{
.name = "CreateProcessW",
.patch = my_CreateProcessW,
.link = (void **) &next_CreateProcessW
},
};
static bool did_init = false;
static struct process_hook_sym_w *process_syms_w;
static struct process_hook_sym_a *process_syms_a;
static size_t process_nsyms_a = 0;
static size_t process_nsyms_w = 0;
static CRITICAL_SECTION createproc_lock;
HRESULT createprocess_push_hook_w(const wchar_t *name, const wchar_t *head, const wchar_t *tail, bool replace_all) {
struct process_hook_sym_w *new_mem;
struct process_hook_sym_w *new_proc;
HRESULT hr;
assert(name != NULL);
assert(head != NULL);
createprocess_hook_init();
EnterCriticalSection(&createproc_lock);
new_mem = realloc(
process_syms_w,
(process_nsyms_w + 1) * sizeof(struct process_hook_sym_w));
if (new_mem == NULL) {
LeaveCriticalSection(&createproc_lock);
return E_OUTOFMEMORY;
}
new_proc = &new_mem[process_nsyms_w];
memset(new_proc, 0, sizeof(*new_proc));
new_proc->name = name;
new_proc->head = head;
new_proc->tail = tail;
new_proc->replace_all = replace_all;
process_syms_w = new_mem;
process_nsyms_w++;
LeaveCriticalSection(&createproc_lock);
return S_OK;
}
HRESULT createprocess_push_hook_a(const char *name, const char *head, const char *tail, bool replace_all) {
struct process_hook_sym_a *new_mem;
struct process_hook_sym_a *new_proc;
assert(name != NULL);
assert(head != NULL);
createprocess_hook_init();
EnterCriticalSection(&createproc_lock);
new_mem = realloc(
process_syms_a,
(process_nsyms_a + 1) * sizeof(struct process_hook_sym_a));
if (new_mem == NULL) {
LeaveCriticalSection(&createproc_lock);
return E_OUTOFMEMORY;
}
new_proc = &new_mem[process_nsyms_a];
memset(new_proc, 0, sizeof(*new_proc));
new_proc->name = name;
new_proc->head = head;
new_proc->tail = tail;
new_proc->replace_all = replace_all;
process_syms_a = new_mem;
process_nsyms_a++;
LeaveCriticalSection(&createproc_lock);
return S_OK;
}
void createprocess_hook_init() {
if (did_init) {
return;
}
did_init = true;
hook_table_apply(
NULL,
"kernel32.dll",
win32_hooks,
_countof(win32_hooks));
InitializeCriticalSection(&createproc_lock);
dprintf("CreateProcess: Init\n");
}
static BOOL WINAPI my_CreateProcessA(
LPCSTR lpApplicationName,
LPSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCSTR lpCurrentDirectory,
LPSTARTUPINFOA lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation
)
{
for (int i = 0; i < process_nsyms_a; i++) {
if (strncmp(process_syms_a[i].name, lpCommandLine, strlen(process_syms_a[i].name))) {
continue;
}
dprintf("CreateProcess: Hooking child process %s %s\n", lpApplicationName, lpCommandLine);
char new_cmd[MAX_PATH] = {0};
strcat_s(new_cmd, MAX_PATH, process_syms_a[i].head);
if (!process_syms_a[i].replace_all) {
strcat_s(new_cmd, MAX_PATH, lpCommandLine);
}
if (process_syms_a[i].tail != NULL) {
strcat_s(new_cmd, MAX_PATH, process_syms_a[i].tail);
}
dprintf("CreateProcess: Replaced CreateProcessA %s\n", new_cmd);
return next_CreateProcessA(
lpApplicationName,
new_cmd,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation
);
}
return next_CreateProcessA(
lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation
);
}
BOOL my_CreateProcessW(
LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation)
{
return next_CreateProcessW(
lpApplicationName,
lpCommandLine,
lpProcessAttributes,
lpThreadAttributes,
bInheritHandles,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation
);
}
+21
View File
@@ -0,0 +1,21 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
HRESULT createprocess_push_hook_w(const wchar_t *name, const wchar_t *head, const wchar_t *tail, bool replace_all);
HRESULT createprocess_push_hook_a(const char *name, const char *head, const char *tail, bool replace_all);
struct process_hook_sym_w {
const wchar_t *name;
const wchar_t *head;
const wchar_t *tail;
bool replace_all;
};
struct process_hook_sym_a {
const char *name;
const char *head;
const char *tail;
bool replace_all;
};
+80
View File
@@ -0,0 +1,80 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "hook/table.h"
#include "util/dprintf.h"
static HCURSOR my_SetCursor(HCURSOR hCursor);
static HCURSOR (*next_SetCursor)(HCURSOR hCursor);
static BOOL my_SetCursorPos(int x, int y);
static BOOL my_SetPhysicalCursorPos(int x, int y);
static int my_ShowCursor(BOOL bShow);
static int cursor_track = -1; // If no mouse is connected, this starts as -1
static const struct hook_symbol cursor_syms[] = {
{
.name = "SetCursor",
.patch = my_SetCursor,
.link = (void **) &next_SetCursor
},/*{
.name = "SetCursorPos",
.patch = my_SetCursorPos,
},*/ {
.name = "SetPhysicalCursorPos",
.patch = my_SetPhysicalCursorPos
}, /*{
.name = "ShowCursor",
.patch = my_ShowCursor
}*/
};
void cursor_hook_init()
{
hook_table_apply(
NULL,
"user32.dll",
cursor_syms,
_countof(cursor_syms));
dprintf("Cursor: Init\n");
}
static BOOL my_SetCursorPos(int x, int y)
{
// dprintf("my_SetCursorPos Hit! x %d y %d\n", x, y);
return true;
}
static BOOL my_SetPhysicalCursorPos(int x, int y)
{
dprintf("my_SetPhysicalCursorPos Hit! x %d y %d\n", x, y);
return true;
}
static int my_ShowCursor(BOOL bShow)
{
dprintf("my_ShowCursor Hit!\n");
if (bShow) {
cursor_track++;
} else {
cursor_track--;
}
return cursor_track;
}
static HCURSOR my_SetCursor(HCURSOR hCursor)
{
dprintf("my_SetCursor Hit!\n");
HCURSOR fake_cursor;
if ( hCursor )
return next_SetCursor(hCursor);
fake_cursor = LoadCursorA(0, (LPCSTR)0x7F00);
next_SetCursor(fake_cursor);
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
void cursor_hook_init();
+351
View File
@@ -0,0 +1,351 @@
/* This is general enough to break out into capnhook eventually.
Don't introduce util/ dependencies here. */
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include "hook/table.h"
#include "hooklib/dll.h"
struct dll_hook_reg {
const wchar_t *name;
HMODULE redir_mod;
};
/* Helper functions */
static void dll_hook_init(void);
static HMODULE dll_hook_search_dll(const wchar_t *name);
/* Hook functions */
static BOOL WINAPI hook_FreeLibrary(HMODULE mod);
static HMODULE WINAPI hook_GetModuleHandleA(const char *name);
static HMODULE WINAPI hook_GetModuleHandleW(const wchar_t *name);
static HMODULE WINAPI hook_LoadLibraryA(const char *name);
static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name);
static HMODULE WINAPI hook_LoadLibraryExA(const char *name, HANDLE file, DWORD flags);
static HMODULE WINAPI hook_LoadLibraryExW(const wchar_t *name, HANDLE file, DWORD flags);
/* Link pointers */
static BOOL (WINAPI *next_FreeLibrary)(HMODULE mod);
static HMODULE (WINAPI *next_GetModuleHandleA)(const char *name);
static HMODULE (WINAPI *next_GetModuleHandleW)(const wchar_t *name);
static HMODULE (WINAPI *next_LoadLibraryA)(const char *name);
static HMODULE (WINAPI *next_LoadLibraryW)(const wchar_t *name);
static HMODULE (WINAPI *next_LoadLibraryExA)(const char *name, HANDLE file, DWORD flags);
static HMODULE (WINAPI *next_LoadLibraryExW)(const wchar_t *name, HANDLE file, DWORD flags);
static const struct hook_symbol dll_loader_syms[] = {
{
.name = "FreeLibrary",
.patch = hook_FreeLibrary,
.link = (void **) &next_FreeLibrary,
}, {
.name = "GetModuleHandleA",
.patch = hook_GetModuleHandleA,
.link = (void **) &next_GetModuleHandleA,
}, {
.name = "GetModuleHandleW",
.patch = hook_GetModuleHandleW,
.link = (void **) &next_GetModuleHandleW,
}, {
.name = "LoadLibraryA",
.patch = hook_LoadLibraryA,
.link = (void **) &next_LoadLibraryA,
}, {
.name = "LoadLibraryW",
.patch = hook_LoadLibraryW,
.link = (void **) &next_LoadLibraryW,
}, {
.name = "LoadLibraryExA",
.patch = hook_LoadLibraryExA,
.link = (void **) &next_LoadLibraryExA,
}, {
.name = "LoadLibraryExW",
.patch = hook_LoadLibraryExW,
.link = (void **) &next_LoadLibraryExW,
}
};
static bool dll_hook_initted;
static CRITICAL_SECTION dll_hook_lock;
static struct dll_hook_reg *dll_hook_list;
static size_t dll_hook_count;
HRESULT dll_hook_push(
HMODULE redir_mod,
const wchar_t *name)
{
struct dll_hook_reg *new_item;
struct dll_hook_reg *new_mem;
HRESULT hr;
assert(name != NULL);
dll_hook_init();
EnterCriticalSection(&dll_hook_lock);
new_mem = realloc(
dll_hook_list,
(dll_hook_count + 1) * sizeof(struct dll_hook_reg));
if (new_mem == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
new_item = &new_mem[dll_hook_count];
new_item->name = name;
new_item->redir_mod = redir_mod;
dll_hook_list = new_mem;
dll_hook_count++;
hr = S_OK;
end:
LeaveCriticalSection(&dll_hook_lock);
return hr;
}
static void dll_hook_init(void)
{
HMODULE kernel32;
/* Init is not thread safe, because API hooking is not thread safe. */
if (dll_hook_initted) {
return;
}
dll_hook_initted = true;
InitializeCriticalSection(&dll_hook_lock);
/* Protect against the (probably impossible) scenario where nothing in the
process imports LoadLibraryW but something imports LoadLibraryA. Also
do the same with LoadLibraryExW.
We know something imports GetModuleHandleW because we do, right here.
(we're about to hook these APIs of course, so we have to set this up
before the hooks go in) */
kernel32 = GetModuleHandleW(L"kernel32.dll");
next_LoadLibraryW = (void *) GetProcAddress(kernel32, "LoadLibraryW");
next_LoadLibraryExW = (void *) GetProcAddress(kernel32, "LoadLibraryExW");
/* Now we can apply the hook table */
hook_table_apply(
NULL,
"kernel32.dll",
dll_loader_syms,
_countof(dll_loader_syms));
}
static HMODULE dll_hook_search_dll(const wchar_t *name)
{
HMODULE result;
size_t i;
result = NULL;
EnterCriticalSection(&dll_hook_lock);
for (i = 0 ; i < dll_hook_count ; i++) {
if (wcsicmp(name, dll_hook_list[i].name) == 0) {
result = dll_hook_list[i].redir_mod;
break;
}
}
LeaveCriticalSection(&dll_hook_lock);
return result;
}
static BOOL WINAPI hook_FreeLibrary(HMODULE mod)
{
bool match;
size_t i;
match = false;
EnterCriticalSection(&dll_hook_lock);
for (i = 0 ; i < dll_hook_count ; i++) {
if (mod == dll_hook_list[i].redir_mod) {
match = true;
break;
}
}
LeaveCriticalSection(&dll_hook_lock);
if (match) {
/* Block attempts to unload redirected modules, since this could cause
a hook DLL to unexpectedly vanish and crash the whole application.
Reference counting might be another solution, although it is
possible that a buggy application might cause a hook DLL unload in
that case. */
SetLastError(ERROR_SUCCESS);
return TRUE;
}
return next_FreeLibrary(mod);
}
static HMODULE WINAPI hook_GetModuleHandleA(const char *name)
{
HMODULE result;
wchar_t *name_w;
size_t name_c;
if (name == NULL) {
return next_GetModuleHandleA(NULL);
}
mbstowcs_s(&name_c, NULL, 0, name, 0);
name_w = malloc(name_c * sizeof(wchar_t));
if (name_w == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
mbstowcs_s(NULL, name_w, name_c, name, name_c - 1);
result = hook_GetModuleHandleW(name_w);
free(name_w);
return result;
}
static HMODULE WINAPI hook_GetModuleHandleW(const wchar_t *name)
{
HMODULE result;
if (name == NULL) {
return next_GetModuleHandleW(NULL);
}
result = dll_hook_search_dll(name);
if (result != NULL) {
SetLastError(ERROR_SUCCESS);
} else {
result = next_GetModuleHandleW(name);
}
return result;
}
static HMODULE WINAPI hook_LoadLibraryA(const char *name)
{
HMODULE result;
wchar_t *name_w;
size_t name_c;
if (name == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
mbstowcs_s(&name_c, NULL, 0, name, 0);
name_w = malloc(name_c * sizeof(wchar_t));
if (name_w == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
mbstowcs_s(NULL, name_w, name_c, name, name_c - 1);
result = hook_LoadLibraryW(name_w);
free(name_w);
return result;
}
static HMODULE WINAPI hook_LoadLibraryW(const wchar_t *name)
{
HMODULE result;
if (name == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
result = dll_hook_search_dll(name);
if (result != NULL) {
SetLastError(ERROR_SUCCESS);
} else {
result = next_LoadLibraryW(name);
}
return result;
}
static HMODULE WINAPI hook_LoadLibraryExA(const char *name, HANDLE file, DWORD flags)
{
HMODULE result;
wchar_t *name_w;
size_t name_c;
if (name == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
mbstowcs_s(&name_c, NULL, 0, name, 0);
name_w = malloc(name_c * sizeof(wchar_t));
if (name_w == NULL) {
SetLastError(ERROR_OUTOFMEMORY);
return NULL;
}
mbstowcs_s(NULL, name_w, name_c, name, name_c - 1);
result = hook_LoadLibraryExW(name_w, file, flags);
free(name_w);
return result;
}
static HMODULE WINAPI hook_LoadLibraryExW(const wchar_t *name, HANDLE file, DWORD flags)
{
HMODULE result;
if (name == NULL) {
SetLastError(ERROR_INVALID_PARAMETER);
return NULL;
}
result = dll_hook_search_dll(name);
if (result != NULL) {
SetLastError(ERROR_SUCCESS);
} else {
result = next_LoadLibraryExW(name, file, flags);
}
return result;
}
+10
View File
@@ -0,0 +1,10 @@
#pragma once
#include <windows.h>
#include <stddef.h>
#include <stdint.h>
HRESULT dll_hook_push(
HMODULE redir_mod,
const wchar_t *name);
+783
View File
@@ -0,0 +1,783 @@
/* Might push this to capnhook, don't add any util dependencies. */
#include <windows.h>
#include <windns.h>
#include <ws2tcpip.h>
#include <winhttp.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "hook/hr.h"
#include "hook/table.h"
#include "util/dprintf.h"
#include "util/get_function_ordinal.h"
#include "hooklib/dns.h"
/* Latest w32headers does not include DnsQueryEx, so we'll have to "polyfill"
its associated data types here for the time being.
Results and cancel handle are passed through, so we'll just use void
pointers for those args. So are most of the fields in this structure, for
that matter. */
typedef struct POLYFILL_DNS_QUERY_REQUEST {
ULONG Version;
PCWSTR QueryName;
WORD QueryType;
ULONG64 QueryOptions;
void* pDnsServerList;
ULONG InterfaceIndex;
void* pQueryCompletionCallback;
PVOID pQueryContext;
} POLYFILL_DNS_QUERY_REQUEST;
struct dns_hook_entry {
wchar_t *from;
wchar_t *to;
};
/* Hook funcs */
static DNS_STATUS WINAPI hook_DnsQuery_A(
const char *pszName,
WORD wType,
DWORD Options,
void *pExtra,
DNS_RECORD **ppQueryResults,
void *pReserved);
static DNS_STATUS WINAPI hook_DnsQuery_W(
const wchar_t *pszName,
WORD wType,
DWORD Options,
void *pExtra,
DNS_RECORD **ppQueryResults,
void *pReserved);
static DNS_STATUS WINAPI hook_DnsQueryEx(
POLYFILL_DNS_QUERY_REQUEST *pRequest,
void *pQueryResults,
void *pCancelHandle);
static int WSAAPI hook_getaddrinfo(
const char *pNodeName,
const char *pServiceName,
const ADDRINFOA *pHints,
ADDRINFOA **ppResult);
static HINTERNET WINAPI hook_WinHttpConnect(
HINTERNET hSession,
const wchar_t *pwszServerName,
INTERNET_PORT nServerPort,
DWORD dwReserved);
static bool WINAPI hook_WinHttpCrackUrl(
const wchar_t *pwszUrl,
DWORD dwUrlLength,
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents);
static DWORD WINAPI hook_send(
SOCKET s,
const char* buf,
int len,
int flags);
static int WINAPI hook_connect(
SOCKET s,
const struct sockaddr *name,
int namelen);
/* Link pointers */
static DNS_STATUS (WINAPI *next_DnsQuery_A)(
const char *pszName,
WORD wType,
DWORD Options,
void *pExtra,
DNS_RECORD **ppQueryResults,
void *pReserved);
static DNS_STATUS (WINAPI *next_DnsQuery_W)(
const wchar_t *pszName,
WORD wType,
DWORD Options,
void *pExtra,
DNS_RECORD **ppQueryResults,
void *pReserved);
static DNS_STATUS (WINAPI *next_DnsQueryEx)(
POLYFILL_DNS_QUERY_REQUEST *pRequest,
void *pQueryResults,
void *pCancelHandle);
static int (WSAAPI *next_getaddrinfo)(
const char *pNodeName,
const char *pServiceName,
const ADDRINFOA *pHints,
ADDRINFOA **ppResult);
static HINTERNET (WINAPI *next_WinHttpConnect)(
HINTERNET hSession,
const wchar_t *pwszServerName,
INTERNET_PORT nServerPort,
DWORD dwReserved);
static bool (WINAPI *next_WinHttpCrackUrl)(
const wchar_t *pwszUrl,
DWORD dwUrlLength,
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents);
static DWORD (WINAPI *next_send)(
SOCKET s,
const char* buf,
int len,
int flags);
static int (__stdcall *next_connect)(
SOCKET s,
const struct sockaddr *name,
int namelen);
static const struct hook_symbol dns_hook_syms_dnsapi[] = {
{
.name = "DnsQuery_A",
.patch = hook_DnsQuery_A,
.link = (void **) &next_DnsQuery_A,
}, {
.name = "DnsQuery_W",
.patch = hook_DnsQuery_W,
.link = (void **) &next_DnsQuery_W,
}, {
.name = "DnsQueryEx",
.patch = hook_DnsQueryEx,
.link = (void **) &next_DnsQueryEx,
}
};
static const struct hook_symbol dns_hook_syms_ws2[] = {
{
.name = "getaddrinfo",
.ordinal = 176,
.patch = hook_getaddrinfo,
.link = (void **) &next_getaddrinfo,
},
};
static const struct hook_symbol dns_hook_syms_winhttp[] = {
{
.name = "WinHttpConnect",
.patch = hook_WinHttpConnect,
.link = (void **) &next_WinHttpConnect,
}, {
.name = "WinHttpCrackUrl",
.patch = hook_WinHttpCrackUrl,
.link = (void **) &next_WinHttpCrackUrl,
}
};
static struct hook_symbol http_hook_syms_ws2[] = {
{
.name = "send",
.patch = hook_send,
.link = (void **) &next_send
},
};
static struct hook_symbol port_hook_syms_ws2[] = {
{
.name = "connect",
.patch = hook_connect,
.link = (void **) &next_connect
},
};
static bool dns_hook_initted;
static CRITICAL_SECTION dns_hook_lock;
static struct dns_hook_entry *dns_hook_entries;
static size_t dns_hook_nentries;
static char received_title_url[255];
static unsigned short startup_port;
static unsigned short billing_port;
static unsigned short aimedb_port;
static void dns_hook_init(void)
{
if (dns_hook_initted) {
return;
}
dns_hook_initted = true;
InitializeCriticalSection(&dns_hook_lock);
dns_hook_apply_hooks(NULL);
}
void dns_hook_apply_hooks(HMODULE mod){
hook_table_apply(
mod,
"dnsapi.dll",
dns_hook_syms_dnsapi,
_countof(dns_hook_syms_dnsapi));
hook_table_apply(
mod,
"ws2_32.dll",
dns_hook_syms_ws2,
_countof(dns_hook_syms_ws2));
hook_table_apply(
mod,
"winhttp.dll",
dns_hook_syms_winhttp,
_countof(dns_hook_syms_winhttp));
}
void http_hook_init(){
for (size_t i = 0; i < _countof(http_hook_syms_ws2); ++i) {
http_hook_syms_ws2[i].ordinal = get_function_ordinal("ws2_32.dll", http_hook_syms_ws2[i].name);
}
hook_table_apply(
NULL,
"ws2_32.dll",
http_hook_syms_ws2,
_countof(http_hook_syms_ws2));
}
void port_hook_init(unsigned short _startup_port, unsigned short _billing_port, unsigned short _aimedb_port){
startup_port = _startup_port;
billing_port = _billing_port;
aimedb_port = _aimedb_port;
for (size_t i = 0; i < _countof(port_hook_syms_ws2); ++i) {
port_hook_syms_ws2[i].ordinal = get_function_ordinal("ws2_32.dll", port_hook_syms_ws2[i].name);
}
hook_table_apply(
NULL,
"ws2_32.dll",
port_hook_syms_ws2,
_countof(port_hook_syms_ws2));
}
// This function match domain and subdomains like *.naominet.jp.
bool match_domain(const wchar_t* target, const wchar_t* pattern) {
if (_wcsicmp(pattern, target) == 0) {
return true;
}
int pattern_ptr_index = 0;
int target_ptr_index = 0;
while (pattern[pattern_ptr_index] != '\0' && target[target_ptr_index] != '\0') {
if (pattern[pattern_ptr_index] == '*') {
pattern_ptr_index++; // Check next character for wildcard match.
while (pattern[pattern_ptr_index] != target[target_ptr_index]) {
target_ptr_index++;
if (target[target_ptr_index] == '\0') return false;
}
}
else if (pattern[pattern_ptr_index] != target[target_ptr_index]) {
return false;
}
else {
pattern_ptr_index++;
target_ptr_index++;
}
}
return pattern[pattern_ptr_index] == '\0' && target[target_ptr_index] == '\0';
}
HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src)
{
HRESULT hr;
struct dns_hook_entry *newmem;
struct dns_hook_entry *newitem;
wchar_t *from;
wchar_t *to;
assert(from_src != NULL);
to = NULL;
from = NULL;
dns_hook_init();
EnterCriticalSection(&dns_hook_lock);
from = _wcsdup(from_src);
if (from == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
if (to_src != NULL) {
to = _wcsdup(to_src);
if (to == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
}
newmem = realloc(
dns_hook_entries,
(dns_hook_nentries + 1) * sizeof(struct dns_hook_entry));
if (newmem == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
dns_hook_entries = newmem;
newitem = &newmem[dns_hook_nentries++];
newitem->from = from;
newitem->to = to;
from = NULL;
to = NULL;
hr = S_OK;
end:
LeaveCriticalSection(&dns_hook_lock);
free(to);
free(from);
return hr;
}
static DNS_STATUS WINAPI hook_DnsQuery_A(
const char *pszName,
WORD wType,
DWORD Options,
void *pExtra,
DNS_RECORD **ppQueryResults,
void *pReserved)
{
const struct dns_hook_entry *pos;
size_t i;
size_t wstr_c;
wchar_t *wstr;
size_t str_c;
char *str;
DNS_STATUS code;
HRESULT hr;
wstr = NULL;
str = NULL;
if (pszName == NULL) {
hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
goto end;
}
mbstowcs_s(&wstr_c, NULL, 0, pszName, 0);
wstr = malloc(wstr_c * sizeof(wchar_t));
if (wstr == NULL) {
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto end;
}
mbstowcs_s(NULL, wstr, wstr_c, pszName, wstr_c - 1);
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(wstr, pos->from)) {
if (pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock);
hr = HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR);
goto end;
}
wcstombs_s(&str_c, NULL, 0, pos->to, 0);
str = malloc(str_c * sizeof(char));
if (str == NULL) {
LeaveCriticalSection(&dns_hook_lock);
hr = HRESULT_FROM_WIN32(ERROR_OUTOFMEMORY);
goto end;
}
wcstombs_s(NULL, str, str_c, pos->to, str_c - 1);
pszName = str;
break;
}
}
LeaveCriticalSection(&dns_hook_lock);
code = next_DnsQuery_A(
pszName,
wType,
Options,
pExtra,
ppQueryResults,
pReserved);
hr = HRESULT_FROM_WIN32(code);
end:
free(str);
free(wstr);
return hr_to_win32_error(hr);
}
static DNS_STATUS WINAPI hook_DnsQuery_W(
const wchar_t *pszName,
WORD wType,
DWORD Options,
void *pExtra,
DNS_RECORD **ppQueryResults,
void *pReserved)
{
const struct dns_hook_entry *pos;
size_t i;
if (pszName == NULL) {
return ERROR_INVALID_PARAMETER;
}
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(pszName, pos->from)) {
if (pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock);
return HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR);
}
pszName = pos->to;
break;
}
}
LeaveCriticalSection(&dns_hook_lock);
return next_DnsQuery_W(
pszName,
wType,
Options,
pExtra,
ppQueryResults,
pReserved);
}
static DNS_STATUS WINAPI hook_DnsQueryEx(
POLYFILL_DNS_QUERY_REQUEST *pRequest,
void *pQueryResults,
void *pCancelHandle)
{
const wchar_t *orig;
const struct dns_hook_entry *pos;
DNS_STATUS code;
size_t i;
if (pRequest == NULL) {
return ERROR_INVALID_PARAMETER;
}
orig = pRequest->QueryName;
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(pRequest->QueryName, pos->from)) {
if (pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock);
return HRESULT_FROM_WIN32(DNS_ERROR_RCODE_NAME_ERROR);
}
pRequest->QueryName = pos->to;
break;
}
}
LeaveCriticalSection(&dns_hook_lock);
code = next_DnsQueryEx(pRequest, pQueryResults, pCancelHandle);
/* Caller might not appreciate QueryName changing under its feet. It is
strongly implied by MSDN that a copy of *pRequest is taken by WINAPI,
so we can change it back after the call has been issued with no ill
effect... we hope.
Hopefully the completion callback is issued from an APC or something
(or otherwise happens after this returns) or we're in trouble. */
pRequest->QueryName = orig;
return code;
}
static int WSAAPI hook_getaddrinfo(
const char *pNodeName,
const char *pServiceName,
const ADDRINFOA *pHints,
ADDRINFOA **ppResult)
{
const struct dns_hook_entry *pos;
char *str;
size_t str_c;
wchar_t *wstr;
size_t wstr_c;
int result;
size_t i;
str = NULL;
wstr = NULL;
if (pNodeName == NULL) {
result = WSA_INVALID_PARAMETER;
goto end;
}
mbstowcs_s(&wstr_c, NULL, 0, pNodeName, 0);
wstr = malloc(wstr_c * sizeof(wchar_t));
if (wstr == NULL) {
result = WSA_NOT_ENOUGH_MEMORY;
goto end;
}
mbstowcs_s(NULL, wstr, wstr_c, pNodeName, wstr_c - 1);
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(wstr, pos->from)) {
if (pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock);
result = EAI_NONAME;
goto end;
}
wcstombs_s(&str_c, NULL, 0, pos->to, 0);
str = malloc(str_c * sizeof(char));
if (str == NULL) {
LeaveCriticalSection(&dns_hook_lock);
result = WSA_NOT_ENOUGH_MEMORY;
goto end;
}
wcstombs_s(NULL, str, str_c, pos->to, str_c - 1);
pNodeName = str;
break;
}
}
LeaveCriticalSection(&dns_hook_lock);
result = next_getaddrinfo(pNodeName, pServiceName, pHints, ppResult);
end:
free(wstr);
free(str);
return result;
}
static HINTERNET WINAPI hook_WinHttpConnect(
HINTERNET hSession,
const wchar_t *pwszServerName,
INTERNET_PORT nServerPort,
DWORD dwReserved)
{
const struct dns_hook_entry *pos;
size_t i;
if (pwszServerName == NULL) {
return NULL;
}
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(pwszServerName, pos->from)) {
if (pos->to == NULL) {
LeaveCriticalSection(&dns_hook_lock);
return NULL;
}
pwszServerName = pos->to;
break;
}
}
LeaveCriticalSection(&dns_hook_lock);
return next_WinHttpConnect(hSession, pwszServerName, nServerPort, dwReserved);
}
// Hook to replace CXB title url
static bool WINAPI hook_WinHttpCrackUrl(
const wchar_t *pwszUrl,
DWORD dwUrlLength,
DWORD dwFlags,
LPURL_COMPONENTS lpUrlComponents)
{
const struct dns_hook_entry *pos;
size_t i;
EnterCriticalSection(&dns_hook_lock);
for (i = 0 ; i < dns_hook_nentries ; i++) {
pos = &dns_hook_entries[i];
if (match_domain(pwszUrl, pos->from)) {
wchar_t* toAddr = pos->to;
wchar_t titleBuffer[255];
if (wcscmp(toAddr, L"title") == 0) {
size_t wstr_c;
mbstowcs_s(&wstr_c, titleBuffer, 255, received_title_url, strlen(received_title_url));
toAddr = titleBuffer;
}
bool result = next_WinHttpCrackUrl(
toAddr,
wcslen(toAddr),
dwFlags,
lpUrlComponents
);
LeaveCriticalSection(&dns_hook_lock);
return result;
}
}
LeaveCriticalSection(&dns_hook_lock);
return next_WinHttpCrackUrl(
pwszUrl,
dwUrlLength,
dwFlags,
lpUrlComponents
);
}
int WINAPI hook_connect(SOCKET s, const struct sockaddr *name, int namelen) {
const struct sockaddr_in *n;
struct sockaddr_in new_name;
unsigned ip;
unsigned short port, new_port;
EnterCriticalSection(&dns_hook_lock);
n = (const struct sockaddr_in *)name;
ip = n->sin_addr.S_un.S_addr;
if (WSANtohs(s, n->sin_port, &port)) return SOCKET_ERROR;
if (port == 80 && startup_port) {
new_port = startup_port;
} else if (port == 8443 && billing_port) {
new_port = billing_port;
} else if (port == 22345 && aimedb_port) {
new_port = aimedb_port;
} else { // No match
dprintf("TCP Connect: %u.%u.%u.%u:%hu\n", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff, port);
LeaveCriticalSection(&dns_hook_lock);
return next_connect(
s,
name,
namelen
);
}
// matched
new_name = *n;
if (WSAHtons(s, new_port, &new_name.sin_port)) return SOCKET_ERROR;
dprintf("TCP Connect: %u.%u.%u.%u:%hu, mapped to port %hu\n", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff, (ip >> 24) & 0xff, port, new_port);
LeaveCriticalSection(&dns_hook_lock);
return next_connect(
s,
(const struct sockaddr *)&new_name,
sizeof(new_name)
);
}
DWORD WINAPI hook_send(SOCKET s, const char* buf, int len, int flags) {
if (strstr(buf, "HTTP/") != NULL) {
char *new_buf = malloc(len + 1);
if (new_buf == NULL) return SOCKET_ERROR;
memcpy(new_buf, buf, len);
new_buf[len] = '\0';
char *host_start = strstr(new_buf, "Host: ");
if (host_start != NULL) {
char *host_end = strstr(host_start, "\r\n");
if (host_end != NULL) {
host_end += 2;
int host_len = host_end - host_start;
char *host_value_start = host_start + 6;
char *host_value_end = strstr(host_value_start, "\r\n");
if (host_value_end != NULL) {
int value_len = host_value_end - host_value_start;
char* host_value = (char*)malloc(value_len + 1);
strncpy(host_value, host_value_start, value_len);
host_value[value_len] = '\0';
for (struct dns_hook_entry *entry = dns_hook_entries; entry && entry->from; entry++) {
char from_value[256];
wcstombs(from_value, entry->from, sizeof(from_value));
if (strcmp(host_value, from_value) == 0) {
char to_value[256];
wcstombs(to_value, entry->to, sizeof(to_value));
snprintf(host_start, len - (host_start - new_buf), "Host: %s\r\n", to_value);
break;
}
}
free(host_value);
}
len = (int)strlen(new_buf);
}
}
DWORD result = next_send(s, new_buf, len, flags);
free(new_buf);
return result;
}
return next_send(s, buf, len, flags);
}
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include <windows.h>
#include <stddef.h>
void http_hook_init();
void port_hook_init(unsigned short _startup_port, unsigned short _billing_port, unsigned short _aimedb_port);
// if to_src is NULL, all lookups for from_src will fail
HRESULT dns_hook_push(const wchar_t *from_src, const wchar_t *to_src);
void dns_hook_apply_hooks(HMODULE mod);
+82
View File
@@ -0,0 +1,82 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "hooklib/config.h"
#include "hooklib/dll.h"
#include "hooklib/dvd.h"
#include "util/dprintf.h"
/* API hooks */
static DWORD WINAPI hook_QueryDosDeviceW(
const wchar_t *lpDeviceName,
wchar_t *lpTargetPath,
DWORD ucchMax);
/* Link pointers */
static DWORD (WINAPI *next_QueryDosDeviceW)(
const wchar_t *lpDeviceName,
wchar_t *lpTargetPath,
DWORD ucchMax);
static bool dvd_hook_initted;
static struct dvd_config dvd_config;
static const struct hook_symbol dvd_hooks[] = {
{
.name = "QueryDosDeviceW",
.patch = hook_QueryDosDeviceW,
.link = (void **) &next_QueryDosDeviceW
},
};
void dvd_hook_init(const struct dvd_config *cfg, HINSTANCE self)
{
assert(cfg != NULL);
if (!cfg->enable) {
return;
}
if (dvd_hook_initted) {
return;
}
dvd_hook_initted = true;
memcpy(&dvd_config, cfg, sizeof(*cfg));
hook_table_apply(NULL, "kernel32.dll", dvd_hooks, _countof(dvd_hooks));
dprintf("DVD: hook enabled.\n");
}
DWORD WINAPI hook_QueryDosDeviceW(
const wchar_t *lpDeviceName,
wchar_t *lpTargetPath,
DWORD ucchMax)
{
DWORD ok;
wchar_t *p_dest;
wchar_t *dvd_string = L"CdRom";
ok = next_QueryDosDeviceW(
lpDeviceName,
lpTargetPath,
ucchMax);
p_dest = wcsstr (lpTargetPath, dvd_string);
if ( p_dest != NULL ) {
dprintf("DVD: Hiding DVD drive.\n");
return 0;
}
return ok;
}
+14
View File
@@ -0,0 +1,14 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
struct dvd_config {
bool enable;
};
/* Init is not thread safe because API hook init is not thread safe blah
blah blah you know the drill by now. */
void dvd_hook_init(const struct dvd_config *cfg, HINSTANCE self);
+218
View File
@@ -0,0 +1,218 @@
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
#include "hook/iobuf.h"
#include "hook/iohook.h"
#include "hooklib/fdshark.h"
#include "util/dprintf.h"
#include "util/dump.h"
static const wchar_t *fdshark_path;
static HANDLE fdshark_target_fd;
static int fdshark_flags;
static HRESULT fdshark_handle_irp(struct irp *irp);
static HRESULT fdshark_handle_open(struct irp *irp);
static HRESULT fdshark_handle_close(struct irp *irp);
static HRESULT fdshark_handle_read(struct irp *irp);
static HRESULT fdshark_handle_write(struct irp *irp);
static HRESULT fdshark_handle_ioctl(struct irp *irp);
static bool fdshark_force_sync(struct irp *irp, HRESULT hr);
HRESULT fdshark_hook_init(const wchar_t *path, int flags)
{
assert(path != NULL);
assert(!(flags & ~FDSHARK_ALL_FLAGS_));
fdshark_path = path;
fdshark_flags = flags;
return iohook_push_handler(fdshark_handle_irp);
}
static HRESULT fdshark_handle_irp(struct irp *irp)
{
assert(irp != NULL);
if (irp->op != IRP_OP_OPEN && irp->fd != fdshark_target_fd) {
return iohook_invoke_next(irp);
}
switch (irp->op) {
case IRP_OP_OPEN: return fdshark_handle_open(irp);
case IRP_OP_CLOSE: return fdshark_handle_close(irp);
case IRP_OP_READ: return fdshark_handle_read(irp);
case IRP_OP_WRITE: return fdshark_handle_write(irp);
case IRP_OP_IOCTL: return fdshark_handle_ioctl(irp);
default: return iohook_invoke_next(irp);
}
}
static HRESULT fdshark_handle_open(struct irp *irp)
{
HRESULT hr;
if (_wcsicmp(irp->open_filename, fdshark_path) != 0) {
return iohook_invoke_next(irp);
}
hr = iohook_invoke_next(irp);
if (FAILED(hr)) {
return hr;
}
dprintf("FdShark: Opened %S\n", fdshark_path);
fdshark_target_fd = irp->fd;
return hr;
}
static HRESULT fdshark_handle_close(struct irp *irp)
{
dprintf("FdShark: Closed %S\n", fdshark_path);
fdshark_target_fd = NULL;
return iohook_invoke_next(irp);
}
static HRESULT fdshark_handle_read(struct irp *irp)
{
HRESULT hr;
if (!(fdshark_flags & FDSHARK_TRACE_READ)) {
return iohook_invoke_next(irp);
}
dprintf("FdShark: Read %p:%i/%i\n",
irp->read.bytes,
(int) irp->read.pos,
(int) irp->read.nbytes);
hr = iohook_invoke_next(irp);
if (FAILED(hr) && !fdshark_force_sync(irp, hr)) {
dprintf("FdShark: FAILED: %x\n", (int) hr);
} else {
dprintf("FdShark: Read %p:%i/%i OK\n",
irp->read.bytes,
(int) irp->read.pos,
(int) irp->read.nbytes);
dump_iobuf(&irp->read);
}
return S_OK;
}
static HRESULT fdshark_handle_write(struct irp *irp)
{
HRESULT hr;
if (!(fdshark_flags & FDSHARK_TRACE_WRITE)) {
return iohook_invoke_next(irp);
}
dprintf("FdShark: Write %p:%i/%i\n",
irp->write.bytes,
(int) irp->write.pos,
(int) irp->write.nbytes);
dump_const_iobuf(&irp->write);
hr = iohook_invoke_next(irp);
if (FAILED(hr) && !fdshark_force_sync(irp, hr)) {
dprintf("FdShark: FAILED: %x\n", (int) hr);
} else {
dprintf("FdShark: Write %p:%i/%i OK\n",
irp->write.bytes,
(int) irp->write.pos,
(int) irp->write.nbytes);
}
return S_OK;
}
static HRESULT fdshark_handle_ioctl(struct irp *irp)
{
HRESULT hr;
if (!(fdshark_flags & FDSHARK_TRACE_IOCTL)) {
return iohook_invoke_next(irp);
}
dprintf("FdShark: Ioctl %08x w:%p:%i/%i r:%p:%i/%i\n",
irp->ioctl,
irp->write.bytes,
(int) irp->write.pos,
(int) irp->write.nbytes,
irp->read.bytes,
(int) irp->read.pos,
(int) irp->read.nbytes);
dump_const_iobuf(&irp->write);
hr = iohook_invoke_next(irp);
if (FAILED(hr) && !fdshark_force_sync(irp, hr)) {
dprintf("FdShark: FAILED: %x\n", (int) hr);
} else {
dprintf("FdShark: Ioctl %08x w:%p:%i/%i r:%p:%i/%i OK\n",
irp->ioctl,
irp->write.bytes,
(int) irp->write.pos,
(int) irp->write.nbytes,
irp->read.bytes,
(int) irp->read.pos,
(int) irp->read.nbytes);
dump_iobuf(&irp->read);
}
return S_OK;
}
static bool fdshark_force_sync(struct irp *irp, HRESULT hr)
{
DWORD xferred;
BOOL ok;
if (!(fdshark_flags & FDSHARK_FORCE_SYNC)) {
return false;
}
if ( hr != HRESULT_FROM_WIN32(ERROR_IO_PENDING) &&
hr != HRESULT_FROM_NT(STATUS_PENDING)) {
return false;
}
ok = GetOverlappedResult(irp->fd, irp->ovl, &xferred, TRUE);
if (!ok) {
hr = HRESULT_FROM_WIN32(GetLastError());
dprintf("FdShark: Synchronous block failed: %x\n", (int) hr);
return false;
}
switch (irp->op) {
case IRP_OP_READ:
case IRP_OP_IOCTL:
irp->read.pos += xferred;
break;
case IRP_OP_WRITE:
irp->write.pos += xferred;
break;
default:
break;
}
return true;
}
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stddef.h>
enum {
FDSHARK_FORCE_SYNC = 0x1,
FDSHARK_TRACE_READ = 0x2,
FDSHARK_TRACE_WRITE = 0x4,
FDSHARK_TRACE_IOCTL = 0x8,
FDSHARK_ALL_FLAGS_ = 0xF,
};
HRESULT fdshark_hook_init(const wchar_t *filename, int flags);
+37
View File
@@ -0,0 +1,37 @@
hooklib_lib = static_library(
'hooklib',
include_directories : inc,
implicit_include_directories : false,
dependencies : [
capnhook.get_variable('hook_dep'),
ws2_32_lib
],
sources : [
'cursor.c',
'cursor.h',
'config.c',
'config.h',
'createprocess.c',
'createprocess.h',
'dll.c',
'dll.h',
'dns.c',
'dns.h',
'dvd.c',
'dvd.h',
'fdshark.c',
'fdshark.h',
'path.c',
'path.h',
'reg.c',
'reg.h',
'setupapi.c',
'setupapi.h',
'spike.c',
'spike.h',
'touch.c',
'touch.h',
'printer.c',
'printer.h',
],
)
File diff suppressed because it is too large Load Diff
+20
View File
@@ -0,0 +1,20 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stddef.h>
typedef HRESULT (*path_hook_t)(
const wchar_t *src,
wchar_t *dest,
size_t *count);
HRESULT path_hook_push(path_hook_t hook);
void path_hook_insert_hooks(HMODULE target);
int path_compare_w(const wchar_t *string1, const wchar_t *string2, size_t count);
static inline bool path_is_separator_w(wchar_t c)
{
return c == L'\\' || c == L'/';
}
File diff suppressed because it is too large Load Diff
+24
View File
@@ -0,0 +1,24 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
#include <stdint.h>
struct printer_config {
bool enable;
bool rotate_180;
char serial_no[8];
wchar_t main_fw_path[MAX_PATH];
wchar_t dsp_fw_path[MAX_PATH];
wchar_t param_fw_path[MAX_PATH];
wchar_t printer_out_path[MAX_PATH];
uint32_t wait_time;
};
void printer_hook_init(const struct printer_config *cfg, int rfid_port_no, HINSTANCE self);
void printer_hook_insert_hooks(HMODULE target);
void printer_set_dimensions(int width, int height);
int WINAPI fwdlusb_updateFirmware_main(uint8_t update, LPCSTR filename, uint16_t *rResult);
int WINAPI fwdlusb_updateFirmware_dsp(uint8_t update, LPCSTR filename, uint16_t *rResult);
int WINAPI fwdlusb_updateFirmware_param(uint8_t update, LPCSTR filename, uint16_t *rResult);
+1054
View File
File diff suppressed because it is too large Load Diff
+37
View File
@@ -0,0 +1,37 @@
#pragma once
#include <windows.h>
#include <stddef.h>
#include <stdint.h>
struct reg_hook_val {
const wchar_t *name;
HRESULT (*read)(void *bytes, uint32_t *nbytes);
HRESULT (*write)(const void *bytes, uint32_t nbytes);
uint32_t type;
};
void reg_hook_insert_hooks(HMODULE target);
HRESULT reg_hook_push_key(
HKEY root,
const wchar_t *name,
const struct reg_hook_val *vals,
size_t nvals);
HRESULT reg_hook_read_bin(
void *bytes,
uint32_t *nbytes,
const void *src_bytes,
size_t src_nbytes);
HRESULT reg_hook_read_u32(
void *bytes,
uint32_t *nbytes,
uint32_t src);
HRESULT reg_hook_read_wstr(
void *bytes,
uint32_t *nbytes,
const wchar_t *src);
+487
View File
@@ -0,0 +1,487 @@
#include <windows.h>
#include <setupapi.h>
#include <assert.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "hook/table.h"
#include "hooklib/setupapi.h"
#include "util/dprintf.h"
struct setupapi_class {
const GUID *guid;
const wchar_t *path;
char *a_path;
HDEVINFO cur_handle;
};
static void setupapi_hook_init(void);
/* API hooks */
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
const GUID *ClassGuid,
wchar_t *Enumerator,
HWND hwndParent,
DWORD Flags);
static HDEVINFO WINAPI my_SetupDiGetClassDevsA(
const GUID *ClassGuid,
char *Enumerator,
HWND hwndParent,
DWORD Flags);
static BOOL WINAPI my_SetupDiEnumDeviceInterfaces(
HDEVINFO DeviceInfoSet,
SP_DEVINFO_DATA *DeviceInfoData,
const GUID *InterfaceClassGuid,
DWORD MemberIndex,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData);
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailW(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_W *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailA(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet);
/* Links */
static HDEVINFO (WINAPI *next_SetupDiGetClassDevsW)(
const GUID *ClassGuid,
wchar_t *Enumerator,
HWND hwndParent,
DWORD Flags);
static HDEVINFO (WINAPI *next_SetupDiGetClassDevsA)(
const GUID *ClassGuid,
char *Enumerator,
HWND hwndParent,
DWORD Flags);
static BOOL (WINAPI *next_SetupDiEnumDeviceInterfaces)(
HDEVINFO DeviceInfoSet,
SP_DEVINFO_DATA *DeviceInfoData,
const GUID *InterfaceClassGuid,
DWORD MemberIndex,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData);
static BOOL (WINAPI *next_SetupDiGetDeviceInterfaceDetailW)(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_W *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL (WINAPI *next_SetupDiGetDeviceInterfaceDetailA)(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData);
static BOOL (WINAPI *next_SetupDiDestroyDeviceInfoList)(HDEVINFO DeviceInfoSet);
/* Hook tbl */
static const struct hook_symbol setupapi_syms[] = {
{
.name = "SetupDiGetClassDevsW",
.patch = my_SetupDiGetClassDevsW,
.link = (void *) &next_SetupDiGetClassDevsW,
}, {
.name = "SetupDiGetClassDevsA",
.patch = my_SetupDiGetClassDevsA,
.link = (void *) &next_SetupDiGetClassDevsA,
}, {
.name = "SetupDiEnumDeviceInterfaces",
.patch = my_SetupDiEnumDeviceInterfaces,
.link = (void *) &next_SetupDiEnumDeviceInterfaces,
}, {
.name = "SetupDiGetDeviceInterfaceDetailW",
.patch = my_SetupDiGetDeviceInterfaceDetailW,
.link = (void *) &next_SetupDiGetDeviceInterfaceDetailW,
}, {
.name = "SetupDiGetDeviceInterfaceDetailA",
.patch = my_SetupDiGetDeviceInterfaceDetailA,
.link = (void *) &next_SetupDiGetDeviceInterfaceDetailA,
}, {
.name = "SetupDiDestroyDeviceInfoList",
.patch = my_SetupDiDestroyDeviceInfoList,
.link = (void *) &next_SetupDiDestroyDeviceInfoList,
}
};
static bool setupapi_initted;
static CRITICAL_SECTION setupapi_lock;
static struct setupapi_class *setupapi_classes;
static size_t setupapi_nclasses;
HRESULT setupapi_add_phantom_dev(const GUID *iface_class, const wchar_t *path)
{
struct setupapi_class *class_;
struct setupapi_class *new_array;
size_t a_path_len;
HRESULT hr;
assert(iface_class != NULL);
assert(path != NULL);
setupapi_hook_init();
EnterCriticalSection(&setupapi_lock);
new_array = realloc(
setupapi_classes,
(setupapi_nclasses + 1) * sizeof(struct setupapi_class));
if (new_array == NULL) {
hr = E_OUTOFMEMORY;
goto end;
}
setupapi_classes = new_array;
class_ = &setupapi_classes[setupapi_nclasses++];
class_->guid = iface_class;
class_->path = path;
a_path_len = wcslen(path) * sizeof(wchar_t) + 1;
class_->a_path = (char*)malloc(a_path_len);
wcstombs(class_->a_path, path, a_path_len);
hr = S_OK;
end:
LeaveCriticalSection(&setupapi_lock);
return hr;
}
static void setupapi_hook_init()
{
if (setupapi_initted) {
return;
}
setupapi_hook_insert_hooks(NULL);
InitializeCriticalSection(&setupapi_lock);
setupapi_initted = true;
}
void setupapi_hook_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"setupapi.dll",
setupapi_syms,
_countof(setupapi_syms));
}
static HDEVINFO WINAPI my_SetupDiGetClassDevsW(
const GUID *ClassGuid,
wchar_t *Enumerator,
HWND hwndParent,
DWORD Flags)
{
struct setupapi_class *class_;
HDEVINFO result;
size_t i;
result = next_SetupDiGetClassDevsW(
ClassGuid,
Enumerator,
hwndParent,
Flags);
if (result == INVALID_HANDLE_VALUE || ClassGuid == NULL) {
return result;
}
EnterCriticalSection(&setupapi_lock);
for (i = 0 ; i < setupapi_nclasses ; i++) {
class_ = &setupapi_classes[i];
if (memcmp(ClassGuid, class_->guid, sizeof(*ClassGuid)) == 0) {
class_->cur_handle = result;
}
}
LeaveCriticalSection(&setupapi_lock);
return result;
}
static HDEVINFO WINAPI my_SetupDiGetClassDevsA(
const GUID *ClassGuid,
char *Enumerator,
HWND hwndParent,
DWORD Flags)
{
struct setupapi_class *class_;
HDEVINFO result;
size_t i;
result = next_SetupDiGetClassDevsA(
ClassGuid,
Enumerator,
hwndParent,
Flags);
if (result == INVALID_HANDLE_VALUE || ClassGuid == NULL) {
return result;
}
EnterCriticalSection(&setupapi_lock);
for (i = 0 ; i < setupapi_nclasses ; i++) {
class_ = &setupapi_classes[i];
if (memcmp(ClassGuid, class_->guid, sizeof(*ClassGuid)) == 0) {
class_->cur_handle = result;
}
}
LeaveCriticalSection(&setupapi_lock);
return result;
}
static BOOL WINAPI my_SetupDiEnumDeviceInterfaces(
HDEVINFO DeviceInfoSet,
SP_DEVINFO_DATA *DeviceInfoData,
const GUID *InterfaceClassGuid,
DWORD MemberIndex,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData)
{
const struct setupapi_class *class_;
size_t i;
if ( DeviceInfoSet == INVALID_HANDLE_VALUE ||
DeviceInterfaceData == NULL ||
DeviceInterfaceData->cbSize != sizeof(*DeviceInterfaceData)) {
goto pass;
}
if (MemberIndex > 0) {
MemberIndex--;
goto pass;
}
EnterCriticalSection(&setupapi_lock);
for ( i = 0, class_ = NULL ;
i < setupapi_nclasses && class_ == NULL ;
i++) {
if (DeviceInfoSet == setupapi_classes[i].cur_handle) {
class_ = &setupapi_classes[i];
dprintf("SetupAPI: Interface {%08lx-...} -> Device node %S\n",
class_->guid->Data1,
class_->path);
memcpy( &DeviceInterfaceData->InterfaceClassGuid,
class_->guid,
sizeof(GUID));
DeviceInterfaceData->Flags = SPINT_ACTIVE;
DeviceInterfaceData->Reserved = (ULONG_PTR) class_->path;
}
}
LeaveCriticalSection(&setupapi_lock);
if (class_ == NULL) {
goto pass;
}
SetLastError(ERROR_SUCCESS);
return TRUE;
pass:
return next_SetupDiEnumDeviceInterfaces(
DeviceInfoSet,
DeviceInfoData,
InterfaceClassGuid,
MemberIndex,
DeviceInterfaceData);
}
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailW(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_W *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData)
{
const wchar_t *wstr;
size_t nbytes_wstr;
size_t nbytes_total;
size_t i;
bool match;
if (DeviceInfoSet == INVALID_HANDLE_VALUE || DeviceInterfaceData == NULL) {
goto pass;
}
EnterCriticalSection(&setupapi_lock);
for ( i = 0, match = false ;
i < setupapi_nclasses && !match ;
i++) {
if ( DeviceInfoSet == setupapi_classes[i].cur_handle &&
DeviceInterfaceData->Reserved == (ULONG_PTR) setupapi_classes[i].path) {
match = true;
}
}
LeaveCriticalSection(&setupapi_lock);
if (!match) {
goto pass;
}
wstr = (const wchar_t *) DeviceInterfaceData->Reserved;
nbytes_wstr = (wcslen(wstr) + 1) * sizeof(wchar_t);
nbytes_total = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath);
nbytes_total += nbytes_wstr;
if (RequiredSize != NULL) {
*RequiredSize = (DWORD) nbytes_total;
}
if ( DeviceInterfaceDetailData == NULL &&
DeviceInterfaceDetailDataSize < nbytes_total) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
if (DeviceInterfaceDetailData->cbSize!=sizeof(*DeviceInterfaceDetailData)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memcpy(DeviceInterfaceDetailData->DevicePath, wstr, nbytes_wstr);
SetLastError(ERROR_SUCCESS);
return TRUE;
pass:
return next_SetupDiGetDeviceInterfaceDetailW(
DeviceInfoSet,
DeviceInterfaceData,
DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize,
RequiredSize,
DeviceInfoData);
}
static BOOL WINAPI my_SetupDiGetDeviceInterfaceDetailA(
HDEVINFO DeviceInfoSet,
SP_DEVICE_INTERFACE_DATA *DeviceInterfaceData,
SP_DEVICE_INTERFACE_DETAIL_DATA_A *DeviceInterfaceDetailData,
DWORD DeviceInterfaceDetailDataSize,
DWORD *RequiredSize,
SP_DEVINFO_DATA *DeviceInfoData)
{
const char *str;
size_t nbytes_str;
size_t nbytes_total;
size_t i;
bool match;
if (DeviceInfoSet == INVALID_HANDLE_VALUE || DeviceInterfaceData == NULL) {
goto pass;
}
EnterCriticalSection(&setupapi_lock);
for (i = 0, match = false; i < setupapi_nclasses && !match; i++) {
if (DeviceInfoSet == setupapi_classes[i].cur_handle &&
DeviceInterfaceData->Reserved == (ULONG_PTR) setupapi_classes[i].path) {
str = setupapi_classes[i].a_path;
match = true;
}
}
LeaveCriticalSection(&setupapi_lock);
if (!match) {
goto pass;
}
nbytes_str = strlen(str) + 1;
nbytes_total = offsetof(SP_DEVICE_INTERFACE_DETAIL_DATA_W, DevicePath);
nbytes_total += nbytes_str;
if (RequiredSize != NULL) {
*RequiredSize = (DWORD) nbytes_total;
}
if ( DeviceInterfaceDetailData == NULL &&
DeviceInterfaceDetailDataSize < nbytes_total) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
if (DeviceInterfaceDetailData->cbSize!=sizeof(*DeviceInterfaceDetailData)) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
memcpy(DeviceInterfaceDetailData->DevicePath, str, nbytes_str);
SetLastError(ERROR_SUCCESS);
return TRUE;
pass:
return next_SetupDiGetDeviceInterfaceDetailA(
DeviceInfoSet,
DeviceInterfaceData,
DeviceInterfaceDetailData,
DeviceInterfaceDetailDataSize,
RequiredSize,
DeviceInfoData);
}
static BOOL WINAPI my_SetupDiDestroyDeviceInfoList(HDEVINFO DeviceInfoSet)
{
size_t i;
EnterCriticalSection(&setupapi_lock);
for (i = 0 ; i < setupapi_nclasses ; i++) {
if (setupapi_classes[i].cur_handle == DeviceInfoSet) {
setupapi_classes[i].cur_handle = NULL;
}
}
LeaveCriticalSection(&setupapi_lock);
return next_SetupDiDestroyDeviceInfoList(DeviceInfoSet);
}
+8
View File
@@ -0,0 +1,8 @@
#pragma once
#include <windows.h>
#include <stddef.h>
HRESULT setupapi_add_phantom_dev(const GUID *iface_class, const wchar_t *path);
void setupapi_hook_insert_hooks(HMODULE target);
+250
View File
@@ -0,0 +1,250 @@
#include <windows.h>
#include <assert.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <wchar.h>
#include "hook/pe.h"
#include "hooklib/spike.h"
#include "util/dprintf.h"
static void spike_hook_read_config(const wchar_t *spike_file);
/* Spike functions. Their "style" is named after the libc function they bear
the closest resemblance to. */
static void spike_fn_puts(const char *msg)
{
char line[512];
sprintf_s(line, _countof(line), "%s\n", msg);
OutputDebugStringA(line);
}
static void spike_fn_fputs(const char *msg)
{
OutputDebugStringA(msg);
}
static void spike_fn_printf(const char *fmt, ...)
{
char line[512];
va_list ap;
va_start(ap, fmt);
vsprintf_s(line, _countof(line), fmt, ap);
strcat(line, "\n");
OutputDebugStringA(line);
}
static void spike_fn_vprintf(
const char *proc,
int line_no,
const char *fmt,
va_list ap)
{
char msg[512];
char line[512];
vsprintf_s(msg, _countof(msg), fmt, ap);
sprintf_s(line, _countof(line), "%s:%i: %s", proc, line_no, msg);
OutputDebugStringA(line);
}
static void spike_fn_vwprintf(
const wchar_t *proc,
int line_no,
const wchar_t *fmt,
va_list ap)
{
wchar_t msg[512];
wchar_t line[512];
vswprintf_s(msg, _countof(msg), fmt, ap);
swprintf_s(line, _countof(line), L"%s:%i: %s", proc, line_no, msg);
OutputDebugStringW(line);
}
static void spike_fn_perror(
int a1,
int a2,
int error,
const char *file,
int line_no,
const char *msg)
{
char line[512];
sprintf_s(
line,
_countof(line),
"%s:%i:%08x: %s\n",
file,
line_no,
error,
msg);
OutputDebugStringA(line);
}
/* Spike inserters */
static void spike_insert_jmp(ptrdiff_t rva, void *proc)
{
uint8_t *base;
uint8_t *target;
uint8_t *func_ptr;
uint32_t delta;
base = (uint8_t *) GetModuleHandleW(NULL);
target = base + rva;
func_ptr = proc;
delta = func_ptr - target - 4; /* -4: EIP delta, after end of target insn */
pe_patch(target, &delta, sizeof(delta));
}
static void spike_insert_ptr(ptrdiff_t rva, void *ptr)
{
uint8_t *base;
uint8_t *target;
base = (uint8_t *) GetModuleHandleW(NULL);
target = base + rva;
pe_patch(target, &ptr, sizeof(ptr));
}
static void spike_insert_log_levels(ptrdiff_t rva, size_t count)
{
uint8_t *base;
uint32_t *levels;
size_t i;
base = (uint8_t *) GetModuleHandleW(NULL);
levels = (uint32_t *) (base + rva);
for (i = 0 ; i < count ; i++) {
levels[i] = 255;
}
}
/* Config reader */
void spike_hook_init(const wchar_t *ini_file)
{
wchar_t module[MAX_PATH];
wchar_t path[MAX_PATH];
const wchar_t *basename;
const wchar_t *slash;
assert(ini_file != NULL);
/* Get the filename (strip path) of the host EXE */
GetModuleFileNameW(NULL, module, _countof(module));
slash = wcsrchr(module, L'\\');
if (slash != NULL) {
basename = slash + 1;
} else {
basename = module;
}
/* Check our INI file to see if any spikes are configured for this EXE.
Normally we separate out config reading into a separate module... */
GetPrivateProfileStringW(
L"spike",
basename,
L"",
path,
_countof(path),
ini_file);
if (path[0] != L'\0') {
dprintf("Spiking %S using config from %S\n", basename, path);
spike_hook_read_config(path);
}
}
static void spike_hook_read_config(const wchar_t *spike_file)
{
int match;
int count;
int rva;
char line[80];
char *ret;
FILE *f;
f = _wfopen(spike_file, L"r");
if (f == NULL) {
dprintf("Error opening spike file %S\n", spike_file);
return;
}
for (;;) {
ret = fgets(line, sizeof(line), f);
if (ret == NULL) {
break;
}
if (line[0] == '#' || line[0] == '\r' || line[0] == '\n') {
continue;
}
match = sscanf(line, "levels %i %i", &rva, &count);
if (match == 2) {
spike_insert_log_levels((ptrdiff_t) rva, count);
}
match = sscanf(line, "j_vprintf %i", &rva);
if (match == 1) {
spike_insert_jmp((ptrdiff_t) rva, spike_fn_vprintf);
}
match = sscanf(line, "j_vwprintf %i", &rva);
if (match == 1) {
spike_insert_jmp((ptrdiff_t) rva, spike_fn_vwprintf);
}
match = sscanf(line, "j_printf %i", &rva);
if (match == 1) {
spike_insert_jmp((ptrdiff_t) rva, spike_fn_printf);
}
match = sscanf(line, "j_puts %i", &rva);
if (match == 1) {
spike_insert_jmp((ptrdiff_t) rva, spike_fn_puts);
}
match = sscanf(line, "j_perror %i", &rva);
if (match == 1) {
spike_insert_jmp((ptrdiff_t) rva, spike_fn_perror);
}
match = sscanf(line, "c_fputs %i", &rva); /* c == "callback" */
if (match == 1) {
spike_insert_ptr((ptrdiff_t) rva, spike_fn_fputs);
}
}
dprintf("Spike insertion complete\n");
fclose(f);
}
+5
View File
@@ -0,0 +1,5 @@
#pragma once
#include <stddef.h>
void spike_hook_init(const wchar_t *ini_file);
+255
View File
@@ -0,0 +1,255 @@
/*
This part (touch screen hook) is mostly taken from spicetools, which is GPL.
This means there can be some license issues if you do use this code in some other places without including source code.
*/
#include <windows.h>
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include "hook/com-proxy.h"
#include "hook/table.h"
#include "hooklib/config.h"
#include "hooklib/dll.h"
#include "hooklib/touch.h"
#include "util/dprintf.h"
/* API hooks */
static LRESULT hook_wndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
static ATOM WINAPI hook_RegisterClassExA(
WNDCLASSEXA* wndClass
);
static int WINAPI hook_GetSystemMetrics(
int nIndex
);
static BOOL WINAPI hook_RegisterTouchWindow(
HWND hwnd,
ULONG ulFlags
);
static BOOL WINAPI hook_GetTouchInputInfo(
HANDLE hTouchInput,
UINT cInputs,
PTOUCHINPUT pInputs,
int cbSize
);
static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor);
/* Link pointers */
static ATOM (WINAPI *next_RegisterClassExA)(
const WNDCLASSEXA* wndClass
);
static int (WINAPI *next_GetSystemMetrics)(
int nIndex
);
static BOOL (WINAPI *next_RegisterTouchWindow)(
HWND hwnd,
ULONG ulFlags
);
static BOOL (WINAPI *next_GetTouchInputInfo)(
HANDLE hTouchInput,
UINT cInputs,
PTOUCHINPUT pInputs,
int cbSize
);
static HCURSOR(WINAPI *next_SetCursor)(HCURSOR cursor);
static bool touch_hook_initted;
static bool touch_held;
static HWND registered_hWnd;
static struct touch_screen_config touch_config;
static WNDPROC orig_wndProc;
static HCURSOR defaultCursor;
static const struct hook_symbol touch_hooks[] = {
{
.name = "RegisterClassExA",
.patch = hook_RegisterClassExA,
.link = (void**)&next_RegisterClassExA
},
{
.name = "GetSystemMetrics",
.patch = hook_GetSystemMetrics,
.link = (void **) &next_GetSystemMetrics
},
{
.name = "RegisterTouchWindow",
.patch = hook_RegisterTouchWindow,
.link = (void **) &next_RegisterTouchWindow
},
{
.name = "GetTouchInputInfo",
.patch = hook_GetTouchInputInfo,
.link = (void **) &next_GetTouchInputInfo
},
{
.name = "SetCursor",
.patch = hook_SetCursor,
.link = (void **) &next_SetCursor
},
};
void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self)
{
assert(cfg != NULL);
if (!cfg->enable) {
return;
}
if (touch_hook_initted) {
return;
}
touch_hook_initted = true;
defaultCursor = LoadCursorA(NULL, IDC_CROSS);
memcpy(&touch_config, cfg, sizeof(*cfg));
touch_hook_insert_hooks(NULL);
dprintf("TOUCH: hook enabled.\n");
}
void touch_hook_insert_hooks(HMODULE target)
{
hook_table_apply(
target,
"user32.dll",
touch_hooks,
_countof(touch_hooks));
}
static HCURSOR WINAPI hook_SetCursor(HCURSOR cursor) {
if (cursor == 0 && touch_config.cursor)
return next_SetCursor(defaultCursor);
return next_SetCursor(cursor);
}
// remap mouse events to touch events
static LRESULT hook_wndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) {
if (hWnd == registered_hWnd && (Msg == WM_LBUTTONDOWN || Msg == WM_LBUTTONUP || (touch_held && Msg == WM_MOUSEMOVE))) {
orig_wndProc(hWnd, WM_TOUCH, 1, 1);
}
return orig_wndProc(hWnd, Msg, wParam, lParam);
}
static ATOM WINAPI hook_RegisterClassExA(
WNDCLASSEXA* wndClass
) {
if (wndClass->lpfnWndProc) {
orig_wndProc = wndClass->lpfnWndProc;
wndClass->lpfnWndProc = (WNDPROC) hook_wndProc;
}
return next_RegisterClassExA(wndClass);
}
// Spicetools misc/wintouchemu.cpp
static int WINAPI hook_GetSystemMetrics(
int nIndex
)
{
if (nIndex == 94) return 0x01 | 0x02 | 0x40 | 0x80;
int orig = next_GetSystemMetrics(nIndex);
return orig;
}
static BOOL WINAPI hook_RegisterTouchWindow(
HWND hwnd,
ULONG ulFlags
)
{
registered_hWnd = hwnd;
return true;
}
// Converting mouse event to touch event
static BOOL WINAPI hook_GetTouchInputInfo(
HANDLE hTouchInput,
UINT cInputs,
PTOUCHINPUT pInputs,
int cbSize
)
{
bool result = false;
int sw, sh, cw, ch;
RECT cRect;
sw = GetSystemMetrics(SM_CXSCREEN);
sh = GetSystemMetrics(SM_CYSCREEN);
GetClientRect(registered_hWnd, &cRect);
cw = cRect.right - cRect.left;
ch = cRect.bottom - cRect.top;
static bool mouse_state_old = false;
for (UINT input = 0; input < cInputs; input++) {
TOUCHINPUT *touch_input = &pInputs[input];
touch_input->x = 0;
touch_input->y = 0;
touch_input->hSource = NULL;
touch_input->dwID = 0;
touch_input->dwFlags = 0;
touch_input->dwMask = 0;
touch_input->dwTime = 0;
touch_input->dwExtraInfo = 0;
touch_input->cxContact = 0;
touch_input->cyContact = 0;
bool mouse_state = (GetKeyState(VK_LBUTTON) & 0x100) != 0;
if (mouse_state || mouse_state_old) {
POINT cursorPos;
GetCursorPos(&cursorPos);
if (touch_config.remap) {
ScreenToClient(registered_hWnd, &cursorPos);
cursorPos.x = (long)(cursorPos.x * ((double)sw / cw));
cursorPos.y = (long)(cursorPos.y * ((double)sh / ch));
}
result = true;
touch_input->x = cursorPos.x * 100;
touch_input->y = cursorPos.y * 100;
touch_input->hSource = hTouchInput;
touch_input->dwID = 0;
touch_input->dwFlags = 0;
if (mouse_state && !mouse_state_old) {
touch_input->dwFlags |= TOUCHEVENTF_DOWN;
touch_held = true;
} else if (mouse_state && mouse_state_old) {
touch_input->dwFlags |= TOUCHEVENTF_MOVE;
} else if (!mouse_state && mouse_state_old) {
touch_input->dwFlags |= TOUCHEVENTF_UP;
touch_held = false;
}
touch_input->dwMask = 0;
touch_input->dwTime = 0;
touch_input->dwExtraInfo = 0;
touch_input->cxContact = 0;
touch_input->cyContact = 0;
}
mouse_state_old = mouse_state;
}
return result;
}
+17
View File
@@ -0,0 +1,17 @@
#pragma once
#include <windows.h>
#include <stdbool.h>
struct touch_screen_config {
bool enable;
bool remap;
bool cursor;
};
/* Init is not thread safe because API hook init is not thread safe blah
blah blah you know the drill by now. */
void touch_screen_hook_init(const struct touch_screen_config *cfg, HINSTANCE self);
void touch_hook_insert_hooks(HMODULE target);