1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | |
5 | |
6 | #ifndef _WRAPPERS_H_ |
7 | #define _WRAPPERS_H_ |
8 | |
9 | #include "metadata.h" |
10 | #include "interoputil.h" |
11 | #ifdef FEATURE_COMINTEROP |
12 | #include "windowsstring.h" |
13 | #endif |
14 | |
15 | class MDEnumHolder |
16 | { |
17 | public: |
18 | inline MDEnumHolder(IMDInternalImport* IMDII) |
19 | { |
20 | CONTRACTL |
21 | { |
22 | NOTHROW; |
23 | GC_NOTRIGGER; |
24 | MODE_ANY; |
25 | PRECONDITION(CheckPointer(IMDII)); |
26 | } |
27 | CONTRACTL_END; |
28 | |
29 | m_IMDII = IMDII; |
30 | |
31 | } |
32 | |
33 | inline ~MDEnumHolder() |
34 | { |
35 | WRAPPER_NO_CONTRACT; |
36 | m_IMDII->EnumClose(&m_HEnum); |
37 | } |
38 | |
39 | inline operator HENUMInternal() |
40 | { |
41 | LIMITED_METHOD_CONTRACT; |
42 | return m_HEnum; |
43 | } |
44 | |
45 | inline HENUMInternal* operator&() |
46 | { |
47 | LIMITED_METHOD_CONTRACT; |
48 | return static_cast<HENUMInternal*>(&m_HEnum); |
49 | } |
50 | |
51 | private: |
52 | MDEnumHolder() {LIMITED_METHOD_CONTRACT;} // Must use parameterized constructor |
53 | |
54 | HENUMInternal m_HEnum; |
55 | IMDInternalImport* m_IMDII; |
56 | }; |
57 | |
58 | |
59 | //-------------------------------------------------------------------------------- |
60 | // safe variant helper |
61 | void SafeVariantClear(_Inout_ VARIANT* pVar); |
62 | |
63 | class VariantHolder |
64 | { |
65 | public: |
66 | inline VariantHolder() |
67 | { |
68 | LIMITED_METHOD_CONTRACT; |
69 | memset(&m_var, 0, sizeof(VARIANT)); |
70 | } |
71 | |
72 | inline ~VariantHolder() |
73 | { |
74 | WRAPPER_NO_CONTRACT; |
75 | SafeVariantClear(&m_var); |
76 | } |
77 | |
78 | inline VARIANT* operator&() |
79 | { |
80 | LIMITED_METHOD_CONTRACT; |
81 | return static_cast<VARIANT*>(&m_var); |
82 | } |
83 | |
84 | private: |
85 | VARIANT m_var; |
86 | }; |
87 | |
88 | |
89 | template <typename TYPE> |
90 | inline void SafeComRelease(TYPE *value) |
91 | { |
92 | CONTRACTL { |
93 | NOTHROW; |
94 | GC_TRIGGERS; |
95 | MODE_ANY; |
96 | SO_TOLERANT; |
97 | } CONTRACTL_END; |
98 | |
99 | SafeRelease((IUnknown*)value); |
100 | } |
101 | template <typename TYPE> |
102 | inline void SafeComReleasePreemp(TYPE *value) |
103 | { |
104 | CONTRACTL { |
105 | NOTHROW; |
106 | GC_TRIGGERS; |
107 | MODE_PREEMPTIVE; |
108 | SO_TOLERANT; |
109 | } CONTRACTL_END; |
110 | |
111 | SafeReleasePreemp((IUnknown*)value); |
112 | } |
113 | |
114 | NEW_WRAPPER_TEMPLATE1(SafeComHolder, SafeComRelease<_TYPE>); |
115 | |
116 | // Use this holder if you're already in preemptive mode for other reasons, |
117 | // use SafeComHolder otherwise. |
118 | NEW_WRAPPER_TEMPLATE1(SafeComHolderPreemp, SafeComReleasePreemp<_TYPE>); |
119 | |
120 | |
121 | |
122 | #ifdef FEATURE_COMINTEROP |
123 | #ifdef CROSSGEN_COMPILE |
124 | namespace clr |
125 | { |
126 | namespace winrt |
127 | { |
128 | template <typename ItfT> inline |
129 | HRESULT GetActivationFactory( |
130 | __in WinRtStringRef const & wzActivatableClassId, |
131 | __deref_out ItfT** ppItf) |
132 | { |
133 | LIMITED_METHOD_CONTRACT; |
134 | return GetActivationFactory(wzActivatableClassId, ppItf); |
135 | } |
136 | |
137 | template <typename ItfT> inline |
138 | HRESULT GetActivationFactory( |
139 | __in WinRtStringRef const & wzActivatableClassId, |
140 | __out typename SafeComHolderPreemp<ItfT>* pItf) |
141 | { |
142 | STATIC_CONTRACT_WRAPPER; |
143 | |
144 | if (pItf == nullptr) |
145 | return E_INVALIDARG; |
146 | |
147 | return GetActivationFactory(wzActivatableClassId, (ItfT**)&(*pItf)); |
148 | } |
149 | } |
150 | } |
151 | #endif //CROSSGEN_COMPILE |
152 | #endif //FEATURE_COMINTEROP |
153 | |
154 | //----------------------------------------------------------------------------- |
155 | // NewPreempHolder : New'ed memory holder, deletes in preemp mode. |
156 | // |
157 | // { |
158 | // NewPreempHolder<Foo> foo = new Foo (); |
159 | // } // delete foo on out of scope in preemp mode. |
160 | //----------------------------------------------------------------------------- |
161 | |
162 | template <typename TYPE> |
163 | void DeletePreemp(TYPE *value) |
164 | { |
165 | WRAPPER_NO_CONTRACT; |
166 | |
167 | GCX_PREEMP(); |
168 | delete value; |
169 | } |
170 | |
171 | NEW_WRAPPER_TEMPLATE1(NewPreempHolder, DeletePreemp<_TYPE>); |
172 | |
173 | |
174 | //----------------------------------------------------------------------------- |
175 | // VariantPtrHolder : Variant holder, Calls VariantClear on scope exit. |
176 | // |
177 | // { |
178 | // VariantHolder foo = pVar |
179 | // } // Call SafeVariantClear on out of scope. |
180 | //----------------------------------------------------------------------------- |
181 | |
182 | FORCEINLINE void VariantPtrRelease(VARIANT* value) |
183 | { |
184 | WRAPPER_NO_CONTRACT; |
185 | |
186 | if (value) |
187 | { |
188 | SafeVariantClear(value); |
189 | } |
190 | } |
191 | |
192 | class VariantPtrHolder : public Wrapper<VARIANT*, VariantPtrDoNothing, VariantPtrRelease, NULL> |
193 | { |
194 | public: |
195 | VariantPtrHolder(VARIANT* p = NULL) |
196 | : Wrapper<VARIANT*, VariantPtrDoNothing, VariantPtrRelease, NULL>(p) |
197 | { |
198 | LIMITED_METHOD_CONTRACT; |
199 | } |
200 | |
201 | FORCEINLINE void operator=(VARIANT* p) |
202 | { |
203 | WRAPPER_NO_CONTRACT; |
204 | |
205 | Wrapper<VARIANT*, VariantPtrDoNothing, VariantPtrRelease, NULL>::operator=(p); |
206 | } |
207 | }; |
208 | |
209 | //----------------------------------------------------------------------------- |
210 | // SafeArrayPtrHolder : SafeArray holder, Calls SafeArrayDestroy on scope exit. |
211 | // In cooperative mode this holder should be used instead of code:SafeArrayHolder. |
212 | // |
213 | // { |
214 | // SafeArrayPtrHolder foo = pSafeArray |
215 | // } // Call SafeArrayDestroy on out of scope. |
216 | //----------------------------------------------------------------------------- |
217 | |
218 | FORCEINLINE void SafeArrayPtrRelease(SAFEARRAY* value) |
219 | { |
220 | WRAPPER_NO_CONTRACT; |
221 | |
222 | if (value) |
223 | { |
224 | // SafeArrayDestroy may block and may also call back to MODE_PREEMPTIVE |
225 | // runtime functions like e.g. code:Unknown_Release_Internal |
226 | GCX_PREEMP(); |
227 | |
228 | HRESULT hr; hr = SafeArrayDestroy(value); |
229 | _ASSERTE(SUCCEEDED(hr)); |
230 | } |
231 | } |
232 | |
233 | class SafeArrayPtrHolder : public Wrapper<SAFEARRAY*, SafeArrayDoNothing, SafeArrayPtrRelease, NULL> |
234 | { |
235 | public: |
236 | SafeArrayPtrHolder(SAFEARRAY* p = NULL) |
237 | : Wrapper<SAFEARRAY*, SafeArrayDoNothing, SafeArrayPtrRelease, NULL>(p) |
238 | { |
239 | LIMITED_METHOD_CONTRACT; |
240 | } |
241 | |
242 | FORCEINLINE void operator=(SAFEARRAY* p) |
243 | { |
244 | WRAPPER_NO_CONTRACT; |
245 | |
246 | Wrapper<SAFEARRAY*, SafeArrayDoNothing, SafeArrayPtrRelease, NULL>::operator=(p); |
247 | } |
248 | }; |
249 | |
250 | //----------------------------------------------------------------------------- |
251 | // ZeroHolder : Sets value to zero on context exit. |
252 | // |
253 | // { |
254 | // ZeroHolder foo = &data; |
255 | // } // set data to zero on context exit |
256 | //----------------------------------------------------------------------------- |
257 | |
258 | FORCEINLINE void ZeroRelease(VOID* value) |
259 | { |
260 | LIMITED_METHOD_CONTRACT; |
261 | if (value) |
262 | { |
263 | (*(size_t*)value) = 0; |
264 | } |
265 | } |
266 | |
267 | class ZeroHolder : public Wrapper<VOID*, ZeroDoNothing, ZeroRelease, NULL> |
268 | { |
269 | public: |
270 | ZeroHolder(VOID* p = NULL) |
271 | : Wrapper<VOID*, ZeroDoNothing, ZeroRelease, NULL>(p) |
272 | { |
273 | LIMITED_METHOD_CONTRACT; |
274 | } |
275 | |
276 | FORCEINLINE void operator=(VOID* p) |
277 | { |
278 | WRAPPER_NO_CONTRACT; |
279 | |
280 | Wrapper<VOID*, ZeroDoNothing, ZeroRelease, NULL>::operator=(p); |
281 | } |
282 | }; |
283 | |
284 | #ifdef FEATURE_COMINTEROP |
285 | class TYPEATTRHolder |
286 | { |
287 | public: |
288 | TYPEATTRHolder(ITypeInfo* pTypeInfo) |
289 | { |
290 | CONTRACTL |
291 | { |
292 | NOTHROW; |
293 | GC_NOTRIGGER; |
294 | MODE_ANY; |
295 | PRECONDITION(CheckPointer(pTypeInfo, NULL_OK)); |
296 | } |
297 | CONTRACTL_END; |
298 | |
299 | m_pTypeInfo = pTypeInfo; |
300 | m_TYPEATTR = NULL; |
301 | } |
302 | |
303 | ~TYPEATTRHolder() |
304 | { |
305 | CONTRACTL |
306 | { |
307 | NOTHROW; |
308 | GC_TRIGGERS; |
309 | MODE_ANY; |
310 | PRECONDITION(m_TYPEATTR ? CheckPointer(m_pTypeInfo) : CheckPointer(m_pTypeInfo, NULL_OK)); |
311 | } |
312 | CONTRACTL_END; |
313 | |
314 | if (m_TYPEATTR) |
315 | { |
316 | GCX_PREEMP(); |
317 | m_pTypeInfo->ReleaseTypeAttr(m_TYPEATTR); |
318 | } |
319 | } |
320 | |
321 | inline void operator=(TYPEATTR* value) |
322 | { |
323 | LIMITED_METHOD_CONTRACT; |
324 | m_TYPEATTR = value; |
325 | } |
326 | |
327 | inline TYPEATTR** operator&() |
328 | { |
329 | LIMITED_METHOD_CONTRACT; |
330 | return &m_TYPEATTR; |
331 | } |
332 | |
333 | inline TYPEATTR* operator->() |
334 | { |
335 | LIMITED_METHOD_CONTRACT; |
336 | return m_TYPEATTR; |
337 | } |
338 | |
339 | private: |
340 | TYPEATTRHolder () |
341 | { |
342 | LIMITED_METHOD_CONTRACT; |
343 | } |
344 | |
345 | ITypeInfo* m_pTypeInfo; |
346 | TYPEATTR* m_TYPEATTR; |
347 | }; |
348 | #endif // FEATURE_COMINTEROP |
349 | |
350 | #endif // _WRAPPERS_H_ |
351 | |