diff --git a/CMakeLists.txt b/CMakeLists.txt
index d553697..2d9b546 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -251,6 +251,14 @@
 check_symbol_exists(strsep string.h HAVE_STRSEP)
 check_symbol_exists(strtok_r string.h HAVE_STRTOK_R)
 
+if (WIN32)
+    # Required due to a bug in MinGW where the .h file is correct
+    # but the symbol is missing from newdev.dll
+    set(CMAKE_REQUIRED_LIBRARIES newdev.lib)
+    check_symbol_exists(DiInstallDevice "windows.h;newdev.h" HAVE_DIINSTALLDEVICE)
+    unset(CMAKE_REQUIRED_LIBRARIES)
+endif ()
+
 # Some OS (e.g. FreeBSD) need some basic headers to allow
 # including network headers
 set(NETEXTRA sys/types.h)
@@ -344,7 +352,7 @@
     if (MINGW)
         target_compile_definitions(${target} PRIVATE
                 WIN32_LEAN_AND_MEAN
-                NTDDI_VERSION=NTDDI_VISTA _WIN32_WINNT=_WIN32_WINNT_VISTA
+                NTDDI_VERSION=NTDDI_WIN10 _WIN32_WINNT=_WIN32_WINNT_WIN10
         )
     endif()
 
diff --git a/config.h.cmake.in b/config.h.cmake.in
index c6c0a96..6c8660c 100644
--- a/config.h.cmake.in
+++ b/config.h.cmake.in
@@ -330,6 +330,9 @@
 /* Define to 1 if you have the <valgrind/memcheck.h> header file. */
 #undef HAVE_VALGRIND_MEMCHECK_H
 
+/* Define to 1 if you have the `DiInstallDevice' function. */
+#cmakedefine HAVE_DIINSTALLDEVICE
+
 /* Availability of different mbed TLS features and APIs */
 #cmakedefine HAVE_PSA_CRYPTO_H
 
diff --git a/configure.ac b/configure.ac
index 1fa0e63..a06c4c9 100644
--- a/configure.ac
+++ b/configure.ac
@@ -346,7 +346,7 @@
 		AM_CONDITIONAL([ENABLE_DNS_UPDOWN], [false])
 		AC_SUBST([DNS_UPDOWN_TYPE], ["windows"])
 		CPPFLAGS="${CPPFLAGS} -DWIN32_LEAN_AND_MEAN"
-		CPPFLAGS="${CPPFLAGS} -DNTDDI_VERSION=NTDDI_VISTA -D_WIN32_WINNT=_WIN32_WINNT_VISTA"
+		CPPFLAGS="${CPPFLAGS} -DNTDDI_VERSION=NTDDI_WIN10 -D_WIN32_WINNT=_WIN32_WINNT_WIN10"
 		WIN32=yes
 		;;
 	*-*-dragonfly*)
@@ -1397,4 +1397,4 @@
 # Put the warning at the end, so it is better visible
 if test "${enable_debug}" = "yes"; then
     AC_MSG_WARN([--enable-developer-debug is enabled. This should be only used for test/development builds and not for production usage])
-fi
\ No newline at end of file
+fi
diff --git a/src/openvpn/dco_win.c b/src/openvpn/dco_win.c
index 90cff8c..bd94c1a 100644
--- a/src/openvpn/dco_win.c
+++ b/src/openvpn/dco_win.c
@@ -35,6 +35,7 @@
 #include "openvpn.h"
 
 #include <bcrypt.h>
+#include <ioapiset.h>
 #include <winsock2.h>
 #include <ws2tcpip.h>
 
