From e2273cf39547ffd8d66f42ea68246229fdff2c81 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 20 Apr 2018 09:43:30 -0500 Subject: [PATCH 1/9] Fix logic issue with cross-drive move check --- src/usvfs_dll/hooks/kernel32.cpp | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index 65ba9844..380ca66d 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -22,7 +22,7 @@ #include namespace fs = boost::filesystem; #else -namespace fs = std::tr2::sys; +namespace fs = std::sys; #include #endif @@ -194,7 +194,7 @@ static inline WCHAR pathNameDriveLetter(LPCWSTR path) } // returns false also in case we fail to determine the drive letter of the path -static inline bool pathesOnDifferentDrives(LPCWSTR path1, LPCWSTR path2) +static inline bool pathsOnDifferentDrives(LPCWSTR path1, LPCWSTR path2) { WCHAR drive1 = pathNameDriveLetter(path1); WCHAR drive2 = pathNameDriveLetter(path2); @@ -1290,11 +1290,11 @@ BOOL WINAPI usvfs::hook_DeleteFileW(LPCWSTR lpFileName) } BOOL rewriteChangedDrives(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName, - const RerouteW& readReroute, const usvfs::CreateRerouter& writeReroute, DWORD newFlags) + const RerouteW& readReroute, const usvfs::CreateRerouter& writeReroute) { - return ((newFlags & MOVEFILE_COPY_ALLOWED) == 0 && (readReroute.wasRerouted() || writeReroute.wasRerouted()) - && pathesOnDifferentDrives(readReroute.fileName(), writeReroute.fileName()) - && !pathesOnDifferentDrives(lpExistingFileName, lpNewFileName)); + return ((readReroute.wasRerouted() || writeReroute.wasRerouted()) + && pathsOnDifferentDrives(readReroute.fileName(), writeReroute.fileName()) + && !pathsOnDifferentDrives(lpExistingFileName, lpNewFileName)); } BOOL WINAPI usvfs::hook_MoveFileA(LPCSTR lpExistingFileName, @@ -1350,13 +1350,13 @@ BOOL WINAPI usvfs::hook_MoveFileW(LPCWSTR lpExistingFileName, if (callOriginal) { - bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute, newFlags); + bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute); if (movedDrives) newFlags |= MOVEFILE_COPY_ALLOWED; bool isDirectory = pathIsDirectory(readReroute.fileName()); PRE_REALCALL - if (isDirectory && movedDrives && newFlags) { + if (isDirectory && movedDrives) { SHFILEOPSTRUCTW sf = { 0 }; sf.wFunc = FO_MOVE; sf.hwnd = 0; @@ -1468,13 +1468,12 @@ BOOL WINAPI usvfs::hook_MoveFileExW(LPCWSTR lpExistingFileName, if (callOriginal) { - bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute, newFlags); - if (movedDrives) newFlags |= MOVEFILE_COPY_ALLOWED; + bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute); bool isDirectory = pathIsDirectory(readReroute.fileName()); PRE_REALCALL - if (isDirectory && movedDrives && newFlags & MOVEFILE_COPY_ALLOWED) { + if (isDirectory && movedDrives) { SHFILEOPSTRUCTW sf = { 0 }; sf.wFunc = FO_MOVE; sf.hwnd = 0; @@ -1583,13 +1582,13 @@ BOOL WINAPI usvfs::hook_MoveFileWithProgressW(LPCWSTR lpExistingFileName, LPCWST if (callOriginal) { - bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute, newFlags); + bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute); if (movedDrives) newFlags |= MOVEFILE_COPY_ALLOWED; bool isDirectory = pathIsDirectory(readReroute.fileName()); PRE_REALCALL - if (isDirectory && movedDrives && newFlags & MOVEFILE_COPY_ALLOWED) { + if (isDirectory && movedDrives) { SHFILEOPSTRUCTW sf = { 0 }; sf.wFunc = FO_MOVE; sf.hwnd = 0; From e13a577b6b767a28803153d70d82c45b642987c5 Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 20 Apr 2018 10:08:55 -0500 Subject: [PATCH 2/9] Let's not map unrouted files --- src/usvfs_dll/hooks/kernel32.cpp | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index 380ca66d..b648f5f1 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -1392,10 +1392,11 @@ BOOL WINAPI usvfs::hook_MoveFileW(LPCWSTR lpExistingFileName, if (res) { //readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone - if (writeReroute.newReroute() && isDirectory) { - RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName())); - } else { - writeReroute.insertMapping(WRITE_CONTEXT()); + if (writeReroute.newReroute()) { + if (isDirectory) + RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName())); + else + writeReroute.insertMapping(WRITE_CONTEXT()); } } @@ -1507,10 +1508,11 @@ BOOL WINAPI usvfs::hook_MoveFileExW(LPCWSTR lpExistingFileName, if (res) { //readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone - if (writeReroute.newReroute() && isDirectory) { - RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName())); - } else { - writeReroute.insertMapping(WRITE_CONTEXT()); + if (writeReroute.newReroute()) { + if (isDirectory) + RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName())); + else + writeReroute.insertMapping(WRITE_CONTEXT()); } } @@ -1622,10 +1624,11 @@ BOOL WINAPI usvfs::hook_MoveFileWithProgressW(LPCWSTR lpExistingFileName, LPCWST if (res) { //readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone - if (writeReroute.newReroute() && isDirectory) { - RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName())); - } else { - writeReroute.insertMapping(WRITE_CONTEXT()); + if (writeReroute.newReroute()) { + if (isDirectory) + RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName())); + else + writeReroute.insertMapping(WRITE_CONTEXT()); } } From c40f665870b453f56bfa336a7175be41c0e8873a Mon Sep 17 00:00:00 2001 From: Silarn Date: Fri, 20 Apr 2018 10:09:15 -0500 Subject: [PATCH 3/9] Bump boost version --- vsbuild/external_dependencies.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vsbuild/external_dependencies.props b/vsbuild/external_dependencies.props index 96721f57..f8c26636 100644 --- a/vsbuild/external_dependencies.props +++ b/vsbuild/external_dependencies.props @@ -4,7 +4,7 @@ - ..\..\boost_1_66_0 + ..\..\boost_1_67_0 $(BOOST_PATH) ..\..\googletest From bb71ce85baf9d28d4320805c1abc8956663097e3 Mon Sep 17 00:00:00 2001 From: Silarn Date: Sat, 21 Apr 2018 15:38:19 -0500 Subject: [PATCH 4/9] Make rerouteCreate and create check the deleted files --- src/usvfs_dll/hooks/kernel32.cpp | 80 +++++++++++++++++++------------- 1 file changed, 47 insertions(+), 33 deletions(-) diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index b648f5f1..ce8555f9 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -485,28 +485,31 @@ class RerouteW const auto& lookupPath = canonizePath(absolutePath(inPath)); result.m_RealPath = lookupPath.wstring(); - const usvfs::RedirectionTreeContainer &table - = inverse ? context->inverseTable() : context->redirectionTable(); - result.m_FileNode = table->findNode(lookupPath); + result.m_Buffer = k32DeleteTracker.lookup(result.m_RealPath); + bool found = !result.m_Buffer.empty(); + if (found) + spdlog::get("hooks")->info("Rerouting file open to location of deleted file: {}", + ush::string_cast(result.m_Buffer)); + else { + const usvfs::RedirectionTreeContainer &table + = inverse ? context->inverseTable() : context->redirectionTable(); + result.m_FileNode = table->findNode(lookupPath); - if (result.m_FileNode.get() - && (!result.m_FileNode->data().linkTarget.empty() || result.m_FileNode->isDirectory())) - { - if (!result.m_FileNode->data().linkTarget.empty()) { - result.m_Buffer = string_cast( - result.m_FileNode->data().linkTarget.c_str(), CodePage::UTF8); - } - else + if (result.m_FileNode.get() + && (!result.m_FileNode->data().linkTarget.empty() || result.m_FileNode->isDirectory())) { - result.m_Buffer = result.m_FileNode->path().wstring(); + if (!result.m_FileNode->data().linkTarget.empty()) { + result.m_Buffer = string_cast( + result.m_FileNode->data().linkTarget.c_str(), CodePage::UTF8); + } + else + { + result.m_Buffer = result.m_FileNode->path().wstring(); + } + found = true; } - wchar_t inIt = inPath[wcslen(inPath) - 1]; - std::wstring::iterator outIt = result.m_Buffer.end() - 1; - if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) - result.m_Buffer.erase(outIt); - if (result.m_Buffer.length() >= MAX_PATH && !ush::startswith(result.m_Buffer.c_str(), LR"(\\?\)")) - result.m_Buffer = LR"(\\?\)" + result.m_Buffer; - std::replace(result.m_Buffer.begin(), result.m_Buffer.end(), L'/', L'\\'); + } + if (found) { result.m_Rerouted = true; } else @@ -515,6 +518,14 @@ class RerouteW else if (inPath) result.m_Buffer = inPath; + wchar_t inIt = inPath[wcslen(inPath) - 1]; + std::wstring::iterator outIt = result.m_Buffer.end() - 1; + if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) + result.m_Buffer.erase(outIt); + if (result.m_Buffer.length() >= MAX_PATH && !ush::startswith(result.m_Buffer.c_str(), LR"(\\?\)")) + result.m_Buffer = LR"(\\?\)" + result.m_Buffer; + std::replace(result.m_Buffer.begin(), result.m_Buffer.end(), L'/', L'\\'); + if (inPath) result.m_FileName = result.m_Buffer.c_str(); return result; @@ -576,10 +587,10 @@ class RerouteW else if (inPath) result.m_Buffer = inPath; std::wstring::iterator it = result.m_Buffer.end() - 1; - wchar_t inIt = inPath[wcslen(inPath) - 1]; - std::wstring::iterator outIt = result.m_Buffer.end() - 1; - if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) - result.m_Buffer.erase(outIt); + wchar_t inIt = inPath[wcslen(inPath) - 1]; + std::wstring::iterator outIt = result.m_Buffer.end() - 1; + if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) + result.m_Buffer.erase(outIt); if (inPath) result.m_FileName = result.m_Buffer.c_str(); @@ -859,14 +870,17 @@ HANDLE WINAPI usvfs::hook_CreateFileA( namespace usvfs { class CreateRerouter { public: - bool rereouteCreate(const usvfs::HookContext::ConstPtr &context, const usvfs::HookCallContext &callContext, + bool rerouteCreate(const usvfs::HookContext::ConstPtr &context, const usvfs::HookCallContext &callContext, LPCWSTR lpFileName, DWORD& dwCreationDisposition, DWORD dwDesiredAccess, LPSECURITY_ATTRIBUTES lpSecurityAttributes) { enum class Open { existing, create, empty }; Open open = Open::existing; + std::wstring finalName = k32DeleteTracker.lookup(lpFileName); + LPCWSTR finalNameCStr = finalName.size() != 0 ? finalName.c_str() : lpFileName; + // Notice since we are calling our patched GetFileAttributesW here this will also check virtualized paths - DWORD virtAttr = GetFileAttributesW(lpFileName); + DWORD virtAttr = GetFileAttributesW(finalNameCStr); m_directlyAvailable = virtAttr == INVALID_FILE_ATTRIBUTES && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND); bool isFile = virtAttr != INVALID_FILE_ATTRIBUTES && (virtAttr & FILE_ATTRIBUTE_DIRECTORY) == 0; m_isDir = virtAttr != INVALID_FILE_ATTRIBUTES && (virtAttr & FILE_ATTRIBUTE_DIRECTORY); @@ -905,8 +919,8 @@ namespace usvfs { break; } - if (m_isDir && pathIsDirectory(lpFileName)) - m_reroute = RerouteW::noReroute(lpFileName); + if (m_isDir && pathIsDirectory(finalNameCStr)) + m_reroute = RerouteW::noReroute(finalNameCStr); else m_reroute = RerouteW::create(context, callContext, lpFileName); @@ -930,7 +944,7 @@ namespace usvfs { bool rerouteNew(const usvfs::HookContext::ConstPtr &context, usvfs::HookCallContext &callContext, LPCWSTR lpFileName, bool replaceExisting, const char* hookName) { DWORD disposition = replaceExisting ? CREATE_ALWAYS : CREATE_NEW; - if (!rereouteCreate(context, callContext, lpFileName, disposition, GENERIC_WRITE, nullptr)) { + if (!rerouteCreate(context, callContext, lpFileName, disposition, GENERIC_WRITE, nullptr)) { spdlog::get("hooks")->info( "{} guaranteed failure, skipping original call: {}, replaceExisting={}, error={}", hookName, ush::string_cast(lpFileName, ush::CodePage::UTF8), replaceExisting ? "true" : "false", error()); @@ -996,7 +1010,7 @@ HANDLE WINAPI usvfs::hook_CreateFileW( DWORD originalDisposition = dwCreationDisposition; CreateRerouter rerouter; - if (rerouter.rereouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess, lpSecurityAttributes)) + if (rerouter.rerouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess, lpSecurityAttributes)) { PRE_REALCALL res = ::CreateFileW(rerouter.fileName(), dwDesiredAccess, dwShareMode, @@ -1062,7 +1076,7 @@ HANDLE WINAPI usvfs::hook_CreateFile2(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD originalDisposition = dwCreationDisposition; CreateRerouter rerouter; - if (rerouter.rereouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess, + if (rerouter.rerouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess, pCreateExParams ? pCreateExParams->lpSecurityAttributes : nullptr)) { PRE_REALCALL @@ -1390,7 +1404,7 @@ BOOL WINAPI usvfs::hook_MoveFileW(LPCWSTR lpExistingFileName, writeReroute.updateResult(callContext, res); if (res) { - //readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone + readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Updating the rerouteCreate to check deleted file entries should make this okay if (writeReroute.newReroute()) { if (isDirectory) @@ -1506,7 +1520,7 @@ BOOL WINAPI usvfs::hook_MoveFileExW(LPCWSTR lpExistingFileName, writeReroute.updateResult(callContext, res); if (res) { - //readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone + readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Updating the rerouteCreate to check deleted file entries should make this okay if (writeReroute.newReroute()) { if (isDirectory) @@ -1622,7 +1636,7 @@ BOOL WINAPI usvfs::hook_MoveFileWithProgressW(LPCWSTR lpExistingFileName, LPCWST writeReroute.updateResult(callContext, res); if (res) { - //readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone + readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Updating the rerouteCreate to check deleted file entries should make this okay if (writeReroute.newReroute()) { if (isDirectory) From b13ed2765a508ad7d756acb7958963a00e68d23d Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Mon, 23 Apr 2018 23:30:08 +0300 Subject: [PATCH 5/9] fix printing of exception information --- src/shared/exceptionex.h | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/shared/exceptionex.h b/src/shared/exceptionex.h index 52b252a3..6505e41a 100644 --- a/src/shared/exceptionex.h +++ b/src/shared/exceptionex.h @@ -64,13 +64,20 @@ typedef MyBoost::error_info ex_win_errcode; //#endif // _MSC_VER typedef MyBoost::error_info ex_msg; -struct incompatibility_error : virtual MyBoost::exception, virtual std::exception {}; -struct usage_error : virtual MyBoost::exception, virtual std::exception {}; -struct data_error : virtual MyBoost::exception, virtual std::exception {}; -struct file_not_found_error : virtual MyBoost::exception, virtual std::exception {}; -struct timeout_error : virtual MyBoost::exception, virtual std::exception {}; -struct unknown_error : virtual MyBoost::exception, virtual std::exception {}; -struct node_missing_error : virtual MyBoost::exception, virtual std::exception {}; +struct std_boost_exception : virtual MyBoost::exception, virtual std::exception +{ + const char* what() const noexcept override { + return MyBoost::diagnostic_information_what(*this); + } +}; + +struct incompatibility_error : std_boost_exception {}; +struct usage_error : std_boost_exception {}; +struct data_error : std_boost_exception {}; +struct file_not_found_error : std_boost_exception {}; +struct timeout_error : std_boost_exception {}; +struct unknown_error : std_boost_exception {}; +struct node_missing_error : std_boost_exception {}; From 3b817f017bf3acb5c4c460a863c4667a8eb5cbb9 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Tue, 24 Apr 2018 01:09:43 +0300 Subject: [PATCH 6/9] GetModuleFileNameW hook: fix for cases where buffer size is not large enough Problem originally observed when path to MO is exactly 63 chars and when usvfs itself is calling GetModuleFileNameW with a 64 byte buffer the previous code would fail (and "reroute" the directory, returning a value of 63 indicating the buffer was large enough). This fix aims to be more general and hopefully handle all cases properly. --- src/usvfs_dll/hooks/kernel32.cpp | 37 +++++++++++++++++++------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index ce8555f9..2f360480 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -1983,27 +1983,34 @@ DWORD WINAPI usvfs::hook_GetModuleFileNameW(HMODULE hModule, res = ::GetModuleFileNameW(hModule, lpFilename, nSize); POST_REALCALL if ((res != 0) && callContext.active()) { + std::vector buf; + // If GetModuleFileNameW failed because the buffer is not large enough this complicates matters + // because we are dealing with incomplete information (consider for example the case that we + // have a long real path which will be routed to a short virtual so the call should actually + // succeed in such a case). + // To solve this we simply use our own buffer to find the complete module path: + DWORD full_res = res; + size_t buf_size = nSize; + while (full_res == buf_size) { + buf_size = std::max(static_cast(MAX_PATH), buf_size * 2); + buf.resize(buf_size); + full_res = ::GetModuleFileNameW(hModule, buf.data(), buf_size); + } + RerouteW reroute - = RerouteW::create(READ_CONTEXT(), callContext, lpFilename, true); + = RerouteW::create(READ_CONTEXT(), callContext, buf.empty() ? lpFilename : buf.data(), true); if (reroute.wasRerouted()) { - DWORD reroutedSize = static_cast(reroute.buffer().size()); + DWORD reroutedSize = static_cast(wcslen(reroute.fileName())); if (reroutedSize >= nSize) { - callContext.updateLastError(ERROR_INSUFFICIENT_BUFFER); reroutedSize = nSize - 1; + callContext.updateLastError(ERROR_INSUFFICIENT_BUFFER); + res = nSize; } - // res can't be bigger than nSize-1 at this point - if (reroutedSize > 0) { - if (reroutedSize < res) { - // zero out the string windows has previously written to - memset(lpFilename, '\0', std::min(res, nSize) * sizeof(wchar_t)); - } - // this truncates the string if the buffer is too small - ush::wcsncpy_sz(lpFilename, reroute.fileName(), reroutedSize + 1); - } - res = reroutedSize; - } + else + res = reroutedSize; + memcpy(lpFilename, reroute.fileName(), reroutedSize * sizeof(lpFilename[0])); + lpFilename[reroutedSize] = 0; - if (reroute.wasRerouted()) { LOG_CALL() .PARAM(hModule) .addParam("lpFilename", usvfs::log::Wrap( From 3f8a56621843ef3b0222443c8434077cfa185ae0 Mon Sep 17 00:00:00 2001 From: Eran Mizrahi Date: Tue, 24 Apr 2018 03:51:35 +0300 Subject: [PATCH 7/9] bump version to 0.4.0.0 and remove beta qualifier --- include/usvfs_version.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/usvfs_version.h b/include/usvfs_version.h index 99eb47bc..bc2776b8 100644 --- a/include/usvfs_version.h +++ b/include/usvfs_version.h @@ -1,12 +1,12 @@ #pragma once #define USVFS_VERSION_MAJOR 0 -#define USVFS_VERSION_MINOR 3 -#define USVFS_VERSION_BUILD 1 +#define USVFS_VERSION_MINOR 4 +#define USVFS_VERSION_BUILD 0 #define USVFS_VERSION_REVISION 0 -#define USVFS_BUILD_STRING "-beta5" -#define USVFS_BUILD_WSTRING L"-beta5" +#define USVFS_BUILD_STRING "" +#define USVFS_BUILD_WSTRING L"" #ifndef USVFS_STRINGIFY # define USVFS_STRINGIFY(x) USVFS_STRINGIFY_HELPER(x) From ffb60a5ebfc4b70291f5aa2b2ad1b46f46772027 Mon Sep 17 00:00:00 2001 From: Silarn Date: Mon, 23 Apr 2018 21:30:16 -0700 Subject: [PATCH 8/9] Fix the reroute functions if inPath is null --- src/usvfs_dll/hooks/kernel32.cpp | 43 ++++++++++++++------------------ 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index 2f360480..9442766f 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -511,6 +511,12 @@ class RerouteW } if (found) { result.m_Rerouted = true; + + wchar_t inIt = inPath[wcslen(inPath) - 1]; + std::wstring::iterator outIt = result.m_Buffer.end() - 1; + if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) + result.m_Buffer.erase(outIt); + std::replace(result.m_Buffer.begin(), result.m_Buffer.end(), L'/', L'\\'); } else result.m_Buffer = inPath; @@ -518,14 +524,6 @@ class RerouteW else if (inPath) result.m_Buffer = inPath; - wchar_t inIt = inPath[wcslen(inPath) - 1]; - std::wstring::iterator outIt = result.m_Buffer.end() - 1; - if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) - result.m_Buffer.erase(outIt); - if (result.m_Buffer.length() >= MAX_PATH && !ush::startswith(result.m_Buffer.c_str(), LR"(\\?\)")) - result.m_Buffer = LR"(\\?\)" + result.m_Buffer; - std::replace(result.m_Buffer.begin(), result.m_Buffer.end(), L'/', L'\\'); - if (inPath) result.m_FileName = result.m_Buffer.c_str(); return result; @@ -567,16 +565,22 @@ class RerouteW if (found) { - if (createPath) + if (createPath) { try { usvfs::FunctionGroupLock lock(usvfs::MutExHookGroup::ALL_GROUPS); result.m_PathCreated = createFakePath(fs::path(result.m_Buffer).parent_path(), securityAttributes); - } catch (const std::exception &e) { + } + catch (const std::exception &e) { spdlog::get("hooks")->error("failed to create {}: {}", ush::string_cast(result.m_Buffer), e.what()); } + } + wchar_t inIt = inPath[wcslen(inPath) - 1]; + std::wstring::iterator outIt = result.m_Buffer.end() - 1; + if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) + result.m_Buffer.erase(outIt); std::replace(result.m_Buffer.begin(), result.m_Buffer.end(), L'/', L'\\'); result.m_Rerouted = true; result.m_NewReroute = true; @@ -586,11 +590,6 @@ class RerouteW } else if (inPath) result.m_Buffer = inPath; - std::wstring::iterator it = result.m_Buffer.end() - 1; - wchar_t inIt = inPath[wcslen(inPath) - 1]; - std::wstring::iterator outIt = result.m_Buffer.end() - 1; - if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/')) - result.m_Buffer.erase(outIt); if (inPath) result.m_FileName = result.m_Buffer.c_str(); @@ -876,12 +875,8 @@ namespace usvfs { enum class Open { existing, create, empty }; Open open = Open::existing; - std::wstring finalName = k32DeleteTracker.lookup(lpFileName); - LPCWSTR finalNameCStr = finalName.size() != 0 ? finalName.c_str() : lpFileName; - // Notice since we are calling our patched GetFileAttributesW here this will also check virtualized paths - DWORD virtAttr = GetFileAttributesW(finalNameCStr); - m_directlyAvailable = virtAttr == INVALID_FILE_ATTRIBUTES && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND); + DWORD virtAttr = GetFileAttributesW(lpFileName); bool isFile = virtAttr != INVALID_FILE_ATTRIBUTES && (virtAttr & FILE_ATTRIBUTE_DIRECTORY) == 0; m_isDir = virtAttr != INVALID_FILE_ATTRIBUTES && (virtAttr & FILE_ATTRIBUTE_DIRECTORY); @@ -919,17 +914,17 @@ namespace usvfs { break; } - if (m_isDir && pathIsDirectory(finalNameCStr)) - m_reroute = RerouteW::noReroute(finalNameCStr); + if (m_isDir && pathIsDirectory(lpFileName)) + m_reroute = RerouteW::noReroute(lpFileName); else m_reroute = RerouteW::create(context, callContext, lpFileName); if (m_reroute.wasRerouted() && open == Open::create && pathIsDirectory(m_reroute.fileName())) - m_reroute = RerouteW::createNew(context, callContext, lpFileName, m_directlyAvailable, lpSecurityAttributes); + m_reroute = RerouteW::createNew(context, callContext, lpFileName, true, lpSecurityAttributes); if (!m_isDir && !isFile && !m_reroute.wasRerouted() && (open == Open::create || open == Open::empty)) { - m_reroute = RerouteW::createNew(context, callContext, lpFileName, m_directlyAvailable, lpSecurityAttributes); + m_reroute = RerouteW::createNew(context, callContext, lpFileName, true, lpSecurityAttributes); bool newFile = !m_reroute.wasRerouted() && pathDirectlyAvailable(m_reroute.fileName()); if (newFile && open == Open::empty) From 0e6d78899293a40b2c92347e3db50716146260f9 Mon Sep 17 00:00:00 2001 From: Silarn Date: Tue, 24 Apr 2018 14:25:33 -0700 Subject: [PATCH 9/9] Flag deleted file reroutes as 'new' so they get removed from the deleted file map --- src/usvfs_dll/hooks/kernel32.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/usvfs_dll/hooks/kernel32.cpp b/src/usvfs_dll/hooks/kernel32.cpp index 9442766f..f61ae23f 100644 --- a/src/usvfs_dll/hooks/kernel32.cpp +++ b/src/usvfs_dll/hooks/kernel32.cpp @@ -487,10 +487,11 @@ class RerouteW result.m_Buffer = k32DeleteTracker.lookup(result.m_RealPath); bool found = !result.m_Buffer.empty(); - if (found) + if (found) { spdlog::get("hooks")->info("Rerouting file open to location of deleted file: {}", ush::string_cast(result.m_Buffer)); - else { + result.m_NewReroute = true; + } else { const usvfs::RedirectionTreeContainer &table = inverse ? context->inverseTable() : context->redirectionTable(); result.m_FileNode = table->findNode(lookupPath);