Skip to content

Commit 378aa38

Browse files
authored
Merge pull request #6 from Modorganizer2/Develop
Stage for 2.1.3 release
2 parents 3fff6ac + 0e6d788 commit 378aa38

File tree

4 files changed

+110
-84
lines changed

4 files changed

+110
-84
lines changed

include/usvfs_version.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
#pragma once
22

33
#define USVFS_VERSION_MAJOR 0
4-
#define USVFS_VERSION_MINOR 3
5-
#define USVFS_VERSION_BUILD 1
4+
#define USVFS_VERSION_MINOR 4
5+
#define USVFS_VERSION_BUILD 0
66
#define USVFS_VERSION_REVISION 0
77

88
#define USVFS_BUILD_STRING ""

src/shared/exceptionex.h

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,20 @@ typedef MyBoost::error_info<struct tag_message, DWORD> ex_win_errcode;
6464
//#endif // _MSC_VER
6565
typedef MyBoost::error_info<struct tag_message, std::string> ex_msg;
6666

67-
struct incompatibility_error : virtual MyBoost::exception, virtual std::exception {};
68-
struct usage_error : virtual MyBoost::exception, virtual std::exception {};
69-
struct data_error : virtual MyBoost::exception, virtual std::exception {};
70-
struct file_not_found_error : virtual MyBoost::exception, virtual std::exception {};
71-
struct timeout_error : virtual MyBoost::exception, virtual std::exception {};
72-
struct unknown_error : virtual MyBoost::exception, virtual std::exception {};
73-
struct node_missing_error : virtual MyBoost::exception, virtual std::exception {};
67+
struct std_boost_exception : virtual MyBoost::exception, virtual std::exception
68+
{
69+
const char* what() const noexcept override {
70+
return MyBoost::diagnostic_information_what(*this);
71+
}
72+
};
73+
74+
struct incompatibility_error : std_boost_exception {};
75+
struct usage_error : std_boost_exception {};
76+
struct data_error : std_boost_exception {};
77+
struct file_not_found_error : std_boost_exception {};
78+
struct timeout_error : std_boost_exception {};
79+
struct unknown_error : std_boost_exception {};
80+
struct node_missing_error : std_boost_exception {};
7481

7582

7683

src/usvfs_dll/hooks/kernel32.cpp

Lines changed: 93 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
#include <boost/algorithm/string/predicate.hpp>
2323
namespace fs = boost::filesystem;
2424
#else
25-
namespace fs = std::tr2::sys;
25+
namespace fs = std::sys;
2626
#include <filesystem>
2727
#endif
2828

@@ -194,7 +194,7 @@ static inline WCHAR pathNameDriveLetter(LPCWSTR path)
194194
}
195195

