cameron314 created this revision.
cameron314 added a reviewer: zturner.
cameron314 added a subscriber: lldb-commits.
cameron314 set the repository for this revision to rL LLVM.

Various fixes for Win32 interop, particularly with regard to paths; paths 
containing non-ASCII characters now work properly (they are converted to and 
from UTF-8 internally).

Repository:
  rL LLVM

http://reviews.llvm.org/D17107

Files:
  cfe/trunk/tools/libclang/CIndexer.cpp
  lldb/trunk/cmake/modules/LLDBConfig.cmake
  lldb/trunk/source/Commands/CommandCompletions.cpp
  lldb/trunk/source/Core/ConnectionSharedMemory.cpp
  lldb/trunk/source/Core/Disassembler.cpp
  lldb/trunk/source/Host/common/File.cpp
  lldb/trunk/source/Host/common/FileSpec.cpp
  lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
  lldb/trunk/source/Host/windows/FileSystem.cpp
  lldb/trunk/source/Host/windows/Host.cpp
  lldb/trunk/source/Host/windows/HostInfoWindows.cpp
  lldb/trunk/source/Host/windows/HostProcessWindows.cpp
  lldb/trunk/source/Host/windows/PipeWindows.cpp
  lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
  lldb/trunk/source/Host/windows/Windows.cpp
  lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
  lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
  lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
  lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
  lldb/trunk/source/Target/ProcessLaunchInfo.cpp
  lldb/trunk/tools/driver/Driver.cpp
  lldb/trunk/tools/driver/Platform.h
  lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
  lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
  lldb/trunk/tools/lldb-mi/Platform.h
  llvm/trunk/include/llvm/Support/ConvertUTF.h
  llvm/trunk/lib/Support/CommandLine.cpp
  llvm/trunk/lib/Support/ConvertUTFWrapper.cpp
  llvm/trunk/unittests/Support/ConvertUTFTest.cpp

Index: lldb/trunk/tools/lldb-mi/Platform.h
===================================================================
--- lldb/trunk/tools/lldb-mi/Platform.h
+++ lldb/trunk/tools/lldb-mi/Platform.h
@@ -60,7 +60,7 @@
 typedef long pid_t;
 
 #define STDIN_FILENO 0
-#define PATH_MAX MAX_PATH
+#define PATH_MAX 32768
 #define snprintf _snprintf
 
 extern int ioctl(int d, int request, ...);
Index: lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
===================================================================
--- lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
+++ lldb/trunk/tools/lldb-mi/MIUtilFileStd.cpp
@@ -17,6 +17,9 @@
 #include "MIUtilFileStd.h"
 #include "MICmnResources.h"
 
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ConvertUTF.h"
+
 //++ ------------------------------------------------------------------------------------
 // Details: CMIUtilFileStd constructor.
 // Type:    Method.
@@ -82,7 +85,14 @@
     m_pFileHandle = ::fopen(vFileNamePath.c_str(), "wb");
 #else
     // Open a file with exclusive write and shared read permissions
-    m_pFileHandle = ::_fsopen(vFileNamePath.c_str(), "wb", _SH_DENYWR);
+    llvm::SmallVector<UTF16, 128> path;
+    if (llvm::convertUTF8ToUTF16String(vFileNamePath.c_str(), path))
+        m_pFileHandle = ::_wfsopen((const wchar_t *)path.data(), L"wb", _SH_DENYWR);
+    else
+    {
+        errno = EINVAL;
+        m_pFileHandle = nullptr;
+    }
 #endif // !defined( _MSC_VER )
 
     if (m_pFileHandle == nullptr)
@@ -222,7 +232,14 @@
         return false;
 
     FILE *pTmp = nullptr;
+#if _WIN32
+    llvm::SmallVector<UTF16, 128> path;
+    if (!llvm::convertUTF8ToUTF16String(vFileNamePath.c_str(), path))
+        return false;
+    pTmp = ::_wfopen((const wchar_t *)path.data(), L"wb");
+#else
     pTmp = ::fopen(vFileNamePath.c_str(), "wb");
