Merge "perfboot.py: warn if dm-verity is disabled"
diff --git a/adb/Android.mk b/adb/Android.mk
index 73b1a98..46905b3 100644
--- a/adb/Android.mk
+++ b/adb/Android.mk
@@ -67,7 +67,6 @@
     usb_linux.cpp \
 
 LIBADB_windows_SRC_FILES := \
-    get_my_path_windows.cpp \
     sysdeps_win32.cpp \
     usb_windows.cpp \
 
@@ -124,7 +123,9 @@
 LOCAL_SHARED_LIBRARIES := liblog libbase libcutils
 include $(BUILD_NATIVE_TEST)
 
-ifneq ($(HOST_OS),windows)
+# adb_test
+# =========================================================
+
 include $(CLEAR_VARS)
 LOCAL_CLANG := $(adb_host_clang)
 LOCAL_MODULE := adb_test
@@ -145,9 +146,13 @@
     LOCAL_LDLIBS += -framework CoreFoundation -framework IOKit
 endif
 
-include $(BUILD_HOST_NATIVE_TEST)
+ifeq ($(HOST_OS),windows)
+    LOCAL_LDLIBS += -lws2_32 -luserenv
+    LOCAL_STATIC_LIBRARIES += AdbWinApi
 endif
 
+include $(BUILD_HOST_NATIVE_TEST)
+
 # adb device tracker (used by ddms) test tool
 # =========================================================
 
@@ -179,6 +184,8 @@
 endif
 
 ifeq ($(HOST_OS),windows)
+    # Use wmain instead of main
+    LOCAL_LDFLAGS += -municode
     LOCAL_LDLIBS += -lws2_32 -lgdi32
     EXTRA_STATIC_LIBS := AdbWinApi
 endif
diff --git a/adb/adb.cpp b/adb/adb.cpp
index aa9ef55..c5ab7b0 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -35,6 +35,7 @@
 #include <unordered_map>
 
 #include <base/logging.h>
+#include <base/macros.h>
 #include <base/stringprintf.h>
 #include <base/strings.h>
 
@@ -557,9 +558,9 @@
     HANDLE                pipe_read, pipe_write;
     HANDLE                stdout_handle, stderr_handle;
     SECURITY_ATTRIBUTES   sa;
-    STARTUPINFO           startup;
+    STARTUPINFOW          startup;
     PROCESS_INFORMATION   pinfo;
-    char                  program_path[ MAX_PATH ];
+    WCHAR                 program_path[ MAX_PATH ];
     int                   ret;
 
     sa.nLength = sizeof(sa);
@@ -635,10 +636,18 @@
     ZeroMemory( &pinfo, sizeof(pinfo) );
 
     /* get path of current program */
-    GetModuleFileName( NULL, program_path, sizeof(program_path) );
-    char args[64];
-    snprintf(args, sizeof(args), "adb -P %d fork-server server",  server_port);
-    ret = CreateProcess(
+    DWORD module_result = GetModuleFileNameW(NULL, program_path,
+                                             arraysize(program_path));
+    if ((module_result == arraysize(program_path)) || (module_result == 0)) {
+        // String truncation or some other error.
+        fprintf(stderr, "GetModuleFileNameW() failure, error %ld\n",
+                GetLastError());
+        return -1;
+    }
+    WCHAR args[64];
+    snwprintf(args, arraysize(args),
+              L"adb -P %d fork-server server", server_port);
+    ret = CreateProcessW(
             program_path,                              /* program path  */
             args,
                                     /* the fork-server argument will set the
@@ -801,11 +810,13 @@
             return 1;
         }
 
+        std::string error;
         InstallStatus r;
         if (kill_forward) {
             r = remove_listener(pieces[0].c_str(), transport);
         } else {
-            r = install_listener(pieces[0], pieces[1].c_str(), transport, no_rebind);
+            r = install_listener(pieces[0], pieces[1].c_str(), transport,
+                                 no_rebind, &error);
         }
         if (r == INSTALL_STATUS_OK) {
 #if ADB_HOST
@@ -821,7 +832,8 @@
           case INSTALL_STATUS_OK: message = "success (!)"; break;
           case INSTALL_STATUS_INTERNAL_ERROR: message = "internal error"; break;
           case INSTALL_STATUS_CANNOT_BIND:
-            message = android::base::StringPrintf("cannot bind to socket: %s", strerror(errno));
+            message = android::base::StringPrintf("cannot bind to socket: %s",
+                                                  error.c_str());
             break;
           case INSTALL_STATUS_CANNOT_REBIND:
             message = android::base::StringPrintf("cannot rebind existing socket");
diff --git a/adb/adb_auth_host.cpp b/adb/adb_auth_host.cpp
index b6bb00c..966e61d 100644
--- a/adb/adb_auth_host.cpp
+++ b/adb/adb_auth_host.cpp
@@ -301,11 +301,15 @@
     char android_dir[PATH_MAX];
     struct stat buf;
 #ifdef _WIN32
-    char path[PATH_MAX];
+    std::string home_str;
     home = getenv("ANDROID_SDK_HOME");
     if (!home) {
-        SHGetFolderPath(NULL, CSIDL_PROFILE, NULL, 0, path);
-        home = path;
+        WCHAR path[MAX_PATH];
+        if (FAILED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path))) {
+            return -1;
+        }
+        home_str = narrow(path);
+        home = home_str.c_str();
     }
     format = "%s\\%s";
 #else
diff --git a/adb/adb_client.cpp b/adb/adb_client.cpp
index 418662c..6d75966 100644
--- a/adb/adb_client.cpp
+++ b/adb/adb_client.cpp
@@ -153,8 +153,8 @@
     }
 
     int fd;
+    std::string reason;
     if (__adb_server_name) {
-        std::string reason;
         fd = network_connect(__adb_server_name, __adb_server_port, SOCK_STREAM, 0, &reason);
         if (fd == -1) {
             *error = android::base::StringPrintf("can't connect to %s:%d: %s",
@@ -163,9 +163,10 @@
             return -2;
         }
     } else {
-        fd = socket_loopback_client(__adb_server_port, SOCK_STREAM);
+        fd = network_loopback_client(__adb_server_port, SOCK_STREAM, &reason);
         if (fd == -1) {
-            *error = perror_str("cannot connect to daemon");
+            *error = android::base::StringPrintf("cannot connect to daemon: %s",
+                                                 reason.c_str());
             return -2;
         }
     }
diff --git a/adb/adb_io_test.cpp b/adb/adb_io_test.cpp
index 0ae21db..f637073 100644
--- a/adb/adb_io_test.cpp
+++ b/adb/adb_io_test.cpp
@@ -30,6 +30,12 @@
 #include "base/file.h"
 #include "base/test_utils.h"
 
+// All of these tests fail on Windows because they use the C Runtime open(),
+// but the adb_io APIs expect file descriptors from adb_open(). Also, the
+// android::base file APIs use the C Runtime which uses CR/LF translation by
+// default (changeable with _setmode()), but the adb_io APIs use adb_read()
+// and adb_write() which do no translation.
+
 TEST(io, ReadFdExactly_whole) {
   const char expected[] = "Foobar";
   TemporaryFile tf;
diff --git a/adb/adb_listeners.cpp b/adb/adb_listeners.cpp
index bb45022..1e7ce5d 100644
--- a/adb/adb_listeners.cpp
+++ b/adb/adb_listeners.cpp
@@ -110,27 +110,30 @@
     free_listener(reinterpret_cast<alistener*>(listener));
 }
 
-static int local_name_to_fd(const char* name) {
+static int local_name_to_fd(const char* name, std::string* error) {
     if (!strncmp("tcp:", name, 4)) {
         int port = atoi(name + 4);
         if (gListenAll > 0) {
-            return socket_inaddr_any_server(port, SOCK_STREAM);
+            return network_inaddr_any_server(port, SOCK_STREAM, error);
         } else {
-            return socket_loopback_server(port, SOCK_STREAM);
+            return network_loopback_server(port, SOCK_STREAM, error);
         }
     }
 #if !defined(_WIN32)  // No Unix-domain sockets on Windows.
     // It's nonsensical to support the "reserved" space on the adb host side
     if (!strncmp(name, "local:", 6)) {
-        return socket_local_server(name + 6, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+        return network_local_server(name + 6,
+                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
     } else if (!strncmp(name, "localabstract:", 14)) {
-        return socket_local_server(name + 14, ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
+        return network_local_server(name + 14,
+                ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM, error);
     } else if (!strncmp(name, "localfilesystem:", 16)) {
-        return socket_local_server(name + 16, ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM);
+        return network_local_server(name + 16,
+                ANDROID_SOCKET_NAMESPACE_FILESYSTEM, SOCK_STREAM, error);
     }
 
 #endif
-    printf("unknown local portname '%s'\n", name);
+    *error = android::base::StringPrintf("unknown local portname '%s'", name);
     return -1;
 }
 
@@ -178,7 +181,8 @@
 InstallStatus install_listener(const std::string& local_name,
                                   const char *connect_to,
                                   atransport* transport,
-                                  int no_rebind)
+                                  int no_rebind,
+                                  std::string* error)
 {
     for (alistener* l = listener_list.next; l != &listener_list; l = l->next) {
         if (local_name == l->local_name) {
@@ -226,9 +230,9 @@
         goto nomem;
     }
 
-    listener->fd = local_name_to_fd(listener->local_name);
+    listener->fd = local_name_to_fd(listener->local_name, error);
     if (listener->fd < 0) {
-        printf("cannot bind '%s': %s\n", listener->local_name, strerror(errno));
+        printf("cannot bind '%s': %s\n", listener->local_name, error->c_str());
         free(listener->local_name);
         free(listener->connect_to);
         free(listener);
diff --git a/adb/adb_listeners.h b/adb/adb_listeners.h
index 67deb21..fa98eed 100644
--- a/adb/adb_listeners.h
+++ b/adb/adb_listeners.h
@@ -33,7 +33,8 @@
 InstallStatus install_listener(const std::string& local_name,
                                const char* connect_to,
                                atransport* transport,
-                               int no_rebind);
+                               int no_rebind,
+                               std::string* error);
 
 std::string format_listeners();
 
diff --git a/adb/adb_utils.cpp b/adb/adb_utils.cpp
index 3ba971d..ca843bd 100644
--- a/adb/adb_utils.cpp
+++ b/adb/adb_utils.cpp
@@ -18,6 +18,7 @@
 
 #include "adb_utils.h"
 
+#include <libgen.h>
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -28,16 +29,11 @@
 #include <base/logging.h>
 #include <base/stringprintf.h>
 #include <base/strings.h>
-#include <cutils/sockets.h>
 
 #include "adb_trace.h"
 #include "sysdeps.h"
 
-#if defined(_WIN32)
-#include <ws2tcpip.h>
-#else
-#include <netdb.h>
-#endif
+ADB_MUTEX_DEFINE(dirname_lock);
 
 bool getcwd(std::string* s) {
   char* cwd = getcwd(nullptr, 0);
@@ -73,35 +69,86 @@
 }
 
 std::string adb_basename(const std::string& path) {
-    size_t base = path.find_last_of(OS_PATH_SEPARATORS);
-    return (base != std::string::npos) ? path.substr(base + 1) : path;
+  size_t base = path.find_last_of(OS_PATH_SEPARATORS);
+  return (base != std::string::npos) ? path.substr(base + 1) : path;
 }
 
-static bool real_mkdirs(const std::string& path) {
-    std::vector<std::string> path_components = android::base::Split(path, OS_PATH_SEPARATOR_STR);
-    // TODO: all the callers do unlink && mkdirs && adb_creat ---
-    // that's probably the operation we should expose.
-    path_components.pop_back();
-    std::string partial_path;
-    for (const auto& path_component : path_components) {
-        if (partial_path.back() != OS_PATH_SEPARATOR) partial_path += OS_PATH_SEPARATOR;
-        partial_path += path_component;
-        if (adb_mkdir(partial_path.c_str(), 0775) == -1 && errno != EEXIST) {
-            return false;
-        }
-    }
-    return true;
+std::string adb_dirname(const std::string& path) {
+  // Copy path because dirname may modify the string passed in.
+  std::string parent_storage(path);
+
+  // Use lock because dirname() may write to a process global and return a
+  // pointer to that. Note that this locking strategy only works if all other
+  // callers to dirname in the process also grab this same lock.
+  adb_mutex_lock(&dirname_lock);
+
+  // Note that if std::string uses copy-on-write strings, &str[0] will cause
+  // the copy to be made, so there is no chance of us accidentally writing to
+  // the storage for 'path'.
+  char* parent = dirname(&parent_storage[0]);
+
+  // In case dirname returned a pointer to a process global, copy that string
+  // before leaving the lock.
+  const std::string result(parent);
+
+  adb_mutex_unlock(&dirname_lock);
+
+  return result;
 }
 
+// Given a relative or absolute filepath, create the parent directory hierarchy
+// as needed. Returns true if the hierarchy is/was setup.
 bool mkdirs(const std::string& path) {
-#if defined(_WIN32)
-    // Replace '/' with '\\' so we can share the code.
-    std::string clean_path = path;
-    std::replace(clean_path.begin(), clean_path.end(), '/', '\\');
-    return real_mkdirs(clean_path);
-#else
-    return real_mkdirs(path);
-#endif
+  // TODO: all the callers do unlink && mkdirs && adb_creat ---
+  // that's probably the operation we should expose.
+
+  // Implementation Notes:
+  //
+  // Pros:
+  // - Uses dirname, so does not need to deal with OS_PATH_SEPARATOR.
+  // - On Windows, uses mingw dirname which accepts '/' and '\\', drive letters
+  //   (C:\foo), UNC paths (\\server\share\dir\dir\file), and Unicode (when
+  //   combined with our adb_mkdir() which takes UTF-8).
+  // - Is optimistic wrt thinking that a deep directory hierarchy will exist.
+  //   So it does as few stat()s as possible before doing mkdir()s.
+  // Cons:
+  // - Recursive, so it uses stack space relative to number of directory
+  //   components.
+
+  const std::string parent(adb_dirname(path));
+
+  if (directory_exists(parent)) {
+    return true;
+  }
+
+  // If dirname returned the same path as what we passed in, don't go recursive.
+  // This can happen on Windows when walking up the directory hierarchy and not
+  // finding anything that already exists (unlike POSIX that will eventually
+  // find . or /).
+  if (parent == path) {
+    errno = ENOENT;
+    return false;
+  }
+
+  // Recursively make parent directories of 'parent'.
+  if (!mkdirs(parent)) {
+    return false;
+  }
+
+  // Now that the parent directory hierarchy of 'parent' has been ensured,
+  // create parent itself.
+  if (adb_mkdir(parent, 0775) == -1) {
+    // Can't just check for errno == EEXIST because it might be a file that
+    // exists.
+    const int saved_errno = errno;
+    if (directory_exists(parent)) {
+      return true;
+    }
+    errno = saved_errno;
+    return false;
+  }
+
+  return true;
 }
 
 void dump_hex(const void* data, size_t byte_count) {
@@ -178,18 +225,3 @@
                << " (" << *canonical_address << ")";
     return true;
 }
-
-int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
-    int getaddrinfo_error = 0;
-    int fd = socket_network_client_timeout(host.c_str(), port, type, timeout, &getaddrinfo_error);
-    if (fd != -1) {
-        return fd;
-    }
-    if (getaddrinfo_error != 0) {
-        // TODO: gai_strerror is not thread safe on Win32.
-        *error = gai_strerror(getaddrinfo_error);
-    } else {
-        *error = strerror(errno);
-    }
-    return -1;
-}
diff --git a/adb/adb_utils.h b/adb/adb_utils.h
index 30cd7a4..739efcc 100644
--- a/adb/adb_utils.h
+++ b/adb/adb_utils.h
@@ -21,7 +21,11 @@
 
 bool getcwd(std::string* cwd);
 bool directory_exists(const std::string& path);
+
+// Like the regular basename and dirname, but thread-safe on all
+// platforms and capable of correctly handling exotic Windows paths.
 std::string adb_basename(const std::string& path);
+std::string adb_dirname(const std::string& path);
 
 bool mkdirs(const std::string& path);
 
@@ -40,6 +44,4 @@
                          std::string* host, int* port,
                          std::string* error);
 
-int network_connect(const std::string& host, int port, int type, int timeout, std::string* error);
-
 #endif
diff --git a/adb/adb_utils_test.cpp b/adb/adb_utils_test.cpp
index 309ac02..34b54e7 100644
--- a/adb/adb_utils_test.cpp
+++ b/adb/adb_utils_test.cpp
@@ -16,6 +16,13 @@
 
 #include "adb_utils.h"
 
+#ifdef _WIN32
+#include <windows.h>
+#include <userenv.h>
+#endif
+
+#include <string>
+
 #include <gtest/gtest.h>
 
 #include <stdlib.h>
@@ -23,12 +30,46 @@
 
 #include "sysdeps.h"
 
+#include <base/macros.h>
 #include <base/test_utils.h>
 
+#ifdef _WIN32
+static std::string subdir(const char* parent, const char* child) {
+  std::string str(parent);
+  str += OS_PATH_SEPARATOR;
+  str += child;
+  return str;
+}
+#endif
+
 TEST(adb_utils, directory_exists) {
+#ifdef _WIN32
+  char profiles_dir[MAX_PATH];
+  DWORD cch = arraysize(profiles_dir);
+
+  // On typical Windows 7, returns C:\Users
+  ASSERT_TRUE(GetProfilesDirectory(profiles_dir, &cch));
+
+  ASSERT_TRUE(directory_exists(profiles_dir));
+
+  // On modern (English?) Windows, this is a directory symbolic link to
+  // C:\ProgramData. Symbolic links are rare on Windows and the user requires
+  // a special permission (by default granted to Administrative users) to
+  // create symbolic links.
+  ASSERT_FALSE(directory_exists(subdir(profiles_dir, "All Users")));
+
+  // On modern (English?) Windows, this is a directory junction to
+  // C:\Users\Default. Junctions are used throughout user profile directories
+  // for backwards compatibility and they don't require any special permissions
+  // to create.
+  ASSERT_FALSE(directory_exists(subdir(profiles_dir, "Default User")));
+
+  ASSERT_FALSE(directory_exists(subdir(profiles_dir, "does-not-exist")));
+#else
   ASSERT_TRUE(directory_exists("/proc"));
   ASSERT_FALSE(directory_exists("/proc/self")); // Symbolic link.
   ASSERT_FALSE(directory_exists("/proc/does-not-exist"));
+#endif
 }
 
 TEST(adb_utils, escape_arg) {
@@ -145,10 +186,19 @@
   EXPECT_FALSE(parse_host_and_port("1.2.3.4:65536", &canonical_address, &host, &port, &error));
 }
 
+void test_mkdirs(const std::string basepath) {
+  EXPECT_TRUE(mkdirs(basepath));
+  EXPECT_NE(-1, adb_creat(basepath.c_str(), 0600));
+  EXPECT_FALSE(mkdirs(basepath + "/subdir/"));
+}
+
 TEST(adb_utils, mkdirs) {
   TemporaryDir td;
-  std::string path = std::string(td.path) + "/dir/subdir/file";
-  EXPECT_TRUE(mkdirs(path));
-  EXPECT_NE(-1, adb_creat(path.c_str(), 0600));
-  EXPECT_FALSE(mkdirs(path + "/subdir/"));
+
+  // Absolute paths.
+  test_mkdirs(std::string(td.path) + "/dir/subdir/file");
+
+  // Relative paths.
+  ASSERT_EQ(0, chdir(td.path)) << strerror(errno);
+  test_mkdirs(std::string("relative/subrel/file"));
 }
diff --git a/adb/client/main.cpp b/adb/client/main.cpp
index c018b8a..6b48621 100644
--- a/adb/client/main.cpp
+++ b/adb/client/main.cpp
@@ -82,21 +82,22 @@
 
 static std::string GetLogFilePath() {
     const char log_name[] = "adb.log";
-    char temp_path[MAX_PATH - sizeof(log_name) + 1];
+    WCHAR temp_path[MAX_PATH];
 
     // https://msdn.microsoft.com/en-us/library/windows/desktop/aa364992%28v=vs.85%29.aspx
-    DWORD nchars = GetTempPath(sizeof(temp_path), temp_path);
-    CHECK_LE(nchars, sizeof(temp_path));
-    if (nchars == 0) {
-        // TODO(danalbert): Log the error message from FormatError().
-        // Windows unfortunately has two errnos, errno and GetLastError(), so
-        // I'm not sure what to do about PLOG here. Probably better to just
-        // ignore it and add a simplified version of FormatError() for use in
-        // log messages.
+    DWORD nchars = GetTempPathW(arraysize(temp_path), temp_path);
+    if ((nchars >= arraysize(temp_path)) || (nchars == 0)) {
+        // If string truncation or some other error.
+        // TODO(danalbert): Log the error message from
+        // FormatMessage(GetLastError()). Pure Windows APIs only touch
+        // GetLastError(), C Runtime APIs touch errno, so maybe there should be
+        // WPLOG or PLOGW (which would read GetLastError() instead of errno),
+        // in addition to PLOG, or maybe better to just ignore it and add a
+        // simplified version of FormatMessage() for use in log messages.
         LOG(ERROR) << "Error creating log file";
     }
 
-    return std::string(temp_path) + log_name;
+    return narrow(temp_path) + log_name;
 }
 #else
 static const char kNullFileName[] = "/dev/null";
@@ -150,9 +151,10 @@
     local_init(DEFAULT_ADB_LOCAL_TRANSPORT_PORT);
     adb_auth_init();
 
+    std::string error;
     std::string local_name = android::base::StringPrintf("tcp:%d", server_port);
-    if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
-        LOG(FATAL) << "Could not install *smartsocket* listener";
+    if (install_listener(local_name, "*smartsocket*", nullptr, 0, &error)) {
+        LOG(FATAL) << "Could not install *smartsocket* listener: " << error;
     }
 
     if (is_daemon) {
@@ -188,9 +190,35 @@
     return 0;
 }
 
+#ifdef _WIN32
+static bool _argv_is_utf8 = false;
+#endif
+
 int main(int argc, char** argv) {
+#ifdef _WIN32
+    if (!_argv_is_utf8) {
+        fatal("_argv_is_utf8 is not set, suggesting that wmain was not "
+              "called. Did you forget to link with -municode?");
+    }
+#endif
+
     adb_sysdeps_init();
     adb_trace_init(argv);
     D("Handling commandline()\n");
     return adb_commandline(argc - 1, const_cast<const char**>(argv + 1));
 }
+
+#ifdef _WIN32
+
+extern "C"
+int wmain(int argc, wchar_t **argv) {
+    // Set diagnostic flag to try to detect if the build system was not
+    // configured to call wmain.
+    _argv_is_utf8 = true;
+
+    // Convert args from UTF-16 to UTF-8 and pass that to main().
+    NarrowArgs narrow_args(argc, argv);
+    return main(argc, narrow_args.data());
+}
+
+#endif
diff --git a/adb/commandline.cpp b/adb/commandline.cpp
index 5e89f95..d7a0c8d 100644
--- a/adb/commandline.cpp
+++ b/adb/commandline.cpp
@@ -990,7 +990,7 @@
             /* this is a special flag used only when the ADB client launches the ADB Server */
             is_daemon = 1;
         } else if (!strncmp(argv[0], "-p", 2)) {
-            const char *product = NULL;
+            const char* product = nullptr;
             if (argv[0][2] == '\0') {
                 if (argc < 2) return usage();
                 product = argv[1];
@@ -999,7 +999,7 @@
             } else {
                 product = argv[0] + 2;
             }
-            if (product) gProductOutPath = find_product_out_path(product);
+            gProductOutPath = find_product_out_path(product);
             if (gProductOutPath.empty()) {
                 fprintf(stderr, "adb: could not resolve \"-p %s\"\n", product);
                 return usage();
diff --git a/adb/console.cpp b/adb/console.cpp
index b7f5345..ba5a72b 100644
--- a/adb/console.cpp
+++ b/adb/console.cpp
@@ -71,9 +71,11 @@
         return -1;
     }
 
-    int fd = socket_loopback_client(port, SOCK_STREAM);
+    std::string error;
+    int fd = network_loopback_client(port, SOCK_STREAM, &error);
     if (fd == -1) {
-        fprintf(stderr, "error: could not connect to TCP port %d\n", port);
+        fprintf(stderr, "error: could not connect to TCP port %d: %s\n", port,
+                error.c_str());
         return -1;
     }
     return fd;
diff --git a/adb/daemon/main.cpp b/adb/daemon/main.cpp
index 157c97b..dc89639 100644
--- a/adb/daemon/main.cpp
+++ b/adb/daemon/main.cpp
@@ -68,13 +68,6 @@
 #if defined(ALLOW_ADBD_ROOT)
     char value[PROPERTY_VALUE_MAX];
 
-    // The emulator is never secure, so don't drop privileges there.
-    // TODO: this seems like a bug --- shouldn't the emulator behave like a device?
-    property_get("ro.kernel.qemu", value, "");
-    if (strcmp(value, "1") == 0) {
-        return false;
-    }
-
     // The properties that affect `adb root` and `adb unroot` are ro.secure and
     // ro.debuggable. In this context the names don't make the expected behavior
     // particularly obvious.
@@ -177,10 +170,13 @@
                 LOG(FATAL) << "Could not set selinux context";
             }
         }