196196
// returns false also in case we fail to determine the drive letter of the path
197-
static inline bool pathesOnDifferentDrives(LPCWSTR path1, LPCWSTR path2)
197+
static inline bool pathsOnDifferentDrives(LPCWSTR path1, LPCWSTR path2)
198198
{
199199
WCHAR drive1 = pathNameDriveLetter(path1);
200200
WCHAR drive2 = pathNameDriveLetter(path2);
@@ -485,29 +485,39 @@ class RerouteW
485485
const auto& lookupPath = canonizePath(absolutePath(inPath));
486486
result.m_RealPath = lookupPath.wstring();
487487

488-
const usvfs::RedirectionTreeContainer &table
489-
= inverse ? context->inverseTable() : context->redirectionTable();
490-
result.m_FileNode = table->findNode(lookupPath);
488+
result.m_Buffer = k32DeleteTracker.lookup(result.m_RealPath);
489+
bool found = !result.m_Buffer.empty();
490+
if (found) {
491+
spdlog::get("hooks")->info("Rerouting file open to location of deleted file: {}",
492+
ush::string_cast<std::string>(result.m_Buffer));
493+
result.m_NewReroute = true;
494+
} else {
495+
const usvfs::RedirectionTreeContainer &table
496+
= inverse ? context->inverseTable() : context->redirectionTable();
497+
result.m_FileNode = table->findNode(lookupPath);
491498

492-
if (result.m_FileNode.get()
493-
&& (!result.m_FileNode->data().linkTarget.empty() || result.m_FileNode->isDirectory()))
494-
{
495-
if (!result.m_FileNode->data().linkTarget.empty()) {
496-
result.m_Buffer = string_cast<std::wstring>(
497-
result.m_FileNode->data().linkTarget.c_str(), CodePage::UTF8);
498-
}
499-
else
499+
if (result.m_FileNode.get()
500+
&& (!result.m_FileNode->data().linkTarget.empty() || result.m_FileNode->isDirectory()))
500501
{
501-
result.m_Buffer = result.m_FileNode->path().wstring();
502+
if (!result.m_FileNode->data().linkTarget.empty()) {
503+
result.m_Buffer = string_cast<std::wstring>(
504+
result.m_FileNode->data().linkTarget.c_str(), CodePage::UTF8);
505+
}
506+
else
507+
{
508+
result.m_Buffer = result.m_FileNode->path().wstring();
509+
}
510+
found = true;
502511
}
503-
wchar_t inIt = inPath[wcslen(inPath) - 1];
512+
}
513+
if (found) {
514+
result.m_Rerouted = true;
515+
516+
wchar_t inIt = inPath[wcslen(inPath) - 1];
504517
std::wstring::iterator outIt = result.m_Buffer.end() - 1;
505518
if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/'))
506-
result.m_Buffer.erase(outIt);
507-
if (result.m_Buffer.length() >= MAX_PATH && !ush::startswith(result.m_Buffer.c_str(), LR"(\\?\)"))
508-
result.m_Buffer = LR"(\\?\)" + result.m_Buffer;
519+
result.m_Buffer.erase(outIt);
509520
std::replace(result.m_Buffer.begin(), result.m_Buffer.end(), L'/', L'\\');
510-
result.m_Rerouted = true;
511521
}
512522
else
513523
result.m_Buffer = inPath;
@@ -556,16 +566,22 @@ class RerouteW
556566

557567
if (found)
558568
{
559-
if (createPath)
569+
if (createPath) {
560570
try {
561571
usvfs::FunctionGroupLock lock(usvfs::MutExHookGroup::ALL_GROUPS);
562572
result.m_PathCreated =
563573
createFakePath(fs::path(result.m_Buffer).parent_path(), securityAttributes);
564-
} catch (const std::exception &e) {
574+
}
575+
catch (const std::exception &e) {
565576
spdlog::get("hooks")->error("failed to create {}: {}",
566577
ush::string_cast<std::string>(result.m_Buffer), e.what());
567578
}
579+
}
568580

581+
wchar_t inIt = inPath[wcslen(inPath) - 1];
582+
std::wstring::iterator outIt = result.m_Buffer.end() - 1;
583+
if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/'))
584+
result.m_Buffer.erase(outIt);
569585
std::replace(result.m_Buffer.begin(), result.m_Buffer.end(), L'/', L'\\');
570586
result.m_Rerouted = true;
571587
result.m_NewReroute = true;
@@ -575,11 +591,6 @@ class RerouteW
575591
}
576592
else if (inPath)
577593
result.m_Buffer = inPath;
578-
std::wstring::iterator it = result.m_Buffer.end() - 1;
579-
wchar_t inIt = inPath[wcslen(inPath) - 1];
580-
std::wstring::iterator outIt = result.m_Buffer.end() - 1;
581-
if ((*outIt == L'\\' || *outIt == L'/') && !(inIt == L'\\' || inIt == L'/'))
582-
result.m_Buffer.erase(outIt);
583594

584595
if (inPath)
585596
result.m_FileName = result.m_Buffer.c_str();
@@ -859,15 +870,14 @@ HANDLE WINAPI usvfs::hook_CreateFileA(
859870
namespace usvfs {
860871
class CreateRerouter {
861872
public:
862-
bool rereouteCreate(const usvfs::HookContext::ConstPtr &context, const usvfs::HookCallContext &callContext,
873+
bool rerouteCreate(const usvfs::HookContext::ConstPtr &context, const usvfs::HookCallContext &callContext,
863874
LPCWSTR lpFileName, DWORD& dwCreationDisposition, DWORD dwDesiredAccess, LPSECURITY_ATTRIBUTES lpSecurityAttributes)
864875
{
865876
enum class Open { existing, create, empty };
866877
Open open = Open::existing;
867878

868879
// Notice since we are calling our patched GetFileAttributesW here this will also check virtualized paths
869880
DWORD virtAttr = GetFileAttributesW(lpFileName);
870-
m_directlyAvailable = virtAttr == INVALID_FILE_ATTRIBUTES && (GetLastError() == ERROR_FILE_NOT_FOUND || GetLastError() == ERROR_PATH_NOT_FOUND);
871881
bool isFile = virtAttr != INVALID_FILE_ATTRIBUTES && (virtAttr & FILE_ATTRIBUTE_DIRECTORY) == 0;
872882
m_isDir = virtAttr != INVALID_FILE_ATTRIBUTES && (virtAttr & FILE_ATTRIBUTE_DIRECTORY);
873883

@@ -911,11 +921,11 @@ namespace usvfs {
911921
m_reroute = RerouteW::create(context, callContext, lpFileName);
912922

913923
if (m_reroute.wasRerouted() && open == Open::create && pathIsDirectory(m_reroute.fileName()))
914-
m_reroute = RerouteW::createNew(context, callContext, lpFileName, m_directlyAvailable, lpSecurityAttributes);
924+
m_reroute = RerouteW::createNew(context, callContext, lpFileName, true, lpSecurityAttributes);
915925

916926
if (!m_isDir && !isFile && !m_reroute.wasRerouted() && (open == Open::create || open == Open::empty))
917927
{
918-
m_reroute = RerouteW::createNew(context, callContext, lpFileName, m_directlyAvailable, lpSecurityAttributes);
928+
m_reroute = RerouteW::createNew(context, callContext, lpFileName, true, lpSecurityAttributes);
919929

920930
bool newFile = !m_reroute.wasRerouted() && pathDirectlyAvailable(m_reroute.fileName());
921931
if (newFile && open == Open::empty)
@@ -930,7 +940,7 @@ namespace usvfs {
930940
bool rerouteNew(const usvfs::HookContext::ConstPtr &context, usvfs::HookCallContext &callContext, LPCWSTR lpFileName, bool replaceExisting, const char* hookName)
931941
{
932942
DWORD disposition = replaceExisting ? CREATE_ALWAYS : CREATE_NEW;
933-
if (!rereouteCreate(context, callContext, lpFileName, disposition, GENERIC_WRITE, nullptr)) {
943+
if (!rerouteCreate(context, callContext, lpFileName, disposition, GENERIC_WRITE, nullptr)) {
934944
spdlog::get("hooks")->info(
935945
"{} guaranteed failure, skipping original call: {}, replaceExisting={}, error={}",
936946
hookName, ush::string_cast<std::string>(lpFileName, ush::CodePage::UTF8), replaceExisting ? "true" : "false", error());
@@ -996,7 +1006,7 @@ HANDLE WINAPI usvfs::hook_CreateFileW(
9961006

9971007
DWORD originalDisposition = dwCreationDisposition;
9981008
CreateRerouter rerouter;
999-
if (rerouter.rereouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess, lpSecurityAttributes))
1009+
if (rerouter.rerouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess, lpSecurityAttributes))
10001010
{
10011011
PRE_REALCALL
10021012
res = ::CreateFileW(rerouter.fileName(), dwDesiredAccess, dwShareMode,
@@ -1062,7 +1072,7 @@ HANDLE WINAPI usvfs::hook_CreateFile2(LPCWSTR lpFileName, DWORD dwDesiredAccess,
10621072

10631073
DWORD originalDisposition = dwCreationDisposition;
10641074
CreateRerouter rerouter;
1065-
if (rerouter.rereouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess,
1075+
if (rerouter.rerouteCreate(READ_CONTEXT(), callContext, lpFileName, dwCreationDisposition, dwDesiredAccess,
10661076
pCreateExParams ? pCreateExParams->lpSecurityAttributes : nullptr))
10671077
{
10681078
PRE_REALCALL
@@ -1290,11 +1300,11 @@ BOOL WINAPI usvfs::hook_DeleteFileW(LPCWSTR lpFileName)
12901300
}
12911301

12921302
BOOL rewriteChangedDrives(LPCWSTR lpExistingFileName, LPCWSTR lpNewFileName,
1293-
const RerouteW& readReroute, const usvfs::CreateRerouter& writeReroute, DWORD newFlags)
1303+
const RerouteW& readReroute, const usvfs::CreateRerouter& writeReroute)
12941304
{
1295-
return ((newFlags & MOVEFILE_COPY_ALLOWED) == 0 && (readReroute.wasRerouted() || writeReroute.wasRerouted())
1296-
&& pathesOnDifferentDrives(readReroute.fileName(), writeReroute.fileName())
1297-
&& !pathesOnDifferentDrives(lpExistingFileName, lpNewFileName));
1305+
return ((readReroute.wasRerouted() || writeReroute.wasRerouted())
1306+
&& pathsOnDifferentDrives(readReroute.fileName(), writeReroute.fileName())
1307+
&& !pathsOnDifferentDrives(lpExistingFileName, lpNewFileName));
12981308
}
12991309

13001310
BOOL WINAPI usvfs::hook_MoveFileA(LPCSTR lpExistingFileName,
@@ -1350,13 +1360,13 @@ BOOL WINAPI usvfs::hook_MoveFileW(LPCWSTR lpExistingFileName,
13501360

13511361
if (callOriginal)
13521362
{
1353-
bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute, newFlags);
1363+
bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute);
13541364
if (movedDrives) newFlags |= MOVEFILE_COPY_ALLOWED;
13551365

13561366
bool isDirectory = pathIsDirectory(readReroute.fileName());
13571367

13581368
PRE_REALCALL
1359-
if (isDirectory && movedDrives && newFlags) {
1369+
if (isDirectory && movedDrives) {
13601370
SHFILEOPSTRUCTW sf = { 0 };
13611371
sf.wFunc = FO_MOVE;
13621372
sf.hwnd = 0;
@@ -1390,12 +1400,13 @@ BOOL WINAPI usvfs::hook_MoveFileW(LPCWSTR lpExistingFileName,
13901400
writeReroute.updateResult(callContext, res);
13911401

13921402
if (res) {
1393-
//readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone
1403+
readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Updating the rerouteCreate to check deleted file entries should make this okay
13941404

1395-
if (writeReroute.newReroute() && isDirectory) {
1396-
RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName()));
1397-
} else {
1398-
writeReroute.insertMapping(WRITE_CONTEXT());
1405+
if (writeReroute.newReroute()) {
1406+
if (isDirectory)
1407+
RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName()));
1408+
else
1409+
writeReroute.insertMapping(WRITE_CONTEXT());
13991410
}
14001411
}
14011412

@@ -1468,13 +1479,12 @@ BOOL WINAPI usvfs::hook_MoveFileExW(LPCWSTR lpExistingFileName,
14681479

14691480
if (callOriginal)
14701481
{
1471-
bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute, newFlags);
1472-
if (movedDrives) newFlags |= MOVEFILE_COPY_ALLOWED;
1482+
bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute);
14731483

14741484
bool isDirectory = pathIsDirectory(readReroute.fileName());
14751485

14761486
PRE_REALCALL
1477-
if (isDirectory && movedDrives && newFlags & MOVEFILE_COPY_ALLOWED) {
1487+
if (isDirectory && movedDrives) {
14781488
SHFILEOPSTRUCTW sf = { 0 };
14791489
sf.wFunc = FO_MOVE;
14801490
sf.hwnd = 0;
@@ -1506,12 +1516,13 @@ BOOL WINAPI usvfs::hook_MoveFileExW(LPCWSTR lpExistingFileName,
15061516
writeReroute.updateResult(callContext, res);
15071517

15081518
if (res) {
1509-
//readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone
1519+
readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Updating the rerouteCreate to check deleted file entries should make this okay
15101520

1511-
if (writeReroute.newReroute() && isDirectory) {
1512-
RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName()));
1513-
} else {
1514-
writeReroute.insertMapping(WRITE_CONTEXT());
1521+
if (writeReroute.newReroute()) {
1522+
if (isDirectory)
1523+
RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName()));
1524+
else
1525+
writeReroute.insertMapping(WRITE_CONTEXT());
15151526
}
15161527
}
15171528

@@ -1583,13 +1594,13 @@ BOOL WINAPI usvfs::hook_MoveFileWithProgressW(LPCWSTR lpExistingFileName, LPCWST
15831594

15841595
if (callOriginal)
15851596
{
1586-
bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute, newFlags);
1597+
bool movedDrives = rewriteChangedDrives(lpExistingFileName, lpNewFileName, readReroute, writeReroute);
15871598
if (movedDrives) newFlags |= MOVEFILE_COPY_ALLOWED;
15881599

15891600
bool isDirectory = pathIsDirectory(readReroute.fileName());
15901601

15911602
PRE_REALCALL
1592-
if (isDirectory && movedDrives && newFlags & MOVEFILE_COPY_ALLOWED) {
1603+
if (isDirectory && movedDrives) {
15931604
SHFILEOPSTRUCTW sf = { 0 };
15941605
sf.wFunc = FO_MOVE;
15951606
sf.hwnd = 0;
@@ -1621,12 +1632,13 @@ BOOL WINAPI usvfs::hook_MoveFileWithProgressW(LPCWSTR lpExistingFileName, LPCWST
16211632
writeReroute.updateResult(callContext, res);
16221633

16231634
if (res) {
1624-
//readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Leaving a ghost fixes some problems with apps expecting the file to be gone
1635+
readReroute.removeMapping(READ_CONTEXT(), isDirectory); // Updating the rerouteCreate to check deleted file entries should make this okay
16251636

1626-
if (writeReroute.newReroute() && isDirectory) {
1627-
RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName()));
1628-
} else {
1629-
writeReroute.insertMapping(WRITE_CONTEXT());
1637+
if (writeReroute.newReroute()) {
1638+
if (isDirectory)
1639+
RerouteW::addDirectoryMapping(WRITE_CONTEXT(), fs::path(lpNewFileName), fs::path(writeReroute.fileName()));
1640+
else
1641+
writeReroute.insertMapping(WRITE_CONTEXT());
16301642
}
16311643
}
16321644

@@ -1967,27 +1979,34 @@ DWORD WINAPI usvfs::hook_GetModuleFileNameW(HMODULE hModule,
19671979
res = ::GetModuleFileNameW(hModule, lpFilename, nSize);
19681980
POST_REALCALL
19691981
if ((res != 0) && callContext.active()) {
1982+
std::vector<WCHAR> buf;
1983+
// If GetModuleFileNameW failed because the buffer is not large enough this complicates matters
1984+
// because we are dealing with incomplete information (consider for example the case that we
1985+
// have a long real path which will be routed to a short virtual so the call should actually
1986+
// succeed in such a case).
1987+
// To solve this we simply use our own buffer to find the complete module path:
1988+
DWORD full_res = res;
1989+
size_t buf_size = nSize;
1990+
while (full_res == buf_size) {
1991+
buf_size = std::max(static_cast<size_t>(MAX_PATH), buf_size * 2);
1992+
buf.resize(buf_size);
1993+
full_res = ::GetModuleFileNameW(hModule, buf.data(), buf_size);
1994+
}
1995+
19701996
RerouteW reroute
1971-
= RerouteW::create(READ_CONTEXT(), callContext, lpFilename, true);
1997+
= RerouteW::create(READ_CONTEXT(), callContext, buf.empty() ? lpFilename : buf.data(), true);
19721998
if (reroute.wasRerouted()) {
1973-
DWORD reroutedSize = static_cast<DWORD>(reroute.buffer().size());
1999+
DWORD reroutedSize = static_cast<DWORD>(wcslen(reroute.fileName()));
19742000
if (reroutedSize >= nSize) {
1975-
callContext.updateLastError(ERROR_INSUFFICIENT_BUFFER);
19762001
reroutedSize = nSize - 1;
2002+
callContext.updateLastError(ERROR_INSUFFICIENT_BUFFER);
2003+
res = nSize;
19772004
}
1978-
// res can't be bigger than nSize-1 at this point
1979-
if (reroutedSize > 0) {
1980-
if (reroutedSize < res) {
1981-
// zero out the string windows has previously written to
1982-
memset(lpFilename, '\0', std::min(res, nSize) * sizeof(wchar_t));
1983-
}
1984-
// this truncates the string if the buffer is too small
1985-
ush::wcsncpy_sz(lpFilename, reroute.fileName(), reroutedSize + 1);
1986-
}
1987-
res = reroutedSize;
1988-
}
2005+
else
2006+
res = reroutedSize;
2007+
memcpy(lpFilename, reroute.fileName(), reroutedSize * sizeof(lpFilename[0]));
2008+
lpFilename[reroutedSize] = 0;
19892009

1990-
if (reroute.wasRerouted()) {
19912010
LOG_CALL()
19922011
.PARAM(hModule)
19932012
.addParam("lpFilename", usvfs::log::Wrap<LPCWSTR>(

vsbuild/external_dependencies.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
<Import Project="external_dependencies_local.props" Condition="Exists('external_dependencies_local.props')"/>
55
</ImportGroup>
66
<PropertyGroup Label="UserMacros">
7-
<BOOST_PATH Condition="'$(BOOST_PATH)'==''">..\..\boost_1_66_0</BOOST_PATH>
7+
<BOOST_PATH Condition="'$(BOOST_PATH)'==''">..\..\boost_1_67_0</BOOST_PATH>
88
<BOOST_PATH Condition="'$(BOOST_PATH)'!=''">$(BOOST_PATH)</BOOST_PATH>
99
<GTEST_PATH Condition="'$(GTEST_PATH)'==''">..\..\googletest</GTEST_PATH>
1010
</PropertyGroup>

0 commit comments

Comments
 (0)