Commit b5ca6e51 authored by Brad King's avatar Brad King Committed by Kitware Robot

Merge topic 'Encoding-win-ext-path'

41b8603c SystemTools: Use Encoding::ToWindowsExtendedPath
e71a3406 Encoding: Add ToWindowsExtendedPath function
Acked-by: Kitware Robot's avatarKitware Robot <kwrobot@kitware.com>
Merge-request: !25
parents 23a4c211 41b8603c
......@@ -59,6 +59,17 @@ public:
static std::string ToNarrow(const std::wstring& str);
static std::string ToNarrow(const wchar_t* str);
#if defined(_WIN32)
/**
* Convert the path to an extended length path to avoid MAX_PATH length
* limitations on Windows. If the input is a local path the result will be
* prefixed with \\?\; if the input is instead a network path, the result
* will be prefixed with \\?\UNC\. All output will also be converted to
* absolute paths with Windows-style backslashes.
**/
static std::wstring ToWindowsExtendedPath(std::string const&);
#endif
#endif // @KWSYS_NAMESPACE@_STL_HAS_WSTRING
}; // class Encoding
......
......@@ -29,6 +29,7 @@
#if defined(_WIN32)
#include <windows.h>
#include <ctype.h>
#include <shellapi.h>
#endif
......@@ -214,6 +215,63 @@ std::string Encoding::ToNarrow(const wchar_t* wcstr)
}
return str;
}
#if defined(_WIN32)
// Convert local paths to UNC style paths
std::wstring Encoding::ToWindowsExtendedPath(std::string const& source)
{
std::wstring wsource = Encoding::ToWide(source);
// Resolve any relative paths
DWORD wfull_len;
/* The +3 is a workaround for a bug in some versions of GetFullPathNameW that
* won't return a large enough buffer size if the input is too small */
wfull_len = GetFullPathNameW(wsource.c_str(), 0, NULL, NULL) + 3;
std::vector<wchar_t> wfull(wfull_len);
GetFullPathNameW(wsource.c_str(), wfull_len, &wfull[0], NULL);
/* This should get the correct size without any extra padding from the
* previous size workaround. */
wfull_len = static_cast<DWORD>(wcslen(&wfull[0]));
if (wfull_len >= 2 && isalpha(wfull[0]) &&
wfull[1] == L':') { /* C:\Foo\bar\FooBar.txt */
return L"\\\\?\\" + std::wstring(&wfull[0]);
} else if (wfull_len >= 2 && wfull[0] == L'\\' &&
wfull[1] == L'\\') { /* Starts with \\ */
if (wfull_len >= 4 && wfull[2] == L'?' &&
wfull[3] == L'\\') { /* Starts with \\?\ */
if (wfull_len >= 8 && wfull[4] == L'U' && wfull[5] == L'N' &&
wfull[6] == L'C' &&
wfull[7] == L'\\') { /* \\?\UNC\Foo\bar\FooBar.txt */
return std::wstring(&wfull[0]);
} else if (wfull_len >= 6 && isalpha(wfull[4]) &&
wfull[5] == L':') { /* \\?\C:\Foo\bar\FooBar.txt */
return std::wstring(&wfull[0]);
} else if (wfull_len >= 5) { /* \\?\Foo\bar\FooBar.txt */
return L"\\\\?\\UNC\\" + std::wstring(&wfull[4]);
}
} else if (wfull_len >= 4 && wfull[2] == L'.' &&
wfull[3] == L'\\') { /* Starts with \\.\ a device name */
if (wfull_len >= 6 && isalpha(wfull[4]) &&
wfull[5] == L':') { /* \\.\C:\Foo\bar\FooBar.txt */
return L"\\\\?\\" + std::wstring(&wfull[4]);
} else if (wfull_len >=
5) { /* \\.\Foo\bar\ Device name is left unchanged */
return std::wstring(&wfull[0]);
}
} else if (wfull_len >= 3) { /* \\Foo\bar\FooBar.txt */
return L"\\\\?\\UNC\\" + std::wstring(&wfull[2]);
}
}
// If this case has been reached, then the path is invalid. Leave it
// unchanged
return Encoding::ToWide(source);
}
#endif
#endif // KWSYS_STL_HAS_WSTRING
} // namespace KWSYS_NAMESPACE
This diff is collapsed.
......@@ -265,13 +265,7 @@ public:
static void ConvertToUnixSlashes(std::string& path);
#ifdef _WIN32
/**
* Convert the path to an extended length path to avoid MAX_PATH length
* limitations on Windows. If the input is a local path the result will be
* prefixed with \\?\; if the input is instead a network path, the result
* will be prefixed with \\?\UNC\. All output will also be converted to
* absolute paths with Windows-style backslashes.
**/
/** Calls Encoding::ToWindowsExtendedPath. */
static std::wstring ConvertToWindowsExtendedPath(const std::string&);
#endif
......
......@@ -180,6 +180,88 @@ static int testCommandLineArguments()
return status;
}
static int testToWindowsExtendedPath()
{
#ifdef _WIN32
int ret = 0;
if (kwsys::Encoding::ToWindowsExtendedPath(
"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
<< std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath(
"L:/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath(
"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
<< std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath(
"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\""
<< std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("//") != L"//") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"//\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\") != L"\\\\.\\") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X") != L"\\\\.\\X") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\X\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:") != L"\\\\?\\X:") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\X:\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("\\\\.\\X:\\") !=
L"\\\\?\\X:\\") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"\\\\.\\X:\\\"" << std::endl;
++ret;
}
if (kwsys::Encoding::ToWindowsExtendedPath("NUL") != L"\\\\.\\NUL") {
std::cout << "Problem with ToWindowsExtendedPath "
<< "\"NUL\"" << std::endl;
++ret;
}
return ret;
#else
return 0;
#endif
}
//----------------------------------------------------------------------------
int testEncoding(int, char* [])
{
......@@ -196,6 +278,7 @@ int testEncoding(int, char* [])
ret |= testRobustEncoding();
ret |= testCommandLineArguments();
ret |= testWithNulls();
ret |= testToWindowsExtendedPath();
return ret;
}
......@@ -585,85 +585,6 @@ static bool CheckStringOperations()
res = false;
}
#ifdef _WIN32
if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
<< std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
"L:/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
L"\\\\?\\L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"L:/Local Mojo/Hex Power Pack/Iffy Voodoo\"" << std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") !=
L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"\\\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\""
<< std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath(
"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo") !=
L"\\\\?\\UNC\\Foo\\Local Mojo\\Hex Power Pack\\Iffy Voodoo") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"//Foo/Local Mojo/Hex Power Pack/Iffy Voodoo\""
<< std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath("//") != L"//") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"//\"" << std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\") !=
L"\\\\.\\") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"\\\\.\\\"" << std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X") !=
L"\\\\.\\X") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"\\\\.\\X\"" << std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:") !=
L"\\\\?\\X:") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"\\\\.\\X:\"" << std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath("\\\\.\\X:\\") !=
L"\\\\?\\X:\\") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"\\\\.\\X:\\\"" << std::endl;
res = false;
}
if (kwsys::SystemTools::ConvertToWindowsExtendedPath("NUL") !=
L"\\\\.\\NUL") {
std::cerr << "Problem with ConvertToWindowsExtendedPath "
<< "\"NUL\"" << std::endl;
res = false;
}
#endif
if (kwsys::SystemTools::ConvertToWindowsOutputPath(
"L://Local Mojo/Hex Power Pack/Iffy Voodoo") !=
"\"L:\\Local Mojo\\Hex Power Pack\\Iffy Voodoo\"") {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment