Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  0001-Satisfy-Windows-7-compatibility.patch  Sprache: unbekannt

 
Spracherkennung für: .patch vermutete Sprache: MT940 {MT940[52] VDM[45] ADA[30]} [Methode: maximale Elemente, drei Dimensionen]

From f59945015c99cb02260553676c036c90ba48ea05 Mon Sep 17 00:00:00 2001
From: Fatih Uzunoglu <fuzun54@outlook.com>
Date: Mon, 22 Jan 2024 21:37:39 +0200
Subject: [PATCH] Satisfy Windows 7 compatibility

---
 cmake/QtBaseConfigureTests.cmake              |  10 +-
 src/corelib/CMakeLists.txt                    |  22 ++--
 src/corelib/global/qt_windows.h               |   6 +-
 src/corelib/io/qfilesystemengine_win.cpp      |   5 +
 src/corelib/kernel/qeventdispatcher_win.cpp   |  10 +-
 src/corelib/kernel/qfunctions_win.cpp         |  13 +-
 src/corelib/thread/qfutex_win_p.h             |  42 +++++-
 src/corelib/thread/qmutex.cpp                 |   4 +-
 src/corelib/thread/qmutex_p.h                 |   2 +
 src/corelib/thread/qmutex_win.cpp             |  30 +++++
 src/corelib/thread/qthread_win.cpp            |  25 ++--
 src/gui/CMakeLists.txt                        |   1 -
 src/gui/rhi/qrhid3d11.cpp                     |   5 +-
 src/gui/rhi/qrhid3d12.cpp                     |  87 ++++++++++---
 .../text/windows/qwindowsfontdatabasebase.cpp |  14 +-
 .../networklistmanager/CMakeLists.txt         |   1 -
 src/plugins/platforms/direct2d/CMakeLists.txt |   2 -
 .../direct2d/qwindowsdirect2dcontext.cpp      |   1 +
 src/plugins/platforms/windows/CMakeLists.txt  |   2 -
 .../platforms/windows/qtwindowsglobal.h       |   4 +
 .../platforms/windows/qwin10helpers.cpp       |  24 +++-
 .../platforms/windows/qwindowscontext.cpp     | 120 +++++++++++++++---
 .../platforms/windows/qwindowscontext.h       |  95 ++++++++++++++
 .../platforms/windows/qwindowsdrag.cpp        |  10 +-
 .../platforms/windows/qwindowskeymapper.cpp   |  17 ++-
 .../windows/qwindowspointerhandler.cpp        |  33 +++--
 .../platforms/windows/qwindowsscreen.cpp      |  18 ++-
 .../platforms/windows/qwindowstheme.cpp       |   6 +-
 .../platforms/windows/qwindowswindow.cpp      |  48 +++++--
 src/widgets/styles/qwindowsstyle.cpp          |  26 +++-
 30 files changed, 570 insertions(+), 113 deletions(-)
 create mode 100644 src/corelib/thread/qmutex_win.cpp

diff --git a/cmake/QtBaseConfigureTests.cmake b/cmake/QtBaseConfigureTests.cmake
index d41fac2e18e..9490de8fa12 100644
--- a/cmake/QtBaseConfigureTests.cmake
+++ b/cmake/QtBaseConfigureTests.cmake
@@ -163,16 +163,16 @@ function(qt_internal_ensure_latest_win_nt_api)
         #if !defined(_WIN32_WINNT) && !defined(WINVER)
         #error "_WIN32_WINNT and WINVER are not defined"
         #endif
-        #if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0A00)
+        #if defined(_WIN32_WINNT) && (_WIN32_WINNT < 0x0601)
         #error "_WIN32_WINNT version too low"
         #endif
-        #if defined(WINVER) && (WINVER < 0x0A00)
+        #if defined(WINVER) && (WINVER < 0x0601)
         #error "WINVER version too low"
         #endif
         int main() { return 0; }
-    ]=] HAVE_WIN10_WIN32_WINNT)
-    if(NOT HAVE_WIN10_WIN32_WINNT)
-        list(APPEND QT_PLATFORM_DEFINITIONS _WIN32_WINNT=0x0A00 WINVER=0x0A00)
+    ]=] HAVE_WIN7_WIN32_WINNT)
+    if(NOT HAVE_WIN7_WIN32_WINNT)
+        list(APPEND QT_PLATFORM_DEFINITIONS _WIN32_WINNT=0x0601 WINVER=0x0601)
         set(QT_PLATFORM_DEFINITIONS ${QT_PLATFORM_DEFINITIONS}
             CACHE STRING "Qt platform specific pre-processor defines" FORCE)
     endif()
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index b6be7a8d49d..db57eed2b05 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -538,16 +538,17 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_animation
         animation/qvariantanimation.cpp animation/qvariantanimation.h animation/qvariantanimation_p.h
 )
 
