|
1 /* |
|
2 * Copyright (C) 2008 Apple Inc. All Rights Reserved. |
|
3 * |
|
4 * Redistribution and use in source and binary forms, with or without |
|
5 * modification, are permitted provided that the following conditions |
|
6 * are met: |
|
7 * 1. Redistributions of source code must retain the above copyright |
|
8 * notice, this list of conditions and the following disclaimer. |
|
9 * 2. Redistributions in binary form must reproduce the above copyright |
|
10 * notice, this list of conditions and the following disclaimer in the |
|
11 * documentation and/or other materials provided with the distribution. |
|
12 * |
|
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY |
|
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
|
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR |
|
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
|
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
|
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
|
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY |
|
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
|
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
|
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
|
24 */ |
|
25 |
|
26 #ifndef COMPropertyBag_h |
|
27 #define COMPropertyBag_h |
|
28 |
|
29 #define NOMINMAX |
|
30 #include <unknwn.h> |
|
31 |
|
32 #include <wtf/Noncopyable.h> |
|
33 #include <wtf/HashMap.h> |
|
34 |
|
35 #include "COMVariantSetter.h" |
|
36 |
|
37 template<typename ValueType, typename KeyType = typename WebCore::String, typename HashType = typename WebCore::StringHash> |
|
38 class COMPropertyBag : public IPropertyBag, public IPropertyBag2, Noncopyable { |
|
39 public: |
|
40 typedef HashMap<KeyType, ValueType, HashType> HashMapType; |
|
41 |
|
42 static COMPropertyBag* createInstance(const HashMapType&); |
|
43 static COMPropertyBag* adopt(HashMapType&); |
|
44 |
|
45 // IUnknown |
|
46 virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void** ppvObject); |
|
47 virtual ULONG STDMETHODCALLTYPE AddRef(); |
|
48 virtual ULONG STDMETHODCALLTYPE Release(); |
|
49 |
|
50 // IPropertyBag |
|
51 virtual HRESULT STDMETHODCALLTYPE Read(LPCOLESTR pszPropName, VARIANT*, IErrorLog*); |
|
52 virtual HRESULT STDMETHODCALLTYPE Write(LPCOLESTR pszPropName, VARIANT*); |
|
53 |
|
54 // IPropertyBag2 |
|
55 virtual HRESULT STDMETHODCALLTYPE Read(ULONG cProperties, PROPBAG2*, IErrorLog*, VARIANT* pvarValue, HRESULT* phrError); |
|
56 virtual HRESULT STDMETHODCALLTYPE Write(ULONG cProperties, PROPBAG2*, VARIANT*); |
|
57 virtual HRESULT STDMETHODCALLTYPE CountProperties(ULONG* pcProperties); |
|
58 virtual HRESULT STDMETHODCALLTYPE GetPropertyInfo(ULONG iProperty, ULONG cProperties, PROPBAG2* pPropBag, ULONG* pcProperties); |
|
59 virtual HRESULT STDMETHODCALLTYPE LoadObject(LPCOLESTR pstrName, DWORD dwHint, IUnknown*, IErrorLog*); |
|
60 |
|
61 private: |
|
62 COMPropertyBag() |
|
63 : m_refCount(0) |
|
64 { |
|
65 } |
|
66 |
|
67 COMPropertyBag(const HashMapType& hashMap) |
|
68 : m_refCount(0) |
|
69 , m_hashMap(hashMap) |
|
70 { |
|
71 } |
|
72 |
|
73 ~COMPropertyBag() {} |
|
74 |
|
75 ULONG m_refCount; |
|
76 HashMapType m_hashMap; |
|
77 }; |
|
78 |
|
79 // COMPropertyBag ------------------------------------------------------------------ |
|
80 template<typename ValueType, typename KeyType, typename HashType> |
|
81 COMPropertyBag<ValueType, KeyType, HashType>* COMPropertyBag<typename ValueType, typename KeyType, HashType>::createInstance(const HashMapType& hashMap) |
|
82 { |
|
83 COMPropertyBag* instance = new COMPropertyBag(hashMap); |
|
84 instance->AddRef(); |
|
85 return instance; |
|
86 } |
|
87 |
|
88 template<typename ValueType, typename KeyType, typename HashType> |
|
89 COMPropertyBag<ValueType, KeyType, HashType>* COMPropertyBag<typename ValueType, typename KeyType, HashType>::adopt(HashMapType& hashMap) |
|
90 { |
|
91 COMPropertyBag* instance = new COMPropertyBag; |
|
92 instance->m_hashMap.swap(hashMap); |
|
93 instance->AddRef(); |
|
94 return instance; |
|
95 } |
|
96 |
|
97 // IUnknown ------------------------------------------------------------------------ |
|
98 template<typename ValueType, typename KeyType, typename HashType> |
|
99 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::QueryInterface(REFIID riid, void** ppvObject) |
|
100 { |
|
101 *ppvObject = 0; |
|
102 if (IsEqualGUID(riid, IID_IUnknown)) |
|
103 *ppvObject = static_cast<IPropertyBag*>(this); |
|
104 else if (IsEqualGUID(riid, IID_IPropertyBag)) |
|
105 *ppvObject = static_cast<IPropertyBag*>(this); |
|
106 else if (IsEqualGUID(riid, IID_IPropertyBag2)) |
|
107 *ppvObject = static_cast<IPropertyBag2*>(this); |
|
108 else |
|
109 return E_NOINTERFACE; |
|
110 |
|
111 AddRef(); |
|
112 return S_OK; |
|
113 } |
|
114 |
|
115 template<typename ValueType, typename KeyType, typename HashType> |
|
116 ULONG STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::AddRef() |
|
117 { |
|
118 return ++m_refCount; |
|
119 } |
|
120 |
|
121 template<typename ValueType, typename KeyType, typename HashType> |
|
122 ULONG STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Release() |
|
123 { |
|
124 ULONG newRef = --m_refCount; |
|
125 if (!newRef) |
|
126 delete this; |
|
127 |
|
128 return newRef; |
|
129 } |
|
130 |
|
131 // IPropertyBag -------------------------------------------------------------------- |
|
132 |
|
133 template<typename ValueType, typename KeyType, typename HashType> |
|
134 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Read(LPCOLESTR pszPropName, VARIANT* pVar, IErrorLog* pErrorLog) |
|
135 { |
|
136 if (!pszPropName) |
|
137 return E_POINTER; |
|
138 |
|
139 HashMapType::const_iterator it = m_hashMap.find(String(pszPropName)); |
|
140 HashMapType::const_iterator end = m_hashMap.end(); |
|
141 if (it == end) |
|
142 return E_INVALIDARG; |
|
143 |
|
144 VARTYPE requestedType = V_VT(pVar); |
|
145 V_VT(pVar) = VT_EMPTY; |
|
146 COMVariantSetter<ValueType>::setVariant(pVar, it->second); |
|
147 |
|
148 if (requestedType != COMVariantSetter<ValueType>::variantType(it->second) && requestedType != VT_EMPTY) |
|
149 return ::VariantChangeType(pVar, pVar, VARIANT_NOUSEROVERRIDE | VARIANT_ALPHABOOL, requestedType); |
|
150 |
|
151 return S_OK; |
|
152 } |
|
153 |
|
154 template<typename ValueType, typename KeyType, typename HashType> |
|
155 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Write(LPCOLESTR pszPropName, VARIANT* pVar) |
|
156 { |
|
157 return E_FAIL; |
|
158 } |
|
159 |
|
160 template<typename ValueType, typename KeyType, typename HashType> |
|
161 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Read(ULONG cProperties, PROPBAG2* pPropBag, IErrorLog* pErrorLog, VARIANT* pvarValue, HRESULT* phrError) |
|
162 { |
|
163 if (!pPropBag || !pvarValue || !phrError) |
|
164 return E_POINTER; |
|
165 |
|
166 HRESULT hr = S_OK; |
|
167 |
|
168 for (ULONG i = 0; i < cProperties; ++i) { |
|
169 VariantInit(&pvarValue[i]); |
|
170 pvarValue[i].vt = pPropBag[i].vt; |
|
171 phrError[i] = Read(pPropBag[i].pstrName, &pvarValue[i], pErrorLog); |
|
172 if (FAILED(phrError[i])) |
|
173 hr = E_FAIL; |
|
174 } |
|
175 |
|
176 return hr; |
|
177 } |
|
178 |
|
179 template<typename ValueType, typename KeyType, typename HashType> |
|
180 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::Write(ULONG cProperties, PROPBAG2*, VARIANT*) |
|
181 { |
|
182 return E_NOTIMPL; |
|
183 } |
|
184 |
|
185 template<typename ValueType, typename KeyType, typename HashType> |
|
186 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::CountProperties(ULONG* pcProperties) |
|
187 { |
|
188 if (!pcProperties) |
|
189 return E_POINTER; |
|
190 |
|
191 *pcProperties = m_hashMap.size(); |
|
192 return S_OK; |
|
193 } |
|
194 |
|
195 template<typename ValueType, typename KeyType, typename HashType> |
|
196 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::GetPropertyInfo(ULONG iProperty, ULONG cProperties, PROPBAG2* pPropBag, ULONG* pcProperties) |
|
197 { |
|
198 if (!pPropBag || !pcProperties) |
|
199 return E_POINTER; |
|
200 |
|
201 if (m_hashMap.size() <= iProperty) |
|
202 return E_INVALIDARG; |
|
203 |
|
204 *pcProperties = 0; |
|
205 typedef HashMapType::const_iterator Iterator; |
|
206 Iterator current = m_hashMap.begin(); |
|
207 Iterator end = m_hashMap.end(); |
|
208 for (ULONG i = 0; i < iProperty; ++i, ++current) |
|
209 ; |
|
210 for (ULONG j = 0; j < cProperties && current != end; ++j, ++current) { |
|
211 // FIXME: the following fields aren't filled in |
|
212 //pPropBag[j].cfType; // (CLIPFORMAT) Clipboard format or MIME type of the property. |
|
213 //pPropBag[j].clsid; // (CLSID) CLSID of the object. This member is valid only if dwType is PROPBAG2_TYPE_OBJECT. |
|
214 |
|
215 pPropBag[j].dwType = PROPBAG2_TYPE_DATA; |
|
216 pPropBag[j].vt = COMVariantSetter<ValueType>::variantType(current->second); |
|
217 pPropBag[j].dwHint = iProperty + j; |
|
218 pPropBag[j].pstrName = (LPOLESTR)CoTaskMemAlloc(sizeof(wchar_t)*(current->first.length()+1)); |
|
219 if (!pPropBag[j].pstrName) |
|
220 return E_OUTOFMEMORY; |
|
221 wcscpy_s(pPropBag[j].pstrName, current->first.length()+1, static_cast<String>(current->first).charactersWithNullTermination()); |
|
222 ++*pcProperties; |
|
223 } |
|
224 return S_OK; |
|
225 } |
|
226 |
|
227 template<typename ValueType, typename KeyType, typename HashType> |
|
228 HRESULT STDMETHODCALLTYPE COMPropertyBag<ValueType, KeyType, HashType>::LoadObject(LPCOLESTR pstrName, DWORD dwHint, IUnknown*, IErrorLog*) |
|
229 { |
|
230 return E_NOTIMPL; |
|
231 } |
|
232 |
|
233 #endif // COMPropertyBag_h |