Skip to content

Commit db1b0f8

Browse files
committed
Update PropVariant
1 parent ccda400 commit db1b0f8

File tree

6 files changed

+57
-29
lines changed

6 files changed

+57
-29
lines changed

src/comhelpers.h

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,57 @@
11
#ifndef COMHELPERS_H
22
#define COMHELPERS_H
33

4+
#include <cassert>
5+
#include <string>
6+
#include <string_view>
47
#include <utility>
58
#include <windows.h>
69

710

811
class PropVariant {
9-
PROPVARIANT mProp;
12+
PROPVARIANT mProp{};
1013

1114
public:
1215
PropVariant() { PropVariantInit(&mProp); }
13-
PropVariant(const PropVariant&) = delete;
16+
PropVariant(const PropVariant &rhs) : PropVariant{} { PropVariantCopy(&mProp, &rhs.mProp); }
1417
~PropVariant() { clear(); }
1518

16-
PropVariant& operator=(const PropVariant&) = delete;
19+
auto operator=(const PropVariant &rhs) -> PropVariant&
20+
{
21+
if(this != &rhs)
22+
PropVariantCopy(&mProp, &rhs.mProp);
23+
return *this;
24+
}
1725

1826
void clear() { PropVariantClear(&mProp); }
1927

20-
PROPVARIANT* get() noexcept { return &mProp; }
28+
auto get() noexcept -> PROPVARIANT* { return &mProp; }
2129

22-
PROPVARIANT& operator*() noexcept { return mProp; }
23-
const PROPVARIANT& operator*() const noexcept { return mProp; }
30+
/* NOLINTBEGIN(cppcoreguidelines-pro-type-union-access) */
31+
[[nodiscard]]
32+
auto type() const noexcept -> VARTYPE { return mProp.vt; }
2433

25-
PROPVARIANT* operator->() noexcept { return &mProp; }
26-
const PROPVARIANT* operator->() const noexcept { return &mProp; }
34+
template<typename T> [[nodiscard]]
35+
auto value() const -> T
36+
{
37+
if constexpr(std::is_same_v<T,UINT>)
38+
{
39+
assert(mProp.vt == VT_UI4 || mProp.vt == VT_UINT);
40+
return mProp.uintVal;
41+
}
42+
else if constexpr(std::is_same_v<T,ULONG>)
43+
{
44+
assert(mProp.vt == VT_UI4 || mProp.vt == VT_UINT);
45+
return mProp.ulVal;
46+
}
47+
else if constexpr(std::is_same_v<T,std::wstring_view> || std::is_same_v<T,std::wstring>
48+
|| std::is_same_v<T,LPWSTR> || std::is_same_v<T,LPCWSTR>)
49+
{
50+
assert(mProp.vt == VT_LPWSTR);
51+
return mProp.pwszVal;
52+
}
53+
}
54+
/* NOLINTEND(cppcoreguidelines-pro-type-union-access) */
2755
};
2856

2957
struct ComWrapper {

src/comptr.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ struct ComPtr {
2222
explicit ComPtr(T *ptr) noexcept : mPtr{ptr} { }
2323
~ComPtr() { if(mPtr) mPtr->Release(); }
2424

25+
/* NOLINTNEXTLINE(bugprone-unhandled-self-assignment) Yes it is. */
2526
ComPtr& operator=(const ComPtr &rhs) noexcept(RefIsNoexcept)
2627
{
2728
if constexpr(RefIsNoexcept)

src/dsoal.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -255,14 +255,14 @@ ComPtr<IMMDevice> GetMMDevice(ComWrapper&, EDataFlow flow, const GUID &id)
255255

256256
PropVariant pv;
257257
hr = ps->GetValue(PKEY_AudioEndpoint_GUID, pv.get());
258-
if(FAILED(hr) || pv->vt != VT_LPWSTR)
258+
if(FAILED(hr) || pv.type() != VT_LPWSTR)
259259
{
260260
WARN("GetMMDevice IPropertyStore::GetValue(GUID) failed: %08lx\n", hr);
261261
continue;
262262
}
263263

264264
GUID devid{};
265-
CLSIDFromString(pv->pwszVal, &devid);
265+
CLSIDFromString(pv.value<const WCHAR*>(), &devid);
266266
if(id == devid) return device;
267267
}
268268

@@ -320,13 +320,13 @@ HRESULT WINAPI GetDeviceID(const GUID &guidSrc, GUID &guidDst) noexcept
320320

321321
PropVariant pv;
322322
hr = ps->GetValue(PKEY_AudioEndpoint_GUID, pv.get());
323-
if(FAILED(hr) || pv->vt != VT_LPWSTR)
323+
if(FAILED(hr) || pv.type() != VT_LPWSTR)
324324
{
325325
WARN("GetDeviceID IPropertyStore::GetValue(GUID) failed: %08lx\n", hr);
326326
return hr;
327327
}
328328

329-
CLSIDFromString(pv->pwszVal, &guidDst);
329+
CLSIDFromString(pv.value<const WCHAR*>(), &guidDst);
330330

331331
return DS_OK;
332332
}

src/dsoundoal.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,13 +60,13 @@ std::optional<DWORD> GetSpeakerConfig(IMMDevice *device)
6060
WARN("GetSpeakerConfig IPropertyStore::GetValue(PhysicalSpeakers) failed: %08lx\n", hr);
6161
return speakerconf;
6262
}
63-
if(pv->vt != VT_UI4)
63+
if(pv.type() != VT_UI4 || pv.type() != VT_UINT)
6464
{
65-
WARN("GetSpeakerConfig PhysicalSpeakers is not a ULONG: 0x%04x\n", pv->vt);
65+
WARN("GetSpeakerConfig PhysicalSpeakers is not a VT_UI4: 0x%04x\n", pv.type());
6666
return speakerconf;
6767
}
6868

