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
15class MDEnumHolder
16{
17public:
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
51private:
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
61void SafeVariantClear(_Inout_ VARIANT* pVar);
62
63class VariantHolder
64{
65public:
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
84private:
85 VARIANT m_var;
86};
87
88
89template <typename TYPE>
90inline 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}
101template <typename TYPE>
102inline 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
114NEW_WRAPPER_TEMPLATE1(SafeComHolder, SafeComRelease<_TYPE>);
115
116// Use this holder if you're already in preemptive mode for other reasons,
117// use SafeComHolder otherwise.
118NEW_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
162template <typename TYPE>
163void DeletePreemp(TYPE *value)
164{
165 WRAPPER_NO_CONTRACT;
166
167 GCX_PREEMP();
168 delete value;
169}
170
171NEW_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
182FORCEINLINE void VariantPtrRelease(VARIANT* value)
183{
184 WRAPPER_NO_CONTRACT;
185
186 if (value)
187 {
188 SafeVariantClear(value);
189 }
190}
191
192class VariantPtrHolder : public Wrapper<VARIANT*, VariantPtrDoNothing, VariantPtrRelease, NULL>
193{
194public:
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
218FORCEINLINE 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
233class SafeArrayPtrHolder : public Wrapper<SAFEARRAY*, SafeArrayDoNothing, SafeArrayPtrRelease, NULL>
234{
235public:
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
258FORCEINLINE void ZeroRelease(VOID* value)
259{
260 LIMITED_METHOD_CONTRACT;
261 if (value)
262 {
263 (*(size_t*)value) = 0;
264 }
265}
266
267class ZeroHolder : public Wrapper<VOID*, ZeroDoNothing, ZeroRelease, NULL>
268{
269public:
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
285class TYPEATTRHolder
286{
287public:
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
339private:
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