blob: ac73356612e5b1daa07ad154cdfbff7621328feb (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
|
// **************************************************************************
// * This file is part of the FreeFileSync project. It is distributed under *
// * GNU General Public License: http://www.gnu.org/licenses/gpl.html *
// * Copyright (C) ZenJu (zenju AT gmx DOT de) - All Rights Reserved *
// **************************************************************************
#ifndef COM_UTILITY_HEADER
#define COM_UTILITY_HEADER
#include "com_ptr.h"
#include <string>
#include <cassert>
namespace zen
{
//get an enumeration interface as a std::vector of bound(!) ComPtr(s)
template <class T, class U>
std::vector<ComPtr<T> > convertEnum(const ComPtr<U>& enumObj); //enumObj: must have the "_NewEnum" property that supports the IEnumUnknown interface
/*
extract text from com object member function returning a single BSTR: HRESULT ComInterface::MemFun([out] BSTR *pbstr);
Example: ComPtr<...> comObj =...;
std::wstring description = getText(comObj, &IUPnPDevice::get_Description);
*/
template <class T, class MemFun>
std::wstring getText(ComPtr<T> comObj, MemFun memFun);
//RAII class handling BSTR
class Bstring
{
public:
Bstring(const std::wstring& str) { str_ = ::SysAllocStringLen(str.data(), str.length()); } //string::data() returns unmodified string potentially containing 0-values
~Bstring() { if (str_) ::SysFreeString(str_); }
const BSTR get() const { return str_; }
private:
Bstring(const Bstring&); //not implemented
Bstring& operator=(const Bstring&); //
BSTR str_;
};
//############################ inline implemenatation ##################################
template <class T, class U> inline
std::vector<ComPtr<T> > convertEnum(const ComPtr<U>& enumObj)
{
std::vector<ComPtr<T> > output;
if (enumObj)
{
ComPtr<IUnknown> unknown;
enumObj->get__NewEnum(unknown.init());
ComPtr<IEnumUnknown> enumUnknown = com_dynamic_cast<IEnumUnknown>(unknown);
assert(enumUnknown); //IEnumUnknown must be supported!
if (enumUnknown)
{
ComPtr<IUnknown> itemTmp;
while (enumUnknown->Next(1, itemTmp.init(), nullptr) == S_OK) //returns S_FALSE == 1 when finished! Don't use SUCCEEDED()!!!
{
ComPtr<T> itemNew = com_dynamic_cast<T>(itemTmp);
if (itemNew)
output.push_back(itemNew);
}
}
}
return output;
}
template <class T, class MemFun> inline
std::wstring getText(ComPtr<T> comObj, MemFun memFun)
{
std::wstring text;
{
if (!comObj)
return std::wstring();
BSTR bstr = nullptr;
if (FAILED((comObj.get()->*memFun)(&bstr)))
return std::wstring();
if (bstr) //nullptr means "no text"
{
text = std::wstring(bstr, ::SysStringLen(bstr)); //correctly copy 0-characters
::SysFreeString(bstr);
}
}
return text;
}
}
#endif //COM_UTILITY_HEADER
|