+#endif
     if (pTmp != nullptr)
     {
         ::fclose(pTmp);
Index: lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
===================================================================
--- lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
+++ lldb/trunk/tools/lldb-mi/MICmnLLDBDebugSessionInfo.cpp
@@ -27,6 +27,7 @@
 #include "MICmnMIValueTuple.h"
 #include "MICmdData.h"
 #include "MICmnLLDBUtilSBValue.h"
+#include "Platform.h"
 
 //++ ------------------------------------------------------------------------------------
 // Details: CMICmnLLDBDebugSessionInfo constructor.
@@ -614,7 +615,7 @@
 {
     lldb::SBFrame &rFrame = const_cast<lldb::SBFrame &>(vrFrame);
 
-    static char pBuffer[MAX_PATH];
+    static char pBuffer[PATH_MAX];
     const MIuint nBytes = rFrame.GetLineEntry().GetFileSpec().GetPath(&pBuffer[0], sizeof(pBuffer));
     MIunused(nBytes);
     CMIUtilString strResolvedPath(&pBuffer[0]);
Index: lldb/trunk/tools/driver/Platform.h
===================================================================
--- lldb/trunk/tools/driver/Platform.h
+++ lldb/trunk/tools/driver/Platform.h
@@ -81,7 +81,7 @@
     typedef long pid_t;
     #define snprintf _snprintf
     extern sighandler_t signal( int sig, sighandler_t );
-    #define PATH_MAX MAX_PATH
+    #define PATH_MAX 32768
 #endif
 
     #define STDIN_FILENO 0
Index: lldb/trunk/tools/driver/Driver.cpp
===================================================================
--- lldb/trunk/tools/driver/Driver.cpp
+++ lldb/trunk/tools/driver/Driver.cpp
@@ -41,6 +41,7 @@
 #include "lldb/API/SBTarget.h"
 #include "lldb/API/SBThread.h"
 #include "lldb/API/SBProcess.h"
+#include "llvm/Support/ConvertUTF.h"
 
 #if !defined(__APPLE__)
 #include "llvm/Support/DataTypes.h"
@@ -1261,14 +1262,33 @@
 }
 
 int
-main (int argc, char const *argv[], const char *envp[])
+#if defined(_WIN32)
+wmain(int argc, wchar_t const *wargv[])
+#else
+main (int argc, char const *argv[])
+#endif
 {
 #ifdef _MSC_VER
 	// disable buffering on windows
 	setvbuf(stdout, NULL, _IONBF, 0);
 	setvbuf(stdin , NULL, _IONBF, 0);
 #endif
 
+#if defined(_WIN32)
+    // Convert wide arguments to UTF-8
+    std::vector<std::string> argvStrings(argc);
+    std::vector<const char*> argvPointers(argc);
+    for (int i = 0; i != argc; ++i)
+    {
+        llvm::convertUTF16ToUTF8String((const UTF16*)wargv[i], argvStrings[i]);
+        argvPointers[i] = argvStrings[i].c_str();
+    }
+    const char** argv = argvPointers.data();
+
+    // Indicate that all our output is in UTF-8
+    SetConsoleCP(CP_UTF8);
+#endif
+
     SBDebugger::Initialize();
     
     SBHostOS::ThreadCreated ("<lldb.driver.main-thread>");
Index: lldb/trunk/source/Target/ProcessLaunchInfo.cpp
===================================================================
--- lldb/trunk/source/Target/ProcessLaunchInfo.cpp
+++ lldb/trunk/source/Target/ProcessLaunchInfo.cpp
@@ -16,6 +16,8 @@
 #include "lldb/Target/FileAction.h"
 #include "lldb/Target/Target.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 #if !defined(_WIN32)
 #include <limits.h>
 #endif
@@ -451,7 +453,18 @@
                         if (cwd && cwd[0])
                             new_path += cwd;
                     }
-                    const char *curr_path = getenv("PATH");
+                    const char *curr_path = nullptr;
+#ifdef _WIN32
+                    const wchar_t *wcurr_path = _wgetenv(L"PATH");
+                    std::string curr_path_buffer;
+                    if (wcurr_path)
+                    {
+                        if (llvm::convertUTF16ToUTF8String((const UTF16 *)wcurr_path, curr_path_buffer))
+                            curr_path = curr_path_buffer.c_str();
+                    }
+#else
+                    curr_path = getenv("PATH");
+#endif
                     if (curr_path)
                     {
                         if (new_path.size() > empty_path_len)
Index: lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
===================================================================
--- lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
+++ lldb/trunk/source/Plugins/ScriptInterpreter/Python/PythonDataObjects.cpp
@@ -21,6 +21,9 @@
 #include "lldb/Host/File.h"
 #include "lldb/Interpreter/ScriptInterpreter.h"
 
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ConvertUTF.h"
+
 #include <stdio.h>
 
 #include "llvm/ADT/StringSwitch.h"
@@ -1163,7 +1166,15 @@
 PythonFile::PythonFile(const char *path, const char *mode)
 {
     FILE *fp = nullptr;
+#if _WIN32
+    llvm::SmallVector<UTF16, 128> wpath;
+    llvm::SmallVector<UTF16, 4> wmode;
+    llvm::convertUTF8ToUTF16String(path, wpath);
+    llvm::convertUTF8ToUTF16String(mode, wmode);
+    fp = _wfopen((const wchar_t *)wpath.data(), (const wchar_t *)wmode.data());
+#else
     fp = fopen(path, mode);
+#endif
     lldb_private::File file(fp, true);
     Reset(file, mode);
 }
Index: lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/MiniDump/ProcessWinMiniDump.cpp
@@ -426,17 +426,22 @@
 ProcessWinMiniDump::MapMiniDumpIntoMemory(const char *file)
 {
     Error error;
-
-    m_data_up->m_dump_file = ::CreateFile(file, GENERIC_READ, FILE_SHARE_READ,
+    llvm::SmallVector<UTF16, 128> wfile;
+    if (!llvm::convertUTF8ToUTF16String(file, wfile))
+    {
+        error.SetError(1, lldb::eErrorTypeGeneric);
+        return error;
+    }
+    m_data_up->m_dump_file = ::CreateFileW((LPWSTR)wfile.data(), GENERIC_READ, FILE_SHARE_READ,
                                           NULL, OPEN_EXISTING,
                                           FILE_ATTRIBUTE_NORMAL, NULL);
     if (m_data_up->m_dump_file == INVALID_HANDLE_VALUE)
     {
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
         return error;
     }
 
-    m_data_up->m_mapping = ::CreateFileMapping(m_data_up->m_dump_file, NULL,
+    m_data_up->m_mapping = ::CreateFileMappingW(m_data_up->m_dump_file, NULL,
                                                PAGE_READONLY, 0, 0, NULL);
     if (m_data_up->m_mapping == NULL)
     {
Index: lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/Live/ProcessWindowsLive.cpp
@@ -47,6 +47,7 @@
 #include "ProcessWindowsLive.h"
 #include "TargetThreadWindowsLive.h"
 
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/Format.h"
 #include "llvm/Support/raw_ostream.h"
 
@@ -61,17 +62,19 @@
 std::string
 GetProcessExecutableName(HANDLE process_handle)
 {
-    std::vector<char> file_name;
+    std::vector<UTF16> file_name;
     DWORD file_name_size = MAX_PATH;  // first guess, not an absolute limit
     DWORD copied = 0;
     do
     {
         file_name_size *= 2;
         file_name.resize(file_name_size);
-        copied = ::GetModuleFileNameEx(process_handle, NULL, file_name.data(), file_name_size);
+        copied = ::GetModuleFileNameExW(process_handle, NULL, (LPWSTR)file_name.data(), file_name_size);
     } while (copied >= file_name_size);
     file_name.resize(copied);
-    return std::string(file_name.begin(), file_name.end());
+    std::string result;
+    llvm::convertUTF16ToUTF8String(file_name, result);
+    return result;
 }
 
 std::string
Index: lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
===================================================================
--- lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
+++ lldb/trunk/source/Plugins/Process/Windows/Live/DebuggerThread.cpp
@@ -27,6 +27,7 @@
 #include "Plugins/Process/Windows/Common/ProcessWindowsLog.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/raw_ostream.h"
 
 using namespace lldb;
@@ -484,13 +485,15 @@
         return DBG_CONTINUE;
     }
 
-    std::vector<char> buffer(1);
-    DWORD required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], 0, VOLUME_NAME_DOS);
+    std::vector<UTF16> buffer(1);
+    DWORD required_size = GetFinalPathNameByHandleW(info.hFile, (LPWSTR)&buffer[0], 0, VOLUME_NAME_DOS);
     if (required_size > 0)
     {
         buffer.resize(required_size + 1);
-        required_size = GetFinalPathNameByHandle(info.hFile, &buffer[0], required_size + 1, VOLUME_NAME_DOS);
-        llvm::StringRef path_str(&buffer[0]);
+        required_size = GetFinalPathNameByHandleW(info.hFile, (LPWSTR)&buffer[0], required_size, VOLUME_NAME_DOS);
+        std::string path_str_utf8;
+        llvm::convertUTF16ToUTF8String(buffer, path_str_utf8);
+        llvm::StringRef path_str = path_str_utf8;
         const char *path = path_str.data();
         if (path_str.startswith("\\\\?\\"))
             path += 4;
Index: lldb/trunk/source/Host/windows/Windows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/Windows.cpp
+++ lldb/trunk/source/Host/windows/Windows.cpp
@@ -12,6 +12,8 @@
 #include "lldb/Host/windows/windows.h"
 #include "lldb/Host/windows/win32.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 #include <stdio.h>
 #include <stdarg.h>
 #include <string.h>
@@ -27,6 +29,33 @@
     int _chdir(const char *path);
 }
 
+namespace
+{
+    bool utf8ToWide(const char* utf8, wchar_t* buf, size_t bufSize)
+    {
+        const UTF8* sourceStart = reinterpret_cast<const UTF8*>(utf8);
+        size_t sourceLen = strlen(utf8) + 1 /* convert null too */;
+        UTF16* target = reinterpret_cast<UTF16*>(buf);
+        ConversionFlags flags = strictConversion;
+        return ConvertUTF8toUTF16(
+            &sourceStart, sourceStart + sourceLen,
+            &target, target + bufSize, flags) ==
+            conversionOK;
+    }
+
+    bool wideToUtf8(const wchar_t* wide, char* buf, size_t bufSize)
+    {
+        const UTF16* sourceStart = reinterpret_cast<const UTF16*>(wide);
+        size_t sourceLen = wcslen(wide) + 1 /* convert null too */;
+        UTF8* target = reinterpret_cast<UTF8*>(buf);
+        ConversionFlags flags = strictConversion;
+        return ConvertUTF16toUTF8(
+            &sourceStart, sourceStart + sourceLen,
+            &target, target + bufSize, flags) ==
+            conversionOK;
+    }
+}
+
 int vasprintf(char **ret, const char *fmt, va_list ap)
 {
     char *buf;
@@ -75,81 +104,90 @@
 
 char* realpath(const char * name, char * resolved)
 {
-    char *retname = NULL;  /* we will return this, if we fail */
+    char *retname = NULL;
 
     /* SUSv3 says we must set `errno = EINVAL', and return NULL,
     * if `name' is passed as a NULL pointer.
     */
-
     if (name == NULL)
+    {
         errno = EINVAL;
+        return NULL;
+    }
 
     /* Otherwise, `name' must refer to a readable filesystem object,
     * if we are going to resolve its absolute path name.
     */
-
-    else if (access(name, 4) == 0)
+    wchar_t wideNameBuffer[PATH_MAX];
+    wchar_t* wideName = wideNameBuffer;
+    if (!utf8ToWide(name, wideName, PATH_MAX))
     {
-        /* If `name' didn't point to an existing entity,
-        * then we don't get to here; we simply fall past this block,
-        * returning NULL, with `errno' appropriately set by `access'.
-        *
-        * When we _do_ get to here, then we can use `_fullpath' to
-        * resolve the full path for `name' into `resolved', but first,
-        * check that we have a suitable buffer, in which to return it.
-        */
+        errno = EINVAL;
+        return NULL;
+    }
 
-        if ((retname = resolved) == NULL)
-        {
-            /* Caller didn't give us a buffer, so we'll exercise the
-            * option granted by SUSv3, and allocate one.
-            *
-            * `_fullpath' would do this for us, but it uses `malloc', and
-            * Microsoft's implementation doesn't set `errno' on failure.
-            * If we don't do this explicitly ourselves, then we will not
-            * know if `_fullpath' fails on `malloc' failure, or for some
-            * other reason, and we want to set `errno = ENOMEM' for the
-            * `malloc' failure case.
-            */
-
-            retname = (char*) malloc(_MAX_PATH);
-        }
+    if (_waccess(wideName, 4) != 0)
+        return NULL;
+
+    /* If `name' didn't point to an existing entity,
+    * then we don't get to here; we simply fall past this block,
+    * returning NULL, with `errno' appropriately set by `access'.
+    *
+    * When we _do_ get to here, then we can use `_fullpath' to
+    * resolve the full path for `name' into `resolved', but first,
+    * check that we have a suitable buffer, in which to return it.
+    */
 
-        /* By now, we should have a valid buffer.
-        * If we don't, then we know that `malloc' failed,
-        * so we can set `errno = ENOMEM' appropriately.
+    if ((retname = resolved) == NULL)
+    {
+        /* Caller didn't give us a buffer, so we'll exercise the
+        * option granted by SUSv3, and allocate one.
+        *
+        * `_fullpath' would do this for us, but it uses `malloc', and
+        * Microsoft's implementation doesn't set `errno' on failure.
+        * If we don't do this explicitly ourselves, then we will not
+        * know if `_fullpath' fails on `malloc' failure, or for some
+        * other reason, and we want to set `errno = ENOMEM' for the
+        * `malloc' failure case.
         */
 
+        retname = (char*) malloc(PATH_MAX);
         if (retname == NULL)
+        {
             errno = ENOMEM;
+            return NULL;
+        }
+    }
 
-        /* Otherwise, when we do have a valid buffer,
-        * `_fullpath' should only fail if the path name is too long.
-        */
+    /* Otherwise, when we do have a valid buffer,
+    * `_fullpath' should only fail if the path name is too long.
+    */
 
-        else if ((retname = _fullpath(retname, name, _MAX_PATH)) == NULL)
-            errno = ENAMETOOLONG;
+    wchar_t wideFullPathBuffer[PATH_MAX];
+    wchar_t* wideFullPath;
+    if ((wideFullPath = _wfullpath(wideFullPathBuffer, wideName, PATH_MAX)) == NULL)
+    {
+        errno = ENAMETOOLONG;
+        return NULL;
     }
 
-    /* By the time we get to here,
-    * `retname' either points to the required resolved path name,
-    * or it is NULL, with `errno' set appropriately, either of which
-    * is our required return condition.
-    */
+    // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
+    // FIXME: Check for failure
+    size_t initialLength = wcslen(wideFullPath);
+    GetShortPathNameW(wideFullPath, wideNameBuffer, PATH_MAX);
+    GetLongPathNameW(wideNameBuffer, wideFullPathBuffer, initialLength + 1);
 
-    if (retname != NULL)
+    // Convert back to UTF-8
+    if (!wideToUtf8(wideFullPathBuffer, retname, PATH_MAX))
     {
-        // Do a LongPath<->ShortPath roundtrip so that case is resolved by OS
-        int initialLength = strlen(retname);
-        TCHAR buffer[MAX_PATH];
-        GetShortPathName(retname, buffer, MAX_PATH);
-        GetLongPathName(buffer, retname, initialLength + 1);
-
-        // Force drive to be upper case
-        if (retname[1] == ':')
-            retname[0] = toupper(retname[0]);
+        errno = EINVAL;
+        return NULL;
     }
 
+    // Force drive to be upper case
+    if (retname[1] == ':')
+        retname[0] = toupper(retname[0]);
+
     return retname;
 }
 
@@ -167,7 +205,24 @@
 // use _getcwd() instead of GetCurrentDirectory() because it updates errno
 char* getcwd(char* path, int max)
 {
-    return _getcwd(path, max);
+    assert(path == NULL || max <= PATH_MAX);
+    wchar_t wpath[PATH_MAX];
+    if (wchar_t* wresult = _wgetcwd(wpath, PATH_MAX))
+    {
+        if (path == NULL)
+        {
+            max = UNI_MAX_UTF8_BYTES_PER_CODE_POINT * wcslen(wresult) + 1;
+            path = (char*)malloc(max);
+            if (path == NULL)
+            {
+                errno = ENOMEM;
+                return NULL;
+            }
+        }
+        if (wideToUtf8(wresult, path, max))
+            return path;
+    }
+    return NULL;
 }
 
 // use _chdir() instead of SetCurrentDirectory() because it updates errno
Index: lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
+++ lldb/trunk/source/Host/windows/ProcessLauncherWindows.cpp
@@ -11,6 +11,9 @@
 #include "lldb/Host/windows/ProcessLauncherWindows.h"
 #include "lldb/Target/ProcessLaunchInfo.h"
 
+#include "llvm/Support/ConvertUTF.h"
+#include "llvm/ADT/SmallVector.h"
+
 #include <string>
 #include <vector>
 
@@ -25,20 +28,19 @@
     if (env.GetArgumentCount() == 0)
         return;
 
-    int bytes = 0;
-    for (int i = 0; i < env.GetArgumentCount(); ++i)
-        bytes += strlen(env.GetArgumentAtIndex(i)) + sizeof(char);
-    bytes += sizeof(char);
-    buffer.resize(bytes);
-    char *cur_entry = &buffer[0];
+    // Environment buffer is a null terminated list of null terminated strings
     for (int i = 0; i < env.GetArgumentCount(); ++i)
     {
-        ::strcpy(cur_entry, env.GetArgumentAtIndex(i));
-        cur_entry += strlen(cur_entry) + sizeof(char);
+        llvm::SmallVector<UTF16, 64> warg;
+        if (llvm::convertUTF8ToUTF16String(env.GetArgumentAtIndex(i), warg))
+        {
+            buffer.insert(buffer.end(), (char*)warg.data(),
+                (char*)(warg.data() + wcslen((wchar_t*)warg.data()) + 1);
+        }
     }
-    // Environment buffer is a null terminated list of null terminated
-    // strings, so it is terminated by two null bytes.
-    buffer.back() = 0;
+    // One null wchar_t (to end the block) is two null bytes
+    buffer.push_back(0);
+    buffer.push_back(0);
 }
 }
 
@@ -70,7 +72,7 @@
         startupinfo.wShowWindow = SW_HIDE;
     }
 
-    DWORD flags = CREATE_NEW_CONSOLE;
+    DWORD flags = CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT;
     if (launch_info.GetFlags().Test(eLaunchFlagDebug))
         flags |= DEBUG_ONLY_THIS_PROCESS;
 
@@ -81,9 +83,18 @@
         env_block = environment.data();
 
     executable = launch_info.GetExecutableFile().GetPath();
+    llvm::SmallVector<UTF16, 128> wexecutable;
+    llvm::convertUTF8ToUTF16String(executable, wexecutable);
+
     launch_info.GetArguments().GetQuotedCommandString(commandLine);
-    BOOL result = ::CreateProcessA(executable.c_str(), const_cast<char *>(commandLine.c_str()), NULL, NULL, TRUE, flags,
-                                   env_block, launch_info.GetWorkingDirectory().GetCString(), &startupinfo, &pi);
+    llvm::SmallVector<UTF16, 64> wcommandLine;
+    llvm::convertUTF8ToUTF16String(commandLine, wcommandLine);
+
+    llvm::SmallVector<UTF16, 128> wworkingDirectory;
+    llvm::convertUTF8ToUTF16String(launch_info.GetWorkingDirectory().GetCString(), wworkingDirectory);
+
+    BOOL result = ::CreateProcessW((LPCWSTR)wexecutable.data(), (LPWSTR)wcommandLine.data(), NULL, NULL, TRUE, flags,
+                                   env_block, (LPCWSTR)wworkingDirectory.data(), &startupinfo, &pi);
     if (result)
     {
         // Do not call CloseHandle on pi.hProcess, since we want to pass that back through the HostProcess.
@@ -131,6 +142,8 @@
             flags = FILE_FLAG_WRITE_THROUGH;
     }
 
-    HANDLE result = ::CreateFile(path, access, share, &secattr, create, flags, NULL);
+    llvm::SmallVector<UTF16, 128> wpath;
+    llvm::convertUTF8ToUTF16String(path, wpath);
+    HANDLE result = ::CreateFileW((LPCWSTR)wpath.data(), access, share, &secattr, create, flags, NULL);
     return (result == INVALID_HANDLE_VALUE) ? NULL : result;
 }
