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-adbc.git


The following commit(s) were added to refs/heads/main by this push:
     new 22b954ddb fix(c): Generate versioned DLLs and import LIBs when 
building with MSVC (#2858)
22b954ddb is described below

commit 22b954ddb53267e7a70ca0b6521522ddc2f1f312
Author: Ali Alamiri <[email protected]>
AuthorDate: Fri Dec 26 07:41:25 2025 +0000

    fix(c): Generate versioned DLLs and import LIBs when building with MSVC 
(#2858)
    
    Hi.
    
    This is to address building binaries and LIBs on Windows. The PR is
    mainly for consideration purposes, as it's my first PR against this repo
    so not necessarily a complete one. Following are the changes I needed to
    make:
    - Disable ASAN/UBSAN builds configs as they require GCC/Clang, and on
    Windows we're building with MSVC.
    - An environment variable to `vcpkg` root is expected so that third
    party packages (sqlite, postgres etc) can be installed and found via
    vcpkg.
    - Disable some warnings for testing code that are safe to ignore for
    MSVC builds.
    - Ensure the generated binaries have file level details (Details tab on
    the file properties in Windows) for the version. This is required by
    Windows MSIs that may be used to install the adbc DLLs in order to
    detect if the DLL being installed is a newer or older version.
    - Generate import LIB file for drivers built with go build, which
    includes flight SQL and Snowflake drivers. This allows the testing
    projects referencing those DLLs to built on Windows.
    - The `GoUtils.cmake` is not automatically copying the driver DLLs to
    the location of the test executables, causing the tests for those
    drivers to fail. Added a post build command to ensure the DLLs are
    copied.
    - Fix some type casting mismatch (casting between size_t and int).
    - Fix warnings where a variable is hiding a previous one with the same
    name. Appended `2` to the second variable name.
    
    What I haven't done is update the GitHub actions to verify a complete
    build on a Windows machine as I'm not too familiar with the CI/CD
    pipeline in this repo.
    
    Hopefully this is a good start to get everything building successfully
    and Windows.
    
    Closes #2846
    
    ---------
    
    Co-authored-by: Sutou Kouhei <[email protected]>
    Co-authored-by: David Li <[email protected]>
    Co-authored-by: Bryce Mecum <[email protected]>
---
 .github/workflows/native-windows.yml               |  99 ++++++++++++++++
 c/CMakePresets.json                                |  53 +++++++++
 c/cmake_modules/AdbcDefines.cmake                  |  20 ++++
 c/cmake_modules/BuildUtils.cmake                   |  24 ++++
 c/cmake_modules/DefineOptions.cmake                |   4 +
 c/cmake_modules/GoUtils.cmake                      | 131 ++++++++++++++++-----
 c/driver/flightsql/CMakeLists.txt                  |  12 ++
 .../postgresql/copy/postgres_copy_reader_test.cc   |   4 +-
 c/driver/snowflake/CMakeLists.txt                  |  12 ++
 c/driver/sqlite/sqlite_test.cc                     |   7 +-
 c/driver/sqlite/statement_reader.c                 |   9 ++
 c/driver_manager/CMakeLists.txt                    |   2 +-
 c/driver_manager/adbc_driver_manager.cc            |  14 +--
 c/driver_manager/adbc_driver_manager_test.cc       |  17 ++-
 c/validation/adbc_validation.cc                    |  11 +-
 c/validation/adbc_validation_connection.cc         |   2 +-
 c/validation/adbc_validation_statement.cc          |  28 ++---
 c/validation/adbc_validation_util.h                |   4 +-
 c/version.rc.in                                    |  49 ++++++++
 ci/scripts/cpp_test.ps1                            |   7 +-
 go/adbc/drivermgr/adbc_driver_manager.cc           |  14 +--
 21 files changed, 442 insertions(+), 81 deletions(-)

diff --git a/.github/workflows/native-windows.yml 
b/.github/workflows/native-windows.yml
index b72ace7e7..186b477af 100644
--- a/.github/workflows/native-windows.yml
+++ b/.github/workflows/native-windows.yml
@@ -260,6 +260,49 @@ jobs:
         with:
           fetch-depth: 0
           persist-credentials: false
+      - name: Set Winlibs version
+        id: winlibs-version
+        shell: pwsh
+        run: |
+          $winlibs_asset_name = 
"winlibs-x86_64-posix-seh-gcc-15.2.0-mingw-w64ucrt-13.0.0-r4.7z"
+          echo "winlibs_asset_name=$winlibs_asset_name" >> $env:GITHUB_OUTPUT
+
+      - name: Cache Winlibs
+        id: cache-winlibs
+        uses: actions/cache@v5
+        with:
+          path: ${{ runner.temp }}/winlibs
+          key: winlibs-${{ steps.winlibs-version.outputs.winlibs_asset_name }}
+
+      - name: Download and setup Winlibs
+        if: steps.cache-winlibs.outputs.cache-hit != 'true'
+        shell: pwsh
+        run: |
+          $base_url = 
"https://github.com/brechtsanders/winlibs_mingw/releases/download/15.2.0posix-13.0.0-ucrt-r4/";
+          $asset_name = "${{ steps.winlibs-version.outputs.winlibs_asset_name 
}}"
+          $hash_expected = 
"148175f2ba3c4ab0bfd93116b75f7ff172e9e0d06ca8680c8a98c375ec45abb5"
+          $url = $base_url + $asset_name
+
+          Write-Host "Downloading $asset_name..."
+          Invoke-WebRequest -Uri $url -OutFile $asset_name -UseBasicParsing
+
+          Write-Host "Verifying hash..."
+          $hash_actual = (Get-FileHash -Path $asset_name -Algorithm 
SHA256).Hash.ToLower()
+          if ($hash_actual -ne $hash_expected) {
+            throw "SHA256 mismatch! Expected: $hash_expected, Got: 
$hash_actual"
+          }
+
+          Write-Host "Extracting..."
+          7z x $asset_name -o"${{ runner.temp }}/winlibs" -y
+          Remove-Item $asset_name -Force
+
+      - name: Add Winlibs to PATH
+        shell: pwsh
+        run: |
+          $winlibs_bin = Join-Path "${{ runner.temp }}" "winlibs\mingw64\bin"
+          $env:PATH="$winlibs_bin;${env:PATH}"
+          echo "PATH=$env:PATH" >> $env:GITHUB_ENV
+
       - name: Get Date
         id: get-date
         shell: bash