+        std::string error;
         std::string local_name =
             android::base::StringPrintf("tcp:%d", server_port);
-        if (install_listener(local_name, "*smartsocket*", nullptr, 0)) {
-            LOG(FATAL) << "Could not install *smartsocket* listener";
+        if (install_listener(local_name, "*smartsocket*", nullptr, 0,
+                             &error)) {
+            LOG(FATAL) << "Could not install *smartsocket* listener: "
+                << error;
         }
     }
 
diff --git a/adb/get_my_path_windows.cpp b/adb/get_my_path_windows.cpp
deleted file mode 100644
index 9d23e1c..0000000
--- a/adb/get_my_path_windows.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Copyright (C) 2007 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <assert.h>
-#include <limits.h>
-#include <windows.h>
-
-#include "adb.h"
-
-void get_my_path(char *exe, size_t maxLen)
-{
-    char  *r;
-
-    /* XXX: should be GetModuleFileNameA */
-    if (GetModuleFileName(NULL, exe, maxLen) > 0) {
-        r = strrchr(exe, '\\');
-        if (r != NULL)
-            *r = '\0';
-    } else {
-        exe[0] = '\0';
-    }
-}
-
diff --git a/adb/mutex_list.h b/adb/mutex_list.h
index ff72751..9003361 100644
--- a/adb/mutex_list.h
+++ b/adb/mutex_list.h
@@ -6,6 +6,7 @@
 #ifndef ADB_MUTEX
 #error ADB_MUTEX not defined when including this file
 #endif
+ADB_MUTEX(dirname_lock)
 ADB_MUTEX(socket_list_lock)
 ADB_MUTEX(transport_lock)
 #if ADB_HOST
diff --git a/adb/services.cpp b/adb/services.cpp
index 708ef42..63a0a76 100644
--- a/adb/services.cpp
+++ b/adb/services.cpp
@@ -432,7 +432,8 @@
         int port = atoi(name + 4);
         name = strchr(name + 4, ':');
         if(name == 0) {
-            ret = socket_loopback_client(port, SOCK_STREAM);
+            std::string error;
+            ret = network_loopback_client(port, SOCK_STREAM, &error);
             if (ret >= 0)
                 disable_tcp_nagle(ret);
         } else {
diff --git a/adb/sysdeps.h b/adb/sysdeps.h
index c033999..9189955 100644
--- a/adb/sysdeps.h
+++ b/adb/sysdeps.h
@@ -26,6 +26,8 @@
 
 #include <errno.h>
 
+#include <string>
+
 /*
  * TEMP_FAILURE_RETRY is defined by some, but not all, versions of
  * <unistd.h>. (Alas, it is not as standard as we'd hoped!) So, if it's
@@ -41,20 +43,35 @@
     _rc; })
 #endif
 
+// Some printf-like functions are implemented in terms of
+// android::base::StringAppendV, so they should use the same attribute for
+// compile-time format string checking. On Windows, if the mingw version of
+// vsnprintf is used in StringAppendV, use `gnu_printf' which allows z in %zd
+// and PRIu64 (and related) to be recognized by the compile-time checking.
+#define ADB_FORMAT_ARCHETYPE __printf__
+#ifdef __USE_MINGW_ANSI_STDIO
+#if __USE_MINGW_ANSI_STDIO
+#undef ADB_FORMAT_ARCHETYPE
+#define ADB_FORMAT_ARCHETYPE gnu_printf
+#endif
+#endif
+
 #ifdef _WIN32
 
 #include <ctype.h>
 #include <direct.h>
+#include <dirent.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <io.h>
 #include <process.h>
 #include <sys/stat.h>
+#include <utime.h>
 #include <winsock2.h>
 #include <windows.h>
 #include <ws2tcpip.h>
 
-#include <string>
+#include <string>   // Prototypes for narrow() and widen() use std::(w)string.
 
 #include "fdevent.h"
 
@@ -107,25 +124,11 @@
 
 #define  S_ISLNK(m)   0   /* no symlinks on Win32 */
 
-static __inline__  int    adb_unlink(const char*  path)
-{
-    int  rc = unlink(path);
-
-    if (rc == -1 && errno == EACCES) {
-        /* unlink returns EACCES when the file is read-only, so we first */
-        /* try to make it writable, then unlink again...                  */
-        rc = chmod(path, _S_IREAD|_S_IWRITE );
-        if (rc == 0)
-            rc = unlink(path);
-    }
-    return rc;
-}
+extern int  adb_unlink(const char*  path);
 #undef  unlink
 #define unlink  ___xxx_unlink
 
-static __inline__ int adb_mkdir(const std::string& path, int mode) {
-	return _mkdir(path.c_str());
-}
+extern int adb_mkdir(const std::string& path, int mode);
 #undef   mkdir
 #define  mkdir  ___xxx_mkdir
 
@@ -167,22 +170,7 @@
 }
 
 // See the comments for the !defined(_WIN32) version of unix_open().
-static __inline__ int  unix_open(const char*  path, int options,...)
-{
-    if ((options & O_CREAT) == 0)
-    {
-        return  open(path, options);
-    }
-    else
-    {
-        int      mode;
-        va_list  args;
-        va_start( args, options );
-        mode = va_arg( args, int );
-        va_end( args );
-        return open(path, options, mode);
-    }
-}
+extern int unix_open(const char* path, int options, ...);
 #define  open    ___xxx_unix_open
 
 
@@ -212,6 +200,12 @@
     Sleep( mseconds );
 }
 
+int network_loopback_client(int port, int type, std::string* error);
+int network_loopback_server(int port, int type, std::string* error);
+int network_inaddr_any_server(int port, int type, std::string* error);
+int network_connect(const std::string& host, int port, int type, int timeout,
+                    std::string* error);
+
 extern int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen);
 
 #undef   accept
@@ -240,10 +234,115 @@
     return isalpha(path[0]) && path[1] == ':' && path[2] == '\\';
 }
 