Index: lldb/trunk/source/Host/windows/PipeWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/PipeWindows.cpp
+++ lldb/trunk/source/Host/windows/PipeWindows.cpp
@@ -74,7 +74,7 @@
     // Always open for overlapped i/o.  We implement blocking manually in Read and Write.
     DWORD read_mode = FILE_FLAG_OVERLAPPED;
     m_read =
-        ::CreateNamedPipe(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
+        ::CreateNamedPipeA(pipe_path.c_str(), PIPE_ACCESS_INBOUND | read_mode, PIPE_TYPE_BYTE | PIPE_WAIT, 1, 1024, 1024, 120 * 1000, NULL);
     if (INVALID_HANDLE_VALUE == m_read)
         return Error(::GetLastError(), eErrorTypeWin32);
     m_read_fd = _open_osfhandle((intptr_t)m_read, _O_RDONLY);
@@ -153,7 +153,7 @@
 
     if (is_read)
     {
-        m_read = ::CreateFile(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+        m_read = ::CreateFileA(pipe_path.c_str(), GENERIC_READ, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
         if (INVALID_HANDLE_VALUE == m_read)
             return Error(::GetLastError(), eErrorTypeWin32);
 
@@ -164,7 +164,7 @@
     }
     else
     {
-        m_write = ::CreateFile(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
+        m_write = ::CreateFileA(pipe_path.c_str(), GENERIC_WRITE, 0, &attributes, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
         if (INVALID_HANDLE_VALUE == m_write)
             return Error(::GetLastError(), eErrorTypeWin32);
 
Index: lldb/trunk/source/Host/windows/HostProcessWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/HostProcessWindows.cpp
+++ lldb/trunk/source/Host/windows/HostProcessWindows.cpp
@@ -14,6 +14,7 @@
 #include "lldb/Host/windows/HostProcessWindows.h"
 
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/ConvertUTF.h"
 
 #include <Psapi.h>
 
@@ -70,9 +71,15 @@
     if (m_process == nullptr)
         error.SetError(ERROR_INVALID_HANDLE, lldb::eErrorTypeWin32);
 
-    char path[MAX_PATH] = { 0 };
-    if (::GetProcessImageFileName(m_process, path, llvm::array_lengthof(path)))
-        file_spec.SetFile(path, false);
+    UTF16 wpath[PATH_MAX] = { 0 };
+    if (::GetProcessImageFileNameW(m_process, (LPWSTR)wpath, llvm::array_lengthof(wpath)))
+    {
+        std::string path;
+        if (llvm::convertUTF16ToUTF8String(wpath, path))
+            file_spec.SetFile(path, false);
+        else
+            error.SetError(1, lldb::eErrorTypeGeneric);
+    }
     else
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
 
Index: lldb/trunk/source/Host/windows/HostInfoWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/HostInfoWindows.cpp
+++ lldb/trunk/source/Host/windows/HostInfoWindows.cpp
@@ -13,6 +13,7 @@
 
 #include "lldb/Host/windows/HostInfoWindows.h"
 #include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/Support/Path.h"
@@ -76,23 +77,25 @@
 bool
 HostInfoWindows::GetHostname(std::string &s)
 {
-    char buffer[MAX_COMPUTERNAME_LENGTH + 1];
+    UTF16 buffer[MAX_COMPUTERNAME_LENGTH + 1];
     DWORD dwSize = MAX_COMPUTERNAME_LENGTH + 1;
-    if (!::GetComputerName(buffer, &dwSize))
+    if (!::GetComputerNameW((LPWSTR)buffer, &dwSize))
         return false;
 
-    s.assign(buffer, buffer + dwSize);
-    return true;
+    return llvm::convertUTF16ToUTF8String(
+        llvm::makeArrayRef(buffer, dwSize), s);
 }
 
 FileSpec
 HostInfoWindows::GetProgramFileSpec()
 {
     static std::once_flag g_once_flag;
     std::call_once(g_once_flag,  []() {
-        char buffer[PATH_MAX];
-        ::GetModuleFileName(NULL, buffer, sizeof(buffer));
-        m_program_filespec.SetFile(buffer, false);
+        UTF16 buffer[PATH_MAX];
+        ::GetModuleFileNameW(NULL, (LPWSTR)buffer, PATH_MAX);
+        std::string path;
+        llvm::convertUTF16ToUTF8String(buffer, path);
+        m_program_filespec.SetFile(path, false);
     });
     return m_program_filespec;
 }
Index: lldb/trunk/source/Host/windows/Host.cpp
===================================================================
--- lldb/trunk/source/Host/windows/Host.cpp
+++ lldb/trunk/source/Host/windows/Host.cpp
@@ -26,6 +26,8 @@
 #include "lldb/Core/StreamFile.h"
 #include "lldb/Core/StructuredData.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 // Windows includes
 #include <TlHelp32.h>
 
@@ -68,12 +70,11 @@
     bool GetExecutableForProcess(const AutoHandle &handle, std::string &path)
     {
         // Get the process image path.  MAX_PATH isn't long enough, paths can actually be up to 32KB.
-        std::vector<char> buffer(32768);
+        std::vector<UTF16> buffer(PATH_MAX);
         DWORD dwSize = buffer.size();
-        if (!::QueryFullProcessImageNameA(handle.get(), 0, &buffer[0], &dwSize))
+        if (!::QueryFullProcessImageNameW(handle.get(), 0, (LPWSTR)&buffer[0], &dwSize))
             return false;
-        path.assign(&buffer[0]);
-        return true;
+        return llvm::convertUTF16ToUTF8String(buffer.data(), path);
     }
 
     void GetProcessExecutableAndTriple(const AutoHandle &handle, ProcessInstanceInfo &process)
@@ -156,15 +157,16 @@
     if (!::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)host_addr, &hmodule))
         return module_filespec;
 
-    std::vector<char> buffer(MAX_PATH);
+    std::vector<wchar_t> buffer(PATH_MAX);
     DWORD chars_copied = 0;
     do {
-        chars_copied = ::GetModuleFileName(hmodule, &buffer[0], buffer.size());
+        chars_copied = ::GetModuleFileNameW(hmodule, &buffer[0], buffer.size());
         if (chars_copied == buffer.size() && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)
             buffer.resize(buffer.size() * 2);
     } while (chars_copied >= buffer.size());
-
-    module_filespec.SetFile(&buffer[0], false);
+    std::string path;
+    llvm::convertUTF16ToUTF8String((const UTF16*)buffer.data(), path);
+    module_filespec.SetFile(path, false);
     return module_filespec;
 }
 
@@ -177,23 +179,25 @@
     if (!snapshot.IsValid())
         return 0;
 
-    PROCESSENTRY32 pe = {0};
-    pe.dwSize = sizeof(PROCESSENTRY32);
-    if (Process32First(snapshot.get(), &pe))
+    PROCESSENTRY32W pe = {0};
+    pe.dwSize = sizeof(PROCESSENTRY32W);
+    if (Process32FirstW(snapshot.get(), &pe))
     {
         do
         {
             AutoHandle handle(::OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pe.th32ProcessID), nullptr);
 
             ProcessInstanceInfo process;
-            process.SetExecutableFile(FileSpec(pe.szExeFile, false), true);
+            std::string exeFile;
+            llvm::convertUTF16ToUTF8String((const UTF16 *)pe.szExeFile, exeFile);
+            process.SetExecutableFile(FileSpec(exeFile, false), true);
             process.SetProcessID(pe.th32ProcessID);
             process.SetParentProcessID(pe.th32ParentProcessID);
             GetProcessExecutableAndTriple(handle, process);
 
             if (match_info.MatchAllProcesses() || match_info.Matches(process))
                 process_infos.Append(process);
-        } while (Process32Next(snapshot.get(), &pe));
+        } while (Process32NextW(snapshot.get(), &pe));
     }
     return process_infos.GetSize();
 }
