Sine Striker
2023-12-29 6eb2efea00eb07ce3a6b089b984885ce4a08c9ca
src/core/qwindowkit_windows.cpp
@@ -2,17 +2,85 @@
namespace QWK {
    RTL_OSVERSIONINFOW GetRealOSVersion() {
        static const auto result = []() -> RTL_OSVERSIONINFOW {
            HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
            using RtlGetVersionPtr = NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW);
            auto pRtlGetVersion = reinterpret_cast<RtlGetVersionPtr>(::GetProcAddress(hMod, "RtlGetVersion"));
            RTL_OSVERSIONINFOW rovi{};
            rovi.dwOSVersionInfoSize = sizeof(rovi);
            pRtlGetVersion(&rovi);
            return rovi;
        }();
    static RTL_OSVERSIONINFOW GetRealOSVersionImpl() {
        HMODULE hMod = ::GetModuleHandleW(L"ntdll.dll");
        using RtlGetVersionPtr = NTSTATUS(WINAPI *)(PRTL_OSVERSIONINFOW);
        auto pRtlGetVersion =
            reinterpret_cast<RtlGetVersionPtr>(::GetProcAddress(hMod, "RtlGetVersion"));
        RTL_OSVERSIONINFOW rovi{};
        rovi.dwOSVersionInfoSize = sizeof(rovi);
        pRtlGetVersion(&rovi);
        return rovi;
    }
    namespace Private {
        RTL_OSVERSIONINFOW GetRealOSVersion() {
            static const auto result = GetRealOSVersionImpl();
            return result;
        }
    }
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
    WindowsRegistryKey::WindowsRegistryKey(HKEY parentHandle, QStringView subKey,
                                           REGSAM permissions, REGSAM access) {
        if (::RegOpenKeyExW(parentHandle, reinterpret_cast<const wchar_t *>(subKey.utf16()), 0,
                            permissions | access, &m_key) != ERROR_SUCCESS) {
            m_key = nullptr;
        }
    }
    WindowsRegistryKey::~WindowsRegistryKey() {
        close();
    }
    void WindowsRegistryKey::close() {
        if (isValid()) {
            ::RegCloseKey(m_key);
            m_key = nullptr;
        }
    }
    QString WindowsRegistryKey::stringValue(QStringView subKey) const {
        QString result;
        if (!isValid())
            return result;
        DWORD type;
        DWORD size;
        auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
        if (::RegQueryValueExW(m_key, subKeyC, nullptr, &type, nullptr, &size) != ERROR_SUCCESS ||
            (type != REG_SZ && type != REG_EXPAND_SZ) || size <= 2) {
            return result;
        }
        // Reserve more for rare cases where trailing '\0' are missing in registry.
        // Rely on 0-termination since strings of size 256 padded with 0 have been
        // observed (QTBUG-84455).
        size += 2;
        QVarLengthArray<unsigned char> buffer(static_cast<int>(size));
        std::fill(buffer.data(), buffer.data() + size, 0u);
        if (::RegQueryValueExW(m_key, subKeyC, nullptr, &type, buffer.data(), &size) ==
            ERROR_SUCCESS)
            result = QString::fromWCharArray(reinterpret_cast<const wchar_t *>(buffer.constData()));
        return result;
    }
    QPair<DWORD, bool> WindowsRegistryKey::dwordValue(QStringView subKey) const {
        if (!isValid())
            return qMakePair(0, false);
        DWORD type;
        auto subKeyC = reinterpret_cast<const wchar_t *>(subKey.utf16());
        if (::RegQueryValueExW(m_key, subKeyC, nullptr, &type, nullptr, nullptr) != ERROR_SUCCESS ||
            type != REG_DWORD) {
            return qMakePair(0, false);
        }
        DWORD value = 0;
        DWORD size = sizeof(value);
        const bool ok =
            ::RegQueryValueExW(m_key, subKeyC, nullptr, nullptr,
                               reinterpret_cast<unsigned char *>(&value), &size) == ERROR_SUCCESS;
        return qMakePair(value, ok);
    }
#endif
}