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#ifndef _GCHANDLEUTILITIES_H_
6#define _GCHANDLEUTILITIES_H_
7
8#include "gcinterface.h"
9
10#ifdef FEATURE_COMINTEROP
11#include <weakreference.h>
12#endif
13
14extern "C" IGCHandleManager* g_pGCHandleManager;
15
16class GCHandleUtilities
17{
18public:
19 // Retrieves the GC handle table.
20 static IGCHandleManager* GetGCHandleManager()
21 {
22 LIMITED_METHOD_CONTRACT;
23
24 assert(g_pGCHandleManager != nullptr);
25 return g_pGCHandleManager;
26 }
27
28private:
29 // This class should never be instantiated.
30 GCHandleUtilities() = delete;
31};
32
33void ValidateObjectAndAppDomain(OBJECTREF objRef, ADIndex appDomainIndex);
34void ValidateHandleAssignment(OBJECTHANDLE handle, OBJECTREF objRef);
35void DiagHandleCreated(OBJECTHANDLE handle, OBJECTREF object);
36void DiagHandleDestroyed(OBJECTHANDLE handle);
37
38// Given a handle, returns an OBJECTREF for the object it refers to.
39inline OBJECTREF ObjectFromHandle(OBJECTHANDLE handle)
40{
41 _ASSERTE(handle);
42
43#if defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE)
44 // not allowed to dispatch virtually on a IGCHandleManager when compiling for DAC
45 DWORD context = (DWORD)GCHandleUtilities::GetGCHandleManager()->GetHandleContext(handle);
46 OBJECTREF objRef = ObjectToOBJECTREF(*(Object**)handle);
47
48 ValidateObjectAndAppDomain(objRef, ADIndex(context));
49#endif // defined(_DEBUG_IMPL) && !defined(DACCESS_COMPILE)
50
51 // Wrap the raw OBJECTREF and return it
52 return UNCHECKED_OBJECTREF_TO_OBJECTREF(*PTR_UNCHECKED_OBJECTREF(handle));
53}
54
55// Quick inline check for whether a handle is null
56inline BOOL IsHandleNullUnchecked(OBJECTHANDLE handle)
57{
58 LIMITED_METHOD_CONTRACT;
59
60 return (handle == NULL || (*(_UNCHECKED_OBJECTREF *)handle) == NULL);
61}
62
63inline BOOL ObjectHandleIsNull(OBJECTHANDLE handle)
64{
65 LIMITED_METHOD_CONTRACT;
66
67 return *(Object **)handle == NULL;
68}
69
70#ifndef DACCESS_COMPILE
71
72// Handle creation convenience functions
73inline OBJECTHANDLE CreateHandleCommon(IGCHandleStore* store, OBJECTREF object, HandleType type)
74{
75 OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), type);
76 if (!hnd)
77 {
78 COMPlusThrowOM();
79 }
80
81 DiagHandleCreated(hnd, object);
82 return hnd;
83}
84
85inline OBJECTHANDLE CreateHandle(IGCHandleStore* store, OBJECTREF object)
86{
87 return CreateHandleCommon(store, object, HNDTYPE_DEFAULT);
88}
89
90inline OBJECTHANDLE CreateWeakHandle(IGCHandleStore* store, OBJECTREF object)
91{
92 return CreateHandleCommon(store, object, HNDTYPE_WEAK_DEFAULT);
93}
94
95inline OBJECTHANDLE CreateShortWeakHandle(IGCHandleStore* store, OBJECTREF object)
96{
97 return CreateHandleCommon(store, object, HNDTYPE_WEAK_SHORT);
98}
99
100inline OBJECTHANDLE CreateLongWeakHandle(IGCHandleStore* store, OBJECTREF object)
101{
102 return CreateHandleCommon(store, object, HNDTYPE_WEAK_LONG);
103}
104
105inline OBJECTHANDLE CreateStrongHandle(IGCHandleStore* store, OBJECTREF object)
106{
107 return CreateHandleCommon(store, object, HNDTYPE_STRONG);
108}
109
110inline OBJECTHANDLE CreatePinningHandle(IGCHandleStore* store, OBJECTREF object)
111{
112 return CreateHandleCommon(store, object, HNDTYPE_PINNED);
113}
114
115inline OBJECTHANDLE CreateAsyncPinningHandle(IGCHandleStore* store, OBJECTREF object)
116{
117 return CreateHandleCommon(store, object, HNDTYPE_ASYNCPINNED);
118}
119
120inline OBJECTHANDLE CreateRefcountedHandle(IGCHandleStore* store, OBJECTREF object)
121{
122 return CreateHandleCommon(store, object, HNDTYPE_REFCOUNTED);
123}
124
125inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object)
126{
127 return CreateHandleCommon(store, object, HNDTYPE_SIZEDREF);
128}
129
130inline OBJECTHANDLE CreateSizedRefHandle(IGCHandleStore* store, OBJECTREF object, int heapToAffinitizeTo)
131{
132 OBJECTHANDLE hnd = store->CreateHandleOfType(OBJECTREFToObject(object), HNDTYPE_SIZEDREF, heapToAffinitizeTo);
133 if (!hnd)
134 {
135 COMPlusThrowOM();
136 }
137
138 DiagHandleCreated(hnd, object);
139 return hnd;
140}
141
142inline OBJECTHANDLE CreateDependentHandle(IGCHandleStore* store, OBJECTREF primary, OBJECTREF secondary)
143{
144 OBJECTHANDLE hnd = store->CreateDependentHandle(OBJECTREFToObject(primary), OBJECTREFToObject(secondary));
145 if (!hnd)
146 {
147 COMPlusThrowOM();
148 }
149
150 DiagHandleCreated(hnd, primary);
151 return hnd;
152}
153
154// Global handle creation convenience functions
155inline OBJECTHANDLE CreateGlobalHandleCommon(OBJECTREF object, HandleType type)
156{
157 CONDITIONAL_CONTRACT_VIOLATION(ModeViolation, object == NULL);
158 OBJECTHANDLE hnd = GCHandleUtilities::GetGCHandleManager()->CreateGlobalHandleOfType(OBJECTREFToObject(object), type);
159 if (!hnd)
160 {
161 COMPlusThrowOM();
162 }
163
164 DiagHandleCreated(hnd, object);
165 return hnd;
166
167}
168
169inline OBJECTHANDLE CreateGlobalHandle(OBJECTREF object)
170{
171 return CreateGlobalHandleCommon(object, HNDTYPE_DEFAULT);
172}
173
174inline OBJECTHANDLE CreateGlobalWeakHandle(OBJECTREF object)
175{
176 return CreateGlobalHandleCommon(object, HNDTYPE_WEAK_DEFAULT);
177}
178
179inline OBJECTHANDLE CreateGlobalShortWeakHandle(OBJECTREF object)
180{
181 return CreateGlobalHandleCommon(object, HNDTYPE_WEAK_SHORT);
182}
183
184inline OBJECTHANDLE CreateGlobalLongWeakHandle(OBJECTREF object)
185{
186 return CreateGlobalHandleCommon(object, HNDTYPE_WEAK_LONG);
187}
188
189inline OBJECTHANDLE CreateGlobalStrongHandle(OBJECTREF object)
190{
191 return CreateGlobalHandleCommon(object, HNDTYPE_STRONG);
192}
193
194inline OBJECTHANDLE CreateGlobalPinningHandle(OBJECTREF object)
195{
196 return CreateGlobalHandleCommon(object, HNDTYPE_PINNED);
197}
198
199inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object)
200{
201 return CreateGlobalHandleCommon(object, HNDTYPE_REFCOUNTED);
202}
203
204// Special handle creation convenience functions
205
206#ifdef FEATURE_COMINTEROP
207inline OBJECTHANDLE CreateWinRTWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pWinRTWeakReference)
208{
209 OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_WINRT, (void*)pWinRTWeakReference);
210 if (!hnd)
211 {
212 COMPlusThrowOM();
213 }
214
215 DiagHandleCreated(hnd, object);
216 return hnd;
217}
218#endif // FEATURE_COMINTEROP
219
220// Creates a variable-strength handle
221inline OBJECTHANDLE CreateVariableHandle(IGCHandleStore* store, OBJECTREF object, uint32_t type)
222{
223 OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_VARIABLE, (void*)((uintptr_t)type));
224 if (!hnd)
225 {
226 COMPlusThrowOM();
227 }
228
229 DiagHandleCreated(hnd, object);
230 return hnd;
231}
232
233// Handle object manipulation convenience functions
234
235inline void StoreObjectInHandle(OBJECTHANDLE handle, OBJECTREF object)
236{
237 ValidateHandleAssignment(handle, object);
238
239 GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, OBJECTREFToObject(object));
240}
241
242inline bool StoreFirstObjectInHandle(OBJECTHANDLE handle, OBJECTREF object)
243{
244 ValidateHandleAssignment(handle, object);
245
246 return GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandleIfNull(handle, OBJECTREFToObject(object));
247}
248
249inline void* InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE handle, OBJECTREF object, OBJECTREF comparandObject)
250{
251 ValidateHandleAssignment(handle, object);
252
253 return GCHandleUtilities::GetGCHandleManager()->InterlockedCompareExchangeObjectInHandle(handle, OBJECTREFToObject(object), OBJECTREFToObject(comparandObject));
254}
255
256inline void ResetOBJECTHANDLE(OBJECTHANDLE handle)
257{
258 GCHandleUtilities::GetGCHandleManager()->StoreObjectInHandle(handle, NULL);
259}
260
261// Handle destruction convenience functions
262inline void DestroyHandleCommon(OBJECTHANDLE handle, HandleType type)
263{
264 CONTRACTL
265 {
266 NOTHROW;
267 GC_NOTRIGGER;
268 MODE_ANY;
269 CAN_TAKE_LOCK;
270 SO_TOLERANT;
271 }
272 CONTRACTL_END;
273
274 DiagHandleDestroyed(handle);
275 GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, type);
276}
277
278inline void DestroyHandle(OBJECTHANDLE handle)
279{
280 DestroyHandleCommon(handle, HNDTYPE_DEFAULT);
281}
282
283inline void DestroyWeakHandle(OBJECTHANDLE handle)
284{
285 DestroyHandleCommon(handle, HNDTYPE_WEAK_DEFAULT);
286}
287
288inline void DestroyShortWeakHandle(OBJECTHANDLE handle)
289{
290 DestroyHandleCommon(handle, HNDTYPE_WEAK_SHORT);
291}
292
293inline void DestroyLongWeakHandle(OBJECTHANDLE handle)
294{
295 DestroyHandleCommon(handle, HNDTYPE_WEAK_LONG);
296}
297
298inline void DestroyStrongHandle(OBJECTHANDLE handle)
299{
300 DestroyHandleCommon(handle, HNDTYPE_STRONG);
301}
302
303inline void DestroyPinningHandle(OBJECTHANDLE handle)
304{
305 DestroyHandleCommon(handle, HNDTYPE_PINNED);
306}
307
308inline void DestroyAsyncPinningHandle(OBJECTHANDLE handle)
309{
310 DestroyHandleCommon(handle, HNDTYPE_ASYNCPINNED);
311}
312
313inline void DestroyRefcountedHandle(OBJECTHANDLE handle)
314{
315 DestroyHandleCommon(handle, HNDTYPE_REFCOUNTED);
316}
317
318inline void DestroyDependentHandle(OBJECTHANDLE handle)
319{
320 DestroyHandleCommon(handle, HNDTYPE_DEPENDENT);
321}
322
323inline void DestroyVariableHandle(OBJECTHANDLE handle)
324{
325 DestroyHandleCommon(handle, HNDTYPE_VARIABLE);
326}
327
328inline void DestroyGlobalHandle(OBJECTHANDLE handle)
329{
330 DestroyHandleCommon(handle, HNDTYPE_DEFAULT);
331}
332
333inline void DestroyGlobalWeakHandle(OBJECTHANDLE handle)
334{
335 DestroyHandleCommon(handle, HNDTYPE_WEAK_DEFAULT);
336}
337
338inline void DestroyGlobalShortWeakHandle(OBJECTHANDLE handle)
339{
340 DestroyHandleCommon(handle, HNDTYPE_WEAK_SHORT);
341}
342
343inline void DestroyGlobalLongWeakHandle(OBJECTHANDLE handle)
344{
345 DestroyHandleCommon(handle, HNDTYPE_WEAK_LONG);
346}
347
348inline void DestroyGlobalStrongHandle(OBJECTHANDLE handle)
349{
350 DestroyHandleCommon(handle, HNDTYPE_STRONG);
351}
352
353inline void DestroyGlobalPinningHandle(OBJECTHANDLE handle)
354{
355 DestroyHandleCommon(handle, HNDTYPE_PINNED);
356}
357
358inline void DestroyGlobalRefcountedHandle(OBJECTHANDLE handle)
359{
360 DestroyHandleCommon(handle, HNDTYPE_REFCOUNTED);
361}
362
363inline void DestroyTypedHandle(OBJECTHANDLE handle)
364{
365 DiagHandleDestroyed(handle);
366 GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfUnknownType(handle);
367}
368
369#ifdef FEATURE_COMINTEROP
370inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle)
371{
372 CONTRACTL
373 {
374 NOTHROW;
375 GC_NOTRIGGER;
376 MODE_ANY;
377 CAN_TAKE_LOCK;
378 SO_TOLERANT;
379 }
380 CONTRACTL_END;
381
382 // Release the WinRT weak reference if we have one. We're assuming that this will not reenter the
383 // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_WINRT
384 // but rather HNDTYPE_WEAK_SHORT or HNDTYPE_WEAK_LONG.
385 void* pExtraInfo = GCHandleUtilities::GetGCHandleManager()->GetExtraInfoFromHandle(handle);
386 IWeakReference* pWinRTWeakReference = reinterpret_cast<IWeakReference*>(pExtraInfo);
387 if (pWinRTWeakReference != nullptr)
388 {
389 pWinRTWeakReference->Release();
390 }
391
392 DiagHandleDestroyed(handle);
393 GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT);
394}
395#endif
396
397// Handle holders/wrappers
398
399#ifndef FEATURE_REDHAWK
400typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyHandle> OHWrapper;
401typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyPinningHandle, NULL> PinningHandleHolder;
402typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyAsyncPinningHandle, NULL> AsyncPinningHandleHolder;
403typedef Wrapper<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyRefcountedHandle> RefCountedOHWrapper;
404
405typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyLongWeakHandle> LongWeakHandleHolder;
406typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalStrongHandle> GlobalStrongHandleHolder;
407typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, DestroyGlobalShortWeakHandle> GlobalShortWeakHandleHolder;
408typedef Holder<OBJECTHANDLE, DoNothing<OBJECTHANDLE>, ResetOBJECTHANDLE> ObjectInHandleHolder;
409
410class RCOBJECTHANDLEHolder : public RefCountedOHWrapper
411{
412public:
413 FORCEINLINE RCOBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : RefCountedOHWrapper(p)
414 {
415 LIMITED_METHOD_CONTRACT;
416 }
417 FORCEINLINE void operator=(OBJECTHANDLE p)
418 {
419 WRAPPER_NO_CONTRACT;
420
421 RefCountedOHWrapper::operator=(p);
422 }
423};
424
425class OBJECTHANDLEHolder : public OHWrapper
426{
427public:
428 FORCEINLINE OBJECTHANDLEHolder(OBJECTHANDLE p = NULL) : OHWrapper(p)
429 {
430 LIMITED_METHOD_CONTRACT;
431 }
432 FORCEINLINE void operator=(OBJECTHANDLE p)
433 {
434 WRAPPER_NO_CONTRACT;
435
436 OHWrapper::operator=(p);
437 }
438};
439
440#endif // !FEATURE_REDHAWK
441
442#endif // !DACCESS_COMPILE
443
444#endif // _GCHANDLEUTILITIES_H_
445
446