diff --git a/util/env_windows.cc b/util/env_windows.cc
index 449f564..812c728 100644
--- a/util/env_windows.cc
+++ b/util/env_windows.cc
@@ -375,8 +375,9 @@ class WindowsEnv : public Env {
     *result = nullptr;
     DWORD desired_access = GENERIC_READ;
     DWORD share_mode = FILE_SHARE_READ;
-    ScopedHandle handle = ::CreateFileA(
-        filename.c_str(), desired_access, share_mode,
+    auto wFilename = toUtf16(filename);
+    ScopedHandle handle = ::CreateFileW(
+        wFilename.c_str(), desired_access, share_mode,
         /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL,
         /*hTemplateFile=*/nullptr);
     if (!handle.is_valid()) {
@@ -392,8 +393,9 @@ class WindowsEnv : public Env {
     *result = nullptr;
     DWORD desired_access = GENERIC_READ;
     DWORD share_mode = FILE_SHARE_READ;
+    auto wFilename = toUtf16(filename);
     ScopedHandle handle =
-        ::CreateFileA(filename.c_str(), desired_access, share_mode,
+        ::CreateFileW(wFilename.c_str(), desired_access, share_mode,
                       /*lpSecurityAttributes=*/nullptr, OPEN_EXISTING,
                       FILE_ATTRIBUTE_READONLY,
                       /*hTemplateFile=*/nullptr);
@@ -413,11 +415,12 @@ class WindowsEnv : public Env {
     }
 
     ScopedHandle mapping =
-        ::CreateFileMappingA(handle.get(),
-                             /*security attributes=*/nullptr, PAGE_READONLY,
-                             /*dwMaximumSizeHigh=*/0,
-                             /*dwMaximumSizeLow=*/0,
-                             /*lpName=*/nullptr);
+            ::CreateFileMappingW(handle.get(),
+                                 /*security attributes=*/nullptr,
+                                 PAGE_READONLY,
+                                 /*dwMaximumSizeHigh=*/0,
+                                 /*dwMaximumSizeLow=*/0,
+                                 /*lpName=*/nullptr);
     if (mapping.is_valid()) {
       void* mmap_base = ::MapViewOfFile(mapping.get(), FILE_MAP_READ,
                                         /*dwFileOffsetHigh=*/0,
@@ -438,8 +441,9 @@ class WindowsEnv : public Env {
                          WritableFile** result) override {
     DWORD desired_access = GENERIC_WRITE;
     DWORD share_mode = 0;  // Exclusive access.
-    ScopedHandle handle = ::CreateFileA(
-        filename.c_str(), desired_access, share_mode,
+    auto wFilename = toUtf16(filename);
+    ScopedHandle handle = ::CreateFileW(
+        wFilename.c_str(), desired_access, share_mode,
         /*lpSecurityAttributes=*/nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
         /*hTemplateFile=*/nullptr);
     if (!handle.is_valid()) {
@@ -455,8 +459,9 @@ class WindowsEnv : public Env {
                            WritableFile** result) override {
     DWORD desired_access = FILE_APPEND_DATA;
     DWORD share_mode = 0;  // Exclusive access.
-    ScopedHandle handle = ::CreateFileA(
-        filename.c_str(), desired_access, share_mode,
+    auto wFilename = toUtf16(filename);
+    ScopedHandle handle = ::CreateFileW(
+        wFilename.c_str(), desired_access, share_mode,
         /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
         /*hTemplateFile=*/nullptr);
     if (!handle.is_valid()) {
@@ -469,14 +474,16 @@ class WindowsEnv : public Env {
   }
 
   bool FileExists(const std::string& filename) override {
-    return GetFileAttributesA(filename.c_str()) != INVALID_FILE_ATTRIBUTES;
+    auto wFilename = toUtf16(filename);
+    return GetFileAttributesW(wFilename.c_str()) != INVALID_FILE_ATTRIBUTES;
   }
 
   Status GetChildren(const std::string& directory_path,
                      std::vector<std::string>* result) override {
     const std::string find_pattern = directory_path + "\\*";
-    WIN32_FIND_DATAA find_data;
-    HANDLE dir_handle = ::FindFirstFileA(find_pattern.c_str(), &find_data);
+    WIN32_FIND_DATAW find_data;
+    auto wFind_pattern = toUtf16(find_pattern);
+    HANDLE dir_handle = ::FindFirstFileW(wFind_pattern.c_str(), &find_data);
     if (dir_handle == INVALID_HANDLE_VALUE) {
       DWORD last_error = ::GetLastError();
       if (last_error == ERROR_FILE_NOT_FOUND) {
@@ -488,11 +495,12 @@ class WindowsEnv : public Env {
       char base_name[_MAX_FNAME];
       char ext[_MAX_EXT];
 
-      if (!_splitpath_s(find_data.cFileName, nullptr, 0, nullptr, 0, base_name,
+      auto find_data_filename = toUtf8(find_data.cFileName);
+      if (!_splitpath_s(find_data_filename.c_str(), nullptr, 0, nullptr, 0, base_name,
                         ARRAYSIZE(base_name), ext, ARRAYSIZE(ext))) {
         result->emplace_back(std::string(base_name) + ext);
       }
-    } while (::FindNextFileA(dir_handle, &find_data));
+    } while (::FindNextFileW(dir_handle, &find_data));
     DWORD last_error = ::GetLastError();
     ::FindClose(dir_handle);
     if (last_error != ERROR_NO_MORE_FILES) {
@@ -501,22 +509,25 @@ class WindowsEnv : public Env {
     return Status::OK();
   }
 
-  Status RemoveFile(const std::string& filename) override {
-    if (!::DeleteFileA(filename.c_str())) {
+  Status RemoveFile(const std::string& filename) {
+    auto wFilename = toUtf16(filename);
+    if (!::DeleteFileW(wFilename.c_str())) {
       return WindowsError(filename, ::GetLastError());
     }
     return Status::OK();
   }
 
   Status CreateDir(const std::string& dirname) override {
-    if (!::CreateDirectoryA(dirname.c_str(), nullptr)) {
+    auto wDirname = toUtf16(dirname);
+    if (!::CreateDirectoryW(wDirname.c_str(), nullptr)) {
       return WindowsError(dirname, ::GetLastError());
     }
     return Status::OK();
   }
 
   Status RemoveDir(const std::string& dirname) override {
-    if (!::RemoveDirectoryA(dirname.c_str())) {
+    auto wDirname = toUtf16(dirname);
+    if (!::RemoveDirectoryW(wDirname.c_str())) {
       return WindowsError(dirname, ::GetLastError());
     }
     return Status::OK();
@@ -524,7 +535,8 @@ class WindowsEnv : public Env {
 
   Status GetFileSize(const std::string& filename, uint64_t* size) override {
     WIN32_FILE_ATTRIBUTE_DATA file_attributes;
-    if (!::GetFileAttributesExA(filename.c_str(), GetFileExInfoStandard,
+    auto wFilename = toUtf16(filename);
+    if (!::GetFileAttributesExW(wFilename.c_str(), GetFileExInfoStandard,
                                 &file_attributes)) {
       return WindowsError(filename, ::GetLastError());
     }
@@ -538,7 +550,9 @@ class WindowsEnv : public Env {
   Status RenameFile(const std::string& from, const std::string& to) override {
     // Try a simple move first. It will only succeed when |to| doesn't already
     // exist.
-    if (::MoveFileA(from.c_str(), to.c_str())) {
+    auto wFrom = toUtf16(from);
+    auto wTo = toUtf16(to);
+    if (::MoveFileW(wFrom.c_str(), wTo.c_str())) {
       return Status::OK();
     }
     DWORD move_error = ::GetLastError();
@@ -547,7 +561,7 @@ class WindowsEnv : public Env {
     // succeed when |to| does exist. When writing to a network share, we may not
     // be able to change the ACLs. Ignore ACL errors then
     // (REPLACEFILE_IGNORE_MERGE_ERRORS).
-    if (::ReplaceFileA(to.c_str(), from.c_str(), /*lpBackupFileName=*/nullptr,
+    if (::ReplaceFileW(wTo.c_str(), wFrom.c_str(), /*lpBackupFileName=*/nullptr,
                        REPLACEFILE_IGNORE_MERGE_ERRORS,
                        /*lpExclude=*/nullptr, /*lpReserved=*/nullptr)) {
       return Status::OK();
@@ -567,8 +581,9 @@ class WindowsEnv : public Env {
   Status LockFile(const std::string& filename, FileLock** lock) override {
     *lock = nullptr;
     Status result;
-    ScopedHandle handle = ::CreateFileA(
-        filename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
+    auto wFilename = toUtf16(filename);
+    ScopedHandle handle = ::CreateFileW(
+        wFilename.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ,
         /*lpSecurityAttributes=*/nullptr, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,
         nullptr);
     if (!handle.is_valid()) {
@@ -608,10 +623,11 @@ class WindowsEnv : public Env {
       return Status::OK();
     }
 
-    char tmp_path[MAX_PATH];
-    if (!GetTempPathA(ARRAYSIZE(tmp_path), tmp_path)) {
+    wchar_t wtmp_path[MAX_PATH];
+    if (!GetTempPathW(ARRAYSIZE(wtmp_path), wtmp_path)) {
       return WindowsError("GetTempPath", ::GetLastError());
     }
+    std::string tmp_path = toUtf8(std::wstring(wtmp_path));
     std::stringstream ss;
     ss << tmp_path << "leveldbtest-" << std::this_thread::get_id();
     *result = ss.str();
@@ -622,7 +638,8 @@ class WindowsEnv : public Env {
   }
 
   Status NewLogger(const std::string& filename, Logger** result) override {
-    std::FILE* fp = std::fopen(filename.c_str(), "w");
+    auto wFilename = toUtf16(filename);
+    std::FILE* fp = _wfopen(wFilename.c_str(), L"w");
     if (fp == nullptr) {
       *result = nullptr;
       return WindowsError(filename, ::GetLastError());
@@ -678,6 +695,31 @@ class WindowsEnv : public Env {
       GUARDED_BY(background_work_mutex_);
 
   Limiter mmap_limiter_;  // Thread-safe.
+
+  // Converts a Windows wide multi-byte UTF-16 string to a UTF-8 string.
+  // See http://utf8everywhere.org/#windows
+  std::string toUtf8(const std::wstring& wstr) {
+    if (wstr.empty()) return std::string();
+    int size_needed = WideCharToMultiByte(
+      CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
+    std::string strTo(size_needed, 0);
+    WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0],
+      size_needed, NULL, NULL);
+    return strTo;
+  }
+
+  // Converts a UTF-8 string to a Windows UTF-16 multi-byte wide character
+  // string.
+  // See http://utf8everywhere.org/#windows
+  std::wstring toUtf16(const std::string& str) {
+    if (str.empty()) return std::wstring();
+    int size_needed = MultiByteToWideChar(
+      CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
+    std::wstring strTo(size_needed, 0);
+    MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &strTo[0],
+      size_needed);
+    return strTo;
+  }
 };
 
 // Return the maximum number of concurrent mmaps.
diff --git a/util/env_windows_test.cc b/util/env_windows_test.cc
index d6822d2..d108ad9 100644
--- a/util/env_windows_test.cc
+++ b/util/env_windows_test.cc
@@ -55,6 +55,70 @@ TEST_F(EnvWindowsTest, TestOpenOnRead) {
   ASSERT_LEVELDB_OK(env_->RemoveFile(test_file));
 }
 
+TEST_F(EnvWindowsTest, TestOpenOnRead_Unicode) {
+  // Write some test data to a single file that will be opened |n| times.
+  std::string test_dir;
+  ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
+  std::string test_file = test_dir + u8"/open_on_runðŸƒ_read.txt";
+
+  std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
+  std::wstring wideUtf8Path = converter.from_bytes(test_file);
+  FILE* f = _wfopen(wideUtf8Path.c_str(), L"w");
+  ASSERT_TRUE(f != nullptr);
+  const char kFileData[] = "abcdefghijklmnopqrstuvwxyz";
+  fputs(kFileData, f);
+  fclose(f);
+
+  // Open test file some number above the sum of the two limits to force
+  // leveldb::WindowsEnv to switch from mapping the file into memory
+  // to basic file reading.
+  const int kNumFiles = kMMapLimit + 5;
+  leveldb::RandomAccessFile* files[kNumFiles] = {0};
+  for (int i = 0; i < kNumFiles; i++) {
+    ASSERT_LEVELDB_OK(env_->NewRandomAccessFile(test_file, &files[i]));
+  }
+  char scratch;
+  Slice read_result;
+  for (int i = 0; i < kNumFiles; i++) {
+    ASSERT_LEVELDB_OK(files[i]->Read(i, 1, &read_result, &scratch));
+    ASSERT_EQ(kFileData[i], read_result[0]);
+  }
+  for (int i = 0; i < kNumFiles; i++) {
+    delete files[i];
+  }
+  ASSERT_LEVELDB_OK(env_->DeleteFile(test_file));
+}
+
+TEST_F(EnvWindowsTest, TestGetChildrenEmpty) {
+  // Create some dummy files.
+  std::string test_dir;
+  ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
+
+  std::vector<std::string> result;
+  ASSERT_LEVELDB_OK(env_->GetChildren(test_dir, &result));
+  ASSERT_EQ(2, result.size()); // "." and ".." are always returned.
+}
+
+TEST_F(EnvWindowsTest, TestGetChildren_ChildFiles) {
+  // Create some dummy files.
+  std::string test_dir;
+  ASSERT_LEVELDB_OK(env_->GetTestDirectory(&test_dir));
+
+  int childFilesCount = 10;
+  for (int i = 0; i < childFilesCount; i++) {
+    std::string test_file = test_dir + u8"/runðŸƒ_and_jumpðŸ¦˜_" + std::to_string(i) + ".txt";
+    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> converter;
+    std::wstring wTest_file = converter.from_bytes(test_file);
+    FILE* f = _wfopen(wTest_file.c_str(), L"w");
+    ASSERT_TRUE(f != nullptr);
+    fclose(f);
+  }
+
+  std::vector<std::string> result;
+  ASSERT_LEVELDB_OK(env_->GetChildren(test_dir, &result));
+  ASSERT_EQ(childFilesCount + 2, result.size()); // "." and ".." are returned.
+}
+
 }  // namespace leveldb
 
 int main(int argc, char** argv) {