+// Like strerror(), but for Win32 error codes.
+std::string SystemErrorCodeToString(DWORD error_code);
+
+// We later define a macro mapping 'stat' to 'adb_stat'. This causes:
+//   struct stat s;
+//   stat(filename, &s);
+// To turn into the following:
+//   struct adb_stat s;
+//   adb_stat(filename, &s);
+// To get this to work, we need to make 'struct adb_stat' the same as
+// 'struct stat'. Note that this definition of 'struct adb_stat' uses the
+// *current* macro definition of stat, so it may actually be inheriting from
+// struct _stat32i64 (or some other remapping).
+struct adb_stat : public stat {};
+
+static_assert(sizeof(struct adb_stat) == sizeof(struct stat),
+    "structures should be the same");
+
+extern int adb_stat(const char* f, struct adb_stat* s);
+
+// stat is already a macro, undefine it so we can redefine it.
+#undef stat
+#define stat adb_stat
+
+// UTF-8 versions of POSIX APIs.
+extern DIR* adb_opendir(const char* dirname);
+extern struct dirent* adb_readdir(DIR* dir);
+extern int adb_closedir(DIR* dir);
+
+extern int adb_utime(const char *, struct utimbuf *);
+extern int adb_chmod(const char *, int);
+
+extern int adb_vfprintf(FILE *stream, const char *format, va_list ap)
+    __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 0)));
+extern int adb_fprintf(FILE *stream, const char *format, ...)
+    __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 2, 3)));
+extern int adb_printf(const char *format, ...)
+    __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 1, 2)));
+
+extern int adb_fputs(const char* buf, FILE* stream);
+extern int adb_fputc(int ch, FILE* stream);
+extern size_t adb_fwrite(const void* ptr, size_t size, size_t nmemb,
+                         FILE* stream);
+
+extern FILE* adb_fopen(const char* f, const char* m);
+
+extern char* adb_getenv(const char* name);
+
+extern char* adb_getcwd(char* buf, int size);
+
+// Remap calls to POSIX APIs to our UTF-8 versions.
+#define opendir adb_opendir
+#define readdir adb_readdir
+#define closedir adb_closedir
+#define rewinddir rewinddir_utf8_not_yet_implemented
+#define telldir telldir_utf8_not_yet_implemented
+#define seekdir seekdir_utf8_not_yet_implemented
+
+#define utime adb_utime
+#define chmod adb_chmod
+
+#define vfprintf adb_vfprintf
+#define fprintf adb_fprintf
+#define printf adb_printf
+#define fputs adb_fputs
+#define fputc adb_fputc
+#define fwrite adb_fwrite
+
+#define fopen adb_fopen
+
+#define getenv adb_getenv
+#define putenv putenv_utf8_not_yet_implemented
+#define setenv setenv_utf8_not_yet_implemented
+#define unsetenv unsetenv_utf8_not_yet_implemented
+
+#define getcwd adb_getcwd
+
+// Convert from UTF-8 to UTF-16, typically used to convert char strings into
+// wchar_t strings that can be passed to wchar_t-based OS and C Runtime APIs
+// on Windows.
+extern std::wstring widen(const std::string& utf8);
+extern std::wstring widen(const char* utf8);
+
+// Convert from UTF-16 to UTF-8, typically used to convert strings from OS and
+// C Runtime APIs that return wchar_t, to a format for our char-based data
+// structures.
+extern std::string narrow(const std::wstring& utf16);
+extern std::string narrow(const wchar_t* utf16);
+
+// Helper class to convert UTF-16 argv from wmain() to UTF-8 args that can be
+// passed to main().
+class NarrowArgs {
+public:
+    NarrowArgs(int argc, wchar_t** argv);
+    ~NarrowArgs();
+
+    inline char** data() {
+        return narrow_args;
+    }
+
+private:
+    char** narrow_args;
+};
+
 #else /* !_WIN32 a.k.a. Unix */
 
 #include "fdevent.h"
 #include <cutils/misc.h>
+#include <cutils/sockets.h>
 #include <cutils/threads.h>
 #include <signal.h>
 #include <sys/wait.h>
@@ -254,6 +353,7 @@
 #include <unistd.h>
 #include <fcntl.h>
 #include <stdarg.h>
+#include <netdb.h>
 #include <netinet/in.h>
 #include <netinet/tcp.h>
 #include <string.h>
@@ -404,6 +504,48 @@
 #undef   creat
 #define  creat  ___xxx_creat
 
+// Helper for network_* functions.
+inline int _fd_set_error_str(int fd, std::string* error) {
+  if (fd == -1) {
+    *error = strerror(errno);
+  }
+  return fd;
+}
+
+inline int network_loopback_client(int port, int type, std::string* error) {
+  return _fd_set_error_str(socket_loopback_client(port, type), error);
+}
+
+inline int network_loopback_server(int port, int type, std::string* error) {
+  return _fd_set_error_str(socket_loopback_server(port, type), error);
+}
+
+inline int network_inaddr_any_server(int port, int type, std::string* error) {
+  return _fd_set_error_str(socket_inaddr_any_server(port, type), error);
+}
+
+inline int network_local_server(const char *name, int namespace_id, int type,
+                                std::string* error) {
+  return _fd_set_error_str(socket_local_server(name, namespace_id, type),
+                           error);
+}
+
+inline int network_connect(const std::string& host, int port, int type,
+                           int timeout, std::string* error) {
+  int getaddrinfo_error = 0;
+  int fd = socket_network_client_timeout(host.c_str(), port, type, timeout,
+                                         &getaddrinfo_error);
+  if (fd != -1) {
+    return fd;
+  }
+  if (getaddrinfo_error != 0) {
+    *error = gai_strerror(getaddrinfo_error);
+  } else {
+    *error = strerror(errno);
+  }
+  return -1;
+}
+
 static __inline__ int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
 {
     int fd;
diff --git a/adb/sysdeps_win32.cpp b/adb/sysdeps_win32.cpp
index a274892..08f267b 100644
--- a/adb/sysdeps_win32.cpp
+++ b/adb/sysdeps_win32.cpp
@@ -25,8 +25,16 @@
 #include <stdio.h>
 #include <stdlib.h>
 
+#include <memory>
+#include <string>
+#include <unordered_map>
+
 #include <cutils/sockets.h>
 
+#include <base/logging.h>
+#include <base/stringprintf.h>
+#include <base/strings.h>
+
 #include "adb.h"
 
 extern void fatal(const char *fmt, ...);
@@ -80,6 +88,29 @@
 
 #define assert(cond)  do { if (!(cond)) fatal( "assertion failed '%s' on %s:%ld\n", #cond, __FILE__, __LINE__ ); } while (0)
 
+std::string SystemErrorCodeToString(const DWORD error_code) {
+  const int kErrorMessageBufferSize = 256;
+  char msgbuf[kErrorMessageBufferSize];
+  DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
+  DWORD len = FormatMessageA(flags, nullptr, error_code, 0, msgbuf,
+                             arraysize(msgbuf), nullptr);
+  if (len == 0) {
+    return android::base::StringPrintf(
+        "Error (%lu) while retrieving error. (%lu)", GetLastError(),
+        error_code);
+  }
+
+  std::string msg(msgbuf);
+  // Messages returned by the system end with line breaks.
+  msg = android::base::Trim(msg);
+  // There are many Windows error messages compared to POSIX, so include the
+  // numeric error code for easier, quicker, accurate identification. Use
+  // decimal instead of hex because there are decimal ranges like 10000-11999
+  // for Winsock.
+  android::base::StringAppendF(&msg, " (%lu)", error_code);
+  return msg;
+}
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -94,13 +125,13 @@
     char     *data;
     DWORD     file_size;
 
-    file = CreateFile( fn,
-                       GENERIC_READ,
-                       FILE_SHARE_READ,
-                       NULL,
-                       OPEN_EXISTING,
-                       0,
-                       NULL );
+    file = CreateFileW( widen(fn).c_str(),
+                        GENERIC_READ,
+                        FILE_SHARE_READ,
+                        NULL,
+                        OPEN_EXISTING,
+                        0,
+                        NULL );
 
     if (file == INVALID_HANDLE_VALUE)
         return NULL;
@@ -253,6 +284,23 @@
     return 0;
 }
 
+// Deleter for unique_fh.
+class fh_deleter {
+ public:
+  void operator()(struct FHRec_* fh) {
+    // We're called from a destructor and destructors should not overwrite
+    // errno because callers may do:
+    //   errno = EBLAH;
+    //   return -1; // calls destructor, which should not overwrite errno
+    const int saved_errno = errno;
+    _fh_close(fh);
+    errno = saved_errno;
+  }
+};
+
+// Like std::unique_ptr, but calls _fh_close() instead of operator delete().
+typedef std::unique_ptr<struct FHRec_, fh_deleter> unique_fh;
+
 /**************************************************************************/
 /**************************************************************************/
 /*****                                                                *****/
@@ -359,8 +407,8 @@
         return -1;
     }
 
-    f->fh_handle = CreateFile( path, desiredAccess, shareMode, NULL, OPEN_EXISTING,
-                               0, NULL );
+    f->fh_handle = CreateFileW( widen(path).c_str(), desiredAccess, shareMode,
+                                NULL, OPEN_EXISTING, 0, NULL );
 
     if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
         const DWORD err = GetLastError();
@@ -400,9 +448,10 @@
         return -1;
     }
 
-    f->fh_handle = CreateFile( path, GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE,
-                               NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
-                               NULL );
+    f->fh_handle = CreateFileW( widen(path).c_str(), GENERIC_WRITE,
+                                FILE_SHARE_READ | FILE_SHARE_WRITE,
+                                NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,
+                                NULL );
 
     if ( f->fh_handle == INVALID_HANDLE_VALUE ) {
         const DWORD err = GetLastError();
@@ -467,21 +516,6 @@
 }
 
 