69-
const ULONG phys_speakers{pv->ulVal};
69+
const auto phys_speakers = pv.value<ULONG>();
7070
pv.clear();
7171

7272
#define BIT_MATCH(v, b) (((v)&(b)) == (b))
@@ -97,9 +97,9 @@ std::optional<DWORD> GetSpeakerConfig(IMMDevice *device)
9797
hr = ps->GetValue(PKEY_AudioEndpoint_FormFactor, pv.get());
9898
if(FAILED(hr))
9999
WARN("GetSpeakerConfig IPropertyStore::GetValue(FormFactor) failed: %08lx\n", hr);
100-
else if(pv->vt != VT_UI4)
101-
WARN("GetSpeakerConfig FormFactor is not a ULONG: 0x%04x\n", pv->vt);
102-
else if(pv->ulVal == Headphones || pv->ulVal == Headset)
100+
else if(pv.type() != VT_UI4 || pv.type() != VT_UINT)
101+
WARN("GetSpeakerConfig FormFactor is not a VT_UI4: 0x%04x\n", pv.type());
102+
else if(pv.value<UINT>() == Headphones || pv.value<UINT>() == Headset)
103103
speakerconf = DSSPEAKER_HEADPHONE;
104104
}
105105

src/enumerate.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,14 @@ HRESULT enumerate_mmdev(const EDataFlow flow, std::deque<GUID> &devlist, T cb)
7070

7171
PropVariant pv;
7272
hr2 = ps->GetValue(PKEY_AudioEndpoint_GUID, pv.get());
73-
if(FAILED(hr2) || pv->vt != VT_LPWSTR)
73+
if(FAILED(hr2) || pv.type() != VT_LPWSTR)
7474
{
7575
WARN("send_device IPropertyStore::GetValue(GUID) failed: %08lx\n", hr2);
7676
return;
7777
}
7878

7979
GUID guid{};
80-
CLSIDFromString(pv->pwszVal, &guid);
80+
CLSIDFromString(pv.value<const WCHAR*>(), &guid);
8181
pv.clear();
8282

8383
if(!devlist.empty() && devlist[0] == guid)
@@ -94,8 +94,8 @@ HRESULT enumerate_mmdev(const EDataFlow flow, std::deque<GUID> &devlist, T cb)
9494
}
9595

9696
TRACE("send_device Calling back with %s - %ls\n", GuidPrinter{devlist.back()}.c_str(),
97-
pv->pwszVal);
98-
keep_going = cb(&devlist.back(), pv->pwszVal, aldriver_name);
97+
pv.value<const WCHAR*>());
98+
keep_going = cb(&devlist.back(), pv.value<const WCHAR*>(), aldriver_name);
9999
};
100100

101101
ComPtr<IMMDevice> device;

src/propset.cpp

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
#include <cstring>
44
#include <deque>
5+
#include <string_view>
56

67
#include <dsconf.h>
78
#include <mmdeviceapi.h>
@@ -17,17 +18,15 @@ namespace {
1718
using voidp = void*;
1819

1920

20-
WCHAR *strdupW(const WCHAR *str)
21+
WCHAR *strdupW(const std::wstring_view str)
2122
{
2223
void *ret;
23-
int l = lstrlenW(str);
24-
if(l < 0) return nullptr;
2524

26-
const size_t numchars{static_cast<size_t>(l)+1};
25+
const size_t numchars{str.size()+1};
2726
ret = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, numchars*sizeof(WCHAR));
2827
if(!ret) return nullptr;
2928

30-
std::memcpy(ret, str, numchars*sizeof(WCHAR));
29+
std::memcpy(ret, str.data(), numchars*sizeof(WCHAR));
3130
return static_cast<WCHAR*>(ret);
3231
}
3332

@@ -120,14 +119,14 @@ HRESULT DSPROPERTY_DescriptionW(void *pPropData, ULONG cbPropData, ULONG *pcbRet
120119

121120
PropVariant pv;
122121
hr = ps->GetValue(ds::bit_cast<PROPERTYKEY>(DEVPKEY_Device_FriendlyName), pv.get());
123-
if(FAILED(hr) || pv->vt != VT_LPWSTR)
122+
if(FAILED(hr) || pv.type() != VT_LPWSTR)
124123
{
125124
WARN(PREFIX "IPropertyStore::GetValue(FriendlyName) failed: %08lx\n", hr);
126125
return hr;
127126
}
128127

129128
ppd->Type = DIRECTSOUNDDEVICE_TYPE_WDM;
130-
ppd->Description = strdupW(pv->pwszVal);
129+
ppd->Description = strdupW(pv.value<std::wstring_view>());
131130
ppd->Module = strdupW(aldriver_name);
132131
ppd->Interface = strdupW(L"Interface");
133132

0 commit comments

Comments
 (0)