@@ -273,6 +316,7 @@ jobs:
         with:
           path: ~/conda_pkgs_dir
           key: conda-${{ runner.os }}-${{ steps.get-date.outputs.today }}-${{ 
env.CACHE_NUMBER }}-${{ hashFiles('ci/**') }}
+
       - uses: 
conda-incubator/setup-miniconda@835234971496cad1653abb28a638a281cf32541f  # 
v3.2.0
         with:
           miniforge-version: latest
@@ -319,3 +363,58 @@ jobs:
           BUILD_ALL: "0"
           BUILD_DRIVER_SQLITE: "1"
         run: .\ci\scripts\python_test.ps1 $pwd $pwd\build
+
+  # ------------------------------------------------------------
+  # MSVC/vcpkg build (no Conda)
+  # ------------------------------------------------------------
+  drivers-vcpkg:
+    name: "C/C++ (vcpkg/${{ matrix.os }}/${{ matrix.config }})"
+    runs-on: ${{ matrix.os }}
+    strategy:
+      matrix:
+        os: ["windows-latest"]
+        arch: ["x64"]
+        config: ["debug", "release"]
+    steps:
+      - uses: actions/checkout@v6
+        with:
+          fetch-depth: 0
+          persist-credentials: false
+      - name: Add msbuild to PATH
+        uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce 
# v2
+      - name: Setup MSYS2 tools
+        run: |
+          # msys64 is pre-installed on windows but not added to path
+          $env:PATH = 
"C:\msys64\mingw64\bin;C:\msys64\usr\bin\;C:\msys64\ucrt64\bin;$env:PATH"
+          echo "PATH=$env:PATH" >> $env:GITHUB_ENV
+
+          # Needed for gendef tool in GoUtils.cmake
+          pacman --noconfirm -S mingw-w64-x86_64-tools
+      # TODO(https://github.com/apache/arrow-adbc/issues/3825)
+      - name: Clone vcpkg
+        run: |
+          git clone https://github.com/microsoft/vcpkg.git
+          cd vcpkg
+          git checkout ef7dbf94b9198bc58f45951adcf1f041fcbc5ea0
+          .\bootstrap-vcpkg.bat
+      - name: Install vcpkg dependencies
+        working-directory: c
+        env:
+          VCPKG_ROOT: ${{ github.workspace }}/vcpkg
+        run: |
+          ${{ github.workspace }}/vcpkg/vcpkg.exe install libpq sqlite3 
--triplet ${{ matrix.arch }}-windows
+      - name: Build and Install (No ASan)
+        env:
+          CMAKE_BUILD_TYPE: ${{ matrix.config }}
+          VCPKG_ROOT: ${{ github.workspace }}/vcpkg
+        run: |
+          cmake .\c\ --preset windows-${{ matrix.config }} 
-DCMAKE_VERBOSE_MAKEFILE=ON
+
+          cmake --build .\build\${{ matrix.config }} --target install --config 
${{ matrix.config }} --parallel
+      - name: Test
+        env:
+          BUILD_ALL: "0"
+          BUILD_DRIVER_MANAGER: "1"
+          BUILD_DRIVER_MANAGER_USER_CONFIG_TEST: "1"
+          BUILD_DRIVER_SQLITE: "1"
+        run: .\ci\scripts\cpp_test.ps1 $pwd\build\${{ matrix.config }} 
$pwd\local\${{ matrix.config }}
diff --git a/c/CMakePresets.json b/c/CMakePresets.json
index fc4fdcb9a..b749532cc 100644
--- a/c/CMakePresets.json
+++ b/c/CMakePresets.json
@@ -23,6 +23,47 @@
                 "ADBC_USE_UBSAN": "ON"
             }
         },
+        {
+            "name": "multi-config-windows-base",
+            "displayName": "Base config for Windows without ASAN/UBSAN",
+            "hidden": true,
+            "toolchainFile": 
"$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
+            "cacheVariables": {
+                "CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
+                "ADBC_BUILD_TESTS": "ON",
+                "ADBC_DRIVER_FLIGHTSQL": "ON",
+                "ADBC_DRIVER_MANAGER": "ON",
+                "ADBC_DRIVER_POSTGRESQL": "ON",
+                "ADBC_DRIVER_SNOWFLAKE": "ON",
+                "ADBC_DRIVER_SQLITE": "ON",
+                "ADBC_BUILD_SHARED": "ON",
+                "ADBC_BUILD_STATIC": "OFF",
+                "ADBC_USE_ASAN": "OFF",
+                "ADBC_USE_UBSAN": "OFF",
+                "ADBC_BUILD_VCPKG": "ON",
+                "CMAKE_TOOLCHAIN_FILE": 
"$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
+                "CMAKE_C_COMPILER": "cl.exe",
+                "CMAKE_CXX_COMPILER": "cl.exe"
+            }
+        },
+        {
+            "name": "windows-debug",
+            "displayName": "Windows Debug",
+            "inherits": "multi-config-windows-base",
+            "binaryDir": "${sourceDir}/../build/debug",
+            "cacheVariables": {
+                "CMAKE_INSTALL_PREFIX": "${sourceDir}/../local/debug"
+            }
+        },
+        {
+            "name": "windows-release",
+            "displayName": "Windows Release",
+            "inherits": "multi-config-windows-base",
+            "binaryDir": "${sourceDir}/../build/release",
+            "cacheVariables": {
+                "CMAKE_INSTALL_PREFIX": "${sourceDir}/../local/release"
+            }
+        },
         {
             "name": "debug-python",
             "displayName": "debug, all drivers, with tests, without ASan/UBSan 
(usable from Python)",
@@ -41,6 +82,18 @@
             }
         }
     ],
