mirror of
https://gitea.tendokyu.moe/TeamTofuShop/segatools.git
synced 2026-09-22 22:37:59 +03:00
Merge branch 'develop' into develop
This commit is contained in:
@@ -200,6 +200,14 @@ static UINT WINAPI hook_GetDriveTypeW(
|
||||
LPCWSTR lpRootPathName
|
||||
);
|
||||
|
||||
static BOOL WINAPI hook_GetDiskFreeSpaceW(
|
||||
LPCWSTR lpRootPathName,
|
||||
LPDWORD lpSectorsPerCluster,
|
||||
LPDWORD lpBytesPerSector,
|
||||
LPDWORD lpNumberOfFreeClusters,
|
||||
LPDWORD lpTotalNumberOfClusters
|
||||
);
|
||||
|
||||
/* Link pointers */
|
||||
|
||||
static BOOL (WINAPI *next_CreateDirectoryA)(
|
||||
@@ -395,6 +403,14 @@ static UINT (WINAPI *next_GetDriveTypeA)(
|
||||
LPCSTR lpRootPathName
|
||||
);
|
||||
|
||||
static BOOL (WINAPI *next_GetDiskFreeSpaceW)(
|
||||
LPCWSTR lpRootPathName,
|
||||
LPDWORD lpSectorsPerCluster,
|
||||
LPDWORD lpBytesPerSector,
|
||||
LPDWORD lpNumberOfFreeClusters,
|
||||
LPDWORD lpTotalNumberOfClusters
|
||||
);
|
||||
|
||||
/* Hook table */
|
||||
|
||||
static const struct hook_symbol path_hook_syms[] = {
|
||||
@@ -538,6 +554,10 @@ static const struct hook_symbol path_hook_syms[] = {
|
||||
.name = "GetDriveTypeW",
|
||||
.patch = hook_GetDriveTypeW,
|
||||
.link = (void **) &next_GetDriveTypeW,
|
||||
}, {
|
||||
.name = "GetDiskFreeSpaceW",
|
||||
.patch = hook_GetDiskFreeSpaceW,
|
||||
.link = (void **) &next_GetDiskFreeSpaceW,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1720,6 +1740,30 @@ static UINT WINAPI hook_GetDriveTypeW(
|
||||
return result;
|
||||
}
|
||||
|
||||
static BOOL WINAPI hook_GetDiskFreeSpaceW(
|
||||
LPCWSTR lpRootPathName,
|
||||
LPDWORD lpSectorsPerCluster,
|
||||
LPDWORD lpBytesPerSector,
|
||||
LPDWORD lpNumberOfFreeClusters,
|
||||
LPDWORD lpTotalNumberOfClusters
|
||||
) {
|
||||
wchar_t *trans;
|
||||
UINT result;
|
||||
BOOL ok;
|
||||
|
||||
ok = path_transform_w(&trans, lpRootPathName);
|
||||
|
||||
if (!ok) {
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
result = next_GetDiskFreeSpaceW(trans ? trans : lpRootPathName, lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters);
|
||||
|
||||
free(trans);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char** str_split_a(char* a_str, const char a_delim) {
|
||||
char** result = 0;
|
||||
size_t count = 0;
|
||||
|
||||
+22
-11
@@ -12,12 +12,15 @@
|
||||
#include "util/dprintf.h"
|
||||
#include "util/str.h"
|
||||
|
||||
#define MAX_CONCURRENT_REG_HANDLES 4
|
||||
|
||||
struct reg_hook_key {
|
||||
HKEY root;
|
||||
const wchar_t *name;
|
||||
const struct reg_hook_val *vals;
|
||||
size_t nvals;
|
||||
HKEY handle;
|
||||
HKEY handles[MAX_CONCURRENT_REG_HANDLES];
|
||||
size_t nhandles;
|
||||
};
|
||||
|
||||
/* Helper functions */
|
||||
@@ -344,7 +347,7 @@ static LRESULT reg_hook_propagate_hr(HRESULT hr)
|
||||
static struct reg_hook_key *reg_hook_match_key_locked(HKEY handle)
|
||||
{
|
||||
struct reg_hook_key *key;
|
||||
size_t i;
|
||||
size_t i, j;
|
||||
|
||||
if (handle == NULL || handle == INVALID_HANDLE_VALUE) {
|
||||
return NULL;
|
||||
@@ -353,8 +356,10 @@ static struct reg_hook_key *reg_hook_match_key_locked(HKEY handle)
|
||||
for (i = 0 ; i < reg_hook_nkeys ; i++) {
|
||||
key = ®_hook_keys[i];
|
||||
|
||||
if (key->handle == handle) {
|
||||
return key;
|
||||
for (j = 0; j < key->nhandles; j++) {
|
||||
if (key->handles[j] == handle) {
|
||||
return key;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -414,9 +419,9 @@ static LSTATUS reg_hook_open_locked(
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
/* Assume only one handle will be open at a time */
|
||||
/* Assume only MAX_CONCURRENT_REG_HANDLES handles will be open at a time */
|
||||
|
||||
if (key->handle != NULL) {
|
||||
if (key->nhandles > MAX_CONCURRENT_REG_HANDLES) {
|
||||
return ERROR_SHARING_VIOLATION;
|
||||
}
|
||||
|
||||
@@ -433,7 +438,7 @@ static LSTATUS reg_hook_open_locked(
|
||||
out);
|
||||
|
||||
if (err == ERROR_SUCCESS) {
|
||||
key->handle = *out;
|
||||
key->handles[key->nhandles++] = *out;
|
||||
}
|
||||
|
||||
return err;
|
||||
@@ -511,16 +516,22 @@ static LSTATUS WINAPI hook_RegCreateKeyExW(
|
||||
static LSTATUS WINAPI hook_RegCloseKey(HKEY handle)
|
||||
{
|
||||
struct reg_hook_key *key;
|
||||
size_t i;
|
||||
size_t i, j, k;
|
||||
|
||||
EnterCriticalSection(®_hook_lock);
|
||||
|
||||
for (i = 0 ; i < reg_hook_nkeys ; i++) {
|
||||
key = ®_hook_keys[i];
|
||||
|
||||
if (key->handle == handle) {
|
||||
//dprintf("Registry: Closed virtual key %S\n", key->name);
|
||||
key->handle = NULL;
|
||||
for (j = 0; j < key->nhandles; j++) {
|
||||
if (key->handles[j] == handle) {
|
||||
for (k = j; k < MAX_CONCURRENT_REG_HANDLES - 1; k++) {
|
||||
key->handles[k] = key->handles[k + 1];
|
||||
}
|
||||
key->handles[MAX_CONCURRENT_REG_HANDLES - 1] = NULL;
|
||||
key->nhandles--;
|
||||
//dprintf("Registry: Closed virtual key %S\n", key->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -170,6 +170,13 @@ void misc_config_load(struct misc_config *cfg, const wchar_t *filename)
|
||||
cfg->enable = GetPrivateProfileIntW(L"misc", L"enable", 1, filename);
|
||||
cfg->allowMasterKeyWrite = GetPrivateProfileIntW(L"misc", L"allowMasterKeyWrite", 0, filename);
|
||||
cfg->allowReboot = GetPrivateProfileIntW(L"misc", L"allowReboot", 0, filename);
|
||||
GetPrivateProfileStringW(
|
||||
L"misc",
|
||||
L"nextProcessFilePath",
|
||||
L"DEVICE\\NextProcess.txt",
|
||||
cfg->nextProcessFile,
|
||||
_countof(cfg->nextProcessFile),
|
||||
filename);
|
||||
}
|
||||
|
||||
void netenv_config_load(struct netenv_config *cfg, const wchar_t *filename)
|
||||
@@ -341,6 +348,7 @@ void vfs_config_load(struct vfs_config *cfg, const wchar_t *filename)
|
||||
assert(filename != NULL);
|
||||
|
||||
cfg->enable = GetPrivateProfileIntW(L"vfs", L"enable", 1, filename);
|
||||
cfg->allowAmfsDownloads = GetPrivateProfileIntW(L"vfs", L"allowAmfsDownloads", 0, filename);
|
||||
|
||||
GetPrivateProfileStringW(
|
||||
L"vfs",
|
||||
|
||||
@@ -177,15 +177,15 @@ HRESULT dns_platform_hook_init(const struct dns_config *cfg)
|
||||
return hr;
|
||||
}
|
||||
|
||||
// Disable api/polling to the original servers
|
||||
// ABaaS log server, receives system and error logs stored in appdata
|
||||
|
||||
hr = dns_hook_push(L"*.amlog.sys-all.net", NULL);
|
||||
hr = dns_hook_push(L"*.amlog.sys-all.net", cfg->startup);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = dns_hook_push(L"*.d-amlog.sys-all.net", NULL);
|
||||
hr = dns_hook_push(L"*.d-amlog.sys-all.net", cfg->startup);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
|
||||
+102
-2
@@ -12,6 +12,8 @@
|
||||
|
||||
#include "platform/misc.h"
|
||||
|
||||
#include <shlwapi.h>
|
||||
|
||||
#include "util/dprintf.h"
|
||||
|
||||
static BOOL WINAPI misc_ExitWindowsEx(unsigned int flags, uint32_t reason);
|
||||
@@ -22,6 +24,11 @@ static HRESULT misc_read_cpu_temp_error(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_cpu_temp_warning(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_platform_id(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_platform_name(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_main_nic(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_extend_nic(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_downloadui_done(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_read_next_process(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT misc_write_next_process(const void *bytes, uint32_t nbytes);
|
||||
|
||||
static const struct hook_symbol misc_syms[] = {
|
||||
{
|
||||
@@ -44,11 +51,12 @@ static const struct reg_hook_val misc_master_keys[] = {
|
||||
.read = misc_read_app_loader_count,
|
||||
.type = REG_DWORD,
|
||||
}, {
|
||||
/* Black-hole val, list it here so we don't get a warning msg */
|
||||
.name = L"NextProcess",
|
||||
.read = misc_read_next_process,
|
||||
.write = misc_write_next_process,
|
||||
.type = REG_SZ,
|
||||
}, {
|
||||
/* ditto */
|
||||
/* Black-hole val for reading, list it here so we don't get a warning msg */
|
||||
.name = L"SystemError",
|
||||
.type = REG_SZ,
|
||||
}
|
||||
@@ -74,7 +82,28 @@ static const struct reg_hook_val misc_static_keys[] = {
|
||||
}
|
||||
};
|
||||
|
||||
static const struct reg_hook_val misc_wireless_keys[] = {
|
||||
{
|
||||
.name = L"main_nic",
|
||||
.read = misc_read_main_nic,
|
||||
.type = REG_DWORD,
|
||||
}, {
|
||||
.name = L"extend_nic",
|
||||
.read = misc_read_extend_nic,
|
||||
.type = REG_DWORD,
|
||||
}
|
||||
};
|
||||
|
||||
static const struct reg_hook_val misc_downloadui_keys[] = {
|
||||
{
|
||||
.name = L"IsDone",
|
||||
.read = misc_read_downloadui_done,
|
||||
.type = REG_DWORD,
|
||||
},
|
||||
};
|
||||
|
||||
static wchar_t misc_platform_id[5];
|
||||
static const struct misc_config *config;
|
||||
|
||||
HRESULT misc_hook_init(const struct misc_config *cfg, const char *platform_id)
|
||||
{
|
||||
@@ -83,6 +112,8 @@ HRESULT misc_hook_init(const struct misc_config *cfg, const char *platform_id)
|
||||
assert(cfg != NULL);
|
||||
assert(platform_id != NULL && strlen(platform_id) == 4);
|
||||
|
||||
config = cfg;
|
||||
|
||||
if (!cfg->enable) {
|
||||
return S_FALSE;
|
||||
}
|
||||
@@ -124,8 +155,29 @@ HRESULT misc_hook_init(const struct misc_config *cfg, const char *platform_id)
|
||||
L"SYSTEM\\SEGA\\SystemProperty\\Master",
|
||||
misc_master_keys,
|
||||
_countof(misc_master_keys));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"SYSTEM\\SEGA\\SystemProperty\\wirelessNetwork",
|
||||
misc_wireless_keys,
|
||||
_countof(misc_wireless_keys));
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = reg_hook_push_key(
|
||||
HKEY_LOCAL_MACHINE,
|
||||
L"SYSTEM\\SEGA\\SystemProperty\\downloadui",
|
||||
misc_downloadui_keys,
|
||||
_countof(misc_downloadui_keys));
|
||||
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
@@ -136,6 +188,10 @@ HRESULT misc_hook_init(const struct misc_config *cfg, const char *platform_id)
|
||||
hook_table_apply(NULL, "user32.dll", misc_syms, _countof(misc_syms));
|
||||
}
|
||||
|
||||
if (PathFileExistsW(cfg->nextProcessFile)) {
|
||||
DeleteFileW(cfg->nextProcessFile);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@@ -175,3 +231,47 @@ static HRESULT misc_read_platform_name(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"ALLS MX2.1"); // TODO: Dynamic
|
||||
}
|
||||
|
||||
static HRESULT misc_read_main_nic(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"");
|
||||
}
|
||||
|
||||
static HRESULT misc_read_extend_nic(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"");
|
||||
}
|
||||
|
||||
static HRESULT misc_read_downloadui_done(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_u32(bytes, nbytes, 1);
|
||||
}
|
||||
|
||||
static HRESULT misc_read_next_process(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"");
|
||||
}
|
||||
|
||||
static HRESULT misc_write_next_process(const void *bytes, uint32_t nbytes)
|
||||
{
|
||||
HRESULT hr;
|
||||
DWORD dwBytesWritten;
|
||||
|
||||
wchar_t* nextProcess = malloc(nbytes);
|
||||
memcpy(nextProcess, bytes, nbytes);
|
||||
|
||||
dprintf("Misc: Next Process: %ls\n", nextProcess);
|
||||
|
||||
HANDLE hFile = CreateFileW(config->nextProcessFile, GENERIC_WRITE, FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
dprintf("Misc: Error opening %ls for writing: %x\n", config->nextProcessFile, (int) hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
WriteFile(hFile, nextProcess, nbytes, &dwBytesWritten, NULL);
|
||||
|
||||
CloseHandle(hFile);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@@ -8,6 +8,7 @@ struct misc_config {
|
||||
bool enable;
|
||||
bool allowReboot;
|
||||
bool allowMasterKeyWrite;
|
||||
wchar_t nextProcessFile[MAX_PATH];
|
||||
};
|
||||
|
||||
HRESULT misc_hook_init(const struct misc_config *cfg, const char *platform_id);
|
||||
|
||||
@@ -41,6 +41,10 @@ static HRESULT vfs_custom_path_hook(
|
||||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
size_t *count);
|
||||
static HRESULT vfs_path_hook_tmp_icf(
|
||||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
size_t *count);
|
||||
static HRESULT vfs_reg_read_amfs(void *bytes, uint32_t *nbytes);
|
||||
static HRESULT vfs_reg_read_appdata(void *bytes, uint32_t *nbytes);
|
||||
|
||||
@@ -77,6 +81,9 @@ static const size_t vfs_option_len = _countof(vfs_option) - 1;
|
||||
static const wchar_t vfs_apm3[] = L"C:\\Mount\\Apm";
|
||||
static const size_t vfs_apm3_len = _countof(vfs_apm3) - 1;
|
||||
|
||||
static const wchar_t vfs_tmp_icf[] = L"E:\\tmpIcf.icf";
|
||||
static const size_t vfs_tmp_icf_len = _countof(vfs_tmp_icf) - 1;
|
||||
|
||||
static const struct reg_hook_val vfs_reg_vals[] = {
|
||||
{
|
||||
.name = L"AMFS",
|
||||
@@ -168,6 +175,12 @@ HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id)
|
||||
vfs_fixup_path(vfs_config.option, _countof(vfs_config.option), true);
|
||||
}
|
||||
|
||||
hr = path_hook_push(vfs_path_hook_tmp_icf);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
return hr;
|
||||
}
|
||||
|
||||
hr = vfs_mkdir_rec(vfs_config.amfs);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
@@ -601,6 +614,29 @@ static HRESULT vfs_path_hook_apm(
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Block writing of E:\tmpIcf.icf to intentionally break the download process if the user has not enabled it
|
||||
static HRESULT vfs_path_hook_tmp_icf(
|
||||
const wchar_t *src,
|
||||
wchar_t *dest,
|
||||
size_t *count)
|
||||
{
|
||||
assert(src != NULL);
|
||||
assert(count != NULL);
|
||||
|
||||
/* Case-insensitive check to see if src starts with vfs_tmp_icf */
|
||||
|
||||
if (path_compare_w(src, vfs_tmp_icf, vfs_tmp_icf_len) != 0) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
if (vfs_config.allowAmfsDownloads) {
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
dprintf("Vfs: AMFS downloads are blocked\n");
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
static HRESULT vfs_reg_read_amfs(void *bytes, uint32_t *nbytes)
|
||||
{
|
||||
return reg_hook_read_wstr(bytes, nbytes, L"E:\\");
|
||||
|
||||
@@ -15,6 +15,7 @@ struct vfs_config {
|
||||
wchar_t redirections_from[MAX_REDIRECTIONS][MAX_PATH];
|
||||
int redirections_from_len[MAX_REDIRECTIONS];
|
||||
wchar_t redirections_to[MAX_REDIRECTIONS][MAX_PATH];
|
||||
bool allowAmfsDownloads;
|
||||
};
|
||||
|
||||
HRESULT vfs_hook_init(const struct vfs_config *config, const char* game_id);
|
||||
|
||||
@@ -707,6 +707,12 @@ redirection0from=\\.\COM5
|
||||
redirection0to=\\.\COM10
|
||||
```
|
||||
|
||||
### `allowAmfsDownloads`
|
||||
|
||||
Default: `0`
|
||||
|
||||
Allows network services to download arbitrary files to the AMFS directory specified above. This has security implications, do not enable this, unless you trust your server operator.
|
||||
|
||||
## `[epay]`
|
||||
|
||||
Configure Thinca Payment (E-Money) emulation and hooks.
|
||||
@@ -783,3 +789,13 @@ Allows the game to write to specific registry keys relevant for the boot process
|
||||
Default: `0`
|
||||
|
||||
Allows the game to reboot the computer. Only intended for owners of real hardware.
|
||||
|
||||
### `nextProcessFilePath`
|
||||
|
||||
Default: `DEVICE\NextProcess.txt`
|
||||
|
||||
This is a file that will be set to the content of what would be written to the `NextProcess` registry key when the game is terminated.
|
||||
|
||||
This allows whatever executed the game process to react what should happen next (System Test Mode selected, network delivery completed, ...) without requiring admin permissions.
|
||||
|
||||
The file is deleted on startup of segatools.
|
||||
Reference in New Issue
Block a user