@@ -312,11 +316,16 @@
 {
     // The environment block on Windows is a contiguous buffer of NULL terminated strings,
     // where the end of the environment block is indicated by two consecutive NULLs.
-    LPCH environment_block = ::GetEnvironmentStrings();
+    LPWCH environment_block = ::GetEnvironmentStringsW();
     env.Clear();
-    while (*environment_block != '\0')
+    while (*environment_block != L'\0')
     {
-        llvm::StringRef current_var(environment_block);
+        std::string current_var;
+        if (!llvm::convertUTF16ToUTF8String((const UTF16 *)environment_block, current_var))
+        {
+            environment_block += wcslen(environment_block) + 1;
+            continue;
+        }
         if (current_var[0] != '=')
             env.AppendString(current_var);
 
Index: lldb/trunk/source/Host/windows/FileSystem.cpp
===================================================================
--- lldb/trunk/source/Host/windows/FileSystem.cpp
+++ lldb/trunk/source/Host/windows/FileSystem.cpp
@@ -15,6 +15,9 @@
 
 #include "lldb/Host/FileSystem.h"
 #include "lldb/Host/windows/AutoHandle.h"
+
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 
 using namespace lldb_private;
@@ -47,25 +50,32 @@
 FileSystem::DeleteDirectory(const FileSpec &file_spec, bool recurse)
 {
     Error error;
+    llvm::SmallVector<UTF16, 128> path_buffer;
+    if (!llvm::convertUTF8ToUTF16String(file_spec.GetPath(), path_buffer))
+    {
+        error.SetError(1, lldb::eErrorTypeGeneric);
+        return error;
+    }
     if (!recurse)
     {
-        BOOL result = ::RemoveDirectory(file_spec.GetCString());
+        BOOL result = ::RemoveDirectoryW((LPCWSTR)path_buffer.data());
         if (!result)
             error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     }
     else
     {
         // SHFileOperation() accepts a list of paths, and so must be double-null-terminated to
-        // indicate the end of the list.
-        std::string path_buffer{file_spec.GetPath()};
+        // indicate the end of the list. The first null terminator is there only in the backing
+        // store but not the actual vector contents, and so we need to push twice.
+        path_buffer.push_back(0);
         path_buffer.push_back(0);
 
-        SHFILEOPSTRUCT shfos = {0};
+        SHFILEOPSTRUCTW shfos = {0};
         shfos.wFunc = FO_DELETE;
-        shfos.pFrom = path_buffer.c_str();
+        shfos.pFrom = (LPCWSTR)path_buffer.data();
         shfos.fFlags = FOF_NO_UI;
 
-        int result = ::SHFileOperation(&shfos);
+        int result = ::SHFileOperationW(&shfos);
         // TODO(zturner): Correctly handle the intricacies of SHFileOperation return values.
         if (result != 0)
             error.SetErrorStringWithFormat("SHFileOperation failed");
@@ -121,15 +131,24 @@
 FileSystem::Hardlink(const FileSpec &src, const FileSpec &dst)
 {
     Error error;
-    if (!::CreateHardLink(src.GetCString(), dst.GetCString(), nullptr))
+    llvm::SmallVector<UTF16, 128> srcBuffer, dstBuffer;
+    if (!llvm::convertUTF8ToUTF16String(src.GetCString(), srcBuffer))
+        error.SetError(1, lldb::eErrorTypeGeneric);
+    else if (!llvm::convertUTF8ToUTF16String(dst.GetCString(), dstBuffer))
+        error.SetError(1, lldb::eErrorTypeGeneric);
+    else if (!::CreateHardLinkW((LPCWSTR)srcBuffer.data(), (LPCWSTR)dstBuffer.data(), nullptr))
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     return error;
 }
 
 int
 FileSystem::GetHardlinkCount(const FileSpec &file_spec)
 {
-    HANDLE file_handle = ::CreateFile(file_spec.GetCString(),
+    llvm::SmallVector<UTF16, 128> path;
+    if (!llvm::convertUTF8ToUTF16String(file_spec.GetCString(), path))
+        return -1;
+
+    HANDLE file_handle = ::CreateFileW((LPCWSTR)path.data(),
                                       FILE_READ_ATTRIBUTES,
                                       FILE_SHARE_READ,
                                       nullptr,
@@ -152,15 +171,22 @@
 FileSystem::Symlink(const FileSpec &src, const FileSpec &dst)
 {
     Error error;
-    DWORD attrib = ::GetFileAttributes(dst.GetCString());
+    llvm::SmallVector<UTF16, 128> srcBuffer, dstBuffer;
+    if (!llvm::convertUTF8ToUTF16String(src.GetCString(), srcBuffer))
+        error.SetError(1, lldb::eErrorTypeGeneric);
+    else if (!llvm::convertUTF8ToUTF16String(dst.GetCString(), dstBuffer))
+        error.SetError(1, lldb::eErrorTypeGeneric);
+    if (error.Fail())
+        return error;
+    DWORD attrib = ::GetFileAttributesW((LPCWSTR)dstBuffer.data());
     if (attrib == INVALID_FILE_ATTRIBUTES)
     {
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
         return error;
     }
     bool is_directory = !!(attrib & FILE_ATTRIBUTE_DIRECTORY);
     DWORD flag = is_directory ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0;
-    BOOL result = ::CreateSymbolicLink(src.GetCString(), dst.GetCString(), flag);
+    BOOL result = ::CreateSymbolicLinkW((LPCWSTR)srcBuffer.data(), (LPCWSTR)dstBuffer.data(), flag);
     if (!result)
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     return error;
@@ -170,7 +196,13 @@
 FileSystem::Unlink(const FileSpec &file_spec)
 {
     Error error;
-    BOOL result = ::DeleteFile(file_spec.GetCString());
+    llvm::SmallVector<UTF16, 128> path;
+    if (!llvm::convertUTF8ToUTF16String(file_spec.GetCString(), path))
+    {
+        error.SetError(1, lldb::eErrorTypeGeneric);
+        return error;
+    }
+    BOOL result = ::DeleteFileW((LPCWSTR)path.data());
     if (!result)
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
     return error;
@@ -180,23 +212,33 @@
 FileSystem::Readlink(const FileSpec &src, FileSpec &dst)
 {
     Error error;
-    HANDLE h = ::CreateFile(src.GetCString(), GENERIC_READ,
+    llvm::SmallVector<UTF16, 128> srcBuffer;
+    if (!llvm::convertUTF8ToUTF16String(src.GetCString(), srcBuffer))
+    {
+        error.SetError(1, lldb::eErrorTypeGeneric);
+        return error;
+    }
+
+    HANDLE h = ::CreateFileW((LPCWSTR)srcBuffer.data(), GENERIC_READ,
             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING,
             FILE_FLAG_OPEN_REPARSE_POINT, NULL);
     if (h == INVALID_HANDLE_VALUE)
     {
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
         return error;
     }
 
-    char buf[PATH_MAX];
+    wchar_t buf[PATH_MAX + 1];
     // Subtract 1 from the path length since this function does not add a null terminator.
-    DWORD result = ::GetFinalPathNameByHandle(h, buf, sizeof(buf) - 1,
+    DWORD result = ::GetFinalPathNameByHandleW(h, buf, PATH_MAX,
             FILE_NAME_NORMALIZED | VOLUME_NAME_DOS);
+    std::string path;
     if (result == 0)
         error.SetError(::GetLastError(), lldb::eErrorTypeWin32);
+    else if (!llvm::convertUTF16ToUTF8String((UTF16*)buf, path))
+        error.SetError(1, lldb::eErrorTypeGeneric);
     else
-        dst.SetFile(buf, false);
+        dst.SetFile(path, false);
 
     ::CloseHandle(h);
     return error;
Index: lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
===================================================================
--- lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
+++ lldb/trunk/source/Host/windows/ConnectionGenericFileWindows.cpp
@@ -12,8 +12,10 @@
 #include "lldb/Host/TimeValue.h"
 #include "lldb/Host/windows/ConnectionGenericFileWindows.h"
 
+#include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
 
 using namespace lldb;
 using namespace lldb_private;
@@ -138,7 +140,14 @@
     // Open the file for overlapped access.  If it does not exist, create it.  We open it overlapped
     // so that we can issue asynchronous reads and then use WaitForMultipleObjects to allow the read
     // to be interrupted by an event object.
-    m_file = ::CreateFile(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
+    llvm::SmallVector<UTF16, 128> wpath;
+    if (!llvm::convertUTF8ToUTF16String(path, wpath))
+    {
+        if (error_ptr)
+            error_ptr->SetError(1, eErrorTypeGeneric);
+        return eConnectionStatusError;
+    }
+    m_file = ::CreateFileW((LPCWSTR)wpath.data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_FLAG_OVERLAPPED, NULL);
     if (m_file == INVALID_HANDLE_VALUE)
     {
         if (error_ptr)
Index: lldb/trunk/source/Host/common/FileSpec.cpp
===================================================================
--- lldb/trunk/source/Host/common/FileSpec.cpp
+++ lldb/trunk/source/Host/common/FileSpec.cpp
@@ -40,6 +40,7 @@
 #include "lldb/Utility/CleanUp.h"
 
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/Program.h"
@@ -90,7 +91,26 @@
 {
     char resolved_path[PATH_MAX];
     if (file_spec->GetPath (resolved_path, sizeof(resolved_path)))
+    {
+#ifdef _WIN32
+        llvm::SmallVector<UTF16, 128> wresolved_path;
+        if (!llvm::convertUTF8ToUTF16String(resolved_path, wresolved_path))
+            return false;
+        int stat_result;
+#ifdef _USE_32BIT_TIME_T
+        struct _stat32 file_stats;
+        stat_result = ::_wstat32((const wchar_t *)wresolved_path.data(), &file_stats);
+#else
+        struct _stat64i32 file_stats;
+        stat_result = ::_wstat64i32((const wchar_t *)wresolved_path.data(), &file_stats);
+#endif
+        if (stat_result == 0)
+            *stats_ptr = *reinterpret_cast<struct stat *>(&file_stats);
+        return stat_result == 0;
+#else
         return ::stat (resolved_path, stats_ptr) == 0;
+#endif
+    }
     return false;
 }
 
@@ -213,8 +233,17 @@
     
     path.push_back(0);  // Be sure we have a nul terminated string
     path.pop_back();
+    int stat_result;
+#ifdef _WIN32
+    llvm::SmallVector<UTF16, 128> wpath;
+    llvm::convertUTF8ToUTF16String(path.data(), wpath);
+    struct _stat32 file_stats;
+    stat_result = ::_wstat32((const wchar_t *)wpath.data(), &file_stats);
+#else
     struct stat file_stats;
-    if (::stat (path.data(), &file_stats) != 0)
+    stat_result = ::stat(file_spec.GetCString(), &file_stats);
+#endif
+    if (stat_result != 0)
     {
         path.clear();
         path.append(original_path.begin(), original_path.end());
@@ -797,7 +826,10 @@
         return false;
 
 #ifdef _WIN32
-    auto attrs = ::GetFileAttributes (resolved_path);
+    llvm::SmallVector<UTF16, 128> wpath;
+    if (!llvm::convertUTF8ToUTF16String (resolved_path, wpath))
+        return false;
+    auto attrs = ::GetFileAttributesW ((LPCWSTR)wpath.data());
     if (attrs == INVALID_FILE_ATTRIBUTES)
         return false;
 
@@ -1100,8 +1132,14 @@
         std::string szDir(dir_path);
         szDir += "\\*";
 
+        llvm::SmallVector<UTF16, 128> wszDir;
+        if (!llvm::convertUTF8ToUTF16String(szDir, wszDir))
+        {
+            return eEnumerateDirectoryResultNext;
+        }
+
         WIN32_FIND_DATA ffd;
-        HANDLE hFind = FindFirstFile(szDir.c_str(), &ffd);
+        HANDLE hFind = FindFirstFileW((LPCWSTR)wszDir.data(), &ffd);
 
         if (hFind == INVALID_HANDLE_VALUE)
         {
@@ -1113,12 +1151,12 @@
             FileSpec::FileType file_type = eFileTypeUnknown;
             if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
             {
-                size_t len = strlen(ffd.cFileName);
+                size_t len = wcslen(ffd.cFileName);
 
-                if (len == 1 && ffd.cFileName[0] == '.')
+                if (len == 1 && ffd.cFileName[0] == L'.')
                     continue;
 
-                if (len == 2 && ffd.cFileName[0] == '.' && ffd.cFileName[1] == '.')
+                if (len == 2 && ffd.cFileName[0] == L'.' && ffd.cFileName[1] == L'.')
                     continue;
 
                 file_type = eFileTypeDirectory;
@@ -1132,8 +1170,14 @@
                 file_type = eFileTypeRegular;
             }
 
-            char child_path[MAX_PATH];
-            const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s\\%s", dir_path, ffd.cFileName);
+            std::string fileName;
+            if (!llvm::convertUTF16ToUTF8String((const UTF16*)ffd.cFileName, fileName))
+            {
+                continue;
+            }
+
+            char child_path[PATH_MAX];
+            const int child_path_len = ::snprintf (child_path, sizeof(child_path), "%s\\%s", dir_path, fileName.c_str());
             if (child_path_len < (int)(sizeof(child_path) - 1))
             {
                 // Don't resolve the file type or path
@@ -1167,7 +1211,7 @@
                         return eEnumerateDirectoryResultQuit;
                 }
             }
-        } while (FindNextFile(hFind, &ffd) != 0);
+        } while (FindNextFileW(hFind, &ffd) != 0);
 
         FindClose(hFind);
 #else
Index: lldb/trunk/source/Host/common/File.cpp
===================================================================
--- lldb/trunk/source/Host/common/File.cpp
+++ lldb/trunk/source/Host/common/File.cpp
@@ -22,6 +22,7 @@
 #include <sys/ioctl.h>
 #endif
 
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/Process.h" // for llvm::sys::Process::FileDescriptorHasColors()
 
 #include "lldb/Core/DataBufferHeap.h"
@@ -318,7 +319,18 @@
 
     do
     {
+#ifdef _WIN32
+        llvm::SmallVector<UTF16, 128> wpath;
+        if (!llvm::convertUTF8ToUTF16String(path, wpath))
+        {
+            m_descriptor = -1;
+            error.SetErrorString("Error converting path to UTF-16");
+            return error;
+        }
+        m_descriptor = ::_wopen((const wchar_t *)wpath.data(), oflag, mode);
+#else
         m_descriptor = ::open(path, oflag, mode);
+#endif
     } while (m_descriptor < 0 && errno == EINTR);
 
     if (!DescriptorIsValid())
@@ -337,8 +349,21 @@
 {
     if (file_spec)
     {
+        int stat_result;
+#ifdef _WIN32
+        llvm::SmallVector<UTF16, 128> wpath;
+        if (!llvm::convertUTF8ToUTF16String(file_spec.GetCString(), wpath))
+        {
+            error.SetError(1, lldb::eErrorTypeGeneric);
+            return 0;
+        }
+        struct _stat32 file_stats;
+        stat_result = ::_wstat32((const wchar_t *)wpath.data(), &file_stats);
+#else
         struct stat file_stats;
-        if (::stat(file_spec.GetCString(), &file_stats) == -1)
+        stat_result = ::stat(file_spec.GetCString(), &file_stats);
+#endif
+        if (stat_result == -1)
             error.SetErrorToErrno();
         else
         {
Index: lldb/trunk/source/Core/Disassembler.cpp
===================================================================
--- lldb/trunk/source/Core/Disassembler.cpp
+++ lldb/trunk/source/Core/Disassembler.cpp
@@ -36,6 +36,8 @@
 #include "lldb/Target/StackFrame.h"
 #include "lldb/Target/Target.h"
 
+#include "llvm/Support/ConvertUTF.h"
+
 #define DEFAULT_DISASM_BYTE_SIZE 32
 
 using namespace lldb;
@@ -876,8 +878,14 @@
         out_stream->Printf ("Instruction::TestEmulation:  Missing file_name.");
         return false;
     }
-        
-    FILE *test_file = fopen (file_name, "r");
+    FILE *test_file = nullptr;
+#if _WIN32
+    llvm::SmallVector<UTF16, 128> wfile_name;
+    if (llvm::convertUTF8ToUTF16String (file_name, wfile_name))
+        test_file = _wfopen ((const wchar_t *)wfile_name.data(), L"r");
+#else
+    test_file = fopen (file_name, "r");
+#endif
     if (!test_file)
     {
         out_stream->Printf ("Instruction::TestEmulation: Attempt to open test file failed.");
Index: lldb/trunk/source/Core/ConnectionSharedMemory.cpp
===================================================================
--- lldb/trunk/source/Core/ConnectionSharedMemory.cpp
+++ lldb/trunk/source/Core/ConnectionSharedMemory.cpp
@@ -29,6 +29,9 @@
 #include "lldb/Core/Communication.h"
 #include "lldb/Core/Log.h"
 
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ConvertUTF.h"
+
 using namespace lldb;
 using namespace lldb_private;
 
@@ -132,18 +135,22 @@
     m_name.assign (name);
 
 #ifdef _WIN32
-    HANDLE handle;
-    if (create) {
-        handle = CreateFileMapping(
-            INVALID_HANDLE_VALUE,
-            NULL,
-            PAGE_READWRITE,
-            llvm::Hi_32(size),
-            llvm::Lo_32(size),
-            name);
+    HANDLE handle = INVALID_HANDLE_VALUE;
+    llvm::SmallVector<UTF16, 128> wname;
+    if (llvm::convertUTF8ToUTF16String(name, wname))
+    {
+        if (create) {
+            handle = CreateFileMappingW(
+                INVALID_HANDLE_VALUE,
+                NULL,
+                PAGE_READWRITE,
+                llvm::Hi_32(size),
+                llvm::Lo_32(size),
+                (LPCWSTR)wname.data());
+        }
+        else
+            handle = OpenFileMappingW(FILE_MAP_ALL_ACCESS, FALSE, (LPCWSTR)wname.data());
     }
-    else
-        handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, name);
 
     m_fd = _open_osfhandle((intptr_t)handle, 0);
 #else
Index: lldb/trunk/source/Commands/CommandCompletions.cpp
===================================================================
--- lldb/trunk/source/Commands/CommandCompletions.cpp
+++ lldb/trunk/source/Commands/CommandCompletions.cpp
@@ -30,6 +30,8 @@
 #include "lldb/Utility/CleanUp.h"
 
 #include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/ConvertUTF.h"
 
 using namespace lldb_private;
 
@@ -166,9 +168,20 @@
             isa_directory = true;
         else if (file_type == FileSpec::eFileTypeSymbolicLink)
         {
+#ifdef _WIN32
+            llvm::SmallVector<UTF16, 128> wpartial_name_copy;
+            if (llvm::convertUTF8ToUTF16String(partial_name_copy, wpartial_name_copy))
+            {
+                struct _stat32 stat_buf;
+                if (_wstat32((const wchar_t *)wpartial_name_copy.data(), &stat_buf) == 0 &&
+                    S_ISDIR(stat_buf.st_mode))
+                    isa_directory = true;
+            }
+#else
             struct stat stat_buf;
             if ((stat(partial_name_copy, &stat_buf) == 0) && S_ISDIR(stat_buf.st_mode))
                 isa_directory = true;
+#endif
         }
 
         if (isa_directory)
Index: lldb/trunk/cmake/modules/LLDBConfig.cmake
===================================================================
--- lldb/trunk/cmake/modules/LLDBConfig.cmake
+++ lldb/trunk/cmake/modules/LLDBConfig.cmake
@@ -245,6 +245,11 @@
   )
 endif()
 
+# Use the Unicode (UTF-16) APIs by default on Win32
+if (CMAKE_SYSTEM_NAME MATCHES "Windows")
+	add_definitions( /D _UNICODE /D UNICODE )
+endif()
+
 set(LLDB_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR})
 set(LLDB_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR})
 
Index: cfe/trunk/tools/libclang/CIndexer.cpp
===================================================================
--- cfe/trunk/tools/libclang/CIndexer.cpp
+++ cfe/trunk/tools/libclang/CIndexer.cpp
@@ -22,6 +22,7 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Config/llvm-config.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/ConvertUTF.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/Program.h"
 #include "llvm/Support/raw_ostream.h"
@@ -53,20 +54,12 @@
   // Find the location where this library lives (libclang.dylib).
 #ifdef LLVM_ON_WIN32
   MEMORY_BASIC_INFORMATION mbi;
-  char path[MAX_PATH];
+  wchar_t wpath[MAX_PATH];
   VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
                sizeof(mbi));
-  GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
-
-#ifdef __CYGWIN__
-  char w32path[MAX_PATH];
-  strcpy(w32path, path);
-#if CYGWIN_VERSION_API_MAJOR > 0 || CYGWIN_VERSION_API_MINOR >= 181
-  cygwin_conv_path(CCP_WIN_A_TO_POSIX, w32path, path, MAX_PATH);
-#else
-  cygwin_conv_to_full_posix_path(w32path, path);
-#endif
-#endif
+  GetModuleFileNameW((HINSTANCE)mbi.AllocationBase, wpath, MAX_PATH);
+  std::string path;
+  llvm::convertUTF16ToUTF8String((const UTF16 *)wpath, path);
 
   LibClangPath += llvm::sys::path::parent_path(path);
 #else
Index: llvm/trunk/unittests/Support/ConvertUTFTest.cpp
===================================================================
--- llvm/trunk/unittests/Support/ConvertUTFTest.cpp
+++ llvm/trunk/unittests/Support/ConvertUTFTest.cpp
@@ -59,7 +59,7 @@
 
 TEST(ConvertUTFTest, Empty) {
   std::string Result;
-  bool Success = convertUTF16ToUTF8String(None, Result);
+  bool Success = convertUTF16ToUTF8String(llvm::ArrayRef<char>(None), Result);
   EXPECT_TRUE(Success);
   EXPECT_TRUE(Result.empty());
 }
Index: llvm/trunk/lib/Support/ConvertUTFWrapper.cpp
===================================================================
--- llvm/trunk/lib/Support/ConvertUTFWrapper.cpp
+++ llvm/trunk/lib/Support/ConvertUTFWrapper.cpp
@@ -36,7 +36,7 @@
     ConversionFlags flags = strictConversion;
     result = ConvertUTF8toUTF16(
         &sourceStart, sourceStart + Source.size(),
-        &targetStart, targetStart + 2*Source.size(), flags);
+        &targetStart, targetStart + Source.size(), flags);
     if (result == conversionOK)
       ResultPtr = reinterpret_cast<char*>(targetStart);
     else
@@ -49,7 +49,7 @@
     ConversionFlags flags = strictConversion;
     result = ConvertUTF8toUTF32(
         &sourceStart, sourceStart + Source.size(),
-        &targetStart, targetStart + 4*Source.size(), flags);
+        &targetStart, targetStart + Source.size(), flags);
     if (result == conversionOK)
       ResultPtr = reinterpret_cast<char*>(targetStart);
     else
@@ -130,6 +130,20 @@
   return true;
 }
 
+bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out)
+{
+  return convertUTF16ToUTF8String(
+    llvm::ArrayRef<char>(reinterpret_cast<const char *>(Src.data()),
+    Src.size() * sizeof(UTF16)), Out);
+}
+
+bool convertUTF16ToUTF8String(const UTF16 *Src, std::string &Out)
+{
+    const UTF16 *End = Src;
+    while (*End) ++End;
+    return convertUTF16ToUTF8String(llvm::makeArrayRef(Src, End), Out);
+}
+
 bool convertUTF8ToUTF16String(StringRef SrcUTF8,
                               SmallVectorImpl<UTF16> &DstUTF16) {
   assert(DstUTF16.empty());
Index: llvm/trunk/lib/Support/CommandLine.cpp
===================================================================
--- llvm/trunk/lib/Support/CommandLine.cpp
+++ llvm/trunk/lib/Support/CommandLine.cpp
@@ -787,9 +787,22 @@
   assert(envVar && "Environment variable name missing");
 
   // Get the environment variable they want us to parse options out of.
+#ifdef _WIN32
+  llvm::SmallVector<UTF16, 32> wenvVar;
+  if (!llvm::convertUTF8ToUTF16String(envVar, wenvVar))
+      return;
+  const wchar_t *wenvValue = _wgetenv((const wchar_t *)wenvVar.data());
+  if (!wenvValue)
+      return;
+  std::string envValueBuffer;
+  if (!llvm::convertUTF16ToUTF8String((const UTF16 *)wenvValue, envValueBuffer))
+      return;
+  const char *envValue = envValueBuffer.c_str();
+#else
   const char *envValue = getenv(envVar);
   if (!envValue)
     return;
+#endif
 
   // Get program's "name", which we wouldn't know without the caller
   // telling us.
Index: llvm/trunk/include/llvm/Support/ConvertUTF.h
===================================================================
--- llvm/trunk/include/llvm/Support/ConvertUTF.h
+++ llvm/trunk/include/llvm/Support/ConvertUTF.h
@@ -252,6 +252,24 @@
 bool convertUTF16ToUTF8String(ArrayRef<char> SrcBytes, std::string &Out);
 
 /**
+* Converts a UTF16 string into a UTF8 std::string.
+*
+* \param [in] Src A buffer of UTF-16 encoded text.
+* \param [out] Out Converted UTF-8 is stored here on success.
+* \returns true on success
+*/
+bool convertUTF16ToUTF8String(ArrayRef<UTF16> Src, std::string &Out);
+
+/**
+* Converts a UTF16 string into a UTF8 std::string.
+*
+* \param [in] Src A pointer to a null-terminated UTF-16 encoded string.
+* \param [out] Out Converted UTF-8 is stored here on success.
+* \returns true on success
+*/
+bool convertUTF16ToUTF8String(const UTF16 *Src, std::string &Out);
+
+/**
  * Converts a UTF-8 string into a UTF-16 string with native endianness.
  *
  * \returns true on success
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to