@@ -222,17 +223,6 @@
 dco_connect_wait(HANDLE handle, OVERLAPPED *ov, int timeout, struct signal_info *sig_info)
 {
     volatile int *signal_received = &sig_info->signal_received;
-    /* GetOverlappedResultEx is available starting from Windows 8 */
-    typedef BOOL(WINAPI * get_overlapped_result_ex_t)(HANDLE, LPOVERLAPPED, LPDWORD, DWORD, BOOL);
-    get_overlapped_result_ex_t get_overlapped_result_ex =
-        (get_overlapped_result_ex_t)GetProcAddress(GetModuleHandle("Kernel32.dll"),
-                                                   "GetOverlappedResultEx");
-
-    if (get_overlapped_result_ex == NULL)
-    {
-        msg(M_ERR, "Failed to load GetOverlappedResult()");
-    }
-
     DWORD timeout_msec = timeout * 1000;
     const int poll_interval_ms = 50;
 
@@ -241,7 +231,7 @@
         timeout_msec -= poll_interval_ms;
 
         DWORD transferred;
-        if (get_overlapped_result_ex(handle, ov, &transferred, poll_interval_ms, FALSE) != 0)
+        if (GetOverlappedResultEx(handle, ov, &transferred, poll_interval_ms, FALSE) != 0)
         {
             /* TCP connection established by dco */
             return;
diff --git a/src/openvpn/win32.c b/src/openvpn/win32.c
index 618772d..4c511a9 100644
--- a/src/openvpn/win32.c
+++ b/src/openvpn/win32.c
@@ -37,6 +37,7 @@
 #include <winsock2.h>
 #include <accctrl.h>
 #include <aclapi.h>
+#include <wow64apiset.h>
 
 #include "buffer.h"
 #include "error.h"
@@ -1333,67 +1334,47 @@
 static void
 win32_get_arch(arch_t *process_arch, arch_t *host_arch)
 {
-    *process_arch = ARCH_UNKNOWN;
-    *host_arch = ARCH_NATIVE;
-
-    typedef BOOL(WINAPI * is_wow64_process2_t)(HANDLE, USHORT *, USHORT *);
-    is_wow64_process2_t is_wow64_process2 =
-        (is_wow64_process2_t)GetProcAddress(GetModuleHandle("Kernel32.dll"), "IsWow64Process2");
-
 #ifdef _ARM64_
     *process_arch = ARCH_ARM64;
 #elif defined(_WIN64)
     *process_arch = ARCH_AMD64;
-    if (is_wow64_process2)
-    {
-        /* this could be amd64 on arm64 */
-        USHORT process_machine = 0;
-        USHORT native_machine = 0;
-        BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
-        if (is_wow64 && native_machine == IMAGE_FILE_MACHINE_ARM64)
-        {
-            *host_arch = ARCH_ARM64;
-        }
-    }
-#elif defined(_WIN32)
+#else
     *process_arch = ARCH_X86;
+#endif
 
-    if (is_wow64_process2)
+    *host_arch = ARCH_NATIVE;
+    /* Determine if we're running on a different host-arch */
+    USHORT process_machine = 0;
+    USHORT native_machine = 0;
+
+    if (!IsWow64Process2(GetCurrentProcess(), &process_machine, &native_machine))
     {
-        /* check if we're running on arm64 or amd64 machine */
-        USHORT process_machine = 0;
-        USHORT native_machine = 0;
-        BOOL is_wow64 = is_wow64_process2(GetCurrentProcess(), &process_machine, &native_machine);
-        if (is_wow64)
-        {
-            switch (native_machine)
-            {
-                case IMAGE_FILE_MACHINE_ARM64:
-                    *host_arch = ARCH_ARM64;
-                    break;
-
-                case IMAGE_FILE_MACHINE_AMD64:
-                    *host_arch = ARCH_AMD64;
-                    break;
-
-                default:
-                    *host_arch = ARCH_UNKNOWN;
-                    break;
-            }
-        }
+        return;
     }
-    else
+
+    switch (native_machine)
     {
-        BOOL w64 = FALSE;
-        BOOL is_wow64 = IsWow64Process(GetCurrentProcess(), &w64) && w64;
-        if (is_wow64)
-        {
-            /* we are unable to differentiate between arm64 and amd64
-             * machines here, so assume we are running on amd64 */
+        case IMAGE_FILE_MACHINE_ARM64:
+            *host_arch = ARCH_ARM64;
+            break;
+
+        case IMAGE_FILE_MACHINE_AMD64:
             *host_arch = ARCH_AMD64;
-        }
+            break;
+
+        case IMAGE_FILE_MACHINE_I386:
+            *host_arch = ARCH_X86;
+            break;
+
+        default:
+            *host_arch = ARCH_UNKNOWN;
+            break;
     }
-#endif /* _ARM64_ */
+
+    if (*host_arch == *process_arch)
+    {
+        *host_arch = ARCH_NATIVE;
+    }
 }
 
 static void
diff --git a/src/openvpnmsica/CMakeLists.txt b/src/openvpnmsica/CMakeLists.txt
index 9126b80..06889c8 100644
--- a/src/openvpnmsica/CMakeLists.txt
+++ b/src/openvpnmsica/CMakeLists.txt
@@ -24,7 +24,7 @@
 target_compile_options(openvpnmsica PRIVATE
     -D_UNICODE
     -UNTDDI_VERSION
-    -D_WIN32_WINNT=_WIN32_WINNT_VISTA
+    -D_WIN32_WINNT=_WIN32_WINNT_WIN10
     )
 
 if (MSVC)
diff --git a/src/openvpnmsica/Makefile.am b/src/openvpnmsica/Makefile.am
index 87bf9a7..5e7838f 100644
--- a/src/openvpnmsica/Makefile.am
+++ b/src/openvpnmsica/Makefile.am
@@ -34,8 +34,7 @@
 lib_LTLIBRARIES = libopenvpnmsica.la
 libopenvpnmsica_la_CFLAGS = \
 	-municode -D_UNICODE \
-	-UNTDDI_VERSION -U_WIN32_WINNT \
-	-D_WIN32_WINNT=_WIN32_WINNT_VISTA \
+	-UNTDDI_VERSION -D_WIN32_WINNT=_WIN32_WINNT_WIN10 \
 	-Wl,--kill-at
 libopenvpnmsica_la_LDFLAGS = -ladvapi32 -lole32 -lmsi -lsetupapi -liphlpapi -lshell32 -lshlwapi -lversion -lnewdev -no-undefined -avoid-version
 endif
diff --git a/src/openvpnserv/CMakeLists.txt b/src/openvpnserv/CMakeLists.txt
index fc15382..2cc4a93 100644
--- a/src/openvpnserv/CMakeLists.txt
+++ b/src/openvpnserv/CMakeLists.txt
@@ -21,7 +21,7 @@
     target_compile_options(${target} PRIVATE
         -D_UNICODE
         -UNTDDI_VERSION
-        -D_WIN32_WINNT=_WIN32_WINNT_VISTA
+        -D_WIN32_WINNT=_WIN32_WINNT_WIN10
     )
     target_link_libraries(${target} PRIVATE
         advapi32.lib userenv.lib iphlpapi.lib fwpuclnt.lib rpcrt4.lib
diff --git a/src/openvpnserv/Makefile.am b/src/openvpnserv/Makefile.am
index ac97eb4..447fb10 100644
--- a/src/openvpnserv/Makefile.am
+++ b/src/openvpnserv/Makefile.am
@@ -23,8 +23,7 @@
 sbin_PROGRAMS = openvpnserv
 openvpnserv_CFLAGS = \
 	-municode -D_UNICODE \
-	-UNTDDI_VERSION -U_WIN32_WINNT \
-	-D_WIN32_WINNT=_WIN32_WINNT_VISTA
+	-UNTDDI_VERSION -D_WIN32_WINNT=_WIN32_WINNT_WIN10
 openvpnserv_LDADD = \
 	-ladvapi32 -luserenv -liphlpapi -lfwpuclnt -lrpcrt4 \
 	-lshlwapi -lnetapi32 -lws2_32 -lntdll -lole32 -lpathcch
diff --git a/src/tapctl/CMakeLists.txt b/src/tapctl/CMakeLists.txt
index 97702c0..94453ed 100644
--- a/src/tapctl/CMakeLists.txt
+++ b/src/tapctl/CMakeLists.txt
@@ -21,10 +21,10 @@
 target_compile_options(tapctl PRIVATE
     -D_UNICODE
     -UNTDDI_VERSION
-    -D_WIN32_WINNT=_WIN32_WINNT_VISTA
+    -D_WIN32_WINNT=_WIN32_WINNT_WIN10
     )
 target_link_libraries(tapctl
-    advapi32.lib ole32.lib setupapi.lib)
+    advapi32.lib newdev.lib ole32.lib setupapi.lib)
 if (MINGW)
     target_compile_options(tapctl PRIVATE -municode)
     target_link_options(tapctl PRIVATE -municode)
diff --git a/src/tapctl/Makefile.am b/src/tapctl/Makefile.am
index 58cd580..5d1f851 100644
--- a/src/tapctl/Makefile.am
+++ b/src/tapctl/Makefile.am
@@ -35,8 +35,7 @@
 sbin_PROGRAMS = tapctl
 tapctl_CFLAGS = \
 	-municode -D_UNICODE \
-	-UNTDDI_VERSION -U_WIN32_WINNT \
-	-D_WIN32_WINNT=_WIN32_WINNT_VISTA
+	-UNTDDI_VERSION	-D_WIN32_WINNT=_WIN32_WINNT_WIN10
 tapctl_LDADD = -ladvapi32 -lole32 -lsetupapi
 endif
 
diff --git a/src/tapctl/tap.c b/src/tapctl/tap.c
index dd22cc5..ac1ecd2 100644
--- a/src/tapctl/tap.c
+++ b/src/tapctl/tap.c
@@ -50,6 +50,7 @@
     (_countof(L"SYSTEM\\CurrentControlSet\\Control\\Network\\") - 1 + 38 + _countof(L"\\") - 1 \
      + 38 + _countof(L"\\Connection"))
 
+#ifndef HAVE_DIINSTALLDEVICE
 /**
  * Dynamically load a library and find a function in it
  *
@@ -99,6 +100,7 @@
     }
     return fptr;
 }
+#endif
 
 /**
  * Returns length of string of strings
