Source: https://github.com/crystalidea/qt6windows7
Release 6.8.3

diff --git a/src/corelib/io/qstandardpaths_win.cpp b/src/corelib/io/qstandardpaths_win.cpp
index 805ce65a5ac..6ed351d2e82 100644
--- a/src/corelib/io/qstandardpaths_win.cpp
+++ b/src/corelib/io/qstandardpaths_win.cpp
@@ -12,6 +12,7 @@
 
 #include <qt_windows.h>
 #include <shlobj.h>
+#include <versionhelpers.h>
 #include <intshcut.h>
 #include <qvarlengtharray.h>
 
@@ -60,20 +61,26 @@ static inline void appendTestMode(QString &path)
 
 static bool isProcessLowIntegrity()
 {
+    if (!IsWindows8OrGreater())
+        return false;
+
     // same as GetCurrentProcessToken()
     const auto process_token = HANDLE(quintptr(-4));
 
     QVarLengthArray<char,256> token_info_buf(256);
     auto* token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
     DWORD token_info_length = token_info_buf.size();
-    if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length)) {
+    if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length)
+        && GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
         // grow buffer and retry GetTokenInformation
         token_info_buf.resize(token_info_length);
         token_info = reinterpret_cast<TOKEN_MANDATORY_LABEL*>(token_info_buf.data());
         if (!GetTokenInformation(process_token, TokenIntegrityLevel, token_info, token_info_length, &token_info_length))
             return false; // assume "normal" process
     }
-
+    else
+        return false;
+    
     // The GetSidSubAuthorityCount return-code is undefined on failure, so
     // there's no point in checking before dereferencing
     DWORD integrity_level = *GetSidSubAuthority(token_info->Label.Sid, *GetSidSubAuthorityCount(token_info->Label.Sid) - 1);
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index a7663b24813..8459cd5cad0 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -360,10 +360,15 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
         ok = t->fastTimerId;
     }
 
-    if (!ok) {
+    typedef BOOL (WINAPI *SetCoalescableTimerFunc) (HWND, UINT_PTR, UINT, TIMERPROC, ULONG);
+    static SetCoalescableTimerFunc mySetCoalescableTimerFunc = 
+        (SetCoalescableTimerFunc)::GetProcAddress(::GetModuleHandle(L"User32"), "SetCoalescableTimer");
+
+    if (!ok && mySetCoalescableTimerFunc) {
         // user normal timers for (Very)CoarseTimers, or if no more multimedia timers available
-        ok = SetCoalescableTimer(internalHwnd, t->timerId, interval, nullptr, tolerance);
+        ok = mySetCoalescableTimerFunc(internalHwnd, t->timerId, interval, nullptr, tolerance);
     }
+    
     if (!ok)
         ok = SetTimer(internalHwnd, t->timerId, interval, nullptr);
 
diff --git a/src/corelib/kernel/qfunctions_win.cpp b/src/corelib/kernel/qfunctions_win.cpp
index 048fdbc934c..e715093d27b 100644
--- a/src/corelib/kernel/qfunctions_win.cpp
+++ b/src/corelib/kernel/qfunctions_win.cpp
@@ -44,10 +44,17 @@ QComHelper::~QComHelper()
 */
 bool qt_win_hasPackageIdentity()
 {
+    typedef BOOL (WINAPI *GetCurrentPackageFullNameFunc) (UINT32 *, PWSTR);
+    static GetCurrentPackageFullNameFunc myGetCurrentPackageFullName = 
+        (GetCurrentPackageFullNameFunc)::GetProcAddress(::GetModuleHandle(L"kernel32"), "GetCurrentPackageFullName");
+
+    if (myGetCurrentPackageFullName)
+    {
 #if defined(HAS_APPMODEL)
+
     static const bool hasPackageIdentity = []() {
         UINT32 length = 0;
-        switch (const auto result = GetCurrentPackageFullName(&length, nullptr)) {
+        switch (const auto result = myGetCurrentPackageFullName(&length, nullptr)) {
         case ERROR_INSUFFICIENT_BUFFER:
             return true;
         case APPMODEL_ERROR_NO_PACKAGE:
@@ -61,6 +68,9 @@ bool qt_win_hasPackageIdentity()
 #else
     return false;
 #endif
+    }
+
+    return false;
 }
 
 QT_END_NAMESPACE
diff --git a/src/corelib/thread/qfutex_p.h b/src/corelib/thread/qfutex_p.h
index 8ba798f9209..f6a8dda6b81 100644
--- a/src/corelib/thread/qfutex_p.h
+++ b/src/corelib/thread/qfutex_p.h
@@ -40,8 +40,8 @@ QT_END_NAMESPACE
 #elif defined(Q_OS_LINUX) && !defined(QT_LINUXBASE)
 // use Linux mutexes everywhere except for LSB builds
 #  include "qfutex_linux_p.h"
-#elif defined(Q_OS_WIN)
-#  include "qfutex_win_p.h"
+//#elif defined(Q_OS_WIN)
+//#  include "qfutex_win_p.h"
 #else
 QT_BEGIN_NAMESPACE
 namespace QtFutex = QtDummyFutex;
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 1b8f76f1230..9e2fe83968c 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -915,6 +915,8 @@ QT_END_NAMESPACE
 // nothing
 #elif defined(Q_OS_DARWIN)
 #  include "qmutex_mac.cpp"
+#elif defined(Q_OS_WIN)
+#  include "qmutex_win.cpp"
 #else
 #  include "qmutex_unix.cpp"
 #endif
diff --git a/src/corelib/thread/qmutex_p.h b/src/corelib/thread/qmutex_p.h
index aabb66fa550..a16d5082154 100644
--- a/src/corelib/thread/qmutex_p.h
+++ b/src/corelib/thread/qmutex_p.h
@@ -86,6 +86,8 @@ public:
     semaphore_t mach_semaphore;
 #elif defined(Q_OS_UNIX)
     sem_t semaphore;
+#elif defined(Q_OS_WIN)
+    Qt::HANDLE event;
 #endif
 };
 
diff --git a/src/corelib/thread/qmutex_win.cpp b/src/corelib/thread/qmutex_win.cpp
new file mode 100644
index 00000000000..9186f89a341
--- /dev/null
+++ b/src/corelib/thread/qmutex_win.cpp
@@ -0,0 +1,30 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "qmutex.h"
+#include <qatomic.h>
+#include "qmutex_p.h"
+#include <qt_windows.h>
+
+QT_BEGIN_NAMESPACE
+
+QMutexPrivate::QMutexPrivate()
+{
+    event = CreateEvent(0, FALSE, FALSE, 0);
+    
+    if (!event)
+        qWarning("QMutexPrivate::QMutexPrivate: Cannot create event");
+}
+
+QMutexPrivate::~QMutexPrivate()
+{ CloseHandle(event); }
+
+bool QMutexPrivate::wait(QDeadlineTimer timeout)
+{
+    return (WaitForSingleObjectEx(event, timeout.isForever() ? INFINITE : timeout.remainingTime(), FALSE) == WAIT_OBJECT_0);
+}
+
+void QMutexPrivate::wakeUp() noexcept
+{ SetEvent(event); }
+
+QT_END_NAMESPACE
\ No newline at end of file
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 88ba6dc8f62..c544d972f68 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -227,6 +227,62 @@ DWORD WINAPI qt_adopted_thread_watcher_function(LPVOID)
     return 0;
 }
 
+#ifndef Q_OS_WIN64
+#  define ULONG_PTR DWORD
+#endif
+
+typedef struct tagTHREADNAME_INFO
+{
+    DWORD dwType;      // must be 0x1000
+    LPCSTR szName;     // pointer to name (in user addr space)
+    HANDLE dwThreadID; // thread ID (-1=caller thread)
+    DWORD dwFlags;     // reserved for future use, must be zero
+} THREADNAME_INFO;
+
+typedef HRESULT(WINAPI* SetThreadDescriptionFunc)(HANDLE, PCWSTR);
+
+#if defined(Q_CC_MSVC)
+
+// Helper function to set the thread name using RaiseException and __try
+static void setThreadNameUsingException(HANDLE threadId, LPCSTR threadName) {
+    THREADNAME_INFO info;
+    info.dwType = 0x1000;
+    info.szName = threadName;
+    info.dwThreadID = threadId;
+    info.dwFlags = 0;
+
+    __try {
+        RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD),
+                       reinterpret_cast<const ULONG_PTR*>(&info));
+    }
+    __except (EXCEPTION_CONTINUE_EXECUTION) {
+    }
+}
+
+#endif // Q_CC_MSVC
+
+void qt_set_thread_name(HANDLE threadId, const QString &name)
+{
+    HMODULE hKernel32 = GetModuleHandleW(L"Kernel32.dll");
+
+    SetThreadDescriptionFunc pSetThreadDescription = 
+        reinterpret_cast<SetThreadDescriptionFunc>(GetProcAddress(hKernel32, "SetThreadDescription"));
+    
+    if (pSetThreadDescription) {
+        pSetThreadDescription(threadId, reinterpret_cast<const wchar_t *>(name.utf16()) );
+    }
+    else {
+
+        #if defined(Q_CC_MSVC)
+
+            std::string stdStr = name.toStdString();
+            LPCSTR threadName = stdStr.c_str();
+            setThreadNameUsingException(threadId, threadName);
+
+        #endif // Q_CC_MSVC
+    }
+}
+
 /**************************************************************************
  ** QThreadPrivate
  *************************************************************************/
@@ -264,7 +320,7 @@ unsigned int __stdcall QT_ENSURE_STACK_ALIGNED_FOR_SSE QThreadPrivate::start(voi
     QString threadName = std::exchange(thr->d_func()->objectName, {});
     if (Q_LIKELY(threadName.isEmpty()))
         threadName = QString::fromUtf8(thr->metaObject()->className());
-    SetThreadDescription(GetCurrentThread(), reinterpret_cast<const wchar_t *>(threadName.utf16()));
+    qt_set_thread_name(GetCurrentThread(), threadName);
 
     emit thr->started(QThread::QPrivateSignal());
     QThread::setTerminationEnabled(true);
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 9e2e0c4e81c..eae05a0e61a 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -12,6 +12,8 @@
 
 #include <cstdio>
 
+#include <versionhelpers.h>
+
 QT_BEGIN_NAMESPACE
 
 using namespace Qt::StringLiterals;
@@ -184,13 +186,22 @@ inline Int aligned(Int v, Int byteAlign)
 
 static IDXGIFactory1 *createDXGIFactory2()
 {
+    typedef HRESULT(WINAPI* CreateDXGIFactory2Func) (UINT flags, REFIID riid, void** factory);
+    static CreateDXGIFactory2Func myCreateDXGIFactory2 =
+        (CreateDXGIFactory2Func)::GetProcAddress(::GetModuleHandle(L"dxgi"), "CreateDXGIFactory2");
+
     IDXGIFactory1 *result = nullptr;
-    const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&result));
-    if (FAILED(hr)) {
-        qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
-            qPrintable(QSystemError::windowsComString(hr)));
-        result = nullptr;
+
+    if (myCreateDXGIFactory2)
+    {
+        const HRESULT hr = myCreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&result));
+        if (FAILED(hr)) {
+            qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
+                qPrintable(QSystemError::windowsComString(hr)));
+            result = nullptr;
+        }
     }
+    
     return result;
 }
 
@@ -5103,6 +5114,15 @@ static const DXGI_FORMAT DEFAULT_SRGB_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
 
 bool QD3D11SwapChain::createOrResize()
 {
+    if (IsWindows10OrGreater())
+    {
+        // continue
+    }
+    else
+    {
+        return createOrResizeWin7();
+    }
+
     // Can be called multiple times due to window resizes - that is not the
     // same as a simple destroy+create (as with other resources). Just need to
     // resize the buffers then.
@@ -5427,4 +5447,9 @@ bool QD3D11SwapChain::createOrResize()
     return true;
 }
 
+bool QD3D11SwapChain::createOrResizeWin7()
+{
+    return false; // not implemented yet ;(
+}
+
 QT_END_NAMESPACE
diff --git a/src/gui/rhi/qrhid3d11_p.h b/src/gui/rhi/qrhid3d11_p.h
index 44ad7017d9f..7f232f1ae9c 100644
--- a/src/gui/rhi/qrhid3d11_p.h
+++ b/src/gui/rhi/qrhid3d11_p.h
@@ -596,6 +596,7 @@ struct QD3D11SwapChain : public QRhiSwapChain
 
     QRhiRenderPassDescriptor *newCompatibleRenderPassDescriptor() override;
     bool createOrResize() override;
