Skip to content

Commit 5835bab

Browse files
committed
Add code to map NT-style paths to Win32 paths.
GetMappedFilenameW() returns an NT-style path, not a Win32 path, but we need a Win32 path. rdar://103071801
1 parent 0a47ed3 commit 5835bab

File tree

1 file changed

+88
-3
lines changed

1 file changed

+88
-3
lines changed

stdlib/public/runtime/Paths.cpp

Lines changed: 88 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,81 @@ _swift_initRootPath(void *)
146146
}
147147
}
148148

149+
#if _WIN32
150+
/// Map an NT-style filename to a Win32 filename.
151+
///
152+
/// We can't use GetFinalPathNameByHandle() because there's no way to obtain
153+
/// a handle (at least, not without using the internal NtCreateFile() API, which
154+
/// we aren't supposed to be using). Additionally, that function would resolve
155+
/// symlinks, which we don't want to do here.
156+
///
157+
/// As a result, we use the approach demonstrated here:
158+
///
159+
/// https://learn.microsoft.com/en-us/windows/win32/memory/obtaining-a-file-name-from-a-file-handle
160+
///
161+
/// @param pszFilename The NT-style filename to convert.
162+
///
163+
/// @result A string, allocated using std::malloc(), containing the Win32-style
164+
/// filename.
165+
LPWSTR
166+
_swift_win32NameFromNTName(LPWSTR pszFilename) {
167+
DWORD dwLen = GetLogicalDriveStringsW(0, NULL);
168+
if (!dwLen)
169+
return NULL;
170+
171+
LPWSTR lpDriveStrings = (LPWSTR)std::malloc(dwLen * sizeof(WCHAR));
172+
if (!lpDriveStrings)
173+
return NULL;
174+
175+
DWORD dwRet = GetLogicalDriveStringsW(dwLen, lpDriveStrings);
176+
if (!dwRet)
177+
return NULL;
178+
179+
LPWSTR pszDrive = lpDriveStrings;
180+
while (*pszDrive) {
181+
size_t len = wcslen(pszDrive);
182+
if (len && pszDrive[len - 1] == '\\')
183+
pszDrive[len - 1] = 0;
184+
185+
WCHAR ntPath[4096];
186+
dwRet = QueryDosDeviceW(pszDrive, ntPath, 4096);
187+
if (dwRet) {
188+
size_t ntLen = wcslen(ntPath);
189+
190+
if (_wcsnicmp(pszFilename, ntPath, ntLen) == 0
191+
&& pszFilename[ntLen] == '\\') {
192+
size_t fnLen = wcslen(pszFilename);
193+
size_t driveLen = wcslen(pszDrive);
194+
size_t pathLen = fnLen - ntLen;
195+
size_t newLen = driveLen + pathLen + 1;
196+
LPWSTR pszWin32Name = (LPWSTR)std::malloc(newLen * sizeof(WCHAR));
197+
if (!pszWin32Name) {
198+
std::free(lpDriveStrings);
199+
return NULL;
200+
}
201+
202+
LPWSTR ptr = pszWin32Name;
203+
memcpy(ptr, pszDrive, driveLen * sizeof(WCHAR));
204+
ptr += driveLen;
205+
memcpy(ptr, pszFilename + ntLen, pathLen * sizeof(WCHAR));
206+
ptr += pathLen;
207+
*ptr = 0;
208+
209+
std::free(lpDriveStrings);
210+
211+
return pszWin32Name;
212+
}
213+
}
214+
215+
pszDrive += len + 1;
216+
}
217+
218+
std::free(lpDriveStrings);
219+
220+
return _wcsdup(pszFilename);
221+
}
222+
#endif
223+
149224
}
150225

151226
SWIFT_RUNTIME_EXPORT
@@ -241,22 +316,32 @@ _swift_initRuntimePath(void *) {
241316
LPWSTR lpFilename = (LPWSTR)std::malloc(dwBufSize * sizeof(WCHAR));
242317

243318
DWORD dwRet = GetMappedFileNameW(GetCurrentProcess(),
244-
_swift_initRuntimePath,
319+
(void *)_swift_initRuntimePath,
245320
lpFilename,
246321
dwBufSize);
247322
if (!dwRet) {
248323
swift::fatalError(/* flags = */ 0,
249324
"Unable to obtain Swift runtime path\n");
250325
}
251326

252-
runtimePath = swift::win32::copyUTF8FromWide(lpFilename);
327+
// GetMappedFileNameW() returns an NT-style path, not a Win32 path; that is,
328+
// it starts with \Device\DeviceName rather than a drive letter.
329+
LPWSTR lpWin32Filename = _swift_win32NameFromNTName(lpFilename);
330+
if (!lpWin32Filename) {
331+
swift::fatalError(/* flags = */ 0,
332+
"Unable to obtain Win32 path for Swift runtime\n");
333+
}
334+
335+
std::free(lpFilename);
336+
337+
runtimePath = swift::win32::copyUTF8FromWide(lpWin32Filename);
253338
if (!runtimePath) {
254339
swift::fatalError(/* flags = */ 0,
255340
"Unable to convert Swift runtime path to UTF-8: %lx, %d\n",
256341
::GetLastError(), errno);
257342
}
258343

259-
free(lpFilename);
344+
std::free(lpWin32Filename);
260345
}
261346
#endif
262347

0 commit comments

Comments
 (0)