Files
jeweha_patch/dllmain.cpp

243 lines
10 KiB
C++

#include <Windows.h>
#include "config.hpp"
#include "detours.h"
#include <stdio.h>
#include "wchar_util.h"
#include "vfs.hpp"
#include "str_util.h"
#include "fileop.h"
#include <fcntl.h>
#include "string_replace_file.hpp"
static HFONT(WINAPI *TrueCreateFontW)(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCWSTR lpFaceName) = CreateFontW;
static HFONT(WINAPI *TrueCreateFontA)(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCSTR lpFaceName) = CreateFontA;
static HANDLE(WINAPI *TrueCreateFileW)(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) = CreateFileW;
static BOOL(WINAPI *TrueReadFile)(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) = ReadFile;
static BOOL(WINAPI *TrueCloseHandle)(HANDLE hObject) = CloseHandle;
static DWORD(WINAPI *TrueGetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh) = GetFileSize;
static decltype(GetFileSizeEx) *TrueGetFileSizeEx = GetFileSizeEx;
static DWORD(WINAPI *TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) = SetFilePointer;
static decltype(GetFileType) *TrueGetFileType = GetFileType;
static decltype(GetFileAttributesW) *TrueGetFileAttributesW = GetFileAttributesW;
static decltype(GetFileAttributesExW) *TrueGetFileAttributesExW = GetFileAttributesExW;
static Config config;
static std::wstring defaultFont;
static VFS vfs;
static StringReplaceFile replaceFile;
static HMODULE hDll = NULL;
char* to_utf8(char* target, const char* source, UINT cp) {
int count = MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, source, -1, NULL, 0);
if (!count) return nullptr;
WCHAR* ws = new WCHAR[count + 1];
MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, source, -1, ws, count);
char* result = nullptr;
int ncount = WideCharToMultiByte(CP_UTF8, 0, ws, -1, nullptr, 0, nullptr, nullptr);
if (ncount) {
if (!target) {
target = new char[ncount + 1];
}
result = target;
WideCharToMultiByte(CP_UTF8, 0, ws, -1, result, ncount, nullptr, nullptr);
}
delete[] ws;
return result;
}
char* jis_to_utf8(char* target, const char* source) {
char* result = to_utf8(target, source, CP_UTF8);
if (!result) {
result = to_utf8(target, source, 932);
}
if (!replaceFile.messages.empty() && result) {
std::string str(result);
auto re = replaceFile.messages.find(str);
if (re != replaceFile.messages.end()) {
str = (*re).second;
if (target) {
strcpy(target, str.c_str());
result = target;
} else {
delete[] result;
result = new char[str.size() + 1];
strcpy(result, str.c_str());
}
}
}
return result;
}
PVOID GetHandle() {
HMODULE hModule = GetModuleHandleA(NULL);
return (char*)hModule + 0xa3f60;
}
static PVOID h = nullptr;
HFONT WINAPI HookedCreateFontW(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCWSTR lpFaceName) {
std::wstring name(lpFaceName);
if (name == L"MS Gothic" || name == L"MS ゴシック") {
lpFaceName = defaultFont.c_str();
}
return TrueCreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, dwItalic, dwUnderline, dwStrikeOut, dwCharSet, dwOutPrecision, dwClipPrecision, dwQuality, dwPitchAndFamily, lpFaceName);
}
HFONT WINAPI HookedCreateFontA(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCSTR lpFaceName) {
UINT cp[] = { CP_UTF8, CP_OEMCP, CP_ACP, 932 };
std::wstring font;
for (int i = 0; i < 4; i++) {
if (wchar_util::str_to_wstr(font, lpFaceName, cp[i])) {
if (font == L"MS Gothic" || font == L"MS ゴシック") {
font = defaultFont;
}
return TrueCreateFontW(nHeight, nWidth, nEscapement, nOrientation, fnWeight, dwItalic, dwUnderline, dwStrikeOut, dwCharSet, dwOutPrecision, dwClipPrecision, dwQuality, dwPitchAndFamily, font.c_str());
}
}
if (!strcmp(lpFaceName, "MS Gothic")) {
lpFaceName = "Microsoft YaHei";
}
return TrueCreateFontA(nHeight, nWidth, nEscapement, nOrientation, fnWeight, dwItalic, dwUnderline, dwStrikeOut, dwCharSet, dwOutPrecision, dwClipPrecision, dwQuality, dwPitchAndFamily, lpFaceName);
}
HANDLE WINAPI HookedCreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile) {
if (vfs.ContainsFile(lpFileName)) {
return vfs.CreateFileW(lpFileName);
}
return TrueCreateFileW(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
}
BOOL WINAPI HookedReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) {
if (vfs.ContainsHandle(hFile)) {
if (lpOverlapped) {
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return vfs.ReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead);
}
return TrueReadFile(hFile, lpBuffer, nNumberOfBytesToRead, lpNumberOfBytesRead, lpOverlapped);
}
BOOL WINAPI HookedCloseHandle(HANDLE hObject) {
if (vfs.ContainsHandle(hObject)) {
vfs.CloseHandle(hObject);
return TRUE;
}
return TrueCloseHandle(hObject);
}
DWORD WINAPI HookedGetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
if (vfs.ContainsHandle(hFile)) {
return vfs.GetFileSize(hFile, lpFileSizeHigh);
}
return TrueGetFileSize(hFile, lpFileSizeHigh);
}
BOOL WINAPI HookedGetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
if (vfs.ContainsHandle(hFile)) {
return vfs.GetFileSizeEx(hFile, lpFileSize);
}
return TrueGetFileSizeEx(hFile, lpFileSize);
}
DWORD WINAPI HookedSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) {
if (vfs.ContainsHandle(hFile)) {
return vfs.SetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
}
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
}
DWORD WINAPI HookedGetFileType(HANDLE hFile) {
if (vfs.ContainsHandle(hFile)) {
return FILE_TYPE_DISK;
}
return TrueGetFileType(hFile);
}
DWORD WINAPI HookedGetFileAttributesW(LPCWSTR lpFileName) {
if (vfs.ContainsFile(lpFileName)) {
return FILE_ATTRIBUTE_READONLY;
}
return TrueGetFileAttributesW(lpFileName);
}
BOOL WINAPI HookedGetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation) {
if (vfs.ContainsFile(lpFileName)) {
return vfs.GetFileAttributesExW(lpFileName, fInfoLevelId, lpFileInformation);
}
return TrueGetFileAttributesExW(lpFileName, fInfoLevelId, lpFileInformation);
}
extern "C" __declspec(dllexport) void Attach() {
config.Load("config.txt");
if (!wchar_util::str_to_wstr(defaultFont, config.configs["defaultFont"], CP_UTF8)) {
defaultFont = L"微软雅黑";
}
if (defaultFont.empty()) {
defaultFont = L"微软雅黑";
}
vfs.AddArchiveFromResourceWithErrorMsg(hDll, 114514);
vfs.AddArchiveWithErrorMsg("evimage.xp3");
vfs.AddArchiveWithErrorMsg("scn.xp3");
vfs.AddArchiveWithErrorMsg("uipsd.xp3");
vfs.AddArchiveWithErrorMsg("video.xp3");
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
h = GetHandle();
// DetourAttach(&h, (PVOID)jis_to_utf8);
DetourAttach(&TrueCreateFontW, HookedCreateFontW);
DetourAttach(&TrueCreateFontA, HookedCreateFontA);
DetourAttach(&TrueCreateFileW, HookedCreateFileW);
DetourAttach(&TrueReadFile, HookedReadFile);
DetourAttach(&TrueCloseHandle, HookedCloseHandle);
DetourAttach(&TrueGetFileSize, HookedGetFileSize);
DetourAttach(&TrueGetFileSizeEx, HookedGetFileSizeEx);
DetourAttach(&TrueSetFilePointer, HookedSetFilePointer);
DetourAttach(&TrueGetFileType, HookedGetFileType);
DetourAttach(&TrueGetFileAttributesW, HookedGetFileAttributesW);
DetourAttach(&TrueGetFileAttributesExW, HookedGetFileAttributesExW);
DetourTransactionCommit();
std::string stringReplaceFile = config.configs["stringReplaceFile"];
if (!stringReplaceFile.empty()) {
if (!replaceFile.Load(stringReplaceFile)) {
MessageBoxW(NULL, L"无法加载文本替换文件。", L"错误", MB_ICONERROR);
}
}
#if _DEBUG
while( !::IsDebuggerPresent() )
::Sleep( 1000 );
#endif
}
extern "C" __declspec(dllexport) void Detach() {
if (!h) return;
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
// DetourDetach(&h, (PVOID)jis_to_utf8);
DetourDetach(&TrueCreateFontW, HookedCreateFontW);
DetourDetach(&TrueCreateFontA, HookedCreateFontA);
DetourDetach(&TrueCreateFileW, HookedCreateFileW);
DetourDetach(&TrueReadFile, HookedReadFile);
DetourDetach(&TrueCloseHandle, HookedCloseHandle);
DetourDetach(&TrueGetFileSize, HookedGetFileSize);
DetourDetach(&TrueGetFileSizeEx, HookedGetFileSizeEx);
DetourDetach(&TrueSetFilePointer, HookedSetFilePointer);
DetourDetach(&TrueGetFileType, HookedGetFileType);
DetourDetach(&TrueGetFileAttributesW, HookedGetFileAttributesW);
DetourDetach(&TrueGetFileAttributesExW, HookedGetFileAttributesExW);
DetourTransactionCommit();
}
BOOL APIENTRY DllMain(HMODULE hModule, DWORD reason, LPVOID rev) {
switch (reason) {
case DLL_PROCESS_ATTACH:
hDll = hModule;
Attach();
break;
case DLL_PROCESS_DETACH:
Detach();
break;
}
return TRUE;
}