从 jeweha patch 移植
This commit is contained in:
46
dllmain.cpp
46
dllmain.cpp
@@ -17,6 +17,10 @@ static BOOL(WINAPI *TrueCloseHandle)(HANDLE hObject) = CloseHandle;
|
|||||||
static DWORD(WINAPI *TrueGetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh) = GetFileSize;
|
static DWORD(WINAPI *TrueGetFileSize)(HANDLE hFile, LPDWORD lpFileSizeHigh) = GetFileSize;
|
||||||
static decltype(GetFileSizeEx) *TrueGetFileSizeEx = GetFileSizeEx;
|
static decltype(GetFileSizeEx) *TrueGetFileSizeEx = GetFileSizeEx;
|
||||||
static DWORD(WINAPI *TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) = SetFilePointer;
|
static DWORD(WINAPI *TrueSetFilePointer)(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) = SetFilePointer;
|
||||||
|
static decltype(SetFilePointerEx) *TrueSetFilePointerEx = SetFilePointerEx;
|
||||||
|
static decltype(GetFileType) *TrueGetFileType = GetFileType;
|
||||||
|
static decltype(GetFileAttributesW) *TrueGetFileAttributesW = GetFileAttributesW;
|
||||||
|
static decltype(GetFileAttributesExW) *TrueGetFileAttributesExW = GetFileAttributesExW;
|
||||||
|
|
||||||
static Config config;
|
static Config config;
|
||||||
static std::wstring defaultFont;
|
static std::wstring defaultFont;
|
||||||
@@ -143,6 +147,34 @@ DWORD WINAPI HookedSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDi
|
|||||||
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
return TrueSetFilePointer(hFile, lDistanceToMove, lpDistanceToMoveHigh, dwMoveMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL WINAPI HookedSetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
|
||||||
|
if (vfs.ContainsHandle(hFile)) {
|
||||||
|
return vfs.SetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, dwMoveMethod);
|
||||||
|
}
|
||||||
|
return TrueSetFilePointerEx(hFile, liDistanceToMove, lpNewFilePointer, 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() {
|
extern "C" __declspec(dllexport) void Attach() {
|
||||||
config.Load("config.txt");
|
config.Load("config.txt");
|
||||||
if (!wchar_util::str_to_wstr(defaultFont, config.configs["defaultFont"], CP_UTF8)) {
|
if (!wchar_util::str_to_wstr(defaultFont, config.configs["defaultFont"], CP_UTF8)) {
|
||||||
@@ -151,11 +183,7 @@ extern "C" __declspec(dllexport) void Attach() {
|
|||||||
if (defaultFont.empty()) {
|
if (defaultFont.empty()) {
|
||||||
defaultFont = L"微软雅黑";
|
defaultFont = L"微软雅黑";
|
||||||
}
|
}
|
||||||
if (!vfs.AddArchive("jewena-chs.dat")) {
|
vfs.AddArchiveWithErrorMsg("jewena-chs.dat");
|
||||||
MessageBoxW(NULL, L"无法打开 jewena-chs.dat。请检查文件是否存在", L"错误", MB_ICONERROR);
|
|
||||||
ExitProcess(1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
DetourTransactionBegin();
|
DetourTransactionBegin();
|
||||||
DetourUpdateThread(GetCurrentThread());
|
DetourUpdateThread(GetCurrentThread());
|
||||||
h = GetHandle();
|
h = GetHandle();
|
||||||
@@ -168,6 +196,10 @@ extern "C" __declspec(dllexport) void Attach() {
|
|||||||
DetourAttach(&TrueGetFileSize, HookedGetFileSize);
|
DetourAttach(&TrueGetFileSize, HookedGetFileSize);
|
||||||
DetourAttach(&TrueGetFileSizeEx, HookedGetFileSizeEx);
|
DetourAttach(&TrueGetFileSizeEx, HookedGetFileSizeEx);
|
||||||
DetourAttach(&TrueSetFilePointer, HookedSetFilePointer);
|
DetourAttach(&TrueSetFilePointer, HookedSetFilePointer);
|
||||||
|
DetourAttach(&TrueSetFilePointerEx, HookedSetFilePointerEx);
|
||||||
|
DetourAttach(&TrueGetFileType, HookedGetFileType);
|
||||||
|
DetourAttach(&TrueGetFileAttributesW, HookedGetFileAttributesW);
|
||||||
|
DetourAttach(&TrueGetFileAttributesExW, HookedGetFileAttributesExW);
|
||||||
DetourTransactionCommit();
|
DetourTransactionCommit();
|
||||||
std::string stringReplaceFile = config.configs["stringReplaceFile"];
|
std::string stringReplaceFile = config.configs["stringReplaceFile"];
|
||||||
if (!stringReplaceFile.empty()) {
|
if (!stringReplaceFile.empty()) {
|
||||||
@@ -194,6 +226,10 @@ extern "C" __declspec(dllexport) void Detach() {
|
|||||||
DetourDetach(&TrueGetFileSize, HookedGetFileSize);
|
DetourDetach(&TrueGetFileSize, HookedGetFileSize);
|
||||||
DetourDetach(&TrueGetFileSizeEx, HookedGetFileSizeEx);
|
DetourDetach(&TrueGetFileSizeEx, HookedGetFileSizeEx);
|
||||||
DetourDetach(&TrueSetFilePointer, HookedSetFilePointer);
|
DetourDetach(&TrueSetFilePointer, HookedSetFilePointer);
|
||||||
|
DetourDetach(&TrueSetFilePointerEx, HookedSetFilePointerEx);
|
||||||
|
DetourDetach(&TrueGetFileType, HookedGetFileType);
|
||||||
|
DetourDetach(&TrueGetFileAttributesW, HookedGetFileAttributesW);
|
||||||
|
DetourDetach(&TrueGetFileAttributesExW, HookedGetFileAttributesExW);
|
||||||
DetourTransactionCommit();
|
DetourTransactionCommit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
171
vfs.cpp
171
vfs.cpp
@@ -3,6 +3,34 @@
|
|||||||
#include "str_util.h"
|
#include "str_util.h"
|
||||||
#include "fileop.h"
|
#include "fileop.h"
|
||||||
#include "shlwapi.h"
|
#include "shlwapi.h"
|
||||||
|
#include "time_util.h"
|
||||||
|
|
||||||
|
DWORD mapZipError(zip_file_t* file) {
|
||||||
|
auto error = zip_file_get_error(file);
|
||||||
|
if (error) {
|
||||||
|
switch (error->zip_err) {
|
||||||
|
case ZIP_ER_EOF:
|
||||||
|
return ERROR_HANDLE_EOF;
|
||||||
|
case ZIP_ER_INVAL:
|
||||||
|
return ERROR_INVALID_PARAMETER;
|
||||||
|
case ZIP_ER_SEEK:
|
||||||
|
return ERROR_SEEK;
|
||||||
|
case ZIP_ER_READ:
|
||||||
|
return ERROR_READ_FAULT;
|
||||||
|
case ZIP_ER_CRC:
|
||||||
|
return ERROR_CRC;
|
||||||
|
case ZIP_ER_ZIPCLOSED:
|
||||||
|
return ERROR_INVALID_HANDLE;
|
||||||
|
case ZIP_ER_NOENT:
|
||||||
|
return ERROR_FILE_NOT_FOUND;
|
||||||
|
case ZIP_ER_EXISTS:
|
||||||
|
return ERROR_FILE_EXISTS;
|
||||||
|
case ZIP_ER_OPEN:
|
||||||
|
return ERROR_OPEN_FAILED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ERROR_INVALID_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
VFS::VFS() {
|
VFS::VFS() {
|
||||||
WCHAR exePath[MAX_PATH];
|
WCHAR exePath[MAX_PATH];
|
||||||
@@ -30,7 +58,7 @@ VFS::~VFS() {
|
|||||||
bool VFS::AddArchive(std::string path) {
|
bool VFS::AddArchive(std::string path) {
|
||||||
zip_t* archive = zip_open(path.c_str(), ZIP_RDONLY, nullptr);
|
zip_t* archive = zip_open(path.c_str(), ZIP_RDONLY, nullptr);
|
||||||
if (!archive) return false;
|
if (!archive) return false;
|
||||||
archives.push_back(archive);
|
archives.push_front(archive);
|
||||||
auto len = zip_get_num_entries(archive, 0);
|
auto len = zip_get_num_entries(archive, 0);
|
||||||
for (zip_int64_t i = 0; i < len; i++) {
|
for (zip_int64_t i = 0; i < len; i++) {
|
||||||
struct zip_stat st;
|
struct zip_stat st;
|
||||||
@@ -42,11 +70,66 @@ bool VFS::AddArchive(std::string path) {
|
|||||||
}
|
}
|
||||||
std::string name = st.name;
|
std::string name = st.name;
|
||||||
name = str_util::str_replace(name, "/", "\\");
|
name = str_util::str_replace(name, "/", "\\");
|
||||||
files[name] = st.size;
|
files[name] = st;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VFS::AddArchiveFromResource(HMODULE hModule, int resourceID) {
|
||||||
|
HRSRC hResInfo = FindResource(hModule, MAKEINTRESOURCE(resourceID), RT_RCDATA);
|
||||||
|
if (!hResInfo) return false;
|
||||||
|
HGLOBAL hResData = LoadResource(hModule, hResInfo);
|
||||||
|
if (!hResData) return false;
|
||||||
|
LPVOID lpResData = LockResource(hResData);
|
||||||
|
if (!lpResData) return false;
|
||||||
|
DWORD dwSize = SizeofResource(hModule, hResInfo);
|
||||||
|
if (!dwSize) return false;
|
||||||
|
auto re = zip_source_buffer_create(lpResData, dwSize, 0, nullptr);
|
||||||
|
if (!re) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
zip_t* archive = zip_open_from_source(re, ZIP_RDONLY, nullptr);
|
||||||
|
if (!archive) return false;
|
||||||
|
archives.push_front(archive);
|
||||||
|
auto len = zip_get_num_entries(archive, 0);
|
||||||
|
for (zip_int64_t i = 0; i < len; i++) {
|
||||||
|
struct zip_stat st;
|
||||||
|
zip_stat_init(&st);
|
||||||
|
zip_stat_index(archive, i, 0, &st);
|
||||||
|
// Skip directories/folders (directory entries usually end with a '/')
|
||||||
|
if (st.name[strlen(st.name) - 1] == '/') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string name = st.name;
|
||||||
|
name = str_util::str_replace(name, "/", "\\");
|
||||||
|
files[name] = st;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFS::AddArchiveWithErrorMsg(std::string path) {
|
||||||
|
if (!AddArchive(path)) {
|
||||||
|
std::wstring wpath;
|
||||||
|
if (!wchar_util::str_to_wstr(wpath, path, CP_UTF8)) {
|
||||||
|
MessageBoxW(NULL, L"无法打开资源文件。请检查资源文件是否完整", L"错误", MB_ICONERROR);
|
||||||
|
ExitProcess(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::wstring wmsg = L"无法打开 " + wpath + L"。请检查文件是否存在";
|
||||||
|
MessageBoxW(NULL, wmsg.c_str(), L"错误", MB_ICONERROR);
|
||||||
|
ExitProcess(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VFS::AddArchiveFromResourceWithErrorMsg(HMODULE hModule, int resourceID) {
|
||||||
|
if (!AddArchiveFromResource(hModule, resourceID)) {
|
||||||
|
MessageBoxW(NULL, L"无法打开内置的资源文件。", L"错误", MB_ICONERROR);
|
||||||
|
ExitProcess(1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool VFS::ContainsFile(std::string path) {
|
bool VFS::ContainsFile(std::string path) {
|
||||||
path = str_util::str_replace(path, "/", "\\");
|
path = str_util::str_replace(path, "/", "\\");
|
||||||
if (fileop::isabs(path)) {
|
if (fileop::isabs(path)) {
|
||||||
@@ -112,7 +195,7 @@ bool VFS::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LP
|
|||||||
}
|
}
|
||||||
zip_int64_t n = zip_fread(file, lpBuffer, nNumberOfBytesToRead);
|
zip_int64_t n = zip_fread(file, lpBuffer, nNumberOfBytesToRead);
|
||||||
if (n == -1) {
|
if (n == -1) {
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(mapZipError(file));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (lpNumberOfBytesRead) {
|
if (lpNumberOfBytesRead) {
|
||||||
@@ -138,7 +221,7 @@ DWORD VFS::GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) {
|
|||||||
}
|
}
|
||||||
auto data = *f;
|
auto data = *f;
|
||||||
auto name = data.second;
|
auto name = data.second;
|
||||||
auto size = files[name];
|
auto size = files[name].size;
|
||||||
if (lpFileSizeHigh) {
|
if (lpFileSizeHigh) {
|
||||||
*lpFileSizeHigh = size >> 32;
|
*lpFileSizeHigh = size >> 32;
|
||||||
}
|
}
|
||||||
@@ -153,9 +236,8 @@ BOOL VFS::GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) {
|
|||||||
}
|
}
|
||||||
auto data = *f;
|
auto data = *f;
|
||||||
auto name = data.second;
|
auto name = data.second;
|
||||||
auto size = files[name];
|
auto size = files[name].size;
|
||||||
lpFileSize->LowPart = size & 0xFFFFFFFF;
|
lpFileSize->QuadPart = size;
|
||||||
lpFileSize->HighPart = size >> 32;
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -173,14 +255,83 @@ DWORD VFS::SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceTo
|
|||||||
if (lpDistanceToMoveHigh) {
|
if (lpDistanceToMoveHigh) {
|
||||||
offset |= ((zip_int64_t)*lpDistanceToMoveHigh) << 32;
|
offset |= ((zip_int64_t)*lpDistanceToMoveHigh) << 32;
|
||||||
}
|
}
|
||||||
zip_int64_t n = zip_fseek(file, offset, dwMoveMethod);
|
zip_int8_t code = zip_fseek(file, offset, dwMoveMethod);
|
||||||
if (n == -1) {
|
if (code == -1) {
|
||||||
SetLastError(ERROR_INVALID_HANDLE);
|
SetLastError(mapZipError(file));
|
||||||
return INVALID_SET_FILE_POINTER;
|
return INVALID_SET_FILE_POINTER;
|
||||||
}
|
}
|
||||||
|
zip_int64_t n = zip_ftell(file);
|
||||||
|
if (n == -1) {
|
||||||
|
SetLastError(mapZipError(file));
|
||||||
|
return INVALID_SET_FILE_POINTER;
|
||||||
|
}
|
||||||
|
if (lpDistanceToMoveHigh) {
|
||||||
|
*lpDistanceToMoveHigh = n >> 32;
|
||||||
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL VFS::SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod) {
|
||||||
|
if (!ContainsHandle(hFile)) {
|
||||||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
zip_file_t* file = (zip_file_t*)hFile;
|
||||||
|
if (!file) {
|
||||||
|
SetLastError(ERROR_INVALID_HANDLE);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
zip_int64_t offset = liDistanceToMove.QuadPart;
|
||||||
|
zip_int8_t code = zip_fseek(file, offset, dwMoveMethod);
|
||||||
|
if (code == -1) {
|
||||||
|
SetLastError(mapZipError(file));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
zip_int64_t n = zip_ftell(file);
|
||||||
|
if (n == -1) {
|
||||||
|
SetLastError(mapZipError(file));
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (lpNewFilePointer) {
|
||||||
|
lpNewFilePointer->QuadPart = n;
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
std::string VFS::GetBasePath() {
|
std::string VFS::GetBasePath() {
|
||||||
return base_path;
|
return base_path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOL VFS::GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation) {
|
||||||
|
std::string path;
|
||||||
|
if (!wchar_util::wstr_to_str(path, lpFileName, CP_UTF8)) {
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
path = str_util::str_replace(path, "/", "\\");
|
||||||
|
if (fileop::isabs(path)) {
|
||||||
|
path = fileop::relpath(path, base_path);
|
||||||
|
}
|
||||||
|
auto c = files.find(path);
|
||||||
|
if (c == files.end()) {
|
||||||
|
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
auto st = (*c).second;
|
||||||
|
if (fInfoLevelId == GetFileExInfoStandard) {
|
||||||
|
if (!lpFileInformation) {
|
||||||
|
SetLastError(ERROR_INVALID_PARAMETER);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
WIN32_FILE_ATTRIBUTE_DATA data;
|
||||||
|
data.dwFileAttributes = FILE_ATTRIBUTE_READONLY;
|
||||||
|
time_util::time_t_to_file_time(st.mtime, &data.ftLastWriteTime);
|
||||||
|
data.ftCreationTime = data.ftLastWriteTime;
|
||||||
|
data.ftLastAccessTime = data.ftLastWriteTime;
|
||||||
|
data.nFileSizeHigh = st.size >> 32;
|
||||||
|
data.nFileSizeLow = st.size & 0xFFFFFFFF;
|
||||||
|
memcpy(lpFileInformation, &data, sizeof(data));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|||||||
7
vfs.hpp
7
vfs.hpp
@@ -31,16 +31,21 @@ class VFS {
|
|||||||
VFS();
|
VFS();
|
||||||
~VFS();
|
~VFS();
|
||||||
bool AddArchive(std::string path);
|
bool AddArchive(std::string path);
|
||||||
|
bool AddArchiveFromResource(HMODULE hModule, int resourceID);
|
||||||
|
void AddArchiveWithErrorMsg(std::string path);
|
||||||
|
void AddArchiveFromResourceWithErrorMsg(HMODULE hModule, int resourceID);
|
||||||
bool ContainsFile(std::string path);
|
bool ContainsFile(std::string path);
|
||||||
bool ContainsFile(std::wstring path);
|
bool ContainsFile(std::wstring path);
|
||||||
bool ContainsHandle(HANDLE hFile);
|
bool ContainsHandle(HANDLE hFile);
|
||||||
HANDLE CreateFileW(std::wstring path);
|
HANDLE CreateFileW(std::wstring path);
|
||||||
bool ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead);
|
bool ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead);
|
||||||
void CloseHandle(HANDLE hFile);
|
void CloseHandle(HANDLE hFile);
|
||||||
|
BOOL GetFileAttributesExW(LPCWSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation);
|
||||||
DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
|
DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh);
|
||||||
BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize);
|
||||||
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod);
|
||||||
std::unordered_map<std::string, zip_uint64_t, CaseInsensitiveHash, CaseInsensitiveEqual> files;
|
BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod);
|
||||||
|
std::unordered_map<std::string, zip_stat_t, CaseInsensitiveHash, CaseInsensitiveEqual> files;
|
||||||
std::string GetBasePath();
|
std::string GetBasePath();
|
||||||
private:
|
private:
|
||||||
std::string base_path;
|
std::string base_path;
|
||||||
|
|||||||
Reference in New Issue
Block a user