From 3f0c21d739510c7d2130dd45293fbfac09c6cf46 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Thu, 13 Mar 2025 09:53:28 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=9B=B4=E5=A5=BD=E7=9A=84=E5=A4=84?= =?UTF-8?q?=E7=90=86=E9=94=99=E8=AF=AF=E5=9B=9E=E8=B0=83=20=E4=BF=AE?= =?UTF-8?q?=E5=A4=8D=E4=B8=80=E4=BA=9B=E5=B0=8F=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dllmain.cpp | 10 +++++++ vfs.cpp | 77 +++++++++++++++++++++++++++++++++++++++++++++++------ vfs.hpp | 1 + 3 files changed, 80 insertions(+), 8 deletions(-) diff --git a/dllmain.cpp b/dllmain.cpp index e3f2333..73faef1 100644 --- a/dllmain.cpp +++ b/dllmain.cpp @@ -17,6 +17,7 @@ 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(SetFilePointerEx) *TrueSetFilePointerEx = SetFilePointerEx; static decltype(GetFileType) *TrueGetFileType = GetFileType; static decltype(GetFileAttributesW) *TrueGetFileAttributesW = GetFileAttributesW; static decltype(GetFileAttributesExW) *TrueGetFileAttributesExW = GetFileAttributesExW; @@ -147,6 +148,13 @@ DWORD WINAPI HookedSetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDi 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; @@ -193,6 +201,7 @@ extern "C" __declspec(dllexport) void Attach() { DetourAttach(&TrueGetFileSize, HookedGetFileSize); DetourAttach(&TrueGetFileSizeEx, HookedGetFileSizeEx); DetourAttach(&TrueSetFilePointer, HookedSetFilePointer); + DetourAttach(&TrueSetFilePointerEx, HookedSetFilePointerEx); DetourAttach(&TrueGetFileType, HookedGetFileType); DetourAttach(&TrueGetFileAttributesW, HookedGetFileAttributesW); DetourAttach(&TrueGetFileAttributesExW, HookedGetFileAttributesExW); @@ -222,6 +231,7 @@ extern "C" __declspec(dllexport) void Detach() { DetourDetach(&TrueGetFileSize, HookedGetFileSize); DetourDetach(&TrueGetFileSizeEx, HookedGetFileSizeEx); DetourDetach(&TrueSetFilePointer, HookedSetFilePointer); + DetourDetach(&TrueSetFilePointerEx, HookedSetFilePointerEx); DetourDetach(&TrueGetFileType, HookedGetFileType); DetourDetach(&TrueGetFileAttributesW, HookedGetFileAttributesW); DetourDetach(&TrueGetFileAttributesExW, HookedGetFileAttributesExW); diff --git a/vfs.cpp b/vfs.cpp index 12780bd..cfc3367 100644 --- a/vfs.cpp +++ b/vfs.cpp @@ -5,6 +5,33 @@ #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() { WCHAR exePath[MAX_PATH]; GetModuleFileNameW(NULL, exePath, MAX_PATH); @@ -31,7 +58,7 @@ VFS::~VFS() { bool VFS::AddArchive(std::string path) { zip_t* archive = zip_open(path.c_str(), ZIP_RDONLY, nullptr); if (!archive) return false; - archives.push_back(archive); + 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; @@ -63,7 +90,7 @@ bool VFS::AddArchiveFromResource(HMODULE hModule, int resourceID) { } zip_t* archive = zip_open_from_source(re, ZIP_RDONLY, nullptr); if (!archive) return false; - archives.push_back(archive); + 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; @@ -168,7 +195,7 @@ bool VFS::ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LP } zip_int64_t n = zip_fread(file, lpBuffer, nNumberOfBytesToRead); if (n == -1) { - SetLastError(ERROR_INVALID_HANDLE); + SetLastError(mapZipError(file)); return false; } if (lpNumberOfBytesRead) { @@ -210,8 +237,7 @@ BOOL VFS::GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize) { auto data = *f; auto name = data.second; auto size = files[name].size; - lpFileSize->LowPart = size & 0xFFFFFFFF; - lpFileSize->HighPart = size >> 32; + lpFileSize->QuadPart = size; return TRUE; } @@ -229,14 +255,49 @@ DWORD VFS::SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceTo if (lpDistanceToMoveHigh) { offset |= ((zip_int64_t)*lpDistanceToMoveHigh) << 32; } - zip_int64_t n = zip_fseek(file, offset, dwMoveMethod); - if (n == -1) { - SetLastError(ERROR_INVALID_HANDLE); + zip_int8_t code = zip_fseek(file, offset, dwMoveMethod); + if (code == -1) { + SetLastError(mapZipError(file)); 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; } +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() { return base_path; } diff --git a/vfs.hpp b/vfs.hpp index f6ff2c2..13c4360 100644 --- a/vfs.hpp +++ b/vfs.hpp @@ -44,6 +44,7 @@ class VFS { DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh); BOOL GetFileSizeEx(HANDLE hFile, PLARGE_INTEGER lpFileSize); DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod); + BOOL SetFilePointerEx(HANDLE hFile, LARGE_INTEGER liDistanceToMove, PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod); std::unordered_map files; std::string GetBasePath(); private: