From 94c2859e18450b05f10f15b0a2d1058d0a5011bd Mon Sep 17 00:00:00 2001 From: Roland Rossgotterer Date: Thu, 20 Dec 2018 15:24:49 +0100 Subject: [PATCH] Replace QDBusConnection::localMachineId with QSysInfo::machineUniqueId() QSysInfo::machineUniqueId() was added in Qt 5.11 and is using DBus independent unique machine ids everywhere except on Linux. This prevents running into an assert in case DBus is not properly installed at a very early stage of the application without any chance to give the user a warning and handle it gracefully. --- src/blackmisc/blackmisc.pro | 2 + src/blackmisc/identifier.cpp | 56 ++++++++++++++++++- .../testidentifier/testidentifier.cpp | 9 +++ 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/src/blackmisc/blackmisc.pro b/src/blackmisc/blackmisc.pro index fc312c982..d3c2857e5 100644 --- a/src/blackmisc/blackmisc.pro +++ b/src/blackmisc/blackmisc.pro @@ -69,6 +69,8 @@ SOURCES += *.cpp \ win32 { LIBS *= -lShell32 -lDbghelp -lversion + # Remove the one below once the Reg functions are removed again from CIdentifier + LIBS *= -lAdvapi32 } win32-g++ { LIBS *= -lpsapi diff --git a/src/blackmisc/identifier.cpp b/src/blackmisc/identifier.cpp index 200c96bc9..50da7124c 100644 --- a/src/blackmisc/identifier.cpp +++ b/src/blackmisc/identifier.cpp @@ -10,10 +10,18 @@ #include "blackmisc/identifier.h" #include -#include #include +#include #include +#ifdef Q_OS_WIN +#include +#endif + +#ifdef Q_OS_MAC +#include +#endif + //! \private const QString &cachedLocalHostName() { @@ -21,12 +29,53 @@ const QString &cachedLocalHostName() return hostName; } +enum { + UuidStringLen = sizeof("00000000-0000-0000-0000-000000000000") +}; + +QByteArray getMachineUniqueIdImpl() +{ + // TODO RR: Remove the workaround branches as soon as the following two changes are published in 5.12.2 (TBC) + // https://codereview.qt-project.org/#/c/249256 + // https://codereview.qt-project.org/#/c/249399 + + QByteArray machineUniqueId; + #ifdef Q_OS_MAC + char uuid[UuidStringLen]; + size_t uuidlen = sizeof(uuid); + int ret = sysctlbyname("kern.uuid", uuid, &uuidlen, nullptr, 0); + if (ret == 0 && uuidlen == sizeof(uuid)) + { + machineUniqueId = QByteArray(uuid, uuidlen - 1); + } + #elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + HKEY key = nullptr; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS) + { + wchar_t buffer[UuidStringLen]; + DWORD size = sizeof(buffer); + bool ok = (RegQueryValueEx(key, L"MachineGuid", nullptr, nullptr, reinterpret_cast(buffer), &size) == ERROR_SUCCESS); + RegCloseKey(key); + if (ok) { machineUniqueId = QStringView(buffer, (size - 1) / 2).toLatin1(); } + } + #else + machineUniqueId = QSysInfo::machineUniqueId(); + #endif + return machineUniqueId; +} + +QByteArray cachedMachineUniqueId() +{ + static const QByteArray machineUniqueId = getMachineUniqueIdImpl(); + return machineUniqueId; +} + namespace BlackMisc { CIdentifier::CIdentifier(const QString &name) : ITimestampBased(QDateTime::currentMSecsSinceEpoch()), m_name(name.trimmed()), - m_machineIdBase64(QDBusConnection::localMachineId().toBase64()), + m_machineIdBase64(cachedMachineUniqueId().toBase64()), m_machineName(cachedLocalHostName()), m_processName(QCoreApplication::applicationName()), m_processId(QCoreApplication::applicationPid()) @@ -115,7 +164,7 @@ namespace BlackMisc bool CIdentifier::isFromLocalMachine() const { - return QDBusConnection::localMachineId() == getMachineId(); + return cachedMachineUniqueId() == getMachineId(); } bool CIdentifier::hasApplicationProcessId() const @@ -175,4 +224,5 @@ namespace BlackMisc { CValueObject::setPropertyByIndex(index, variant); } + } // ns diff --git a/tests/blackmisc/testidentifier/testidentifier.cpp b/tests/blackmisc/testidentifier/testidentifier.cpp index 4f41b4ac4..cfdfddc3d 100644 --- a/tests/blackmisc/testidentifier/testidentifier.cpp +++ b/tests/blackmisc/testidentifier/testidentifier.cpp @@ -32,6 +32,9 @@ namespace BlackMiscTest private slots: //! Identifier tests void identifierBasics(); + + //! Machine unique id tests + void machineUniqueId(); }; //! Test identifiable object @@ -59,6 +62,12 @@ namespace BlackMiscTest QVERIFY2(oa.identifier().getName() == q.objectName(), "Names shall be equal"); } + void CTestIdentifier::machineUniqueId() + { + CIdentifier o; + QVERIFY2(!o.getMachineId().isEmpty(), "Machine id shall never be empty! If this test failed on a supported platform, get a fallback solution!"); + } + CTestIdentifiable::CTestIdentifiable(QObject *nameObject) : CIdentifiable(nameObject) { }