This is an automated email from the ASF dual-hosted git repository.

lidavidm pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow.git


The following commit(s) were added to refs/heads/main by this push:
     new fc5fd482f2 GH-47726 : [C++][FlightRPC] ODBC Unicode Support (#47771)
fc5fd482f2 is described below

commit fc5fd482f21bb51a8bd955fe6c46e8650e8105bd
Author: Alina (Xi) Li <[email protected]>
AuthorDate: Thu Oct 16 00:28:48 2025 -0700

    GH-47726 : [C++][FlightRPC] ODBC Unicode Support (#47771)
    
    ### Rationale for this change
    Enable ODBC unicode support, so ODBC can handle wide characters.
    
    ### What changes are included in this PR?
    - Enable ODBC unicode support by setting `-DUNICODE` to 1
    - DSN is read and retrieved in unicode format, and then converted to 
regular strings for driver
    - Fix a string reading bug in `GetAttributeSQLWCHAR`
    
    ### Are these changes tested?
    Build is tested locally
    ### Are there any user-facing changes?
    No
    * GitHub Issue: #47726
    
    Lead-authored-by: Alina (Xi) Li <[email protected]>
    Co-authored-by: Alina (Xi) Li <[email protected]>
    Co-authored-by: rscales <[email protected]>
    Signed-off-by: David Li <[email protected]>
---
 cpp/src/arrow/flight/sql/odbc/CMakeLists.txt       |   2 +-
 cpp/src/arrow/flight/sql/odbc/odbc.def             |   4 +-
 .../arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt |  17 +--
 .../flight/sql/odbc/odbc_impl/attribute_utils.h    |  11 +-
 .../sql/odbc/odbc_impl/config/configuration.cc     |  49 +++---
 .../sql/odbc/odbc_impl/config/configuration.h      |   1 +
 .../sql/odbc/odbc_impl/flight_sql_connection.cc    |   2 +-
 .../flight/sql/odbc/odbc_impl/odbc_connection.cc   |  42 +++---
 .../arrow/flight/sql/odbc/odbc_impl/system_dsn.cc  | 136 ++++++++++++-----
 .../sql/odbc/odbc_impl/system_trust_store.cc       |  13 +-
 .../flight/sql/odbc/odbc_impl/system_trust_store.h |   4 +-
 .../sql/odbc/odbc_impl/ui/add_property_window.cc   |  18 +--
 .../sql/odbc/odbc_impl/ui/add_property_window.h    |   6 +-
 .../flight/sql/odbc/odbc_impl/ui/custom_window.cc  |   3 +-
 .../flight/sql/odbc/odbc_impl/ui/custom_window.h   |   2 +-
 .../odbc/odbc_impl/ui/dsn_configuration_window.cc  | 166 ++++++++++++---------
 .../arrow/flight/sql/odbc/odbc_impl/ui/window.cc   |  58 +++----
 .../arrow/flight/sql/odbc/odbc_impl/ui/window.h    |  32 ++--
 cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h     |  16 ++
 19 files changed, 358 insertions(+), 224 deletions(-)

diff --git a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt 
b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
index 98a0121782..79f351ae9c 100644
--- a/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/CMakeLists.txt
@@ -55,7 +55,7 @@ add_arrow_lib(arrow_flight_sql_odbc
               DEPENDENCIES
               arrow_flight_sql
               DEFINITIONS
-              FMT_HEADER_ONLY
+              UNICODE
               SHARED_LINK_FLAGS
               ${ARROW_VERSION_SCRIPT_FLAGS} # Defined in 
cpp/arrow/CMakeLists.txt
               SHARED_LINK_LIBS
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc.def 
b/cpp/src/arrow/flight/sql/odbc/odbc.def
index fe7ef1a046..a8191ff662 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc.def
+++ b/cpp/src/arrow/flight/sql/odbc/odbc.def
@@ -17,8 +17,8 @@
 
 LIBRARY   arrow_flight_sql_odbc
 EXPORTS
-       ; TODO: update to ConfigDSNW when driver has unicode implemented
-       ; ConfigDSN
+       ; GH-46574 TODO enable DSN window
+       ; ConfigDSNW
        SQLAllocConnect
        SQLAllocEnv
        SQLAllocHandle
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
index 1ec196ec1f..b232577ee3 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/CMakeLists.txt
@@ -39,12 +39,16 @@ add_library(arrow_odbc_spi_impl
             blocking_queue.h
             calendar_utils.cc
             calendar_utils.h
+            config/configuration.cc
+            config/configuration.h
+            config/connection_string_parser.cc
+            config/connection_string_parser.h
             diagnostics.cc
             diagnostics.h
+            error_codes.h
             encoding.cc
             encoding.h
             encoding_utils.h
-            error_codes.h
             exceptions.cc
             exceptions.h
             flight_sql_auth_method.cc
@@ -106,16 +110,13 @@ add_library(arrow_odbc_spi_impl
             type_utilities.h
             util.cc
             util.h)
+target_compile_definitions(arrow_odbc_spi_impl PUBLIC UNICODE)
 target_include_directories(arrow_odbc_spi_impl PUBLIC include 
include/odbc_impl)
 target_include_directories(arrow_odbc_spi_impl PUBLIC 
${CMAKE_CURRENT_LIST_DIR})
 
 if(WIN32)
   target_sources(arrow_odbc_spi_impl
-                 PRIVATE config/configuration.cc
-                         config/configuration.h
-                         config/connection_string_parser.cc
-                         config/connection_string_parser.h
-                         ui/add_property_window.cc
+                 PRIVATE ui/add_property_window.cc
                          ui/add_property_window.h
                          ui/custom_window.cc
                          ui/custom_window.h
@@ -123,9 +124,7 @@ if(WIN32)
                          ui/dsn_configuration_window.h
                          ui/window.cc
                          ui/window.h
-                         win_system_dsn.cc
-                         system_dsn.cc
-                         system_dsn.h)
+                         system_dsn.cc)
 endif()
 
 target_link_libraries(arrow_odbc_spi_impl PUBLIC arrow_flight_sql_shared
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
index 7750185b63..7baea759ed 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/attribute_utils.h
@@ -83,18 +83,21 @@ template <typename O>
 inline SQLRETURN GetAttributeSQLWCHAR(const std::string& attribute_value,
                                       bool is_length_in_bytes, SQLPOINTER 
output,
                                       O output_size, O* output_len_ptr) {
-  size_t result = ConvertToSqlWChar(
+  size_t length = ConvertToSqlWChar(
       attribute_value, reinterpret_cast<SQLWCHAR*>(output),
       is_length_in_bytes ? output_size : output_size * GetSqlWCharSize());
 
+  if (!is_length_in_bytes) {
+    length = length / GetSqlWCharSize();
+  }
+
   if (output_len_ptr) {
-    *output_len_ptr =
-        static_cast<O>(is_length_in_bytes ? result : result / 
GetSqlWCharSize());
+    *output_len_ptr = static_cast<O>(length);
   }
 
   if (output &&
       output_size <
-          static_cast<O>(result + (is_length_in_bytes ? GetSqlWCharSize() : 
1))) {
+          static_cast<O>(length + (is_length_in_bytes ? GetSqlWCharSize() : 
1))) {
     return SQL_SUCCESS_WITH_INFO;
   }
   return SQL_SUCCESS;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc
index 1619a68a14..cdb889f056 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.cc
@@ -17,6 +17,9 @@
 
 #include "arrow/flight/sql/odbc/odbc_impl/config/configuration.h"
 #include "arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.h"
+#include "arrow/flight/sql/odbc/odbc_impl/util.h"
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
 
 #include <odbcinst.h>
 #include <boost/range/adaptor/map.hpp>
@@ -26,7 +29,6 @@
 
 namespace arrow::flight::sql::odbc {
 namespace config {
-
 static const char DEFAULT_DSN[] = "Apache Arrow Flight SQL";
 static const char DEFAULT_ENABLE_ENCRYPTION[] = TRUE_STR;
 static const char DEFAULT_USE_CERT_STORE[] = TRUE_STR;
@@ -35,23 +37,27 @@ static const char DEFAULT_DISABLE_CERT_VERIFICATION[] = 
FALSE_STR;
 namespace {
 std::string ReadDsnString(const std::string& dsn, const std::string_view& key,
                           const std::string& dflt = "") {
-#define BUFFER_SIZE (1024)
-  std::vector<char> buf(BUFFER_SIZE);
+  CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
+  CONVERT_WIDE_STR(const std::wstring wkey, key);
+  CONVERT_WIDE_STR(const std::wstring wdflt, dflt);
 
-  std::string key_str = std::string(key);
+#define BUFFER_SIZE (1024)
+  std::vector<wchar_t> buf(BUFFER_SIZE);
   int ret =
-      SQLGetPrivateProfileString(dsn.c_str(), key_str.c_str(), dflt.c_str(), 
buf.data(),
-                                 static_cast<int>(buf.size()), "ODBC.INI");
+      SQLGetPrivateProfileString(wdsn.c_str(), wkey.c_str(), wdflt.c_str(), 
buf.data(),
+                                 static_cast<int>(buf.size()), L"ODBC.INI");
 
   if (ret > BUFFER_SIZE) {
     // If there wasn't enough space, try again with the right size buffer.
     buf.resize(ret + 1);
     ret =
-        SQLGetPrivateProfileString(dsn.c_str(), key_str.c_str(), dflt.c_str(), 
buf.data(),
-                                   static_cast<int>(buf.size()), "ODBC.INI");
+        SQLGetPrivateProfileString(wdsn.c_str(), wkey.c_str(), wdflt.c_str(), 
buf.data(),
+                                   static_cast<int>(buf.size()), L"ODBC.INI");
   }
 
-  return std::string(buf.data(), ret);
+  std::wstring wresult = std::wstring(buf.data(), ret);
+  CONVERT_UTF8_STR(const std::string result, wresult);
+  return result;
 }
 
 void RemoveAllKnownKeys(std::vector<std::string>& keys) {
@@ -68,28 +74,32 @@ void RemoveAllKnownKeys(std::vector<std::string>& keys) {
 }
 
 std::vector<std::string> ReadAllKeys(const std::string& dsn) {
-  std::vector<char> buf(BUFFER_SIZE);
+  CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
+
+  std::vector<wchar_t> buf(BUFFER_SIZE);
 
-  int ret = SQLGetPrivateProfileString(dsn.c_str(), NULL, "", buf.data(),
-                                       static_cast<int>(buf.size()), 
"ODBC.INI");
+  int ret = SQLGetPrivateProfileString(wdsn.c_str(), NULL, L"", buf.data(),
+                                       static_cast<int>(buf.size()), 
L"ODBC.INI");
 
   if (ret > BUFFER_SIZE) {
     // If there wasn't enough space, try again with the right size buffer.
     buf.resize(ret + 1);
-    ret = SQLGetPrivateProfileString(dsn.c_str(), NULL, "", buf.data(),
-                                     static_cast<int>(buf.size()), "ODBC.INI");
+    ret = SQLGetPrivateProfileString(wdsn.c_str(), NULL, L"", buf.data(),
+                                     static_cast<int>(buf.size()), 
L"ODBC.INI");
   }
 
   // When you pass NULL to SQLGetPrivateProfileString it gives back a \0 
delimited list of
   // all the keys. The below loop simply tokenizes all the keys and places 
them into a
   // vector.
   std::vector<std::string> keys;
-  char* begin = buf.data();
+  wchar_t* begin = buf.data();
   while (begin && *begin != '\0') {
-    char* cur;
+    wchar_t* cur;
     for (cur = begin; *cur != '\0'; ++cur) {
     }
-    keys.emplace_back(begin, cur);
+
+    CONVERT_UTF8_STR(const std::string key, std::wstring(begin, cur));
+    keys.emplace_back(key);
     begin = ++cur;
   }
   return keys;
@@ -153,6 +163,11 @@ const std::string& Configuration::Get(const 
std::string_view& key) const {
   return itr->second;
 }
 
+void Configuration::Set(const std::string_view& key, const std::wstring& 
wvalue) {
+  CONVERT_UTF8_STR(const std::string value, wvalue);
+  Set(key, value);
+}
+
 void Configuration::Set(const std::string_view& key, const std::string& value) 
{
   const std::string copy = boost::trim_copy(value);
   if (!copy.empty()) {
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h
index beca536002..77d07b1420 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/config/configuration.h
@@ -59,6 +59,7 @@ class Configuration {
   void Clear();
   bool IsSet(const std::string_view& key) const;
   const std::string& Get(const std::string_view& key) const;
+  void Set(const std::string_view& key, const std::wstring& wvalue);
   void Set(const std::string_view& key, const std::string& value);
 
   /**
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc
index 9b36718f5a..b4f9c69b39 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.cc
@@ -71,7 +71,7 @@ namespace {
 
 #if _WIN32 || _WIN64
 constexpr auto SYSTEM_TRUST_STORE_DEFAULT = true;
-constexpr auto STORES = {"CA", "MY", "ROOT", "SPC"};
+constexpr auto STORES = {L"CA", L"MY", L"ROOT", L"SPC"};
 
 inline std::string GetCerts() {
   std::string certs;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc
index 1f2df4192e..c0a55840d5 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/odbc_connection.cc
@@ -17,6 +17,9 @@
 
 #include "arrow/flight/sql/odbc/odbc_impl/odbc_connection.h"
 
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
+
 #include "arrow/flight/sql/odbc/odbc_impl/attribute_utils.h"
 #include "arrow/flight/sql/odbc/odbc_impl/exceptions.h"
 #include "arrow/flight/sql/odbc/odbc_impl/odbc_descriptor.h"
@@ -24,6 +27,7 @@
 #include "arrow/flight/sql/odbc/odbc_impl/odbc_statement.h"
 #include "arrow/flight/sql/odbc/odbc_impl/spi/connection.h"
 #include "arrow/flight/sql/odbc/odbc_impl/spi/statement.h"
+#include "arrow/flight/sql/odbc/odbc_impl/util.h"
 
 #include <odbcinst.h>
 #include <sql.h>
@@ -56,41 +60,43 @@ const boost::xpressive::sregex CONNECTION_STR_REGEX(
 void loadPropertiesFromDSN(const std::string& dsn,
                            Connection::ConnPropertyMap& properties) {
   const size_t BUFFER_SIZE = 1024 * 10;
-  std::vector<char> outputBuffer;
-  outputBuffer.resize(BUFFER_SIZE, '\0');
+  std::vector<wchar_t> output_buffer;
+  output_buffer.resize(BUFFER_SIZE, '\0');
   SQLSetConfigMode(ODBC_BOTH_DSN);
 
-  SQLGetPrivateProfileString(dsn.c_str(), NULL, "", &outputBuffer[0], 
BUFFER_SIZE,
-                             "odbc.ini");
+  CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
+
+  SQLGetPrivateProfileString(wdsn.c_str(), NULL, L"", &output_buffer[0], 
BUFFER_SIZE,
+                             L"odbc.ini");
 
   // The output buffer holds the list of keys in a series of NUL-terminated 
strings.
   // The series is terminated with an empty string (eg a NUL-terminator 
terminating the
   // last key followed by a NUL terminator after).
-  std::vector<std::string_view> keys;
+  std::vector<std::wstring_view> keys;
   size_t pos = 0;
   while (pos < BUFFER_SIZE) {
-    std::string key(&outputBuffer[pos]);
-    if (key.empty()) {
+    std::wstring wkey(&output_buffer[pos]);
+    if (wkey.empty()) {
       break;
     }
-    size_t len = key.size();
+    size_t len = wkey.size();
 
     // Skip over Driver or DSN keys.
-    if (!boost::iequals(key, "DSN") && !boost::iequals(key, "Driver")) {
-      keys.emplace_back(std::move(key));
+    if (!boost::iequals(wkey, L"DSN") && !boost::iequals(wkey, L"Driver")) {
+      keys.emplace_back(std::move(wkey));
     }
     pos += len + 1;
   }
 
-  for (auto& key : keys) {
-    outputBuffer.clear();
-    outputBuffer.resize(BUFFER_SIZE, '\0');
-
-    std::string key_str = std::string(key);
-    SQLGetPrivateProfileString(dsn.c_str(), key_str.c_str(), "", 
&outputBuffer[0],
-                               BUFFER_SIZE, "odbc.ini");
+  for (auto& wkey : keys) {
+    output_buffer.clear();
+    output_buffer.resize(BUFFER_SIZE, '\0');
+    SQLGetPrivateProfileString(wdsn.c_str(), wkey.data(), L"", 
&output_buffer[0],
+                               BUFFER_SIZE, L"odbc.ini");
 
-    std::string value = std::string(&outputBuffer[0]);
+    std::wstring wvalue = std::wstring(&output_buffer[0]);
+    CONVERT_UTF8_STR(const std::string value, wvalue);
+    CONVERT_UTF8_STR(const std::string key, std::wstring(wkey));
     auto propIter = properties.find(key);
     if (propIter == properties.end()) {
       properties.emplace(std::make_pair(std::move(key), std::move(value)));
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc
index 1c7593c317..d10eff2580 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_dsn.cc
@@ -27,12 +27,13 @@
 #include "arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.h"
 #include "arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.h"
 #include "arrow/flight/sql/odbc/odbc_impl/ui/window.h"
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
 
 #include <odbcinst.h>
-#include <codecvt>
-#include <locale>
 #include <sstream>
 
+using arrow::flight::sql::odbc::DriverException;
 using arrow::flight::sql::odbc::FlightSqlConnection;
 using arrow::flight::sql::odbc::config::Configuration;
 using arrow::flight::sql::odbc::config::ConnectionStringParser;
@@ -40,19 +41,13 @@ using 
arrow::flight::sql::odbc::config::DsnConfigurationWindow;
 using arrow::flight::sql::odbc::config::Result;
 using arrow::flight::sql::odbc::config::Window;
 
-BOOL CALLBACK ConfigDriver(HWND hwndParent, WORD fRequest, LPCSTR lpszDriver,
-                           LPCSTR lpszArgs, LPSTR lpszMsg, WORD cbMsgMax,
-                           WORD* pcbMsgOut) {
-  return false;
-}
-
-bool DisplayConnectionWindow(void* windowParent, Configuration& config) {
-  HWND hwndParent = (HWND)windowParent;
+bool DisplayConnectionWindow(void* window_parent, Configuration& config) {
+  HWND hwnd_parent = (HWND)window_parent;
 
-  if (!hwndParent) return true;
+  if (!hwnd_parent) return true;
 
   try {
-    Window parent(hwndParent);
+    Window parent(hwnd_parent);
     DsnConfigurationWindow window(&parent, config);
 
     window.Create();
@@ -61,30 +56,46 @@ bool DisplayConnectionWindow(void* windowParent, 
Configuration& config) {
     window.Update();
 
     return ProcessMessages(window) == Result::OK;
-  } catch (arrow::flight::sql::odbc::DriverException& err) {
+  } catch (const DriverException& err) {
     std::stringstream buf;
-    buf << "Message: " << err.GetMessageText() << ", Code: " << 
err.GetNativeError();
-    std::string message = buf.str();
-    MessageBox(NULL, message.c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK);
-
-    SQLPostInstallerError(err.GetNativeError(), err.GetMessageText().c_str());
+    buf << "SQL State: " << err.GetSqlState() << ", Message: " << 
err.GetMessageText()
+        << ", Code: " << err.GetNativeError();
+    std::wstring wmessage =
+        arrow::util::UTF8ToWideString(buf.str()).ValueOr(L"Error during load 
DSN");
+    MessageBox(NULL, wmessage.c_str(), L"Error!", MB_ICONEXCLAMATION | MB_OK);
+
+    std::wstring wmessage_text = 
arrow::util::UTF8ToWideString(err.GetMessageText())
+                                     .ValueOr(L"Error during load DSN");
+    SQLPostInstallerError(err.GetNativeError(), wmessage_text.c_str());
   }
 
   return false;
 }
 
+void PostError(DWORD error_code, LPCWSTR error_msg) {
+  MessageBox(NULL, error_msg, L"Error!", MB_ICONEXCLAMATION | MB_OK);
+  SQLPostInstallerError(error_code, error_msg);
+}
+
+void PostArrowUtilError(arrow::Status error_status) {
+  std::string error_msg = error_status.message();
+  std::wstring werror_msg = arrow::util::UTF8ToWideString(error_msg).ValueOr(
+      L"Error during utf8 to wide string conversion");
+
+  PostError(ODBC_ERROR_GENERAL_ERR, werror_msg.c_str());
+}
+
 void PostLastInstallerError() {
 #define BUFFER_SIZE (1024)
   DWORD code;
-  char msg[BUFFER_SIZE];
+  wchar_t msg[BUFFER_SIZE];
   SQLInstallerError(1, &code, msg, BUFFER_SIZE, NULL);
 
-  std::stringstream buf;
-  buf << "Message: \"" << msg << "\", Code: " << code;
-  std::string error_msg = buf.str();
+  std::wstringstream buf;
+  buf << L"Message: \"" << msg << L"\", Code: " << code;
+  std::wstring error_msg = buf.str();
 
-  MessageBox(NULL, error_msg.c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK);
-  SQLPostInstallerError(code, error_msg.c_str());
+  PostError(code, error_msg.c_str());
 }
 
 /**
@@ -93,7 +104,7 @@ void PostLastInstallerError() {
  * @param dsn DSN name.
  * @return True on success and false on fail.
  */
-bool UnregisterDsn(const std::string& dsn) {
+bool UnregisterDsn(const std::wstring& dsn) {
   if (SQLRemoveDSNFromIni(dsn.c_str())) {
     return true;
   }
@@ -109,10 +120,16 @@ bool UnregisterDsn(const std::string& dsn) {
  * @param driver Driver.
  * @return True on success and false on fail.
  */
-bool RegisterDsn(const Configuration& config, LPCSTR driver) {
+bool RegisterDsn(const Configuration& config, LPCWSTR driver) {
   const std::string& dsn = config.Get(FlightSqlConnection::DSN);
+  auto wdsn_result = arrow::util::UTF8ToWideString(dsn);
+  if (!wdsn_result.status().ok()) {
+    PostArrowUtilError(wdsn_result.status());
+    return false;
+  }
+  std::wstring wdsn = wdsn_result.ValueOrDie();
 
-  if (!SQLWriteDSNToIni(dsn.c_str(), driver)) {
+  if (!SQLWriteDSNToIni(wdsn.c_str(), driver)) {
     PostLastInstallerError();
     return false;
   }
@@ -125,9 +142,22 @@ bool RegisterDsn(const Configuration& config, LPCSTR 
driver) {
       continue;
     }
 
-    std::string key_str = std::string(key);
-    if (!SQLWritePrivateProfileString(dsn.c_str(), key_str.c_str(), 
it->second.c_str(),
-                                      "ODBC.INI")) {
+    auto wkey_result = arrow::util::UTF8ToWideString(key);
+    if (!wkey_result.status().ok()) {
+      PostArrowUtilError(wkey_result.status());
+      return false;
+    }
+    std::wstring wkey = wkey_result.ValueOrDie();
+
+    auto wvalue_result = arrow::util::UTF8ToWideString(it->second);
+    if (!wvalue_result.status().ok()) {
+      PostArrowUtilError(wvalue_result.status());
+      return false;
+    }
+    std::wstring wvalue = wvalue_result.ValueOrDie();
+
+    if (!SQLWritePrivateProfileString(wdsn.c_str(), wkey.c_str(), 
wvalue.c_str(),
+                                      L"ODBC.INI")) {
       PostLastInstallerError();
       return false;
     }
@@ -136,15 +166,24 @@ bool RegisterDsn(const Configuration& config, LPCSTR 
driver) {
   return true;
 }
 
-BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR driver, LPCSTR 
attributes) {
+BOOL INSTAPI ConfigDSNW(HWND hwnd_parent, WORD req, LPCWSTR wdriver,
+                        LPCWSTR wattributes) {
   Configuration config;
   ConnectionStringParser parser(config);
-  parser.ParseConfigAttributes(attributes);
+
+  auto attributes_result = 
arrow::util::WideStringToUTF8(std::wstring(wattributes));
+  if (!attributes_result.status().ok()) {
+    PostArrowUtilError(attributes_result.status());
+    return FALSE;
+  }
+  std::string attributes = attributes_result.ValueOrDie();
+
+  parser.ParseConfigAttributes(attributes.c_str());
 
   switch (req) {
     case ODBC_ADD_DSN: {
       config.LoadDefaults();
-      if (!DisplayConnectionWindow(hwndParent, config) || !RegisterDsn(config, 
driver))
+      if (!DisplayConnectionWindow(hwnd_parent, config) || 
!RegisterDsn(config, wdriver))
         return FALSE;
 
       break;
@@ -152,13 +191,28 @@ BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR 
driver, LPCSTR attribut
 
     case ODBC_CONFIG_DSN: {
       const std::string& dsn = config.Get(FlightSqlConnection::DSN);
-      if (!SQLValidDSN(dsn.c_str())) return FALSE;
+      auto wdsn_result = arrow::util::UTF8ToWideString(dsn);
+      if (!wdsn_result.status().ok()) {
+        PostArrowUtilError(wdsn_result.status());
+        return FALSE;
+      }
+      std::wstring wdsn = wdsn_result.ValueOrDie();
+      if (!SQLValidDSN(wdsn.c_str())) return FALSE;
 
       Configuration loaded(config);
-      loaded.LoadDsn(dsn);
+      try {
+        loaded.LoadDsn(dsn);
+      } catch (const DriverException& err) {
+        std::string error_msg = err.GetMessageText();
+        std::wstring werror_msg =
+            arrow::util::UTF8ToWideString(error_msg).ValueOr(L"Error during 
DSN load");
+
+        PostError(err.GetNativeError(), werror_msg.c_str());
+        return FALSE;
+      }
 
-      if (!DisplayConnectionWindow(hwndParent, loaded) || 
!UnregisterDsn(dsn.c_str()) ||
-          !RegisterDsn(loaded, driver))
+      if (!DisplayConnectionWindow(hwnd_parent, loaded) || 
!UnregisterDsn(wdsn.c_str()) ||
+          !RegisterDsn(loaded, wdriver))
         return FALSE;
 
       break;
@@ -166,7 +220,13 @@ BOOL INSTAPI ConfigDSN(HWND hwndParent, WORD req, LPCSTR 
driver, LPCSTR attribut
 
     case ODBC_REMOVE_DSN: {
       const std::string& dsn = config.Get(FlightSqlConnection::DSN);
-      if (!SQLValidDSN(dsn.c_str()) || !UnregisterDsn(dsn)) return FALSE;
+      auto wdsn_result = arrow::util::UTF8ToWideString(dsn);
+      if (!wdsn_result.status().ok()) {
+        PostArrowUtilError(wdsn_result.status());
+        return FALSE;
+      }
+      std::wstring wdsn = wdsn_result.ValueOrDie();
+      if (!SQLValidDSN(wdsn.c_str()) || !UnregisterDsn(wdsn)) return FALSE;
 
       break;
     }
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc
index 673be40fb1..d7d2e72b4b 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.cc
@@ -15,6 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
+
 #include "arrow/flight/sql/odbc/odbc_impl/system_trust_store.h"
 
 #if defined _WIN32 || defined _WIN64
@@ -28,13 +31,13 @@ bool SystemTrustStore::HasNext() {
 
 std::string SystemTrustStore::GetNext() const {
   DWORD size = 0;
-  CryptBinaryToString(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
-                      CRYPT_STRING_BASE64HEADER, nullptr, &size);
+  CryptBinaryToStringA(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
+                       CRYPT_STRING_BASE64HEADER, nullptr, &size);
 
   std::string cert;
   cert.resize(size);
-  CryptBinaryToString(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
-                      CRYPT_STRING_BASE64HEADER, &cert[0], &size);
+  CryptBinaryToStringA(p_context_->pbCertEncoded, p_context_->cbCertEncoded,
+                       CRYPT_STRING_BASE64HEADER, &cert[0], &size);
   cert.resize(size);
 
   return cert;
@@ -42,7 +45,7 @@ std::string SystemTrustStore::GetNext() const {
 
 bool SystemTrustStore::SystemHasStore() { return h_store_ != nullptr; }
 
-SystemTrustStore::SystemTrustStore(const char* store)
+SystemTrustStore::SystemTrustStore(const wchar_t* store)
     : stores_(store), h_store_(CertOpenSystemStore(NULL, store)), 
p_context_(nullptr) {}
 
 SystemTrustStore::~SystemTrustStore() {
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h
index 52bdaf628e..94ad924aaa 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/system_trust_store.h
@@ -37,12 +37,12 @@ namespace arrow::flight::sql::odbc {
 /// 
https://github.com/apache/drill/blob/master/contrib/native/client/src/clientlib/wincert.ipp.
 class SystemTrustStore {
  private:
-  const char* stores_;
+  const wchar_t* stores_;
   HCERTSTORE h_store_;
   PCCERT_CONTEXT p_context_;
 
  public:
-  explicit SystemTrustStore(const char* store);
+  explicit SystemTrustStore(const wchar_t* store);
 
   ~SystemTrustStore();
 
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc
index 0bf4b7d2a0..634fd77862 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.cc
@@ -32,7 +32,7 @@ namespace arrow::flight::sql::odbc {
 namespace config {
 
 AddPropertyWindow::AddPropertyWindow(Window* parent)
-    : CustomWindow(parent, "AddProperty", "Add Property"),
+    : CustomWindow(parent, L"AddProperty", L"Add Property"),
       width_(300),
       height_(120),
       accepted_(false),
@@ -70,7 +70,7 @@ void AddPropertyWindow::Create() {
   }
 }
 
-bool AddPropertyWindow::GetProperty(std::string& key, std::string& value) {
+bool AddPropertyWindow::GetProperty(std::wstring& key, std::wstring& value) {
   if (accepted_) {
     key = this->key_;
     value = this->value_;
@@ -88,10 +88,10 @@ void AddPropertyWindow::OnCreate() {
   int cancel_pos_x = width_ - MARGIN - BUTTON_WIDTH;
   int ok_pos_x = cancel_pos_x - INTERVAL - BUTTON_WIDTH;
 
-  ok_button_ = CreateButton(ok_pos_x, group_pos_y, BUTTON_WIDTH, 
BUTTON_HEIGHT, "Ok",
+  ok_button_ = CreateButton(ok_pos_x, group_pos_y, BUTTON_WIDTH, 
BUTTON_HEIGHT, L"Ok",
                             ChildId::OK_BUTTON, BS_DEFPUSHBUTTON);
   cancel_button_ = CreateButton(cancel_pos_x, group_pos_y, BUTTON_WIDTH, 
BUTTON_HEIGHT,
-                                "Cancel", ChildId::CANCEL_BUTTON);
+                                L"Cancel", ChildId::CANCEL_BUTTON);
   is_initialized_ = true;
   CheckEnableOk();
 }
@@ -105,16 +105,16 @@ int AddPropertyWindow::CreateEdits(int pos_x, int pos_y, 
int size_x) {
   int row_pos = pos_y;
 
   labels_.push_back(
-      CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT, "Key:", 
ChildId::KEY_LABEL));
+      CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT, L"Key:", 
ChildId::KEY_LABEL));
   key_edit_ =
-      CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, "", 
ChildId::KEY_EDIT);
+      CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, L"", 
ChildId::KEY_EDIT);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
-  labels_.push_back(CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Value:", ChildId::VALUE_LABEL));
+  labels_.push_back(CreateLabel(pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT, 
L"Value:",
+                                ChildId::VALUE_LABEL));
   value_edit_ =
-      CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, "", 
ChildId::VALUE_EDIT);
+      CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, L"", 
ChildId::VALUE_EDIT);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h
index 0aad617c29..e334fd2f90 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/add_property_window.h
@@ -69,7 +69,7 @@ class AddPropertyWindow : public CustomWindow {
    *
    * @return true if the dialog was OK'd, false otherwise.
    */
-  bool GetProperty(std::string& key, std::string& value);
+  bool GetProperty(std::wstring& key, std::wstring& value);
 
  private:
   /**
@@ -96,9 +96,9 @@ class AddPropertyWindow : public CustomWindow {
 
   std::unique_ptr<Window> value_edit_;
 
-  std::string key_;
+  std::wstring key_;
 
-  std::string value_;
+  std::wstring value_;
 
   /** Window width. */
   int width_;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc
index 4571398104..9aded323d0 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.cc
@@ -82,7 +82,8 @@ LRESULT CALLBACK CustomWindow::WndProc(HWND hwnd, UINT msg, 
WPARAM wparam,
   return DefWindowProc(hwnd, msg, wparam, lparam);
 }
 
-CustomWindow::CustomWindow(Window* parent, const char* class_name, const char* 
title)
+CustomWindow::CustomWindow(Window* parent, const wchar_t* class_name,
+                           const wchar_t* title)
     : Window(parent, class_name, title) {
   WNDCLASS wcx;
 
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h
index 93b72d5a94..a658001148 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/custom_window.h
@@ -64,7 +64,7 @@ class CustomWindow : public Window {
    * @param class_name Window class name.
    * @param title Window title.
    */
-  CustomWindow(Window* parent, const char* class_name, const char* title);
+  CustomWindow(Window* parent, const wchar_t* class_name, const wchar_t* 
title);
 
   /**
    * Destructor.
diff --git 
a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc
index 81af697667..3f49690daa 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.cc
@@ -15,6 +15,9 @@
 // specific language governing permissions and limitations
 // under the License.
 
+#include "arrow/result.h"
+#include "arrow/util/utf8.h"
+
 #include "arrow/flight/sql/odbc/odbc_impl/ui/dsn_configuration_window.h"
 
 #include "arrow/flight/sql/odbc/odbc_impl/flight_sql_connection.h"
@@ -54,7 +57,7 @@ std::string TestConnection(const config::Configuration& 
config) {
 namespace config {
 
 DsnConfigurationWindow::DsnConfigurationWindow(Window* parent, Configuration& 
config)
-    : CustomWindow(parent, "FlightConfigureDSN", "Configure Apache Arrow 
Flight SQL"),
+    : CustomWindow(parent, L"FlightConfigureDSN", L"Configure Apache Arrow 
Flight SQL"),
       width_(480),
       height_(375),
       config_(config),
@@ -95,8 +98,8 @@ void DsnConfigurationWindow::Create() {
 
 void DsnConfigurationWindow::OnCreate() {
   tab_control_ = CreateTabControl(ChildId::TAB_CONTROL);
-  tab_control_->AddTab("Common", COMMON_TAB);
-  tab_control_->AddTab("Advanced", ADVANCED_TAB);
+  tab_control_->AddTab(L"Common", COMMON_TAB);
+  tab_control_->AddTab(L"Advanced", ADVANCED_TAB);
 
   int group_pos_y = 3 * MARGIN;
   int group_size_y = width_ - 2 * MARGIN;
@@ -119,11 +122,11 @@ void DsnConfigurationWindow::OnCreate() {
 
   int button_pos_y = std::max(common_group_pos_y, advanced_group_pos_y);
   test_button_ = CreateButton(test_pos_x, button_pos_y, BUTTON_WIDTH + 20, 
BUTTON_HEIGHT,
-                              "Test Connection", 
ChildId::TEST_CONNECTION_BUTTON);
-  ok_button_ = CreateButton(ok_pos_x, button_pos_y, BUTTON_WIDTH, 
BUTTON_HEIGHT, "Ok",
+                              L"Test Connection", 
ChildId::TEST_CONNECTION_BUTTON);
+  ok_button_ = CreateButton(ok_pos_x, button_pos_y, BUTTON_WIDTH, 
BUTTON_HEIGHT, L"Ok",
                             ChildId::OK_BUTTON);
   cancel_button_ = CreateButton(cancel_pos_x, button_pos_y, BUTTON_WIDTH, 
BUTTON_HEIGHT,
-                                "Cancel", ChildId::CANCEL_BUTTON);
+                                L"Cancel", ChildId::CANCEL_BUTTON);
   is_initialized_ = true;
   CheckEnableOk();
   SelectTab(COMMON_TAB);
@@ -140,32 +143,35 @@ int 
DsnConfigurationWindow::CreateConnectionSettingsGroup(int pos_x, int pos_y,
 
   int row_pos = pos_y + 2 * INTERVAL;
 
-  const char* val = config_.Get(FlightSqlConnection::DSN).c_str();
+  std::string dsn = config_.Get(FlightSqlConnection::DSN);
+  CONVERT_WIDE_STR(const std::wstring wdsn, dsn);
   labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Data Source Name:", ChildId::NAME_LABEL));
-  name_edit_ =
-      CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val, 
ChildId::NAME_EDIT);
+                                L"Data Source Name:", ChildId::NAME_LABEL));
+  name_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, 
wdsn.c_str(),
+                          ChildId::NAME_EDIT);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
-  val = config_.Get(FlightSqlConnection::HOST).c_str();
+  std::string host = config_.Get(FlightSqlConnection::HOST);
+  CONVERT_WIDE_STR(const std::wstring whost, host);
   labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Host Name:", ChildId::SERVER_LABEL));
-  server_edit_ =
-      CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val, 
ChildId::SERVER_EDIT);
+                                L"Host Name:", ChildId::SERVER_LABEL));
+  server_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, 
whost.c_str(),
+                            ChildId::SERVER_EDIT);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
-  val = config_.Get(FlightSqlConnection::PORT).c_str();
-  labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Port:", ChildId::PORT_LABEL));
-  port_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val,
+  std::string port = config_.Get(FlightSqlConnection::PORT);
+  CONVERT_WIDE_STR(const std::wstring wport, port);
+  labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT, 
L"Port:",
+                                ChildId::PORT_LABEL));
+  port_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, 
wport.c_str(),
                           ChildId::PORT_EDIT, ES_NUMBER);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
   connection_settings_group_box_ =
-      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Connection 
settings",
+      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Connection 
settings",
                      ChildId::CONNECTION_SETTINGS_GROUP_BOX);
 
   return row_pos - pos_y;
@@ -182,38 +188,40 @@ int DsnConfigurationWindow::CreateAuthSettingsGroup(int 
pos_x, int pos_y, int si
   int row_pos = pos_y + 2 * INTERVAL;
 
   labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Authentication Type:", 
ChildId::AUTH_TYPE_LABEL));
+                                L"Authentication Type:", 
ChildId::AUTH_TYPE_LABEL));
   auth_type_combo_box_ =
       CreateComboBox(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
-                     "Authentication Type:", ChildId::AUTH_TYPE_COMBOBOX);
-  auth_type_combo_box_->AddString("Basic Authentication");
-  auth_type_combo_box_->AddString("Token Authentication");
+                     L"Authentication Type:", ChildId::AUTH_TYPE_COMBOBOX);
+  auth_type_combo_box_->AddString(L"Basic Authentication");
+  auth_type_combo_box_->AddString(L"Token Authentication");
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
-  const char* val = config_.Get(FlightSqlConnection::UID).c_str();
+  std::string uid = config_.Get(FlightSqlConnection::UID);
+  CONVERT_WIDE_STR(const std::wstring wuid, uid);
 
-  labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "User:", ChildId::USER_LABEL));
-  user_edit_ =
-      CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, val, 
ChildId::USER_EDIT);
+  labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT, 
L"User:",
+                                ChildId::USER_LABEL));
+  user_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, 
wuid.c_str(),
+                          ChildId::USER_EDIT);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
-  val = config_.Get(FlightSqlConnection::PWD).c_str();
+  std::string pwd = config_.Get(FlightSqlConnection::PWD);
+  CONVERT_WIDE_STR(const std::wstring wpwd, pwd);
   labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Password:", ChildId::PASSWORD_LABEL));
-  password_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, 
val,
+                                L"Password:", ChildId::PASSWORD_LABEL));
+  password_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, 
wpwd.c_str(),
                               ChildId::USER_EDIT, ES_PASSWORD);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
   const auto& token = config_.Get(FlightSqlConnection::TOKEN);
-  val = token.c_str();
+  CONVERT_WIDE_STR(const std::wstring wtoken, token);
   labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Authentication Token:", 
ChildId::AUTH_TOKEN_LABEL));
-  auth_token_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT, 
val,
-                                ChildId::AUTH_TOKEN_EDIT);
+                                L"Authentication Token:", 
ChildId::AUTH_TOKEN_LABEL));
+  auth_token_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x, ROW_HEIGHT,
+                                wtoken.c_str(), ChildId::AUTH_TOKEN_EDIT);
   auth_token_edit_->SetEnabled(false);
 
   // Ensure the right elements are selected.
@@ -223,7 +231,7 @@ int DsnConfigurationWindow::CreateAuthSettingsGroup(int 
pos_x, int pos_y, int si
   row_pos += INTERVAL + ROW_HEIGHT;
 
   auth_settings_group_box_ =
-      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Authentication 
settings",
+      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Authentication 
settings",
                      ChildId::AUTH_SETTINGS_GROUP_BOX);
 
   return row_pos - pos_y;
@@ -240,37 +248,39 @@ int 
DsnConfigurationWindow::CreateEncryptionSettingsGroup(int pos_x, int pos_y,
 
   int row_pos = pos_y + 2 * INTERVAL;
 
-  const char* val = config_.Get(FlightSqlConnection::USE_ENCRYPTION).c_str();
+  std::string val = config_.Get(FlightSqlConnection::USE_ENCRYPTION);
 
   const bool enable_encryption = util::AsBool(val).value_or(true);
   labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Use Encryption:", 
ChildId::ENABLE_ENCRYPTION_LABEL));
+                                L"Use Encryption:", 
ChildId::ENABLE_ENCRYPTION_LABEL));
   enable_encryption_check_box_ =
-      CreateCheckBox(edit_pos_x, row_pos - 2, edit_size_x, ROW_HEIGHT, "",
+      CreateCheckBox(edit_pos_x, row_pos - 2, edit_size_x, ROW_HEIGHT, L"",
                      ChildId::ENABLE_ENCRYPTION_CHECKBOX, enable_encryption);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
-  val = config_.Get(FlightSqlConnection::TRUSTED_CERTS).c_str();
+  std::string trusted_certs = config_.Get(FlightSqlConnection::TRUSTED_CERTS);
+  CONVERT_WIDE_STR(const std::wstring wtrusted_certs, trusted_certs);
 
   labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, ROW_HEIGHT,
-                                "Certificate:", ChildId::CERTIFICATE_LABEL));
-  certificate_edit_ = CreateEdit(edit_pos_x, row_pos, edit_size_x - MARGIN - 
BUTTON_WIDTH,
-                                 ROW_HEIGHT, val, ChildId::CERTIFICATE_EDIT);
+                                L"Certificate:", ChildId::CERTIFICATE_LABEL));
+  certificate_edit_ =
+      CreateEdit(edit_pos_x, row_pos, edit_size_x - MARGIN - BUTTON_WIDTH, 
ROW_HEIGHT,
+                 wtrusted_certs.c_str(), ChildId::CERTIFICATE_EDIT);
   certificate_browse_button_ =
       CreateButton(edit_pos_x + edit_size_x - BUTTON_WIDTH, row_pos - 2, 
BUTTON_WIDTH,
-                   BUTTON_HEIGHT, "Browse", 
ChildId::CERTIFICATE_BROWSE_BUTTON);
+                   BUTTON_HEIGHT, L"Browse", 
ChildId::CERTIFICATE_BROWSE_BUTTON);
 
   row_pos += INTERVAL + ROW_HEIGHT;
 
   val = config_.Get(FlightSqlConnection::USE_SYSTEM_TRUST_STORE).c_str();
 
   const bool use_system_cert_store = util::AsBool(val).value_or(true);
-  labels_.push_back(
-      CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, 2 * ROW_HEIGHT,
-                  "Use System Certificate Store:", 
ChildId::USE_SYSTEM_CERT_STORE_LABEL));
+  labels_.push_back(CreateLabel(label_pos_x, row_pos, LABEL_WIDTH, 2 * 
ROW_HEIGHT,
+                                L"Use System Certificate Store:",
+                                ChildId::USE_SYSTEM_CERT_STORE_LABEL));
   use_system_cert_store_check_box_ =
-      CreateCheckBox(edit_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, "",
+      CreateCheckBox(edit_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, L"",
                      ChildId::USE_SYSTEM_CERT_STORE_CHECKBOX, 
use_system_cert_store);
 
   val = 
config_.Get(FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION).c_str();
@@ -278,19 +288,24 @@ int 
DsnConfigurationWindow::CreateEncryptionSettingsGroup(int pos_x, int pos_y,
   const int right_pos_x = label_pos_x + (size_x - (2 * INTERVAL)) / 2;
   const int right_check_pos_x = right_pos_x + (edit_pos_x - label_pos_x);
   const bool disable_cert_verification = util::AsBool(val).value_or(false);
-  labels_.push_back(CreateLabel(
-      right_pos_x, row_pos, LABEL_WIDTH, 2 * ROW_HEIGHT,
-      "Disable Certificate Verification:", 
ChildId::DISABLE_CERT_VERIFICATION_LABEL));
+  labels_.push_back(CreateLabel(right_pos_x, row_pos, LABEL_WIDTH, 2 * 
ROW_HEIGHT,
+                                L"Disable Certificate Verification:",
+                                ChildId::DISABLE_CERT_VERIFICATION_LABEL));
   disable_cert_verification_check_box_ = CreateCheckBox(
-      right_check_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, "",
+      right_check_pos_x, row_pos - 2, 20, 2 * ROW_HEIGHT, L"",
       ChildId::DISABLE_CERT_VERIFICATION_CHECKBOX, disable_cert_verification);
 
   row_pos += INTERVAL + static_cast<int>(1.5 * static_cast<int>(ROW_HEIGHT));
 
   encryption_settings_group_box_ =
-      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Encryption 
settings",
+      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Encryption 
settings",
                      ChildId::AUTH_SETTINGS_GROUP_BOX);
 
+  certificate_edit_->SetEnabled(enable_encryption);
+  certificate_browse_button_->SetEnabled(enable_encryption);
+  use_system_cert_store_check_box_->SetEnabled(enable_encryption);
+  disable_cert_verification_check_box_->SetEnabled(enable_encryption);
+
   return row_pos - pos_y;
 }
 
@@ -306,12 +321,15 @@ int DsnConfigurationWindow::CreatePropertiesGroup(int 
pos_x, int pos_y, int size
 
   property_list_ =
       CreateList(label_pos_x, row_pos, list_size, list_height, 
ChildId::PROPERTY_LIST);
-  property_list_->ListAddColumn("Key", 0, column_size);
-  property_list_->ListAddColumn("Value", 1, column_size);
+  property_list_->ListAddColumn(L"Key", 0, column_size);
+  property_list_->ListAddColumn(L"Value", 1, column_size);
 
   const auto keys = config_.GetCustomKeys();
   for (const auto& key : keys) {
-    property_list_->ListAddItem({std::string(key), config_.Get(key)});
+    CONVERT_WIDE_STR(const std::wstring wkey, key);
+    CONVERT_WIDE_STR(const std::wstring wval, config_.Get(key));
+
+    property_list_->ListAddItem({wkey, wval});
   }
 
   SendMessage(property_list_->GetHandle(), LVM_SETEXTENDEDLISTVIEWSTYLE,
@@ -321,15 +339,15 @@ int DsnConfigurationWindow::CreatePropertiesGroup(int 
pos_x, int pos_y, int size
 
   int delete_pos_x = width_ - INTERVAL - MARGIN - BUTTON_WIDTH;
   int add_pos_x = delete_pos_x - INTERVAL - BUTTON_WIDTH;
-  add_button_ = CreateButton(add_pos_x, row_pos, BUTTON_WIDTH, BUTTON_HEIGHT, 
"Add",
+  add_button_ = CreateButton(add_pos_x, row_pos, BUTTON_WIDTH, BUTTON_HEIGHT, 
L"Add",
                              ChildId::ADD_BUTTON);
   delete_button_ = CreateButton(delete_pos_x, row_pos, BUTTON_WIDTH, 
BUTTON_HEIGHT,
-                                "Delete", ChildId::DELETE_BUTTON);
+                                L"Delete", ChildId::DELETE_BUTTON);
 
   row_pos += INTERVAL + BUTTON_HEIGHT;
 
   property_group_box_ =
-      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, "Advanced 
properties",
+      CreateGroupBox(pos_x, pos_y, size_x, row_pos - pos_y, L"Advanced 
properties",
                      ChildId::PROPERTY_GROUP_BOX);
 
   return row_pos - pos_y;
@@ -390,7 +408,7 @@ void DsnConfigurationWindow::CheckEnableOk() {
 void DsnConfigurationWindow::SaveParameters(Configuration& target_config) {
   target_config.Clear();
 
-  std::string text;
+  std::wstring text;
   name_edit_->GetText(text);
   target_config.Set(FlightSqlConnection::DSN, text);
   server_edit_->GetText(text);
@@ -429,13 +447,17 @@ void 
DsnConfigurationWindow::SaveParameters(Configuration& target_config) {
         FlightSqlConnection::DISABLE_CERTIFICATE_VERIFICATION,
         disable_cert_verification_check_box_->IsChecked() ? TRUE_STR : 
FALSE_STR);
   } else {
+    // System trust store verification requires encryption
     target_config.Set(FlightSqlConnection::USE_ENCRYPTION, FALSE_STR);
+    target_config.Set(FlightSqlConnection::USE_SYSTEM_TRUST_STORE, FALSE_STR);
   }
 
   // Get all the list properties.
   const auto properties = property_list_->ListGetAll();
   for (const auto& property : properties) {
-    target_config.Set(property[0], property[1]);
+    std::string property_key = 
arrow::util::WideStringToUTF8(property[0]).ValueOr("");
+    std::string property_value = 
arrow::util::WideStringToUTF8(property[1]).ValueOr("");
+    target_config.Set(property_key, property_value);
   }
 }
 
@@ -471,9 +493,14 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM 
wparam, LPARAM lparam) {
             SaveParameters(test_config);
             std::string test_message = TestConnection(test_config);
 
-            MessageBox(NULL, test_message.c_str(), "Test Connection Success", 
MB_OK);
+            CONVERT_WIDE_STR(const std::wstring w_test_message, test_message);
+
+            MessageBox(NULL, w_test_message.c_str(), L"Test Connection 
Success", MB_OK);
           } catch (DriverException& err) {
-            MessageBox(NULL, err.GetMessageText().c_str(), "Error!",
+            const std::wstring w_message_text =
+                arrow::util::UTF8ToWideString(err.GetMessageText())
+                    .ValueOr(L"Test failed");
+            MessageBox(NULL, w_message_text.c_str(), L"Error!",
                        MB_ICONEXCLAMATION | MB_OK);
           }
 
@@ -485,7 +512,10 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM 
wparam, LPARAM lparam) {
             accepted_ = true;
             PostMessage(GetHandle(), WM_CLOSE, 0, 0);
           } catch (DriverException& err) {
-            MessageBox(NULL, err.GetMessageText().c_str(), "Error!",
+            const std::wstring w_message_text =
+                arrow::util::UTF8ToWideString(err.GetMessageText())
+                    .ValueOr(L"Error when saving DSN");
+            MessageBox(NULL, w_message_text.c_str(), L"Error!",
                        MB_ICONEXCLAMATION | MB_OK);
           }
 
@@ -528,7 +558,7 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM 
wparam, LPARAM lparam) {
 
         case ChildId::CERTIFICATE_BROWSE_BUTTON: {
           OPENFILENAME open_file_name;
-          char file_name[FILENAME_MAX];
+          wchar_t file_name[FILENAME_MAX];
 
           ZeroMemory(&open_file_name, sizeof(open_file_name));
           open_file_name.lStructSize = sizeof(open_file_name);
@@ -537,7 +567,7 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM 
wparam, LPARAM lparam) {
           open_file_name.lpstrFile[0] = '\0';
           open_file_name.nMaxFile = FILENAME_MAX;
           // TODO: What type should this be?
-          open_file_name.lpstrFilter = "All\0*.*";
+          open_file_name.lpstrFilter = L"All\0*.*";
           open_file_name.nFilterIndex = 1;
           open_file_name.lpstrFileTitle = NULL;
           open_file_name.nMaxFileTitle = 0;
@@ -574,8 +604,8 @@ bool DsnConfigurationWindow::OnMessage(UINT msg, WPARAM 
wparam, LPARAM lparam) {
           add_window.Update();
 
           if (ProcessMessages(add_window) == Result::OK) {
-            std::string key;
-            std::string value;
+            std::wstring key;
+            std::wstring value;
             add_window.GetProperty(key, value);
             property_list_->ListAddItem({key, value});
           }
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc
index e31887521b..f21329977b 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.cc
@@ -48,7 +48,7 @@ HINSTANCE GetHInstance() {
   return h_instance;
 }
 
-Window::Window(Window* parent, const char* class_name, const char* title)
+Window::Window(Window* parent, const wchar_t* class_name, const wchar_t* title)
     : class_name_(class_name),
       title_(title),
       handle_(NULL),
@@ -91,7 +91,7 @@ void Window::Create(DWORD style, int pos_x, int pos_y, int 
width, int height, in
 }
 
 std::unique_ptr<Window> Window::CreateTabControl(int id) {
-  std::unique_ptr<Window> child(new Window(this, WC_TABCONTROL, ""));
+  std::unique_ptr<Window> child(new Window(this, WC_TABCONTROL, L""));
 
   // Get the dimensions of the parent window's client area, and
   // create a tab control child window of that size.
@@ -106,7 +106,7 @@ std::unique_ptr<Window> Window::CreateTabControl(int id) {
 
 std::unique_ptr<Window> Window::CreateList(int pos_x, int pos_y, int size_x, 
int size_y,
                                            int id) {
-  std::unique_ptr<Window> child(new Window(this, WC_LISTVIEW, ""));
+  std::unique_ptr<Window> child(new Window(this, WC_LISTVIEW, L""));
 
   child->Create(
       WS_CHILD | WS_VISIBLE | WS_BORDER | LVS_REPORT | LVS_EDITLABELS | 
WS_TABSTOP, pos_x,
@@ -116,8 +116,8 @@ std::unique_ptr<Window> Window::CreateList(int pos_x, int 
pos_y, int size_x, int
 }
 
 std::unique_ptr<Window> Window::CreateGroupBox(int pos_x, int pos_y, int 
size_x,
-                                               int size_y, const char* title, 
int id) {
-  std::unique_ptr<Window> child(new Window(this, "Button", title));
+                                               int size_y, const wchar_t* 
title, int id) {
+  std::unique_ptr<Window> child(new Window(this, L"Button", title));
 
   child->Create(WS_CHILD | WS_VISIBLE | BS_GROUPBOX, pos_x, pos_y, size_x, 
size_y, id);
 
@@ -125,8 +125,8 @@ std::unique_ptr<Window> Window::CreateGroupBox(int pos_x, 
int pos_y, int size_x,
 }
 
 std::unique_ptr<Window> Window::CreateLabel(int pos_x, int pos_y, int size_x, 
int size_y,
-                                            const char* title, int id) {
-  std::unique_ptr<Window> child(new Window(this, "Static", title));
+                                            const wchar_t* title, int id) {
+  std::unique_ptr<Window> child(new Window(this, L"Static", title));
 
   child->Create(WS_CHILD | WS_VISIBLE, pos_x, pos_y, size_x, size_y, id);
 
@@ -134,8 +134,8 @@ std::unique_ptr<Window> Window::CreateLabel(int pos_x, int 
pos_y, int size_x, in
 }
 
 std::unique_ptr<Window> Window::CreateEdit(int pos_x, int pos_y, int size_x, 
int size_y,
-                                           const char* title, int id, int 
style) {
-  std::unique_ptr<Window> child(new Window(this, "Edit", title));
+                                           const wchar_t* title, int id, int 
style) {
+  std::unique_ptr<Window> child(new Window(this, L"Edit", title));
 
   child->Create(WS_CHILD | WS_VISIBLE | WS_BORDER | ES_AUTOHSCROLL | 
WS_TABSTOP | style,
                 pos_x, pos_y, size_x, size_y, id);
@@ -144,8 +144,8 @@ std::unique_ptr<Window> Window::CreateEdit(int pos_x, int 
pos_y, int size_x, int
 }
 
 std::unique_ptr<Window> Window::CreateButton(int pos_x, int pos_y, int size_x, 
int size_y,
-                                             const char* title, int id, int 
style) {
-  std::unique_ptr<Window> child(new Window(this, "Button", title));
+                                             const wchar_t* title, int id, int 
style) {
+  std::unique_ptr<Window> child(new Window(this, L"Button", title));
 
   child->Create(WS_CHILD | WS_VISIBLE | WS_TABSTOP | style, pos_x, pos_y, 
size_x, size_y,
                 id);
@@ -154,9 +154,9 @@ std::unique_ptr<Window> Window::CreateButton(int pos_x, int 
pos_y, int size_x, i
 }
 
 std::unique_ptr<Window> Window::CreateCheckBox(int pos_x, int pos_y, int 
size_x,
-                                               int size_y, const char* title, 
int id,
+                                               int size_y, const wchar_t* 
title, int id,
                                                bool state) {
-  std::unique_ptr<Window> child(new Window(this, "Button", title));
+  std::unique_ptr<Window> child(new Window(this, L"Button", title));
 
   child->Create(WS_CHILD | WS_VISIBLE | BS_CHECKBOX | WS_TABSTOP, pos_x, 
pos_y, size_x,
                 size_y, id);
@@ -167,8 +167,8 @@ std::unique_ptr<Window> Window::CreateCheckBox(int pos_x, 
int pos_y, int size_x,
 }
 
 std::unique_ptr<Window> Window::CreateComboBox(int pos_x, int pos_y, int 
size_x,
-                                               int size_y, const char* title, 
int id) {
-  std::unique_ptr<Window> child(new Window(this, "Combobox", title));
+                                               int size_y, const wchar_t* 
title, int id) {
+  std::unique_ptr<Window> child(new Window(this, L"Combobox", title));
 
   child->Create(WS_CHILD | WS_VISIBLE | CBS_DROPDOWNLIST | WS_TABSTOP, pos_x, 
pos_y,
                 size_x, size_y, id);
@@ -199,12 +199,12 @@ bool Window::IsTextEmpty() const {
   return (len <= 0);
 }
 
-void Window::ListAddColumn(const std::string& name, int index, int width) {
+void Window::ListAddColumn(const std::wstring& name, int index, int width) {
   LVCOLUMN lvc;
   lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
   lvc.fmt = LVCFMT_LEFT;
   lvc.cx = width;
-  lvc.pszText = const_cast<char*>(name.c_str());
+  lvc.pszText = const_cast<wchar_t*>(name.c_str());
   lvc.iSubItem = index;
 
   if (ListView_InsertColumn(handle_, index, &lvc) == -1) {
@@ -214,10 +214,10 @@ void Window::ListAddColumn(const std::string& name, int 
index, int width) {
   }
 }
 
-void Window::ListAddItem(const std::vector<std::string>& items) {
+void Window::ListAddItem(const std::vector<std::wstring>& items) {
   LVITEM lvi = {0};
   lvi.mask = LVIF_TEXT;
-  lvi.pszText = const_cast<char*>(items[0].c_str());
+  lvi.pszText = const_cast<wchar_t*>(items[0].c_str());
 
   int ret = ListView_InsertItem(handle_, &lvi);
   if (ret < 0) {
@@ -228,7 +228,7 @@ void Window::ListAddItem(const std::vector<std::string>& 
items) {
 
   for (size_t i = 1; i < items.size(); ++i) {
     ListView_SetItemText(handle_, ret, static_cast<int>(i),
-                         const_cast<char*>(items[i].c_str()));
+                         const_cast<wchar_t*>(items[i].c_str()));
   }
 }
 
@@ -243,15 +243,15 @@ void Window::ListDeleteSelectedItem() {
   }
 }
 
-std::vector<std::vector<std::string> > Window::ListGetAll() {
+std::vector<std::vector<std::wstring> > Window::ListGetAll() {
 #define BUF_LEN 1024
-  char buf[BUF_LEN];
+  wchar_t buf[BUF_LEN];
 
-  std::vector<std::vector<std::string> > values;
+  std::vector<std::vector<std::wstring> > values;
   const int num_columns = Header_GetItemCount(ListView_GetHeader(handle_));
   const int num_items = ListView_GetItemCount(handle_);
   for (int i = 0; i < num_items; ++i) {
-    std::vector<std::string> row;
+    std::vector<std::wstring> row;
     for (int j = 0; j < num_columns; ++j) {
       ListView_GetItemText(handle_, i, j, buf, BUF_LEN);
       row.emplace_back(buf);
@@ -262,11 +262,11 @@ std::vector<std::vector<std::string> > 
Window::ListGetAll() {
   return values;
 }
 
-void Window::AddTab(const std::string& name, int index) {
+void Window::AddTab(const std::wstring& name, int index) {
   TCITEM tab_control_item;
   tab_control_item.mask = TCIF_TEXT | TCIF_IMAGE;
   tab_control_item.iImage = -1;
-  tab_control_item.pszText = const_cast<char*>(name.c_str());
+  tab_control_item.pszText = const_cast<wchar_t*>(name.c_str());
   if (TabCtrl_InsertItem(handle_, index, &tab_control_item) == -1) {
     std::stringstream buf;
     buf << "Can not add tab, error code: " << GetLastError();
@@ -274,7 +274,7 @@ void Window::AddTab(const std::string& name, int index) {
   }
 }
 
-void Window::GetText(std::string& text) const {
+void Window::GetText(std::wstring& text) const {
   if (!IsEnabled()) {
     text.clear();
 
@@ -297,7 +297,7 @@ void Window::GetText(std::string& text) const {
   boost::algorithm::trim(text);
 }
 
-void Window::SetText(const std::string& text) const {
+void Window::SetText(const std::wstring& text) const {
   SNDMSG(handle_, WM_SETTEXT, 0, reinterpret_cast<LPARAM>(text.c_str()));
 }
 
@@ -309,7 +309,7 @@ void Window::SetChecked(bool state) {
   Button_SetCheck(handle_, state ? BST_CHECKED : BST_UNCHECKED);
 }
 
-void Window::AddString(const std::string& str) {
+void Window::AddString(const std::wstring& str) {
   SNDMSG(handle_, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str.c_str()));
 }
 
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h
index 0ca7ba329c..b8aa438d9a 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/ui/window.h
@@ -43,7 +43,7 @@ class Window {
    * @param class_name Window class name.
    * @param title Window title.
    */
-  Window(Window* parent, const char* class_name, const char* title);
+  Window(Window* parent, const wchar_t* class_name, const wchar_t* title);
 
   /**
    * Constructor for the existing window.
@@ -102,7 +102,7 @@ class Window {
    * @return Auto pointer containing new window.
    */
   std::unique_ptr<Window> CreateGroupBox(int pos_x, int pos_y, int size_x, int 
size_y,
-                                         const char* title, int id);
+                                         const wchar_t* title, int id);
 
   /**
    * Create child label window.
@@ -116,7 +116,7 @@ class Window {
    * @return Auto pointer containing new window.
    */
   std::unique_ptr<Window> CreateLabel(int pos_x, int pos_y, int size_x, int 
size_y,
-                                      const char* title, int id);
+                                      const wchar_t* title, int id);
 
   /**
    * Create child Edit window.
@@ -131,7 +131,7 @@ class Window {
    * @return Auto pointer containing new window.
    */
   std::unique_ptr<Window> CreateEdit(int pos_x, int pos_y, int size_x, int 
size_y,
-                                     const char* title, int id, int style = 0);
+                                     const wchar_t* title, int id, int style = 
0);
 
   /**
    * Create child button window.
@@ -146,7 +146,7 @@ class Window {
    * @return Auto pointer containing new window.
    */
   std::unique_ptr<Window> CreateButton(int pos_x, int pos_y, int size_x, int 
size_y,
-                                       const char* title, int id, int style = 
0);
+                                       const wchar_t* title, int id, int style 
= 0);
 
   /**
    * Create child CheckBox window.
@@ -161,7 +161,7 @@ class Window {
    * @return Auto pointer containing new window.
    */
   std::unique_ptr<Window> CreateCheckBox(int pos_x, int pos_y, int size_x, int 
size_y,
-                                         const char* title, int id, bool 
state);
+                                         const wchar_t* title, int id, bool 
state);
 
   /**
    * Create child ComboBox window.
@@ -175,7 +175,7 @@ class Window {
    * @return Auto pointer containing new window.
    */
   std::unique_ptr<Window> CreateComboBox(int pos_x, int pos_y, int size_x, int 
size_y,
-                                         const char* title, int id);
+                                         const wchar_t* title, int id);
 
   /**
    * Show window.
@@ -201,15 +201,15 @@ class Window {
 
   void SetVisible(bool isVisible);
 
-  void ListAddColumn(const std::string& name, int index, int width);
+  void ListAddColumn(const std::wstring& name, int index, int width);
 
-  void ListAddItem(const std::vector<std::string>& items);
+  void ListAddItem(const std::vector<std::wstring>& items);
 
   void ListDeleteSelectedItem();
 
-  std::vector<std::vector<std::string> > ListGetAll();
+  std::vector<std::vector<std::wstring> > ListGetAll();
 
-  void AddTab(const std::string& name, int index);
+  void AddTab(const std::wstring& name, int index);
 
   bool IsTextEmpty() const;
 
@@ -218,14 +218,14 @@ class Window {
    *
    * @param text Text.
    */
-  void GetText(std::string& text) const;
+  void GetText(std::wstring& text) const;
 
   /**
    * Set window text.
    *
    * @param text Text.
    */
-  void SetText(const std::string& text) const;
+  void SetText(const std::wstring& text) const;
 
   /**
    * Get CheckBox state.
@@ -246,7 +246,7 @@ class Window {
    *
    * @param str String.
    */
-  void AddString(const std::string& str);
+  void AddString(const std::wstring& str);
 
   /**
    * Set current ComboBox selection.
@@ -285,10 +285,10 @@ class Window {
   void SetHandle(HWND value) { handle_ = value; }
 
   /** Window class name. */
-  std::string class_name_;
+  std::wstring class_name_;
 
   /** Window title. */
-  std::string title_;
+  std::wstring title_;
 
   /** Window handle. */
   HWND handle_;
diff --git a/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h 
b/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h
index 32c2c90747..8197f741d1 100644
--- a/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h
+++ b/cpp/src/arrow/flight/sql/odbc/odbc_impl/util.h
@@ -17,6 +17,8 @@
 
 #pragma once
 
+#include "arrow/util/utf8.h"
+
 #include "arrow/flight/sql/odbc/odbc_impl/exceptions.h"
 #include "arrow/flight/sql/odbc/odbc_impl/spi/connection.h"
 #include "arrow/flight/sql/odbc/odbc_impl/types.h"
@@ -27,6 +29,20 @@
 #include <functional>
 #include <optional>
 
+#define CONVERT_WIDE_STR(wstring_var, utf8_target)                             
   \
+  wstring_var = [&] {                                                          
   \
+    arrow::Result<std::wstring> res = 
arrow::util::UTF8ToWideString(utf8_target); \
+    arrow::flight::sql::odbc::util::ThrowIfNotOK(res.status());                
   \
+    return res.ValueOrDie();                                                   
   \
+  }()
+
+#define CONVERT_UTF8_STR(string_var, wide_str_target)                          
      \
+  string_var = [&] {                                                           
      \
+    arrow::Result<std::string> res = 
arrow::util::WideStringToUTF8(wide_str_target); \
+    arrow::flight::sql::odbc::util::ThrowIfNotOK(res.status());                
      \
+    return res.ValueOrDie();                                                   
      \
+  }()
+
 namespace arrow::flight::sql::odbc {
 namespace util {
 

Reply via email to