From 741101db8b0ca77d50431d4c06f013d5cd68be44 Mon Sep 17 00:00:00 2001 From: Adrian McCarthy Date: Mon, 20 Jun 2016 17:51:27 +0000 Subject: [PATCH] Properly handle short file names on the command line in Windows [TAKE 2] Trying to expand short names with a relative path doesn't work, so this first gets the module name to get a full path (which can still have short names). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@273171 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Support/Windows/Process.inc | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/Support/Windows/Process.inc b/lib/Support/Windows/Process.inc index 3aef79fee84..b012991c2a5 100644 --- a/lib/Support/Windows/Process.inc +++ b/lib/Support/Windows/Process.inc @@ -201,6 +201,9 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl &Args, const int DirSize = Dir.size(); // Search for matching files. + // FIXME: This assumes the wildcard is only in the file name and not in the + // directory portion of the file path. For example, it doesn't handle + // "*\foo.c" nor "s?c\bar.cpp". WIN32_FIND_DATAW FileData; HANDLE FindHandle = FindFirstFileW(Arg, &FileData); if (FindHandle == INVALID_HANDLE_VALUE) { @@ -215,7 +218,7 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl &Args, if (ec) break; - // Push the filename onto Dir, and remove it afterwards. + // Append FileName to Dir, and remove it afterwards. llvm::sys::path::append(Dir, StringRef(FileName.data(), FileName.size())); AllocateAndPush(Dir, Args, Allocator); Dir.resize(DirSize); @@ -225,6 +228,23 @@ WildcardExpand(const wchar_t *Arg, SmallVectorImpl &Args, return ec; } +static std::error_code +ExpandShortFileName(const wchar_t *Arg, SmallVectorImpl &Args, + SpecificBumpPtrAllocator &Allocator) { + SmallVector LongPath; + DWORD Length = GetLongPathNameW(Arg, LongPath.data(), LongPath.capacity()); + if (Length == 0) + return mapWindowsError(GetLastError()); + if (Length > LongPath.capacity()) { + // We're not going to try to deal with paths longer than MAX_PATH, so we'll + // treat this as an error. GetLastError() returns ERROR_SUCCESS, which + // isn't useful, so we'll hardcode an appropriate error value. + return mapWindowsError(ERROR_INSUFFICIENT_BUFFER); + } + LongPath.set_size(Length); + return ConvertAndPushArg(LongPath.data(), Args, Allocator); +} + std::error_code Process::GetArgumentVector(SmallVectorImpl &Args, ArrayRef, @@ -238,7 +258,19 @@ Process::GetArgumentVector(SmallVectorImpl &Args, Args.reserve(ArgCount); std::error_code ec; - for (int i = 0; i < ArgCount; ++i) { + // The first argument may contain just the name of the executable (e.g., + // "clang") rather than the full path, so swap it with the full path. + wchar_t ModuleName[MAX_PATH]; + int Length = ::GetModuleFileNameW(NULL, ModuleName, MAX_PATH); + if (0 < Length && Length < MAX_PATH) + UnicodeCommandLine[0] = ModuleName; + + // If the first argument is a shortened (8.3) name (which is possible even + // if we got the module name), the driver will have trouble distinguishing it + // (e.g., clang.exe v. clang++.exe), so expand it now. + ec = ExpandShortFileName(UnicodeCommandLine[0], Args, ArgAllocator); + + for (int i = 1; i < ArgCount && !ec; ++i) { ec = WildcardExpand(UnicodeCommandLine[i], Args, ArgAllocator); if (ec) break; -- 2.11.0