+    "buildPresets": [
+        {
+          "name": "debug-windows",
+          "configurePreset": "windows-debug",
+          "configuration": "Debug"
+        },
+        {
+          "name": "release-windows",
+          "configurePreset": "windows-release",
+          "configuration": "Release"
+        }
+    ],
     "testPresets": [
         {
             "name": "debug",
diff --git a/c/cmake_modules/AdbcDefines.cmake 
b/c/cmake_modules/AdbcDefines.cmake
index 11fe1a5d2..12b593759 100644
--- a/c/cmake_modules/AdbcDefines.cmake
+++ b/c/cmake_modules/AdbcDefines.cmake
@@ -148,6 +148,26 @@ endmacro()
 # Common testing setup
 add_custom_target(all-tests)
 if(ADBC_BUILD_TESTS)
+  if(MSVC)
+    # MSVC emitted warnings for testing code
+    # Unary minus operator applied to unsigned type, result still unsigned
+    add_compile_options(/wd4146)
+    # An integer type is converted to a smaller integer type.
+    add_compile_options(/wd4244)
+    # Class has virtual functions, but its non-trivial destructor is not 
virtual; instances of this class may not be destructed correctly
+    add_compile_options(/wd4265)
+    # No override available for virtual member function from base
+    add_compile_options(/wd4266)
+    # Signed integral constant overflow
+    add_compile_options(/wd4307)
+    # Move constructor was implicitly defined as deleted
+    add_compile_options(/wd5026)
+    # Class has virtual functions, but its trivial destructor is not virtual
+    add_compile_options(/wd5204)
+    # Implicit fall-through occurs here
+    add_compile_options(/wd5262)
+  endif()
+
   find_package(GTest)
   if(NOT GTest_FOUND)
     message(STATUS "Building googletest from source")
diff --git a/c/cmake_modules/BuildUtils.cmake b/c/cmake_modules/BuildUtils.cmake
index 293b18d16..d7f4c2040 100644
--- a/c/cmake_modules/BuildUtils.cmake
+++ b/c/cmake_modules/BuildUtils.cmake
@@ -241,6 +241,17 @@ function(ADD_ARROW_LIB LIB_NAME)
                                      VERSION "${ADBC_FULL_SO_VERSION}"
                                      SOVERSION "${ADBC_SO_VERSION}")
 
+    if(WIN32)
+      # Binaries generated on Windows need file version information, otherwise 
when the binary is part of a Windows installer
+      # the installer won't know to update a previously installed version.
+      set(VERSION_RC_TEMPLATE "${CMAKE_SOURCE_DIR}/version.rc.in")
+      configure_file("${VERSION_RC_TEMPLATE}"
+                     "${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}_version.rc" 
@ONLY)
+
+      target_sources(${LIB_NAME}_shared
+                     PRIVATE 
"${CMAKE_CURRENT_BINARY_DIR}/${LIB_NAME}_version.rc")
+    endif()
+
     # https://github.com/apache/arrow-adbc/issues/81
     target_compile_features(${LIB_NAME}_shared PRIVATE cxx_std_11)
 
@@ -289,6 +300,19 @@ function(ADD_ARROW_LIB LIB_NAME)
             ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
             INCLUDES
             DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
+
+    # If we're building on Windows using vcpkg, ensure the runtime 
dependencies of binaries are copied to the install folder.
+    # TODO(https://github.com/apache/arrow-adbc/issues/3826): auto-detect this
+    if(ADBC_BUILD_VCPKG)
+      install(TARGETS ${LIB_NAME}_shared
+                      RUNTIME_DEPENDENCIES
+                      PRE_EXCLUDE_REGEXES
+                      "api-ms-win-.*"
+                      "ext-ms-.*"
+                      POST_EXCLUDE_REGEXES
+                      ".*system32.*"
+              RUNTIME DESTINATION ${RUNTIME_INSTALL_DIR})
+    endif()
   endif()
 
   if(BUILD_STATIC)
diff --git a/c/cmake_modules/DefineOptions.cmake 
b/c/cmake_modules/DefineOptions.cmake
index 759a8be40..37b0f62dc 100644
--- a/c/cmake_modules/DefineOptions.cmake
+++ b/c/cmake_modules/DefineOptions.cmake
@@ -232,6 +232,10 @@ if("${CMAKE_SOURCE_DIR}" STREQUAL 
"${CMAKE_CURRENT_SOURCE_DIR}")
   define_option(ADBC_DRIVER_BIGQUERY "Build the BigQuery driver" OFF)
 
   define_option(ADBC_INTEGRATION_DUCKDB "Build the test suite for DuckDB" OFF)
+
+  define_option(ADBC_BUILD_VCPKG
+                "Build on Windows using vcpkg for dependencies and Visual 
Studio generator."
+                OFF)
 endif()
 
 macro(validate_config)
diff --git a/c/cmake_modules/GoUtils.cmake b/c/cmake_modules/GoUtils.cmake
index a0e2ccef7..3909efdcd 100644
--- a/c/cmake_modules/GoUtils.cmake
+++ b/c/cmake_modules/GoUtils.cmake
@@ -18,6 +18,13 @@
 find_program(GO_BIN "go" REQUIRED)
 message(STATUS "Detecting Go executable: Found ${GO_BIN}")
 
+# Find tools for generating import libraries on Windows when building with 
vcpkg
+if(WIN32)
+  # msys64 is needed for dlltool and gendef
+  find_program(DLLTOOL_BIN "dlltool")
+  find_program(GENDEF_BIN "gendef")
+endif()
+
 set(ADBC_GO_PACKAGE_INIT
     [=[
 get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
@@ -65,6 +72,20 @@ function(adbc_add_static_library target_name base_name)
 endfunction()
 ]=])
 
+# Function to generate import library from DLL on Windows
+function(generate_import_library DLL_PATH LIB_PATH DEF_PATH)
+  add_custom_command(OUTPUT "${DEF_PATH}"
+                     COMMAND ${GENDEF_BIN} - "${DLL_PATH}" > "${DEF_PATH}"
+                     DEPENDS "${DLL_PATH}"
+                     COMMENT "Generating .def file from ${DLL_PATH}")
+
+  add_custom_command(OUTPUT "${LIB_PATH}"
+                     COMMAND ${DLLTOOL_BIN} -d "${DEF_PATH}" -l "${LIB_PATH}" 
-D
+                             "${DLL_PATH}"
+                     DEPENDS "${DEF_PATH}"
+                     COMMENT "Generating import library ${LIB_PATH}")
+endfunction()
+
 function(add_go_lib GO_MOD_DIR GO_LIBNAME)
   set(options)
   set(one_value_args
@@ -184,36 +205,79 @@ function(add_go_lib GO_MOD_DIR GO_LIBNAME)
       list(APPEND GO_ENV_VARS "GOARCH=arm64")
     endif()
 
-    add_custom_command(OUTPUT "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
-                       WORKING_DIRECTORY ${GO_MOD_DIR}
-                       DEPENDS ${ARG_SOURCES}
-                       COMMAND ${CMAKE_COMMAND} -E env ${GO_ENV_VARS} 
${GO_BIN} build
-                               ${GO_BUILD_TAGS} "${GO_BUILD_FLAGS}" -o
-                               ${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}
-                               -buildmode=c-shared ${GO_LDFLAGS} .
-                       COMMAND ${CMAKE_COMMAND} -E remove -f
-                               "${LIBOUT_SHARED}.${ADBC_SO_VERSION}.0.h"
-                       COMMENT "Building Go Shared lib ${GO_LIBNAME}"
-                       COMMAND_EXPAND_LISTS)
+    if(WIN32)
+      # On Windows with MSVC, generate a lib from the DLL file created by Go. 
Binaries generated on Windows have their version
+      # as part of the DLL/file details, therefore the generated DLL file name 
does not need to have the version info.
+      set(LIBOUT_IMPORT_LIB
+          
"${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_IMPORT_LIBRARY_PREFIX}${GO_LIBNAME}${CMAKE_IMPORT_LIBRARY_SUFFIX}"
+      )
+      set(LIBOUT_DEF_FILE "${CMAKE_CURRENT_BINARY_DIR}/${GO_LIBNAME}.def")
+
+      add_custom_command(OUTPUT "${LIBOUT_SHARED}"
+                         WORKING_DIRECTORY ${GO_MOD_DIR}
+                         DEPENDS ${ARG_SOURCES}
+                         COMMAND ${CMAKE_COMMAND} -E env ${GO_ENV_VARS} 
${GO_BIN} build
+                                 ${GO_BUILD_TAGS} "${GO_BUILD_FLAGS}" -o 
${LIBOUT_SHARED}
+                                 -buildmode=c-shared ${GO_LDFLAGS} .
+                         COMMAND ${CMAKE_COMMAND} -E remove -f 
"${LIBOUT_SHARED}.h"
+                         COMMENT "Building Go Shared lib ${GO_LIBNAME}"
+                         COMMAND_EXPAND_LISTS)
+
+      # Generate import library if tools are available
+      if(GENDEF_BIN AND DLLTOOL_BIN)
+        generate_import_library("${LIBOUT_SHARED}" "${LIBOUT_IMPORT_LIB}"
+                                "${LIBOUT_DEF_FILE}")
+        set(IMPORT_LIB_OUTPUTS "${LIBOUT_IMPORT_LIB}" "${LIBOUT_DEF_FILE}")
+      else()
+        set(IMPORT_LIB_OUTPUTS)
+        message(WARNING "Import library generation tools not found. You may 
need to link directly to the DLL or use delay-loading."
+        )
+      endif()
+
+      add_custom_target(${GO_LIBNAME}_target ALL DEPENDS "${LIBOUT_SHARED}"
+                                                         ${IMPORT_LIB_OUTPUTS})
+
+      add_library(${GO_LIBNAME}_shared SHARED IMPORTED GLOBAL)
+      set_target_properties(${GO_LIBNAME}_shared PROPERTIES IMPORTED_LOCATION
+                                                            "${LIBOUT_SHARED}")
 
-    add_custom_command(OUTPUT "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" 
"${LIBOUT_SHARED}"
-                       DEPENDS "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
-                       WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
-                       COMMAND ${CMAKE_COMMAND} -E create_symlink
-                               "${LIB_NAME_SHARED}.${ADBC_FULL_SO_VERSION}"
-                               "${LIB_NAME_SHARED}.${ADBC_SO_VERSION}"
-                       COMMAND ${CMAKE_COMMAND} -E create_symlink
-                               "${LIB_NAME_SHARED}.${ADBC_SO_VERSION}"
-                               "${LIB_NAME_SHARED}")
-
-    add_custom_target(${GO_LIBNAME}_target ALL
-                      DEPENDS "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
-                              "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" 
"${LIBOUT_SHARED}")
-    add_library(${GO_LIBNAME}_shared SHARED IMPORTED GLOBAL)
-    set_target_properties(${GO_LIBNAME}_shared
-                          PROPERTIES IMPORTED_LOCATION
-                                     "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
-                                     IMPORTED_SONAME "${LIB_NAME_SHARED}")
+      # Set import library if it was generated
+      if(IMPORT_LIB_OUTPUTS)
+        set_target_properties(${GO_LIBNAME}_shared PROPERTIES IMPORTED_IMPLIB
+                                                              
"${LIBOUT_IMPORT_LIB}")
+      endif()
+    else()
+      add_custom_command(OUTPUT "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
+                         WORKING_DIRECTORY ${GO_MOD_DIR}
+                         DEPENDS ${ARG_SOURCES}
+                         COMMAND ${CMAKE_COMMAND} -E env ${GO_ENV_VARS} 
${GO_BIN} build
+                                 ${GO_BUILD_TAGS} "${GO_BUILD_FLAGS}" -o
+                                 ${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}
+                                 -buildmode=c-shared ${GO_LDFLAGS} .
+                         COMMAND ${CMAKE_COMMAND} -E remove -f
+                                 "${LIBOUT_SHARED}.${ADBC_SO_VERSION}.0.h"
+                         COMMENT "Building Go Shared lib ${GO_LIBNAME}"
+                         COMMAND_EXPAND_LISTS)
+
+      add_custom_command(OUTPUT "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" 
"${LIBOUT_SHARED}"
+                         DEPENDS "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
+                         WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+                         COMMAND ${CMAKE_COMMAND} -E create_symlink
+                                 "${LIB_NAME_SHARED}.${ADBC_FULL_SO_VERSION}"
+                                 "${LIB_NAME_SHARED}.${ADBC_SO_VERSION}"
+                         COMMAND ${CMAKE_COMMAND} -E create_symlink
+                                 "${LIB_NAME_SHARED}.${ADBC_SO_VERSION}"
+                                 "${LIB_NAME_SHARED}")
+
+      add_custom_target(${GO_LIBNAME}_target ALL
+                        DEPENDS "${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
+                                "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" 
"${LIBOUT_SHARED}")
+      add_library(${GO_LIBNAME}_shared SHARED IMPORTED GLOBAL)
+      set_target_properties(${GO_LIBNAME}_shared
+                            PROPERTIES IMPORTED_LOCATION
+                                       
"${LIBOUT_SHARED}.${ADBC_FULL_SO_VERSION}"
+                                       IMPORTED_SONAME "${LIB_NAME_SHARED}")
+    endif()
     add_dependencies(${GO_LIBNAME}_shared ${GO_LIBNAME}_target)
     if(ARG_OUTPUTS)
       list(APPEND ${ARG_OUTPUTS} ${GO_LIBNAME}_shared)
@@ -243,6 +307,9 @@ function(add_go_lib GO_MOD_DIR GO_LIBNAME)
       if(WIN32)
         install(PROGRAMS $<TARGET_FILE:${GO_LIBNAME}_shared> 
${INSTALL_IS_OPTIONAL}
                 DESTINATION ${RUNTIME_INSTALL_DIR})
+        if(IMPORT_LIB_OUTPUTS)
+          install(FILES "${LIBOUT_IMPORT_LIB}" TYPE LIB)
+        endif()
       else()
         install(PROGRAMS $<TARGET_FILE:${GO_LIBNAME}_shared> 
${INSTALL_IS_OPTIONAL}
                 TYPE LIB)
@@ -259,8 +326,10 @@ function(add_go_lib GO_MOD_DIR GO_LIBNAME)
               ${CMAKE_INSTALL_LIBDIR})
     endif()
     if(WIN32)
-      # This symlink doesn't get installed
-      install(FILES "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" TYPE BIN)
+      install(FILES "${LIBOUT_SHARED}" TYPE BIN)
+      if(IMPORT_LIB_OUTPUTS)
+        install(FILES "${LIBOUT_IMPORT_LIB}" TYPE LIB)
+      endif()
     else()
       install(FILES "${LIBOUT_SHARED}" "${LIBOUT_SHARED}.${ADBC_SO_VERSION}" 
TYPE LIB)
     endif()
diff --git a/c/driver/flightsql/CMakeLists.txt 
b/c/driver/flightsql/CMakeLists.txt
index 9f60cbf07..300833410 100644
--- a/c/driver/flightsql/CMakeLists.txt
+++ b/c/driver/flightsql/CMakeLists.txt
@@ -63,6 +63,18 @@ if(ADBC_BUILD_TESTS)
                 adbc_driver_common
                 adbc_validation
                 ${TEST_LINK_LIBS})
