Remove ambiguity in handling of registry keys from setupAPI.h

QWindowsScreen uses setupAPI.h's SetupDiOpenDevRegKey function to read
EDID data for monitors. This function is documented as returning
INVALID_HANDLE_VALUE in case of failure.

The QWindowsScreen code was ambiguous in the sense that it considered
both nullptr and INVALID_HANDLE_VALUE as being invalid handle values.
This inconsistency is likely not a bug, but makes the code harder to
understand.

This patch removes this ambiguity, and QWindowsScreen now follows the
documented behavior when SetupDiOpenDevRegKey fails. In addition, we
replace use of unique_ptr with the new QUniqueHandle template class
because HKEY is a handle type, not a regular pointer type.

Pick-to: 6.5 6.6
Change-Id: Ia863bda504077e59833f6f7a0f855e7915e4edd9
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
This commit is contained in:
Jøger Hansegård 2023-11-05 13:36:32 +01:00
parent 923d09f3f1
commit 55141c59cd

View File

@ -19,6 +19,7 @@
#include <private/qhighdpiscaling_p.h> #include <private/qhighdpiscaling_p.h>
#include <private/qwindowsfontdatabasebase_p.h> #include <private/qwindowsfontdatabasebase_p.h>
#include <private/qpixmap_win_p.h> #include <private/qpixmap_win_p.h>
#include <private/quniquehandle_p.h>
#include <QtGui/qscreen.h> #include <QtGui/qscreen.h>
@ -116,16 +117,22 @@ static float getMonitorSDRWhiteLevel(DISPLAYCONFIG_PATH_TARGET_INFO *targetInfo)
using WindowsScreenDataList = QList<QWindowsScreenData>; using WindowsScreenDataList = QList<QWindowsScreenData>;
struct RegistryHandleDeleter namespace {
struct DiRegKeyHandleTraits
{ {
void operator()(HKEY handle) const noexcept using Type = HKEY;
static Type invalidValue()
{ {
if (handle != nullptr && handle != INVALID_HANDLE_VALUE) // The setupapi.h functions return INVALID_HANDLE_VALUE when failing to open a registry key
RegCloseKey(handle); return reinterpret_cast<HKEY>(INVALID_HANDLE_VALUE);
} }
static bool close(Type handle) { return RegCloseKey(handle) == ERROR_SUCCESS; }
}; };
using RegistryHandlePtr = std::unique_ptr<std::remove_pointer_t<HKEY>, RegistryHandleDeleter>; using DiRegKeyHandle = QUniqueHandle<DiRegKeyHandleTraits>;
}
static void setMonitorDataFromSetupApi(QWindowsScreenData &data, static void setMonitorDataFromSetupApi(QWindowsScreenData &data,
const std::vector<DISPLAYCONFIG_PATH_INFO> &pathGroup) const std::vector<DISPLAYCONFIG_PATH_INFO> &pathGroup)
@ -207,10 +214,10 @@ static void setMonitorDataFromSetupApi(QWindowsScreenData &data,
continue; continue;
} }
const RegistryHandlePtr edidRegistryKey{ SetupDiOpenDevRegKey( const DiRegKeyHandle edidRegistryKey{ SetupDiOpenDevRegKey(
devInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) }; devInfo, &deviceInfoData, DICS_FLAG_GLOBAL, 0, DIREG_DEV, KEY_READ) };
if (!edidRegistryKey || edidRegistryKey.get() == INVALID_HANDLE_VALUE) if (!edidRegistryKey.isValid())
continue; continue;
DWORD edidDataSize{ 0 }; DWORD edidDataSize{ 0 };