Revision control
Copy as Markdown
// Copyright (C) 2025 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 "qwindows_propertystore_p.h"
#include <QtCore/qstring.h>
#include <QtCore/qdebug.h>
#include <QtCore/private/qsystemerror_p.h>
#include <QtMultimedia/private/qcomtaskresource_p.h>
#include <QtMultimedia/private/qwindows_scopedpropvariant_p.h>
#include <mmdeviceapi.h>
#include <propsys.h>
#include <propvarutil.h>
QT_BEGIN_NAMESPACE
namespace QtMultimediaPrivate {
PropertyStoreHelper::PropertyStoreHelper(ComPtr<IPropertyStore> props) : m_props(std::move(props))
{
}
q23::expected<PropertyStoreHelper, QString>
PropertyStoreHelper::open(const ComPtr<IMMDevice> &device)
{
ComPtr<IPropertyStore> props;
HRESULT hr = device->OpenPropertyStore(STGM_READ, props.GetAddressOf());
if (!SUCCEEDED(hr)) {
return q23::unexpected{ QSystemError::windowsComString(hr) };
}
return PropertyStoreHelper(std::move(props));
}
std::optional<QString> PropertyStoreHelper::getString(const PROPERTYKEY &property)
{
ScopedPropVariant variant;
if (!SUCCEEDED(m_props->GetValue(property, variant.get())))
return std::nullopt;
QComTaskResource<WCHAR> str;
HRESULT hr = PropVariantToStringAlloc(*variant, str.address());
if (SUCCEEDED(hr))
return QString::fromWCharArray(variant->pwszVal);
qWarning() << "PropertyStoreHelper::getString: PropVariantToStringAlloc failed"
<< QSystemError::windowsComString(hr);
return std::nullopt;
}
std::optional<uint32_t> PropertyStoreHelper::getUInt32(const PROPERTYKEY &property)
{
ScopedPropVariant variant;
if (!SUCCEEDED(m_props->GetValue(property, variant.get())))
return std::nullopt;
ULONG ret;
HRESULT hr = PropVariantToUInt32(*variant, &ret);
if (SUCCEEDED(hr))
return uint32_t{ ret };
qWarning() << "PropertyStoreHelper::getUInt32: PropVariantToUInt32 failed"
<< QSystemError::windowsComString(hr);
return std::nullopt;
}
namespace {
// mingw workaround: PropVariantToGUID does not provide correct signature
auto wrapPropVariantArg(const PROPVARIANT &arg)
{
if constexpr (std::is_invocable_v<decltype(PropVariantToGUID), const PROPVARIANT *, GUID *>)
return &arg;
else
return arg;
}
} // namespace
std::optional<QUuid> PropertyStoreHelper::getGUID(const PROPERTYKEY &property)
{
ScopedPropVariant variant;
if (!SUCCEEDED(m_props->GetValue(property, variant.get())))
return std::nullopt;
GUID ret;
HRESULT hr = PropVariantToGUID(wrapPropVariantArg(*variant), &ret);
if (SUCCEEDED(hr))
return QUuid{ ret };
qWarning() << "PropertyStoreHelper::getGUID: PropVariantToGUID failed"
<< QSystemError::windowsComString(hr);
return std::nullopt;
}
} // namespace QtMultimediaPrivate
QT_END_NAMESPACE