Skip to content

Commit f0b119d

Browse files
remutroLukeUsher
authored andcommitted
Fix mapped drives not working after symlink fix (Windows)
1 parent e8c2680 commit f0b119d

File tree

1 file changed

+52
-6
lines changed

1 file changed

+52
-6
lines changed

nall/nall/directory.cpp

Lines changed: 52 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,34 @@
11
#include <nall/directory.hpp>
2+
#if defined(PLATFORM_WINDOWS)
3+
#include <winioctl.h>
4+
5+
//normally defined in ntifs.h (WDK)
6+
typedef struct _REPARSE_DATA_BUFFER {
7+
unsigned long ReparseTag;
8+
unsigned short ReparseDataLength;
9+
unsigned short Reserved;
10+
union {
11+
struct {
12+
unsigned short SubstituteNameOffset;
13+
unsigned short SubstituteNameLength;
14+
unsigned short PrintNameOffset;
15+
unsigned short PrintNameLength;
16+
unsigned long Flags;
17+
wchar_t PathBuffer[1];
18+
} SymbolicLinkReparseBuffer;
19+
struct {
20+
unsigned short SubstituteNameOffset;
21+
unsigned short SubstituteNameLength;
22+
unsigned short PrintNameOffset;
23+
unsigned short PrintNameLength;
24+
wchar_t PathBuffer[1];
25+
} MountPointReparseBuffer;
26+
struct {
27+
unsigned char DataBuffer[1];
28+
} GenericReparseBuffer;
29+
} DUMMYUNIONNAME;
30+
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
31+
#endif
232

333
namespace nall {
434

@@ -90,15 +120,31 @@ NALL_HEADER_INLINE auto directory::ufiles(const string& pathname, const string&
90120
NALL_HEADER_INLINE auto directory::resolveSymLink(const string& pathname) -> string {
91121
string result = pathname;
92122
#if defined (PLATFORM_WINDOWS)
93-
HANDLE hFile = CreateFile(utf16_t(result.data()), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
123+
HANDLE hFile = CreateFile(utf16_t(result.data()), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
124+
NULL, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, NULL);
94125
if(hFile != INVALID_HANDLE_VALUE)
95126
{
96-
wchar_t buffer[MAX_PATH];
97-
memset(buffer, 0, MAX_PATH * sizeof(wchar_t));
98-
if(GetFinalPathNameByHandle(hFile, buffer, MAX_PATH, 0) < MAX_PATH) {
99-
result = (slice((const char*)utf8_t(buffer), 4, wcslen(buffer) - 4)).transform("\\", "/"); //remove "\\?\" prefix
127+
BYTE buffer[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
128+
memset(buffer, 0, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
129+
if(DeviceIoControl(hFile, FSCTL_GET_REPARSE_POINT, NULL, 0, buffer, MAXIMUM_REPARSE_DATA_BUFFER_SIZE, NULL, NULL)) {
130+
REPARSE_DATA_BUFFER* reparseData = (REPARSE_DATA_BUFFER*)buffer;
131+
u16 substituteNameOffset = 0, substituteNameLength = 0;
132+
wchar_t* pathBuffer = nullptr;
133+
if(reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) {
134+
pathBuffer = reparseData->SymbolicLinkReparseBuffer.PathBuffer;
135+
substituteNameOffset = reparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
136+
substituteNameLength = reparseData->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
137+
result = (slice((const char*)utf8_t(pathBuffer) + substituteNameOffset, 0, substituteNameLength)).transform("\\", "/");
138+
if(result.beginsWith("/??/")) result = result.slice(4);
139+
} else if (reparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) {
140+
pathBuffer = reparseData->MountPointReparseBuffer.PathBuffer;
141+
substituteNameOffset = reparseData->MountPointReparseBuffer.SubstituteNameOffset / sizeof(wchar_t);
142+
substituteNameLength = reparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(wchar_t);
143+
result = (slice((const char*)utf8_t(pathBuffer) + substituteNameOffset, 0, substituteNameLength)).transform("\\", "/");
144+
if(result.beginsWith("/??/")) result = result.slice(4);
100145
}
101-
CloseHandle(hFile);
146+
}
147+
CloseHandle(hFile);
102148
}
103149
#else
104150
struct stat sb = {};

0 commit comments

Comments
 (0)