<FeaturePortableShuffleThunks Condition="'$(Platform)' != 'x86'">true</FeaturePortableShuffleThunks>
<FeatureInstantiatingStubAsIL>true</FeatureInstantiatingStubAsIL>
<FeatureStubsAsIL>true</FeatureStubsAsIL>
+ <FeatureComWrappers>true</FeatureComWrappers>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetsWindows)' == 'true'">
set(FEATURE_SINGLE_FILE_DIAGNOSTICS 1)
endif(NOT DEFINED FEATURE_SINGLE_FILE_DIAGNOSTICS)
-if (CLR_CMAKE_TARGET_WIN32)
+if (CLR_CMAKE_TARGET_WIN32 OR CLR_CMAKE_TARGET_UNIX)
set(FEATURE_COMWRAPPERS 1)
endif()
HRESULT DumpManagedObject(CLRDataEnumMemoryFlags flags, OBJECTREF objRef);
HRESULT DumpManagedExcepObject(CLRDataEnumMemoryFlags flags, OBJECTREF objRef);
HRESULT DumpManagedStackTraceStringObject(CLRDataEnumMemoryFlags flags, STRINGREF orefStackTrace);
-#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
+#if (defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)) && !defined(TARGET_UNIX)
HRESULT DumpStowedExceptionObject(CLRDataEnumMemoryFlags flags, CLRDATA_ADDRESS ccwPtr);
HRESULT EnumMemStowedException(CLRDataEnumMemoryFlags flags);
#endif
{
SUPPORTS_DAC;
-#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
+#if (defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)) && !defined(TARGET_UNIX)
// Dump the exception object stored in the WinRT stowed exception
EnumMemStowedException(flags);
#endif // defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
}
-#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
+#if (defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)) && !defined(TARGET_UNIX)
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// WinRT stowed exception holds the (CCW)pointer to a managed exception object.
ReportMem(remoteStowedException, sizeof(STOWED_EXCEPTION_INFORMATION_HEADER));
// check if this is a v2 stowed exception
- STOWED_EXCEPTION_INFORMATION_V2 stowedException = { 0 };
+ STOWED_EXCEPTION_INFORMATION_V2 stowedException = { {0} };
if (FAILED(m_pTarget->ReadVirtual(TO_CDADDR(remoteStowedException),
(PBYTE)&stowedException, sizeof(STOWED_EXCEPTION_INFORMATION_HEADER), &bytesRead))
|| bytesRead != sizeof(STOWED_EXCEPTION_INFORMATION_HEADER)
IDS_EE_INTEROP_STUB_CA_NO_ACCESS_TO_STUB_METHOD "The interop method '%1' cannot access the stub method '%2' specified in ManagedToNativeComInteropStubAttribute. Please make sure they have compatible access modifiers and security accessibility."
#endif // FEATURE_COMINTEROP
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
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
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
IDS_EE_INTEROP_CODE_SIZE_COMMENT "Code size"
#define IDS_E_PROF_TIMEOUT_WAITING_FOR_CONCURRENT_GC 0x251D
#define IDS_EE_CANNOTCAST_NOMARSHAL 0x2629
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
#define IDS_EE_NATIVE_COM_WEAKREF_BAD_TYPE 0x262e
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
#define IDS_HOST_ASSEMBLY_RESOLVER_ASSEMBLY_ALREADY_LOADED_IN_CONTEXT 0x2636
#define IDS_HOST_ASSEMBLY_RESOLVER_DYNAMICALLY_EMITTED_ASSEMBLIES_UNSUPPORTED 0x2637
uint32_t types[] =
{
HNDTYPE_WEAK_SHORT
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
, HNDTYPE_WEAK_NATIVE_COM
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
};
uint32_t flags = (((ScanContext*) lp1)->concurrent) ? HNDGCF_ASYNC : HNDGCF_NORMAL;
#include <interoplibimports.h>
#include <corerror.h>
+#ifdef _WIN32
#include <new> // placement new
+#endif // _WIN32
+
using OBJECTHANDLE = InteropLib::OBJECTHANDLE;
using AllocScenario = InteropLibImports::AllocScenario;
&& fpAddRef != nullptr
&& fpRelease != nullptr);
- *fpQueryInterface = ManagedObjectWrapper_IUnknownImpl.QueryInterface;
- *fpAddRef = ManagedObjectWrapper_IUnknownImpl.AddRef;
- *fpRelease = ManagedObjectWrapper_IUnknownImpl.Release;
+ *fpQueryInterface = (void*)ManagedObjectWrapper_IUnknownImpl.QueryInterface;
+ *fpAddRef = (void*)ManagedObjectWrapper_IUnknownImpl.AddRef;
+ *fpRelease = (void*)ManagedObjectWrapper_IUnknownImpl.Release;
}
// The logic here should match code:ClrDataAccess::DACTryGetComWrappersObjectFromCCW in daccess/request.cpp
if ((flags & CreateComInterfaceFlagsEx::TrackerSupport) == CreateComInterfaceFlagsEx::TrackerSupport)
{
ABI::ComInterfaceEntry& curr = runtimeDefinedLocal[runtimeDefinedCount++];
- curr.IID = __uuidof(IReferenceTrackerTarget);
+ curr.IID = IID_IReferenceTrackerTarget;
curr.Vtable = &ManagedObjectWrapper_IReferenceTrackerTargetImpl;
}
-
- _ASSERTE(runtimeDefinedCount <= ARRAYSIZE(runtimeDefinedLocal));
+
+ _ASSERTE(runtimeDefinedCount <= (int) ARRAYSIZE(runtimeDefinedLocal));
// Compute size for ManagedObjectWrapper instance.
const size_t totalRuntimeDefinedSize = runtimeDefinedCount * sizeof(ABI::ComInterfaceEntry);
{
prev = wrapper->_refCount;
refCount = prev | DestroySentinel;
- } while (::InterlockedCompareExchange64(&wrapper->_refCount, refCount, prev) != prev);
+ } while (InterlockedCompareExchange64(&wrapper->_refCount, refCount, prev) != prev);
// The destroy sentinel represents the bit that indicates the wrapper
// should be destroyed. Since the reference count field (64-bit) holds
bool ManagedObjectWrapper::TrySetObjectHandle(_In_ OBJECTHANDLE objectHandle, _In_ OBJECTHANDLE current)
{
- return (::InterlockedCompareExchangePointer(&Target, objectHandle, current) == current);
+ return (InterlockedCompareExchangePointer(&Target, objectHandle, current) == current);
}
bool ManagedObjectWrapper::IsSet(_In_ CreateComInterfaceFlagsEx flag) const
default:
_ASSERTE(false && "Unknown result value");
+ FALLTHROUGH;
case TryInvokeICustomQueryInterfaceResult::FailedToInvoke:
// Set the 'lacks' flag since our attempt to use ICustomQueryInterface
// indicated the object lacks an implementation.
ComHolder<IReferenceTracker> trackerObject;
if (flags & InteropLib::Com::CreateObjectFlags_TrackerObject)
{
- hr = external->QueryInterface(&trackerObject);
+ hr = external->QueryInterface(IID_IReferenceTracker, (void**)&trackerObject);
if (SUCCEEDED(hr))
RETURN_IF_FAILED(TrackerObjectManager::OnIReferenceTrackerFound(trackerObject));
}
#include <interoplibabi.h>
#include "referencetrackertypes.hpp"
+#ifndef DEFINE_ENUM_FLAG_OPERATORS
+#define DEFINE_ENUM_FLAG_OPERATORS(ENUMTYPE) \
+extern "C++" { \
+ inline ENUMTYPE operator | (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a)|((int)b)); } \
+ inline ENUMTYPE operator |= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) |= ((int)b)); } \
+ inline ENUMTYPE operator & (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a)&((int)b)); } \
+ inline ENUMTYPE operator &= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) &= ((int)b)); } \
+ inline ENUMTYPE operator ~ (ENUMTYPE a) { return (ENUMTYPE)(~((int)a)); } \
+ inline ENUMTYPE operator ^ (ENUMTYPE a, ENUMTYPE b) { return ENUMTYPE(((int)a)^((int)b)); } \
+ inline ENUMTYPE operator ^= (ENUMTYPE &a, ENUMTYPE b) { return (ENUMTYPE &)(((int &)a) ^= ((int)b)); } \
+}
+#endif
+
enum class CreateComInterfaceFlagsEx : int32_t
{
None = InteropLib::Com::CreateComInterfaceFlags_None,
struct ComInterfaceEntry;
}
+static constexpr size_t ManagedObjectWrapperRefCountOffset();
+
// Class for wrapping a managed object and projecting it in a non-managed environment
class ManagedObjectWrapper
{
static NativeObjectWrapperContext* MapFromRuntimeContext(_In_ void* cxt);
// Create a NativeObjectWrapperContext instance
- static HRESULT NativeObjectWrapperContext::Create(
+ static HRESULT Create(
_In_ IUnknown* external,
_In_opt_ IUnknown* nativeObjectAsInner,
_In_ InteropLib::Com::CreateObjectFlags flags,
// interface QI. Once we have the IReferenceTracker
// instance we can be sure the QI for IUnknown will really
// be the true identity.
- HRESULT hr = external->QueryInterface(&trackerObject);
+ HRESULT hr = external->QueryInterface(IID_IReferenceTracker, (void**)&trackerObject);
if (SUCCEEDED(hr))
checkForIdentity = trackerObject.p;
}
HRESULT hr;
IUnknown* identityLocal;
- RETURN_IF_FAILED(checkForIdentity->QueryInterface(&identityLocal));
+ RETURN_IF_FAILED(checkForIdentity->QueryInterface(IID_IUnknown, (void **)&identityLocal));
// Set the inner if scenario dictates an update.
if (*innerMaybe == nullptr // User didn't supply inner - .NET 5 API scenario sanity check.
#ifdef _WIN32
#include <Windows.h>
+#endif // _WIN32
+
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
+#endif // !ARRAYSIZE
+
+#if defined(_WIN32) || defined(HOST_UNIX)
#include <objidl.h> // COM interfaces
// Common macro for working in COM
#define RETURN_IF_FAILED(exp) { hr = exp; if (FAILED(hr)) { _ASSERTE(false && #exp); return hr; } }
#define RETURN_VOID_IF_FAILED(exp) { hr = exp; if (FAILED(hr)) { _ASSERTE(false && #exp); return; } }
-
-#endif // _WIN32
+#endif // defined(_WIN32) || defined(HOST_UNIX)
#define ABI_ASSERT(abi_definition) static_assert((abi_definition), "ABI is being invalidated.")
// Documentation found at https://docs.microsoft.com/windows/win32/api/windows.ui.xaml.hosting.referencetracker/
+//64bd43f8-bfee-4ec4-b7eb-2935158dae21
+const GUID IID_IReferenceTrackerTarget = { 0x64bd43f8, 0xbfee, 0x4ec4, { 0xb7, 0xeb, 0x29, 0x35, 0x15, 0x8d, 0xae, 0x21} };
+
class DECLSPEC_UUID("64bd43f8-bfee-4ec4-b7eb-2935158dae21") IReferenceTrackerTarget : public IUnknown
{
public:
STDMETHOD(FoundTrackerTarget)(_In_ IReferenceTrackerTarget* target) = 0;
};
+//11d3b13a-180e-4789-a8be-7712882893e6
+const GUID IID_IReferenceTracker = { 0x11d3b13a, 0x180e, 0x4789, { 0xa8, 0xbe, 0x77, 0x12, 0x88, 0x28, 0x93, 0xe6} };
+
class DECLSPEC_UUID("11d3b13a-180e-4789-a8be-7712882893e6") IReferenceTracker : public IUnknown
{
public:
namespace
{
- const IID IID_IReferenceTrackerHost = __uuidof(IReferenceTrackerHost);
- const IID IID_IReferenceTrackerTarget = __uuidof(IReferenceTrackerTarget);
- const IID IID_IReferenceTracker = __uuidof(IReferenceTracker);
- const IID IID_IReferenceTrackerManager = __uuidof(IReferenceTrackerManager);
- const IID IID_IFindReferenceTargetsCallback = __uuidof(IFindReferenceTargetsCallback);
+
+ //29a71c6a-3c42-4416-a39d-e2825a07a773
+ const GUID IID_IReferenceTrackerHost = { 0x29a71c6a, 0x3c42, 0x4416, { 0xa3, 0x9d, 0xe2, 0x82, 0x5a, 0x7, 0xa7, 0x73} };
+
+ //3cf184b4-7ccb-4dda-8455-7e6ce99a3298
+ const GUID IID_IReferenceTrackerManager = { 0x3cf184b4, 0x7ccb, 0x4dda, { 0x84, 0x55, 0x7e, 0x6c, 0xe9, 0x9a, 0x32, 0x98} };
+
+ //04b3486c-4687-4229-8d14-505ab584dd88
+ const GUID IID_IFindReferenceTargetsCallback = { 0x04b3486c, 0x4687, 0x4229, { 0x8d, 0x14, 0x50, 0x5a, 0xb5, 0x84, 0xdd, 0x88} };
// In order to minimize the impact of a constructor running on module load,
// the HostServices class should have no instance fields.
// QI for IUnknown to get the identity unknown
ComHolder<IUnknown> identity;
- RETURN_IF_FAILED(obj->QueryInterface(&identity));
+ RETURN_IF_FAILED(obj->QueryInterface(IID_IUnknown, (void**)&identity));
// Get or create an existing implementation for this external.
ComHolder<IUnknown> target;
RETURN_IF_FAILED(g_HostServicesInstance.QueryInterface(IID_IReferenceTrackerHost, (void**)&hostServices));
// Attempt to set the tracker instance.
- if (::InterlockedCompareExchangePointer((void**)&s_TrackerManager, trackerManager.p, nullptr) == nullptr)
+ if (InterlockedCompareExchangePointer((void**)&s_TrackerManager, trackerManager.p, nullptr) == nullptr)
{
(void)trackerManager.Detach(); // Ownership has been transfered
RETURN_IF_FAILED(s_TrackerManager->SetReferenceTrackerHost(hostServices));
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+//
+
+//
+// ===========================================================================
+// File: weakreference.h
+//
+// ===========================================================================
+// simplified weakreference.h for PAL
+
+#include "rpc.h"
+#include "rpcndr.h"
+
+#include "unknwn.h"
+
+#ifndef __IInspectable_INTERFACE_DEFINED__
+#define __IInspectable_INTERFACE_DEFINED__
+
+typedef struct HSTRING__{
+ int unused;
+} HSTRING__;
+
+typedef HSTRING__* HSTRING;
+
+typedef /* [v1_enum] */
+enum TrustLevel
+ {
+ BaseTrust = 0,
+ PartialTrust = ( BaseTrust + 1 ) ,
+ FullTrust = ( PartialTrust + 1 )
+ } TrustLevel;
+
+// AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90
+const IID IID_IInspectable = { 0xaf86e2e0, 0xb12d, 0x4c6a, { 0x9c, 0x5a, 0xd7, 0xaa, 0x65, 0x10, 0x1e, 0x90} };
+
+MIDL_INTERFACE("AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90")
+IInspectable : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE GetIids(
+ /* [out] */ ULONG * iidCount,
+ /* [size_is][size_is][out] */ IID * *iids) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetRuntimeClassName(
+ /* [out] */ HSTRING * className) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(
+ /* [out] */ TrustLevel * trustLevel) = 0;
+};
+#endif // __IInspectable_INTERFACE_DEFINED__
+
+#ifndef __IWeakReference_INTERFACE_DEFINED__
+#define __IWeakReference_INTERFACE_DEFINED__
+
+// 00000037-0000-0000-C000-000000000046
+const IID IID_IWeakReference = { 0x00000037, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+
+MIDL_INTERFACE("00000037-0000-0000-C000-000000000046")
+IWeakReference : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE Resolve(
+ /* [in] */ REFIID riid,
+ /* [iid_is][out] */ IInspectable **objectReference) = 0;
+
+};
+
+#endif // __IWeakReference_INTERFACE_DEFINED__
+
+#ifndef __IWeakReferenceSource_INTERFACE_DEFINED__
+#define __IWeakReferenceSource_INTERFACE_DEFINED__
+
+// 00000038-0000-0000-C000-000000000046
+const IID IID_IWeakReferenceSource = { 0x00000038, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+
+MIDL_INTERFACE("00000038-0000-0000-C000-000000000046")
+IWeakReferenceSource : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE GetWeakReference(
+ /* [retval][out] */ IWeakReference * *weakReference) = 0;
+};
+
+#endif // __IWeakReferenceSource_INTERFACE_DEFINED__
return h;
}
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
OBJECTHANDLE CreateRefcountedHandle(OBJECTREF object)
{
WRAPPER_NO_CONTRACT;
WRAPPER_NO_CONTRACT;
return ::CreateNativeComWeakHandle(m_handleStore, object, pComWeakHandleInfo);
}
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
OBJECTHANDLE CreateVariableHandle(OBJECTREF object, UINT type)
{
bool isReferenced = false;
if (ObjCMarshalNative::IsTrackedReference((OBJECTREF)pObject, &isReferenced))
return isReferenced;
-#endif
-#if (defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)) && defined(FEATURE_OBJCMARSHAL)
-#error COM and Objective-C are not supported at the same time.
#endif
return false;
#include "gcinterface.h"
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
#include <weakreference.h>
#endif
// Special handle creation convenience functions
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
struct NativeComWeakHandleInfo
{
DiagHandleCreated(hnd, object);
return hnd;
}
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
// Creates a variable-strength handle
inline OBJECTHANDLE CreateVariableHandle(IGCHandleStore* store, OBJECTREF object, uint32_t type)
GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfUnknownType(handle);
}
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
inline void DestroyNativeComWeakHandle(OBJECTHANDLE handle)
{
CONTRACTL
DiagHandleDestroyed(handle);
GCHandleUtilities::GetGCHandleManager()->DestroyHandleOfType(handle, HNDTYPE_WEAK_NATIVE_COM);
}
-#endif
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
// Handle holders/wrappers
// Runtime headers
#include "common.h"
#include "rcwrefcache.h"
+#ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
#include "olecontexthelpers.h"
+#endif
#include "finalizerthread.h"
// Interop library header
using CreateObjectFlags = InteropLib::Com::CreateObjectFlags;
using CreateComInterfaceFlags = InteropLib::Com::CreateComInterfaceFlags;
+
namespace
{
+
+ void* GetCurrentCtxCookieWrapper()
+ {
+ STATIC_CONTRACT_WRAPPER;
+
+ #ifdef FEATURE_COMINTEROP_APARTMENT_SUPPORT
+ return GetCurrentCtxCookie();
+ #else
+ return NULL;
+ #endif // FEATURE_COMINTEROP_APARTMENT_SUPPORT
+
+ }
+
// This class is used to track the external object within the runtime.
struct ExternalObjectContext : public InteropLibInterface::ExternalObjectContextBase
{
ExternalObjectContext::Construct(
resultHolder.GetContext(),
identity,
- GetCurrentCtxCookie(),
+ GetCurrentCtxCookieWrapper(),
gc.objRefMaybe->GetSyncBlockIndex(),
wrapperId,
eocFlags);
ExtObjCxtCache* cache = ExtObjCxtCache::GetInstanceNoThrow();
gc.objsEnumRef = cache->CreateManagedEnumerable(
ExternalObjectContext::Flags_ReferenceTracker,
- GetCurrentCtxCookie());
+ GetCurrentCtxCookieWrapper());
CallReleaseObjects(&gc.implRef, &gc.objsEnumRef);
}
#include <optdefault.h>
-#ifdef FEATURE_COMINTEROP
-
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
#ifndef CROSSGEN_COMPILE
//--------------------------------------------------------------------------------
}
CONTRACTL_END;
+#ifdef FEATURE_COMINTEROP
// No need to notify the thread that the RCW is in use here.
// This is a privileged function called during GC or shutdown.
RCW* pRCW = pInteropInfo->GetRawRCW();
if (pRCW)
pRCW->MinorCleanup();
+#endif // FEATURE_COMINTEROP
#ifdef FEATURE_COMWRAPPERS
void* eoc;
}
#endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION
+#ifdef FEATURE_COMINTEROP
// No need to notify the thread that the RCW is in use here.
// This is only called during finalization of a __ComObject so no one
// else could have a reference to this object.
pInteropInfo->SetCCW(NULL);
pCCW->Cleanup();
}
+#endif // FEATURE_COMINTEROP
#ifdef FEATURE_COMWRAPPERS
pInteropInfo->ClearManagedObjectComWrappers(&ComWrappersNative::DestroyManagedObjectComWrapper);
#endif // FEATURE_COMWRAPPERS
}
+#endif // !CROSSGEN_COMPILE
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
+
+#ifdef FEATURE_COMINTEROP
+#ifndef CROSSGEN_COMPILE
+
//--------------------------------------------------------------------------------
// Helper to release all of the RCWs in the specified context across all caches.
// If pCtxCookie is NULL, release all RCWs
// Called from EEStartup, to initialize com Interop specific data structures.
void InitializeComInterop();
+#endif // FEATURE_COMINTEROP
+
//--------------------------------------------------------------------------------
// Clean up Helpers
//--------------------------------------------------------------------------------
+
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
+
// called by syncblock, on the finalizer thread to do major cleanup
void CleanupSyncBlockComData(InteropSyncBlockInfo* pInteropInfo);
// called by syncblock, during GC, do only minimal work
void MinorCleanupSyncBlockComData(InteropSyncBlockInfo* pInteropInfo);
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS)
+
+#ifdef FEATURE_COMINTEROP
+
// A wrapper that catches all exceptions - used in the OnThreadTerminate case.
void ReleaseRCWsInCachesNoThrow(LPVOID pCtxCookie);
continue;
}
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
if (psb->m_pInteropInfo)
{
// called during GC
// so do only minorcleanup
MinorCleanupSyncBlockComData(psb->m_pInteropInfo);
}
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
// This method will be called only by the GC thread
//<TODO>@todo add an assert for the above statement</TODO>
// clean up comdata
if (psb->m_pInteropInfo)
{
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
CleanupSyncBlockComData(psb->m_pInteropInfo);
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
#ifndef TARGET_UNIX
if (g_fEEShutDown)
WeakHandleSpinLockHolder& operator=(const WeakHandleSpinLockHolder& other);
};
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
// Get the native COM information for the object underlying an RCW if applicable. If the incoming object cannot
// use a native COM weak reference, nullptr is returned. Otherwise, a new NativeComWeakHandleInfo containing an
// 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).
+#ifdef FEATURE_COMINTEROP
if (pMT->IsComObjectType()
&& (pMT == g_pBaseCOMObject || !pMT->IsExtensibleRCW()))
{
pWeakReferenceSource = reinterpret_cast<IWeakReferenceSource*>(GetComIPFromObjectRef(pObject, IID_IWeakReferenceSource, false /* throwIfNoComIP */));
}
-#ifdef FEATURE_COMWRAPPERS
else
+#endif
{
+#ifdef FEATURE_COMWRAPPERS
pWeakReferenceSource = reinterpret_cast<IWeakReferenceSource*>(ComWrappersNative::GetIdentityForObject(pObject, IID_IWeakReferenceSource, &wrapperId));
+#endif
}
-#endif
+
if (pWeakReferenceSource == nullptr)
{
(void)GlobalComWrappersForMarshalling::TryGetOrCreateObjectForComInstance(pTargetIdentity, ObjFromComIP::NONE, &gc.rcw);
}
}
+#ifdef FEATURE_COMINTEROP
else
{
// If the original RCW was not created through ComWrappers, fall back to the built-in system.
GetObjectRefFromComIP(&gc.rcw, pTargetIdentity);
}
+#endif // FEATURE_COMINTEROP
}
// 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
return OBJECTREFToObject(gc.target);
}
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
//************************************************************************
_ASSERTE(gc.pThis->GetMethodTable()->CanCastToClass(pWeakReferenceMT));
// Create the handle.
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
NativeComWeakHandleInfo *comWeakHandleInfo = nullptr;
if (gc.pTarget != NULL)
{
infoHolder.SuppressRelease();
}
else
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
{
gc.pThis->m_Handle = GetAppDomain()->CreateTypedHandle(gc.pTarget,
trackResurrection ? HNDTYPE_WEAK_LONG : HNDTYPE_WEAK_SHORT);
_ASSERTE(gc.pThis->GetMethodTable()->GetCanonicalMethodTable() == pWeakReferenceOfTCanonMT);
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
NativeComWeakHandleInfo *comWeakHandleInfo = nullptr;
if (gc.pTarget != NULL)
{
infoHolder.SuppressRelease();
}
else
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
{
gc.pThis->m_Handle = GetAppDomain()->CreateTypedHandle(gc.pTarget,
trackResurrection ? HNDTYPE_WEAK_LONG : HNDTYPE_WEAK_SHORT);
// Cache the old handle value
HandleType handleType = GCHandleUtilities::GetGCHandleManager()->HandleFetchType(handleToDestroy);
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
_ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT || handleType == HNDTYPE_WEAK_NATIVE_COM);
isWeakNativeComHandle = handleType == HNDTYPE_WEAK_NATIVE_COM;
-#else // !FEATURE_COMINTEROP
+#else // !FEATURE_COMINTEROP && !FEATURE_COMWRAPPERS
_ASSERTE(handleType == HNDTYPE_WEAK_LONG || handleType == HNDTYPE_WEAK_SHORT);
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
handle = (handleType == HNDTYPE_WEAK_LONG) ?
SPECIAL_HANDLE_FINALIZED_LONG : SPECIAL_HANDLE_FINALIZED_SHORT;
if (handleToDestroy != NULL)
{
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
if (isWeakNativeComHandle)
{
DestroyNativeComWeakHandle(handleToDestroy);
}
else
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
{
DestroyTypedHandle(handleToDestroy);
}
OBJECTREF pTarget = GetWeakReferenceTarget(pThis);
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
// 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_INNER_RETURN(Object*, LoadComWeakReferenceTarget(pThis, g_pObjectClass, GetEEFuncEntryPointMacro(WeakReferenceNative::GetTarget)));
-#else // !FEATURE_COMINTEROP
+#else // !FEATURE_COMINTEROP && !FEATURE_COMWRAPPERS
FC_GC_POLL_AND_RETURN_OBJREF(pTarget);
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
}
FCIMPLEND
OBJECTREF pTarget = GetWeakReferenceTarget(pThis);
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
// 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_INNER_RETURN(Object*, LoadComWeakReferenceTarget(pThis, pThis->GetMethodTable()->GetInstantiation()[0], GetEEFuncEntryPointMacro(WeakReferenceOfTNative::GetTarget)));
-#else // !FEATURE_COMINTEROP
+#else // !FEATURE_COMINTEROP && !FEATURE_COMWRAPPERS
FC_GC_POLL_AND_RETURN_OBJREF(pTarget);
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
}
FCIMPLEND
FC_INNER_PROLOG_NO_ME_SETUP();
HELPER_METHOD_FRAME_BEGIN_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, target, weakReference);
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
NewHolder<NativeComWeakHandleInfo> comWeakHandleInfo(GetComWeakReferenceInfo(&target));
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
WeakHandleSpinLockHolder handle(AcquireWeakHandleSpinLock(weakReference), &weakReference);
GCX_NOTRIGGER();
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
//
// We have four combinations to handle here
//
DestroyTypedHandle(previousHandle);
}
else
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
{
StoreObjectInHandle(handle.Handle, target);
}
-#ifdef FEATURE_COMINTEROP
+#if defined(FEATURE_COMINTEROP) || defined(FEATURE_COMWRAPPERS)
comWeakHandleInfo.SuppressRelease();
-#endif // FEATURE_COMINTEROP
+#endif // FEATURE_COMINTEROP || FEATURE_COMWRAPPERS
HELPER_METHOD_FRAME_END();
FC_INNER_EPILOG();
endif()
endif(CLR_CMAKE_TARGET_WIN32)
+if(CLR_CMAKE_TARGET_UNIX)
+ add_subdirectory(COM/ComWrappers/MockReferenceTrackerRuntime)
+ add_subdirectory(COM/ComWrappers/WeakReference)
+endif(CLR_CMAKE_TARGET_UNIX)
+
if(CLR_CMAKE_TARGET_OSX OR CLR_CMAKE_TARGET_IOS OR CLR_CMAKE_TARGET_TVOS)
add_subdirectory(ObjectiveC/AutoReleaseTest)
add_subdirectory(ObjectiveC/ObjectiveCMarshalAPI)
<PropertyGroup>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DisableProjectBuild Condition="'$(RuntimeFlavor)' == 'mono'">true</DisableProjectBuild>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<PropertyGroup>
<OutputType>Exe</OutputType>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DisableProjectBuild Condition="'$(RuntimeFlavor)' == 'mono'">true</DisableProjectBuild>
</PropertyGroup>
<ItemGroup>
<Compile Include="Program.cs" />
--- /dev/null
+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetPathOfFileAbove(Directory.Build.props, $(MSBuildThisFileDirectory)..))" />
+
+ <PropertyGroup>
+ <!-- Unlike COM, ComWrappers are cross-platform -->
+ <CLRTestTargetUnsupported></CLRTestTargetUnsupported>
+ </PropertyGroup>
+
+</Project>
// The first test registers a global ComWrappers instance for tracker support.
// Subsequents tests assume the global instance has already been registered.
ValidateRegisterForTrackerSupport();
-
+#if Windows
ValidateNotRegisteredForMarshalling();
+#endif
IntPtr trackerObjRaw = MockReferenceTrackerRuntime.CreateTrackerObject();
var trackerObj = GlobalComWrappers.Instance.GetOrCreateObjectForComInstance(trackerObjRaw, CreateObjectFlags.TrackerObject);
Marshal.Release(trackerObjRaw);
ValidateNotifyEndOfReferenceTrackingOnThread();
-
+#if Windows
// Register a global ComWrappers instance for marshalling.
ValidateRegisterForMarshalling();
ValidateComActivation(validateUseRegistered: true);
ValidateComActivation(validateUseRegistered: false);
-
+#endif
ValidateNotifyEndOfReferenceTrackingOnThread();
}
catch (Exception e)
<UseManagedCOMServer>true</UseManagedCOMServer>
<IsManagedCOMClient>true</IsManagedCOMClient>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <!-- There is only a Windows version of this test -->
+ <CLRTestTargetUnsupported Condition="'$(TargetsWindows)' != 'true'">true</CLRTestTargetUnsupported>
</PropertyGroup>
<ItemGroup>
<Compile Include="GlobalInstance.cs" />
<UseManagedCOMServer>true</UseManagedCOMServer>
<IsManagedCOMClient>true</IsManagedCOMClient>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <!-- There is only a Windows version of this test -->
+ <CLRTestTargetUnsupported Condition="'$(TargetsWindows)' != 'true'">true</CLRTestTargetUnsupported>
</PropertyGroup>
<ItemGroup>
<Compile Include="GlobalInstance.cs" />
+++ /dev/null
-<Project Sdk="Microsoft.NET.Sdk">
- <PropertyGroup>
- <OutputType>Exe</OutputType>
- <ApplicationManifest>App.manifest</ApplicationManifest>
- <UseManagedCOMServer>true</UseManagedCOMServer>
- <IsManagedCOMClient>true</IsManagedCOMClient>
- <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
- </PropertyGroup>
- <ItemGroup>
- <Compile Include="GlobalInstance.cs" />
- <Compile Include="GlobalInstance.TrackerSupport.cs" />
- <Compile Include="../Common.cs" />
- <Compile Include="../../ServerContracts/Server.Contracts.cs" />
- <Compile Include="../../ServerContracts/ServerGuids.cs" />
- </ItemGroup>
- <ItemGroup>
- <ProjectReference Include="../MockReferenceTrackerRuntime/CMakeLists.txt" />
- <ProjectReference Include="../../NativeServer/CMakeLists.txt" />
- <ProjectReference Include="../../NETServer/NETServer.csproj">
- <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
- <OutputItemType>Content</OutputItemType>
- <CopyToOutputDirectory>Always</CopyToOutputDirectory>
- </ProjectReference>
- </ItemGroup>
- <ItemGroup>
- <None Include="CoreShim.X.manifest">
- <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
- </None>
- </ItemGroup>
-</Project>
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <ApplicationManifest>App.manifest</ApplicationManifest>
+ <UseManagedCOMServer>true</UseManagedCOMServer>
+ <IsManagedCOMClient>true</IsManagedCOMClient>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <!-- There is a Windows and a non-Windows version of this test to allow it to be compiled for all targets -->
+ <CLRTestTargetUnsupported Condition="'$(TargetsWindows)' == 'true'">true</CLRTestTargetUnsupported>
+ <DisableProjectBuild Condition="'$(RuntimeFlavor)' == 'mono'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="GlobalInstance.cs" />
+ <Compile Include="GlobalInstance.TrackerSupport.cs" />
+ <Compile Include="../Common.cs" />
+ <Compile Include="../../ServerContracts/Server.Contracts.cs" />
+ <Compile Include="../../ServerContracts/ServerGuids.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="../MockReferenceTrackerRuntime/CMakeLists.txt" />
+ <ProjectReference Include="../../NETServer/NETServer.csproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="CoreShim.X.manifest">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+</Project>
--- /dev/null
+<Project Sdk="Microsoft.NET.Sdk">
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <ApplicationManifest>App.manifest</ApplicationManifest>
+ <UseManagedCOMServer>true</UseManagedCOMServer>
+ <IsManagedCOMClient>true</IsManagedCOMClient>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+ <DefineConstants>$(DefineConstants);Windows</DefineConstants>
+ <!-- There is a Windows and a non-Windows version of this test to allow it to be compiled for all targets -->
+ <CLRTestTargetUnsupported Condition="'$(TargetsWindows)' != 'true'">true</CLRTestTargetUnsupported>
+ </PropertyGroup>
+ <ItemGroup>
+ <Compile Include="GlobalInstance.cs" />
+ <Compile Include="GlobalInstance.TrackerSupport.cs" />
+ <Compile Include="../Common.cs" />
+ <Compile Include="../../ServerContracts/Server.Contracts.cs" />
+ <Compile Include="../../ServerContracts/ServerGuids.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="../MockReferenceTrackerRuntime/CMakeLists.txt" />
+ <ProjectReference Include="../../NativeServer/CMakeLists.txt" />
+ <ProjectReference Include="../../NETServer/NETServer.csproj">
+ <ReferenceOutputAssembly>false</ReferenceOutputAssembly>
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </ProjectReference>
+ </ItemGroup>
+ <ItemGroup>
+ <None Include="CoreShim.X.manifest">
+ <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+ </None>
+ </ItemGroup>
+</Project>
#include <xplatform.h>
#include <ComHelpers.h>
+#ifdef _WIN32
+#include <inspectable.h>
+#else
+#include <atomic>
+#include <exception>
+#endif //_WIN32
#include <unordered_map>
#include <list>
#include <mutex>
-#include <inspectable.h>
namespace API
{
// Documentation found at https://docs.microsoft.com/windows/win32/api/windows.ui.xaml.hosting.referencetracker/
+ //64bd43f8-bfee-4ec4-b7eb-2935158dae21
+ const GUID IID_IReferenceTrackerTarget = { 0x64bd43f8, 0xbfee, 0x4ec4, { 0xb7, 0xeb, 0x29, 0x35, 0x15, 0x8d, 0xae, 0x21} };
class DECLSPEC_UUID("64bd43f8-bfee-4ec4-b7eb-2935158dae21") IReferenceTrackerTarget : public IUnknown
{
public:
STDMETHOD(Unpeg)() = 0;
};
+ //29a71c6a-3c42-4416-a39d-e2825a07a773
+ const GUID IID_IReferenceTrackerHost = { 0x29a71c6a, 0x3c42, 0x4416, { 0xa3, 0x9d, 0xe2, 0x82, 0x5a, 0x07, 0xa7, 0x73} };
class DECLSPEC_UUID("29a71c6a-3c42-4416-a39d-e2825a07a773") IReferenceTrackerHost : public IUnknown
{
public:
STDMETHOD(RemoveMemoryPressure)(_In_ UINT64 bytesAllocated) = 0;
};
+ //3cf184b4-7ccb-4dda-8455-7e6ce99a3298
+ const GUID IID_IReferenceTrackerManager = { 0x3cf184b4, 0x7ccb, 0x4dda, { 0x84, 0x55, 0x7e, 0x6c, 0xe9, 0x9a, 0x32, 0x98} };
class DECLSPEC_UUID("3cf184b4-7ccb-4dda-8455-7e6ce99a3298") IReferenceTrackerManager : public IUnknown
{
public:
STDMETHOD(FoundTrackerTarget)(_In_ IReferenceTrackerTarget* target) = 0;
};
+ //11d3b13a-180e-4789-a8be-7712882893e6
+ const GUID IID_IReferenceTracker = { 0x11d3b13a, 0x180e, 0x4789, { 0xa8, 0xbe, 0x77, 0x12, 0x88, 0x28, 0x93, 0xe6} };
class DECLSPEC_UUID("11d3b13a-180e-4789-a8be-7712882893e6") IReferenceTracker : public IUnknown
{
public:
namespace
{
// Testing types
+ //447BB9ED-DA48-4ABC-8963-5BB5C3E0AA09
+ const GUID IID_ITest = { 0x447BB9ED, 0xda48, 0x4abc, { 0x89, 0x63, 0x5b, 0xb5, 0xc3, 0xe0, 0xaa, 0x9} };
struct DECLSPEC_UUID("447BB9ED-DA48-4ABC-8963-5BB5C3E0AA09") ITest : public IUnknown
{
STDMETHOD(SetValue)(int i) = 0;
};
+ //42951130-245C-485E-B60B-4ED4254256F8
+ const GUID IID_ITrackerObject = { 0x42951130, 0x245c, 0x485e, { 0xb6, 0x0b, 0x4e, 0xd4, 0x25, 0x42, 0x56, 0xf8} };
struct DECLSPEC_UUID("42951130-245C-485E-B60B-4ED4254256F8") ITrackerObject : public IUnknown
{
STDMETHOD(AddObjectRef)(_In_ IUnknown* c, _Out_ int* id) = 0;
while (curr != std::end(_impl._elements))
{
ComSmartPtr<API::IReferenceTrackerTarget> mowMaybe;
- if (S_OK == curr->second->QueryInterface(&mowMaybe))
+ if (S_OK == curr->second->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&mowMaybe))
{
if (shouldPeg)
{
if (_impl._outerRefTrackerTarget)
{
ComSmartPtr<API::IReferenceTrackerTarget> thisTgtMaybe;
- if (S_OK == _outer->QueryInterface(&thisTgtMaybe))
+ if (S_OK == _outer->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&thisTgtMaybe))
{
if (shouldPeg)
{
if (_impl._outerRefTrackerTarget)
{
ComSmartPtr<API::IReferenceTrackerTarget> thisTgtMaybe;
- if (S_OK == _outer->QueryInterface(&thisTgtMaybe))
+ if (S_OK == _outer->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&thisTgtMaybe))
RETURN_IF_FAILED(thisTgtMaybe->ReleaseFromReferenceTracker());
}
{
// Check if we are aggregating with a tracker target
ComSmartPtr<API::IReferenceTrackerTarget> tgt;
- if (SUCCEEDED(_implOuter->QueryInterface(&tgt)))
+ if (SUCCEEDED(_implOuter->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&tgt)))
{
_outerRefTrackerTarget = true;
(void)tgt->AddRefFromReferenceTracker();
if (FAILED(tgt->Peg()))
{
- throw std::exception{ "Peg failure" };
+ throw std::runtime_error{ "Peg failure" };
}
}
}
assert(c != nullptr && id != nullptr);
ComSmartPtr<API::IReferenceTrackerTarget> mowMaybe;
- if (S_OK == c->QueryInterface(&mowMaybe))
+ if (S_OK == c->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&mowMaybe))
{
(void)mowMaybe->AddRefFromReferenceTracker();
c = mowMaybe.p;
return S_FALSE;
ComSmartPtr<API::IReferenceTrackerTarget> mowMaybe;
- if (S_OK == iter->second->QueryInterface(&mowMaybe))
+ if (S_OK == iter->second->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&mowMaybe))
{
(void)mowMaybe->ReleaseFromReferenceTracker();
(void)mowMaybe->Unpeg();
else
{
// Send non-IUnknown queries to the implementation.
- if (riid == __uuidof(API::IReferenceTracker))
+ if (riid == API::IID_IReferenceTracker)
{
tgt = static_cast<API::IReferenceTracker*>(&_impl);
}
STDMETHOD(SetReferenceTrackerHost)(_In_ API::IReferenceTrackerHost* pHostServices)
{
assert(pHostServices != nullptr);
- return pHostServices->QueryInterface(&_runtimeServices);
+ return pHostServices->QueryInterface(API::IID_IReferenceTrackerHost, (void**)&_runtimeServices);
}
// Lifetime maintained by stack - we don't care about ref counts
if (ppvObject == nullptr)
return E_POINTER;
- if (IsEqualIID(riid, __uuidof(API::IReferenceTrackerManager)))
+ if (IsEqualIID(riid, API::IID_IReferenceTrackerManager))
{
*ppvObject = static_cast<API::IReferenceTrackerManager*>(this);
}
ComSmartPtr<API::IReferenceTrackerTarget> mowMaybe;
for (auto& e : _elements)
{
- if (S_OK == e.second->QueryInterface(&mowMaybe))
+ if (S_OK == e.second->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&mowMaybe))
{
(void)pCallback->FoundTrackerTarget(mowMaybe.p);
mowMaybe.Release();
HRESULT STDMETHODCALLTYPE TrackerObject::TrackerObjectImpl::GetReferenceTrackerManager(_Outptr_ API::IReferenceTrackerManager** ppTrackerManager)
{
assert(ppTrackerManager != nullptr);
- return TrackerRuntimeManager.QueryInterface(__uuidof(API::IReferenceTrackerManager), (void**)ppTrackerManager);
+ return TrackerRuntimeManager.QueryInterface(API::IID_IReferenceTrackerManager, (void**)ppTrackerManager);
}
HRESULT STDMETHODCALLTYPE TrackerObject::TrackerObjectImpl::AddRefFromTrackerSource()
assert(obj != nullptr);
API::IReferenceTrackerTarget* targetMaybe;
- if (S_OK == obj->QueryInterface(&targetMaybe))
+ if (S_OK == obj->QueryInterface(API::IID_IReferenceTrackerTarget, (void**)&targetMaybe))
{
(void)targetMaybe->AddRefFromReferenceTracker();
(void)targetMaybe->Release();
HRESULT hr;
ComSmartPtr<ITest> testObj;
- RETURN_IF_FAILED(obj->QueryInterface(&testObj));
+ RETURN_IF_FAILED(obj->QueryInterface(IID_ITest, (void**)&testObj));
RETURN_IF_FAILED(testObj->SetValue(i));
*out = testObj.Detach();
#include <xplatform.h>
#include <ComHelpers.h>
+#ifdef _WIN32
#include <inspectable.h>
#include <WeakReference.h>
+#endif //_WIN32
namespace
{
/* [in] */ REFIID riid,
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
{
+#ifdef _WIN32
return DoQueryInterface(riid, ppvObject, static_cast<IWeakReference*>(this));
+#else
+ if (ppvObject == nullptr)
+ return E_POINTER;
+
+ if (riid == __uuidof(IUnknown))
+ {
+ *ppvObject = static_cast<IUnknown*>(this);
+ }
+ else
+ {
+ if (riid == __uuidof(IWeakReference))
+ {
+ *ppvObject = static_cast<IWeakReference*>(this);
+ }
+ else
+ {
+ *ppvObject = nullptr;
+ return E_NOINTERFACE;
+ }
+ }
+
+ DoAddRef();
+ return S_OK;
+#endif
}
DEFINE_REF_COUNTING()
/* [in] */ REFIID riid,
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR* __RPC_FAR* ppvObject)
{
+#ifdef _WIN32
HRESULT hr = DoQueryInterface(riid, ppvObject, static_cast<IWeakReferenceSource*>(this), static_cast<IInspectable*>(this), static_cast<IWeakReferenceSource*>(this));
+#else
+ HRESULT hr;
+
+ if (ppvObject == nullptr)
+ hr = E_POINTER;
+
+ if (riid == __uuidof(IUnknown) || riid == __uuidof(IWeakReferenceSource))
+ {
+ *ppvObject = static_cast<IWeakReferenceSource*>(this);
+ hr = S_OK;
+ }
+ else if (riid == __uuidof(IInspectable))
+ {
+ *ppvObject = static_cast<IInspectable*>(this);
+ hr = S_OK;
+ }
+ else
+ {
+ *ppvObject = nullptr;
+ hr = E_NOINTERFACE;
+ }
+
+
+ if (hr == S_OK)
+ DoAddRef();
+#endif
if (SUCCEEDED(hr) && _weakReference)
{
_weakReference->AddStrongRef();
{
try
{
- ValidateNonComWrappers();
+ if (OperatingSystem.IsWindows())
+ {
+ ValidateNonComWrappers();
+
+ ComWrappers.RegisterForMarshalling(TestComWrappers.MarshallingInstance);
+ ValidateGlobalInstanceMarshalling();
+ }
ComWrappers.RegisterForTrackerSupport(TestComWrappers.TrackerSupportInstance);
ValidateGlobalInstanceTrackerSupport();
- ComWrappers.RegisterForMarshalling(TestComWrappers.MarshallingInstance);
- ValidateGlobalInstanceMarshalling();
-
ValidateLocalInstance();
}
catch (Exception e)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
- <!-- Test unsupported outside of windows -->
- <CLRTestTargetUnsupported Condition="'$(TargetsWindows)' != 'true'">true</CLRTestTargetUnsupported>
<!-- Registers global instances of ComWrappers -->
<UnloadabilityIncompatible>true</UnloadabilityIncompatible>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
// The .NET Foundation licenses this file to you under the MIT license.
#pragma once
-
+#ifdef _WIN32
#include <Windows.h>
#include <comdef.h>
#include <cassert>
#include <exception>
#include <type_traits>
+#endif
#include <atomic>
// Common macro for working in COM
#define RETURN_IF_FAILED(exp) { hr = exp; if (FAILED(hr)) { return hr; } }
+#ifdef _WIN32
namespace Internal
{
template<typename I>
/* [in] */ REFIID riid,
/* [iid_is][out] */ _COM_Outptr_ void __RPC_FAR *__RPC_FAR *ppvObject,
/* [in] */ I obj)
- {
+ {
if (riid == __uuidof(I))
{
*ppvObject = static_cast<I>(obj);
return __QueryInterfaceImpl(riid, ppvObject, remain...);
}
}
+ #endif
// Implementation of IUnknown operations
class UnknownImpl
{
-public:
- UnknownImpl() = default;
+public:
+ UnknownImpl() : _refCount{ 1 } {};
virtual ~UnknownImpl() = default;
UnknownImpl(const UnknownImpl&) = delete;
UnknownImpl& operator=(const UnknownImpl&) = delete;
- UnknownImpl(UnknownImpl&&) = default;
- UnknownImpl& operator=(UnknownImpl&&) = default;
+ UnknownImpl(UnknownImpl&&) = delete;
+ UnknownImpl& operator=(UnknownImpl&&) = delete;
template<typename I1, typename ...IR>
HRESULT DoQueryInterface(
}
else
{
+ //Internal::__QueryInterfaceImpl available only for _WIN32 due to __uuidof(T) availability
+#ifdef _WIN32
HRESULT hr = Internal::__QueryInterfaceImpl(riid, ppvObject, i1, remain...);
if (hr != S_OK)
return hr;
+#else
+ *ppvObject = nullptr;
+ return E_NOTIMPL;
+#endif
}
DoAddRef();
}
private:
- std::atomic<ULONG> _refCount = 1;
+ std::atomic<ULONG> _refCount;
};
// Macro to use for defining ref counting impls
STDMETHOD_(ULONG, AddRef)(void) { return UnknownImpl::DoAddRef(); } \
STDMETHOD_(ULONG, Release)(void) { return UnknownImpl::DoRelease(); }
+#ifdef _WIN32
// Templated class factory
template<typename T>
class ClassFactoryBasic : public UnknownImpl, public IClassFactory
DEFINE_REF_COUNTING();
};
+#endif
template<typename T>
struct ComSmartPtr
#ifndef WINDOWS
+#define __RPC_FAR
+#define DECLSPEC_UUID(x)
+#define DECLSPEC_NOVTABLE
+#define MIDL_INTERFACE(x) struct DECLSPEC_UUID(x) DECLSPEC_NOVTABLE
+//Check OBJC_TESTS presence to avoid interface definition on OSX (already defined)
+#ifndef OBJC_TESTS
+#define interface struct
+#endif
+#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
+#define STDMETHOD_(type,method) virtual type STDMETHODCALLTYPE method
+#undef _In_
+#define _In_
+#undef _Outptr_
+#define _Outptr_
+#undef _Out_
+#define _Out_
+#undef _In_opt_
+#define _In_opt_
+#undef _COM_Outptr_
+#define _COM_Outptr_
+#undef _Inout_
+#define _Inout_
+#define __RPC__out
+#define __RPC__in
+#define __RPC__deref_out
+#define __RPC__deref_out_opt
+#define __RPC__deref_out_ecount_full_opt(x)
+#define __RPC_unique_pointer
+
+
+#define E_POINTER _HRESULT_TYPEDEF_(0x80004003L)
+#define E_NOINTERFACE _HRESULT_TYPEDEF_(0x80004002L)
+#define S_FALSE _HRESULT_TYPEDEF_(0x00000001L)
+#define E_OUTOFMEMORY _HRESULT_TYPEDEF_(0x8007000EL)
+#define E_NOTIMPL _HRESULT_TYPEDEF_(0x80004001L)
+
+// Declaring a handle dummy struct for HSTRING the same way DECLARE_HANDLE does.
+typedef struct HSTRING__{
+ int unused;
+} HSTRING__;
+
+// Declare the HSTRING handle for C/C++
+typedef __RPC_unique_pointer HSTRING__* HSTRING;
+
+typedef unsigned __int64 UINT64, *PUINT64;
+typedef unsigned short USHORT;
+typedef USHORT *PUSHORT;
+typedef unsigned char UCHAR;
+typedef UCHAR *PUCHAR;
+
+#ifndef GUID_DEFINED
+typedef struct _GUID {
+ ULONG Data1; // NOTE: diff from Win32, for LP64
+ USHORT Data2;
+ USHORT Data3;
+ UCHAR Data4[ 8 ];
+} GUID;
+typedef const GUID *LPCGUID;
+#define GUID_DEFINED
+#endif // !GUID_DEFINED
+
+
+#ifdef __cplusplus
+#define REFGUID const GUID &
+#endif
+
+
+#ifdef __cplusplus
+extern "C++" {
+#if !defined _SYS_GUID_OPERATOR_EQ_ && !defined _NO_SYS_GUID_OPERATOR_EQ_
+#define _SYS_GUID_OPERATOR_EQ_
+inline int IsEqualGUID(REFGUID rguid1, REFGUID rguid2)
+ { return !memcmp(&rguid1, &rguid2, sizeof(GUID)); }
+inline int operator==(REFGUID guidOne, REFGUID guidOther)
+ { return IsEqualGUID(guidOne,guidOther); }
+inline int operator!=(REFGUID guidOne, REFGUID guidOther)
+ { return !IsEqualGUID(guidOne,guidOther); }
+#endif
+};
+#endif // __cplusplus
+
+
+typedef GUID IID;
+#ifdef __cplusplus
+#define REFIID const IID &
+#endif
+
+#define IID_NULL { 0x00000000, 0x0000, 0x0000, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}
+
+#define IsEqualIID(riid1, riid2) IsEqualGUID(riid1, riid2)
+
+#define __uuidof(type) IID_##type
+
+#ifndef assert
+#define assert(e) ((void)0)
+#endif // assert
+
#include <stddef.h>
#undef INT_MIN
#define FALSE 0
#endif
-class IUnknown
+#ifndef __IUnknown_INTERFACE_DEFINED__
+#define __IUnknown_INTERFACE_DEFINED__
+
+
+//00000000-0000-0000-C000-000000000046
+const IID IID_IUnknown = { 0x00000000, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+
+MIDL_INTERFACE("00000000-0000-0000-C000-000000000046")
+IUnknown
+{
+ virtual HRESULT STDMETHODCALLTYPE QueryInterface(
+ REFIID riid,
+ void **ppvObject) = 0;
+
+ virtual ULONG STDMETHODCALLTYPE AddRef( void) = 0;
+
+ virtual ULONG STDMETHODCALLTYPE Release( void) = 0;
+
+};
+
+#endif // __IUnknown_INTERFACE_DEFINED__
+
+struct IDispatch : public IUnknown
+{
+
+};
+
+typedef /* [v1_enum] */
+enum TrustLevel
+ {
+ BaseTrust = 0,
+ PartialTrust = ( BaseTrust + 1 ) ,
+ FullTrust = ( PartialTrust + 1 )
+ } TrustLevel;
+
+//AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90
+const IID IID_IInspectable = { 0xaf86e2e0, 0xb12d, 0x4c6a, { 0x9c, 0x5a, 0xd7, 0xaa, 0x65, 0x10, 0x1e, 0x90} };
+
+MIDL_INTERFACE("AF86E2E0-B12D-4c6a-9C5A-D7AA65101E90")
+IInspectable : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE GetIids(
+ /* [out] */ __RPC__out ULONG * iidCount,
+ /* [size_is][size_is][out] */ __RPC__deref_out_ecount_full_opt(*iidCount) IID * *iids) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetRuntimeClassName(
+ /* [out] */ __RPC__deref_out_opt HSTRING * className) = 0;
+
+ virtual HRESULT STDMETHODCALLTYPE GetTrustLevel(
+ /* [out] */ __RPC__out TrustLevel * trustLevel) = 0;
+};
+
+
+//00000037-0000-0000-C000-000000000046
+const IID IID_IWeakReference = { 0x00000037, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+
+MIDL_INTERFACE("00000037-0000-0000-C000-000000000046")
+IWeakReference : public IUnknown
+{
+public:
+ virtual HRESULT STDMETHODCALLTYPE Resolve(
+ /* [in] */ __RPC__in REFIID riid,
+ /* [iid_is][out] */ __RPC__deref_out IInspectable **objectReference) = 0;
+
+};
+
+//00000038-0000-0000-C000-000000000046
+const IID IID_IWeakReferenceSource = { 0x00000038, 0x0000, 0x0000, { 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46} };
+
+MIDL_INTERFACE("00000038-0000-0000-C000-000000000046")
+IWeakReferenceSource : public IUnknown
{
public:
- virtual int QueryInterface(void* riid,void** ppvObject) = 0;
- virtual unsigned long AddRef() = 0;
- virtual unsigned long Release() = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetWeakReference(
+ /* [retval][out] */ __RPC__deref_out_opt IWeakReference * *weakReference) = 0;
};
#define DECIMAL_NEG ((BYTE)0x80)
<ExcludeList Include="$(XunitTestBinBase)/Interop/COM/Reflection/Reflection/**">
<Issue>https://github.com/dotnet/runtime/issues/34371</Issue>
</ExcludeList>
+ <ExcludeList Include="$(XunitTestBinBase)/Interop/COM/ComWrappers/**">
+ <Issue>Not supported on Mono</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)/Interop/ICastable/Castable/**">
<Issue>needs triage</Issue>
</ExcludeList>