+
+  if(ADBC_TEST_LINKAGE STREQUAL "shared")
+    # The Go build is not copying the DLL to the test location, causing the 
test to fail on Windows when building with vcpkg.
+    if(WIN32)
+      add_custom_command(TARGET adbc-driver-flightsql-test
+                         POST_BUILD
+                         COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                                 "$<TARGET_FILE:adbc_driver_flightsql_shared>"
+                                 
"$<TARGET_FILE_DIR:adbc-driver-flightsql-test>")
+    endif()
+  endif()
+
   target_compile_features(adbc-driver-flightsql-test PRIVATE cxx_std_17)
   target_include_directories(adbc-driver-flightsql-test SYSTEM
                              PRIVATE ${REPOSITORY_ROOT}/c/ 
${REPOSITORY_ROOT}/c/include/
diff --git a/c/driver/postgresql/copy/postgres_copy_reader_test.cc 
b/c/driver/postgresql/copy/postgres_copy_reader_test.cc
index 18e487f9c..483c38ac9 100644
--- a/c/driver/postgresql/copy/postgres_copy_reader_test.cc
+++ b/c/driver/postgresql/copy/postgres_copy_reader_test.cc
@@ -238,10 +238,10 @@ TEST(PostgresCopyUtilsTest, PostgresCopyReadReal) {
   ASSERT_TRUE(ArrowBitGet(validity, 3));
   ASSERT_FALSE(ArrowBitGet(validity, 4));
 
-  ASSERT_FLOAT_EQ(data_buffer[0], -123.456);
+  ASSERT_FLOAT_EQ(data_buffer[0], -123.456f);
   ASSERT_EQ(data_buffer[1], -1);
   ASSERT_EQ(data_buffer[2], 1);
-  ASSERT_FLOAT_EQ(data_buffer[3], 123.456);
+  ASSERT_FLOAT_EQ(data_buffer[3], 123.456f);
   ASSERT_EQ(data_buffer[4], 0);
 }
 
diff --git a/c/driver/snowflake/CMakeLists.txt 
b/c/driver/snowflake/CMakeLists.txt
index 2a81eb2c4..0560a3df5 100644
--- a/c/driver/snowflake/CMakeLists.txt
+++ b/c/driver/snowflake/CMakeLists.txt
@@ -63,6 +63,18 @@ if(ADBC_BUILD_TESTS)
                 adbc_validation
                 nanoarrow
                 ${TEST_LINK_LIBS})
