adb: win32: define UNICODE/_UNICODE, Unicode error messages, misc

Define the UNICODE and _UNICODE preprocessor symbols to make passing
char* to Ansi/Unicode-agnostic Windows and C Runtime APIs break the
build. The solution is to call wide Windows and C Runtime APIs and use
widen(utf8).c_str(). Most code was already calling wide APIs. Defining
these symbols makes a call to CreateEvent() (which previously mapped to
CreateEventA()) turn into a call to CreateEventW().

Make SystemErrorCodeToString() use Unicode.

Add various comments.

Change-Id: I9b212412348a29826718e897a486489e1f142d16
Signed-off-by: Spencer Low <CompareAndSwap@gmail.com>
diff --git a/Android.mk b/Android.mk
index ec7f49c..e911bc3 100644
--- a/Android.mk
+++ b/Android.mk
@@ -22,6 +22,15 @@
     -Wno-missing-field-initializers \
     -DADB_REVISION='"$(adb_version)"' \
 
+# Define windows.h and tchar.h Unicode preprocessor symbols so that
+# CreateFile(), _tfopen(), etc. map to versions that take wchar_t*, breaking the
+# build if you accidentally pass char*. Fix by calling like:
+# CreateFileW(widen(utf8).c_str()).
+ADB_COMMON_windows_CFLAGS := \
+    -DUNICODE=1 -D_UNICODE=1 \
+
+ADB_COMMON_CFLAGS += $(ADB_COMMON_$(HOST_OS)_CFLAGS)
+
 # libadb
 # =========================================================
 
diff --git a/sysdeps_win32.cpp b/sysdeps_win32.cpp
index 08f267b..803a172 100644
--- a/sysdeps_win32.cpp
+++ b/sysdeps_win32.cpp
@@ -90,9 +90,9 @@
 
 std::string SystemErrorCodeToString(const DWORD error_code) {
   const int kErrorMessageBufferSize = 256;
-  char msgbuf[kErrorMessageBufferSize];
+  WCHAR msgbuf[kErrorMessageBufferSize];
   DWORD flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS;
-  DWORD len = FormatMessageA(flags, nullptr, error_code, 0, msgbuf,
+  DWORD len = FormatMessageW(flags, nullptr, error_code, 0, msgbuf,
                              arraysize(msgbuf), nullptr);
   if (len == 0) {
     return android::base::StringPrintf(
@@ -100,7 +100,8 @@
         error_code);
   }
 
-  std::string msg(msgbuf);
+  // Convert UTF-16 to UTF-8.
+  std::string msg(narrow(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
@@ -803,6 +804,14 @@
     snprintf(port_str, sizeof(port_str), "%d", port);
 
     struct addrinfo* addrinfo_ptr = nullptr;
+
+#if (NTDDI_VERSION >= NTDDI_WINXPSP2) || (_WIN32_WINNT >= _WIN32_WINNT_WS03)
+    // TODO: When the Android SDK tools increases the Windows system
+    // requirements >= WinXP SP2, switch to GetAddrInfoW(widen(host).c_str()).
+#else
+    // Otherwise, keep using getaddrinfo(), or do runtime API detection
+    // with GetProcAddress("GetAddrInfoW").
+#endif
     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(),
@@ -3237,9 +3246,10 @@
 //
 // 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.)
+// such as Lucida Console or Consolas, and in the case of East Asian languages
+// (such as Chinese, Japanese, Korean), the user must go to the Control Panel
+// and change the "system locale" to Chinese, etc., which allows a Chinese, etc.
+// 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
@@ -3294,6 +3304,10 @@
 // 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) {
+    // Note: Do not call SystemErrorCodeToString() from widen() because
+    // SystemErrorCodeToString() calls narrow() which may call fatal() which
+    // calls adb_vfprintf() which calls widen(), potentially causing infinite
+    // recursion.
     const int chars_to_convert = MultiByteToWideChar(CP_UTF8, 0, utf8, size,
                                                      NULL, 0);
     if (chars_to_convert <= 0) {
@@ -3349,11 +3363,14 @@
 
 // Convert from UTF-16 to UTF-8.
 std::string narrow(const wchar_t* utf16) {
+    // Note: Do not call SystemErrorCodeToString() from narrow() because
+    // SystemErrorCodeToString() calls narrows() and we don't want potential
+    // infinite recursion.
     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",
+        fatal("WideCharToMultiByte failed counting: %d, GetLastError: %lu",
               chars_required, GetLastError());
     }
 
@@ -3371,7 +3388,7 @@
                                            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",
+        fatal("WideCharToMultiByte failed conversion: %d, GetLastError: %lu",
               result, GetLastError());
     }
 
@@ -3707,7 +3724,9 @@
 
 // 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.
+// currently updated if putenv, setenv, unsetenv are called. Note that no
+// thread synchronization is done, but we're called early enough in
+// single-threaded startup that things work ok.
 static std::unordered_map<std::string, char*> g_environ_utf8;
 
 // Make sure that shadow UTF-8 environment variables are setup.
@@ -3744,8 +3763,7 @@
 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));
+    const auto it = g_environ_utf8.find(std::string(name));
     if (it == g_environ_utf8.end()) {
         return nullptr;
     }