1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_FileUtilsWin_h
8 #define mozilla_FileUtilsWin_h
12 #include "mozilla/Scoped.h"
13 #include "nsStringGlue.h"
18 EnsureLongPath(nsAString
& aDosPath
)
20 uint32_t aDosPathOriginalLen
= aDosPath
.Length();
21 auto inputPath
= PromiseFlatString(aDosPath
);
22 // Try to get the long path, or else get the required length of the long path
23 DWORD longPathLen
= GetLongPathNameW(inputPath
.get(),
24 reinterpret_cast<wchar_t*>(aDosPath
.BeginWriting()),
26 if (longPathLen
== 0) {
29 aDosPath
.SetLength(longPathLen
);
30 if (longPathLen
<= aDosPathOriginalLen
) {
31 // Our string happened to be long enough for the first call to succeed.
34 // Now we have a large enough buffer, get the actual string
35 longPathLen
= GetLongPathNameW(inputPath
.get(),
36 reinterpret_cast<wchar_t*>(aDosPath
.BeginWriting()), aDosPath
.Length());
37 if (longPathLen
== 0) {
40 // This success check should always be less-than because longPathLen excludes
41 // the null terminator on success, but includes it in the first call that
42 // returned the required size.
43 if (longPathLen
< aDosPath
.Length()) {
44 aDosPath
.SetLength(longPathLen
);
47 // We shouldn't reach this, but if we do then it's a failure!
52 NtPathToDosPath(const nsAString
& aNtPath
, nsAString
& aDosPath
)
55 if (aNtPath
.IsEmpty()) {
58 NS_NAMED_LITERAL_STRING(symLinkPrefix
, "\\??\\");
59 uint32_t ntPathLen
= aNtPath
.Length();
60 uint32_t symLinkPrefixLen
= symLinkPrefix
.Length();
61 if (ntPathLen
>= 6 && aNtPath
.CharAt(5) == L
':' &&
62 ntPathLen
>= symLinkPrefixLen
&&
63 Substring(aNtPath
, 0, symLinkPrefixLen
).Equals(symLinkPrefix
)) {
64 // Symbolic link for DOS device. Just strip off the prefix.
69 nsAutoString logicalDrives
;
72 len
= GetLogicalDriveStringsW(
73 len
, reinterpret_cast<wchar_t*>(logicalDrives
.BeginWriting()));
76 } else if (len
> logicalDrives
.Length()) {
77 logicalDrives
.SetLength(len
);
82 const char16_t
* cur
= logicalDrives
.BeginReading();
83 const char16_t
* end
= logicalDrives
.EndReading();
85 targetPath
.SetLength(MAX_PATH
);
86 wchar_t driveTemplate
[] = L
" :";
88 // Unfortunately QueryDosDevice doesn't support the idiom for querying the
89 // output buffer size, so it may require retries.
90 driveTemplate
[0] = *cur
;
91 DWORD targetPathLen
= 0;
92 SetLastError(ERROR_SUCCESS
);
94 targetPathLen
= QueryDosDeviceW(driveTemplate
,
95 reinterpret_cast<wchar_t*>(targetPath
.BeginWriting()),
97 if (targetPathLen
|| GetLastError() != ERROR_INSUFFICIENT_BUFFER
) {
100 targetPath
.SetLength(targetPath
.Length() * 2);
103 // Need to use wcslen here because targetPath contains embedded NULL chars
104 size_t firstTargetPathLen
= wcslen(targetPath
.get());
105 const char16_t
* pathComponent
= aNtPath
.BeginReading() +
107 bool found
= _wcsnicmp(char16ptr_t(aNtPath
.BeginReading()), targetPath
.get(),
108 firstTargetPathLen
) == 0 &&
109 *pathComponent
== L
'\\';
111 aDosPath
= driveTemplate
;
112 aDosPath
+= pathComponent
;
113 return EnsureLongPath(aDosPath
);
116 // Advance to the next NUL character in logicalDrives
118 } while (cur
!= end
);
119 // Try to handle UNC paths. NB: This must happen after we've checked drive
120 // mappings in case a UNC path is mapped to a drive!
121 NS_NAMED_LITERAL_STRING(uncPrefix
, "\\\\");
122 NS_NAMED_LITERAL_STRING(deviceMupPrefix
, "\\Device\\Mup\\");
123 if (StringBeginsWith(aNtPath
, deviceMupPrefix
)) {
124 aDosPath
= uncPrefix
;
125 aDosPath
+= Substring(aNtPath
, deviceMupPrefix
.Length());
128 NS_NAMED_LITERAL_STRING(deviceLanmanRedirectorPrefix
,
129 "\\Device\\LanmanRedirector\\");
130 if (StringBeginsWith(aNtPath
, deviceLanmanRedirectorPrefix
)) {
131 aDosPath
= uncPrefix
;
132 aDosPath
+= Substring(aNtPath
, deviceLanmanRedirectorPrefix
.Length());
139 HandleToFilename(HANDLE aHandle
, const LARGE_INTEGER
& aOffset
,
140 nsAString
& aFilename
);
142 } // namespace mozilla
144 #endif // mozilla_FileUtilsWin_h