+
+  if(ADBC_TEST_LINKAGE STREQUAL "shared")
+    # The Go build is not copying the DLL to the test location, causing the 
test to fail on Windows when building with vcpkg.
+    if(WIN32)
+      add_custom_command(TARGET adbc-driver-snowflake-test
+                         POST_BUILD
+                         COMMAND ${CMAKE_COMMAND} -E copy_if_different
+                                 "$<TARGET_FILE:adbc_driver_snowflake_shared>"
+                                 
"$<TARGET_FILE_DIR:adbc-driver-snowflake-test>")
+    endif()
+  endif()
+
   target_compile_features(adbc-driver-snowflake-test PRIVATE cxx_std_17)
   target_include_directories(adbc-driver-snowflake-test SYSTEM
                              PRIVATE ${REPOSITORY_ROOT}/c/ 
${REPOSITORY_ROOT}/c/include/
diff --git a/c/driver/sqlite/sqlite_test.cc b/c/driver/sqlite/sqlite_test.cc
index f270f5059..81817eb5d 100644
--- a/c/driver/sqlite/sqlite_test.cc
+++ b/c/driver/sqlite/sqlite_test.cc
@@ -446,7 +446,7 @@ class SqliteReaderTest : public ::testing::Test {
 
   void Exec(const std::string& query) {
     SCOPED_TRACE(query);
-    int rc = sqlite3_prepare_v2(db, query.c_str(), query.size(), &stmt,
+    int rc = sqlite3_prepare_v2(db, query.c_str(), 
static_cast<int>(query.size()), &stmt,
                                 /*pzTail=*/nullptr);
     ASSERT_EQ(SQLITE_OK, rc) << "Failed to prepare query: " << 
sqlite3_errmsg(db);
     ASSERT_EQ(SQLITE_DONE, sqlite3_step(stmt));
@@ -480,8 +480,9 @@ class SqliteReaderTest : public ::testing::Test {
 
   void Exec(const std::string& query, size_t infer_rows,
             adbc_validation::StreamReader* reader) {
-    ASSERT_EQ(SQLITE_OK, sqlite3_prepare_v2(db, query.c_str(), query.size(), 
&stmt,
-                                            /*pzTail=*/nullptr));
+    ASSERT_EQ(SQLITE_OK,
+              sqlite3_prepare_v2(db, query.c_str(), 
static_cast<int>(query.size()), &stmt,
+                                 /*pzTail=*/nullptr));
     struct AdbcSqliteBinder* binder =
         this->binder.schema.release ? &this->binder : nullptr;
     ASSERT_THAT(InternalAdbcSqliteExportReader(db, stmt, binder, infer_rows,
diff --git a/c/driver/sqlite/statement_reader.c 
b/c/driver/sqlite/statement_reader.c
index 554bdaf20..7c2cae682 100644
--- a/c/driver/sqlite/statement_reader.c
+++ b/c/driver/sqlite/statement_reader.c
@@ -451,8 +451,17 @@ AdbcStatusCode InternalAdbcSqliteBinderBindNext(struct 
AdbcSqliteBinder* binder,
         }
         case NANOARROW_TYPE_TIMESTAMP: {
           struct ArrowSchemaView bind_schema_view;
+// TODO(https://github.com/apache/arrow-adbc/issues/1675)
+#ifdef _MSC_VER
+#pragma warning(push)
+#pragma warning(disable : 4244)  // RAISE_NA returns ArrowErrorCode, but this 
function
+                                 // returns AdbcStatusCode
+#endif
           RAISE_NA(ArrowSchemaViewInit(&bind_schema_view, 
binder->schema.children[col],
                                        &arrow_error));
+#ifdef _MSC_VER
+#pragma warning(pop)
+#endif
           enum ArrowTimeUnit unit = bind_schema_view.time_unit;
           int64_t value =
               ArrowArrayViewGetIntUnsafe(binder->batch.children[col], 
binder->next_row);
diff --git a/c/driver_manager/CMakeLists.txt b/c/driver_manager/CMakeLists.txt
index 35f89ac84..ef488fb03 100644
--- a/c/driver_manager/CMakeLists.txt
+++ b/c/driver_manager/CMakeLists.txt
@@ -119,7 +119,7 @@ if(ADBC_BUILD_TESTS)
 
   if(ADBC_DRIVER_SQLITE)
     target_compile_definitions(adbc-driver-manager-test
-                               PRIVATE 
ADBC_DRIVER_MANAGER_TEST_LIB="${CMAKE_BINARY_DIR}/driver/sqlite/${CMAKE_SHARED_LIBRARY_PREFIX}adbc_driver_sqlite${CMAKE_SHARED_LIBRARY_SUFFIX}"
+                               PRIVATE 
ADBC_DRIVER_MANAGER_TEST_LIB="$<TARGET_FILE:adbc_driver_sqlite_shared>"
     )
   endif()
   if(ADBC_DRIVER_MANAGER_TEST_MANIFEST_USER_LEVEL)
diff --git a/c/driver_manager/adbc_driver_manager.cc 
b/c/driver_manager/adbc_driver_manager.cc
index c0e011098..93bc78791 100644
--- a/c/driver_manager/adbc_driver_manager.cc
+++ b/c/driver_manager/adbc_driver_manager.cc
@@ -462,18 +462,16 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
 
 SearchPaths GetEnvPaths(const char_type* env_var) {
 #ifdef _WIN32
-  size_t required_size;
-
-  _wgetenv_s(&required_size, NULL, 0, env_var);
+  DWORD required_size = GetEnvironmentVariableW(env_var, NULL, 0);
   if (required_size == 0) {
     return {};
   }
 
   std::wstring path_var;
   path_var.resize(required_size);
-  _wgetenv_s(&required_size, path_var.data(), required_size, env_var);
+  DWORD actual_size = GetEnvironmentVariableW(env_var, path_var.data(), 
required_size);
   // Remove null terminator
-  path_var.resize(required_size - 1);
+  path_var.resize(actual_size);
   auto path = Utf8Encode(path_var);
 #else
   const char* path_var = std::getenv(env_var);
@@ -483,8 +481,8 @@ SearchPaths GetEnvPaths(const char_type* env_var) {
   std::string path(path_var);
 #endif  // _WIN32
   SearchPaths paths;
-  for (auto path : InternalAdbcParsePath(path)) {
-    paths.emplace_back(SearchPathSource::kEnv, path);
+  for (auto parsed_path : InternalAdbcParsePath(path)) {
+    paths.emplace_back(SearchPathSource::kEnv, parsed_path);
   }
   return paths;
 }
@@ -1531,7 +1529,7 @@ std::string 
InternalAdbcDriverManagerDefaultEntrypoint(const std::string& driver
     // if pos == npos this is the entire filename
     std::string token = filename.substr(prev, pos - prev);
     // capitalize first letter
-    token[0] = std::toupper(static_cast<unsigned char>(token[0]));
+    token[0] = static_cast<char>(std::toupper(static_cast<unsigned 
char>(token[0])));
 
     entrypoint += token;
 
diff --git a/c/driver_manager/adbc_driver_manager_test.cc 
b/c/driver_manager/adbc_driver_manager_test.cc
index d67a1218c..80a2fe77f 100644
--- a/c/driver_manager/adbc_driver_manager_test.cc
+++ b/c/driver_manager/adbc_driver_manager_test.cc
@@ -569,7 +569,10 @@ class DriverManifest : public ::testing::Test {
  protected:
   void SetConfigPath(const char* path) {
 #ifdef _WIN32
-    ASSERT_TRUE(SetEnvironmentVariable("ADBC_DRIVER_PATH", path));
+    int size_needed = MultiByteToWideChar(CP_UTF8, 0, path, -1, nullptr, 0);
+    std::wstring wpath(size_needed, 0);
+    MultiByteToWideChar(CP_UTF8, 0, path, -1, &wpath[0], size_needed);
+    ASSERT_TRUE(SetEnvironmentVariableW(L"ADBC_DRIVER_PATH", wpath.c_str()));
 #else
     setenv("ADBC_DRIVER_PATH", path, 1);
 #endif
@@ -1138,12 +1141,20 @@ TEST_F(DriverManifest, AllDisabled) {
   EXPECT_THAT(error.message,
               ::testing::HasSubstr("not enabled at run time: ADBC_DRIVER_PATH 
(enable "
                                    "ADBC_LOAD_FLAG_SEARCH_ENV)"));
+
+#ifdef _WIN32
   EXPECT_THAT(error.message,
-              ::testing::HasSubstr("not enabled at run time: user config dir 
/"));
+              ::testing::HasSubstr("not enabled at run time: 
HKEY_CURRENT_USER"));
   EXPECT_THAT(error.message,
-              ::testing::HasSubstr(" (enable ADBC_LOAD_FLAG_SEARCH_USER)"));
+              ::testing::HasSubstr("not enabled at run time: 
HKEY_LOCAL_MACHINE"));
+#else
+  EXPECT_THAT(error.message,
+              ::testing::HasSubstr("not enabled at run time: user config dir 
/"));
   EXPECT_THAT(error.message,
               ::testing::HasSubstr("not enabled at run time: system config dir 
/"));
+#endif  // _WIN32
+  EXPECT_THAT(error.message,
+              ::testing::HasSubstr(" (enable ADBC_LOAD_FLAG_SEARCH_USER)"));
   EXPECT_THAT(error.message,
               ::testing::HasSubstr(" (enable ADBC_LOAD_FLAG_SEARCH_SYSTEM)"));
 }
diff --git a/c/validation/adbc_validation.cc b/c/validation/adbc_validation.cc
index 5cd592679..626b03f3d 100644
--- a/c/validation/adbc_validation.cc
+++ b/c/validation/adbc_validation.cc
@@ -51,11 +51,12 @@ AdbcStatusCode DoIngestSampleTable(struct AdbcConnection* 
connection,
   Handle<struct ArrowSchema> schema;
   Handle<struct ArrowArray> array;
   struct ArrowError na_error;
-  CHECK_OK(MakeSchema(&schema.value, {{"int64s", NANOARROW_TYPE_INT64},
-                                      {"strings", NANOARROW_TYPE_STRING}}));
-  CHECK_OK((MakeBatch<int64_t, std::string>(&schema.value, &array.value, 
&na_error,
-                                            {42, -42, std::nullopt},
-                                            {"foo", std::nullopt, ""})));
+  CHECK_OK(static_cast<AdbcStatusCode>(MakeSchema(
+      &schema.value,
+      {{"int64s", NANOARROW_TYPE_INT64}, {"strings", 
NANOARROW_TYPE_STRING}})));
+  CHECK_OK((static_cast<AdbcStatusCode>(MakeBatch<int64_t, std::string>(
+      &schema.value, &array.value, &na_error, {42, -42, std::nullopt},
+      {"foo", std::nullopt, ""}))));
 
   Handle<struct AdbcStatement> statement;
   CHECK_OK(AdbcStatementNew(connection, &statement.value, error));
diff --git a/c/validation/adbc_validation_connection.cc 
b/c/validation/adbc_validation_connection.cc
index 9c9bdeff2..d7e61b918 100644
--- a/c/validation/adbc_validation_connection.cc
+++ b/c/validation/adbc_validation_connection.cc
@@ -868,7 +868,7 @@ void ConstraintTest(const AdbcGetObjectsConstraint* 
constraint,
                     const std::vector<std::string>& columns) {
   std::string_view constraint_type(constraint->constraint_type.data,
                                    constraint->constraint_type.size_bytes);
-  int number_of_columns = columns.size();
+  int number_of_columns = static_cast<int>(columns.size());
   ASSERT_EQ(constraint_type, key_type);
   ASSERT_EQ(constraint->n_column_names, number_of_columns)
       << "expected constraint " << key_type
diff --git a/c/validation/adbc_validation_statement.cc 
b/c/validation/adbc_validation_statement.cc
index ae5ef518a..131dbb2b6 100644
--- a/c/validation/adbc_validation_statement.cc
+++ b/c/validation/adbc_validation_statement.cc
@@ -1358,22 +1358,22 @@ void StatementTest::TestSqlIngestTemporaryAppend() {
     ASSERT_THAT((MakeBatch<int64_t>(&schema.value, &array.value, &na_error, 
{0, 1, 2})),
                 IsOkErrno());
 
-    Handle<struct AdbcStatement> statement;
-    ASSERT_THAT(AdbcStatementNew(&connection, &statement.value, &error),
+    Handle<struct AdbcStatement> statement2;
+    ASSERT_THAT(AdbcStatementNew(&connection, &statement2.value, &error),
                 IsOkStatus(&error));
 
-    ASSERT_THAT(AdbcStatementSetOption(&statement.value, 
ADBC_INGEST_OPTION_TEMPORARY,
+    ASSERT_THAT(AdbcStatementSetOption(&statement2.value, 
ADBC_INGEST_OPTION_TEMPORARY,
                                        ADBC_OPTION_VALUE_ENABLED, &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementSetOption(&statement.value, 
ADBC_INGEST_OPTION_MODE,
+    ASSERT_THAT(AdbcStatementSetOption(&statement2.value, 
ADBC_INGEST_OPTION_MODE,
                                        ADBC_INGEST_OPTION_MODE_APPEND, &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementSetOption(&statement.value, 
ADBC_INGEST_OPTION_TARGET_TABLE,
+    ASSERT_THAT(AdbcStatementSetOption(&statement2.value, 
ADBC_INGEST_OPTION_TARGET_TABLE,
                                        name.c_str(), &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementBind(&statement.value, &array.value, 
&schema.value, &error),
+    ASSERT_THAT(AdbcStatementBind(&statement2.value, &array.value, 
&schema.value, &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementExecuteQuery(&statement.value, nullptr, nullptr, 
&error),
+    ASSERT_THAT(AdbcStatementExecuteQuery(&statement2.value, nullptr, nullptr, 
&error),
                 IsOkStatus(&error));
   }
 
@@ -1533,22 +1533,22 @@ void StatementTest::TestSqlIngestTemporaryReplace() {
                                                  {"foo", "bar", 
std::nullopt})),
                 IsOkErrno());
 
-    Handle<struct AdbcStatement> statement;
-    ASSERT_THAT(AdbcStatementNew(&connection, &statement.value, &error),
+    Handle<struct AdbcStatement> statement2;
+    ASSERT_THAT(AdbcStatementNew(&connection, &statement2.value, &error),
                 IsOkStatus(&error));
 
-    ASSERT_THAT(AdbcStatementSetOption(&statement.value, 
ADBC_INGEST_OPTION_TEMPORARY,
+    ASSERT_THAT(AdbcStatementSetOption(&statement2.value, 
ADBC_INGEST_OPTION_TEMPORARY,
                                        ADBC_OPTION_VALUE_ENABLED, &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementSetOption(&statement.value, 
ADBC_INGEST_OPTION_MODE,
+    ASSERT_THAT(AdbcStatementSetOption(&statement2.value, 
ADBC_INGEST_OPTION_MODE,
                                        ADBC_INGEST_OPTION_MODE_APPEND, &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementSetOption(&statement.value, 
ADBC_INGEST_OPTION_TARGET_TABLE,
+    ASSERT_THAT(AdbcStatementSetOption(&statement2.value, 
ADBC_INGEST_OPTION_TARGET_TABLE,
                                        name.c_str(), &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementBind(&statement.value, &array.value, 
&schema.value, &error),
+    ASSERT_THAT(AdbcStatementBind(&statement2.value, &array.value, 
&schema.value, &error),
                 IsOkStatus(&error));
-    ASSERT_THAT(AdbcStatementExecuteQuery(&statement.value, nullptr, nullptr, 
&error),
+    ASSERT_THAT(AdbcStatementExecuteQuery(&statement2.value, nullptr, nullptr, 
&error),
                 IsOkStatus(&error));
   }
 
diff --git a/c/validation/adbc_validation_util.h 
b/c/validation/adbc_validation_util.h
index 57f3859f4..980912f71 100644
--- a/c/validation/adbc_validation_util.h
+++ b/c/validation/adbc_validation_util.h
@@ -445,8 +445,8 @@ void CompareArray(struct ArrowArrayView* array,
       } else if constexpr (std::is_same<T, std::vector<std::byte>>::value) {
         struct ArrowBufferView view = ArrowArrayViewGetBytesUnsafe(array, i);
         ASSERT_EQ(v->size(), view.size_bytes);
-        for (int64_t i = 0; i < view.size_bytes; i++) {
-          ASSERT_EQ((*v)[i], std::byte{view.data.as_uint8[i]});
+        for (int64_t i2 = 0; i2 < view.size_bytes; i2++) {
+          ASSERT_EQ((*v)[i2], std::byte{view.data.as_uint8[i2]});
         }
       } else if constexpr (std::is_same<T, ArrowInterval*>::value) {
         ASSERT_NE(array->buffer_views[1].data.data, nullptr);
diff --git a/c/version.rc.in b/c/version.rc.in
new file mode 100644
index 000000000..39938829b
--- /dev/null
+++ b/c/version.rc.in
@@ -0,0 +1,49 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you 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 <windows.h>
+
+#define LANG_CODE_US_ENGLISH 0x0409
+#define CHARSET_UNICODE 0x04b0
+#define US_ENGLISH_UNICODE "040904b0"
+
+VS_VERSION_INFO VERSIONINFO
+FILEVERSION @ADBC_VERSION_MAJOR@,@ADBC_VERSION_MINOR@,@ADBC_VERSION_PATCH@,0
+PRODUCTVERSION @ADBC_VERSION_MAJOR@,@ADBC_VERSION_MINOR@,@ADBC_VERSION_PATCH@,0
+FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
+FILEFLAGS 0x0L
+FILEOS VOS__WINDOWS32
+FILETYPE VFT_DLL
+FILESUBTYPE VFT2_UNKNOWN
+BEGIN
+    BLOCK "StringFileInfo"
+    BEGIN
+        BLOCK US_ENGLISH_UNICODE
+        BEGIN
+            VALUE "FileDescription", "ADBC: Arrow Database Connectivity"
+            VALUE "FileVersion", "@ADBC_VERSION@"
+            VALUE "ProductVersion", "@ADBC_VERSION@"
+            VALUE "CompanyName", "Apache Software Foundation"
+            VALUE "ProductName", "@LIB_NAME@"
+            VALUE "InternalName", "@LIB_NAME@"
+        END
+    END
+    BLOCK "VarFileInfo"
+    BEGIN
+        VALUE "Translation", LANG_CODE_US_ENGLISH, CHARSET_UNICODE
+    END
+END
diff --git a/ci/scripts/cpp_test.ps1 b/ci/scripts/cpp_test.ps1
index e25c2e026..9d92d50b1 100755
--- a/ci/scripts/cpp_test.ps1
+++ b/ci/scripts/cpp_test.ps1
@@ -32,9 +32,10 @@ $BuildDriverSqlite = ($BuildAll -and (-not 
($env:BUILD_DRIVER_SQLITE -eq "0")))
 $env:LD_LIBRARY_PATH += ":$($InstallDir)"
 $env:LD_LIBRARY_PATH += ":$($InstallDir)/bin"
 $env:LD_LIBRARY_PATH += ":$($InstallDir)/lib"
-$env:PATH += ";$($InstallDir)"
-$env:PATH += ";$($InstallDir)\bin"
-$env:PATH += ";$($InstallDir)\lib"
+# InstallDir must come first, else on CI we may pick up system sqlite and crash
+$env:PATH = "$($InstallDir);$env:PATH"
+$env:PATH = "$($InstallDir)\bin;$env:PATH"
+$env:PATH = "$($InstallDir)\lib;$env:PATH"
 
 function Test-Project {
     Push-Location $BuildDir
diff --git a/go/adbc/drivermgr/adbc_driver_manager.cc 
b/go/adbc/drivermgr/adbc_driver_manager.cc
index c0e011098..93bc78791 100644
--- a/go/adbc/drivermgr/adbc_driver_manager.cc
+++ b/go/adbc/drivermgr/adbc_driver_manager.cc
@@ -462,18 +462,16 @@ AdbcStatusCode LoadDriverManifest(const 
std::filesystem::path& driver_manifest,
 
 SearchPaths GetEnvPaths(const char_type* env_var) {
 #ifdef _WIN32
-  size_t required_size;
-
-  _wgetenv_s(&required_size, NULL, 0, env_var);
+  DWORD required_size = GetEnvironmentVariableW(env_var, NULL, 0);
   if (required_size == 0) {
     return {};
   }
 
   std::wstring path_var;
   path_var.resize(required_size);
-  _wgetenv_s(&required_size, path_var.data(), required_size, env_var);
+  DWORD actual_size = GetEnvironmentVariableW(env_var, path_var.data(), 
required_size);
   // Remove null terminator
-  path_var.resize(required_size - 1);
+  path_var.resize(actual_size);
   auto path = Utf8Encode(path_var);
 #else
   const char* path_var = std::getenv(env_var);
@@ -483,8 +481,8 @@ SearchPaths GetEnvPaths(const char_type* env_var) {
   std::string path(path_var);
 #endif  // _WIN32
   SearchPaths paths;
-  for (auto path : InternalAdbcParsePath(path)) {
-    paths.emplace_back(SearchPathSource::kEnv, path);
+  for (auto parsed_path : InternalAdbcParsePath(path)) {
+    paths.emplace_back(SearchPathSource::kEnv, parsed_path);
   }
   return paths;
 }
@@ -1531,7 +1529,7 @@ std::string 
InternalAdbcDriverManagerDefaultEntrypoint(const std::string& driver
     // if pos == npos this is the entire filename
     std::string token = filename.substr(prev, pos - prev);
     // capitalize first letter
-    token[0] = std::toupper(static_cast<unsigned char>(token[0]));
+    token[0] = static_cast<char>(std::toupper(static_cast<unsigned 
char>(token[0])));
 
     entrypoint += token;
 


Reply via email to