|
14 | 14 |
|
15 | 15 | #include "includes_normalize.h" |
16 | 16 |
|
17 | | -#include "string_piece.h" |
18 | | -#include "string_piece_util.h" |
19 | | -#include "util.h" |
| 17 | +#include <string.h> |
| 18 | + |
| 19 | +#include <windows.h> |
20 | 20 |
|
21 | 21 | #include <algorithm> |
22 | 22 | #include <iterator> |
23 | 23 | #include <sstream> |
24 | 24 |
|
25 | | -#include <windows.h> |
| 25 | +#include "string_piece.h" |
| 26 | +#include "string_piece_util.h" |
| 27 | +#include "util.h" |
26 | 28 |
|
27 | 29 | namespace { |
28 | 30 |
|
| 31 | +constexpr const std::size_t MAX_PATH_LONG = 32767; |
| 32 | + |
29 | 33 | bool InternalGetFullPathName(const StringPiece& file_name, char* buffer, |
30 | 34 | size_t buffer_length, std::string* err) { |
31 | | - DWORD result_size = GetFullPathNameA(file_name.AsString().c_str(), |
32 | | - buffer_length, buffer, NULL); |
33 | | - if (result_size == 0) { |
34 | | - *err = "GetFullPathNameA(" + file_name.AsString() + "): " + |
35 | | - GetLastErrorString(); |
| 35 | + // IMPORTANT: Using GetFullPathNameA() with a long paths will fail with |
| 36 | + // "The filename or extension is too long" even if long path supported is |
| 37 | + // enabled. GetFullPathNameW() must be used for this function to work! |
| 38 | + buffer[0] = '\0'; |
| 39 | + // Convert to wide filename first. |
| 40 | + std::wstring wide_filename; |
| 41 | + if (!ConvertUTF8ToWin32Unicode(file_name, &wide_filename, err)) |
36 | 42 | return false; |
37 | | - } else if (result_size > buffer_length) { |
38 | | - *err = "path too long"; |
| 43 | + |
| 44 | + // Call GetFullPathNameW() |
| 45 | + DWORD wide_full_size = GetFullPathNameW(wide_filename.c_str(), 0, NULL, NULL); |
| 46 | + if (wide_full_size == 0) { |
| 47 | + *err = "GetFullPathNameW(" + |
| 48 | + std::string(wide_filename.begin(), wide_filename.end()) + |
| 49 | + "): " + GetLastErrorString(); |
| 50 | + return false; |
| 51 | + } |
| 52 | + |
| 53 | + // NOTE: wide_full_size includes the null-terminating character. |
| 54 | + std::wstring wide_path; |
| 55 | + wide_path.resize(static_cast<size_t>(wide_full_size - 1)); |
| 56 | + DWORD wide_full_size2 = |
| 57 | + GetFullPathNameW(wide_filename.c_str(), wide_full_size, |
| 58 | + const_cast<wchar_t*>(wide_path.data()), NULL); |
| 59 | + if (wide_full_size2 == 0) { |
| 60 | + *err = "GetFullPathNameW(" + file_name.AsString() + "): " + GetLastErrorString(); |
| 61 | + return false; |
| 62 | + } |
| 63 | + |
| 64 | + // Convert wide_path to Unicode. |
| 65 | + int utf8_size = |
| 66 | + WideCharToMultiByte(CP_UTF8, 0, wide_path.c_str(), wide_path.size() + 1, |
| 67 | + buffer, buffer_length, NULL, NULL); |
| 68 | + if (utf8_size <= 0 || utf8_size >= buffer_length) { |
| 69 | + *err = "WideCharToMultiByte(" + std::string(wide_path.begin(), wide_path.end()) + |
| 70 | + "): " + GetLastErrorString(); |
39 | 71 | return false; |
40 | 72 | } |
41 | 73 | return true; |
@@ -74,8 +106,8 @@ bool SameDrive(StringPiece a, StringPiece b, std::string* err) { |
74 | 106 | return true; |
75 | 107 | } |
76 | 108 |
|
77 | | - char a_absolute[_MAX_PATH]; |
78 | | - char b_absolute[_MAX_PATH]; |
| 109 | + char a_absolute[MAX_PATH_LONG]; |
| 110 | + char b_absolute[MAX_PATH_LONG]; |
79 | 111 | if (!InternalGetFullPathName(a, a_absolute, sizeof(a_absolute), err)) { |
80 | 112 | return false; |
81 | 113 | } |
@@ -144,7 +176,7 @@ std::string IncludesNormalize::AbsPath(StringPiece s, std::string* err) { |
144 | 176 | return result; |
145 | 177 | } |
146 | 178 |
|
147 | | - char result[_MAX_PATH]; |
| 179 | + char result[MAX_PATH_LONG]; |
148 | 180 | if (!InternalGetFullPathName(s, result, sizeof(result), err)) { |
149 | 181 | return ""; |
150 | 182 | } |
@@ -183,9 +215,9 @@ std::string IncludesNormalize::Relativize( |
183 | 215 |
|
184 | 216 | bool IncludesNormalize::Normalize(const std::string& input, std::string* result, |
185 | 217 | std::string* err) const { |
186 | | - char copy[_MAX_PATH + 1]; |
| 218 | + char copy[MAX_PATH_LONG + 1]; |
187 | 219 | size_t len = input.size(); |
188 | | - if (len > _MAX_PATH) { |
| 220 | + if (len > MAX_PATH_LONG) { |
189 | 221 | *err = "path too long"; |
190 | 222 | return false; |
191 | 223 | } |
|
0 commit comments