diff --git a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs
index 323e60a564801..8c377012666b5 100644
--- a/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs
+++ b/src/coreclr/src/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs
@@ -331,8 +331,15 @@ public static void RegisterForTrackerSupport(ComWrappers instance)
{
throw new InvalidOperationException(SR.InvalidOperation_ResetGlobalComWrappersInstance);
}
+
+ SetGlobalInstanceRegisteredForTrackerSupport();
}
+
+ [DllImport(RuntimeHelpers.QCall)]
+ [SuppressGCTransition]
+ private static extern void SetGlobalInstanceRegisteredForTrackerSupport();
+
///
/// Register a instance to be used as the global instance for marshalling in the runtime.
///
@@ -390,4 +397,4 @@ internal static int CallICustomQueryInterface(object customQueryInterfaceMaybe,
return (int)customQueryInterface.GetInterface(ref iid, out ppObject);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/coreclr/src/debug/daccess/daccess.cpp b/src/coreclr/src/debug/daccess/daccess.cpp
index a05d4f09d0d68..444114587c2ab 100644
--- a/src/coreclr/src/debug/daccess/daccess.cpp
+++ b/src/coreclr/src/debug/daccess/daccess.cpp
@@ -8252,7 +8252,7 @@ void CALLBACK DacHandleWalker::EnumCallbackSOS(PTR_UNCHECKED_OBJECTREF handle, u
if (param->Type == HNDTYPE_DEPENDENT)
data.Secondary = GetDependentHandleSecondary(handle.GetAddr()).GetAddr();
#ifdef FEATURE_COMINTEROP
- else if (param->Type == HNDTYPE_WEAK_WINRT)
+ else if (param->Type == HNDTYPE_WEAK_NATIVE_COM)
data.Secondary = HndGetHandleExtraInfo(handle.GetAddr());
#endif // FEATURE_COMINTEROP
else
diff --git a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp
index 905698ad4fd71..e3152652fb5f9 100644
--- a/src/coreclr/src/debug/daccess/dacdbiimpl.cpp
+++ b/src/coreclr/src/debug/daccess/dacdbiimpl.cpp
@@ -7491,8 +7491,8 @@ UINT32 DacRefWalker::GetHandleWalkerMask()
if ((mHandleMask & CorHandleWeakRefCount) || (mHandleMask & CorHandleStrongRefCount))
result |= (1 << HNDTYPE_REFCOUNTED);
- if (mHandleMask & CorHandleWeakWinRT)
- result |= (1 << HNDTYPE_WEAK_WINRT);
+ if (mHandleMask & CorHandleWeakNativeCom)
+ result |= (1 << HNDTYPE_WEAK_NATIVE_COM);
#endif // FEATURE_COMINTEROP
if (mHandleMask & CorHandleStrongDependent)
@@ -7667,8 +7667,8 @@ void CALLBACK DacHandleWalker::EnumCallbackDac(PTR_UNCHECKED_OBJECTREF handle, u
data.i64ExtraData = refCnt;
break;
- case HNDTYPE_WEAK_WINRT:
- data.dwType = (DWORD)CorHandleWeakWinRT;
+ case HNDTYPE_WEAK_NATIVE_COM:
+ data.dwType = (DWORD)CorHandleWeakNativeCom;
break;
#endif
diff --git a/src/coreclr/src/debug/daccess/request.cpp b/src/coreclr/src/debug/daccess/request.cpp
index 2be663ebd77ea..79880ff064e5e 100644
--- a/src/coreclr/src/debug/daccess/request.cpp
+++ b/src/coreclr/src/debug/daccess/request.cpp
@@ -3253,7 +3253,7 @@ HRESULT ClrDataAccess::GetHandleEnum(ISOSHandleEnum **ppHandleEnum)
unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_VARIABLE, HNDTYPE_DEPENDENT,
HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF,
#ifdef FEATURE_COMINTEROP
- HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_WINRT
+ HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_NATIVE_COM
#endif
};
@@ -3291,7 +3291,7 @@ HRESULT ClrDataAccess::GetHandleEnumForGC(unsigned int gen, ISOSHandleEnum **ppH
unsigned int types[] = {HNDTYPE_WEAK_SHORT, HNDTYPE_WEAK_LONG, HNDTYPE_STRONG, HNDTYPE_PINNED, HNDTYPE_VARIABLE, HNDTYPE_DEPENDENT,
HNDTYPE_ASYNCPINNED, HNDTYPE_SIZEDREF,
#ifdef FEATURE_COMINTEROP
- HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_WINRT
+ HNDTYPE_REFCOUNTED, HNDTYPE_WEAK_NATIVE_COM
#endif
};
diff --git a/src/coreclr/src/dlls/mscorrc/mscorrc.rc b/src/coreclr/src/dlls/mscorrc/mscorrc.rc
index 8a7410ef25b2d..4573e20be97ae 100644
--- a/src/coreclr/src/dlls/mscorrc/mscorrc.rc
+++ b/src/coreclr/src/dlls/mscorrc/mscorrc.rc
@@ -344,7 +344,7 @@ BEGIN
IDS_EE_WINRT_NOT_FACTORY_FOR_TYPE "Windows Runtime factory '%1' is not a factory for Windows Runtime type '%2'."
IDS_EE_WINRT_INVALID_FACTORY_FOR_TYPE "Windows Runtime type '%1' has a invalid Windows Runtime factory"
IDS_EE_CANNOTCAST_NOMARSHAL "The Windows Runtime Object can only be used in the threading context where it was created, because it implements INoMarshal or has MarshalingBehaviorAttribute(MarshalingType.None) set."
- IDS_EE_WINRT_WEAKREF_BAD_TYPE "The object resolved by a native IWeakReference has an incompatible type for its managed WeakReference instance.\r\nExpected WeakReference target type: '%1'\r\nNative IWeakReference returned type: '%2'"
+ IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE "The object resolved by a native IWeakReference has an incompatible type for its managed WeakReference instance.\r\nExpected WeakReference target type: '%1'\r\nNative IWeakReference returned type: '%2'"
#endif // FEATURE_COMINTEROP
IDS_EE_INTEROP_CODE_SIZE_COMMENT "Code size"
diff --git a/src/coreclr/src/dlls/mscorrc/resource.h b/src/coreclr/src/dlls/mscorrc/resource.h
index 342c0570d493b..4011efb748215 100644
--- a/src/coreclr/src/dlls/mscorrc/resource.h
+++ b/src/coreclr/src/dlls/mscorrc/resource.h
@@ -600,7 +600,7 @@
#ifdef FEATURE_COMINTEROP
-#define IDS_EE_WINRT_WEAKREF_BAD_TYPE 0x262e
+#define IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE 0x262e
#endif // FEATURE_COMINTEROP
#define IDS_EE_BADMARSHAL_TYPE_ANSIBSTR 0x262f
diff --git a/src/coreclr/src/gc/gchandletable.cpp b/src/coreclr/src/gc/gchandletable.cpp
index b7c4bf2687233..d3f93b457521e 100644
--- a/src/coreclr/src/gc/gchandletable.cpp
+++ b/src/coreclr/src/gc/gchandletable.cpp
@@ -168,7 +168,7 @@ Object* GCHandleManager::InterlockedCompareExchangeObjectInHandle(OBJECTHANDLE h
HandleType GCHandleManager::HandleFetchType(OBJECTHANDLE handle)
{
uint32_t type = ::HandleFetchType(handle);
- assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_WINRT);
+ assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_NATIVE_COM);
return static_cast(type);
}
diff --git a/src/coreclr/src/gc/gcinterface.h b/src/coreclr/src/gc/gcinterface.h
index 122106c2ae273..e9bef6a502b45 100644
--- a/src/coreclr/src/gc/gcinterface.h
+++ b/src/coreclr/src/gc/gcinterface.h
@@ -422,18 +422,18 @@ typedef enum
HNDTYPE_SIZEDREF = 8,
/*
- * WINRT WEAK HANDLES
+ * NATIVE WEAK HANDLES
*
- * WinRT weak reference handles hold two different types of weak handles to any
+ * Native weak reference handles hold two different types of weak handles to any
* RCW with an underlying COM object that implements IWeakReferenceSource. The
* object reference itself is a short weak handle to the RCW. In addition an
* IWeakReference* to the underlying COM object is stored, allowing the handle
* to create a new RCW if the existing RCW is collected. This ensures that any
- * code holding onto a WinRT weak reference can always access an RCW to the
+ * code holding onto a native weak reference can always access an RCW to the
* underlying COM object as long as it has not been released by all of its strong
* references.
*/
- HNDTYPE_WEAK_WINRT = 9
+ HNDTYPE_WEAK_NATIVE_COM = 9
} HandleType;
typedef enum
diff --git a/src/coreclr/src/gc/handletable.cpp b/src/coreclr/src/gc/handletable.cpp
index 898e843419341..1b56c74c791cf 100644
--- a/src/coreclr/src/gc/handletable.cpp
+++ b/src/coreclr/src/gc/handletable.cpp
@@ -409,10 +409,10 @@ void HndDestroyHandleOfUnknownType(HHANDLETABLE hTable, OBJECTHANDLE handle)
_ASSERTE(handle);
#ifdef FEATURE_COMINTEROP
- // If we're being asked to destroy a WinRT weak handle, that will cause a leak
+ // If we're being asked to destroy a native COM weak handle, that will cause a leak
// of the IWeakReference* that it holds in its extra data. Instead of using this
- // API use DestroyWinRTWeakHandle instead.
- _ASSERTE(HandleFetchType(handle) != HNDTYPE_WEAK_WINRT);
+ // API use DestroyNativeComWeakHandle instead.
+ _ASSERTE(HandleFetchType(handle) != HNDTYPE_WEAK_NATIVE_COM);
#endif // FEATURE_COMINTEROP
// fetch the type and then free normally
diff --git a/src/coreclr/src/gc/objecthandle.cpp b/src/coreclr/src/gc/objecthandle.cpp
index 4a4f201ca03bd..e6a5160d7ee54 100644
--- a/src/coreclr/src/gc/objecthandle.cpp
+++ b/src/coreclr/src/gc/objecthandle.cpp
@@ -426,7 +426,7 @@ void CALLBACK ScanPointerForProfilerAndETW(_UNCHECKED_OBJECTREF *pObjRef, uintpt
case HNDTYPE_WEAK_SHORT:
case HNDTYPE_WEAK_LONG:
#ifdef FEATURE_COMINTEROP
- case HNDTYPE_WEAK_WINRT:
+ case HNDTYPE_WEAK_NATIVE_COM:
#endif // FEATURE_COMINTEROP
rootFlags |= kEtwGCRootFlagsWeakRef;
break;
@@ -520,7 +520,7 @@ static const uint32_t s_rgTypeFlags[] =
HNDF_EXTRAINFO, // HNDTYPE_DEPENDENT
HNDF_NORMAL, // HNDTYPE_ASYNCPINNED
HNDF_EXTRAINFO, // HNDTYPE_SIZEDREF
- HNDF_EXTRAINFO, // HNDTYPE_WEAK_WINRT
+ HNDF_EXTRAINFO, // HNDTYPE_WEAK_NATIVE_COM
};
int getNumberOfSlots()
@@ -1380,7 +1380,7 @@ void Ref_CheckAlive(uint32_t condemned, uint32_t maxgen, uintptr_t lp1)
{
HNDTYPE_WEAK_SHORT
#ifdef FEATURE_COMINTEROP
- , HNDTYPE_WEAK_WINRT
+ , HNDTYPE_WEAK_NATIVE_COM
#endif // FEATURE_COMINTEROP
};
uint32_t flags = (((ScanContext*) lp1)->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL;
@@ -1439,7 +1439,7 @@ void Ref_UpdatePointers(uint32_t condemned, uint32_t maxgen, ScanContext* sc, Re
HNDTYPE_REFCOUNTED,
#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
#ifdef FEATURE_COMINTEROP
- HNDTYPE_WEAK_WINRT,
+ HNDTYPE_WEAK_NATIVE_COM,
#endif // FEATURE_COMINTEROP
HNDTYPE_SIZEDREF,
};
@@ -1485,7 +1485,7 @@ void Ref_ScanHandlesForProfilerAndETW(uint32_t maxgen, uintptr_t lp1, handle_sca
HNDTYPE_REFCOUNTED,
#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
#ifdef FEATURE_COMINTEROP
- HNDTYPE_WEAK_WINRT,
+ HNDTYPE_WEAK_NATIVE_COM,
#endif // FEATURE_COMINTEROP
HNDTYPE_PINNED,
// HNDTYPE_VARIABLE,
@@ -1631,7 +1631,7 @@ void Ref_AgeHandles(uint32_t condemned, uint32_t maxgen, uintptr_t lp1)
HNDTYPE_REFCOUNTED,
#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
#ifdef FEATURE_COMINTEROP
- HNDTYPE_WEAK_WINRT,
+ HNDTYPE_WEAK_NATIVE_COM,
#endif // FEATURE_COMINTEROP
HNDTYPE_ASYNCPINNED,
HNDTYPE_SIZEDREF,
@@ -1674,7 +1674,7 @@ void Ref_RejuvenateHandles(uint32_t condemned, uint32_t maxgen, uintptr_t lp1)
HNDTYPE_REFCOUNTED,
#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
#ifdef FEATURE_COMINTEROP
- HNDTYPE_WEAK_WINRT,
+ HNDTYPE_WEAK_NATIVE_COM,
#endif // FEATURE_COMINTEROP
HNDTYPE_ASYNCPINNED,
HNDTYPE_SIZEDREF,
@@ -1716,7 +1716,7 @@ void Ref_VerifyHandleTable(uint32_t condemned, uint32_t maxgen, ScanContext* sc)
HNDTYPE_REFCOUNTED,
#endif // FEATURE_COMINTEROP || FEATURE_REDHAWK
#ifdef FEATURE_COMINTEROP
- HNDTYPE_WEAK_WINRT,
+ HNDTYPE_WEAK_NATIVE_COM,
#endif // FEATURE_COMINTEROP
HNDTYPE_ASYNCPINNED,
HNDTYPE_SIZEDREF,
diff --git a/src/coreclr/src/inc/cordebug.idl b/src/coreclr/src/inc/cordebug.idl
index 87e1458cfc91d..be745368f2bb3 100644
--- a/src/coreclr/src/inc/cordebug.idl
+++ b/src/coreclr/src/inc/cordebug.idl
@@ -2567,7 +2567,8 @@ typedef enum CorGCReferenceType
CorHandleStrongDependent = 1<<6,
CorHandleStrongAsyncPinned = 1<<7,
CorHandleStrongSizedByref = 1<<8,
- CorHandleWeakWinRT = 1<<9,
+ CorHandleWeakNativeCom = 1<<9,
+ CorHandleWeakWinRT = CorHandleWeakNativeCom,
CorReferenceStack = 0x80000001,
CorReferenceFinalizer = 80000002,
diff --git a/src/coreclr/src/pal/prebuilt/inc/cordebug.h b/src/coreclr/src/pal/prebuilt/inc/cordebug.h
index 96dc9c0eb1926..69c897575113f 100644
--- a/src/coreclr/src/pal/prebuilt/inc/cordebug.h
+++ b/src/coreclr/src/pal/prebuilt/inc/cordebug.h
@@ -6376,7 +6376,8 @@ enum CorGCReferenceType
CorHandleStrongDependent = ( 1 << 6 ) ,
CorHandleStrongAsyncPinned = ( 1 << 7 ) ,
CorHandleStrongSizedByref = ( 1 << 8 ) ,
- CorHandleWeakWinRT = ( 1 << 9 ) ,
+ CorHandleWeakNativeCom = ( 1 << 9 ) ,
+ CorHandleWeakWinRT = CorHandleWeakNativeCom,
CorReferenceStack = 0x80000001,
CorReferenceFinalizer = 80000002,
CorHandleStrongOnly = 0x1e3,
diff --git a/src/coreclr/src/vm/appdomain.hpp b/src/coreclr/src/vm/appdomain.hpp
index 0ca41f064ee5c..f017b42c73a2a 100644
--- a/src/coreclr/src/vm/appdomain.hpp
+++ b/src/coreclr/src/vm/appdomain.hpp
@@ -1110,10 +1110,10 @@ class BaseDomain
return ::CreateRefcountedHandle(m_handleStore, object);
}
- OBJECTHANDLE CreateWinRTWeakHandle(OBJECTREF object, IWeakReference* pWinRTWeakReference)
+ OBJECTHANDLE CreateNativeComWeakHandle(OBJECTREF object, IWeakReference* pComWeakReference)
{
WRAPPER_NO_CONTRACT;
- return ::CreateWinRTWeakHandle(m_handleStore, object, pWinRTWeakReference);
+ return ::CreateNativeComWeakHandle(m_handleStore, object, pComWeakReference);
}
#endif // FEATURE_COMINTEROP
diff --git a/src/coreclr/src/vm/ecalllist.h b/src/coreclr/src/vm/ecalllist.h
index 87aa7b62be5b2..155ae2c516e7c 100644
--- a/src/coreclr/src/vm/ecalllist.h
+++ b/src/coreclr/src/vm/ecalllist.h
@@ -986,6 +986,7 @@ FCFuncStart(gComWrappersFuncs)
QCFuncElement("TryGetOrCreateComInterfaceForObjectInternal", ComWrappersNative::TryGetOrCreateComInterfaceForObject)
QCFuncElement("TryGetOrCreateObjectForComInstanceInternal", ComWrappersNative::TryGetOrCreateObjectForComInstance)
QCFuncElement("SetGlobalInstanceRegisteredForMarshalling", GlobalComWrappersForMarshalling::SetGlobalInstanceRegisteredForMarshalling)
+ QCFuncElement("SetGlobalInstanceRegisteredForTrackerSupport", GlobalComWrappersForTrackerSupport::SetGlobalInstanceRegisteredForTrackerSupport)
FCFuncEnd()
#endif // FEATURE_COMWRAPPERS
diff --git a/src/coreclr/src/vm/gchandleutilities.h b/src/coreclr/src/vm/gchandleutilities.h
index b875644b853b5..d90a2f0faef09 100644
--- a/src/coreclr/src/vm/gchandleutilities.h
+++ b/src/coreclr/src/vm/gchandleutilities.h
@@ -201,9 +201,9 @@ inline OBJECTHANDLE CreateGlobalRefcountedHandle(OBJECTREF object)
// Special handle creation convenience functions
#ifdef FEATURE_COMINTEROP
-inline OBJECTHANDLE CreateWinRTWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pWinRTWeakReference)
+inline OBJECTHANDLE CreateNativeComWeakHandle(IGCHandleStore* store, OBJECTREF object, IWeakReference* pComWeakReference)
{
- OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_WINRT, (void*)pWinRTWeakReference);
+ OBJECTHANDLE hnd = store->CreateHandleWithExtraInfo(OBJECTREFToObject(object), HNDTYPE_WEAK_NATIVE_COM, (void*)pComWeakReference);
if (!hnd)
{
COMPlusThrowOM();
@@ -363,7 +363,7 @@ inline void DestroyTypedHandle(OBJECTHANDLE handle)
}
#ifdef FEATURE_COMINTEROP
-inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle)
+inline void DestroyNativeComWeakHandle(OBJECTHANDLE handle)
{
CONTRACTL
{
@@ -375,7 +375,7 @@ inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle)
CONTRACTL_END;
// Release the WinRT weak reference if we have one. We're assuming that this will not reenter the
- // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_WINRT
+ // runtime, since if we are pointing at a managed object, we should not be using HNDTYPE_WEAK_NATIVE_COM
// but rather HNDTYPE_WEAK_SHORT or HNDTYPE_WEAK_LONG.
void* pExtraInfo = GCHandleUtilities::GetGCHandleManager()->GetExtraInfoFromHandle(handle);
IWeakReference* pWinRTWeakReference = reinterpret_cast(pExtraInfo);
@@ -385,7 +385,7 @@ inline void DestroyWinRTWeakHandle(OBJECTHANDLE handle)
}
DiagHandleDestroyed(handle);
- GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_WINRT);
+ GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_NATIVE_COM);
}
#endif
diff --git a/src/coreclr/src/vm/interoplibinterface.cpp b/src/coreclr/src/vm/interoplibinterface.cpp
index 934e0bbf6fadc..3eaf5ba37f410 100644
--- a/src/coreclr/src/vm/interoplibinterface.cpp
+++ b/src/coreclr/src/vm/interoplibinterface.cpp
@@ -401,7 +401,8 @@ namespace
Volatile ExtObjCxtCache::g_Instance;
// Indicator for if a ComWrappers implementation is globally registered
- bool g_IsGlobalComWrappersRegistered;
+ bool g_IsGlobalComWrappersRegisteredForMarshalling;
+ bool g_IsGlobalComWrappersRegisteredForTrackerSupport;
// Defined handle types for the specific object uses.
const HandleType InstanceHandleType{ HNDTYPE_STRONG };
@@ -1387,15 +1388,15 @@ void QCALLTYPE GlobalComWrappersForMarshalling::SetGlobalInstanceRegisteredForMa
// QCALL contracts are not used here because the managed declaration
// uses the SuppressGCTransition attribute
- _ASSERTE(!g_IsGlobalComWrappersRegistered);
- g_IsGlobalComWrappersRegistered = true;
+ _ASSERTE(!g_IsGlobalComWrappersRegisteredForMarshalling);
+ g_IsGlobalComWrappersRegisteredForMarshalling = true;
}
bool GlobalComWrappersForMarshalling::TryGetOrCreateComInterfaceForObject(
_In_ OBJECTREF instance,
_Outptr_ void** wrapperRaw)
{
- if (!g_IsGlobalComWrappersRegistered)
+ if (!g_IsGlobalComWrappersRegisteredForMarshalling)
return false;
// Switch to Cooperative mode since object references
@@ -1420,7 +1421,7 @@ bool GlobalComWrappersForMarshalling::TryGetOrCreateObjectForComInstance(
_In_ INT32 objFromComIPFlags,
_Out_ OBJECTREF* objRef)
{
- if (!g_IsGlobalComWrappersRegistered)
+ if (!g_IsGlobalComWrappersRegisteredForMarshalling)
return false;
// Determine the true identity of the object
@@ -1452,6 +1453,110 @@ bool GlobalComWrappersForMarshalling::TryGetOrCreateObjectForComInstance(
}
}
+void QCALLTYPE GlobalComWrappersForTrackerSupport::SetGlobalInstanceRegisteredForTrackerSupport()
+{
+ // QCALL contracts are not used here because the managed declaration
+ // uses the SuppressGCTransition attribute
+
+ _ASSERTE(!g_IsGlobalComWrappersRegisteredForTrackerSupport);
+ g_IsGlobalComWrappersRegisteredForTrackerSupport = true;
+}
+
+bool GlobalComWrappersForTrackerSupport::TryGetOrCreateComInterfaceForObject(
+ _In_ OBJECTREF instance,
+ _Outptr_ void** wrapperRaw)
+{
+ CONTRACTL
+ {
+ THROWS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ if (!g_IsGlobalComWrappersRegisteredForTrackerSupport)
+ return false;
+
+ // Passing NULL as the ComWrappers implementation indicates using the globally registered instance
+ return TryGetOrCreateComInterfaceForObjectInternal(
+ NULL,
+ instance,
+ CreateComInterfaceFlags::CreateComInterfaceFlags_TrackerSupport,
+ ComWrappersScenario::TrackerSupportGlobalInstance,
+ wrapperRaw);
+}
+
+bool GlobalComWrappersForTrackerSupport::TryGetOrCreateObjectForComInstance(
+ _In_ IUnknown* externalComObject,
+ _Out_ OBJECTREF* objRef)
+{
+ CONTRACTL
+ {
+ THROWS;
+ MODE_COOPERATIVE;
+ }
+ CONTRACTL_END;
+
+ if (!g_IsGlobalComWrappersRegisteredForTrackerSupport)
+ return false;
+
+ // Determine the true identity of the object
+ SafeComHolder identity;
+ {
+ GCX_PREEMP();
+
+ HRESULT hr = externalComObject->QueryInterface(IID_IUnknown, &identity);
+ _ASSERTE(hr == S_OK);
+ }
+
+ // Passing NULL as the ComWrappers implementation indicates using the globally registered instance
+ return TryGetOrCreateObjectForComInstanceInternal(
+ NULL /*comWrappersImpl*/,
+ identity,
+ CreateObjectFlags::CreateObjectFlags_TrackerObject,
+ ComWrappersScenario::TrackerSupportGlobalInstance,
+ NULL /*wrapperMaybe*/,
+ objRef);
+}
+
+IUnknown* ComWrappersNative::GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_TRIGGERS;
+ MODE_COOPERATIVE;
+ PRECONDITION(CheckPointer(objectPROTECTED));
+ }
+ CONTRACTL_END;
+
+ ASSERT_PROTECTED(objectPROTECTED);
+
+ SyncBlock* syncBlock = (*objectPROTECTED)->PassiveGetSyncBlock();
+ if (syncBlock == nullptr)
+ {
+ return nullptr;
+ }
+
+ InteropSyncBlockInfo* interopInfo = syncBlock->GetInteropInfoNoCreate();
+ if (interopInfo == nullptr)
+ {
+ return nullptr;
+ }
+
+ void* context;
+ if (interopInfo->TryGetExternalComObjectContext(&context))
+ {
+ IUnknown* identity = reinterpret_cast(reinterpret_cast(context)->Identity);
+ GCX_PREEMP();
+ IUnknown* result;
+ if (SUCCEEDED(identity->QueryInterface(riid, (void**)&result)))
+ {
+ return result;
+ }
+ }
+ return nullptr;
+}
+
#endif // FEATURE_COMWRAPPERS
void Interop::OnGCStarted(_In_ int nCondemnedGeneration)
diff --git a/src/coreclr/src/vm/interoplibinterface.h b/src/coreclr/src/vm/interoplibinterface.h
index 6a5884a66075c..3e5abda54cd6a 100644
--- a/src/coreclr/src/vm/interoplibinterface.h
+++ b/src/coreclr/src/vm/interoplibinterface.h
@@ -37,6 +37,9 @@ class ComWrappersNative
public: // COM activation
static void MarkWrapperAsComActivated(_In_ IUnknown* wrapperMaybe);
+
+public: // Unwrapping support
+ static IUnknown* GetIdentityForObject(_In_ OBJECTREF* objectPROTECTED, _In_ REFIID riid);
};
class GlobalComWrappersForMarshalling
@@ -58,6 +61,25 @@ class GlobalComWrappersForMarshalling
_Out_ OBJECTREF* objRef);
};
+
+class GlobalComWrappersForTrackerSupport
+{
+public:
+ // Native QCall for the ComWrappers managed type to indicate a global instance
+ // is registered for tracker support. This should be set if the private static member
+ // representing the global instance for tracker support on ComWrappers is non-null.
+ static void QCALLTYPE SetGlobalInstanceRegisteredForTrackerSupport();
+
+public: // Functions operating on a registered global instance for tracker support
+ static bool TryGetOrCreateComInterfaceForObject(
+ _In_ OBJECTREF instance,
+ _Outptr_ void** wrapperRaw);
+
+ static bool TryGetOrCreateObjectForComInstance(
+ _In_ IUnknown* externalComObject,
+ _Out_ OBJECTREF* objRef);
+};
+
#endif // FEATURE_COMWRAPPERS
class Interop
diff --git a/src/coreclr/src/vm/marshalnative.cpp b/src/coreclr/src/vm/marshalnative.cpp
index 56657944eb8a5..f9cd26b4477e5 100644
--- a/src/coreclr/src/vm/marshalnative.cpp
+++ b/src/coreclr/src/vm/marshalnative.cpp
@@ -558,7 +558,7 @@ FCIMPL2(LPVOID, MarshalNative::GCHandleInternalAlloc, Object *obj, int type)
OBJECTREF objRef(obj);
- assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_WINRT);
+ assert(type >= HNDTYPE_WEAK_SHORT && type <= HNDTYPE_WEAK_NATIVE_COM);
if (CORProfilerTrackGC())
{
diff --git a/src/coreclr/src/vm/runtimehandles.cpp b/src/coreclr/src/vm/runtimehandles.cpp
index a16bc1a1c2aaa..82c793bf3f7af 100644
--- a/src/coreclr/src/vm/runtimehandles.cpp
+++ b/src/coreclr/src/vm/runtimehandles.cpp
@@ -1110,7 +1110,7 @@ PVOID QCALLTYPE RuntimeTypeHandle::GetGCHandle(QCall::TypeHandle pTypeHandle, IN
GCX_COOP();
TypeHandle th = pTypeHandle.AsTypeHandle();
- assert(handleType >= HNDTYPE_WEAK_SHORT && handleType <= HNDTYPE_WEAK_WINRT);
+ assert(handleType >= HNDTYPE_WEAK_SHORT && handleType <= HNDTYPE_WEAK_NATIVE_COM);
objHandle = AppDomain::GetCurrentDomain()->CreateTypedHandle(NULL, static_cast(handleType));
th.GetLoaderAllocator()->RegisterHandleForCleanup(objHandle);
diff --git a/src/coreclr/src/vm/weakreferencenative.cpp b/src/coreclr/src/vm/weakreferencenative.cpp
index b1dc825494f35..2cdb83ce9b81e 100644
--- a/src/coreclr/src/vm/weakreferencenative.cpp
+++ b/src/coreclr/src/vm/weakreferencenative.cpp
@@ -16,6 +16,7 @@
#include "typestring.h"
#include "typeparse.h"
#include "threadsuspend.h"
+#include "interoplibinterface.h"
//************************************************************************
@@ -34,7 +35,7 @@ const LPVOID specialWeakReferenceHandles[3] = { 0, 0, 0 };
//
// A WeakReference instance can hold one of three types of handles - short or long weak handles,
-// or a WinRT weak reference handle. The WinRT weak reference handle has the extra capability
+// or a native COM weak reference handle. The native COM weak reference handle has the extra capability
// of recreating an RCW for a COM object which is still alive even though the previous RCW had
// been collected. In order to differentiate this type of handle from the standard weak handles,
// the bottom bit is stolen.
@@ -50,23 +51,23 @@ const LPVOID specialWeakReferenceHandles[3] = { 0, 0, 0 };
// The following functions are to set, test, and unset that bit before the handle is used.
//
-// Determine if an object handle is a WinRT weak reference handle
-bool IsWinRTWeakReferenceHandle(OBJECTHANDLE handle)
+// Determine if an object handle is a native COM weak reference handle
+bool IsNativeComWeakReferenceHandle(OBJECTHANDLE handle)
{
STATIC_CONTRACT_LEAF;
return (reinterpret_cast(handle) & 0x1) != 0x0;
}
-// Mark an object handle as being a WinRT weak reference handle
-OBJECTHANDLE SetWinRTWeakReferenceHandle(OBJECTHANDLE handle)
+// Mark an object handle as being a native COM weak reference handle
+OBJECTHANDLE SetNativeComWeakReferenceHandle(OBJECTHANDLE handle)
{
STATIC_CONTRACT_LEAF;
- _ASSERTE(!IsWinRTWeakReferenceHandle(handle));
+ _ASSERTE(!IsNativeComWeakReferenceHandle(handle));
return reinterpret_cast(reinterpret_cast(handle) | 0x1);
}
-// Get the object handle value even if the object is a WinRT weak reference
+// Get the object handle value even if the object is a native COM weak reference
OBJECTHANDLE GetHandleValue(OBJECTHANDLE handle)
{
STATIC_CONTRACT_LEAF;
@@ -102,17 +103,17 @@ struct WeakHandleSpinLockHolder
#ifdef FEATURE_COMINTEROP
-// Get a WinRT weak reference for the object underlying an RCW if applicable. If the incoming object cannot
-// use a WinRT weak reference, nullptr is returned. Otherwise, an AddRef-ed IWeakReference* for the COM
+// Get a native COM weak reference for the object underlying an RCW if applicable. If the incoming object cannot
+// use a native COM weak reference, nullptr is returned. Otherwise, an AddRef-ed IWeakReference* for the COM
// object underlying the RCW is returned.
//
-// In order to qualify to be used with a HNDTYPE_WEAK_WINRT, the incoming object must:
+// In order to qualify to be used with a HNDTYPE_WEAK_NATIVE_COM, the incoming object must:
// * be an RCW
// * respond to a QI for IWeakReferenceSource
// * succeed when asked for an IWeakReference*
//
// Note that *pObject should be GC protected on the way into this method
-IWeakReference* GetWinRTWeakReference(OBJECTREF* pObject)
+IWeakReference* GetComWeakReference(OBJECTREF* pObject)
{
CONTRACTL
{
@@ -132,21 +133,24 @@ IWeakReference* GetWinRTWeakReference(OBJECTREF* pObject)
MethodTable* pMT = (*pObject)->GetMethodTable();
- // If the object is not an RCW, then we do not want to use a WinRT weak reference to it
- if (!pMT->IsComObjectType())
- {
- return nullptr;
- }
+ SafeComHolder pWeakReferenceSource(nullptr);
- // If the object is a managed type deriving from a COM type, then we also do not want to use a WinRT
+ // If the object is not an RCW, then we do not want to use a native COM weak reference to it
+ // If the object is a managed type deriving from a COM type, then we also do not want to use a native COM
// weak reference to it. (Otherwise, we'll wind up resolving IWeakReference-s back into the CLR
// when we don't want to have reentrancy).
- if (pMT != g_pBaseCOMObject && pMT->IsExtensibleRCW())
+ if (pMT->IsComObjectType()
+ && (pMT == g_pBaseCOMObject || !pMT->IsExtensibleRCW()))
{
- return nullptr;
+ pWeakReferenceSource = reinterpret_cast(GetComIPFromObjectRef(pObject, IID_IWeakReferenceSource, false /* throwIfNoComIP */));
+ }
+#ifdef FEATURE_COMWRAPPERS
+ else
+ {
+ pWeakReferenceSource = reinterpret_cast(ComWrappersNative::GetIdentityForObject(pObject, IID_IWeakReferenceSource));
}
+#endif
- SafeComHolder pWeakReferenceSource(reinterpret_cast(GetComIPFromObjectRef(pObject, IID_IWeakReferenceSource, false /* throwIfNoComIP */)));
if (pWeakReferenceSource == nullptr)
{
return nullptr;
@@ -162,17 +166,17 @@ IWeakReference* GetWinRTWeakReference(OBJECTREF* pObject)
return pWeakReference.Extract();
}
-// Given an object handle that stores a WinRT weak reference, attempt to create an RCW
-// and store it back in the handle, returning the RCW. If the underlying WinRT object
+// Given an object handle that stores a native COM weak reference, attempt to create an RCW
+// and store it back in the handle, returning the RCW. If the underlying native COM object
// is not alive, then the result is NULL.
//
// In order to create a new RCW, we must:
-// * Have an m_handle of HNDTYPE_WEAK_WINRT (ie the bottom bit of m_handle is set)
+// * Have an m_handle of HNDTYPE_WEAK_NATIVE_COM (ie the bottom bit of m_handle is set)
// * Have stored an IWeakReference* in the handle extra info when setting up the handle
-// (see GetWinRTWeakReference)
+// (see GetComWeakReference)
// * The IWeakReference* must respond to a Resolve request for IID_IInspectable
// *
-NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, TypeHandle targetType, LPVOID __me)
+NOINLINE Object* LoadComWeakReferenceTarget(WEAKREFERENCEREF weakReference, TypeHandle targetType, LPVOID __me)
{
CONTRACTL
{
@@ -200,14 +204,14 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty
//
// Since we're acquiring and releasing the lock multiple times, we need to check the handle state each time we
// reacquire the lock to make sure that another thread hasn't reassigned the target of the handle or finalized it
- SafeComHolder pWinRTWeakReference = nullptr;
+ SafeComHolder pComWeakReference = nullptr;
{
WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(gc.weakReference), &gc.weakReference);
GCX_NOTRIGGER();
// Make sure that while we were not holding the spin lock, another thread did not change the target of
// this weak reference. Only fetch the IWeakReference* if we still have a valid handle holding a NULL object
- // and the handle is still a HNDTYPE_WEAK_WINRT type handle.
+ // and the handle is still a HNDTYPE_WEAK_NATIVE_COM type handle.
if ((handle.Handle != NULL) && !IS_SPECIAL_HANDLE(handle.Handle))
{
if (*(Object **)(handle.Handle) != NULL)
@@ -217,22 +221,22 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty
// weak reference is targeting.
gc.target = ObjectToOBJECTREF(*(Object **)(handle.Handle));
}
- else if(IsWinRTWeakReferenceHandle(handle.RawHandle))
+ else if(IsNativeComWeakReferenceHandle(handle.RawHandle))
{
- _ASSERTE(GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handle.Handle) == HNDTYPE_WEAK_WINRT);
+ _ASSERTE(GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handle.Handle) == HNDTYPE_WEAK_NATIVE_COM);
// Retrieve the associated IWeakReference* for this weak reference. Add a reference to it while we release
// the spin lock so that another thread doesn't release it out from underneath us.
//
- // Setting pWinRTWeakReference will claim that it triggers a GC, however that's not true in this case because
+ // Setting pComWeakReference will claim that it triggers a GC, however that's not true in this case because
// it's always set to NULL here and there's nothing for it to release.
- _ASSERTE(pWinRTWeakReference.IsNull());
+ _ASSERTE(pComWeakReference.IsNull());
CONTRACT_VIOLATION(GCViolation);
IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
- pWinRTWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle));
- if (!pWinRTWeakReference.IsNull())
+ pComWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle));
+ if (!pComWeakReference.IsNull())
{
- pWinRTWeakReference->AddRef();
+ pComWeakReference->AddRef();
}
}
}
@@ -242,16 +246,16 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty
// identity of the underlying COM object (assuming that object is still alive). This work is done without holding the
// spin lock since it will call out to arbitrary code and as such we need to switch to preemptive mode.
SafeComHolder pTargetIdentity = nullptr;
- if (pWinRTWeakReference != nullptr)
+ if (pComWeakReference != nullptr)
{
_ASSERTE(gc.target == NULL);
GCX_PREEMP();
- // Using the IWeakReference*, get ahold of the target WinRT object's IInspectable*. If this resolve fails, then we
- // assume that the underlying WinRT object is no longer alive, and thus we cannot create a new RCW for it.
+ // Using the IWeakReference*, get ahold of the target native COM object's IInspectable*. If this resolve fails, then we
+ // assume that the underlying native COM object is no longer alive, and thus we cannot create a new RCW for it.
SafeComHolderPreemp pTarget = nullptr;
- if (SUCCEEDED(pWinRTWeakReference->Resolve(IID_IInspectable, &pTarget)))
+ if (SUCCEEDED(pComWeakReference->Resolve(IID_IInspectable, &pTarget)))
{
if (!pTarget.IsNull())
{
@@ -264,7 +268,11 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty
// If we were able to get an IUnkown identity for the object, then we can find or create an associated RCW for it.
if (!pTargetIdentity.IsNull())
{
- GetObjectRefFromComIP(&gc.rcw, pTargetIdentity);
+ // Try the global COM wrappers first before falling back to the built-in system.
+ if (!GlobalComWrappersForTrackerSupport::TryGetOrCreateObjectForComInstance(pTargetIdentity, &gc.rcw))
+ {
+ GetObjectRefFromComIP(&gc.rcw, pTargetIdentity);
+ }
}
// If we were able to get an RCW, then we need to reacquire the spin lock and store the RCW in the handle. Note that
@@ -272,7 +280,7 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty
// building the RCW. In that case, we will defer to the hadle that the other thread set, and let the RCW die.
if (gc.rcw != NULL)
{
- // Make sure the type we got back from the WinRT object is compatible with the type the managed
+ // Make sure the type we got back from the native COM object is compatible with the type the managed
// weak reference expects. (For instance, in the WeakReference case, the returned type
// had better be compatible with T).
TypeHandle rcwType(gc.rcw->GetMethodTable());
@@ -284,7 +292,7 @@ NOINLINE Object* LoadWinRTWeakReferenceTarget(WEAKREFERENCEREF weakReference, Ty
SString resolvedTypeName;
TypeString::AppendType(resolvedTypeName, rcwType, TypeString::FormatNamespace | TypeString::FormatFullInst | TypeString::FormatAssembly);
- COMPlusThrow(kInvalidCastException, IDS_EE_WINRT_WEAKREF_BAD_TYPE, weakReferenceTypeName.GetUnicode(), resolvedTypeName.GetUnicode());
+ COMPlusThrow(kInvalidCastException, IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE, weakReferenceTypeName.GetUnicode(), resolvedTypeName.GetUnicode());
}
WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(gc.weakReference), &gc.weakReference);
@@ -420,12 +428,21 @@ FCIMPL3(void, WeakReferenceNative::Create, WeakReferenceObject * pThisUNSAFE, Ob
// Create the handle.
#ifdef FEATURE_COMINTEROP
- IWeakReference* pRawWinRTWeakReference = GetWinRTWeakReference(&gc.pTarget);
- if (pRawWinRTWeakReference != nullptr)
+ IWeakReference* pRawComWeakReference = nullptr;
+ if (gc.pTarget != NULL)
{
- SafeComHolder pWinRTWeakReferenceHolder(pRawWinRTWeakReference);
- gc.pThis->m_Handle = SetWinRTWeakReferenceHandle(GetAppDomain()->CreateWinRTWeakHandle(gc.pTarget, pWinRTWeakReferenceHolder));
- pWinRTWeakReferenceHolder.SuppressRelease();
+ SyncBlock* pSyncBlock = gc.pTarget->PassiveGetSyncBlock();
+ if (pSyncBlock != nullptr && pSyncBlock->GetInteropInfoNoCreate() != nullptr)
+ {
+ pRawComWeakReference = GetComWeakReference(&gc.pTarget);
+ }
+ }
+
+ if (pRawComWeakReference != nullptr)
+ {
+ SafeComHolder pComWeakReferenceHolder(pRawComWeakReference);
+ gc.pThis->m_Handle = SetNativeComWeakReferenceHandle(GetAppDomain()->CreateNativeComWeakHandle(gc.pTarget, pComWeakReferenceHolder));
+ pComWeakReferenceHolder.SuppressRelease();
}
else
#endif // FEATURE_COMINTEROP
@@ -463,12 +480,21 @@ FCIMPL3(void, WeakReferenceOfTNative::Create, WeakReferenceObject * pThisUNSAFE,
// Create the handle.
#ifdef FEATURE_COMINTEROP
- IWeakReference* pRawWinRTWeakReference = GetWinRTWeakReference(&gc.pTarget);
- if (pRawWinRTWeakReference != nullptr)
+ IWeakReference* pRawComWeakReference = nullptr;
+ if (gc.pTarget != NULL)
+ {
+ SyncBlock* pSyncBlock = gc.pTarget->PassiveGetSyncBlock();
+ if (pSyncBlock != nullptr && pSyncBlock->GetInteropInfoNoCreate() != nullptr)
+ {
+ pRawComWeakReference = GetComWeakReference(&gc.pTarget);
+ }
+ }
+
+ if (pRawComWeakReference != nullptr)
{
- SafeComHolder pWinRTWeakReferenceHolder(pRawWinRTWeakReference);
- gc.pThis->m_Handle = SetWinRTWeakReferenceHandle(GetAppDomain()->CreateWinRTWeakHandle(gc.pTarget, pWinRTWeakReferenceHolder));
- pWinRTWeakReferenceHolder.SuppressRelease();
+ SafeComHolder pComWeakReferenceHolder(pRawComWeakReference);
+ gc.pThis->m_Handle = SetNativeComWeakReferenceHandle(GetAppDomain()->CreateNativeComWeakHandle(gc.pTarget, pComWeakReferenceHolder));
+ pComWeakReferenceHolder.SuppressRelease();
}
else
#endif // FEATURE_COMINTEROP
@@ -499,7 +525,7 @@ void FinalizeWeakReference(Object * obj)
// The suspension state of the runtime must be prevented from changing while in this function in order for this to be safe.
OBJECTHANDLE handle = ThreadSuspend::SysIsSuspended() ? pThis->m_Handle.LoadWithoutBarrier() : AcquireWeakHandleSpinLock(pThis);
OBJECTHANDLE handleToDestroy = NULL;
- bool isWeakWinRTHandle = false;
+ bool isWeakNativeComHandle = false;
// Check for not yet constructed or already finalized handle
if ((handle != NULL) && !IS_SPECIAL_HANDLE(handle))
@@ -509,8 +535,8 @@ void FinalizeWeakReference(Object * obj)
// Cache the old handle value
HandleType handleType = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handleToDestroy);
#ifdef FEATURE_COMINTEROP
- _ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT || handleType == HNDTYPE_WEAK_WINRT);
- isWeakWinRTHandle = handleType == HNDTYPE_WEAK_WINRT;
+ _ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT || handleType == HNDTYPE_WEAK_NATIVE_COM);
+ isWeakNativeComHandle = handleType == HNDTYPE_WEAK_NATIVE_COM;
#else // !FEATURE_COMINTEROP
_ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT);
#endif // FEATURE_COMINTEROP
@@ -528,9 +554,9 @@ void FinalizeWeakReference(Object * obj)
if (handleToDestroy != NULL)
{
#ifdef FEATURE_COMINTEROP
- if (isWeakWinRTHandle)
+ if (isWeakNativeComHandle)
{
- DestroyWinRTWeakHandle(handleToDestroy);
+ DestroyNativeComWeakHandle(handleToDestroy);
}
else
#endif // FEATURE_COMINTEROP
@@ -645,14 +671,14 @@ FCIMPL1(Object *, WeakReferenceNative::GetTarget, WeakReferenceObject * pThisUNS
OBJECTREF pTarget = GetWeakReferenceTarget(pThis);
#ifdef FEATURE_COMINTEROP
- // If we found an object, or we're not a WinRT weak reference, then we're done. Othewrise
- // we can try to create a new RCW to the underlying WinRT object if it's still alive.
- if (pTarget != NULL || !IsWinRTWeakReferenceHandle(pThis->m_Handle))
+ // If we found an object, or we're not a native COM weak reference, then we're done. Othewrise
+ // we can try to create a new RCW to the underlying native COM object if it's still alive.
+ if (pTarget != NULL || !IsNativeComWeakReferenceHandle(pThis->m_Handle))
{
FC_GC_POLL_AND_RETURN_OBJREF(pTarget);
}
- FC_INNER_RETURN(Object*, LoadWinRTWeakReferenceTarget(pThis, g_pObjectClass, GetEEFuncEntryPointMacro(WeakReferenceNative::GetTarget)));
+ FC_INNER_RETURN(Object*, LoadComWeakReferenceTarget(pThis, g_pObjectClass, GetEEFuncEntryPointMacro(WeakReferenceNative::GetTarget)));
#else // !FEATURE_COMINTEROP
FC_GC_POLL_AND_RETURN_OBJREF(pTarget);
#endif // FEATURE_COMINTEROP
@@ -673,14 +699,14 @@ FCIMPL1(Object *, WeakReferenceOfTNative::GetTarget, WeakReferenceObject * pThis
#ifdef FEATURE_COMINTEROP
- // If we found an object, or we're not a WinRT weak reference, then we're done. Othewrise
- // we can try to create a new RCW to the underlying WinRT object if it's still alive.
- if (pTarget != NULL || !IsWinRTWeakReferenceHandle(pThis->m_Handle))
+ // If we found an object, or we're not a native COM weak reference, then we're done. Othewrise
+ // we can try to create a new RCW to the underlying native COM object if it's still alive.
+ if (pTarget != NULL || !IsNativeComWeakReferenceHandle(pThis->m_Handle))
{
FC_GC_POLL_AND_RETURN_OBJREF(pTarget);
}
- FC_INNER_RETURN(Object*, LoadWinRTWeakReferenceTarget(pThis, pThis->GetMethodTable()->GetInstantiation()[0], GetEEFuncEntryPointMacro(WeakReferenceOfTNative::GetTarget)));
+ FC_INNER_RETURN(Object*, LoadComWeakReferenceTarget(pThis, pThis->GetMethodTable()->GetInstantiation()[0], GetEEFuncEntryPointMacro(WeakReferenceOfTNative::GetTarget)));
#else // !FEATURE_COMINTEROP
FC_GC_POLL_AND_RETURN_OBJREF(pTarget);
#endif // FEATURE_COMINTEROP
@@ -711,7 +737,7 @@ FCIMPLEND
#include
-// Slow path helper for setting the target of a weak reference. This code is used if a WinRT weak reference might
+// Slow path helper for setting the target of a weak reference. This code is used if a native COM weak reference might
// be required.
NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF target, LPVOID __me)
{
@@ -721,7 +747,7 @@ NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF t
HELPER_METHOD_FRAME_BEGIN_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, target, weakReference);
#ifdef FEATURE_COMINTEROP
- SafeComHolder pTargetWeakReference(GetWinRTWeakReference(&target));
+ SafeComHolder pTargetWeakReference(GetComWeakReference(&target));
#endif // FEATURE_COMINTEROP
@@ -735,30 +761,30 @@ NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF t
// Existing target is a GC object, new target is a GC object:
// * Just store the new object in the handle
//
- // Existing target is WinRT, new target is WinRT:
+ // Existing target is native COM weak reference, new target is native COM weak reference:
// * Release the existing IWeakReference*
// * Store the new IWeakReference*
// * Store the new object in the handle
//
- // Existing target is WinRT, new target is GC:
+ // Existing target is native COM weak reference, new target is GC:
// * Release the existing IWeakReference*
// * Store null to the IWeakReference* field
// * Store the new object in the handle
//
- // Existing target is GC, new target is WinRT:
+ // Existing target is GC, new target is native COM weak reference:
// * Destroy the existing handle
- // * Allocate a new WinRT weak handle for the new target
+ // * Allocate a new native COM weak handle for the new target
//
- if (IsWinRTWeakReferenceHandle(handle.RawHandle))
+ if (IsNativeComWeakReferenceHandle(handle.RawHandle))
{
- // If the existing reference is a WinRT weak reference, we need to release its IWeakReference pointer
+ // If the existing reference is a native COM weak reference, we need to release its IWeakReference pointer
// and update it with the new weak reference pointer. If the incoming object is not an RCW that can
// use IWeakReference, then pTargetWeakReference will be null. Therefore, no matter what the incoming
// object type is, we can unconditionally store pTargetWeakReference to the object handle's extra data.
IGCHandleManager *mgr = GCHandleUtilities::GetGCHandleManager();
IWeakReference* pExistingWeakReference = reinterpret_cast(mgr->GetExtraInfoFromHandle(handle.Handle));
- mgr->SetExtraInfoForHandle(handle.Handle, HNDTYPE_WEAK_WINRT, reinterpret_cast(pTargetWeakReference.GetValue()));
+ mgr->SetExtraInfoForHandle(handle.Handle, HNDTYPE_WEAK_NATIVE_COM, reinterpret_cast(pTargetWeakReference.GetValue()));
StoreObjectInHandle(handle.Handle, target);
if (pExistingWeakReference != nullptr)
@@ -768,15 +794,15 @@ NOINLINE void SetWeakReferenceTarget(WEAKREFERENCEREF weakReference, OBJECTREF t
}
else if (pTargetWeakReference != nullptr)
{
- // The existing handle is not a WinRT weak reference, but we need to store the new object in
- // a WinRT weak reference. Therefore we need to destroy the old handle and create a new WinRT
+ // The existing handle is not a native COM weak reference, but we need to store the new object in
+ // a native COM weak reference. Therefore we need to destroy the old handle and create a new native COM
// handle. The new handle needs to be allocated first to prevent the weak reference from holding
// a destroyed handle if we fail to allocate the new one.
- _ASSERTE(!IsWinRTWeakReferenceHandle(handle.RawHandle));
+ _ASSERTE(!IsNativeComWeakReferenceHandle(handle.RawHandle));
OBJECTHANDLE previousHandle = handle.RawHandle;
- handle.Handle = GetAppDomain()->CreateWinRTWeakHandle(target, pTargetWeakReference);
- handle.RawHandle = SetWinRTWeakReferenceHandle(handle.Handle);
+ handle.Handle = GetAppDomain()->CreateNativeComWeakHandle(target, pTargetWeakReference);
+ handle.RawHandle = SetNativeComWeakReferenceHandle(handle.Handle);
DestroyTypedHandle(previousHandle);
}
@@ -822,7 +848,7 @@ FCIMPL2(void, WeakReferenceNative::SetTarget, WeakReferenceObject * pThisUNSAFE,
// If the existing handle is a GC weak handle and the new target is not an RCW, then
// we can avoid setting up a helper method frame and just reset the handle directly.
- if (!IsWinRTWeakReferenceHandle(handle))
+ if (!IsNativeComWeakReferenceHandle(handle))
{
if (pTarget == NULL || !pTarget->GetMethodTable()->IsComObjectType())
{
@@ -875,7 +901,7 @@ FCIMPL2(void, WeakReferenceOfTNative::SetTarget, WeakReferenceObject * pThisUNSA
// If the existing handle is a GC weak handle and the new target is not an RCW, then
// we can avoid setting up a helper method frame and just reset the handle directly.
- if (!IsWinRTWeakReferenceHandle(handle))
+ if (!IsNativeComWeakReferenceHandle(handle))
{
if (pTarget == NULL || !pTarget->GetMethodTable()->IsComObjectType())
{
diff --git a/src/coreclr/tests/src/Interop/CMakeLists.txt b/src/coreclr/tests/src/Interop/CMakeLists.txt
index 8a39e97624f93..778d9ab3bded8 100644
--- a/src/coreclr/tests/src/Interop/CMakeLists.txt
+++ b/src/coreclr/tests/src/Interop/CMakeLists.txt
@@ -81,6 +81,7 @@ if(CLR_CMAKE_TARGET_WIN32)
add_subdirectory(COM/NativeClients/Dispatch)
add_subdirectory(COM/NativeClients/Events)
add_subdirectory(COM/ComWrappers/MockReferenceTrackerRuntime)
+ add_subdirectory(COM/ComWrappers/WeakReference)
add_subdirectory(WinRT/NativeComponent)
# IJW isn't supported on ARM64
diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/CMakeLists.txt b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/CMakeLists.txt
new file mode 100644
index 0000000000000..8166db2186574
--- /dev/null
+++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/CMakeLists.txt
@@ -0,0 +1,10 @@
+project (WeakReferenceNative)
+include_directories( ${INC_PLATFORM_DIR} )
+set(SOURCES WeakReferenceNative.cpp)
+
+# add the shared library
+add_library (WeakReferenceNative SHARED ${SOURCES})
+target_link_libraries(WeakReferenceNative ${LINK_LIBRARIES_ADDITIONAL})
+
+# add the install targets
+install (TARGETS WeakReferenceNative DESTINATION bin)
diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp
new file mode 100644
index 0000000000000..5617b11767981
--- /dev/null
+++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceNative.cpp
@@ -0,0 +1,124 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#include
+#include
+#include
+#include
+
+namespace
+{
+ struct WeakReference : public IWeakReference, public UnknownImpl
+ {
+ IInspectable* _reference;
+ std::atomic _strongRefCount;
+
+ WeakReference(IInspectable* reference, ULONG strongRefCount)
+ : _reference(reference),
+ _strongRefCount(strongRefCount)
+ {}
+
+ ULONG AddStrongRef()
+ {
+ assert(_strongRefCount > 0);
+ return (++_strongRefCount);
+ }
+
+ ULONG ReleaseStrongRef()
+ {
+ assert(_strongRefCount > 0);
+ return --_strongRefCount;
+ }
+
+ STDMETHOD(Resolve)(REFIID riid, IInspectable** ppvObject)
+ {
+ if (_strongRefCount > 0)
+ {
+ void* pObject;
+ HRESULT hr = _reference->QueryInterface(riid, &pObject);
+ *ppvObject = reinterpret_cast(pObject);
+ return hr;
+ }
+ return E_NOINTERFACE;
+ }
+
+ STDMETHOD(QueryInterface)(
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
+ {
+ return DoQueryInterface(riid, ppvObject, static_cast(this));
+ }
+
+ DEFINE_REF_COUNTING()
+ };
+
+ struct WeakReferencableObject : public IWeakReferenceSource, public IInspectable, public UnknownImpl
+ {
+ ComSmartPtr _weakReference;
+ STDMETHOD(GetWeakReference)(_COM_Outptr_ IWeakReference** ppWeakReference)
+ {
+ if (!_weakReference)
+ {
+ ULONG refCount = UnknownImpl::GetRefCount();
+ _weakReference = new WeakReference(this, refCount);
+ }
+ _weakReference->AddRef();
+ *ppWeakReference = _weakReference;
+ return S_OK;
+ }
+
+ STDMETHOD(GetRuntimeClassName)(HSTRING* pRuntimeClassName)
+ {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(GetIids)(
+ ULONG *iidCount,
+ IID **iids)
+ {
+ return E_NOTIMPL;
+ }
+
+ STDMETHOD(GetTrustLevel)(TrustLevel *trustLevel)
+ {
+ *trustLevel = FullTrust;
+ return S_OK;
+ }
+
+ STDMETHOD(QueryInterface)(
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
+ {
+ HRESULT hr = DoQueryInterface(riid, ppvObject, static_cast(this), static_cast(this), static_cast(this));
+ if (SUCCEEDED(hr) && _weakReference)
+ {
+ _weakReference->AddStrongRef();
+ }
+ return hr;
+ }
+ STDMETHOD_(ULONG, AddRef)(void)
+ {
+ if (_weakReference)
+ {
+ return _weakReference->AddStrongRef();
+ }
+ return UnknownImpl::DoAddRef();
+ }
+ STDMETHOD_(ULONG, Release)(void)
+ {
+ if (_weakReference)
+ {
+ ULONG c = _weakReference->ReleaseStrongRef();
+ if (c == 0)
+ delete this;
+ return c;
+ }
+ return UnknownImpl::DoRelease();
+ }
+ };
+}
+extern "C" DLL_EXPORT WeakReferencableObject* STDMETHODCALLTYPE CreateWeakReferencableObject()
+{
+ return new WeakReferencableObject();
+}
diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs
new file mode 100644
index 0000000000000..acde6f6415802
--- /dev/null
+++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.cs
@@ -0,0 +1,137 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+namespace ComWrappersTests
+{
+ using System;
+ using System.Collections;
+ using System.Collections.Generic;
+ using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
+ using TestLibrary;
+
+ static class WeakReferenceNative
+ {
+ [DllImport(nameof(WeakReferenceNative))]
+ public static extern IntPtr CreateWeakReferencableObject();
+ }
+
+ public struct VtblPtr
+ {
+ public IntPtr Vtbl;
+ }
+
+ public class WeakReferencableWrapper
+ {
+ private struct Vtbl
+ {
+ public IntPtr QueryInterface;
+ public _AddRef AddRef;
+ public _Release Release;
+ }
+
+ private delegate int _AddRef(IntPtr This);
+ private delegate int _Release(IntPtr This);
+
+ private readonly IntPtr instance;
+ private readonly Vtbl vtable;
+
+ public WeakReferencableWrapper(IntPtr instance)
+ {
+ var inst = Marshal.PtrToStructure(instance);
+ this.vtable = Marshal.PtrToStructure(inst.Vtbl);
+ this.instance = instance;
+ }
+
+ ~WeakReferencableWrapper()
+ {
+ if (this.instance != IntPtr.Zero)
+ {
+ this.vtable.Release(this.instance);
+ }
+ }
+ }
+
+ class Program
+ {
+ class TestComWrappers : ComWrappers
+ {
+ protected unsafe override ComInterfaceEntry* ComputeVtables(object obj, CreateComInterfaceFlags flags, out int count)
+ {
+ count = 0;
+ return null;
+ }
+
+ protected override object CreateObject(IntPtr externalComObject, CreateObjectFlags flag)
+ {
+ return new WeakReferencableWrapper(externalComObject);
+ }
+
+ protected override void ReleaseObjects(IEnumerable objects)
+ {
+ }
+
+ public static readonly ComWrappers Instance = new TestComWrappers();
+ }
+
+ static void ValidateNativeWeakReference()
+ {
+ Console.WriteLine($"Running {nameof(ValidateNativeWeakReference)}...");
+
+ static (WeakReference, IntPtr) GetWeakReference()
+ {
+ var cw = new TestComWrappers();
+
+ IntPtr objRaw = WeakReferenceNative.CreateWeakReferencableObject();
+
+ var obj = (WeakReferencableWrapper)cw.GetOrCreateObjectForComInstance(objRaw, CreateObjectFlags.None);
+
+ // The returned WeakReferencableWrapper from ComWrappers takes ownership
+ // of the ref returned from CreateWeakReferencableObject.
+ // Call Marshal.AddRef to ensure that objRaw owns a reference.
+ Marshal.AddRef(objRaw);
+
+ return (new WeakReference(obj), objRaw);
+ }
+
+ static bool CheckIfWeakReferenceIsAlive(WeakReference wr)
+ {
+ return wr.TryGetTarget(out _);
+ }
+
+ var (weakRef, nativeRef) = GetWeakReference();
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ // A weak reference to an RCW wrapping an IWeakReference should stay alive even after the RCW dies
+ Assert.IsTrue(CheckIfWeakReferenceIsAlive(weakRef));
+
+ // Release the last native reference.
+ Marshal.Release(nativeRef);
+
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ // After all native references die and the RCW is collected, the weak reference should be dead and stay dead.
+ Assert.IsFalse(CheckIfWeakReferenceIsAlive(weakRef));
+
+ }
+
+ static int Main(string[] doNotUse)
+ {
+ try
+ {
+ ComWrappers.RegisterForTrackerSupport(TestComWrappers.Instance);
+ ValidateNativeWeakReference();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+
+ return 100;
+ }
+ }
+}
+
diff --git a/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj
new file mode 100644
index 0000000000000..edcc33106ebde
--- /dev/null
+++ b/src/coreclr/tests/src/Interop/COM/ComWrappers/WeakReference/WeakReferenceTest.csproj
@@ -0,0 +1,24 @@
+
+
+ Exe
+
+ true
+
+ true
+ true
+ true
+
+
+
+
+
+
+
+
+
+ 1
+
+
+
+
+
diff --git a/src/coreclr/tests/src/Interop/common/ComHelpers.h b/src/coreclr/tests/src/Interop/common/ComHelpers.h
index c90ff7a773a2e..673f19063647d 100644
--- a/src/coreclr/tests/src/Interop/common/ComHelpers.h
+++ b/src/coreclr/tests/src/Interop/common/ComHelpers.h
@@ -105,6 +105,12 @@ class UnknownImpl
return c;
}
+protected:
+ ULONG GetRefCount()
+ {
+ return _refCount;
+ }
+
private:
std::atomic _refCount = 1;
};