-int  adb_shutdown(int  fd)
-{
-    FH   f = _fh_from_int(fd, __func__);
-
-    if (!f || f->clazz != &_fh_socket_class) {
-        D("adb_shutdown: invalid fd %d\n", fd);
-        return -1;
-    }
-
-    D( "adb_shutdown: %s\n", f->name);
-    shutdown( f->fh_socket, SD_BOTH );
-    return 0;
-}
-
-
 int  adb_close(int  fd)
 {
     FH   f = _fh_from_int(fd, __func__);
@@ -505,29 +539,63 @@
 
 #undef setsockopt
 
-static void _socket_set_errno( void ) {
-    switch (WSAGetLastError()) {
+static void _socket_set_errno( const DWORD err ) {
+    // The Windows C Runtime (MSVCRT.DLL) strerror() does not support a lot of
+    // POSIX and socket error codes, so this can only meaningfully map so much.
+    switch ( err ) {
     case 0:              errno = 0; break;
     case WSAEWOULDBLOCK: errno = EAGAIN; break;
     case WSAEINTR:       errno = EINTR; break;
+    case WSAEFAULT:      errno = EFAULT; break;
+    case WSAEINVAL:      errno = EINVAL; break;
+    case WSAEMFILE:      errno = EMFILE; break;
     default:
-        D( "_socket_set_errno: unhandled value %d\n", WSAGetLastError() );
         errno = EINVAL;
+        D( "_socket_set_errno: mapping Windows error code %lu to errno %d\n",
+           err, errno );
     }
 }
 
 static void _fh_socket_init( FH  f ) {
     f->fh_socket = INVALID_SOCKET;
     f->event     = WSACreateEvent();
+    if (f->event == WSA_INVALID_EVENT) {
+        D("WSACreateEvent failed: %s\n",
+          SystemErrorCodeToString(WSAGetLastError()).c_str());
+
+        // _event_socket_start assumes that this field is INVALID_HANDLE_VALUE
+        // on failure, instead of NULL which is what Windows really returns on
+        // error. It might be better to change all the other code to look for
+        // NULL, but that is a much riskier change.
+        f->event = INVALID_HANDLE_VALUE;
+    }
     f->mask      = 0;
 }
 
 static int _fh_socket_close( FH  f ) {
-    /* gently tell any peer that we're closing the socket */
-    shutdown( f->fh_socket, SD_BOTH );
-    closesocket( f->fh_socket );
-    f->fh_socket = INVALID_SOCKET;
-    CloseHandle( f->event );
+    if (f->fh_socket != INVALID_SOCKET) {
+        /* gently tell any peer that we're closing the socket */
+        if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
+            // If the socket is not connected, this returns an error. We want to
+            // minimize logging spam, so don't log these errors for now.
+#if 0
+            D("socket shutdown failed: %s\n",
+              SystemErrorCodeToString(WSAGetLastError()).c_str());
+#endif
+        }
+        if (closesocket(f->fh_socket) == SOCKET_ERROR) {
+            D("closesocket failed: %s\n",
+              SystemErrorCodeToString(WSAGetLastError()).c_str());
+        }
+        f->fh_socket = INVALID_SOCKET;
+    }
+    if (f->event != NULL) {
+        if (!CloseHandle(f->event)) {
+            D("CloseHandle failed: %s\n",
+              SystemErrorCodeToString(GetLastError()).c_str());
+        }
+        f->event = NULL;
+    }
     f->mask = 0;
     return 0;
 }
@@ -540,7 +608,10 @@
 static int _fh_socket_read(FH f, void* buf, int len) {
     int  result = recv(f->fh_socket, reinterpret_cast<char*>(buf), len, 0);
     if (result == SOCKET_ERROR) {
-        _socket_set_errno();
+        const DWORD err = WSAGetLastError();
+        D("recv fd %d failed: %s\n", _fh_to_int(f),
+          SystemErrorCodeToString(err).c_str());
+        _socket_set_errno(err);
         result = -1;
     }
     return  result;
@@ -549,7 +620,10 @@
 static int _fh_socket_write(FH f, const void* buf, int len) {
     int  result = send(f->fh_socket, reinterpret_cast<const char*>(buf), len, 0);
     if (result == SOCKET_ERROR) {
-        _socket_set_errno();
+        const DWORD err = WSAGetLastError();
+        D("send fd %d failed: %s\n", _fh_to_int(f),
+          SystemErrorCodeToString(err).c_str());
+        _socket_set_errno(err);
         result = -1;
     }
     return result;
@@ -570,31 +644,39 @@
 static void
 _cleanup_winsock( void )
 {
+    // TODO: WSAStartup() might be called multiple times and this won't properly
+    // cleanup the right number of times. Plus, WSACleanup() probably doesn't
+    // make sense since it might interrupt other threads using Winsock (since
+    // our various threads are not explicitly cleanly shutdown at process exit).
     WSACleanup();
 }
 
 static void
 _init_winsock( void )
 {
+    // TODO: Multiple threads calling this may potentially cause multiple calls
+    // to WSAStartup() and multiple atexit() calls.
     if (!_winsock_init) {
         WSADATA  wsaData;
         int      rc = WSAStartup( MAKEWORD(2,2), &wsaData);
         if (rc != 0) {
-            fatal( "adb: could not initialize Winsock\n" );
+            fatal( "adb: could not initialize Winsock: %s",
+                   SystemErrorCodeToString( rc ).c_str());
         }
         atexit( _cleanup_winsock );
         _winsock_init = 1;
     }
 }
 
-int socket_loopback_client(int port, int type)
-{
-    FH  f = _fh_alloc( &_fh_socket_class );
+int network_loopback_client(int port, int type, std::string* error) {
     struct sockaddr_in addr;
     SOCKET  s;
 
-    if (!f)
+    unique_fh  f(_fh_alloc(&_fh_socket_class));
+    if (!f) {
+        *error = strerror(errno);
         return -1;
+    }
 
     if (!_winsock_init)
         _init_winsock();
@@ -606,32 +688,40 @@
 
     s = socket(AF_INET, type, 0);
     if(s == INVALID_SOCKET) {
-        D("socket_loopback_client: could not create socket\n" );
-        _fh_close(f);
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("could not create socket: %s\n", error->c_str());
+        return -1;
+    }
+    f->fh_socket = s;
+
+    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("could not connect to %s:%d: %s\n",
+          type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
         return -1;
     }
 
-    f->fh_socket = s;
-    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        D("socket_loopback_client: could not connect to %s:%d\n", type != SOCK_STREAM ? "udp" : "tcp", port );
-        _fh_close(f);
-        return -1;
-    }
-    snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
-    D( "socket_loopback_client: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
-    return _fh_to_int(f);
+    const int fd = _fh_to_int(f.get());
+    snprintf( f->name, sizeof(f->name), "%d(lo-client:%s%d)", fd,
+              type != SOCK_STREAM ? "udp:" : "", port );
+    D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
+       fd );
+    f.release();
+    return fd;
 }
 
 #define LISTEN_BACKLOG 4
 
-int socket_loopback_server(int port, int type)
-{
-    FH   f = _fh_alloc( &_fh_socket_class );
+// interface_address is INADDR_LOOPBACK or INADDR_ANY.
+static int _network_server(int port, int type, u_long interface_address,
+                           std::string* error) {
     struct sockaddr_in addr;
     SOCKET  s;
     int  n;
 
+    unique_fh   f(_fh_alloc(&_fh_socket_class));
     if (!f) {
+        *error = strerror(errno);
         return -1;
     }
 
@@ -641,149 +731,151 @@
     memset(&addr, 0, sizeof(addr));
     addr.sin_family = AF_INET;
     addr.sin_port = htons(port);
-    addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+    addr.sin_addr.s_addr = htonl(interface_address);
 
+    // TODO: Consider using dual-stack socket that can simultaneously listen on
+    // IPv4 and IPv6.
     s = socket(AF_INET, type, 0);
-    if(s == INVALID_SOCKET) return -1;
+    if (s == INVALID_SOCKET) {
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("could not create socket: %s\n", error->c_str());
+        return -1;
+    }
 
     f->fh_socket = s;
 
     n = 1;
-    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
+    if (setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n,
+                   sizeof(n)) == SOCKET_ERROR) {
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("setsockopt level %d optname %d failed: %s\n",
+          SOL_SOCKET, SO_EXCLUSIVEADDRUSE, error->c_str());
+        return -1;
+    }
 
-    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        _fh_close(f);
+    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) == SOCKET_ERROR) {
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("could not bind to %s:%d: %s\n",
+          type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
         return -1;
     }
     if (type == SOCK_STREAM) {
-        int ret;
-
-        ret = listen(s, LISTEN_BACKLOG);
-        if (ret < 0) {
-            _fh_close(f);
+        if (listen(s, LISTEN_BACKLOG) == SOCKET_ERROR) {
+            *error = SystemErrorCodeToString(WSAGetLastError());
+            D("could not listen on %s:%d: %s\n",
+              type != SOCK_STREAM ? "udp" : "tcp", port, error->c_str());
             return -1;
         }
     }
-    snprintf( f->name, sizeof(f->name), "%d(lo-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
-    D( "socket_loopback_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
-    return _fh_to_int(f);
+    const int fd = _fh_to_int(f.get());
+    snprintf( f->name, sizeof(f->name), "%d(%s-server:%s%d)", fd,
+              interface_address == INADDR_LOOPBACK ? "lo" : "any",
+              type != SOCK_STREAM ? "udp:" : "", port );
+    D( "port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp",
+       fd );
+    f.release();
+    return fd;
 }
 
+int network_loopback_server(int port, int type, std::string* error) {
+    return _network_server(port, type, INADDR_LOOPBACK, error);
+}
 
-int socket_network_client_timeout(const char *host, int port, int type, int timeout,
-                                  int* getaddrinfo_error) {
-    FH  f = _fh_alloc( &_fh_socket_class );
-    if (!f) return -1;
+int network_inaddr_any_server(int port, int type, std::string* error) {
+    return _network_server(port, type, INADDR_ANY, error);
+}
+
+int network_connect(const std::string& host, int port, int type, int timeout, std::string* error) {
+    unique_fh f(_fh_alloc(&_fh_socket_class));
+    if (!f) {
+        *error = strerror(errno);
+        return -1;
+    }
 
     if (!_winsock_init) _init_winsock();
 
-    hostent* hp = gethostbyname(host);
-    if(hp == 0) {
-        _fh_close(f);
+    struct addrinfo hints;
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = AF_UNSPEC;
+    hints.ai_socktype = type;
+
+    char port_str[16];
+    snprintf(port_str, sizeof(port_str), "%d", port);
+
+    struct addrinfo* addrinfo_ptr = nullptr;
+    if (getaddrinfo(host.c_str(), port_str, &hints, &addrinfo_ptr) != 0) {
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("could not resolve host '%s' and port %s: %s\n", host.c_str(),
+          port_str, error->c_str());
         return -1;
     }
+    std::unique_ptr<struct addrinfo, decltype(freeaddrinfo)*>
+        addrinfo(addrinfo_ptr, freeaddrinfo);
+    addrinfo_ptr = nullptr;
 
-    sockaddr_in addr;
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = hp->h_addrtype;
-    addr.sin_port = htons(port);
-    memcpy(&addr.sin_addr, hp->h_addr, hp->h_length);
-
-    SOCKET s = socket(hp->h_addrtype, type, 0);
+    // TODO: Try all the addresses if there's more than one? This just uses
+    // the first. Or, could call WSAConnectByName() (Windows Vista and newer)
+    // which tries all addresses, takes a timeout and more.
+    SOCKET s = socket(addrinfo->ai_family, addrinfo->ai_socktype,
+                      addrinfo->ai_protocol);
     if(s == INVALID_SOCKET) {
-        _fh_close(f);
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("could not create socket: %s\n", error->c_str());
         return -1;
     }
     f->fh_socket = s;
 
-    // TODO: implement timeouts for Windows.
-
-    if(connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        _fh_close(f);
+    // TODO: Implement timeouts for Windows. Seems like the default in theory
+    // (according to http://serverfault.com/a/671453) and in practice is 21 sec.
+    if(connect(s, addrinfo->ai_addr, addrinfo->ai_addrlen) == SOCKET_ERROR) {
+        *error = SystemErrorCodeToString(WSAGetLastError());
+        D("could not connect to %s:%s:%s: %s\n",
+          type != SOCK_STREAM ? "udp" : "tcp", host.c_str(), port_str,
+          error->c_str());
         return -1;
     }
 
-    snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
-    D( "socket_network_client_timeout: host '%s' port %d type %s => fd %d\n", host, port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
-    return _fh_to_int(f);
-}
-
-
-int socket_inaddr_any_server(int port, int type)
-{
-    FH  f = _fh_alloc( &_fh_socket_class );
-    struct sockaddr_in addr;
-    SOCKET  s;
-    int n;
-
-    if (!f)
-        return -1;
-
-    if (!_winsock_init)
-        _init_winsock();
-
-    memset(&addr, 0, sizeof(addr));
-    addr.sin_family = AF_INET;
-    addr.sin_port = htons(port);
-    addr.sin_addr.s_addr = htonl(INADDR_ANY);
-
-    s = socket(AF_INET, type, 0);
-    if(s == INVALID_SOCKET) {
-        _fh_close(f);
-        return -1;
-    }
-
-    f->fh_socket = s;
-    n = 1;
-    setsockopt(s, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (const char*)&n, sizeof(n));
-
-    if(bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-        _fh_close(f);
-        return -1;
-    }
-
-    if (type == SOCK_STREAM) {
-        int ret;
-
-        ret = listen(s, LISTEN_BACKLOG);
-        if (ret < 0) {
-            _fh_close(f);
-            return -1;
-        }
-    }
-    snprintf( f->name, sizeof(f->name), "%d(any-server:%s%d)", _fh_to_int(f), type != SOCK_STREAM ? "udp:" : "", port );
-    D( "socket_inaddr_server: port %d type %s => fd %d\n", port, type != SOCK_STREAM ? "udp" : "tcp", _fh_to_int(f) );
-    return _fh_to_int(f);
+    const int fd = _fh_to_int(f.get());
+    snprintf( f->name, sizeof(f->name), "%d(net-client:%s%d)", fd,
+              type != SOCK_STREAM ? "udp:" : "", port );
+    D( "host '%s' port %d type %s => fd %d\n", host.c_str(), port,
+       type != SOCK_STREAM ? "udp" : "tcp", fd );
+    f.release();
+    return fd;
 }
 
 #undef accept
 int  adb_socket_accept(int  serverfd, struct sockaddr*  addr, socklen_t  *addrlen)
 {
     FH   serverfh = _fh_from_int(serverfd, __func__);
-    FH   fh;
 
     if ( !serverfh || serverfh->clazz != &_fh_socket_class ) {
-        D( "adb_socket_accept: invalid fd %d\n", serverfd );
+        D("adb_socket_accept: invalid fd %d\n", serverfd);
+        errno = EBADF;
         return -1;
     }
 
-    fh = _fh_alloc( &_fh_socket_class );
+    unique_fh fh(_fh_alloc( &_fh_socket_class ));
     if (!fh) {
-        D( "adb_socket_accept: not enough memory to allocate accepted socket descriptor\n" );
+        PLOG(ERROR) << "adb_socket_accept: failed to allocate accepted socket "
+                       "descriptor";
         return -1;
     }
 
     fh->fh_socket = accept( serverfh->fh_socket, addr, addrlen );
     if (fh->fh_socket == INVALID_SOCKET) {
         const DWORD err = WSAGetLastError();
-        _fh_close( fh );
-        D( "adb_socket_accept: accept on fd %d return error %ld\n", serverfd, err );
+        LOG(ERROR) << "adb_socket_accept: accept on fd " << serverfd <<
+                      " failed: " + SystemErrorCodeToString(err);
+        _socket_set_errno( err );
         return -1;
     }
 
-    snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", _fh_to_int(fh), serverfh->name );
-    D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, _fh_to_int(fh) );
-    return  _fh_to_int(fh);
+    const int fd = _fh_to_int(fh.get());
+    snprintf( fh->name, sizeof(fh->name), "%d(accept:%s)", fd, serverfh->name );
+    D( "adb_socket_accept on fd %d returns fd %d\n", serverfd, fd );
+    fh.release();
+    return  fd;
 }
 
 
@@ -793,10 +885,42 @@
 
     if ( !fh || fh->clazz != &_fh_socket_class ) {
         D("adb_setsockopt: invalid fd %d\n", fd);
+        errno = EBADF;
+        return -1;
+    }
+    int result = setsockopt( fh->fh_socket, level, optname,
+                             reinterpret_cast<const char*>(optval), optlen );
+    if ( result == SOCKET_ERROR ) {
+        const DWORD err = WSAGetLastError();
+        D( "adb_setsockopt: setsockopt on fd %d level %d optname %d "
+           "failed: %s\n", fd, level, optname,
+           SystemErrorCodeToString(err).c_str() );
+        _socket_set_errno( err );
+        result = -1;
+    }
+    return result;
+}
+
+
+int  adb_shutdown(int  fd)
+{
+    FH   f = _fh_from_int(fd, __func__);
+
+    if (!f || f->clazz != &_fh_socket_class) {
+        D("adb_shutdown: invalid fd %d\n", fd);
+        errno = EBADF;
         return -1;
     }
 
-    return setsockopt( fh->fh_socket, level, optname, reinterpret_cast<const char*>(optval), optlen );
+    D( "adb_shutdown: %s\n", f->name);
+    if (shutdown(f->fh_socket, SD_BOTH) == SOCKET_ERROR) {
+        const DWORD err = WSAGetLastError();
+        D("socket shutdown fd %d failed: %s\n", fd,
+          SystemErrorCodeToString(err).c_str());
+        _socket_set_errno(err);
+        return -1;
+    }
+    return 0;
 }
 
 /**************************************************************************/
@@ -1199,16 +1323,19 @@
 int  adb_socketpair(int sv[2]) {
     SocketPair pair;
 
-    FH fa = _fh_alloc(&_fh_socketpair_class);
-    FH fb = _fh_alloc(&_fh_socketpair_class);
-
-    if (!fa || !fb)
-        goto Fail;
+    unique_fh fa(_fh_alloc(&_fh_socketpair_class));
+    if (!fa) {
+        return -1;
+    }
+    unique_fh fb(_fh_alloc(&_fh_socketpair_class));
+    if (!fb) {
+        return -1;
+    }
 
     pair = reinterpret_cast<SocketPair>(malloc(sizeof(*pair)));
     if (pair == NULL) {
         D("adb_socketpair: not enough memory to allocate pipes\n" );
-        goto Fail;
+        return -1;
     }
 
     bip_buffer_init( &pair->a2b_bip );
@@ -1217,10 +1344,10 @@
     fa->fh_pair = pair;
     fb->fh_pair = pair;
     pair->used  = 2;
-    pair->a_fd  = fa;
+    pair->a_fd  = fa.get();
 
-    sv[0] = _fh_to_int(fa);
-    sv[1] = _fh_to_int(fb);
+    sv[0] = _fh_to_int(fa.get());
+    sv[1] = _fh_to_int(fb.get());
 
     pair->a2b_bip.fdin  = sv[0];
     pair->a2b_bip.fdout = sv[1];
@@ -1230,12 +1357,9 @@
     snprintf( fa->name, sizeof(fa->name), "%d(pair:%d)", sv[0], sv[1] );
     snprintf( fb->name, sizeof(fb->name), "%d(pair:%d)", sv[1], sv[0] );
     D( "adb_socketpair: returns (%d, %d)\n", sv[0], sv[1] );
+    fa.release();
+    fb.release();
     return 0;
-
-Fail:
-    _fh_close(fb);
-    _fh_close(fa);
-    return -1;
 }
 
 /**************************************************************************/
@@ -2083,6 +2207,7 @@
     hook->check   = _event_socket_check;
     hook->peek    = _event_socket_peek;
 
+    // TODO: check return value?
     _event_socket_start( hook );
 }
 
@@ -3052,3 +3177,615 @@
 #pragma pop_macro("read")
     }
 }
+
+/**************************************************************************/
+/**************************************************************************/
+/*****                                                                *****/
+/*****      Unicode support                                           *****/
+/*****                                                                *****/
+/**************************************************************************/
+/**************************************************************************/
+
+// This implements support for using files with Unicode filenames and for
+// outputting Unicode text to a Win32 console window. This is inspired from
+// http://utf8everywhere.org/.
+//
+// Background
+// ----------
+//
+// On POSIX systems, to deal with files with Unicode filenames, just pass UTF-8
+// filenames to APIs such as open(). This works because filenames are largely
+// opaque 'cookies' (perhaps excluding path separators).
+//
+// On Windows, the native file APIs such as CreateFileW() take 2-byte wchar_t
+// UTF-16 strings. There is an API, CreateFileA() that takes 1-byte char
+// strings, but the strings are in the ANSI codepage and not UTF-8. (The
+// CreateFile() API is really just a macro that adds the W/A based on whether
+// the UNICODE preprocessor symbol is defined).
+//
+// Options
+// -------
+//
+// Thus, to write a portable program, there are a few options:
+//
+// 1. Write the program with wchar_t filenames (wchar_t path[256];).
+//    For Windows, just call CreateFileW(). For POSIX, write a wrapper openW()
+//    that takes a wchar_t string, converts it to UTF-8 and then calls the real
+//    open() API.
+//
+// 2. Write the program with a TCHAR typedef that is 2 bytes on Windows and
+//    1 byte on POSIX. Make T-* wrappers for various OS APIs and call those,
+//    potentially touching a lot of code.
+//
+// 3. Write the program with a 1-byte char filenames (char path[256];) that are
+//    UTF-8. For POSIX, just call open(). For Windows, write a wrapper that
+//    takes a UTF-8 string, converts it to UTF-16 and then calls the real OS
+//    or C Runtime API.
+//
+// The Choice
+// ----------
+//
+// The code below chooses option 3, the UTF-8 everywhere strategy. It
+// introduces narrow() which converts UTF-16 to UTF-8. This is used by the
+// NarrowArgs helper class that is used to convert wmain() args into UTF-8
+// args that are passed to main() at the beginning of program startup. We also
+// introduce widen() which converts from UTF-8 to UTF-16. This is used to
+// implement wrappers below that call UTF-16 OS and C Runtime APIs.
+//
+// Unicode console output
+// ----------------------
+//
+// The way to output Unicode to a Win32 console window is to call
+// WriteConsoleW() with UTF-16 text. (The user must also choose a proper font
+// such as Lucida Console or Consolas, and in the case of Chinese, must go to
+// the Control Panel and change the "system locale" to Chinese, which allows
+// a Chinese font to be used in console windows.)
+//
+// The problem is getting the C Runtime to make fprintf and related APIs call
+// WriteConsoleW() under the covers. The C Runtime API, _setmode() sounds
+// promising, but the various modes have issues:
+//
+// 1. _setmode(_O_TEXT) (the default) does not use WriteConsoleW() so UTF-8 and
+//    UTF-16 do not display properly.
+// 2. _setmode(_O_BINARY) does not use WriteConsoleW() and the text comes out
+//    totally wrong.
+// 3. _setmode(_O_U8TEXT) seems to cause the C Runtime _invalid_parameter
+//    handler to be called (upon a later I/O call), aborting the process.
+// 4. _setmode(_O_U16TEXT) and _setmode(_O_WTEXT) cause non-wide printf/fprintf
+//    to output nothing.
+//
+// So the only solution is to write our own adb_fprintf() that converts UTF-8
+// to UTF-16 and then calls WriteConsoleW().
+
+
+// Function prototype because attributes cannot be placed on func definitions.
+static void _widen_fatal(const char *fmt, ...)
+    __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 1, 2)));
+
+// A version of fatal() that does not call adb_(v)fprintf(), so it can be
+// called from those functions.
+static void _widen_fatal(const char *fmt, ...) {
+    va_list ap;
+    va_start(ap, fmt);
+    // If (v)fprintf are macros that point to adb_(v)fprintf, when random adb
+    // code calls (v)fprintf, it may end up calling adb_(v)fprintf, which then
+    // calls _widen_fatal(). So then how does _widen_fatal() output a error?
+    // By directly calling real C Runtime APIs that don't properly output
+    // Unicode, but will be able to get a comprehendible message out. To do
+    // this, make sure we don't call (v)fprintf macros by undefining them.
+#pragma push_macro("fprintf")
+#pragma push_macro("vfprintf")
+#undef fprintf
+#undef vfprintf
+    fprintf(stderr, "error: ");
+    vfprintf(stderr, fmt, ap);
+    fprintf(stderr, "\n");
+#pragma pop_macro("vfprintf")
+#pragma pop_macro("fprintf")
+    va_end(ap);
+    exit(-1);
+}
+
+// TODO: Consider implementing widen() and narrow() out of std::wstring_convert
+// once libcxx is supported on Windows. Or, consider libutils/Unicode.cpp.
+
+// Convert from UTF-8 to UTF-16. A size of -1 specifies a NULL terminated
+// string. Any other size specifies the number of chars to convert, excluding
+// any NULL terminator (if you're passing an explicit size, you probably don't
+// have a NULL terminated string in the first place).
+std::wstring widen(const char* utf8, const int size) {
+    const int chars_to_convert = MultiByteToWideChar(CP_UTF8, 0, utf8, size,
+                                                     NULL, 0);
+    if (chars_to_convert <= 0) {
+        // UTF-8 to UTF-16 should be lossless, so we don't expect this to fail.
+        _widen_fatal("MultiByteToWideChar failed counting: %d, "
+                     "GetLastError: %lu", chars_to_convert, GetLastError());
+    }
+
+    std::wstring utf16;
+    size_t chars_to_allocate = chars_to_convert;
+    if (size == -1) {
+        // chars_to_convert includes a NULL terminator, so subtract space
+        // for that because resize() includes that itself.
+        --chars_to_allocate;
+    }
+    utf16.resize(chars_to_allocate);
+
+    // This uses &string[0] to get write-access to the entire string buffer
+    // which may be assuming that the chars are all contiguous, but it seems
+    // to work and saves us the hassle of using a temporary
+    // std::vector<wchar_t>.
+    const int result = MultiByteToWideChar(CP_UTF8, 0, utf8, size, &utf16[0],
+                                           chars_to_convert);
+    if (result != chars_to_convert) {
+        // UTF-8 to UTF-16 should be lossless, so we don't expect this to fail.
+        _widen_fatal("MultiByteToWideChar failed conversion: %d, "
+                     "GetLastError: %lu", result, GetLastError());
+    }
+
+    // If a size was passed in (size != -1), then the string is NULL terminated
+    // by a NULL char that was written by std::string::resize(). If size == -1,
+    // then MultiByteToWideChar() read a NULL terminator from the original
+    // string and converted it to a NULL UTF-16 char in the output.
+
+    return utf16;
+}
+
+// Convert a NULL terminated string from UTF-8 to UTF-16.
+std::wstring widen(const char* utf8) {
+    // Pass -1 to let widen() determine the string length.
+    return widen(utf8, -1);
+}
+
+// Convert from UTF-8 to UTF-16.
+std::wstring widen(const std::string& utf8) {
+    return widen(utf8.c_str(), utf8.length());
+}
+
+// Convert from UTF-16 to UTF-8.
+std::string narrow(const std::wstring& utf16) {
+    return narrow(utf16.c_str());
+}
+
+// Convert from UTF-16 to UTF-8.
+std::string narrow(const wchar_t* utf16) {
+    const int chars_required = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, NULL,
+                                                   0, NULL, NULL);
+    if (chars_required <= 0) {
+        // UTF-16 to UTF-8 should be lossless, so we don't expect this to fail.
+        fatal("WideCharToMultiByte failed counting: %d, GetLastError: %d",
+              chars_required, GetLastError());
+    }
+
+    std::string utf8;
+    // Subtract space for the NULL terminator because resize() includes
+    // that itself. Note that this could potentially throw a std::bad_alloc
+    // exception.
+    utf8.resize(chars_required - 1);
+
+    // This uses &string[0] to get write-access to the entire string buffer
+    // which may be assuming that the chars are all contiguous, but it seems
+    // to work and saves us the hassle of using a temporary
+    // std::vector<char>.
+    const int result = WideCharToMultiByte(CP_UTF8, 0, utf16, -1, &utf8[0],
+                                           chars_required, NULL, NULL);
+    if (result != chars_required) {
+        // UTF-16 to UTF-8 should be lossless, so we don't expect this to fail.
+        fatal("WideCharToMultiByte failed conversion: %d, GetLastError: %d",
+              result, GetLastError());
+    }
+
+    return utf8;
+}
+
+// Constructor for helper class to convert wmain() UTF-16 args to UTF-8 to
+// be passed to main().
+NarrowArgs::NarrowArgs(const int argc, wchar_t** const argv) {
+    narrow_args = new char*[argc + 1];
+
+    for (int i = 0; i < argc; ++i) {
+        narrow_args[i] = strdup(narrow(argv[i]).c_str());
+    }
+    narrow_args[argc] = nullptr;   // terminate
+}
+
+NarrowArgs::~NarrowArgs() {
+    if (narrow_args != nullptr) {
+        for (char** argp = narrow_args; *argp != nullptr; ++argp) {
+            free(*argp);
+        }
+        delete[] narrow_args;
+        narrow_args = nullptr;
+    }
+}
+
+int unix_open(const char* path, int options, ...) {
+    if ((options & O_CREAT) == 0) {
+        return _wopen(widen(path).c_str(), options);
+    } else {
+        int      mode;
+        va_list  args;
+        va_start(args, options);
+        mode = va_arg(args, int);
+        va_end(args);
+        return _wopen(widen(path).c_str(), options, mode);
+    }
+}
+
+// Version of stat() that takes a UTF-8 path.
+int adb_stat(const char* f, struct adb_stat* s) {
+#pragma push_macro("wstat")
+// This definition of wstat seems to be missing from <sys/stat.h>.
+#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
+#ifdef _USE_32BIT_TIME_T
+#define wstat _wstat32i64
+#else
+#define wstat _wstat64
+#endif
+#else
+// <sys/stat.h> has a function prototype for wstat() that should be available.
+#endif
+
+    return wstat(widen(f).c_str(), s);
+
+#pragma pop_macro("wstat")
+}
+
+// Version of opendir() that takes a UTF-8 path.
+DIR* adb_opendir(const char* name) {
+    // Just cast _WDIR* to DIR*. This doesn't work if the caller reads any of
+    // the fields, but right now all the callers treat the structure as
+    // opaque.
+    return reinterpret_cast<DIR*>(_wopendir(widen(name).c_str()));
+}
+
+// Version of readdir() that returns UTF-8 paths.
+struct dirent* adb_readdir(DIR* dir) {
+    _WDIR* const wdir = reinterpret_cast<_WDIR*>(dir);
+    struct _wdirent* const went = _wreaddir(wdir);
+    if (went == nullptr) {
+        return nullptr;
+    }
+    // Convert from UTF-16 to UTF-8.
+    const std::string name_utf8(narrow(went->d_name));
+
+    // Cast the _wdirent* to dirent* and overwrite the d_name field (which has
+    // space for UTF-16 wchar_t's) with UTF-8 char's.
+    struct dirent* ent = reinterpret_cast<struct dirent*>(went);
+
+    if (name_utf8.length() + 1 > sizeof(went->d_name)) {
+        // Name too big to fit in existing buffer.
+        errno = ENOMEM;
+        return nullptr;
+    }
+
+    // Note that sizeof(_wdirent::d_name) is bigger than sizeof(dirent::d_name)
+    // because _wdirent contains wchar_t instead of char. So even if name_utf8
+    // can fit in _wdirent::d_name, the resulting dirent::d_name field may be
+    // bigger than the caller expects because they expect a dirent structure
+    // which has a smaller d_name field. Ignore this since the caller should be
+    // resilient.
+
+    // Rewrite the UTF-16 d_name field to UTF-8.
+    strcpy(ent->d_name, name_utf8.c_str());
+
+    return ent;
+}
+
+// Version of closedir() to go with our version of adb_opendir().
+int adb_closedir(DIR* dir) {
+    return _wclosedir(reinterpret_cast<_WDIR*>(dir));
+}
+
+// Version of unlink() that takes a UTF-8 path.
+int adb_unlink(const char* path) {
+    const std::wstring wpath(widen(path));
+
+    int  rc = _wunlink(wpath.c_str());
+
+    if (rc == -1 && errno == EACCES) {
+        /* unlink returns EACCES when the file is read-only, so we first */
+        /* try to make it writable, then unlink again...                 */
+        rc = _wchmod(wpath.c_str(), _S_IREAD | _S_IWRITE);
+        if (rc == 0)
+            rc = _wunlink(wpath.c_str());
+    }
+    return rc;
+}
+
+// Version of mkdir() that takes a UTF-8 path.
+int adb_mkdir(const std::string& path, int mode) {
+    return _wmkdir(widen(path.c_str()).c_str());
+}
+
+// Version of utime() that takes a UTF-8 path.
+int adb_utime(const char* path, struct utimbuf* u) {
+    static_assert(sizeof(struct utimbuf) == sizeof(struct _utimbuf),
+        "utimbuf and _utimbuf should be the same size because they both "
+        "contain the same types, namely time_t");
+    return _wutime(widen(path).c_str(), reinterpret_cast<struct _utimbuf*>(u));
+}
+
+// Version of chmod() that takes a UTF-8 path.
+int adb_chmod(const char* path, int mode) {
+    return _wchmod(widen(path).c_str(), mode);
+}
+
+// Internal function to get a Win32 console HANDLE from a C Runtime FILE*.
+static HANDLE _get_console_handle(FILE* const stream) {
+    // Get a C Runtime file descriptor number from the FILE* structure.
+    const int fd = fileno(stream);
+    if (fd < 0) {
+        return NULL;
+    }
+
+    // If it is not a "character device", it is probably a file and not a
+    // console. Do this check early because it is probably cheap. Still do more
+    // checks after this since there are devices that pass this test, but are
+    // not a console, such as NUL, the Windows /dev/null equivalent (I think).
+    if (!isatty(fd)) {
+        return NULL;
+    }
+
+    // Given a C Runtime file descriptor number, get the underlying OS
+    // file handle.
+    const intptr_t osfh = _get_osfhandle(fd);
+    if (osfh == -1) {
+        return NULL;
+    }
+
+    const HANDLE h = reinterpret_cast<const HANDLE>(osfh);
+
+    DWORD old_mode = 0;
+    if (!GetConsoleMode(h, &old_mode)) {
+        return NULL;
+    }
+
+    // If GetConsoleMode() was successful, assume this is a console.
+    return h;
+}
+
+// Internal helper function to write UTF-8 bytes to a console. Returns -1
+// on error.
+static int _console_write_utf8(const char* buf, size_t size, FILE* stream,
+                               HANDLE console) {
+    // Convert from UTF-8 to UTF-16.
+    // This could throw std::bad_alloc.
+    const std::wstring output(widen(buf, size));
+
+    // Note that this does not do \n => \r\n translation because that
+    // doesn't seem necessary for the Windows console. For the Windows
+    // console \r moves to the beginning of the line and \n moves to a new
+    // line.
+
+    // Flush any stream buffering so that our output is afterwards which
+    // makes sense because our call is afterwards.
+    (void)fflush(stream);
+
+    // Write UTF-16 to the console.
+    DWORD written = 0;
+    if (!WriteConsoleW(console, output.c_str(), output.length(), &written,
+                       NULL)) {
+        errno = EIO;
+        return -1;
+    }
+
+    // This is the number of UTF-16 chars written, which might be different
+    // than the number of UTF-8 chars passed in. It doesn't seem practical to
+    // get this count correct.
+    return written;
+}
+
+// Function prototype because attributes cannot be placed on func definitions.
+static int _console_vfprintf(const HANDLE console, FILE* stream,
+                             const char *format, va_list ap)
+    __attribute__((__format__(ADB_FORMAT_ARCHETYPE, 3, 0)));
+
+// Internal function to format a UTF-8 string and write it to a Win32 console.
+// Returns -1 on error.
+static int _console_vfprintf(const HANDLE console, FILE* stream,
+                             const char *format, va_list ap) {
+    std::string output_utf8;
+
+    // Format the string.
+    // This could throw std::bad_alloc.
+    android::base::StringAppendV(&output_utf8, format, ap);
+
+    return _console_write_utf8(output_utf8.c_str(), output_utf8.length(),
+                               stream, console);
+}
+
+// Version of vfprintf() that takes UTF-8 and can write Unicode to a
+// Windows console.
+int adb_vfprintf(FILE *stream, const char *format, va_list ap) {
+    const HANDLE console = _get_console_handle(stream);
+
+    // If there is an associated Win32 console, write to it specially,
+    // otherwise defer to the regular C Runtime, passing it UTF-8.
+    if (console != NULL) {
+        return _console_vfprintf(console, stream, format, ap);
+    } else {
+        // If vfprintf is a macro, undefine it, so we can call the real
+        // C Runtime API.
+#pragma push_macro("vfprintf")
+#undef vfprintf
+        return vfprintf(stream, format, ap);
+#pragma pop_macro("vfprintf")
+    }
+}
+
+// Version of fprintf() that takes UTF-8 and can write Unicode to a
+// Windows console.
+int adb_fprintf(FILE *stream, const char *format, ...) {
+    va_list ap;
+    va_start(ap, format);
+    const int result = adb_vfprintf(stream, format, ap);
+    va_end(ap);
+
+    return result;
+}
+
+// Version of printf() that takes UTF-8 and can write Unicode to a
+// Windows console.
+int adb_printf(const char *format, ...) {
+    va_list ap;
+    va_start(ap, format);
+    const int result = adb_vfprintf(stdout, format, ap);
+    va_end(ap);
+
+    return result;
+}
+
+// Version of fputs() that takes UTF-8 and can write Unicode to a
+// Windows console.
+int adb_fputs(const char* buf, FILE* stream) {
+    // adb_fprintf returns -1 on error, which is conveniently the same as EOF
+    // which fputs (and hence adb_fputs) should return on error.
+    return adb_fprintf(stream, "%s", buf);
+}
+
+// Version of fputc() that takes UTF-8 and can write Unicode to a
+// Windows console.
+int adb_fputc(int ch, FILE* stream) {
+    const int result = adb_fprintf(stream, "%c", ch);
+    if (result <= 0) {
+        // If there was an error, or if nothing was printed (which should be an
+        // error), return an error, which fprintf signifies with EOF.
+        return EOF;
+    }
+    // For success, fputc returns the char, cast to unsigned char, then to int.
+    return static_cast<unsigned char>(ch);
+}
+
+// Internal function to write UTF-8 to a Win32 console. Returns the number of
+// items (of length size) written. On error, returns a short item count or 0.
+static size_t _console_fwrite(const void* ptr, size_t size, size_t nmemb,
+                              FILE* stream, HANDLE console) {
+    // TODO: Note that a Unicode character could be several UTF-8 bytes. But
+    // if we're passed only some of the bytes of a character (for example, from
+    // the network socket for adb shell), we won't be able to convert the char
+    // to a complete UTF-16 char (or surrogate pair), so the output won't look
+    // right.
+    //
+    // To fix this, see libutils/Unicode.cpp for hints on decoding UTF-8.
+    //
+    // For now we ignore this problem because the alternative is that we'd have
+    // to parse UTF-8 and buffer things up (doable). At least this is better
+    // than what we had before -- always incorrect multi-byte UTF-8 output.
+    int result = _console_write_utf8(reinterpret_cast<const char*>(ptr),
+                                     size * nmemb, stream, console);
+    if (result == -1) {
+        return 0;
+    }
+    return result / size;
+}
+
+// Version of fwrite() that takes UTF-8 and can write Unicode to a
+// Windows console.
+size_t adb_fwrite(const void* ptr, size_t size, size_t nmemb, FILE* stream) {
+    const HANDLE console = _get_console_handle(stream);
+
+    // If there is an associated Win32 console, write to it specially,
+    // otherwise defer to the regular C Runtime, passing it UTF-8.
+    if (console != NULL) {
+        return _console_fwrite(ptr, size, nmemb, stream, console);
+    } else {
+        // If fwrite is a macro, undefine it, so we can call the real
+        // C Runtime API.
+#pragma push_macro("fwrite")
+#undef fwrite
+        return fwrite(ptr, size, nmemb, stream);
+#pragma pop_macro("fwrite")
+    }
+}
+
+// Version of fopen() that takes a UTF-8 filename and can access a file with
+// a Unicode filename.
+FILE* adb_fopen(const char* f, const char* m) {
+    return _wfopen(widen(f).c_str(), widen(m).c_str());
+}
+
+// Shadow UTF-8 environment variable name/value pairs that are created from
+// _wenviron the first time that adb_getenv() is called. Note that this is not
+// currently updated if putenv, setenv, unsetenv are called.
+static std::unordered_map<std::string, char*> g_environ_utf8;
+
+// Make sure that shadow UTF-8 environment variables are setup.
+static void _ensure_env_setup() {
+    // If some name/value pairs exist, then we've already done the setup below.
+    if (g_environ_utf8.size() != 0) {
+        return;
+    }
+
+    // Read name/value pairs from UTF-16 _wenviron and write new name/value
+    // pairs to UTF-8 g_environ_utf8. Note that it probably does not make sense
+    // to use the D() macro here because that tracing only works if the
+    // ADB_TRACE environment variable is setup, but that env var can't be read
+    // until this code completes.
+    for (wchar_t** env = _wenviron; *env != nullptr; ++env) {
+        wchar_t* const equal = wcschr(*env, L'=');
+        if (equal == nullptr) {
+            // Malformed environment variable with no equal sign. Shouldn't
+            // really happen, but we should be resilient to this.
+            continue;
+        }
+
+        const std::string name_utf8(narrow(std::wstring(*env, equal - *env)));
+        char* const value_utf8 = strdup(narrow(equal + 1).c_str());
+
+        // Overwrite any duplicate name, but there shouldn't be a dup in the
+        // first place.
+        g_environ_utf8[name_utf8] = value_utf8;
+    }
+}
+
+// Version of getenv() that takes a UTF-8 environment variable name and
+// retrieves a UTF-8 value.
+char* adb_getenv(const char* name) {
+    _ensure_env_setup();
+
+    std::unordered_map<std::string, char*>::const_iterator it =
+        g_environ_utf8.find(std::string(name));
+    if (it == g_environ_utf8.end()) {
+        return nullptr;
+    }
+
+    return it->second;
+}
+
+// Version of getcwd() that returns the current working directory in UTF-8.
+char* adb_getcwd(char* buf, int size) {
+    wchar_t* wbuf = _wgetcwd(nullptr, 0);
+    if (wbuf == nullptr) {
+        return nullptr;
+    }
+
+    const std::string buf_utf8(narrow(wbuf));
+    free(wbuf);
+    wbuf = nullptr;
+
+    // If size was specified, make sure all the chars will fit.
+    if (size != 0) {
+        if (size < static_cast<int>(buf_utf8.length() + 1)) {
+            errno = ERANGE;
+            return nullptr;
+        }
+    }
+
+    // If buf was not specified, allocate storage.
+    if (buf == nullptr) {
+        if (size == 0) {
+            size = buf_utf8.length() + 1;
+        }
+        buf = reinterpret_cast<char*>(malloc(size));
+        if (buf == nullptr) {
+            return nullptr;
+        }
+    }
+
+    // Destination buffer was allocated with enough space, or we've already
+    // checked an existing buffer size for enough space.
+    strcpy(buf, buf_utf8.c_str());
+
+    return buf;
+}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 87aff88..4a273c4 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -126,19 +126,18 @@
 static int
 read_packet(int  fd, const char* name, apacket** ppacket)
 {
-    char *p = (char*)ppacket;  /* really read a packet address */
-    int   r;
-    int   len = sizeof(*ppacket);
-    char  buff[8];
+    char buff[8];
     if (!name) {
         snprintf(buff, sizeof buff, "fd=%d", fd);
         name = buff;
     }
+    char* p = reinterpret_cast<char*>(ppacket);  /* really read a packet address */
+    int len = sizeof(apacket*);
     while(len > 0) {
-        r = adb_read(fd, p, len);
+        int r = adb_read(fd, p, len);
         if(r > 0) {
             len -= r;
-            p   += r;
+            p += r;
         } else {
             D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
             if((r < 0) && (errno == EINTR)) continue;
@@ -155,20 +154,18 @@
 static int
 write_packet(int  fd, const char* name, apacket** ppacket)
 {
-    char *p = (char*) ppacket;  /* we really write the packet address */
-    int r, len = sizeof(ppacket);
     char buff[8];
     if (!name) {
         snprintf(buff, sizeof buff, "fd=%d", fd);
         name = buff;
     }
-
     if (ADB_TRACING) {
         dump_packet(name, "to remote", *ppacket);
     }
-    len = sizeof(ppacket);
+    char* p = reinterpret_cast<char*>(ppacket);  /* we really write the packet address */
+    int len = sizeof(apacket*);
     while(len > 0) {
-        r = adb_write(fd, p, len);
+        int r = adb_write(fd, p, len);
         if(r > 0) {
             len -= r;
             p += r;
diff --git a/adb/transport_local.cpp b/adb/transport_local.cpp
index 0dc9581..650e5ea 100644
--- a/adb/transport_local.cpp
+++ b/adb/transport_local.cpp
@@ -94,13 +94,17 @@
     int fd = -1;
 
 #if ADB_HOST
+    if (find_emulator_transport_by_adb_port(adb_port) != nullptr) {
+        return -1;
+    }
+
     const char *host = getenv("ADBHOST");
     if (host) {
         fd = network_connect(host, adb_port, SOCK_STREAM, 0, error);
     }
 #endif
     if (fd < 0) {
-        fd = socket_loopback_client(adb_port, SOCK_STREAM);
+        fd = network_loopback_client(adb_port, SOCK_STREAM, error);
     }
 
     if (fd >= 0) {
@@ -108,8 +112,10 @@
         close_on_exec(fd);
         disable_tcp_nagle(fd);
         std::string serial = android::base::StringPrintf("emulator-%d", console_port);
-        register_socket_transport(fd, serial.c_str(), adb_port, 1);
-        return 0;
+        if (register_socket_transport(fd, serial.c_str(), adb_port, 1) == 0) {
+            return 0;
+        }
+        adb_close(fd);
     }
     return -1;
 }
@@ -118,16 +124,16 @@
 static void *client_socket_thread(void *x)
 {
 #if ADB_HOST
-    int  port  = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
-    int  count = ADB_LOCAL_TRANSPORT_MAX;
-
     D("transport: client_socket_thread() starting\n");
+    while (true) {
+        int port = DEFAULT_ADB_LOCAL_TRANSPORT_PORT;
+        int count = ADB_LOCAL_TRANSPORT_MAX;
 
-    /* try to connect to any number of running emulator instances     */
-    /* this is only done when ADB starts up. later, each new emulator */
-    /* will send a message to ADB to indicate that is is starting up  */
-    for ( ; count > 0; count--, port += 2 ) {
-        local_connect(port);
+        // Try to connect to any number of running emulator instances.
+        for ( ; count > 0; count--, port += 2 ) {
+            local_connect(port);
+        }
+        sleep(1);
     }
 #endif
     return 0;
@@ -144,9 +150,10 @@
     serverfd = -1;
     for(;;) {
         if(serverfd == -1) {
-            serverfd = socket_inaddr_any_server(port, SOCK_STREAM);
+            std::string error;
+            serverfd = network_inaddr_any_server(port, SOCK_STREAM, &error);
             if(serverfd < 0) {
-                D("server: cannot bind socket yet: %s\n", strerror(errno));
+                D("server: cannot bind socket yet: %s\n", error.c_str());
                 adb_sleep_ms(1000);
                 continue;
             }
diff --git a/adb/transport_test.cpp b/adb/transport_test.cpp
index 4b74adf..49deb73 100644
--- a/adb/transport_test.cpp
+++ b/adb/transport_test.cpp
@@ -63,6 +63,27 @@
     }
 };
 
+class TransportSetup {
+public:
+  TransportSetup() {
+#ifdef _WIN32
+    // Use extern instead of including sysdeps.h which brings in various macros
+    // that conflict with APIs used in this file.
+    extern void adb_sysdeps_init(void);
+    adb_sysdeps_init();
+#else
+    // adb_sysdeps_init() is an inline function that we cannot link against.
+#endif
+  }
+};
+
+// Static initializer will call adb_sysdeps_init() before main() to initialize
+// the transport mutex before it is used in the tests. Alternatives would be to
+// use __attribute__((constructor)) here or to use that or a static initializer
+// for adb_sysdeps_init() itself in sysdeps_win32.cpp (caveats of unclear
+// init order), or to use a test fixture whose SetUp() could do the init once.
+static TransportSetup g_TransportSetup;
+
 TEST(transport, kick_transport) {
   TestTransport t;
 
diff --git a/base/file_test.cpp b/base/file_test.cpp
index 4056684..2158421 100644
--- a/base/file_test.cpp
+++ b/base/file_test.cpp
@@ -34,17 +34,7 @@
   EXPECT_EQ("", s);  // s was cleared.
 }
 
-TEST(file, ReadFileToString_success) {
-  std::string s("hello");
-  ASSERT_TRUE(android::base::ReadFileToString("/proc/version", &s))
-    << strerror(errno);
-  EXPECT_GT(s.length(), 6U);
-  EXPECT_EQ('\n', s[s.length() - 1]);
-  s[5] = 0;
-  EXPECT_STREQ("Linux", s.c_str());
-}
-
-TEST(file, WriteStringToFile) {
+TEST(file, ReadFileToString_WriteStringToFile) {
   TemporaryFile tf;
   ASSERT_TRUE(tf.fd != -1);
   ASSERT_TRUE(android::base::WriteStringToFile("abc", tf.path))
@@ -89,13 +79,23 @@
 }
 
 TEST(file, ReadFully) {
-  int fd = open("/proc/version", O_RDONLY);
+#ifdef _WIN32
+  VersionFile ver;
+  ASSERT_NE(ver.filename, nullptr);
+  const char* filename = ver.filename;
+  // Note that ReadFully() does CR/LF translation, so we expect \n, not \r\n.
+  const char expected[] = "\nMicrosoft Windows";
+#else
+  const char* filename = "/proc/version";
+  const char expected[] = "Linux";
+#endif
+  int fd = open(filename, O_RDONLY);
   ASSERT_NE(-1, fd) << strerror(errno);
 
   char buf[1024];
   memset(buf, 0, sizeof(buf));
-  ASSERT_TRUE(android::base::ReadFully(fd, buf, 5));
-  ASSERT_STREQ("Linux", buf);
+  ASSERT_TRUE(android::base::ReadFully(fd, buf, sizeof(expected) - 1));
+  ASSERT_STREQ(expected, buf);
 
   ASSERT_EQ(0, lseek(fd, 0, SEEK_SET)) << strerror(errno);
 
diff --git a/base/include/base/test_utils.h b/base/include/base/test_utils.h
index 83f0f1c..402e0a5 100644
--- a/base/include/base/test_utils.h
+++ b/base/include/base/test_utils.h
@@ -35,7 +35,6 @@
   DISALLOW_COPY_AND_ASSIGN(TemporaryFile);
 };
 
-#if !defined(_WIN32)
 class TemporaryDir {
  public:
   TemporaryDir();
@@ -48,6 +47,5 @@
 
   DISALLOW_COPY_AND_ASSIGN(TemporaryDir);
 };
-#endif
 
 #endif // TEST_UTILS_H
diff --git a/base/stringprintf_test.cpp b/base/stringprintf_test.cpp
index 54b2b6c..5cc2086 100644
--- a/base/stringprintf_test.cpp
+++ b/base/stringprintf_test.cpp
@@ -20,14 +20,11 @@
 
 #include <string>
 
-// The z size sepcifier isn't supported on Windows, so this test isn't useful.
-#if !defined(_WIN32)
 TEST(StringPrintfTest, HexSizeT) {
   size_t size = 0x00107e59;
   EXPECT_EQ("00107e59", android::base::StringPrintf("%08zx", size));
   EXPECT_EQ("0x00107e59", android::base::StringPrintf("0x%08zx", size));
 }
-#endif
 
 TEST(StringPrintfTest, StringAppendF) {
   std::string s("a");
diff --git a/base/test_utils.cpp b/base/test_utils.cpp
index dceb8b7..b0c5a12 100644
--- a/base/test_utils.cpp
+++ b/base/test_utils.cpp
@@ -14,7 +14,9 @@
  * limitations under the License.
  */
 
+#include "base/logging.h"
 #include "base/test_utils.h"
+#include "utils/Compat.h" // For OS_PATH_SEPARATOR.
 
 #include <fcntl.h>
 #include <stdio.h>
@@ -24,17 +26,47 @@
 
 #if defined(_WIN32)
 #include <windows.h>
+#include <direct.h>
 #endif
 
 #include <string>
 
+#ifdef _WIN32
+int mkstemp(char* template_name) {
+  if (_mktemp(template_name) == nullptr) {
+    return -1;
+  }
+  // Use open() to match the close() that TemporaryFile's destructor does.
+  // Note that on Windows, this does CR/LF translation and _setmode() should
+  // be used to change that if appropriate.
+  return open(template_name, O_CREAT | O_EXCL | O_RDWR, S_IRUSR | S_IWUSR);
+}
+
+char* mkdtemp(char* template_name) {
+  if (_mktemp(template_name) == nullptr) {
+    return nullptr;
+  }
+  if (_mkdir(template_name) == -1) {
+    return nullptr;
+  }
+  return template_name;
+}
+#endif
+
 static std::string GetSystemTempDir() {
 #if defined(__ANDROID__)
   return "/data/local/tmp";
 #elif defined(_WIN32)
-  char wd[MAX_PATH] = {};
-  _getcwd(wd, sizeof(wd));
-  return wd;
+  char tmp_dir[MAX_PATH];
+  DWORD result = GetTempPathA(sizeof(tmp_dir), tmp_dir);
+  CHECK_NE(result, 0ul) << "GetTempPathA failed, error: " << GetLastError();
+  CHECK_LT(result, sizeof(tmp_dir)) << "path truncated to: " << result;
+
+  // GetTempPath() returns a path with a trailing slash, but init()
+  // does not expect that, so remove it.
+  CHECK_EQ(tmp_dir[result - 1], '\\');
+  tmp_dir[result - 1] = '\0';
+  return tmp_dir;
 #else
   return "/tmp";
 #endif
@@ -50,21 +82,11 @@
 }
 
 void TemporaryFile::init(const std::string& tmp_dir) {
-  snprintf(path, sizeof(path), "%s/TemporaryFile-XXXXXX", tmp_dir.c_str());
-#if !defined(_WIN32)
+  snprintf(path, sizeof(path), "%s%cTemporaryFile-XXXXXX", tmp_dir.c_str(),
+           OS_PATH_SEPARATOR);
   fd = mkstemp(path);
-#else
-  // Windows doesn't have mkstemp, and tmpfile creates the file in the root
-  // directory, requiring root (?!) permissions. We have to settle for mktemp.
-  if (mktemp(path) == nullptr) {
-    abort();
-  }
-
-  fd = open(path, O_RDWR | O_NOINHERIT | O_CREAT, _S_IREAD | _S_IWRITE);
-#endif
 }
 
-#if !defined(_WIN32)
 TemporaryDir::TemporaryDir() {
   init(GetSystemTempDir());
 }
@@ -74,7 +96,7 @@
 }
 
 bool TemporaryDir::init(const std::string& tmp_dir) {
-  snprintf(path, sizeof(path), "%s/TemporaryDir-XXXXXX", tmp_dir.c_str());
+  snprintf(path, sizeof(path), "%s%cTemporaryDir-XXXXXX", tmp_dir.c_str(),
+           OS_PATH_SEPARATOR);
   return (mkdtemp(path) != nullptr);
 }
-#endif
diff --git a/include/cutils/trace.h b/include/cutils/trace.h
index e4ed179..6d9b3bc 100644
--- a/include/cutils/trace.h
+++ b/include/cutils/trace.h
@@ -67,7 +67,8 @@
 #define ATRACE_TAG_RS               (1<<15)
 #define ATRACE_TAG_BIONIC           (1<<16)
 #define ATRACE_TAG_POWER            (1<<17)
-#define ATRACE_TAG_LAST             ATRACE_TAG_POWER
+#define ATRACE_TAG_PACKAGE_MANAGER  (1<<18)
+#define ATRACE_TAG_LAST             ATRACE_TAG_PACKAGE_MANAGER
 
 // Reserved for initialization.
 #define ATRACE_TAG_NOT_READY        (1LL<<63)
diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h
index 9046fbe..7047e0f 100644
--- a/include/private/android_filesystem_config.h
+++ b/include/private/android_filesystem_config.h
@@ -99,6 +99,10 @@
 #define AID_NET_BW_ACCT   3007  /* change bandwidth statistics accounting */
 #define AID_NET_BT_STACK  3008  /* bluetooth: access config files */
 
+/* The range 5000-5999 is also reserved for OEM, and must never be used here. */
+#define AID_OEM_RESERVED_2_START 5000
+#define AID_OEM_RESERVED_2_END   5999
+
 #define AID_EVERYBODY     9997  /* shared between all apps in the same profile */
 #define AID_MISC          9998  /* access to misc storage */
 #define AID_NOBODY        9999
diff --git a/init/action.cpp b/init/action.cpp
index bd5fe75..2eb809e 100644
--- a/init/action.cpp
+++ b/init/action.cpp
@@ -30,7 +30,7 @@
 class Action::Command
 {
 public:
-    Command(int (*f)(int nargs, char** args),
+    Command(int (*f)(const std::vector<std::string>& args),
             const std::vector<std::string>& args,
             const std::string& filename,
             int line);
@@ -40,13 +40,13 @@
     std::string BuildSourceString() const;
 
 private:
-    int (*func_)(int nargs, char** args);
+    int (*func_)(const std::vector<std::string>& args);
     const std::vector<std::string> args_;
     const std::string filename_;
     int line_;
 };
 
-Action::Command::Command(int (*f)(int nargs, char** args),
+Action::Command::Command(int (*f)(const std::vector<std::string>& args),
                          const std::vector<std::string>& args,
                          const std::string& filename,
                          int line) :
@@ -56,22 +56,17 @@
 
 int Action::Command::InvokeFunc() const
 {
-    std::vector<std::string> strs;
-    strs.resize(args_.size());
-    strs[0] = args_[0];
+    std::vector<std::string> expanded_args;
+    expanded_args.resize(args_.size());
+    expanded_args[0] = args_[0];
     for (std::size_t i = 1; i < args_.size(); ++i) {
-        if (expand_props(args_[i], &strs[i]) == -1) {
+        if (expand_props(args_[i], &expanded_args[i]) == -1) {
             ERROR("%s: cannot expand '%s'\n", args_[0].c_str(), args_[i].c_str());
             return -EINVAL;
         }
     }
 
-    std::vector<char*> args;
-    for (auto& s : strs) {
-        args.push_back(&s[0]);
-    }
-
-    return func_(args.size(), &args[0]);
+    return func_(expanded_args);
 }
 
 std::string Action::Command::BuildCommandString() const
@@ -92,7 +87,7 @@
 {
 }
 
-void Action::AddCommand(int (*f)(int nargs, char** args),
+void Action::AddCommand(int (*f)(const std::vector<std::string>& args),
                         const std::vector<std::string>& args,
                         const std::string& filename, int line)
 {
@@ -305,7 +300,7 @@
     QueuePropertyTrigger("", "");
 }
 
-void ActionManager::QueueBuiltinAction(int (*func)(int nargs, char** args),
+void ActionManager::QueueBuiltinAction(int (*func)(const std::vector<std::string>& args),
                                        const std::string& name)
 {
     Action* act = new Action();
diff --git a/init/action.h b/init/action.h
index 8ee09b0..ae28fe1 100644
--- a/init/action.h
+++ b/init/action.h
@@ -26,7 +26,7 @@
 public:
     Action();
 
-    void AddCommand(int (*f)(int nargs, char** args),
+    void AddCommand(int (*f)(const std::vector<std::string>& args),
                     const std::vector<std::string>& args,
                     const std::string& filename = "", int line = 0);
     bool InitTriggers(const std::vector<std::string>& args, std::string* err);
@@ -60,7 +60,7 @@
     void QueueEventTrigger(const std::string& trigger);
     void QueuePropertyTrigger(const std::string& name, const std::string& value);
     void QueueAllPropertyTriggers();
-    void QueueBuiltinAction(int (*func)(int nargs, char** args),
+    void QueueBuiltinAction(int (*func)(const std::vector<std::string>& args),
                             const std::string& name);
     void ExecuteOneCommand();
     bool HasMoreCommands() const;
diff --git a/init/bootchart.cpp b/init/bootchart.cpp
index e5b153a..efaee1c 100644
--- a/init/bootchart.cpp
+++ b/init/bootchart.cpp
@@ -203,7 +203,7 @@
     return count;
 }
 
-int do_bootchart_init(int nargs, char** args) {
+int do_bootchart_init(const std::vector<std::string>& args) {
     g_remaining_samples = bootchart_init();
     if (g_remaining_samples < 0) {
         ERROR("Bootcharting init failure: %s\n", strerror(errno));
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 4bc3b87..7848e10 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -61,7 +61,7 @@
 // System call provided by bionic but not in any header file.
 extern "C" int init_module(void *, unsigned long, const char *);
 
-static int insmod(const char *filename, char *options)
+static int insmod(const char *filename, const char *options)
 {
     std::string module;
     if (!read_file(filename, &module)) {
@@ -170,37 +170,37 @@
     }
 }
 
-int do_class_start(int nargs, char **args)
+int do_class_start(const std::vector<std::string>& args)
 {
         /* Starting a class does not start services
          * which are explicitly disabled.  They must
          * be started individually.
          */
-    service_for_each_class(args[1], service_start_if_not_disabled);
+    service_for_each_class(args[1].c_str(), service_start_if_not_disabled);
     return 0;
 }
 
-int do_class_stop(int nargs, char **args)
+int do_class_stop(const std::vector<std::string>& args)
 {
-    service_for_each_class(args[1], service_stop);
+    service_for_each_class(args[1].c_str(), service_stop);
     return 0;
 }
 
-int do_class_reset(int nargs, char **args)
+int do_class_reset(const std::vector<std::string>& args)
 {
-    service_for_each_class(args[1], service_reset);
+    service_for_each_class(args[1].c_str(), service_reset);
     return 0;
 }
 
-int do_domainname(int nargs, char **args)
+int do_domainname(const std::vector<std::string>& args)
 {
-    return write_file("/proc/sys/kernel/domainname", args[1]);
+    return write_file("/proc/sys/kernel/domainname", args[1].c_str());
 }
 
-int do_enable(int nargs, char **args)
+int do_enable(const std::vector<std::string>& args)
 {
     struct service *svc;
-    svc = service_find_by_name(args[1]);
+    svc = service_find_by_name(args[1].c_str());
     if (svc) {
         svc->flags &= ~(SVC_DISABLED | SVC_RC_DISABLED);
         if (svc->flags & SVC_DISABLED_START) {
@@ -212,8 +212,13 @@
     return 0;
 }
 
-int do_exec(int nargs, char** args) {
-    service* svc = make_exec_oneshot_service(nargs, args);
+int do_exec(const std::vector<std::string>& args) {
+    std::vector<char*> strs;
+    strs.reserve(args.size());
+    for (const auto& s : args) {
+        strs.push_back(const_cast<char*>(s.c_str()));
+    }
+    service* svc = make_exec_oneshot_service(strs.size(), &strs[0]);
     if (svc == NULL) {
         return -1;
     }
@@ -221,94 +226,78 @@
     return 0;
 }
 
-int do_export(int nargs, char **args)
+int do_export(const std::vector<std::string>& args)
 {
-    return add_environment(args[1], args[2]);
+    return add_environment(args[1].c_str(), args[2].c_str());
 }
 
-int do_hostname(int nargs, char **args)
+int do_hostname(const std::vector<std::string>& args)
 {
-    return write_file("/proc/sys/kernel/hostname", args[1]);
+    return write_file("/proc/sys/kernel/hostname", args[1].c_str());
 }
 
-int do_ifup(int nargs, char **args)
+int do_ifup(const std::vector<std::string>& args)
 {
-    return __ifupdown(args[1], 1);
+    return __ifupdown(args[1].c_str(), 1);
 }
 
-
-static int do_insmod_inner(int nargs, char **args, int opt_len)
+int do_insmod(const std::vector<std::string>& args)
 {
-    char options[opt_len + 1];
-    int i;
+    std::string options;
 
-    options[0] = '\0';
-    if (nargs > 2) {
-        strcpy(options, args[2]);
-        for (i = 3; i < nargs; ++i) {
-            strcat(options, " ");
-            strcat(options, args[i]);
+    if (args.size() > 2) {
+        options += args[2];
+        for (std::size_t i = 3; i < args.size(); ++i) {
+            options += ' ';
+            options += args[i];
         }
     }
 
-    return insmod(args[1], options);
+    return insmod(args[1].c_str(), options.c_str());
 }
 
-int do_insmod(int nargs, char **args)
-{
-    int i;
-    int size = 0;
-
-    if (nargs > 2) {
-        for (i = 2; i < nargs; ++i)
-            size += strlen(args[i]) + 1;
-    }
-
-    return do_insmod_inner(nargs, args, size);
-}
-
-int do_mkdir(int nargs, char **args)
+int do_mkdir(const std::vector<std::string>& args)
 {
     mode_t mode = 0755;
     int ret;
 
     /* mkdir <path> [mode] [owner] [group] */
 
-    if (nargs >= 3) {
-        mode = strtoul(args[2], 0, 8);
+    if (args.size() >= 3) {
+        mode = std::stoul(args[2], 0, 8);
     }
 
-    ret = make_dir(args[1], mode);
+    ret = make_dir(args[1].c_str(), mode);
     /* chmod in case the directory already exists */
     if (ret == -1 && errno == EEXIST) {
-        ret = fchmodat(AT_FDCWD, args[1], mode, AT_SYMLINK_NOFOLLOW);
+        ret = fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW);
     }
     if (ret == -1) {
         return -errno;
     }
 
-    if (nargs >= 4) {
-        uid_t uid = decode_uid(args[3]);
+    if (args.size() >= 4) {
+        uid_t uid = decode_uid(args[3].c_str());
         gid_t gid = -1;
 
-        if (nargs == 5) {
-            gid = decode_uid(args[4]);
+        if (args.size() == 5) {
+            gid = decode_uid(args[4].c_str());
         }
 
-        if (lchown(args[1], uid, gid) == -1) {
+        if (lchown(args[1].c_str(), uid, gid) == -1) {
             return -errno;
         }
 
         /* chown may have cleared S_ISUID and S_ISGID, chmod again */
         if (mode & (S_ISUID | S_ISGID)) {
-            ret = fchmodat(AT_FDCWD, args[1], mode, AT_SYMLINK_NOFOLLOW);
+            ret = fchmodat(AT_FDCWD, args[1].c_str(), mode, AT_SYMLINK_NOFOLLOW);
             if (ret == -1) {
                 return -errno;
             }
         }
     }
 
-    return e4crypt_set_directory_policy(args[1]);
+    return e4crypt_set_directory_policy(args[1].c_str());
 }
 
 static struct {
@@ -336,35 +325,36 @@
 #define DATA_MNT_POINT "/data"
 
 /* mount <type> <device> <path> <flags ...> <options> */
-int do_mount(int nargs, char **args)
+int do_mount(const std::vector<std::string>& args)
 {
     char tmp[64];
-    char *source, *target, *system;
-    char *options = NULL;
+    const char *source, *target, *system;
+    const char *options = NULL;
     unsigned flags = 0;
+    std::size_t na = 0;
     int n, i;
     int wait = 0;
 
-    for (n = 4; n < nargs; n++) {
+    for (na = 4; na < args.size(); na++) {
         for (i = 0; mount_flags[i].name; i++) {
-            if (!strcmp(args[n], mount_flags[i].name)) {
+            if (!args[na].compare(mount_flags[i].name)) {
                 flags |= mount_flags[i].flag;
                 break;
             }
         }
 
         if (!mount_flags[i].name) {
-            if (!strcmp(args[n], "wait"))
+            if (!args[na].compare("wait"))
                 wait = 1;
             /* if our last argument isn't a flag, wolf it up as an option string */
-            else if (n + 1 == nargs)
-                options = args[n];
+            else if (na + 1 == args.size())
+                options = args[na].c_str();
         }
     }
 
-    system = args[1];
-    source = args[2];
-    target = args[3];
+    system = args[1].c_str();
+    source = args[2].c_str();
+    target = args[3].c_str();
 
     if (!strncmp(source, "mtd@", 4)) {
         n = mtd_name_to_number(source + 4);
@@ -456,7 +446,7 @@
  * This function might request a reboot, in which case it will
  * not return.
  */
-int do_mount_all(int nargs, char **args)
+int do_mount_all(const std::vector<std::string>& args)
 {
     pid_t pid;
     int ret = -1;
@@ -464,10 +454,10 @@
     int status;
     struct fstab *fstab;
 
-    if (nargs != 2) {
+    if (args.size() != 2) {
         return -1;
     }
-    const char* fstabfile = args[1];
+    const char* fstabfile = args[1].c_str();
     /*
      * Call fs_mgr_mount_all() to mount all filesystems.  We fork(2) and
      * do the call in the child to provide protection to the main init
@@ -545,78 +535,77 @@
     return ret;
 }
 
-int do_swapon_all(int nargs, char **args)
+int do_swapon_all(const std::vector<std::string>& args)
 {
     struct fstab *fstab;
     int ret;
 
-    fstab = fs_mgr_read_fstab(args[1]);
+    fstab = fs_mgr_read_fstab(args[1].c_str());
     ret = fs_mgr_swapon_all(fstab);
     fs_mgr_free_fstab(fstab);
 
     return ret;
 }
 
-int do_setprop(int nargs, char **args)
+int do_setprop(const std::vector<std::string>& args)
 {
-    const char *name = args[1];
-    const char *value = args[2];
+    const char* name = args[1].c_str();
+    const char* value = args[2].c_str();
     property_set(name, value);
     return 0;
 }
 
-int do_setrlimit(int nargs, char **args)
+int do_setrlimit(const std::vector<std::string>& args)
 {
     struct rlimit limit;
     int resource;
-    resource = atoi(args[1]);
-    limit.rlim_cur = atoi(args[2]);
-    limit.rlim_max = atoi(args[3]);
+    resource = std::stoi(args[1]);
+    limit.rlim_cur = std::stoi(args[2]);
+    limit.rlim_max = std::stoi(args[3]);
     return setrlimit(resource, &limit);
 }
 
-int do_start(int nargs, char **args)
+int do_start(const std::vector<std::string>& args)
 {
     struct service *svc;
-    svc = service_find_by_name(args[1]);
+    svc = service_find_by_name(args[1].c_str());
     if (svc) {
         service_start(svc, NULL);
     }
     return 0;
 }
 
-int do_stop(int nargs, char **args)
+int do_stop(const std::vector<std::string>& args)
 {
     struct service *svc;
-    svc = service_find_by_name(args[1]);
+    svc = service_find_by_name(args[1].c_str());
     if (svc) {
         service_stop(svc);
     }
     return 0;
 }
 
-int do_restart(int nargs, char **args)
+int do_restart(const std::vector<std::string>& args)
 {
     struct service *svc;
-    svc = service_find_by_name(args[1]);
+    svc = service_find_by_name(args[1].c_str());
     if (svc) {
         service_restart(svc);
     }
     return 0;
 }
 
-int do_powerctl(int nargs, char **args)
+int do_powerctl(const std::vector<std::string>& args)
 {
-    const char* command = args[1];
+    const char* command = args[1].c_str();
     int len = 0;
-    int cmd = 0;
-    const char *reboot_target;
+    unsigned int cmd = 0;
+    const char *reboot_target = "";
     void (*callback_on_ro_remount)(const struct mntent*) = NULL;
 
     if (strncmp(command, "shutdown", 8) == 0) {
         cmd = ANDROID_RB_POWEROFF;
         len = 8;
-        callback_on_ro_remount = unmount_and_fsck;
     } else if (strncmp(command, "reboot", 6) == 0) {
         cmd = ANDROID_RB_RESTART2;
         len = 6;
@@ -626,10 +615,15 @@
     }
 
     if (command[len] == ',') {
-        reboot_target = &command[len + 1];
-    } else if (command[len] == '\0') {
-        reboot_target = "";
-    } else {
+        if (cmd == ANDROID_RB_POWEROFF &&
+            !strcmp(&command[len + 1], "userrequested")) {
+            // The shutdown reason is PowerManager.SHUTDOWN_USER_REQUESTED.
+            // Run fsck once the file system is remounted in read-only mode.
+            callback_on_ro_remount = unmount_and_fsck;
+        } else if (cmd == ANDROID_RB_RESTART2) {
+            reboot_target = &command[len + 1];
+        }
+    } else if (command[len] != '\0') {
         ERROR("powerctl: unrecognized reboot target '%s'\n", &command[len]);
         return -EINVAL;
     }
@@ -638,42 +632,42 @@
                                         callback_on_ro_remount);
 }
 
-int do_trigger(int nargs, char **args)
+int do_trigger(const std::vector<std::string>& args)
 {
     ActionManager::GetInstance().QueueEventTrigger(args[1]);
     return 0;
 }
 
-int do_symlink(int nargs, char **args)
+int do_symlink(const std::vector<std::string>& args)
 {
-    return symlink(args[1], args[2]);
+    return symlink(args[1].c_str(), args[2].c_str());
 }
 
-int do_rm(int nargs, char **args)
+int do_rm(const std::vector<std::string>& args)
 {
-    return unlink(args[1]);
+    return unlink(args[1].c_str());
 }
 
-int do_rmdir(int nargs, char **args)
+int do_rmdir(const std::vector<std::string>& args)
 {
-    return rmdir(args[1]);
+    return rmdir(args[1].c_str());
 }
 
-int do_sysclktz(int nargs, char **args)
+int do_sysclktz(const std::vector<std::string>& args)
 {
     struct timezone tz;
 
-    if (nargs != 2)
+    if (args.size() != 2)
         return -1;
 
     memset(&tz, 0, sizeof(tz));
-    tz.tz_minuteswest = atoi(args[1]);
+    tz.tz_minuteswest = std::stoi(args[1]);
     if (settimeofday(NULL, &tz))
         return -1;
     return 0;
 }
 
-int do_verity_load_state(int nargs, char **args) {
+int do_verity_load_state(const std::vector<std::string>& args) {
     int mode = -1;
     int rc = fs_mgr_load_verity_state(&mode);
     if (rc == 0 && mode == VERITY_MODE_LOGGING) {
@@ -687,18 +681,18 @@
                  android::base::StringPrintf("%d", mode).c_str());
 }
 
-int do_verity_update_state(int nargs, char** args) {
+int do_verity_update_state(const std::vector<std::string>& args) {
     return fs_mgr_update_verity_state(verity_update_property);
 }
 
-int do_write(int nargs, char **args)
+int do_write(const std::vector<std::string>& args)
 {
-    const char *path = args[1];
-    const char *value = args[2];
+    const char* path = args[1].c_str();
+    const char* value = args[2].c_str();
     return write_file(path, value);
 }
 
-int do_copy(int nargs, char **args)
+int do_copy(const std::vector<std::string>& args)
 {
     char *buffer = NULL;
     int rc = 0;
@@ -707,16 +701,16 @@
     int brtw, brtr;
     char *p;
 
-    if (nargs != 3)
+    if (args.size() != 3)
         return -1;
 
-    if (stat(args[1], &info) < 0)
+    if (stat(args[1].c_str(), &info) < 0)
         return -1;
 
-    if ((fd1 = open(args[1], O_RDONLY|O_CLOEXEC)) < 0)
+    if ((fd1 = open(args[1].c_str(), O_RDONLY|O_CLOEXEC)) < 0)
         goto out_err;
 
-    if ((fd2 = open(args[2], O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0660)) < 0)
+    if ((fd2 = open(args[2].c_str(), O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0660)) < 0)
         goto out_err;
 
     if (!(buffer = (char*) malloc(info.st_size)))
@@ -760,13 +754,14 @@
     return rc;
 }
 
-int do_chown(int nargs, char **args) {
+int do_chown(const std::vector<std::string>& args) {
     /* GID is optional. */
-    if (nargs == 3) {
-        if (lchown(args[2], decode_uid(args[1]), -1) == -1)
+    if (args.size() == 3) {
+        if (lchown(args[2].c_str(), decode_uid(args[1].c_str()), -1) == -1)
             return -errno;
-    } else if (nargs == 4) {
-        if (lchown(args[3], decode_uid(args[1]), decode_uid(args[2])) == -1)
+    } else if (args.size() == 4) {
+        if (lchown(args[3].c_str(), decode_uid(args[1].c_str()),
+                   decode_uid(args[2].c_str())) == -1)
             return -errno;
     } else {
         return -1;
@@ -787,43 +782,41 @@
     return mode;
 }
 
-int do_chmod(int nargs, char **args) {
-    mode_t mode = get_mode(args[1]);
-    if (fchmodat(AT_FDCWD, args[2], mode, AT_SYMLINK_NOFOLLOW) < 0) {
+int do_chmod(const std::vector<std::string>& args) {
+    mode_t mode = get_mode(args[1].c_str());
+    if (fchmodat(AT_FDCWD, args[2].c_str(), mode, AT_SYMLINK_NOFOLLOW) < 0) {
         return -errno;
     }
     return 0;
 }
 
-int do_restorecon(int nargs, char **args) {
-    int i;
+int do_restorecon(const std::vector<std::string>& args) {
     int ret = 0;
 
-    for (i = 1; i < nargs; i++) {
-        if (restorecon(args[i]) < 0)
+    for (auto it = std::next(args.begin()); it != args.end(); ++it) {
+        if (restorecon(it->c_str()) < 0)
             ret = -errno;
     }
     return ret;
 }
 
-int do_restorecon_recursive(int nargs, char **args) {
-    int i;
+int do_restorecon_recursive(const std::vector<std::string>& args) {
     int ret = 0;
 
-    for (i = 1; i < nargs; i++) {
-        if (restorecon_recursive(args[i]) < 0)
+    for (auto it = std::next(args.begin()); it != args.end(); ++it) {
+        if (restorecon_recursive(it->c_str()) < 0)
             ret = -errno;
     }
     return ret;
 }
 
-int do_loglevel(int nargs, char **args) {
-    if (nargs != 2) {
+int do_loglevel(const std::vector<std::string>& args) {
+    if (args.size() != 2) {
         ERROR("loglevel: missing argument\n");
         return -EINVAL;
     }
 
-    int log_level = atoi(args[1]);
+    int log_level = std::stoi(args[1]);
     if (log_level < KLOG_ERROR_LEVEL || log_level > KLOG_DEBUG_LEVEL) {
         ERROR("loglevel: invalid log level'%d'\n", log_level);
         return -EINVAL;
@@ -832,28 +825,28 @@
     return 0;
 }
 
-int do_load_persist_props(int nargs, char **args) {
-    if (nargs == 1) {
+int do_load_persist_props(const std::vector<std::string>& args) {
+    if (args.size() == 1) {
         load_persist_props();
         return 0;
     }
     return -1;
 }
 
-int do_load_all_props(int nargs, char **args) {
-    if (nargs == 1) {
+int do_load_all_props(const std::vector<std::string>& args) {
+    if (args.size() == 1) {
         load_all_props();
         return 0;
     }
     return -1;
 }
 
-int do_wait(int nargs, char **args)
+int do_wait(const std::vector<std::string>& args)
 {
-    if (nargs == 2) {
-        return wait_for_file(args[1], COMMAND_RETRY_TIMEOUT);
-    } else if (nargs == 3) {
-        return wait_for_file(args[1], atoi(args[2]));
+    if (args.size() == 2) {
+        return wait_for_file(args[1].c_str(), COMMAND_RETRY_TIMEOUT);
+    } else if (args.size() == 3) {
+        return wait_for_file(args[1].c_str(), std::stoi(args[2]));
     } else
         return -1;
 }
@@ -870,9 +863,9 @@
     return 0;
 }
 
-int do_installkey(int nargs, char **args)
+int do_installkey(const std::vector<std::string>& args)
 {
-    if (nargs != 2) {
+    if (args.size() != 2) {
         return -1;
     }
 
@@ -881,6 +874,6 @@
         return 0;
     }
 
-    return e4crypt_create_device_key(args[1],
+    return e4crypt_create_device_key(args[1].c_str(),
                                      do_installkeys_ensure_dir_exists);
 }
diff --git a/init/init.cpp b/init/init.cpp
index 66143bf..ac4db7c 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -540,7 +540,7 @@
     }
 }
 
-static int wait_for_coldboot_done_action(int nargs, char **args) {
+static int wait_for_coldboot_done_action(const std::vector<std::string>& args) {
     Timer t;
 
     NOTICE("Waiting for %s...\n", COLDBOOT_DONE);
@@ -570,7 +570,7 @@
  * time. We do not reboot or halt on failures, as this is a best-effort
  * attempt.
  */
-static int mix_hwrng_into_linux_rng_action(int nargs, char **args)
+static int mix_hwrng_into_linux_rng_action(const std::vector<std::string>& args)
 {
     int result = -1;
     int hwrandom_fd = -1;
@@ -632,13 +632,13 @@
     return result;
 }
 
-static int keychord_init_action(int nargs, char **args)
+static int keychord_init_action(const std::vector<std::string>& args)
 {
     keychord_init();
     return 0;
 }
 
-static int console_init_action(int nargs, char **args)
+static int console_init_action(const std::vector<std::string>& args)
 {
     std::string console = property_get("ro.boot.console");
     if (!console.empty()) {
@@ -753,7 +753,7 @@
     if (qemu[0]) import_kernel_cmdline(true, import_kernel_nv);
 }
 
-static int queue_property_triggers_action(int nargs, char **args)
+static int queue_property_triggers_action(const std::vector<std::string>& args)
 {
     ActionManager::GetInstance().QueueAllPropertyTriggers();
     /* enable property triggers */
diff --git a/init/init_parser.cpp b/init/init_parser.cpp
index ab0dbc3..d420351 100644
--- a/init/init_parser.cpp
+++ b/init/init_parser.cpp
@@ -62,7 +62,7 @@
 
 static struct {
     const char *name;
-    int (*func)(int nargs, char **args);
+    int (*func)(const std::vector<std::string>& args);
     unsigned char nargs;
     unsigned char flags;
 } keyword_info[KEYWORD_COUNT] = {
diff --git a/init/keywords.h b/init/keywords.h
index e637d7d..922feee 100644
--- a/init/keywords.h
+++ b/init/keywords.h
@@ -1,43 +1,45 @@
 #ifndef KEYWORD
-int do_bootchart_init(int nargs, char **args);
-int do_class_start(int nargs, char **args);
-int do_class_stop(int nargs, char **args);
-int do_class_reset(int nargs, char **args);
-int do_domainname(int nargs, char **args);
-int do_enable(int nargs, char **args);
-int do_exec(int nargs, char **args);
-int do_export(int nargs, char **args);
-int do_hostname(int nargs, char **args);
-int do_ifup(int nargs, char **args);
-int do_insmod(int nargs, char **args);
-int do_installkey(int nargs, char **args);
-int do_mkdir(int nargs, char **args);
-int do_mount_all(int nargs, char **args);
-int do_mount(int nargs, char **args);
-int do_powerctl(int nargs, char **args);
-int do_restart(int nargs, char **args);
-int do_restorecon(int nargs, char **args);
-int do_restorecon_recursive(int nargs, char **args);
-int do_rm(int nargs, char **args);
-int do_rmdir(int nargs, char **args);
-int do_setprop(int nargs, char **args);
-int do_setrlimit(int nargs, char **args);
-int do_start(int nargs, char **args);
-int do_stop(int nargs, char **args);
-int do_swapon_all(int nargs, char **args);
-int do_trigger(int nargs, char **args);
-int do_symlink(int nargs, char **args);
-int do_sysclktz(int nargs, char **args);
-int do_write(int nargs, char **args);
-int do_copy(int nargs, char **args);
-int do_chown(int nargs, char **args);
-int do_chmod(int nargs, char **args);
-int do_loglevel(int nargs, char **args);
-int do_load_persist_props(int nargs, char **args);
-int do_load_all_props(int nargs, char **args);
-int do_verity_load_state(int nargs, char **args);
-int do_verity_update_state(int nargs, char **args);
-int do_wait(int nargs, char **args);
+#include <string>
+#include <vector>
+int do_bootchart_init(const std::vector<std::string>& args);
+int do_class_start(const std::vector<std::string>& args);
+int do_class_stop(const std::vector<std::string>& args);
+int do_class_reset(const std::vector<std::string>& args);
+int do_domainname(const std::vector<std::string>& args);
+int do_enable(const std::vector<std::string>& args);
+int do_exec(const std::vector<std::string>& args);
+int do_export(const std::vector<std::string>& args);
+int do_hostname(const std::vector<std::string>& args);
+int do_ifup(const std::vector<std::string>& args);
+int do_insmod(const std::vector<std::string>& args);
+int do_installkey(const std::vector<std::string>& args);
+int do_mkdir(const std::vector<std::string>& args);
+int do_mount_all(const std::vector<std::string>& args);
+int do_mount(const std::vector<std::string>& args);
+int do_powerctl(const std::vector<std::string>& args);
+int do_restart(const std::vector<std::string>& args);
+int do_restorecon(const std::vector<std::string>& args);
+int do_restorecon_recursive(const std::vector<std::string>& args);
+int do_rm(const std::vector<std::string>& args);
+int do_rmdir(const std::vector<std::string>& args);
+int do_setprop(const std::vector<std::string>& args);
+int do_setrlimit(const std::vector<std::string>& args);
+int do_start(const std::vector<std::string>& args);
+int do_stop(const std::vector<std::string>& args);
+int do_swapon_all(const std::vector<std::string>& args);
+int do_trigger(const std::vector<std::string>& args);
+int do_symlink(const std::vector<std::string>& args);
+int do_sysclktz(const std::vector<std::string>& args);
+int do_write(const std::vector<std::string>& args);
+int do_copy(const std::vector<std::string>& args);
+int do_chown(const std::vector<std::string>& args);
+int do_chmod(const std::vector<std::string>& args);
+int do_loglevel(const std::vector<std::string>& args);
+int do_load_persist_props(const std::vector<std::string>& args);
+int do_load_all_props(const std::vector<std::string>& args);
+int do_verity_load_state(const std::vector<std::string>& args);
+int do_verity_update_state(const std::vector<std::string>& args);
+int do_wait(const std::vector<std::string>& args);
 #define __MAKE_KEYWORD_ENUM__
 #define KEYWORD(symbol, flags, nargs, func) K_##symbol,
 enum {
diff --git a/init/parser/tokenizer.h b/init/parser/tokenizer.h
index 40a22b1..8312a08 100644
--- a/init/parser/tokenizer.h
+++ b/init/parser/tokenizer.h
@@ -12,6 +12,9 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
+#ifndef _INIT_PARSER_TOKENIZER_H
+#define _INIT_PARSER_TOKENIZER_H
+
 #include <string>
 
 namespace init {
@@ -67,3 +70,5 @@
 };
 
 }  // namespace init
+
+#endif