339 lines
9.7 KiB
C
339 lines
9.7 KiB
C
#include <windows.h>
|
|
|
|
#include <stdbool.h>
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "hook/table.h"
|
|
|
|
#include "util/defs.h"
|
|
#include "util/log.h"
|
|
#include "util/mem.h"
|
|
#include "util/str.h"
|
|
|
|
static BOOL STDCALL my_SetCurrentDirectoryA(LPCSTR lpPathName);
|
|
static HANDLE STDCALL
|
|
my_FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData);
|
|
static HANDLE STDCALL my_CreateFileW(
|
|
LPCWSTR lpFileName,
|
|
DWORD dwDesiredAccess,
|
|
DWORD dwShareMode,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
DWORD dwCreationDisposition,
|
|
DWORD dwFlagsAndAttributes,
|
|
HANDLE hTemplateFile);
|
|
static BOOL WINAPI my_CreateDirectoryW(
|
|
LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
|
|
|
|
static BOOL(STDCALL *real_SetCurrentDirectoryA)(LPCSTR lpPathName);
|
|
static HANDLE(STDCALL *real_FindFirstFileW)(
|
|
LPCWSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData);
|
|
static HANDLE(STDCALL *real_CreateFileW)(
|
|
LPCWSTR lpFileName,
|
|
DWORD dwDesiredAccess,
|
|
DWORD dwShareMode,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
DWORD dwCreationDisposition,
|
|
DWORD dwFlagsAndAttributes,
|
|
HANDLE hTemplateFile);
|
|
static BOOL(WINAPI *real_CreateDirectoryW)(
|
|
LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes);
|
|
|
|
static const struct hook_symbol filesystem_hook_syms[] = {
|
|
{.name = "CreateFileW",
|
|
.patch = my_CreateFileW,
|
|
.link = (void **) &real_CreateFileW},
|
|
{
|
|
.name = "SetCurrentDirectoryA",
|
|
.patch = my_SetCurrentDirectoryA,
|
|
.link = (void **) &real_SetCurrentDirectoryA,
|
|
},
|
|
{.name = "FindFirstFileW",
|
|
.patch = my_FindFirstFileW,
|
|
.link = (void **) &real_FindFirstFileW},
|
|
{.name = "CreateDirectoryW",
|
|
.patch = my_CreateDirectoryW,
|
|
.link = (void **) &real_CreateDirectoryW},
|
|
};
|
|
|
|
void ddrhook1_get_launcher_path_parts(
|
|
char **output_path, char **output_foldername)
|
|
{
|
|
char module_path[MAX_PATH];
|
|
char launcher_path[MAX_PATH];
|
|
|
|
memset(launcher_path, 0, MAX_PATH);
|
|
|
|
if (output_path != NULL)
|
|
*output_path = NULL;
|
|
|
|
if (output_foldername != NULL)
|
|
*output_foldername = NULL;
|
|
|
|
if (GetModuleFileNameA(NULL, module_path, sizeof(module_path)) == 0)
|
|
return;
|
|
|
|
char *filename_ptr = NULL;
|
|
if (GetFullPathNameA(
|
|
module_path, sizeof(launcher_path), launcher_path, &filename_ptr) ==
|
|
0)
|
|
return;
|
|
|
|
if (filename_ptr != NULL)
|
|
launcher_path[strlen(launcher_path) - strlen(filename_ptr) - 1] = 0;
|
|
|
|
// Trim tailing slashes
|
|
for (int i = strlen(launcher_path) - 1; i > 0; i--) {
|
|
if (launcher_path[i] != '\\' && launcher_path[i] != '/')
|
|
break;
|
|
|
|
launcher_path[i] = 0;
|
|
}
|
|
|
|
int idx_folder = 0;
|
|
for (idx_folder = strlen(launcher_path); idx_folder - 1 > 0; idx_folder--) {
|
|
if (launcher_path[idx_folder - 1] == '\\' ||
|
|
launcher_path[idx_folder - 1] == '/') {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (output_foldername != NULL) {
|
|
int len = strlen(launcher_path) - idx_folder;
|
|
|
|
if (len < 0)
|
|
len = 0;
|
|
|
|
*output_foldername = (char *) xmalloc(len + 2);
|
|
memset(*output_foldername, 0, len + 1);
|
|
strncpy(*output_foldername, launcher_path + idx_folder, len);
|
|
}
|
|
|
|
if (output_path != NULL) {
|
|
size_t len = idx_folder - 1 < 0 ? 0 : idx_folder - 1;
|
|
|
|
if (len > strlen(launcher_path))
|
|
len = strlen(launcher_path);
|
|
|
|
*output_path = (char *) xmalloc(len + 1);
|
|
memset(*output_path, 0, len + 1);
|
|
strncpy(*output_path, launcher_path, len);
|
|
}
|
|
}
|
|
|
|
static wchar_t *ddrhook1_filesystem_get_path(LPCWSTR path)
|
|
{
|
|
wchar_t *new_path = NULL;
|
|
|
|
// char *tmp;
|
|
// wstr_narrow(path, &tmp);
|
|
// log_misc("path: %s", tmp);
|
|
// free(tmp);
|
|
|
|
// Deal with hardcoded paths: D:/HDX, E:/conf, E:/conf/nvram, E:/conf/raw,
|
|
// F:/update, ...
|
|
if (wstr_insensitive_eq(path, L"D:/HDX") ||
|
|
wstr_insensitive_eq(path, L"D:\\HDX") ||
|
|
wstr_insensitive_eq(path, L"D:/JDX") ||
|
|
wstr_insensitive_eq(path, L"D:\\JDX")) {
|
|
char *_new_path;
|
|
ddrhook1_get_launcher_path_parts(&_new_path, NULL);
|
|
|
|
if (_new_path) {
|
|
new_path = str_widen(_new_path);
|
|
return new_path;
|
|
}
|
|
} else if (
|
|
wcslen(path) >= 7 &&
|
|
(wcsnicmp(path, L"E:/conf", 7) == 0 ||
|
|
wcsnicmp(path, L"E:\\conf", 7) == 0)) {
|
|
char *launcher_folder;
|
|
wchar_t *sub_path;
|
|
|
|
ddrhook1_get_launcher_path_parts(NULL, &launcher_folder);
|
|
sub_path = wcsstr(path, L"conf");
|
|
|
|
if (sub_path && launcher_folder) {
|
|
wchar_t *launcher_folder_w = str_widen(launcher_folder);
|
|
new_path = (wchar_t *) xmalloc(MAX_PATH * sizeof(wchar_t));
|
|
swprintf(
|
|
new_path, MAX_PATH, L"%s\\%s", launcher_folder_w, sub_path);
|
|
free(launcher_folder_w);
|
|
return new_path;
|
|
}
|
|
} else if (
|
|
wstr_insensitive_eq(path, L"F:/update") ||
|
|
wstr_insensitive_eq(path, L"F:\\update") ||
|
|
wstr_insensitive_eq(path, L".\\F:/update") ||
|
|
wstr_insensitive_eq(path, L".\\F:\\update")) {
|
|
char *launcher_folder;
|
|
wchar_t *sub_path;
|
|
|
|
ddrhook1_get_launcher_path_parts(NULL, &launcher_folder);
|
|
sub_path = wcsstr(path, L"update");
|
|
|
|
if (sub_path && launcher_folder) {
|
|
wchar_t *launcher_folder_w = str_widen(launcher_folder);
|
|
new_path = (wchar_t *) xmalloc(MAX_PATH * sizeof(wchar_t));
|
|
swprintf(
|
|
new_path, MAX_PATH, L"%s\\%s", launcher_folder_w, sub_path);
|
|
free(launcher_folder_w);
|
|
return new_path;
|
|
}
|
|
} else if (
|
|
wcslen(path) >= 24 &&
|
|
(wcsnicmp(path, L"D:/JDX/JDX-001/contents/", 24) == 0 ||
|
|
wcsnicmp(path, L"D:\\JDX\\JDX-001\\contents\\", 24) == 0)) {
|
|
char *content_path;
|
|
|
|
ddrhook1_get_launcher_path_parts(&content_path, NULL);
|
|
|
|
if (content_path) {
|
|
wchar_t *content_path_w = str_widen(content_path);
|
|
new_path = (wchar_t *) xmalloc(MAX_PATH * sizeof(wchar_t));
|
|
swprintf(new_path, MAX_PATH, L"%s\\%s", content_path_w, path + 24);
|
|
free(content_path_w);
|
|
return new_path;
|
|
}
|
|
} else if (
|
|
wcslen(path) >= 7 &&
|
|
(wcsnicmp(path, L"D:/HDX/", 7) == 0 ||
|
|
wcsnicmp(path, L"D:\\HDX\\", 7) == 0 ||
|
|
wcsnicmp(path, L"D:/JDX/", 7) == 0 ||
|
|
wcsnicmp(path, L"D:\\JDX\\", 7) == 0)) {
|
|
char *content_path;
|
|
|
|
ddrhook1_get_launcher_path_parts(&content_path, NULL);
|
|
|
|
if (content_path) {
|
|
wchar_t *content_path_w = str_widen(content_path);
|
|
new_path = (wchar_t *) xmalloc(MAX_PATH * sizeof(wchar_t));
|
|
swprintf(new_path, MAX_PATH, L"%s\\%s", content_path_w, path + 7);
|
|
free(content_path_w);
|
|
return new_path;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
static BOOL STDCALL my_SetCurrentDirectoryA(LPCSTR lpPathName)
|
|
{
|
|
wchar_t *_lpPathName = str_widen(lpPathName);
|
|
wchar_t *_new_path = ddrhook1_filesystem_get_path(_lpPathName);
|
|
char *new_path = NULL;
|
|
|
|
if (_lpPathName != NULL) {
|
|
free(_lpPathName);
|
|
}
|
|
|
|
if (_new_path != NULL) {
|
|
wstr_narrow(_new_path, &new_path);
|
|
free(_new_path);
|
|
}
|
|
|
|
if (new_path != NULL) {
|
|
bool r = real_SetCurrentDirectoryA(new_path);
|
|
log_misc(
|
|
"SetCurrentDirectoryA remapped path %s -> %s",
|
|
lpPathName,
|
|
new_path);
|
|
free(new_path);
|
|
return r;
|
|
}
|
|
|
|
return real_SetCurrentDirectoryA(lpPathName);
|
|
}
|
|
|
|
static HANDLE STDCALL
|
|
my_FindFirstFileW(LPCWSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData)
|
|
{
|
|
wchar_t *new_path = ddrhook1_filesystem_get_path(lpFileName);
|
|
|
|
if (new_path) {
|
|
HANDLE r = real_FindFirstFileW(new_path, lpFindFileData);
|
|
|
|
char *tmp;
|
|
wstr_narrow(new_path, &tmp);
|
|
log_misc("FindFirstFileW remapped path: %s", tmp);
|
|
free(tmp);
|
|
|
|
free(new_path);
|
|
return r;
|
|
}
|
|
|
|
return real_FindFirstFileW(lpFileName, lpFindFileData);
|
|
}
|
|
|
|
static HANDLE STDCALL my_CreateFileW(
|
|
LPCWSTR lpFileName,
|
|
DWORD dwDesiredAccess,
|
|
DWORD dwShareMode,
|
|
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
|
DWORD dwCreationDisposition,
|
|
DWORD dwFlagsAndAttributes,
|
|
HANDLE hTemplateFile)
|
|
{
|
|
wchar_t *new_path = ddrhook1_filesystem_get_path(lpFileName);
|
|
|
|
if (new_path) {
|
|
HANDLE r = real_CreateFileW(
|
|
new_path,
|
|
dwDesiredAccess,
|
|
dwShareMode,
|
|
lpSecurityAttributes,
|
|
dwCreationDisposition,
|
|
dwFlagsAndAttributes,
|
|
hTemplateFile);
|
|
|
|
// char *tmp;
|
|
// wstr_narrow(new_path, &tmp);
|
|
// log_misc("CreateFileW remapped path %s", tmp);
|
|
// free(tmp);
|
|
|
|
free(new_path);
|
|
return r;
|
|
}
|
|
|
|
return real_CreateFileW(
|
|
new_path ? new_path : lpFileName,
|
|
dwDesiredAccess,
|
|
dwShareMode,
|
|
lpSecurityAttributes,
|
|
dwCreationDisposition,
|
|
dwFlagsAndAttributes,
|
|
hTemplateFile);
|
|
}
|
|
|
|
BOOL WINAPI my_CreateDirectoryW(
|
|
LPCWSTR lpPathName, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
|
|
{
|
|
wchar_t *new_path = ddrhook1_filesystem_get_path(lpPathName);
|
|
|
|
if (new_path) {
|
|
BOOL r = real_CreateDirectoryW(new_path, lpSecurityAttributes);
|
|
|
|
char *tmp;
|
|
wstr_narrow(new_path, &tmp);
|
|
log_misc("CreateDirectoryW remapped path %s", tmp);
|
|
free(tmp);
|
|
|
|
free(new_path);
|
|
return r;
|
|
}
|
|
|
|
return real_CreateDirectoryW(lpPathName, lpSecurityAttributes);
|
|
}
|
|
|
|
void ddrhook1_filesystem_hook_init()
|
|
{
|
|
hook_table_apply(
|
|
NULL,
|
|
"kernel32.dll",
|
|
filesystem_hook_syms,
|
|
lengthof(filesystem_hook_syms));
|
|
|
|
log_info("Inserted filesystem hooks");
|
|
} |