+    bool createOrResizeWin7();
 
     void releaseBuffers();
     bool newColorBuffer(const QSize &size, DXGI_FORMAT format, DXGI_SAMPLE_DESC sampleDesc,
diff --git a/src/gui/rhi/qrhid3d12.cpp b/src/gui/rhi/qrhid3d12.cpp
index 0662c53ed65..1039914d57f 100644
--- a/src/gui/rhi/qrhid3d12.cpp
+++ b/src/gui/rhi/qrhid3d12.cpp
@@ -203,19 +203,35 @@ static inline QD3D12RenderTargetData *rtData(QRhiRenderTarget *rt)
 
 bool QRhiD3D12::create(QRhi::Flags flags)
 {
+    typedef HRESULT(WINAPI* CreateDXGIFactory2Func) (UINT flags, REFIID riid, void** factory);
+    typedef HRESULT(WINAPI* D3D12CreateDeviceFunc) (IUnknown *, D3D_FEATURE_LEVEL, REFIID, void **);
+    typedef HRESULT(WINAPI* D3D12GetDebugInterfaceFunc) (REFIID, void **);
+
+    static CreateDXGIFactory2Func myCreateDXGIFactory2 =
+        (CreateDXGIFactory2Func)::GetProcAddress(::GetModuleHandle(L"dxgi"), "CreateDXGIFactory2");
+
+    static D3D12CreateDeviceFunc myD3D12CreateDevice =
+        (D3D12CreateDeviceFunc)::GetProcAddress(::GetModuleHandle(L"D3d12"), "D3D12CreateDevice");
+
+    static D3D12GetDebugInterfaceFunc myD3D12GetDebugInterface =
+        (D3D12GetDebugInterfaceFunc)::GetProcAddress(::GetModuleHandle(L"D3d12"), "D3D12GetDebugInterface");
+
+    if (!myCreateDXGIFactory2 || !myD3D12CreateDevice || !myD3D12GetDebugInterface)
+        return false;
+
     rhiFlags = flags;
 
     UINT factoryFlags = 0;
     if (debugLayer)
         factoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
-    HRESULT hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
+    HRESULT hr = myCreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
     if (FAILED(hr)) {
         // retry without debug, if it was requested (to match D3D11 backend behavior)
         if (debugLayer) {
             qCDebug(QRHI_LOG_INFO, "Debug layer was requested but is not available. "
                                    "Attempting to create DXGIFactory2 without it.");
             factoryFlags &= ~DXGI_CREATE_FACTORY_DEBUG;
-            hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
+            hr = myCreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
         }
         if (SUCCEEDED(hr)) {
             debugLayer = false;
@@ -242,7 +258,7 @@ bool QRhiD3D12::create(QRhi::Flags flags)
 
     if (debugLayer) {
         ID3D12Debug1 *debug = nullptr;
-        if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
+        if (SUCCEEDED(myD3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
             qCDebug(QRHI_LOG_INFO, "Enabling D3D12 debug layer");
             debug->EnableDebugLayer();
             debug->Release();
@@ -310,7 +326,7 @@ bool QRhiD3D12::create(QRhi::Flags flags)
         if (minimumFeatureLevel == 0)
             minimumFeatureLevel = MIN_FEATURE_LEVEL;
 
-        hr = D3D12CreateDevice(activeAdapter,
+        hr = myD3D12CreateDevice(activeAdapter,
                                minimumFeatureLevel,
                                __uuidof(ID3D12Device2),
                                reinterpret_cast<void **>(&dev));
@@ -2762,6 +2778,9 @@ QD3D12Descriptor QD3D12SamplerManager::getShaderVisibleDescriptor(const D3D12_SA
     return descriptor;
 }
 
+typedef HRESULT(WINAPI* D3D12SerializeVersionedRootSignatureFunc) (const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *, ID3DBlob **, ID3DBlob **);
+D3D12SerializeVersionedRootSignatureFunc myD3D12SerializeVersionedRootSignature = nullptr;
+
 bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
 {
     this->rhiD = rhiD;
@@ -2807,8 +2826,15 @@ bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
     rsDesc.Desc_1_1.NumStaticSamplers = 1;
     rsDesc.Desc_1_1.pStaticSamplers = &samplerDesc;
 
+    if (!myD3D12SerializeVersionedRootSignature)
+        myD3D12SerializeVersionedRootSignature =
+        (D3D12SerializeVersionedRootSignatureFunc)::GetProcAddress(::GetModuleHandle(L"D3d12"), "D3D12SerializeVersionedRootSignature");
+
+    if (!myD3D12SerializeVersionedRootSignature)
+        return false;
+
     ID3DBlob *signature = nullptr;
-    HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
+    HRESULT hr = myD3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
     if (FAILED(hr)) {
         qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
         return false;
@@ -4219,7 +4245,7 @@ bool QD3D12Texture::prepareCreate(QSize *adjustedSize)
         else
             srvFormat = toD3DTextureFormat(m_readViewFormat.format, m_readViewFormat.srgb ? sRGB : Flags());
     }
-
+    
     mipLevelCount = uint(hasMipMaps ? rhiD->q->mipLevelsForSize(size) : 1);
     sampleDesc = rhiD->effectiveSampleDesc(m_sampleCount, dxgiFormat);
     if (sampleDesc.Count > 1) {
@@ -5001,6 +5027,9 @@ QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D1
 {
     QRHI_RES_RHI(QRhiD3D12);
 
+    if (!myD3D12SerializeVersionedRootSignature)
+        return {};
+
     // It's not just that the root signature has to be tied to the pipeline
     // (cannot just freely create it like e.g. with Vulkan where one just
     // creates a descriptor layout 1:1 with the QRhiShaderResourceBindings'
@@ -5085,7 +5114,7 @@ QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D1
     rsDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAGS(rsFlags);
 
     ID3DBlob *signature = nullptr;
-    HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
+    HRESULT hr = myD3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
     if (FAILED(hr)) {
         qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
         return {};
diff --git a/src/gui/text/windows/qwindowsfontdatabasebase.cpp b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
index 84e619b0d93..e751d4b1fb7 100644
--- a/src/gui/text/windows/qwindowsfontdatabasebase.cpp
+++ b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
@@ -715,7 +715,16 @@ QFont QWindowsFontDatabaseBase::systemDefaultFont()
     // Qt 6: Obtain default GUI font (typically "Segoe UI, 9pt", see QTBUG-58610)
     NONCLIENTMETRICS ncm = {};
     ncm.cbSize = sizeof(ncm);
-    SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI());
+
+    typedef BOOL (WINAPI *SystemParametersInfoForDpiFunc) (UINT, UINT, PVOID, UINT, UINT);
+    static SystemParametersInfoForDpiFunc mySystemParametersInfoForDpi = 
+        (SystemParametersInfoForDpiFunc)::GetProcAddress(::GetModuleHandle(L"user32"), "SystemParametersInfoForDpi");
+
+    if (mySystemParametersInfoForDpi)
+        mySystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0, defaultVerticalDPI());
+    else
+        SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize , &ncm, 0);
+
     const QFont systemFont = QWindowsFontDatabase::LOGFONT_to_QFont(ncm.lfMessageFont);
     qCDebug(lcQpaFonts) << __FUNCTION__ << systemFont;
     return systemFont;
diff --git a/src/network/kernel/qdnslookup_win.cpp b/src/network/kernel/qdnslookup_win.cpp
index 1b07776db9d..5410edab880 100644
--- a/src/network/kernel/qdnslookup_win.cpp
+++ b/src/network/kernel/qdnslookup_win.cpp
@@ -5,11 +5,9 @@
 #include <winsock2.h>
 #include "qdnslookup_p.h"
 
-#include <qendian.h>
+#include <qurl.h>
 #include <private/qnativesocketengine_p.h>
 #include <private/qsystemerror_p.h>
-#include <qurl.h>
-#include <qspan.h>
 
 #include <qt_windows.h>
 #include <windns.h>
@@ -65,100 +63,103 @@ DNS_STATUS WINAPI DnsQueryEx(PDNS_QUERY_REQUEST pQueryRequest,
 
 QT_BEGIN_NAMESPACE
 
-static DNS_STATUS sendAlternate(QDnsLookupRunnable *self, QDnsLookupReply *reply,
-                                PDNS_QUERY_REQUEST request, PDNS_QUERY_RESULT results)
-{
-    // WinDNS wants MTU - IP Header - UDP header for some reason, in spite
-    // of never needing that much
-    QVarLengthArray<unsigned char, 1472> query(1472);
-
-    auto dnsBuffer = new (query.data()) DNS_MESSAGE_BUFFER;
-    DWORD dnsBufferSize = query.size();
-    WORD xid = 0;
-    bool recursionDesired = true;
-
-    SetLastError(ERROR_SUCCESS);
-
-    // MinGW winheaders incorrectly declare the third parameter as LPWSTR
-    if (!DnsWriteQuestionToBuffer_W(dnsBuffer, &dnsBufferSize,
-                                    const_cast<LPWSTR>(request->QueryName), request->QueryType,
-                                    xid, recursionDesired)) {
-        // let's try reallocating
-        query.resize(dnsBufferSize);
-        if (!DnsWriteQuestionToBuffer_W(dnsBuffer, &dnsBufferSize,
-                                        const_cast<LPWSTR>(request->QueryName), request->QueryType,
-                                        xid, recursionDesired)) {
-            return GetLastError();
-        }
-    }
-
-    // set AD bit: we want to trust this server
-    dnsBuffer->MessageHead.AuthenticatedData = true;
-
-    QDnsLookupRunnable::ReplyBuffer replyBuffer;
-    if (!self->sendDnsOverTls(reply, { query.data(), qsizetype(dnsBufferSize) }, replyBuffer))
-        return DNS_STATUS(-1);   // error set in reply
-
-    // interpret the RCODE in the reply
-    auto response = reinterpret_cast<PDNS_MESSAGE_BUFFER>(replyBuffer.data());
-    DNS_HEADER *header = &response->MessageHead;
-    if (!header->IsResponse)
-        return DNS_ERROR_BAD_PACKET;        // not a reply
-
-    // Convert the byte order for the 16-bit quantities in the header, so
-    // DnsExtractRecordsFromMessage can parse the contents.
-    //header->Xid = qFromBigEndian(header->Xid);
-    header->QuestionCount = qFromBigEndian(header->QuestionCount);
-    header->AnswerCount = qFromBigEndian(header->AnswerCount);
-    header->NameServerCount = qFromBigEndian(header->NameServerCount);
-    header->AdditionalCount = qFromBigEndian(header->AdditionalCount);
-
-    results->QueryOptions = request->QueryOptions;
-    return DnsExtractRecordsFromMessage_W(response, replyBuffer.size(), &results->pQueryRecords);
-}
-
 void QDnsLookupRunnable::query(QDnsLookupReply *reply)
 {
-    // Perform DNS query.
-    alignas(DNS_ADDR_ARRAY) uchar dnsAddresses[sizeof(DNS_ADDR_ARRAY) + sizeof(DNS_ADDR)];
-    DNS_QUERY_REQUEST request = {};
-    request.Version = 1;
-    request.QueryName = reinterpret_cast<const wchar_t *>(requestName.constData());
-    request.QueryType = requestType;
-    request.QueryOptions = DNS_QUERY_STANDARD | DNS_QUERY_TREAT_AS_FQDN;
+    typedef BOOL (WINAPI *DnsQueryExFunc) (PDNS_QUERY_REQUEST, PDNS_QUERY_RESULT, PDNS_QUERY_CANCEL);
+    static DnsQueryExFunc myDnsQueryEx = 
+        (DnsQueryExFunc)::GetProcAddress(::GetModuleHandle(L"Dnsapi"), "DnsQueryEx");
+
+    PDNS_RECORD ptrStart = nullptr;
+
+    if (myDnsQueryEx)
+    {
+        // Perform DNS query.
+        alignas(DNS_ADDR_ARRAY) uchar dnsAddresses[sizeof(DNS_ADDR_ARRAY) + sizeof(DNS_ADDR)];
+        DNS_QUERY_REQUEST request = {};
+        request.Version = 1;
+        request.QueryName = reinterpret_cast<const wchar_t *>(requestName.constData());
+        request.QueryType = requestType;
+        request.QueryOptions = DNS_QUERY_STANDARD | DNS_QUERY_TREAT_AS_FQDN;
+
+        if (!nameserver.isNull()) {
+            memset(dnsAddresses, 0, sizeof(dnsAddresses));
+            request.pDnsServerList = new (dnsAddresses) DNS_ADDR_ARRAY;
+            auto addr = new (request.pDnsServerList->AddrArray) DNS_ADDR[1];
+            auto sa = new (addr[0].MaxSa) sockaddr;
+            request.pDnsServerList->MaxCount = sizeof(dnsAddresses);
+            request.pDnsServerList->AddrCount = 1;
+            // ### setting port 53 seems to cause some systems to fail
+            setSockaddr(sa, nameserver, port == DnsPort ? 0 : port);
+            request.pDnsServerList->Family = sa->sa_family;
+        }
 
-    if (protocol == QDnsLookup::Standard && !nameserver.isNull()) {
-        memset(dnsAddresses, 0, sizeof(dnsAddresses));
-        request.pDnsServerList = new (dnsAddresses) DNS_ADDR_ARRAY;
-        auto addr = new (request.pDnsServerList->AddrArray) DNS_ADDR[1];
-        auto sa = new (addr[0].MaxSa) sockaddr;
-        request.pDnsServerList->MaxCount = sizeof(dnsAddresses);
-        request.pDnsServerList->AddrCount = 1;
-        // ### setting port 53 seems to cause some systems to fail
-        setSockaddr(sa, nameserver, port == DnsPort ? 0 : port);
-        request.pDnsServerList->Family = sa->sa_family;
+        DNS_QUERY_RESULT results = {};
+        results.Version = 1;
+        const DNS_STATUS status = myDnsQueryEx(&request, &results, nullptr);
+        if (status >= DNS_ERROR_RCODE_FORMAT_ERROR && status <= DNS_ERROR_RCODE_LAST)
+            return reply->makeDnsRcodeError(status - DNS_ERROR_RCODE_FORMAT_ERROR + 1);
+        else if (status == ERROR_TIMEOUT)
+            return reply->makeTimeoutError();
+        else if (status != ERROR_SUCCESS)
+            return reply->makeResolverSystemError(status);
+
+        ptrStart = results.pQueryRecords;
     }
+    else
+    {
+        // Perform DNS query.
+        PDNS_RECORD dns_records = 0;
+        QByteArray requestNameUTF8 = requestName.toUtf8();
+        const QString requestNameUtf16 = QString::fromUtf8(requestNameUTF8.data(), requestNameUTF8.size());
+        IP4_ARRAY srvList;
+        memset(&srvList, 0, sizeof(IP4_ARRAY));
+        if (!nameserver.isNull()) {
+            if (nameserver.protocol() == QAbstractSocket::IPv4Protocol) {
+                // The below code is referenced from: http://support.microsoft.com/kb/831226
+                srvList.AddrCount = 1;
+                srvList.AddrArray[0] = htonl(nameserver.toIPv4Address());
+            } else if (nameserver.protocol() == QAbstractSocket::IPv6Protocol) {
+                // For supporting IPv6 nameserver addresses, we'll need to switch
+                // from DnsQuey() to DnsQueryEx() as it supports passing an IPv6
+                // address in the nameserver list
+                qWarning("%s", "IPv6 addresses for nameservers are currently not supported");
+                reply->error = QDnsLookup::ResolverError;
+                reply->errorString = tr("IPv6 addresses for nameservers are currently not supported");
+                return;
+            }
+        }
+        const DNS_STATUS status = DnsQuery_W(reinterpret_cast<const wchar_t*>(requestNameUtf16.utf16()), requestType, DNS_QUERY_STANDARD, &srvList, &dns_records, NULL);
+        switch (status) {
+        case ERROR_SUCCESS:
+            break;
+        case DNS_ERROR_RCODE_FORMAT_ERROR:
+            reply->error = QDnsLookup::InvalidRequestError;
+            reply->errorString = tr("Server could not process query");
+            return;
+        case DNS_ERROR_RCODE_SERVER_FAILURE:
+        case DNS_ERROR_RCODE_NOT_IMPLEMENTED:
+            reply->error = QDnsLookup::ServerFailureError;
+            reply->errorString = tr("Server failure");
+            return;
+        case DNS_ERROR_RCODE_NAME_ERROR:
+            reply->error = QDnsLookup::NotFoundError;
+            reply->errorString = tr("Non existent domain");
+            return;
+        case DNS_ERROR_RCODE_REFUSED:
+            reply->error = QDnsLookup::ServerRefusedError;
+            reply->errorString = tr("Server refused to answer");
+            return;
+        default:
+            reply->error = QDnsLookup::InvalidReplyError;
+            reply->errorString = QSystemError(status, QSystemError::NativeError).toString();
+            return;
+        }
 
-    DNS_QUERY_RESULT results = {};
-    results.Version = 1;
-    DNS_STATUS status = ERROR_INVALID_PARAMETER;
-    switch (protocol) {
-    case QDnsLookup::Standard:
-        status = DnsQueryEx(&request, &results, nullptr);
-        break;
-    case QDnsLookup::DnsOverTls:
-        status = sendAlternate(this, reply, &request, &results);
-        break;
+        ptrStart = dns_records;
     }
 
-    if (status == DNS_STATUS(-1))
-        return;     // error already set in reply
-    if (status >= DNS_ERROR_RCODE_FORMAT_ERROR && status <= DNS_ERROR_RCODE_LAST)
-        return reply->makeDnsRcodeError(status - DNS_ERROR_RCODE_FORMAT_ERROR + 1);
-    else if (status == ERROR_TIMEOUT)
-        return reply->makeTimeoutError();
-    else if (status != ERROR_SUCCESS)
-        return reply->makeResolverSystemError(status);
+    if (!ptrStart)
+        return;
 
     QStringView lastEncodedName;
     QString cachedDecodedName;
@@ -170,9 +171,9 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
     auto extractMaybeCachedHost = [&](QStringView name) -> const QString & {
         return lastEncodedName == name ? cachedDecodedName : extractAndCacheHost(name);
     };
-
+    
     // Extract results.
-    for (PDNS_RECORD ptr = results.pQueryRecords; ptr != NULL; ptr = ptr->pNext) {
+    for (PDNS_RECORD ptr = ptrStart; ptr != NULL; ptr = ptr->pNext) {
         // warning: always assign name to the record before calling extractXxxHost() again
         const QString &name = extractMaybeCachedHost(ptr->pName);
         if (ptr->wType == QDnsLookup::A) {
@@ -224,25 +225,6 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
             record.d->timeToLive = ptr->dwTtl;
             record.d->weight = ptr->Data.Srv.wWeight;
             reply->serviceRecords.append(record);
-        } else if (ptr->wType == QDnsLookup::TLSA) {
-            // Note: untested, because the DNS_RECORD reply appears to contain
-            // no records relating to TLSA. Maybe WinDNS filters them out of
-            // zones without DNSSEC.
-            QDnsTlsAssociationRecord record;
-            record.d->name = name;
-            record.d->timeToLive = ptr->dwTtl;
-
-            const auto &tlsa = ptr->Data.Tlsa;
-            const quint8 usage = tlsa.bCertUsage;
-            const quint8 selector = tlsa.bSelector;
-            const quint8 matchType = tlsa.bMatchingType;
-
-            record.d->usage = QDnsTlsAssociationRecord::CertificateUsage(usage);
-            record.d->selector = QDnsTlsAssociationRecord::Selector(selector);
-            record.d->matchType = QDnsTlsAssociationRecord::MatchingType(matchType);
-            record.d->value.assign(tlsa.bCertificateAssociationData,
-                                   tlsa.bCertificateAssociationData + tlsa.bCertificateAssociationDataLength);
-            reply->tlsAssociationRecords.append(std::move(record));
         } else if (ptr->wType == QDnsLookup::TXT) {
             QDnsTextRecord record;
             record.d->name = name;
@@ -254,7 +236,7 @@ void QDnsLookupRunnable::query(QDnsLookupReply *reply)
         }
     }
 
-    DnsRecordListFree(results.pQueryRecords, DnsFreeRecordList);
+    DnsRecordListFree(ptrStart, DnsFreeRecordList);
 }
 
 QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index 026e81cb0c7..3bbc974b744 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -58,43 +58,73 @@ public:
 } // namespace ABI
 #endif // HAS_UI_VIEW_SETTINGS
 
+// based on SDL approach
+// see SDL_windows_gaming_input.c, SDL_windows.c
+
+void * WIN_LoadComBaseFunction(const char *name)
+{
+    static bool s_bLoaded = false;
+    static HMODULE s_hComBase = NULL;
+   
+    if (!s_bLoaded) {
+       s_hComBase = ::LoadLibraryEx(L"combase.dll", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
+       s_bLoaded = true;
+    }
+    if (s_hComBase) {
+        return (void *) ::GetProcAddress(s_hComBase, name);
+    } else {
+        return NULL;
+    }
+}
+
 QT_BEGIN_NAMESPACE
 
 // Return tablet mode, note: Does not work for GetDesktopWindow().
 bool qt_windowsIsTabletMode(HWND hwnd)
 {
-    bool result = false;
-
-    const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
-    HSTRING_HEADER uiViewSettingsIdRefHeader;
-    HSTRING uiViewSettingsIdHs = nullptr;
-    const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
-    if (FAILED(WindowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
-        return false;
-
-    IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
-    // __uuidof(IUIViewSettingsInterop);
-    const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
-
-    HRESULT hr = RoGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
-                                                   reinterpret_cast<void **>(&uiViewSettingsInterop));
-    if (FAILED(hr))
-        return false;
-
-    //  __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings);
-    const GUID uiViewSettingsRefId = {0xc63657f6, 0x8850, 0x470d,{0x88, 0xf8, 0x45, 0x5e, 0x16, 0xea, 0x2c, 0x26}};
-    ABI::Windows::UI::ViewManagement::IUIViewSettings *viewSettings = nullptr;
-    hr = uiViewSettingsInterop->GetForWindow(hwnd, uiViewSettingsRefId,
-                                             reinterpret_cast<void **>(&viewSettings));
-    if (SUCCEEDED(hr)) {
-        ABI::Windows::UI::ViewManagement::UserInteractionMode currentMode;
-        hr = viewSettings->get_UserInteractionMode(&currentMode);
-        if (SUCCEEDED(hr))
-            result = currentMode == 1; // Touch, 1
-        viewSettings->Release();
+    typedef HRESULT (WINAPI *WindowsCreateStringReference_t)(PCWSTR sourceString, UINT32 length, HSTRING_HEADER *hstringHeader, HSTRING* string);
+    typedef HRESULT (WINAPI *RoGetActivationFactory_t)(HSTRING activatableClassId, REFIID iid, void** factory);
+
+    WindowsCreateStringReference_t WindowsCreateStringReferenceFunc = (WindowsCreateStringReference_t)WIN_LoadComBaseFunction("WindowsCreateStringReference");
+    RoGetActivationFactory_t RoGetActivationFactoryFunc = (RoGetActivationFactory_t)WIN_LoadComBaseFunction("RoGetActivationFactory");
+
+    if (WindowsCreateStringReferenceFunc && RoGetActivationFactoryFunc)
+    {
+        bool result = false;
+
+        const wchar_t uiViewSettingsId[] = L"Windows.UI.ViewManagement.UIViewSettings";
+        HSTRING_HEADER uiViewSettingsIdRefHeader;
+        HSTRING uiViewSettingsIdHs = nullptr;
+        const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
+        if (FAILED(WindowsCreateStringReferenceFunc(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader, &uiViewSettingsIdHs)))
+            return false;
+
+        IUIViewSettingsInterop *uiViewSettingsInterop = nullptr;
+        // __uuidof(IUIViewSettingsInterop);
+        const GUID uiViewSettingsInteropRefId = {0x3694dbf9, 0x8f68, 0x44be,{0x8f, 0xf5, 0x19, 0x5c, 0x98, 0xed, 0xe8, 0xa6}};
+
+        HRESULT hr = RoGetActivationFactoryFunc(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
+                                                       reinterpret_cast<void **>(&uiViewSettingsInterop));
+        if (FAILED(hr))
+            return false;
+
+        //  __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings);
+        const GUID uiViewSettingsRefId = {0xc63657f6, 0x8850, 0x470d,{0x88, 0xf8, 0x45, 0x5e, 0x16, 0xea, 0x2c, 0x26}};
+        ABI::Windows::UI::ViewManagement::IUIViewSettings *viewSettings = nullptr;
+        hr = uiViewSettingsInterop->GetForWindow(hwnd, uiViewSettingsRefId,
+                                                 reinterpret_cast<void **>(&viewSettings));
+        if (SUCCEEDED(hr)) {
+            ABI::Windows::UI::ViewManagement::UserInteractionMode currentMode;
+            hr = viewSettings->get_UserInteractionMode(&currentMode);
+            if (SUCCEEDED(hr))
+                result = currentMode == 1; // Touch, 1
+            viewSettings->Release();
+        }
+        uiViewSettingsInterop->Release();
+        return result;
     }
-    uiViewSettingsInterop->Release();
-    return result;
+
+    return false;
 }
 
-QT_END_NAMESPACE
+QT_END_NAMESPACE
\ No newline at end of file
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 88e9da5557c..7df58793707 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -43,6 +43,7 @@
 #include <QtCore/qsysinfo.h>
 #include <QtCore/qscopedpointer.h>
 #include <QtCore/quuid.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 #include <QtCore/private/qwinregistry_p.h>
 #if QT_CONFIG(cpp_winrt)
 #  include <QtCore/private/qfactorycacheregistration_p.h>
@@ -59,6 +60,8 @@
 #include <wtsapi32.h>
 #include <shellscalingapi.h>
 
+#include "vxkex.h"
+
 QT_BEGIN_NAMESPACE
 
 using namespace Qt::StringLiterals;
@@ -120,6 +123,77 @@ static inline bool sessionManagerInteractionBlocked()
 static inline bool sessionManagerInteractionBlocked() { return false; }
 #endif
 
+/*!
+    \class QWindowsUser32DLL
+    \brief Struct that contains dynamically resolved symbols of User32.dll.
+    The stub libraries shipped with the MinGW compiler miss some of the
+    functions. They need to be retrieved dynamically.
+    In addition, touch-related functions are available only from Windows onwards.
+    These need to resolved dynamically for Q_CC_MSVC as well.
+    \sa QWindowsShell32DLL
+    \internal
+*/
+
+void QWindowsUser32DLL::init()
+{
+    QSystemLibrary library(QStringLiteral("user32"));
+    setProcessDPIAware = (SetProcessDPIAware)library.resolve("SetProcessDPIAware");
+    setProcessDpiAwarenessContext = (SetProcessDpiAwarenessContext)library.resolve("SetProcessDpiAwarenessContext");
+    getThreadDpiAwarenessContext = (GetThreadDpiAwarenessContext)library.resolve("GetThreadDpiAwarenessContext");
+    isValidDpiAwarenessContext = (IsValidDpiAwarenessContext)library.resolve("IsValidDpiAwarenessContext");
+    areDpiAwarenessContextsEqual = (AreDpiAwarenessContextsEqual)library.resolve("AreDpiAwarenessContextsEqual");
+
+    addClipboardFormatListener = (AddClipboardFormatListener)library.resolve("AddClipboardFormatListener");
+    removeClipboardFormatListener = (RemoveClipboardFormatListener)library.resolve("RemoveClipboardFormatListener");
+
+    getDisplayAutoRotationPreferences = (GetDisplayAutoRotationPreferences)library.resolve("GetDisplayAutoRotationPreferences");
+    setDisplayAutoRotationPreferences = (SetDisplayAutoRotationPreferences)library.resolve("SetDisplayAutoRotationPreferences");
+
+    if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8) {
+        enableMouseInPointer = (EnableMouseInPointer)library.resolve("EnableMouseInPointer");
+        getPointerType = (GetPointerType)library.resolve("GetPointerType");
+        getPointerInfo = (GetPointerInfo)library.resolve("GetPointerInfo");
+        getPointerDeviceRects = (GetPointerDeviceRects)library.resolve("GetPointerDeviceRects");
+        getPointerTouchInfo = (GetPointerTouchInfo)library.resolve("GetPointerTouchInfo");
+        getPointerFrameTouchInfo = (GetPointerFrameTouchInfo)library.resolve("GetPointerFrameTouchInfo");
+        getPointerFrameTouchInfoHistory = (GetPointerFrameTouchInfoHistory)library.resolve("GetPointerFrameTouchInfoHistory");
+        getPointerPenInfo = (GetPointerPenInfo)library.resolve("GetPointerPenInfo");
+        getPointerPenInfoHistory = (GetPointerPenInfoHistory)library.resolve("GetPointerPenInfoHistory");
+        skipPointerFrameMessages = (SkipPointerFrameMessages)library.resolve("SkipPointerFrameMessages");
+    }
+    
+    if (QOperatingSystemVersion::current()
+        >= QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 14393)) {
+        adjustWindowRectExForDpi = (AdjustWindowRectExForDpi)library.resolve("AdjustWindowRectExForDpi");
+        enableNonClientDpiScaling = (EnableNonClientDpiScaling)library.resolve("EnableNonClientDpiScaling");
+        getWindowDpiAwarenessContext = (GetWindowDpiAwarenessContext)library.resolve("GetWindowDpiAwarenessContext");
+        getAwarenessFromDpiAwarenessContext = (GetAwarenessFromDpiAwarenessContext)library.resolve("GetAwarenessFromDpiAwarenessContext");
+        systemParametersInfoForDpi = (SystemParametersInfoForDpi)library.resolve("SystemParametersInfoForDpi");
+        getDpiForWindow = (GetDpiForWindow)library.resolve("GetDpiForWindow");
+        getSystemMetricsForDpi = (GetSystemMetricsForDpi)library.resolve("GetSystemMetricsForDpi");
+    }
+}
+
+bool QWindowsUser32DLL::supportsPointerApi()
+{
+    return enableMouseInPointer && getPointerType && getPointerInfo && getPointerDeviceRects
+            && getPointerTouchInfo && getPointerFrameTouchInfo && getPointerFrameTouchInfoHistory
+            && getPointerPenInfo && getPointerPenInfoHistory && skipPointerFrameMessages;
+}
+
+void QWindowsShcoreDLL::init()
+{
+    if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1)
+        return;
+    QSystemLibrary library(QStringLiteral("SHCore"));
+    getProcessDpiAwareness = (GetProcessDpiAwareness)library.resolve("GetProcessDpiAwareness");
+    setProcessDpiAwareness = (SetProcessDpiAwareness)library.resolve("SetProcessDpiAwareness");
+    getDpiForMonitor = (GetDpiForMonitor)library.resolve("GetDpiForMonitor");
+}
+
+QWindowsUser32DLL QWindowsContext::user32dll;
+QWindowsShcoreDLL QWindowsContext::shcoredll;
+
 QWindowsContext *QWindowsContext::m_instance = nullptr;
 
 /*!
@@ -160,6 +234,9 @@ bool QWindowsContextPrivate::m_v2DpiAware = false;
 QWindowsContextPrivate::QWindowsContextPrivate()
     : m_oleInitializeResult(OleInitialize(nullptr))
 {
+    QWindowsContext::user32dll.init();
+    QWindowsContext::shcoredll.init();
+    
     if (m_pointerHandler.touchDevice())
         m_systemInfo |= QWindowsContext::SI_SupportsTouch;
     m_displayContext = GetDC(nullptr);
@@ -338,19 +415,39 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
 [[nodiscard]] static inline QtWindows::DpiAwareness
     dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
 {
-    // IsValidDpiAwarenessContext() will handle the NULL pointer case.
-    if (!IsValidDpiAwarenessContext(context))
-        return QtWindows::DpiAwareness::Invalid;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
-        return QtWindows::DpiAwareness::Unaware_GdiScaled;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
-        return QtWindows::DpiAwareness::PerMonitorVersion2;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
-        return QtWindows::DpiAwareness::PerMonitor;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
-        return QtWindows::DpiAwareness::System;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
-        return QtWindows::DpiAwareness::Unaware;
+    if (QWindowsContext::user32dll.isValidDpiAwarenessContext && QWindowsContext::user32dll.areDpiAwarenessContextsEqual)
+    {
+        // IsValidDpiAwarenessContext() will handle the NULL pointer case.
+        if (!QWindowsContext::user32dll.isValidDpiAwarenessContext(context))
+            return QtWindows::DpiAwareness::Invalid;
+        if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
+            return QtWindows::DpiAwareness::Unaware_GdiScaled;
+        if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
+            return QtWindows::DpiAwareness::PerMonitorVersion2;
+        if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
+            return QtWindows::DpiAwareness::PerMonitor;
+        if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
+            return QtWindows::DpiAwareness::System;
+        if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
+            return QtWindows::DpiAwareness::Unaware;
+    }
+    else
+    {
+        // IsValidDpiAwarenessContext() will handle the NULL pointer case.
+        if (!vxkex::IsValidDpiAwarenessContext(context))
+            return QtWindows::DpiAwareness::Invalid;
+        if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
+            return QtWindows::DpiAwareness::Unaware_GdiScaled;
+        if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
+            return QtWindows::DpiAwareness::PerMonitorVersion2;
+        if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
+            return QtWindows::DpiAwareness::PerMonitor;
+        if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
+            return QtWindows::DpiAwareness::System;
+        if (vxkex::AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
+            return QtWindows::DpiAwareness::Unaware;
+    }
+    
     return QtWindows::DpiAwareness::Invalid;
 }
 
@@ -358,7 +455,11 @@ QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
 {
     if (!hwnd)
         return QtWindows::DpiAwareness::Invalid;
-    const auto context = GetWindowDpiAwarenessContext(hwnd);
+
+    const auto context = QWindowsContext::user32dll.getWindowDpiAwarenessContext ? 
+            QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd) :
+                vxkex::GetWindowDpiAwarenessContext(hwnd);
+
     return dpiAwarenessContextToQtDpiAwareness(context);
 }
 
@@ -371,7 +472,9 @@ QtWindows::DpiAwareness QWindowsContext::processDpiAwareness()
     // return the default DPI_AWARENESS_CONTEXT for the process if
     // SetThreadDpiAwarenessContext() was never called. So we can use
     // it as an equivalent.
-    const auto context = GetThreadDpiAwarenessContext();
+    const DPI_AWARENESS_CONTEXT context = QWindowsContext::user32dll.getThreadDpiAwarenessContext ? 
+        QWindowsContext::user32dll.getThreadDpiAwarenessContext() :
+            vxkex::GetThreadDpiAwarenessContext();
     return dpiAwarenessContextToQtDpiAwareness(context);
 }
 
@@ -431,11 +534,21 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
     if (processDpiAwareness() == dpiAwareness)
         return true;
     const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
-    if (!IsValidDpiAwarenessContext(context)) {
+
+    BOOL bResultIsValid = QWindowsContext::user32dll.isValidDpiAwarenessContext ? 
+            QWindowsContext::user32dll.isValidDpiAwarenessContext(context) : 
+                vxkex::IsValidDpiAwarenessContext(context);
+
+    if (!bResultIsValid) {
         qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
         return false;
     }
-    if (!SetProcessDpiAwarenessContext(context)) {
+
+    BOOL bResultSet = QWindowsContext::user32dll.setProcessDpiAwarenessContext ? 
+        QWindowsContext::user32dll.setProcessDpiAwarenessContext(context) : 
+            vxkex::SetProcessDpiAwarenessContext(context);
+
+    if (!bResultSet) {
         qCWarning(lcQpaWindow).noquote().nospace()
             << "SetProcessDpiAwarenessContext() failed: "
             << QSystemError::windowsString()
@@ -868,9 +981,9 @@ void QWindowsContext::forceNcCalcSize(HWND hwnd)
 bool QWindowsContext::systemParametersInfo(unsigned action, unsigned param, void *out,
                                            unsigned dpi)
 {
-    const BOOL result = dpi != 0
-        ? SystemParametersInfoForDpi(action, param, out, 0, dpi)
-        : SystemParametersInfo(action, param, out, 0);
+    const BOOL result = (QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0)
+        ? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
+        : vxkex::SystemParametersInfoForDpi(action, param, out, 0, dpi);
     return result == TRUE;
 }
 
@@ -957,7 +1070,10 @@ static bool enableNonClientDpiScaling(HWND hwnd)
 {
     bool result = false;
     if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
-        result = EnableNonClientDpiScaling(hwnd) != FALSE;
+        result = QWindowsContext::user32dll.enableNonClientDpiScaling ? 
+            (QWindowsContext::user32dll.enableNonClientDpiScaling(hwnd) != FALSE) : 
+                (vxkex::EnableNonClientDpiScaling(hwnd) != FALSE);
+
         if (!result) {
             const DWORD errorCode = GetLastError();
             qErrnoWarning(int(errorCode), "EnableNonClientDpiScaling() failed for HWND %p (%lu)",
diff --git a/src/plugins/platforms/windows/qwindowscontext.h b/src/plugins/platforms/windows/qwindowscontext.h
index 4e9be1af967..357f7839353 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -14,6 +14,7 @@
 #define STRICT_TYPED_ITEMIDS
 #include <shlobj.h>
 #include <shlwapi.h>
+#include <shellscalingapi.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -44,6 +45,95 @@ struct QWindowsContextPrivate;
 class QPoint;
 class QKeyEvent;
 class QPointingDevice;
+
+struct QWindowsUser32DLL
+{
+    inline void init();
+    inline bool supportsPointerApi();
+
+    typedef BOOL (WINAPI *EnableMouseInPointer)(BOOL);
+    typedef BOOL (WINAPI *GetPointerType)(UINT32, PVOID);
+    typedef BOOL (WINAPI *GetPointerInfo)(UINT32, PVOID);
+    typedef BOOL (WINAPI *GetPointerDeviceRects)(HANDLE, RECT *, RECT *);
+    typedef BOOL (WINAPI *GetPointerTouchInfo)(UINT32, PVOID);
+    typedef BOOL (WINAPI *GetPointerFrameTouchInfo)(UINT32, UINT32 *, PVOID);
+    typedef BOOL (WINAPI *GetPointerFrameTouchInfoHistory)(UINT32, UINT32 *, UINT32 *, PVOID);
+    typedef BOOL (WINAPI *GetPointerPenInfo)(UINT32, PVOID);
+    typedef BOOL (WINAPI *GetPointerPenInfoHistory)(UINT32, UINT32 *, PVOID);
+    typedef BOOL (WINAPI *SkipPointerFrameMessages)(UINT32);
+    typedef BOOL (WINAPI *SetProcessDPIAware)();
+    typedef BOOL (WINAPI *SetProcessDpiAwarenessContext)(HANDLE);
+    typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
+    typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
+    typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
+    typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
+    typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
+    typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
+    typedef DPI_AWARENESS_CONTEXT (WINAPI *GetWindowDpiAwarenessContext)(HWND);
+    typedef DPI_AWARENESS (WINAPI *GetAwarenessFromDpiAwarenessContext)(int);
+    typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
+    typedef int  (WINAPI *GetDpiForWindow)(HWND);
+    typedef BOOL (WINAPI *GetSystemMetricsForDpi)(INT, UINT);
+    typedef BOOL (WINAPI *AreDpiAwarenessContextsEqual)(DPI_AWARENESS_CONTEXT, DPI_AWARENESS_CONTEXT);
+    typedef DPI_AWARENESS_CONTEXT (WINAPI *GetThreadDpiAwarenessContext)();
+    typedef BOOL (WINAPI *IsValidDpiAwarenessContext)(DPI_AWARENESS_CONTEXT);
+    
+    // Windows pointer functions (Windows 8 or later).
+    EnableMouseInPointer enableMouseInPointer = nullptr;
+    GetPointerType getPointerType = nullptr;
+    GetPointerInfo getPointerInfo = nullptr;
+    GetPointerDeviceRects getPointerDeviceRects = nullptr;
+    GetPointerTouchInfo getPointerTouchInfo = nullptr;
+    GetPointerFrameTouchInfo getPointerFrameTouchInfo = nullptr;
+    GetPointerFrameTouchInfoHistory getPointerFrameTouchInfoHistory = nullptr;
+    GetPointerPenInfo getPointerPenInfo = nullptr;
+    GetPointerPenInfoHistory getPointerPenInfoHistory = nullptr;
+    SkipPointerFrameMessages skipPointerFrameMessages = nullptr;
+
+    // Windows Vista onwards
+    SetProcessDPIAware setProcessDPIAware = nullptr;
+
+    // Windows 10 version 1607 onwards
+    GetDpiForWindow getDpiForWindow = nullptr;
+    GetThreadDpiAwarenessContext getThreadDpiAwarenessContext = nullptr;
+    IsValidDpiAwarenessContext isValidDpiAwarenessContext = nullptr;
+
+    // Windows 10 version 1703 onwards
+    SetProcessDpiAwarenessContext setProcessDpiAwarenessContext = nullptr;
+    AreDpiAwarenessContextsEqual areDpiAwarenessContextsEqual = nullptr;
+
+    // Clipboard listeners are present on Windows Vista onwards
+    // but missing in MinGW 4.9 stub libs. Can be removed in MinGW 5.
+    AddClipboardFormatListener addClipboardFormatListener = nullptr;
+    RemoveClipboardFormatListener removeClipboardFormatListener = nullptr;
+
+    // Rotation API
+    GetDisplayAutoRotationPreferences getDisplayAutoRotationPreferences = nullptr;
+    SetDisplayAutoRotationPreferences setDisplayAutoRotationPreferences = nullptr;
+
+    AdjustWindowRectExForDpi adjustWindowRectExForDpi = nullptr;
+    EnableNonClientDpiScaling enableNonClientDpiScaling = nullptr;
+    GetWindowDpiAwarenessContext getWindowDpiAwarenessContext = nullptr;
+    GetAwarenessFromDpiAwarenessContext getAwarenessFromDpiAwarenessContext = nullptr;
+    SystemParametersInfoForDpi systemParametersInfoForDpi = nullptr;
+    GetSystemMetricsForDpi getSystemMetricsForDpi = nullptr;
+};
+
+// Shell scaling library (Windows 8.1 onwards)
+struct QWindowsShcoreDLL
+{
+    void init();
+    inline bool isValid() const { return getProcessDpiAwareness && setProcessDpiAwareness && getDpiForMonitor; }
+
+    typedef HRESULT (WINAPI *GetProcessDpiAwareness)(HANDLE,PROCESS_DPI_AWARENESS *);
+    typedef HRESULT (WINAPI *SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
+    typedef HRESULT (WINAPI *GetDpiForMonitor)(HMONITOR,int,UINT *,UINT *);
+
+    GetProcessDpiAwareness getProcessDpiAwareness = nullptr;
+    SetProcessDpiAwareness setProcessDpiAwareness = nullptr;
+    GetDpiForMonitor getDpiForMonitor = nullptr;
+};
+
 class QWindowsContext
 {
     Q_DISABLE_COPY_MOVE(QWindowsContext)
@@ -134,6 +224,9 @@ public:
     QWindowsScreenManager &screenManager();
     QWindowsTabletSupport *tabletSupport() const;
 
+    static QWindowsUser32DLL user32dll;
+    static QWindowsShcoreDLL shcoredll;
+
     bool asyncExpose() const;
     void setAsyncExpose(bool value);
 
diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp
index 5d3a47c22fd..563b22a831f 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -33,6 +33,8 @@
 
 #include <shlobj.h>
 
+#include "vxkex.h"
+
 QT_BEGIN_NAMESPACE
 
 /*!
@@ -674,7 +676,11 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
                 const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
 
                 POINTER_INFO pointerInfo{};
-                if (!GetPointerInfo(pointerId, &pointerInfo))
+                BOOL bResultPointerInfo = QWindowsContext::user32dll.getPointerInfo ? 
+                    QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo) : 
+                        vxkex::GetPointerInfo(pointerId, &pointerInfo);
+
+                if (!bResultPointerInfo)
                     return E_FAIL;
 
                 if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp
index a9fcf711edd..3a08bd35363 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.cpp
+++ b/src/plugins/platforms/windows/qwindowsintegration.cpp
@@ -140,6 +140,7 @@ static inline unsigned parseOptions(const QStringList &paramList,
                                     DarkModeHandling *darkModeHandling)
 {
     unsigned options = 0;
+
     for (const QString &param : paramList) {
         if (param.startsWith(u"fontengine=")) {
             if (param.endsWith(u"gdi")) {
@@ -485,7 +486,14 @@ QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const
         else
 #endif // QT_NO_FREETYPE
 #if QT_CONFIG(directwrite3)
-        if (!(d->m_options & (QWindowsIntegration::FontDatabaseGDI | QWindowsIntegration::DontUseDirectWriteFonts)))
+
+        /* IDWriteFontFace3 is only reportedly available starting with Windows 10. This change is necessary starting
+        with Qt 6.8, where DirectWrite is used by default to populate the font database. 
+        More info: https://github.com/videolan/vlc/blob/master/contrib/src/qt/0001-Use-DirectWrite-font-database-only-with-Windows-10-a.patch
+        */
+
+        if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10 &&
+            !(d->m_options & (QWindowsIntegration::FontDatabaseGDI | QWindowsIntegration::DontUseDirectWriteFonts)))
             d->m_fontDatabase = new QWindowsDirectWriteFontDatabase;
         else
 #endif
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 5b8e4e58ffe..5c84b47794e 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -17,6 +17,8 @@
 #include <QtCore/private/qdebug_p.h>
 #include <QtCore/private/qtools_p.h>
 
+#include "vxkex.h"
+
 #if defined(WM_APPCOMMAND)
 #  ifndef FAPPCOMMAND_MOUSE
 #    define FAPPCOMMAND_MOUSE 0x8000
@@ -732,14 +734,17 @@ static inline QString messageKeyText(const MSG &msg)
 
 [[nodiscard]] static inline int getTitleBarHeight(const HWND hwnd)
 {
-    const UINT dpi = GetDpiForWindow(hwnd);
-    const int captionHeight = GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
+    const BOOL bNewAPI = (QWindowsContext::user32dll.getSystemMetricsForDpi != nullptr);
+    const UINT dpi = bNewAPI ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
+    const int captionHeight = bNewAPI ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi) : vxkex::GetSystemMetricsForDpi(SM_CYCAPTION, dpi);
     if (IsZoomed(hwnd))
         return captionHeight;
     // The frame height should also be taken into account if the window
     // is not maximized.
-    const int frameHeight = GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
-                            + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+    const int frameHeight = bNewAPI ? 
+        (QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi))
+        : (vxkex::GetSystemMetricsForDpi(SM_CYSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi));
+
     return captionHeight + frameHeight;
 }
 
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 7995716444a..fab22b394ab 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -26,6 +26,8 @@
 
 #include <windowsx.h>
 
+#include "vxkex.h"
+
 QT_BEGIN_NAMESPACE
 
 enum {
@@ -55,7 +57,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
     *result = 0;
     const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
 
-    if (!GetPointerType(pointerId, &m_pointerType)) {
+    BOOL bResultPt = QWindowsContext::user32dll.getPointerType ? 
+        QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType) : 
+            vxkex::GetPointerType(pointerId, &m_pointerType);
+
+    if (!bResultPt) {
         qWarning() << "GetPointerType() failed:" << qt_error_string();
         return false;
     }
@@ -69,12 +75,21 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
     }
     case QT_PT_TOUCH: {
         quint32 pointerCount = 0;
-        if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
+        BOOL bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ? 
+            QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr) : 
+                vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr);
+
+        if (!bResultPointerTouchInfo) {
             qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
             return false;
         }
         QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
-        if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
+
+        bResultPointerTouchInfo = QWindowsContext::user32dll.getPointerFrameTouchInfo ? 
+            QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data()) : 
+                vxkex::GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data());
+
+        if (!bResultPointerTouchInfo) {
             qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
             return false;
         }
@@ -87,10 +102,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
         // dispatch any skipped frames if event compression is disabled by the app
         if (historyCount > 1 && !QCoreApplication::testAttribute(Qt::AA_CompressHighFrequencyEvents)) {
             touchInfo.resize(pointerCount * historyCount);
-            if (!GetPointerFrameTouchInfoHistory(pointerId,
-                                                 &historyCount,
-                                                 &pointerCount,
-                                                 touchInfo.data())) {
+
+            BOOL bResultTouchHistory = QWindowsContext::user32dll.getPointerFrameTouchInfoHistory ?
+                QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data()) :
+                    vxkex::GetPointerFrameTouchInfoHistory(pointerId, &historyCount, &pointerCount, touchInfo.data());
+
+            if (!bResultTouchHistory) {
                 qWarning() << "GetPointerFrameTouchInfoHistory() failed:" << qt_error_string();
                 return false;
             }
@@ -108,7 +125,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
     }
     case QT_PT_PEN: {
         POINTER_PEN_INFO penInfo;
-        if (!GetPointerPenInfo(pointerId, &penInfo)) {
+
+        BOOL bResultPenInfo = QWindowsContext::user32dll.getPointerPenInfo ? 
+            QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo) : vxkex::GetPointerPenInfo(pointerId, &penInfo);
+
+        if (!bResultPenInfo) {
             qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
             return false;
         }
@@ -120,7 +141,11 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
                 || !QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents))) {
             QVarLengthArray<POINTER_PEN_INFO, 10> penInfoHistory(historyCount);
 
-            if (!GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
+            BOOL bResultPenInfoHistory = QWindowsContext::user32dll.getPointerPenInfoHistory ?
+                QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data()) : 
+                    vxkex::GetPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data());
+
+            if (!bResultPenInfoHistory) {
                 qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
                 return false;
             }
@@ -527,7 +552,10 @@ bool QWindowsPointerHandler::translateTouchEvent(QWindow *window, HWND hwnd,
         inputIds.insert(touchPoint.id);
 
         // Avoid getting repeated messages for this frame if there are multiple pointerIds
-        SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
+        if (QWindowsContext::user32dll.skipPointerFrameMessages)
+            QWindowsContext::user32dll.skipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
+        else
+            vxkex::SkipPointerFrameMessages(touchInfo[i].pointerInfo.pointerId);
     }
 
     // Some devices send touches for each finger in a different message/frame, instead of consolidating
@@ -574,7 +602,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
     auto *penInfo = static_cast<POINTER_PEN_INFO *>(vPenInfo);
 
     RECT pRect, dRect;
-    if (!GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
+
+    BOOL bResultDeviceRects = QWindowsContext::user32dll.getPointerDeviceRects ? 
+        QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect) : 
+            vxkex::GetPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect);
+
+    if (!bResultDeviceRects)
         return false;
 
     const auto systemId = (qint64)penInfo->pointerInfo.sourceDevice;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index 6c86c47caac..24588473185 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -32,6 +32,8 @@
 #include <setupapi.h>
 #include <shellscalingapi.h>
 
+#include "vxkex.h"
+
 QT_BEGIN_NAMESPACE
 
 using namespace Qt::StringLiterals;
@@ -45,7 +47,15 @@ static inline QDpi monitorDPI(HMONITOR hMonitor)
 {
     UINT dpiX;
     UINT dpiY;
-    if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
+
+    HRESULT hr = S_OK;
+
+    if (QWindowsContext::shcoredll.isValid())
+        hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
+    else
+        hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
+
+    if (SUCCEEDED(hr))
         return QDpi(dpiX, dpiY);
     return {0, 0};
 }
@@ -609,7 +619,10 @@ bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
         orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
         break;
     }
-    result = SetDisplayAutoRotationPreferences(orientationPreference);
+    if (QWindowsContext::user32dll.setDisplayAutoRotationPreferences)
+        result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences(orientationPreference);
+    else
+        result = vxkex::SetDisplayAutoRotationPreferences(orientationPreference);
     return result;
 }
 
@@ -617,7 +630,15 @@ Qt::ScreenOrientation QWindowsScreen::orientationPreference()
 {
     Qt::ScreenOrientation result = Qt::PrimaryOrientation;
     ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
-    if (GetDisplayAutoRotationPreferences(&orientationPreference)) {
+
+    BOOL bResult = TRUE;
+    
+    if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences)
+        bResult = QWindowsContext::user32dll.getDisplayAutoRotationPreferences((DWORD *)&orientationPreference);
+    else
+        bResult = vxkex::GetDisplayAutoRotationPreferences(&orientationPreference);
+
+    if (bResult) {
         switch (orientationPreference) {
         case ORIENTATION_PREFERENCE_NONE:
             break;
diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp
index 97b2dd339be..2d6dbf36adc 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -45,6 +45,8 @@
 
 #include <algorithm>
 
+#include "vxkex.h"
+
 #if QT_CONFIG(cpp_winrt)
 #   include <QtCore/private/qt_winrtbase_p.h>
 
@@ -97,36 +99,52 @@ static constexpr QColor getSysColor(winrt::Windows::UI::Color &&color)
 
 [[maybe_unused]] [[nodiscard]] static inline QColor qt_accentColor(AccentColorLevel level)
 {
+    QColor accent;
+    QColor accentLight;
+    QColor accentLighter;
+    QColor accentLightest;
+    QColor accentDark;
+    QColor accentDarker;
+    QColor accentDarkest;
+
 #if QT_CONFIG(cpp_winrt)
-    using namespace winrt::Windows::UI::ViewManagement;
-    const auto settings = UISettings();
-    const QColor accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
-    const QColor accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
-    const QColor accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
-    const QColor accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
-    const QColor accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
-    const QColor accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
-    const QColor accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
-#else
-    const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
-    if (!registry.isValid())
-        return {};
-    const QVariant value = registry.value(L"AccentColor");
-    if (!value.isValid())
-        return {};
-    // The retrieved value is in the #AABBGGRR format, we need to
-    // convert it to the #AARRGGBB format which Qt expects.
-    const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
-    if (!abgr.isValid())
-        return {};
-    const QColor accent = QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
-    const QColor accentLight = accent.lighter(120);
-    const QColor accentLighter = accentLight.lighter(120);
-    const QColor accentLightest = accentLighter.lighter(120);
-    const QColor accentDark = accent.darker(120);
-    const QColor accentDarker = accentDark.darker(120);
-    const QColor accentDarkest = accentDarker.darker(120);
+    if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
+    {
+        using namespace winrt::Windows::UI::ViewManagement;
+        const auto settings = UISettings();
+        accent = getSysColor(settings.GetColorValue(UIColorType::Accent));
+        accentLight = getSysColor(settings.GetColorValue(UIColorType::AccentLight1));
+        accentLighter = getSysColor(settings.GetColorValue(UIColorType::AccentLight2));
+        accentLightest = getSysColor(settings.GetColorValue(UIColorType::AccentLight3));
+        accentDark = getSysColor(settings.GetColorValue(UIColorType::AccentDark1));
+        accentDarker = getSysColor(settings.GetColorValue(UIColorType::AccentDark2));
+        accentDarkest = getSysColor(settings.GetColorValue(UIColorType::AccentDark3));
+    }
 #endif
+
+    if (!accent.isValid())
+    {
+        const QWinRegistryKey registry(HKEY_CURRENT_USER, LR"(Software\Microsoft\Windows\DWM)");
+        if (!registry.isValid())
+            return {};
+        const QVariant value = registry.value(L"AccentColor");
+        if (!value.isValid())
+            return {};
+        // The retrieved value is in the #AABBGGRR format, we need to
+        // convert it to the #AARRGGBB format which Qt expects.
+        const QColor abgr = QColor::fromRgba(qvariant_cast<DWORD>(value));
+        if (!abgr.isValid())
+            return {};
+        accent = QColor::fromRgb(abgr.blue(), abgr.green(), abgr.red(), abgr.alpha());
+        accentLight = accent.lighter(120);
+        accentLighter = accentLight.lighter(120);
+        accentLightest = accentLighter.lighter(120);
+        accentDarkest = accent.darker(120 * 120 * 120);
+        accentDark = accent.darker(120);
+        accentDarker = accentDark.darker(120);
+        accentDarkest = accentDarker.darker(120);
+    }
+
     switch (level) {
     case AccentColorDarkest:
         return accentDarkest;
@@ -154,6 +172,7 @@ static inline QColor getSysColor(int index)
 // QTBUG-48823/Windows 10: SHGetFileInfo() (as called by item views on file system
 // models has been observed to trigger a WM_PAINT on the mainwindow. Suppress the
 // behavior by running it in a thread.
+
 class QShGetFileInfoThread : public QThread
 {
 public:
@@ -326,46 +345,45 @@ void QWindowsTheme::populateLightSystemBasePalette(QPalette &result)
 
 void QWindowsTheme::populateDarkSystemBasePalette(QPalette &result)
 {
-    QColor foreground, background,
-           accent, accentDark, accentDarker, accentDarkest,
-           accentLight, accentLighter, accentLightest;
+    QColor foreground = Qt::white;
+    QColor background = QColor(0x1E, 0x1E, 0x1E);
+    QColor accent = qt_accentColor(AccentColorNormal);
+    QColor accentDark = accent.darker(120);
+    QColor accentDarker = accentDark.darker(120);
+    QColor accentDarkest = accentDarker.darker(120);
+    QColor accentLight = accent.lighter(120);
+    QColor accentLighter = accentLight.lighter(120);
+    QColor accentLightest = accentLighter.lighter(120);
+
 #if QT_CONFIG(cpp_winrt)
-    using namespace winrt::Windows::UI::ViewManagement;
-    const auto settings = UISettings();
-
-    // We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
-    // returns the old system colors, not the dark mode colors. If the background is black (which it
-    // usually), then override it with a dark gray instead so that we can go up and down the lightness.
-    if (QWindowsTheme::queryColorScheme() == Qt::ColorScheme::Dark) {
-        // the system is actually running in dark mode, so UISettings will give us dark colors
-        foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
-        background = [&settings]() -> QColor {
-            auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
-            if (systemBackground == Qt::black)
-                systemBackground = QColor(0x1E, 0x1E, 0x1E);
-            return systemBackground;
-        }();
-        accent = qt_accentColor(AccentColorNormal);
-        accentDark = qt_accentColor(AccentColorDark);
-        accentDarker = qt_accentColor(AccentColorDarker);
-        accentDarkest = qt_accentColor(AccentColorDarkest);
-        accentLight = qt_accentColor(AccentColorLight);
-        accentLighter = qt_accentColor(AccentColorLighter);
-        accentLightest = qt_accentColor(AccentColorLightest);
-    } else
-#endif
+    if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
     {
-        // If the system is running in light mode, then we need to make up our own dark palette
-        foreground = Qt::white;
-        background = QColor(0x1E, 0x1E, 0x1E);
-        accent = qt_accentColor(AccentColorNormal);
-        accentDark = accent.darker(120);
-        accentDarker = accentDark.darker(120);
-        accentDarkest = accentDarker.darker(120);
-        accentLight = accent.lighter(120);
-        accentLighter = accentLight.lighter(120);
-        accentLightest = accentLighter.lighter(120);
+        using namespace winrt::Windows::UI::ViewManagement;
+        const auto settings = UISettings();
+
+        // We have to craft a palette from these colors. The settings.UIElementColor(UIElementType) API
+        // returns the old system colors, not the dark mode colors. If the background is black (which it
+        // usually), then override it with a dark gray instead so that we can go up and down the lightness.
+        if (QWindowsTheme::queryColorScheme() == Qt::ColorScheme::Dark) {
+            // the system is actually running in dark mode, so UISettings will give us dark colors
+            foreground = getSysColor(settings.GetColorValue(UIColorType::Foreground));
+            background = [&settings]() -> QColor {
+                auto systemBackground = getSysColor(settings.GetColorValue(UIColorType::Background));
+                if (systemBackground == Qt::black)
+                    systemBackground = QColor(0x1E, 0x1E, 0x1E);
+                return systemBackground;
+            }();
+            accent = qt_accentColor(AccentColorNormal);
+            accentDark = qt_accentColor(AccentColorDark);
+            accentDarker = qt_accentColor(AccentColorDarker);
+            accentDarkest = qt_accentColor(AccentColorDarkest);
+            accentLight = qt_accentColor(AccentColorLight);
+            accentLighter = qt_accentColor(AccentColorLighter);
+            accentLightest = qt_accentColor(AccentColorLightest);
+        }
     }
+#endif
+
     const QColor linkColor = accentLightest;
     const QColor buttonColor = background.lighter(200);
 
@@ -738,7 +756,10 @@ void QWindowsTheme::refreshFonts()
     fixedFont.setStyleHint(QFont::TypeWriter);
 
     LOGFONT lfIconTitleFont;
-    SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
+    if (QWindowsContext::user32dll.systemParametersInfoForDpi)
+        QWindowsContext::user32dll.systemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
+    else
+        vxkex::SystemParametersInfoForDpi(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0, dpi);
     const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
 
     m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
@@ -1001,6 +1022,7 @@ public:
 static QPixmap pixmapFromShellImageList(int iImageList, int iIcon)
 {
     QPixmap result;
+
     // For MinGW:
     static const IID iID_IImageList = {0x46eb5926, 0x582e, 0x4017, {0x9f, 0xdf, 0xe8, 0x99, 0x8d, 0xaa, 0x9, 0x50}};
 
@@ -1015,6 +1037,7 @@ static QPixmap pixmapFromShellImageList(int iImageList, int iIcon)
         DestroyIcon(hIcon);
     }
     imageList->Release();
+
     return result;
 }
 
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index f44a28f5636..6d6409c7878 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -46,6 +46,8 @@
 
 #include <shellscalingapi.h>
 
+#include "vxkex.h"
+
 QT_BEGIN_NAMESPACE
 
 using QWindowCreationContextPtr = QSharedPointer<QWindowCreationContext>;
@@ -522,11 +524,15 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
 
 [[nodiscard]] static inline int getResizeBorderThickness(const UINT dpi)
 {
-    // The width of the padded border will always be 0 if DWM composition is
-    // disabled, but since it will always be enabled and can't be programtically
-    // disabled from Windows 8, we are safe to go.
-    return GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
-           + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+    if (QWindowsContext::user32dll.getSystemMetricsForDpi) {
+        // The width of the padded border will always be 0 if DWM composition is
+        // disabled, but since it will always be enabled and can't be programtically
+        // disabled from Windows 8, we are safe to go.
+        return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
+               + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+    }
+    else
+        return vxkex::GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
 }
 
 /*!
@@ -538,11 +544,21 @@ static QMargins invisibleMargins(QPoint screenPoint)
 {
     POINT pt = {screenPoint.x(), screenPoint.y()};
     if (HMONITOR hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONULL)) {
-        UINT dpiX;
-        UINT dpiY;
-        if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
-            const int gap = getResizeBorderThickness(dpiX);
-            return QMargins(gap, 0, gap, gap);
+        if (QWindowsContext::shcoredll.isValid()) {
+            UINT dpiX;
+            UINT dpiY;
+
+            HRESULT hr = S_OK;
+
+            if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows10)
+                hr = QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
+            else
+                hr = vxkex::GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
+
+            if (SUCCEEDED(hr)) {
+                const int gap = getResizeBorderThickness(dpiX);
+                return QMargins(gap, 0, gap, gap);
+            }
         }
     }
     return QMargins();
@@ -550,7 +566,8 @@ static QMargins invisibleMargins(QPoint screenPoint)
 
 [[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
 {
-    const UINT dpi = GetDpiForWindow(hwnd);
+    const UINT dpi = (QWindowsContext::user32dll.getDpiForWindow) ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
+
     const int gap = getResizeBorderThickness(dpi);
     return QMargins(gap, 0, gap, gap);
 }
@@ -851,7 +868,7 @@ static inline bool shouldApplyDarkFrame(const QWindow *w)
 {
     if (!w->isTopLevel() || w->flags().testFlag(Qt::FramelessWindowHint))
         return false;
-
+    
     // the user of the application has explicitly opted out of dark frames
     if (!QWindowsIntegration::instance()->darkModeHandling().testFlag(QWindowsApplication::DarkModeWindowFrames))
         return false;
@@ -1071,9 +1088,17 @@ QMargins QWindowsGeometryHint::frame(const QWindow *w, DWORD style, DWORD exStyl
         return {};
     RECT rect = {0,0,0,0};
     style &= ~DWORD(WS_OVERLAPPED); // Not permitted, see docs.
-    if (AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) {
-        qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
+    if (QWindowsContext::user32dll.adjustWindowRectExForDpi)
+    {
+        if (QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) 
+            qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
+    }
+    else
+    {
+        if (vxkex::AdjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi))) == FALSE) 
+            qErrnoWarning("%s: vxkex::AdjustWindowRectExForDpi failed", __FUNCTION__);
     }
+
     const QMargins result(qAbs(rect.left), qAbs(rect.top),
                           qAbs(rect.right), qAbs(rect.bottom));
     qCDebug(lcQpaWindow).nospace() << __FUNCTION__ << " style="
@@ -1380,7 +1405,7 @@ void QWindowsForeignWindow::setParent(const QPlatformWindow *newParentWindow)
     qCDebug(lcQpaWindow) << __FUNCTION__ << window() << "newParent="
         << newParentWindow << newParent << "oldStyle=" << debugWinStyle(oldStyle);
 
-    auto updateWindowFlags = [&] {
+    auto updateWindowFlags = [&]{
         // Top level window flags need to be set/cleared manually.
         DWORD newStyle = oldStyle;
         if (isTopLevel) {
@@ -1588,7 +1613,8 @@ void QWindowsWindow::initialize()
             QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
         }
     }
-    QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
+    QWindowsWindow::setSavedDpi(QWindowsContext::user32dll.getDpiForWindow ?
+        QWindowsContext::user32dll.getDpiForWindow(handle()) : vxkex::GetDpiForWindow(handle()));
 }
 
 QSurfaceFormat QWindowsWindow::format() const
@@ -2083,7 +2109,7 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
 
 void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
 {
-    const UINT dpi = GetDpiForWindow(hwnd);
+    const UINT dpi = QWindowsContext::user32dll.getDpiForWindow ? QWindowsContext::user32dll.getDpiForWindow(hwnd) : vxkex::GetDpiForWindow(hwnd);
     const qreal scale = dpiRelativeScale(dpi);
     setSavedDpi(dpi);
 
@@ -2177,6 +2203,7 @@ void QWindowsWindow::setGeometry(const QRect &rectIn)
     }
     if (m_windowState & Qt::WindowMinimized)
         m_data.geometry = rect; // Otherwise set by handleGeometryChange() triggered by event.
+
     if (m_data.hwnd) {
         // A ResizeEvent with resulting geometry will be sent. If we cannot
         // achieve that size (for example, window title minimal constraint),
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index 638d684ce4f..1c89fd87ede 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -15,6 +15,8 @@
 #include <QtGui/private/qguiapplication_p.h>
 #include <QtCore/qt_windows.h>
 #include <qpa/qplatformintegration.h>
+#include "qwindowsuiawrapper_p.h"
+#include "qwindowsuiawrapper.cpp"
 
 #include <QtCore/private/qwinregistry_p.h>
 
@@ -47,7 +49,7 @@ bool QWindowsUiaAccessibility::handleWmGetObject(HWND hwnd, WPARAM wParam, LPARA
     if (QWindow *window = QWindowsContext::instance()->findWindow(hwnd)) {
         if (QAccessibleInterface *accessible = window->accessibleRoot()) {
             auto provider = QWindowsUiaMainProvider::providerForAccessible(accessible);
-            *lResult = UiaReturnRawElementProvider(hwnd, wParam, lParam, provider.Get());
+            *lResult = QWindowsUiaWrapper::instance()->returnRawElementProvider(hwnd, wParam, lParam, provider.Get());
             return true;
         }
     }
@@ -122,8 +124,12 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
     if (!isActive() || !accessible || !accessible->isValid())
         return;
 
+    // Ensures QWindowsUiaWrapper is properly initialized.
+    if (!QWindowsUiaWrapper::instance()->ready())
+        return;
+
     // No need to do anything when nobody is listening.
-    if (!UiaClientsAreListening())
+    if (!QWindowsUiaWrapper::instance()->clientsAreListening())
         return;
 
     switch (event->type()) {
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index f01c594b6cd..02e853da78b 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -21,6 +21,7 @@
 #include "qwindowscontext.h"
 #include "qwindowsuiautils.h"
 #include "qwindowsuiaprovidercache.h"
+#include "qwindowsuiawrapper_p.h"
 
 #include <QtCore/qloggingcategory.h>
 #include <QtGui/private/qaccessiblebridgeutils_p.h>
@@ -75,7 +76,7 @@ void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
                 accessible = child;
         }
         if (auto provider = providerForAccessible(accessible))
-            UiaRaiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId);
+            QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId);
     }
 }
 
@@ -92,7 +93,7 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
 
                     QComVariant oldVal;
                     QComVariant newVal{toggleState};
-                    UiaRaiseAutomationPropertyChangedEvent(
+                    QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(
                             provider.Get(), UIA_ToggleToggleStatePropertyId, oldVal.get(), newVal.get());
                 }
             }
@@ -102,15 +103,15 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
                 // Notifies window opened/closed.
                 if (auto provider = providerForAccessible(accessible)) {
                     if (accessible->state().active) {
-                        UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId);
+                        QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId);
                         if (QAccessibleInterface *focused = accessible->focusChild()) {
                             if (auto focusedProvider = providerForAccessible(focused)) {
-                                UiaRaiseAutomationEvent(focusedProvider.Get(),
+                                QWindowsUiaWrapper::instance()->raiseAutomationEvent(focusedProvider.Get(),
                                                         UIA_AutomationFocusChangedEventId);
                             }
                         }
                     } else {
-                        UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowClosedEventId);
+                        QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Window_WindowClosedEventId);
                     }
                 }
             }
@@ -142,7 +143,7 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
                 // Notifies changes in string values.
                 const QComVariant oldVal;
                 const QComVariant newVal{ event->value().toString() };
-                UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId,
+                QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId,
                                                        oldVal.get(), newVal.get());
             }
         } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
@@ -150,7 +151,7 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
                 // Notifies changes in values of controls supporting the value interface.
                 const QComVariant oldVal;
                 const QComVariant newVal{ valueInterface->currentValue().toDouble() };
-                UiaRaiseAutomationPropertyChangedEvent(
+                QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(
                         provider.Get(), UIA_RangeValueValuePropertyId, oldVal.get(), newVal.get());
             }
         }
@@ -166,7 +167,7 @@ void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
             if (auto provider = providerForAccessible(accessible)) {
                 QComVariant oldVal;
                 QComVariant newVal{ accessible->text(QAccessible::Name) };
-                UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId,
+                QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId,
                                                        oldVal.get(), newVal.get());
             }
         }
@@ -177,7 +178,7 @@ void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
 {
     if (QAccessibleInterface *accessible = event->accessibleInterface()) {
         if (auto provider = providerForAccessible(accessible))
-            UiaRaiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId);
+            QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId);
     }
 }
 
@@ -188,14 +189,14 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
         if (accessible->textInterface()) {
             if (auto provider = providerForAccessible(accessible)) {
                 if (event->type() == QAccessible::TextSelectionChanged) {
-                    UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId);
+                    QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId);
                 } else if (event->type() == QAccessible::TextCaretMoved) {
                     if (!accessible->state().readOnly) {
-                        UiaRaiseAutomationEvent(provider.Get(),
+                        QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(),
                                                 UIA_Text_TextSelectionChangedEventId);
                     }
                 } else {
-                    UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextChangedEventId);
+                    QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider.Get(), UIA_Text_TextChangedEventId);
                 }
             }
         }
@@ -212,7 +213,7 @@ void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *ev
                     ? NotificationProcessing_ImportantAll
                     : NotificationProcessing_All;
             QBStr activityId{ QString::fromLatin1("") };
-            UiaRaiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message.bstr(),
+            QWindowsUiaWrapper::instance()->raiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message.bstr(),
                                       activityId.bstr());
 
         }
@@ -615,7 +616,7 @@ HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderS
     // Returns a host provider only for controls associated with a native window handle. Others should return NULL.
     if (QAccessibleInterface *accessible = accessibleInterface()) {
         if (HWND hwnd = hwndForAccessible(accessible)) {
-            return UiaHostProviderFromHwnd(hwnd, pRetVal);
+            return QWindowsUiaWrapper::instance()->hostProviderFromHwnd(hwnd, pRetVal);
         }
     }
     return S_OK;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper.cpp
new file mode 100644
index 00000000000..caeb8e1da48
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper.cpp
@@ -0,0 +1,89 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <initguid.h>
+
+#include "qwindowsuiawrapper_p.h"
+#include <QtCore/private/qsystemlibrary_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// private constructor
+QWindowsUiaWrapper::QWindowsUiaWrapper()
+{
+    QSystemLibrary uiaLib(QStringLiteral("UIAutomationCore"));
+    if (uiaLib.load()) {
+        m_pUiaReturnRawElementProvider = reinterpret_cast<PtrUiaReturnRawElementProvider>(uiaLib.resolve("UiaReturnRawElementProvider"));
+        m_pUiaHostProviderFromHwnd = reinterpret_cast<PtrUiaHostProviderFromHwnd>(uiaLib.resolve("UiaHostProviderFromHwnd"));
+        m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast<PtrUiaRaiseAutomationPropertyChangedEvent>(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent"));
+        m_pUiaRaiseAutomationEvent = reinterpret_cast<PtrUiaRaiseAutomationEvent>(uiaLib.resolve("UiaRaiseAutomationEvent"));
+        m_pUiaRaiseNotificationEvent = reinterpret_cast<PtrUiaRaiseNotificationEvent>(uiaLib.resolve("UiaRaiseNotificationEvent"));
+        m_pUiaClientsAreListening = reinterpret_cast<PtrUiaClientsAreListening>(uiaLib.resolve("UiaClientsAreListening"));
+    }
+}
+
+QWindowsUiaWrapper::~QWindowsUiaWrapper()
+{
+}
+
+// shared instance
+QWindowsUiaWrapper *QWindowsUiaWrapper::instance()
+{
+    static QWindowsUiaWrapper wrapper;
+    return &wrapper;
+}
+
+// True if all symbols resolved.
+BOOL QWindowsUiaWrapper::ready()
+{
+    return m_pUiaReturnRawElementProvider
+        && m_pUiaHostProviderFromHwnd
+        && m_pUiaRaiseAutomationPropertyChangedEvent
+        && m_pUiaRaiseAutomationEvent
+        && m_pUiaClientsAreListening;
+}
+
+BOOL QWindowsUiaWrapper::clientsAreListening()
+{
+    if (!m_pUiaClientsAreListening)
+        return FALSE;
+    return m_pUiaClientsAreListening();
+}
+
+LRESULT QWindowsUiaWrapper::returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el)
+{
+    if (!m_pUiaReturnRawElementProvider)
+        return static_cast<LRESULT>(NULL);
+    return m_pUiaReturnRawElementProvider(hwnd, wParam, lParam, el);
+}
+
+HRESULT QWindowsUiaWrapper::hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider)
+{
+    if (!m_pUiaHostProviderFromHwnd)
+        return UIA_E_NOTSUPPORTED;
+    return m_pUiaHostProviderFromHwnd(hwnd, ppProvider);
+}
+
+HRESULT QWindowsUiaWrapper::raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue)
+{
+    if (!m_pUiaRaiseAutomationPropertyChangedEvent)
+        return UIA_E_NOTSUPPORTED;
+    return m_pUiaRaiseAutomationPropertyChangedEvent(pProvider, id, oldValue, newValue);
+}
+
+HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id)
+{
+    if (!m_pUiaRaiseAutomationEvent)
+        return UIA_E_NOTSUPPORTED;
+    return m_pUiaRaiseAutomationEvent(pProvider, id);
+}
+
+HRESULT QWindowsUiaWrapper::raiseNotificationEvent(IRawElementProviderSimple *pProvider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
+{
+    if (!m_pUiaRaiseNotificationEvent)
+        return UIA_E_NOTSUPPORTED;
+    return m_pUiaRaiseNotificationEvent(pProvider, notificationKind, notificationProcessing, displayString, activityId);
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper_p.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper_p.h
new file mode 100644
index 00000000000..e005318114c
--- /dev/null
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiawrapper_p.h
@@ -0,0 +1,57 @@
+// Copyright (C) 2017 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWINDOWSUIAWRAPPER_H
+#define QWINDOWSUIAWRAPPER_H
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists for the convenience
+// of other Qt classes.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtGui/private/qtguiglobal_p.h>
+
+QT_REQUIRE_CONFIG(accessibility);
+
+QT_BEGIN_NAMESPACE
+
+class QWindowsUiaWrapper
+{
+    QWindowsUiaWrapper();
+    virtual ~QWindowsUiaWrapper();
+public:
+    static QWindowsUiaWrapper *instance();
+    BOOL ready();
+    BOOL clientsAreListening();
+    LRESULT returnRawElementProvider(HWND hwnd, WPARAM wParam, LPARAM lParam, IRawElementProviderSimple *el);
+    HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider);
+    HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue);
+    HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id);
+    HRESULT raiseNotificationEvent(IRawElementProviderSimple *pProvider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId);
+
+private:
+    typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *);
+    typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **);
+    typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT);
+    typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID);
+    typedef HRESULT (WINAPI *PtrUiaRaiseNotificationEvent)(IRawElementProviderSimple *, NotificationKind, NotificationProcessing, BSTR, BSTR);
+
+    typedef BOOL (WINAPI *PtrUiaClientsAreListening)();
+    PtrUiaReturnRawElementProvider             m_pUiaReturnRawElementProvider = nullptr;
+    PtrUiaHostProviderFromHwnd                 m_pUiaHostProviderFromHwnd = nullptr;
+    PtrUiaRaiseAutomationPropertyChangedEvent  m_pUiaRaiseAutomationPropertyChangedEvent = nullptr;
+    PtrUiaRaiseAutomationEvent                 m_pUiaRaiseAutomationEvent = nullptr;
+    PtrUiaRaiseNotificationEvent               m_pUiaRaiseNotificationEvent = nullptr;
+    PtrUiaClientsAreListening                  m_pUiaClientsAreListening = nullptr;
+};
+
+QT_END_NAMESPACE
+
+#endif //QWINDOWSUIAWRAPPER_H
+
diff --git a/src/plugins/platforms/windows/vxkex.h b/src/plugins/platforms/windows/vxkex.h
new file mode 100644
index 00000000000..6bbf2209f43
--- /dev/null
+++ b/src/plugins/platforms/windows/vxkex.h
@@ -0,0 +1,426 @@
+#pragma once
+
+#include <shtypes.h>
+#include <winuser.h>
+#include <windef.h>
+#include <shellscalingapi.h>
+
+#define MDT_MAXIMUM_DPI 3
+
+namespace vxkex {
+
+static INT GetSystemMetricsForDpi(
+    IN  INT     Index,
+    IN  UINT    Dpi)
+{
+    INT Value;
+
+    Value = GetSystemMetrics(Index);
+
+    switch (Index) {
+    case SM_CXVSCROLL:
+    case SM_CYHSCROLL:
+    case SM_CYCAPTION:
+    case SM_CYVTHUMB:
+    case SM_CXHTHUMB:
+    case SM_CXICON:
+    case SM_CYICON:
+    case SM_CXCURSOR:
+    case SM_CYCURSOR:
+    case SM_CYMENU:
+    case SM_CYVSCROLL:
+    case SM_CXHSCROLL:
+    case SM_CXMIN:
+    case SM_CXMINTRACK:
+    case SM_CYMIN:
+    case SM_CYMINTRACK:
+    case SM_CXSIZE:
+    case SM_CXFRAME:
+    case SM_CYFRAME:
+    case SM_CXICONSPACING:
+    case SM_CYICONSPACING:
+    case SM_CXSMICON:
+    case SM_CYSMICON:
+    case SM_CYSMCAPTION:
+    case SM_CXSMSIZE:
+    case SM_CYSMSIZE:
+    case SM_CXMENUSIZE:
+    case SM_CYMENUSIZE:
+    case SM_CXMENUCHECK:
+    case SM_CYMENUCHECK:
+        // These are pixel values that have to be scaled according to DPI.
+        Value *= Dpi;
+        Value /= USER_DEFAULT_SCREEN_DPI;
+        break;
+    }
+
+    return Value;
+}
+
+static BOOL SystemParametersInfoForDpi(
+    IN      UINT    Action,
+    IN      UINT    Parameter,
+    IN OUT  PVOID   Data,
+    IN      UINT    WinIni,
+    IN      UINT    Dpi)
+{
+    switch (Action) {
+    case SPI_GETICONTITLELOGFONT:
+        return SystemParametersInfo(Action, Parameter, Data, 0);
+    case SPI_GETICONMETRICS:
+        {
+            BOOL Success;
+            PICONMETRICS IconMetrics;
+
+            Success = SystemParametersInfo(Action, Parameter, Data, 0);
+
+            if (Success) {
+                IconMetrics = (PICONMETRICS) Data;
+
+                IconMetrics->iHorzSpacing *= Dpi;
+                IconMetrics->iVertSpacing *= Dpi;
+                IconMetrics->iHorzSpacing /= USER_DEFAULT_SCREEN_DPI;
+                IconMetrics->iVertSpacing /= USER_DEFAULT_SCREEN_DPI;
+            }
+
+            return Success;
+        }
+    case SPI_GETNONCLIENTMETRICS:
+        {
+            BOOL Success;
+            PNONCLIENTMETRICS NonClientMetrics;
+
+            Success = SystemParametersInfo(Action, Parameter, Data, 0);
+
+            if (Success) {
+                NonClientMetrics = (PNONCLIENTMETRICS) Data;
+
+                NonClientMetrics->iBorderWidth          *= Dpi;
+                NonClientMetrics->iScrollWidth          *= Dpi;
+                NonClientMetrics->iScrollHeight         *= Dpi;
+                NonClientMetrics->iCaptionWidth         *= Dpi;
+                NonClientMetrics->iCaptionHeight        *= Dpi;
+                NonClientMetrics->iSmCaptionWidth       *= Dpi;
+                NonClientMetrics->iSmCaptionHeight      *= Dpi;
+                NonClientMetrics->iMenuWidth            *= Dpi;
+                NonClientMetrics->iMenuHeight           *= Dpi;
+                NonClientMetrics->iPaddedBorderWidth    *= Dpi;
+
+                NonClientMetrics->iBorderWidth          /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iScrollWidth          /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iScrollHeight         /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iCaptionWidth         /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iCaptionHeight        /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iSmCaptionWidth       /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iSmCaptionHeight      /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iMenuWidth            /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iMenuHeight           /= USER_DEFAULT_SCREEN_DPI;
+                NonClientMetrics->iPaddedBorderWidth    /= USER_DEFAULT_SCREEN_DPI;
+            }
+
+            return Success;
+        }
+    default:
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+}
+
+static HRESULT GetScaleFactorForMonitor(
+    IN  HMONITOR                Monitor,
+    OUT DEVICE_SCALE_FACTOR    *ScaleFactor)
+{
+    HDC DeviceContext;
+    ULONG LogPixelsX;
+
+    DeviceContext = GetDC(NULL);
+    if (!DeviceContext) {
+        *ScaleFactor = SCALE_100_PERCENT;
+        return S_OK;
+    }
+
+    LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
+    ReleaseDC(NULL, DeviceContext);
+
+    *ScaleFactor = (DEVICE_SCALE_FACTOR) (9600 / LogPixelsX);
+    return S_OK;
+}
+
+static HRESULT GetDpiForMonitor(
+    IN  HMONITOR            Monitor,
+    IN  MONITOR_DPI_TYPE    DpiType,
+    OUT UINT *              DpiX,
+    OUT UINT *              DpiY)
+{
+    HDC DeviceContext;
+
+    if (DpiType >= MDT_MAXIMUM_DPI) {
+        return E_INVALIDARG;
+    }
+
+    if (!DpiX || !DpiY) {
+        return E_INVALIDARG;
+    }
+
+    if (!IsProcessDPIAware()) {
+        *DpiX = USER_DEFAULT_SCREEN_DPI;
+        *DpiY = USER_DEFAULT_SCREEN_DPI;
+        return S_OK;
+    }
+
+    DeviceContext = GetDC(NULL);
+    if (!DeviceContext) {
+        *DpiX = USER_DEFAULT_SCREEN_DPI;
+        *DpiY = USER_DEFAULT_SCREEN_DPI;
+        return S_OK;
+    }
+
+    *DpiX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
+    *DpiY = GetDeviceCaps(DeviceContext, LOGPIXELSY);
+
+    if (DpiType == MDT_EFFECTIVE_DPI) {
+        DEVICE_SCALE_FACTOR ScaleFactor;
+
+        // We have to multiply the DPI values by the scaling factor.
+        vxkex::GetScaleFactorForMonitor(Monitor, &ScaleFactor);
+
+        *DpiX *= ScaleFactor;
+        *DpiY *= ScaleFactor;
+        *DpiX /= 100;
+        *DpiY /= 100;
+    }
+
+    ReleaseDC(NULL, DeviceContext);
+    return S_OK;
+}
+
+static UINT GetDpiForSystem(
+    VOID)
+{
+    HDC DeviceContext;
+    ULONG LogPixelsX;
+
+    if (!IsProcessDPIAware()) {
+        return 96;
+    }
+
+    DeviceContext = GetDC(NULL);
+    if (!DeviceContext) {
+        return 96;
+    }
+
+    LogPixelsX = GetDeviceCaps(DeviceContext, LOGPIXELSX);
+    ReleaseDC(NULL, DeviceContext);
+
+    return LogPixelsX;
+}
+
+static UINT GetDpiForWindow(
+    IN  HWND    Window)
+{
+    if (!IsWindow(Window)) {
+        return 0;
+    }
+
+    return vxkex::GetDpiForSystem();
+}
+
+static BOOL AdjustWindowRectExForDpi(
+    IN OUT  LPRECT  Rect,
+    IN      ULONG   WindowStyle,
+    IN      BOOL    HasMenu,
+    IN      ULONG   WindowExStyle,
+    IN      ULONG   Dpi)
+{
+    // I'm not sure how to implement this function properly.
+    // If it turns out to be important, I'll have to do some testing
+    // on a Win10 VM.
+
+    return AdjustWindowRectEx(
+        Rect,
+        WindowStyle,
+        HasMenu,
+        WindowExStyle);
+}
+
+static BOOL SetDisplayAutoRotationPreferences(
+    IN  ORIENTATION_PREFERENCE  Orientation)
+{
+    return TRUE;
+}
+
+static BOOL GetDisplayAutoRotationPreferences(
+    OUT ORIENTATION_PREFERENCE * Orientation)
+{
+    *Orientation = ORIENTATION_PREFERENCE_NONE;
+    return TRUE;
+}
+
+// scaling.c
+
+static BOOL SetProcessDpiAwarenessContext(
+    IN  DPI_AWARENESS_CONTEXT   DpiContext)
+{
+    if ((ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE) {
+        //NOTHING;
+    } else if ((ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ||
+             (ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ||
+             (ULONG_PTR)DpiContext == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) {
+        SetProcessDPIAware();
+    } else {
+        return FALSE;
+    }
+
+    return TRUE;
+}
+
+static BOOL AreDpiAwarenessContextsEqual(
+    IN  DPI_AWARENESS_CONTEXT   Value1,
+    IN  DPI_AWARENESS_CONTEXT   Value2)
+{
+    return (Value1 == Value2);
+}
+
+static BOOL IsValidDpiAwarenessContext(
+    IN  DPI_AWARENESS_CONTEXT   Value)
+{
+    if ((ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE ||
+        (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED ||
+        (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_SYSTEM_AWARE ||
+        (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE ||
+        (ULONG_PTR)Value == (ULONG_PTR)DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) {
+        return TRUE;
+    } else {
+        return FALSE;
+    }
+}
+
+static BOOL EnableNonClientDpiScaling(
+    IN  HWND    Window)
+{
+    return TRUE;
+}
+
+static DPI_AWARENESS_CONTEXT GetThreadDpiAwarenessContext(
+    VOID)
+{
+    if (IsProcessDPIAware()) {
+        return DPI_AWARENESS_CONTEXT_SYSTEM_AWARE;
+    } else {
+        return DPI_AWARENESS_CONTEXT_UNAWARE;
+    }
+}
+
+static DPI_AWARENESS_CONTEXT GetWindowDpiAwarenessContext(
+    IN  HWND    Window)
+{
+    ULONG WindowThreadId;
+    ULONG WindowProcessId;
+
+    WindowThreadId = GetWindowThreadProcessId(Window, &WindowProcessId);
+    if (!WindowThreadId) {
+        return 0;
+    }
+
+    // looks like there's a bug in vxkex, here should be == instead of =
+    // and if is always true
+    // anyway I don't want to deal with Windows kernel mode structures here
+
+    if (1) { //if (WindowProcessId = (ULONG) NtCurrentTeb()->ClientId.UniqueProcess) {
+        return vxkex::GetThreadDpiAwarenessContext();
+    }
+
+    return DPI_AWARENESS_CONTEXT_UNAWARE;
+}
+
+// pointer.c
+
+static BOOL GetPointerType(
+    IN  UINT32               PointerId,
+    OUT POINTER_INPUT_TYPE  *PointerType)
+{
+    *PointerType = PT_MOUSE;
+    return TRUE;
+}
+
+static BOOL GetPointerFrameTouchInfo(
+    IN      UINT32   PointerId,
+    IN OUT  UINT32   *PointerCount,
+    OUT     LPVOID  TouchInfo)
+{
+    return FALSE;
+}
+
+static BOOL GetPointerFrameTouchInfoHistory(
+    IN      UINT32   PointerId,
+    IN OUT  UINT32   *EntriesCount,
+    IN OUT  UINT32   *PointerCount,
+    OUT     LPVOID   TouchInfo)
+{
+    return FALSE;
+}
+
+static BOOL GetPointerPenInfo(
+    IN  UINT32   PointerId,
+    OUT LPVOID  PenInfo)
+{
+    return FALSE;
+}
+
+static BOOL GetPointerPenInfoHistory(
+    IN      UINT32  PointerId,
+    IN OUT  UINT32  *EntriesCount,
+    OUT     LPVOID  PenInfo)
+{
+    return FALSE;
+}
+
+static BOOL SkipPointerFrameMessages(
+    IN  UINT32   PointerId)
+{
+    return TRUE;
+}
+
+static BOOL GetPointerDeviceRects(
+    IN  HANDLE  Device,
+    OUT LPRECT  PointerDeviceRect,
+    OUT LPRECT  DisplayRect)
+{
+    PointerDeviceRect->top = 0;
+    PointerDeviceRect->left = 0;
+    PointerDeviceRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+    PointerDeviceRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+
+    DisplayRect->top = 0;
+    DisplayRect->left = 0;
+    DisplayRect->bottom = GetSystemMetrics(SM_CYVIRTUALSCREEN);
+    DisplayRect->right = GetSystemMetrics(SM_CXVIRTUALSCREEN);
+
+    return TRUE;
+}
+
+static BOOL GetPointerInfo(
+    IN  DWORD           PointerId,
+    OUT POINTER_INFO    *PointerInfo)
+{
+    PointerInfo->pointerType = PT_MOUSE;
+    PointerInfo->pointerId = PointerId;
+    PointerInfo->frameId = 0;
+    PointerInfo->pointerFlags = POINTER_FLAG_NONE;
+    PointerInfo->sourceDevice = NULL;
+    PointerInfo->hwndTarget = NULL;
+    GetCursorPos(&PointerInfo->ptPixelLocation);
+    GetCursorPos(&PointerInfo->ptHimetricLocation);
+    GetCursorPos(&PointerInfo->ptPixelLocationRaw);
+    GetCursorPos(&PointerInfo->ptHimetricLocationRaw);
+    PointerInfo->dwTime = 0;
+    PointerInfo->historyCount = 1;
+    PointerInfo->InputData = 0;
+    PointerInfo->dwKeyStates = 0;
+    PointerInfo->PerformanceCount = 0;
+    PointerInfo->ButtonChangeType = POINTER_CHANGE_NONE;
+
+    return TRUE;
+}
+
+} // namespace vxkex
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index a8407add019..a8097330210 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -59,6 +59,10 @@
 
 #include <algorithm>
 
+#if defined(Q_OS_WIN)
+#include "../../plugins/platforms/windows/vxkex.h"
+#endif
+
 QT_BEGIN_NAMESPACE
 
 #if defined(Q_OS_WIN)
@@ -254,6 +258,11 @@ void QWindowsStyle::polish(QPalette &pal)
     QCommonStyle::polish(pal);
 }
 
+#if defined(Q_OS_WIN)
+typedef BOOL (WINAPI *GetSystemMetricsForDpiFunc)(int, UINT);
+typedef BOOL (WINAPI *SystemParametersInfoForDpiFunc)(UINT, UINT, PVOID, UINT, UINT);
+#endif
+
 int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const QStyleOption *, const QWidget *widget)
 {
 #if defined(Q_OS_WIN)
@@ -261,29 +270,43 @@ int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const
     // hardcode DPI to 1x 96 DPI.
     const int dpi = 96;
 
+    static GetSystemMetricsForDpiFunc myGetSystemMetricsForDpi = 
+        (GetSystemMetricsForDpiFunc)::GetProcAddress(::GetModuleHandle(L"User32"), "GetSystemMetricsForDpi");
+
+    static SystemParametersInfoForDpiFunc mySystemParametersInfoForDpi = 
+        (SystemParametersInfoForDpiFunc)::GetProcAddress(::GetModuleHandle(L"User32"), "SystemParametersInfoForDpi");
+
     switch (pm) {
     case QStyle::PM_DockWidgetFrameWidth:
-        return GetSystemMetricsForDpi(SM_CXFRAME, dpi);
+        return myGetSystemMetricsForDpi ? myGetSystemMetricsForDpi(SM_CXFRAME, dpi) : vxkex::GetSystemMetricsForDpi(SM_CXFRAME, dpi);
 
     case QStyle::PM_TitleBarHeight: {
-        const int resizeBorderThickness =
-            GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+        const int resizeBorderThickness = myGetSystemMetricsForDpi ?
+            (myGetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + myGetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) :
+            (vxkex::GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + vxkex::GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)) ;
         if (widget && (widget->windowType() == Qt::Tool))
-            return GetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness;
-        return GetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness;
+            return myGetSystemMetricsForDpi ? 
+                (myGetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness) :
+                (vxkex::GetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness);
+        return myGetSystemMetricsForDpi ? 
+            (myGetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness) :
+            (vxkex::GetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness);
     }
 
     case QStyle::PM_ScrollBarExtent:
         {
             NONCLIENTMETRICS ncm;
             ncm.cbSize = sizeof(NONCLIENTMETRICS);
-            if (SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi))
+            BOOL bResult = mySystemParametersInfoForDpi 
+                ? mySystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi) 
+                : vxkex::SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi);
+            if (bResult)
                 return qMax(ncm.iScrollHeight, ncm.iScrollWidth);
         }
         break;
 
     case  QStyle::PM_MdiSubWindowFrameWidth:
-        return GetSystemMetricsForDpi(SM_CYFRAME, dpi);
+        return myGetSystemMetricsForDpi ? myGetSystemMetricsForDpi(SM_CYFRAME, dpi) : vxkex::GetSystemMetricsForDpi(SM_CYFRAME, dpi);
 
     default:
         break;