-# This needs to be done before one below adds kernel32 because the symbols we use
-# from synchronization also appears in kernel32 in the version of MinGW we use in CI.
-# However, when picking the symbols from libkernel32.a it will try to load the symbols
-# from the wrong DLL at runtime and crash!
+# Do not include synchronization, because
+# MinGW redirects it to api-ms-win-core-synch-l1-2-0.a
+# Which seems to be available on Windows 7 (for some reason)
+# but is broken.  Use the symbols from kernel32 instead.
 qt_internal_extend_target(Core CONDITION QT_FEATURE_thread AND WIN32
     SOURCES
         thread/qfutex_win_p.h
+        thread/qmutex_win.cpp
         thread/qwaitcondition_win.cpp
-    LIBRARIES
-        synchronization
+    # LIBRARIES
+    #     synchronization
 )
 
 qt_internal_extend_target(Core CONDITION WIN32
@@ -866,10 +867,10 @@ qt_internal_extend_target(Core CONDITION WASM
 )
 
 # On MS-Win, clang has two flavors, one of which immitates MSVC (so claims to be it)
-qt_internal_extend_target(Core CONDITION MSVC
-    LIBRARIES
-        runtimeobject
-)
+# qt_internal_extend_target(Core CONDITION MSVC
+#    LIBRARIES
+#        runtimeobject
+# )
 
 qt_internal_extend_target(Core CONDITION QT_FEATURE_icu
     SOURCES
@@ -1426,6 +1427,7 @@ qt_internal_extend_target(Core CONDITION QT_FEATURE_ctf
 set_source_files_properties(
     thread/qmutex_mac.cpp
     thread/qmutex_unix.cpp
+    thread/qmutex_win.cpp
     PROPERTIES HEADER_FILE_ONLY ON)
 
 # Remove QT_NO_CAST_TO_ASCII to ensure that the symbols are included in the library.
diff --git a/src/corelib/global/qt_windows.h b/src/corelib/global/qt_windows.h
index 5586d0b9272..eb0264b4ee2 100644
--- a/src/corelib/global/qt_windows.h
+++ b/src/corelib/global/qt_windows.h
@@ -10,16 +10,16 @@
 #endif
 
 #ifndef WINVER
-#  define WINVER 0x0A00 // _WIN32_WINNT_WIN10
+#  define WINVER 0x0601
 #endif
 #ifndef _WIN32_WINNT
-#  define _WIN32_WINNT 0x0A00
+#  define _WIN32_WINNT 0x0601
 #endif
 #ifndef _WIN32_IE
 #  define _WIN32_IE 0x0A00
 #endif
 #ifndef NTDDI_VERSION
-#  define NTDDI_VERSION 0x0A00000C // NTDDI_WIN10_NI
+#  define NTDDI_VERSION 0x06010000
 #endif
 
 #ifndef NOMINMAX
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 8300c3b5eea..8795463a74e 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -1,6 +1,11 @@
 // Copyright (C) 2022 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
 
+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0602)
+#undef _WIN32_WINNT
+#define _WIN32_WINNT 0x0602 // Windows 8, to access FILE_ID_INFO
+#endif
+
 #include "qfilesystemengine_p.h"
 #include "qoperatingsystemversion.h"
 #include "qplatformdefs.h"
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index a7663b24813..78ad3d3edeb 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -362,7 +362,15 @@ void QEventDispatcherWin32Private::registerTimer(WinTimerInfo *t)
 
     if (!ok) {
         // user normal timers for (Very)CoarseTimers, or if no more multimedia timers available
-        ok = SetCoalescableTimer(internalHwnd, t->timerId, interval, nullptr, tolerance);
+
+        typedef UINT_PTR (*SetCoalescableTimerCompat)(HWND, UINT_PTR, UINT, TIMERPROC, ULONG);
+        static SetCoalescableTimerCompat setCoalescableTimer = []() {
+            QSystemLibrary user32dll(QLatin1String("user32"));
+            return (SetCoalescableTimerCompat)(user32dll.resolve("SetCoalescableTimer"));
+        }();
+
+        if (setCoalescableTimer)
+            ok = setCoalescableTimer(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..c1761868888 100644
--- a/src/corelib/kernel/qfunctions_win.cpp
+++ b/src/corelib/kernel/qfunctions_win.cpp
@@ -4,6 +4,7 @@
 #include "qfunctions_win_p.h"
 
 #include <QtCore/qdebug.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 
 #include <combaseapi.h>
 #include <objbase.h>
@@ -47,7 +48,17 @@ bool qt_win_hasPackageIdentity()
 #if defined(HAS_APPMODEL)
     static const bool hasPackageIdentity = []() {
         UINT32 length = 0;
-        switch (const auto result = GetCurrentPackageFullName(&length, nullptr)) {
+
+        typedef LONG (*GetCurrentPackageFullNameCompat)(UINT32*, PWSTR);
+        static GetCurrentPackageFullNameCompat getCurrentPackageFullName = []() {
+            QSystemLibrary kernel32dll(QLatin1String("kernel32"));
+            return (GetCurrentPackageFullNameCompat)(kernel32dll.resolve("GetCurrentPackageFullName"));
+        }();
+
+        if (!getCurrentPackageFullName)
+            return false;
+
+        switch (const auto result = getCurrentPackageFullName(&length, nullptr)) {
         case ERROR_INSUFFICIENT_BUFFER:
             return true;
         case APPMODEL_ERROR_NO_PACKAGE:
diff --git a/src/corelib/thread/qfutex_win_p.h b/src/corelib/thread/qfutex_win_p.h
index 75a12bd82c1..3d2aa021db6 100644
--- a/src/corelib/thread/qfutex_win_p.h
+++ b/src/corelib/thread/qfutex_win_p.h
@@ -18,37 +18,65 @@
 #include <private/qglobal_p.h>
 #include <qdeadlinetimer.h>
 #include <qtsan_impl.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 
 #include <qt_windows.h>
 
-#define QT_ALWAYS_USE_FUTEX
-
 QT_BEGIN_NAMESPACE
 
 namespace QtWindowsFutex {
-constexpr inline bool futexAvailable() { return true; }
+typedef BOOL(*WaitOnAddressCompat)( _In_ volatile VOID *Address, _In_ PVOID CompareAddress, _In_ SIZE_T AddressSize, _In_ DWORD dwMilliseconds);
+typedef void(*WakeByAddressAllCompat)(_In_ PVOID Address);
+typedef void(*WakeByAddressSingleCompat)(_In_ PVOID Address);
+
+struct FutexFuncs {
+    WaitOnAddressCompat waitOnAddress = nullptr;
+    WakeByAddressAllCompat wakeByAddressAll = nullptr;
+    WakeByAddressSingleCompat wakeByAddressSingle = nullptr;
+};
+
+inline const FutexFuncs futexFuncs = []() {
+    FutexFuncs funcs;
+
+    QSystemLibrary synchWin8ApiSet(QLatin1String("api-ms-win-core-synch-l1-2-0"));
+
+    funcs.waitOnAddress = (WaitOnAddressCompat)(synchWin8ApiSet.resolve("WaitOnAddress"));
+    funcs.wakeByAddressAll = (WakeByAddressAllCompat)(synchWin8ApiSet.resolve("WakeByAddressAll"));
+    funcs.wakeByAddressSingle = (WakeByAddressSingleCompat)(synchWin8ApiSet.resolve("WakeByAddressSingle"));
+
+    return funcs;
+}();
+
+inline bool futexAvailable()
+{
+    return (futexFuncs.waitOnAddress && futexFuncs.wakeByAddressAll && futexFuncs.wakeByAddressSingle);
+}
 
 template <typename Atomic>
 inline void futexWait(Atomic &futex, typename Atomic::Type expectedValue)
 {
+    assert(futexFuncs.waitOnAddress);
     QtTsan::futexRelease(&futex);
-    WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), INFINITE);
+    futexFuncs.waitOnAddress(&futex, &expectedValue, sizeof(expectedValue), INFINITE);
     QtTsan::futexAcquire(&futex);
 }
 template <typename Atomic>
 inline bool futexWait(Atomic &futex, typename Atomic::Type expectedValue, QDeadlineTimer deadline)
 {
+    assert(futexFuncs.waitOnAddress);
     using namespace std::chrono;
-    BOOL r = WaitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(deadline.remainingTime()));
+    BOOL r = futexFuncs.waitOnAddress(&futex, &expectedValue, sizeof(expectedValue), DWORD(deadline.remainingTime()));
     return r || GetLastError() != ERROR_TIMEOUT;
 }
 template <typename Atomic> inline void futexWakeAll(Atomic &futex)
 {
-    WakeByAddressAll(&futex);
+    assert(futexFuncs.wakeByAddressAll);
+    futexFuncs.wakeByAddressAll(&futex);
 }
 template <typename Atomic> inline void futexWakeOne(Atomic &futex)
 {
-    WakeByAddressSingle(&futex);
+    assert(futexFuncs.wakeByAddressSingle);
+    futexFuncs.wakeByAddressSingle(&futex);
 }
 } // namespace QtWindowsFutex
 namespace QtFutex = QtWindowsFutex;
diff --git a/src/corelib/thread/qmutex.cpp b/src/corelib/thread/qmutex.cpp
index 1b8f76f1230..0659d4dc068 100644
--- a/src/corelib/thread/qmutex.cpp
+++ b/src/corelib/thread/qmutex.cpp
@@ -911,10 +911,12 @@ void QMutexPrivate::derefWaiters(int value) noexcept
 
 QT_END_NAMESPACE
 
-#if defined(QT_ALWAYS_USE_FUTEX)
+#if defined(Q_OS_LINUX) && defined(QT_ALWAYS_USE_FUTEX)
 // 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..ce3586a90b7
--- /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
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index 88ba6dc8f62..2d17f1b4dee 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -11,6 +11,7 @@
 
 #include <private/qcoreapplication_p.h>
 #include <private/qeventdispatcher_win_p.h>
+#include <private/qsystemlibrary_p.h>
 #include "qloggingcategory.h"
 
 #include <qt_windows.h>
@@ -20,17 +21,6 @@
 #endif // _MT
 #include <process.h>
 
-extern "C" {
-// MinGW is missing the declaration of SetThreadDescription:
-WINBASEAPI
-HRESULT
-WINAPI
-SetThreadDescription(
-    _In_ HANDLE hThread,
-    _In_ PCWSTR lpThreadDescription
-    );
-}
-
 QT_BEGIN_NAMESPACE
 
 #if QT_CONFIG(thread)
@@ -264,7 +254,18 @@ 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()));
+
+    {
+        typedef HRESULT (*SetThreadDescriptionFunc)(HANDLE, PCWSTR);
+
+        static SetThreadDescriptionFunc setThreadDescription = []() {
+            QSystemLibrary kernel32(QLatin1String("kernel32"));
+            return (SetThreadDescriptionFunc)(kernel32.resolve("SetThreadDescription"));
+        }();
+
+        if (setThreadDescription)
+            setThreadDescription(GetCurrentThread(), reinterpret_cast<const wchar_t *>(threadName.utf16()));
+    }
 
     emit thr->started(QThread::QPrivateSignal());
     QThread::setTerminationEnabled(true);
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index 2cc72625131..16c8086decc 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -479,7 +479,6 @@ qt_internal_extend_target(Gui CONDITION WIN32
         d3d11
         dxgi
         dxguid
-        d3d12
     ATTRIBUTION_FILE_DIR_PATHS
         ../3rdparty/D3D12MemoryAllocator
 )
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index 9e2e0c4e81c..9a0b5721abc 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -8,6 +8,7 @@
 #include <qmath.h>
 #include <QtCore/qcryptographichash.h>
 #include <QtCore/private/qsystemerror_p.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 #include "qrhid3dhelpers_p.h"
 
 #include <cstdio>
@@ -185,9 +186,9 @@ inline Int aligned(Int v, Int byteAlign)
 static IDXGIFactory1 *createDXGIFactory2()
 {
     IDXGIFactory1 *result = nullptr;
-    const HRESULT hr = CreateDXGIFactory2(0, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&result));
+    const HRESULT hr = CreateDXGIFactory1(__uuidof(IDXGIFactory2), reinterpret_cast<void **>(&result));
     if (FAILED(hr)) {
-        qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
+        qWarning("CreateDXGIFactory1() failed to create DXGI factory: %s",
             qPrintable(QSystemError::windowsComString(hr)));
         result = nullptr;
     }
diff --git a/src/gui/rhi/qrhid3d12.cpp b/src/gui/rhi/qrhid3d12.cpp
index f663c006346..2e8578d055d 100644
--- a/src/gui/rhi/qrhid3d12.cpp
+++ b/src/gui/rhi/qrhid3d12.cpp
@@ -5,6 +5,7 @@
 #include "D3D12MemAlloc.h"
 #include <qmath.h>
 #include <QtCore/private/qsystemerror_p.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 #include <comdef.h>
 #include "qrhid3dhelpers_p.h"
 #include "cs_mipmap_p.h"
@@ -150,6 +151,17 @@ QT_BEGIN_NAMESPACE
     \variable QRhiD3D12CommandBufferNativeHandles::commandList
 */
 
+typedef HRESULT (*D3D12SerializeVersionedRootSignatureFunc)(
+              const D3D12_VERSIONED_ROOT_SIGNATURE_DESC *pRootSignature,
+              ID3DBlob                                  **ppBlob,
+              ID3DBlob                                  **ppErrorBlob
+);
+
+static const D3D12SerializeVersionedRootSignatureFunc d3D12SerializeVersionedRootSignature = []() {
+        QSystemLibrary d3d12lib(QStringLiteral("d3d12"));
+        return reinterpret_cast<D3D12SerializeVersionedRootSignatureFunc>(d3d12lib.resolve("D3D12SerializeVersionedRootSignature"));
+}();
+
 // https://learn.microsoft.com/en-us/windows/win32/direct3d12/hardware-feature-levels
 static const D3D_FEATURE_LEVEL MIN_FEATURE_LEVEL = D3D_FEATURE_LEVEL_11_0;
 
@@ -219,20 +231,30 @@ bool QRhiD3D12::create(QRhi::Flags flags)
     UINT factoryFlags = 0;
     if (debugLayer)
         factoryFlags |= DXGI_CREATE_FACTORY_DEBUG;
-    HRESULT hr = CreateDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
-    if (FAILED(hr)) {
-        // retry without debug, if it was requested (to match D3D11 backend behavior)
-        if (debugLayer) {
+
+    HRESULT hr = E_FAIL;
+
+    if (debugLayer) {
+        typedef HRESULT (*CreateDXGIFactory2FuncPtr)(UINT Flags, REFIID riid, void **ppFactory);
+        CreateDXGIFactory2FuncPtr createDXGIFactory2 = nullptr;
+        QSystemLibrary dxgilib(QLatin1String("dxgi"));
+        createDXGIFactory2 = reinterpret_cast<CreateDXGIFactory2FuncPtr>(dxgilib.resolve("CreateDXGIFactory2"));
+        if (createDXGIFactory2) {
+            hr = createDXGIFactory2(factoryFlags, __uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
+        }
+
+        if (FAILED(hr)) {
             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));
-        }
-        if (SUCCEEDED(hr)) {
             debugLayer = false;
-        } else {
-            qWarning("CreateDXGIFactory2() failed to create DXGI factory: %s",
-                     qPrintable(QSystemError::windowsComString(hr)));
+        }
+    }
+
+    if (!debugLayer) {
+        hr = CreateDXGIFactory1(__uuidof(IDXGIFactory2), reinterpret_cast<void **>(&dxgiFactory));
+        if (FAILED(hr)) {
+            qWarning("CreateDXGIFactory1() failed to create DXGI factory: %s",
+                qPrintable(QSystemError::windowsComString(hr)));
             return false;
         }
     }
@@ -253,7 +275,18 @@ bool QRhiD3D12::create(QRhi::Flags flags)
 
     if (debugLayer) {
         ID3D12Debug1 *debug = nullptr;
-        if (SUCCEEDED(D3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
+
+        QSystemLibrary d3d12lib(QStringLiteral("d3d12"));
+
+        typedef HRESULT (*D3D12GetDebugInterfaceFunc)(
+            REFIID riid,
+            void   **ppvDebug
+        );
+        static const auto d3D12GetDebugInterface = reinterpret_cast<D3D12GetDebugInterfaceFunc>(d3d12lib.resolve("D3D12GetDebugInterface"));
+
+        if (!d3D12GetDebugInterface) {
+            qWarning("Can not enable D3D12 debug layer. Symbol D3D12GetDebugInterface is missing, is D3D12 installed properly?");
+        } else if (SUCCEEDED(d3D12GetDebugInterface(__uuidof(ID3D12Debug1), reinterpret_cast<void **>(&debug)))) {
             qCDebug(QRHI_LOG_INFO, "Enabling D3D12 debug layer");
             debug->EnableDebugLayer();
             debug->Release();
@@ -321,7 +354,22 @@ bool QRhiD3D12::create(QRhi::Flags flags)
         if (minimumFeatureLevel == 0)
             minimumFeatureLevel = MIN_FEATURE_LEVEL;
 
-        hr = D3D12CreateDevice(activeAdapter,
+        QSystemLibrary d3d12lib(QStringLiteral("d3d12"));
+        typedef HRESULT (*D3D12CreateDeviceFunc)(
+            IUnknown                 *pAdapter,
+            D3D_FEATURE_LEVEL         MinimumFeatureLevel,
+            REFIID                    riid,
+            void                    **ppDevice
+        );
+        D3D12CreateDeviceFunc d3D12CreateDevice = reinterpret_cast<D3D12CreateDeviceFunc>(d3d12lib.resolve("D3D12CreateDevice"));
+
+        if (!d3D12CreateDevice) {
+            qWarning("Symbol D3D12CreateDevice could not be resolved, RhiD3D12 will not be available. Is DirectX 12 installed?");
+            return false;
+        }
+
+
+        hr = d3D12CreateDevice(activeAdapter,
                                minimumFeatureLevel,
                                __uuidof(ID3D12Device2),
                                reinterpret_cast<void **>(&dev));
@@ -2819,7 +2867,12 @@ bool QD3D12MipmapGenerator::create(QRhiD3D12 *rhiD)
     rsDesc.Desc_1_1.pStaticSamplers = &samplerDesc;
 
     ID3DBlob *signature = nullptr;
-    HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
+    if (!d3D12SerializeVersionedRootSignature) {
+        qWarning("Could not resolve D3D12SerializeVersionedRootSignature. Is D3D12 properly installed?");
+        return false;
+    }
+
+    HRESULT hr = d3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
     if (FAILED(hr)) {
         qWarning("Failed to serialize root signature: %s", qPrintable(QSystemError::windowsComString(hr)));
         return false;
@@ -5096,7 +5149,11 @@ QD3D12ObjectHandle QD3D12ShaderResourceBindings::createRootSignature(const QD3D1
     rsDesc.Desc_1_1.Flags = D3D12_ROOT_SIGNATURE_FLAGS(rsFlags);
 
     ID3DBlob *signature = nullptr;
-    HRESULT hr = D3D12SerializeVersionedRootSignature(&rsDesc, &signature, nullptr);
+    if (!d3D12SerializeVersionedRootSignature) {
+        qWarning("Could not resolve D3D12SerializeVersionedRootSignature. Is D3D12 properly installed?");
+        return {};
+    }
+    HRESULT hr = d3D12SerializeVersionedRootSignature(&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..58af4939252 100644
--- a/src/gui/text/windows/qwindowsfontdatabasebase.cpp
+++ b/src/gui/text/windows/qwindowsfontdatabasebase.cpp
@@ -6,6 +6,7 @@
 
 #include <QtCore/QThreadStorage>
 #include <QtCore/QtEndian>
+#include <QtCore/private/qsystemlibrary_p.h>
 
 #if QT_CONFIG(directwrite)
 #  if QT_CONFIG(directwrite3)
@@ -715,7 +716,18 @@ 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 (*SystemParametersInfoForDpiCompat)(UINT, UINT, PVOID, UINT, UINT);
+    static SystemParametersInfoForDpiCompat systemParametersInfoForDpi = []() {
+        QSystemLibrary user32dll(QLatin1String("user32"));
+        return (SystemParametersInfoForDpiCompat)(user32dll.resolve("SystemParametersInfoForDpi"));
+    }();
+
+    if (systemParametersInfoForDpi)
+        systemParametersInfoForDpi(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/plugins/networkinformation/networklistmanager/CMakeLists.txt b/src/plugins/networkinformation/networklistmanager/CMakeLists.txt
index acd3754f4e5..3c80ad3e1a2 100644
--- a/src/plugins/networkinformation/networklistmanager/CMakeLists.txt
+++ b/src/plugins/networkinformation/networklistmanager/CMakeLists.txt
@@ -16,7 +16,6 @@ qt_internal_add_plugin(QNLMNIPlugin
 
 qt_internal_extend_target(QNLMNIPlugin CONDITION WIN32
     LIBRARIES
-        runtimeobject
         oleaut32
 )
 
diff --git a/src/plugins/platforms/direct2d/CMakeLists.txt b/src/plugins/platforms/direct2d/CMakeLists.txt
index 278af74af0b..e2f1969a321 100644
--- a/src/plugins/platforms/direct2d/CMakeLists.txt
+++ b/src/plugins/platforms/direct2d/CMakeLists.txt
@@ -75,10 +75,8 @@ qt_internal_add_plugin(QWindowsDirect2DIntegrationPlugin
         winmm
         winspool
         wtsapi32
-        shcore
         comdlg32
         d3d9
-        runtimeobject
 )
 
 # Resources:
diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
index 307ca2e550d..8f1199e2291 100644
--- a/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
+++ b/src/plugins/platforms/direct2d/qwindowsdirect2dcontext.cpp
@@ -2,6 +2,7 @@
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
 
 #include <QtCore/qt_windows.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 #include "qwindowsdirect2dcontext.h"
 #include "qwindowsdirect2dhelpers.h"
 #include "qwindowsdirect2dintegration.h"
diff --git a/src/plugins/platforms/windows/CMakeLists.txt b/src/plugins/platforms/windows/CMakeLists.txt
index cc4460cb182..fb725ea6061 100644
--- a/src/plugins/platforms/windows/CMakeLists.txt
+++ b/src/plugins/platforms/windows/CMakeLists.txt
@@ -62,10 +62,8 @@ qt_internal_add_plugin(QWindowsIntegrationPlugin
         winmm
         winspool
         wtsapi32
-        shcore
         comdlg32
         d3d9
-        runtimeobject
 )
 
 # Resources:
diff --git a/src/plugins/platforms/windows/qtwindowsglobal.h b/src/plugins/platforms/windows/qtwindowsglobal.h
index 96a72600eb9..067069d8de0 100644
--- a/src/plugins/platforms/windows/qtwindowsglobal.h
+++ b/src/plugins/platforms/windows/qtwindowsglobal.h
@@ -60,6 +60,10 @@
 #  define DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED    ((HANDLE)-5)
 #endif
 
+#ifndef WM_DPICHANGED_AFTERPARENT
+#define WM_DPICHANGED_AFTERPARENT 0x02E3
+#endif
+
 QT_BEGIN_NAMESPACE
 
 namespace QtWindows
diff --git a/src/plugins/platforms/windows/qwin10helpers.cpp b/src/plugins/platforms/windows/qwin10helpers.cpp
index 026e81cb0c7..78c9bf2ea04 100644
--- a/src/plugins/platforms/windows/qwin10helpers.cpp
+++ b/src/plugins/platforms/windows/qwin10helpers.cpp
@@ -4,6 +4,7 @@
 #include "qwin10helpers.h"
 
 #include <QtCore/qdebug.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 #include <winstring.h>
 #include <roapi.h>
 
@@ -69,14 +70,33 @@ bool qt_windowsIsTabletMode(HWND hwnd)
     HSTRING_HEADER uiViewSettingsIdRefHeader;
     HSTRING uiViewSettingsIdHs = nullptr;
     const auto uiViewSettingsIdLen = UINT32(sizeof(uiViewSettingsId) / sizeof(uiViewSettingsId[0]) - 1);
-    if (FAILED(WindowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader,&nbsp;&uiViewSettingsIdHs)))
+
+    typedef HRESULT (*WindowsCreateStringReferenceCompat)(PCWSTR, UINT32, HSTRING_HEADER*, HSTRING*);
+    static WindowsCreateStringReferenceCompat windowsCreateStringReference = []() {
+        QSystemLibrary winrtstringapisetdll(QLatin1String("api-ms-win-core-winrt-string-l1-1-0"));
+        return (WindowsCreateStringReferenceCompat)(winrtstringapisetdll.resolve("WindowsCreateStringReference"));
+    }();
+
+    if (!windowsCreateStringReference)
+        return false;
+
+    if (FAILED(windowsCreateStringReference(uiViewSettingsId, uiViewSettingsIdLen, &uiViewSettingsIdRefHeader,&nbsp;&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,
+    typedef HRESULT (*RoGetActivationFactoryCompat)(HSTRING, REFIID, void **);
+    static RoGetActivationFactoryCompat roGetActivationFactory = []() {
+        QSystemLibrary combasedll(QLatin1String("combase"));
+        return (RoGetActivationFactoryCompat)(combasedll.resolve("RoGetActivationFactory"));
+    }();
+
+    if (!roGetActivationFactory)
+        return false;
+
+    HRESULT hr = roGetActivationFactory(uiViewSettingsIdHs, uiViewSettingsInteropRefId,
                                                    reinterpret_cast<void **>(&uiViewSettingsInterop));
     if (FAILED(hr))
         return false;
diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp
index 88e9da5557c..82433b04fdc 100644
--- a/src/plugins/platforms/windows/qwindowscontext.cpp
+++ b/src/plugins/platforms/windows/qwindowscontext.cpp
@@ -43,6 +43,8 @@
 #include <QtCore/qsysinfo.h>
 #include <QtCore/qscopedpointer.h>
 #include <QtCore/quuid.h>
+#include <QtCore/qoperatingsystemversion.h>
+#include <QtCore/private/qsystemlibrary_p.h>
 #include <QtCore/private/qwinregistry_p.h>
 #if QT_CONFIG(cpp_winrt)
 #  include <QtCore/private/qfactorycacheregistration_p.h>
@@ -120,6 +122,85 @@ static inline bool sessionManagerInteractionBlocked()
 static inline bool sessionManagerInteractionBlocked() { return false; }
 #endif
 
+static inline int windowDpiAwareness(HWND hwnd)
+{
+    return QWindowsContext::user32dll.getWindowDpiAwarenessContext && QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext
+        ? QWindowsContext::user32dll.getAwarenessFromDpiAwarenessContext(QWindowsContext::user32dll.getWindowDpiAwarenessContext(hwnd))
+        : -1;
+}
+
+/*!
+    \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");
+    areDpiAwarenessContextsEqual = (AreDpiAwarenessContextsEqual)library.resolve("AreDpiAwarenessContextsEqual");
+    isValidDpiAwarenessContext = (IsValidDpiAwarenessContext)library.resolve("IsValidDpiAwarenessContext");
+
+    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)) {
+        adjustWindowRectEx = (AdjustWindowRectEx)library.resolve("AdjustWindowRectEx");
+        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 +241,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);
@@ -336,29 +420,31 @@ void QWindowsContext::setDetectAltGrModifier(bool a)
 }
 
 [[nodiscard]] static inline QtWindows::DpiAwareness
-    dpiAwarenessContextToQtDpiAwareness(DPI_AWARENESS_CONTEXT context)
+    dpiAwarenessContextToQtDpiAwareness(PVOID context)
 {
     // IsValidDpiAwarenessContext() will handle the NULL pointer case.
-    if (!IsValidDpiAwarenessContext(context))
+    if (!QWindowsContext::user32dll.isValidDpiAwarenessContext ||
+        !QWindowsContext::user32dll.areDpiAwarenessContextsEqual ||
+        !QWindowsContext::user32dll.isValidDpiAwarenessContext(context))
         return QtWindows::DpiAwareness::Invalid;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
+    if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE_GDISCALED))
         return QtWindows::DpiAwareness::Unaware_GdiScaled;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
+    if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2))
         return QtWindows::DpiAwareness::PerMonitorVersion2;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
+    if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE))
         return QtWindows::DpiAwareness::PerMonitor;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
+    if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_SYSTEM_AWARE))
         return QtWindows::DpiAwareness::System;
-    if (AreDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
+    if (QWindowsContext::user32dll.areDpiAwarenessContextsEqual(context, DPI_AWARENESS_CONTEXT_UNAWARE))
         return QtWindows::DpiAwareness::Unaware;
     return QtWindows::DpiAwareness::Invalid;
 }
 
 QtWindows::DpiAwareness QWindowsContext::windowDpiAwareness(HWND hwnd)
 {
-    if (!hwnd)
+    if (!user32dll.getWindowDpiAwarenessContext || !hwnd)
         return QtWindows::DpiAwareness::Invalid;
-    const auto context = GetWindowDpiAwarenessContext(hwnd);
+    const auto context = user32dll.getWindowDpiAwarenessContext(hwnd);
     return dpiAwarenessContextToQtDpiAwareness(context);
 }
 
@@ -371,7 +457,10 @@ 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();
+    if (!user32dll.getThreadDpiAwarenessContext)
+        return QtWindows::DpiAwareness::Invalid;
+
+    const auto context = user32dll.getThreadDpiAwarenessContext();
     return dpiAwarenessContextToQtDpiAwareness(context);
 }
 
@@ -431,11 +520,11 @@ bool QWindowsContext::setProcessDpiAwareness(QtWindows::DpiAwareness dpiAwarenes
     if (processDpiAwareness() == dpiAwareness)
         return true;
     const auto context = qtDpiAwarenessToDpiAwarenessContext(dpiAwareness);
-    if (!IsValidDpiAwarenessContext(context)) {
+    if (!user32dll.isValidDpiAwarenessContext || !user32dll.isValidDpiAwarenessContext(context)) {
         qCWarning(lcQpaWindow) << dpiAwareness << "is not supported by current system.";
         return false;
     }
-    if (!SetProcessDpiAwarenessContext(context)) {
+    if (!user32dll.setProcessDpiAwarenessContext || !user32dll.setProcessDpiAwarenessContext(context)) {
         qCWarning(lcQpaWindow).noquote().nospace()
             << "SetProcessDpiAwarenessContext() failed: "
             << QSystemError::windowsString()
@@ -868,8 +957,8 @@ 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)
+    const BOOL result = QWindowsContext::user32dll.systemParametersInfoForDpi != nullptr && dpi != 0
+        ? QWindowsContext::user32dll.systemParametersInfoForDpi(action, param, out, 0, dpi)
         : SystemParametersInfo(action, param, out, 0);
     return result == TRUE;
 }
@@ -957,7 +1046,8 @@ static bool enableNonClientDpiScaling(HWND hwnd)
 {
     bool result = false;
     if (QWindowsContext::windowDpiAwareness(hwnd) == QtWindows::DpiAwareness::PerMonitor) {
-        result = EnableNonClientDpiScaling(hwnd) != FALSE;
+        if (QWindowsContext::user32dll.enableNonClientDpiScaling)
+            result = QWindowsContext::user32dll.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..1916868ba0b 100644
--- a/src/plugins/platforms/windows/qwindowscontext.h
+++ b/src/plugins/platforms/windows/qwindowscontext.h
@@ -44,6 +44,98 @@ 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)(PVOID);
+    typedef BOOL (WINAPI *AddClipboardFormatListener)(HWND);
+    typedef BOOL (WINAPI *RemoveClipboardFormatListener)(HWND);
+    typedef BOOL (WINAPI *GetDisplayAutoRotationPreferences)(DWORD *);
+    typedef BOOL (WINAPI *SetDisplayAutoRotationPreferences)(DWORD);
+    typedef BOOL (WINAPI *AdjustWindowRectEx)(LPRECT,DWORD,BOOL,DWORD);
+    typedef BOOL (WINAPI *AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UINT);
+    typedef BOOL (WINAPI *EnableNonClientDpiScaling)(HWND);
+    typedef PVOID  (WINAPI *GetWindowDpiAwarenessContext)(HWND);
+    typedef int  (WINAPI *GetAwarenessFromDpiAwarenessContext)(PVOID);
+    typedef BOOL (WINAPI *SystemParametersInfoForDpi)(UINT, UINT, PVOID, UINT, UINT);
+    typedef int  (WINAPI *GetDpiForWindow)(HWND);
+    typedef BOOL (WINAPI *GetSystemMetricsForDpi)(INT, UINT);
+    typedef BOOL (WINAPI *AreDpiAwarenessContextsEqual)(PVOID, PVOID);
+    typedef PVOID  (WINAPI *GetThreadDpiAwarenessContext)();
+    typedef BOOL (WINAPI *IsValidDpiAwarenessContext)(PVOID);
+
+    // 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;
+
+    // Windows 10 version 1703 onwards
+    SetProcessDpiAwarenessContext setProcessDpiAwarenessContext = nullptr;
+    AreDpiAwarenessContextsEqual areDpiAwarenessContextsEqual = nullptr;
+
+    IsValidDpiAwarenessContext isValidDpiAwarenessContext = 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;
+
+    AdjustWindowRectEx adjustWindowRectEx = 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,int *);
+    typedef HRESULT (WINAPI *SetProcessDpiAwareness)(int);
+    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 +226,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..b75c7122987 100644
--- a/src/plugins/platforms/windows/qwindowsdrag.cpp
+++ b/src/plugins/platforms/windows/qwindowsdrag.cpp
@@ -1,6 +1,11 @@
 // 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
 
+# if !defined(WINVER) || (WINVER < 0x0602)
+#  undef WINVER
+#  define WINVER 0x0602
+# endif
+
 #include <QtCore/qt_windows.h>
 #include "qwindowsdrag.h"
 #include "qwindowscontext.h"
@@ -670,11 +675,14 @@ static HRESULT startDoDragDrop(LPDATAOBJECT pDataObj, LPDROPSOURCE pDropSource,
             }
 
             if (msg.message == WM_POINTERUPDATE) {
+                if (!QWindowsContext::user32dll.getPointerInfo)
+                    return E_FAIL;
 
                 const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
 
                 POINTER_INFO pointerInfo{};
-                if (!GetPointerInfo(pointerId, &pointerInfo))
+
+                if (!QWindowsContext::user32dll.getPointerInfo(pointerId, &pointerInfo))
                     return E_FAIL;
 
                 if (pointerInfo.pointerFlags & POINTER_FLAG_PRIMARY) {
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index 5b8e4e58ffe..ab6b19de478 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -732,14 +732,23 @@ 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);
+    UINT dpi;
+
+    if (QWindowsContext::user32dll.getDpiForWindow)
+        dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
+    else
+        dpi = 96;
+
+    const int captionHeight = QWindowsContext::user32dll.getSystemMetricsForDpi ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYCAPTION, dpi)
+                                                                                : GetSystemMetrics(SM_CYCAPTION);
     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 = (QWindowsContext::user32dll.getSystemMetricsForDpi ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CYSIZEFRAME, dpi)
+                                                                              : GetSystemMetrics(SM_CYSIZEFRAME))
+                            + (QWindowsContext::user32dll.getSystemMetricsForDpi ? QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi)
+                                                                                : GetSystemMetrics(SM_CXPADDEDBORDER));
     return captionHeight + frameHeight;
 }
 
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index 7995716444a..e1c0eb2e58f 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -1,6 +1,11 @@
 // Copyright (C) 2019 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
 
+# if !defined(WINVER) || (WINVER < 0x0602)
+#  undef WINVER
+#  define WINVER 0x0602
+# endif
+
 #include <QtCore/qt_windows.h>
 
 #include "qwindowspointerhandler.h"
@@ -52,10 +57,17 @@ QWindowsPointerHandler::~QWindowsPointerHandler()
 
 bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, QtWindows::WindowsEventType et, MSG msg, LRESULT *result)
 {
+    if (!QWindowsContext::user32dll.getPointerType ||
+        !QWindowsContext::user32dll.getPointerFrameTouchInfo ||
+        !QWindowsContext::user32dll.getPointerFrameTouchInfoHistory ||
+        !QWindowsContext::user32dll.getPointerPenInfo ||
+        !QWindowsContext::user32dll.getPointerPenInfoHistory)
+        return false;
+
     *result = 0;
     const quint32 pointerId = GET_POINTERID_WPARAM(msg.wParam);
 
-    if (!GetPointerType(pointerId, &m_pointerType)) {
+    if (!QWindowsContext::user32dll.getPointerType(pointerId, &m_pointerType)) {
         qWarning() << "GetPointerType() failed:" << qt_error_string();
         return false;
     }
@@ -69,12 +81,12 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
     }
     case QT_PT_TOUCH: {
         quint32 pointerCount = 0;
-        if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
+        if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, nullptr)) {
             qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
             return false;
         }
         QVarLengthArray<POINTER_TOUCH_INFO, 10> touchInfo(pointerCount);
-        if (!GetPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
+        if (!QWindowsContext::user32dll.getPointerFrameTouchInfo(pointerId, &pointerCount, touchInfo.data())) {
             qWarning() << "GetPointerFrameTouchInfo() failed:" << qt_error_string();
             return false;
         }
@@ -87,7 +99,7 @@ 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,
+            if (!QWindowsContext::user32dll.getPointerFrameTouchInfoHistory(pointerId,
                                                  &historyCount,
                                                  &pointerCount,
                                                  touchInfo.data())) {
@@ -108,7 +120,7 @@ bool QWindowsPointerHandler::translatePointerEvent(QWindow *window, HWND hwnd, Q
     }
     case QT_PT_PEN: {
         POINTER_PEN_INFO penInfo;
-        if (!GetPointerPenInfo(pointerId, &penInfo)) {
+        if (!QWindowsContext::user32dll.getPointerPenInfo(pointerId, &penInfo)) {
             qWarning() << "GetPointerPenInfo() failed:" << qt_error_string();
             return false;
         }
@@ -120,7 +132,7 @@ 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())) {
+            if (!QWindowsContext::user32dll.getPointerPenInfoHistory(pointerId, &historyCount, penInfoHistory.data())) {
                 qWarning() << "GetPointerPenInfoHistory() failed:" << qt_error_string();
                 return false;
             }
@@ -527,7 +539,8 @@ 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);
     }
 
     // Some devices send touches for each finger in a different message/frame, instead of consolidating
@@ -574,7 +587,11 @@ 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))
+
+    if (!QWindowsContext::user32dll.getPointerDeviceRects)
+        return false;
+
+    if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
         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..14d10bef072 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -43,9 +43,12 @@ static inline QDpi deviceDPI(HDC hdc)
 
 static inline QDpi monitorDPI(HMONITOR hMonitor)
 {
+    if (!QWindowsContext::shcoredll.getDpiForMonitor)
+        return QDpi(96, 96);
+
     UINT dpiX;
     UINT dpiY;
-    if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
+    if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY)))
         return QDpi(dpiX, dpiY);
     return {0, 0};
 }
@@ -591,6 +594,9 @@ QRect QWindowsScreen::virtualGeometry(const QPlatformScreen *screen) // cf QScre
 
 bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
 {
+    if (!QWindowsContext::user32dll.setDisplayAutoRotationPreferences)
+        return false;
+
     bool result = false;
     ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
     switch (o) {
@@ -609,7 +615,10 @@ bool QWindowsScreen::setOrientationPreference(Qt::ScreenOrientation o)
         orientationPreference = ORIENTATION_PREFERENCE_LANDSCAPE_FLIPPED;
         break;
     }
-    result = SetDisplayAutoRotationPreferences(orientationPreference);
+
+    static_assert(sizeof(ORIENTATION_PREFERENCE) == sizeof(DWORD), "Incompatible ORIENTATION_PREFERENCE <-> DWORD. Change qwindowscontext_p.h instead of casting.");
+
+    result = QWindowsContext::user32dll.setDisplayAutoRotationPreferences((DWORD)(orientationPreference));
     return result;
 }
 
@@ -617,7 +626,10 @@ Qt::ScreenOrientation QWindowsScreen::orientationPreference()
 {
     Qt::ScreenOrientation result = Qt::PrimaryOrientation;
     ORIENTATION_PREFERENCE orientationPreference = ORIENTATION_PREFERENCE_NONE;
-    if (GetDisplayAutoRotationPreferences(&orientationPreference)) {
+
+    static_assert(sizeof(ORIENTATION_PREFERENCE) == sizeof(DWORD), "Incompatible ORIENTATION_PREFERENCE <-> DWORD. Change qwindowscontext_p.h instead of casting.");
+
+    if (QWindowsContext::user32dll.getDisplayAutoRotationPreferences && QWindowsContext::user32dll.getDisplayAutoRotationPreferences((DWORD*)(&orientationPreference))) {
         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..72f78c114fa 100644
--- a/src/plugins/platforms/windows/qwindowstheme.cpp
+++ b/src/plugins/platforms/windows/qwindowstheme.cpp
@@ -738,7 +738,11 @@ 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
+        SystemParametersInfo(SPI_GETICONTITLELOGFONT, sizeof(lfIconTitleFont), &lfIconTitleFont, 0);
     const QFont iconTitleFont = QWindowsFontDatabase::LOGFONT_to_QFont(lfIconTitleFont, dpi);
 
     m_fonts[SystemFont] = new QFont(QWindowsFontDatabase::systemDefaultFont());
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index f44a28f5636..06d7c7c5ad0 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -150,7 +150,7 @@ static QByteArray debugWinExStyle(DWORD exStyle)
         rc += " WS_EX_NOACTIVATE";
     if (exStyle & WS_EX_NOPARENTNOTIFY)
         rc += " WS_EX_NOPARENTNOTIFY";
-    if (exStyle & WS_EX_NOREDIRECTIONBITMAP)
+    if (exStyle & 0x00200000L /* WS_EX_NOREDIRECTIONBITMAP */)
         rc += " WS_EX_NOREDIRECTIONBITMAP";
     if (exStyle & WS_EX_RIGHT)
         rc += " WS_EX_RIGHT";
@@ -525,8 +525,11 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
     // 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)
+        return QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi)
+                + QWindowsContext::user32dll.getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+    else
+        return GetSystemMetrics(SM_CXSIZEFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER);
 }
 
 /*!
@@ -536,11 +539,14 @@ static inline void updateGLWindowSettings(const QWindow *w, HWND hwnd, Qt::Windo
 
 static QMargins invisibleMargins(QPoint screenPoint)
 {
+    if (!QWindowsContext::shcoredll.getDpiForMonitor)
+        return QMargins();
+
     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))) {
+        if (SUCCEEDED(QWindowsContext::shcoredll.getDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
             const int gap = getResizeBorderThickness(dpiX);
             return QMargins(gap, 0, gap, gap);
         }
@@ -550,7 +556,12 @@ static QMargins invisibleMargins(QPoint screenPoint)
 
 [[nodiscard]] static inline QMargins invisibleMargins(const HWND hwnd)
 {
-    const UINT dpi = GetDpiForWindow(hwnd);
+    UINT dpi;
+    if (QWindowsContext::user32dll.getDpiForWindow)
+        dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
+    else
+        dpi = 96;
+
     const int gap = getResizeBorderThickness(dpi);
     return QMargins(gap, 0, gap, gap);
 }
@@ -843,7 +854,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
 
         // Currently only compatible with D3D surfaces, use it with care.
         if (qEnvironmentVariableIntValue("QT_QPA_DISABLE_REDIRECTION_SURFACE"))
-            exStyle |= WS_EX_NOREDIRECTIONBITMAP;
+            exStyle |= 0x00200000L /* WS_EX_NOREDIRECTIONBITMAP */;
     }
 }
 
@@ -1071,7 +1082,14 @@ 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) {
+
+    BOOL x;
+    if (QWindowsContext::user32dll.adjustWindowRectExForDpi)
+        x = QWindowsContext::user32dll.adjustWindowRectExForDpi(&rect, style, FALSE, exStyle, unsigned(qRound(dpi)));
+    else
+        x = AdjustWindowRectEx(&rect, style, FALSE, exStyle);
+
+    if (x == FALSE) {
         qErrnoWarning("%s: AdjustWindowRectExForDpi failed", __FUNCTION__);
     }
     const QMargins result(qAbs(rect.left), qAbs(rect.top),
@@ -1588,7 +1606,14 @@ void QWindowsWindow::initialize()
             QWindowSystemInterface::handleGeometryChange<QWindowSystemInterface::SynchronousDelivery>(w, obtainedGeometry);
         }
     }
-    QWindowsWindow::setSavedDpi(GetDpiForWindow(handle()));
+
+    UINT dpi;
+    if (QWindowsContext::user32dll.getDpiForWindow)
+        dpi = QWindowsContext::user32dll.getDpiForWindow(handle());
+    else
+        dpi = 96;
+
+    QWindowsWindow::setSavedDpi(dpi);
 }
 
 QSurfaceFormat QWindowsWindow::format() const
@@ -2083,7 +2108,12 @@ void QWindowsWindow::handleDpiChanged(HWND hwnd, WPARAM wParam, LPARAM lParam)
 
 void QWindowsWindow::handleDpiChangedAfterParent(HWND hwnd)
 {
-    const UINT dpi = GetDpiForWindow(hwnd);
+    UINT dpi;
+    if (QWindowsContext::user32dll.getDpiForWindow)
+        dpi = QWindowsContext::user32dll.getDpiForWindow(hwnd);
+    else
+        dpi = 96;
+
     const qreal scale = dpiRelativeScale(dpi);
     setSavedDpi(dpi);
 
diff --git a/src/widgets/styles/qwindowsstyle.cpp b/src/widgets/styles/qwindowsstyle.cpp
index a8407add019..11a6dd0ea1d 100644
--- a/src/widgets/styles/qwindowsstyle.cpp
+++ b/src/widgets/styles/qwindowsstyle.cpp
@@ -62,6 +62,7 @@
 QT_BEGIN_NAMESPACE
 
 #if defined(Q_OS_WIN)
+#include <QtCore/private/qsystemlibrary_p.h>
 
 QT_BEGIN_INCLUDE_NAMESPACE
 #include "qt_windows.h"
@@ -261,29 +262,42 @@ int QWindowsStylePrivate::pixelMetricFromSystemDp(QStyle::PixelMetric pm, const
     // hardcode DPI to 1x 96 DPI.
     const int dpi = 96;
 
+    typedef int (*GetSystemMetricsForDpiFunc)(int, UINT);
+    static GetSystemMetricsForDpiFunc getSystemMetricsForDpi = []() {
+        QSystemLibrary user32dll(QLatin1String("user32"));
+        return (GetSystemMetricsForDpiFunc)(user32dll.resolve("GetSystemMetricsForDpi"));
+    }();
+
+    typedef BOOL (*SystemParametersInfoForDpiFunc)(UINT, UINT, PVOID, UINT, UINT);
+    static SystemParametersInfoForDpiFunc systemParametersInfoForDpi = []() {
+        QSystemLibrary user32dll(QLatin1String("user32"));
+        return (SystemParametersInfoForDpiFunc)(user32dll.resolve("SystemParametersInfoForDpi"));
+    }();
+
     switch (pm) {
     case QStyle::PM_DockWidgetFrameWidth:
-        return GetSystemMetricsForDpi(SM_CXFRAME, dpi);
+        return getSystemMetricsForDpi ? getSystemMetricsForDpi(SM_CXFRAME, dpi) : GetSystemMetrics(SM_CXFRAME);
 
     case QStyle::PM_TitleBarHeight: {
         const int resizeBorderThickness =
-            GetSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) + GetSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi);
+            (getSystemMetricsForDpi ? getSystemMetricsForDpi(SM_CXSIZEFRAME, dpi) : GetSystemMetrics(SM_CXSIZEFRAME)) +
+            (getSystemMetricsForDpi ? getSystemMetricsForDpi(SM_CXPADDEDBORDER, dpi) : GetSystemMetrics(SM_CXPADDEDBORDER));
         if (widget && (widget->windowType() == Qt::Tool))
-            return GetSystemMetricsForDpi(SM_CYSMCAPTION, dpi) + resizeBorderThickness;
-        return GetSystemMetricsForDpi(SM_CYCAPTION, dpi) + resizeBorderThickness;
+            return (getSystemMetricsForDpi ? getSystemMetricsForDpi(SM_CYSMCAPTION, dpi) : GetSystemMetrics(SM_CYSMCAPTION)) + resizeBorderThickness;
+        return (getSystemMetricsForDpi ? getSystemMetricsForDpi(SM_CYCAPTION, dpi) : GetSystemMetrics(SM_CYCAPTION)) + resizeBorderThickness;
     }
 
     case QStyle::PM_ScrollBarExtent:
         {
             NONCLIENTMETRICS ncm;
             ncm.cbSize = sizeof(NONCLIENTMETRICS);
-            if (SystemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm,&nbsp;0, dpi))
+            if (systemParametersInfoForDpi ? systemParametersInfoForDpi(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0, dpi) : SystemParametersInfo(SPI_GETNONCLIENTMETRICS, sizeof(NONCLIENTMETRICS), &ncm, 0))
                 return qMax(ncm.iScrollHeight, ncm.iScrollWidth);
         }
         break;
 
     case  QStyle::PM_MdiSubWindowFrameWidth:
-        return GetSystemMetricsForDpi(SM_CYFRAME, dpi);
+        return getSystemMetricsForDpi ? getSystemMetricsForDpi(SM_CYFRAME, dpi) : GetSystemMetrics(SM_CYFRAME);
 
     default:
         break;
-- 
2.53.0


[Dauer der Verarbeitung: 0.11 Sekunden, vorverarbeitet 2026-10-24]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104848
#Domains=416967