Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1503,6 +1503,7 @@ internal static void SetPendingExceptionObject(Exception? exception)

[SupportedOSPlatform("windows")]
[UnmanagedCallersOnly]
[RequiresUnsafe]
private static unsafe void GetIEnumeratorToEnumVariantMarshaler(object* pResult, Exception* pException)
{
try
Expand All @@ -1514,6 +1515,77 @@ private static unsafe void GetIEnumeratorToEnumVariantMarshaler(object* pResult,
*pException = ex;
}
}

private const int DispatchExPropertyCanRead = 1;
private const int DispatchExPropertyCanWrite = 2;

[SupportedOSPlatform("windows")]
[UnmanagedCallersOnly]
[RequiresUnsafe]
private static unsafe void GetDispatchExPropertyFlags(PropertyInfo* pMemberInfo, int* pResult, Exception* pException)
{
try
{
int result = 0;
PropertyInfo property = *pMemberInfo;
if (property.CanRead)
{
result |= DispatchExPropertyCanRead;
}

if (property.CanWrite)
{
result |= DispatchExPropertyCanWrite;
}

*pResult = result;
}
catch (Exception ex)
{
*pException = ex;
}
}

[SupportedOSPlatform("windows")]
[UnmanagedCallersOnly]
[RequiresUnsafe]
private static unsafe int CallICustomQueryInterface(ICustomQueryInterface* pObject, Guid* pIid, IntPtr* ppObject, Exception* pException)
{
try
{
return (int)(*pObject).GetInterface(ref *pIid, out *ppObject);
}
catch (Exception ex)
{
*pException = ex;
return 0;
}
}

[SupportedOSPlatform("windows")]
[UnmanagedCallersOnly]
[RequiresUnsafe]
private static unsafe void InvokeConnectionPointProviderMethod(
object* pProvider,
delegate*<object, object?, void> providerMethodEntryPoint,
object* pDelegate,
delegate*<object, object?, nint, void> delegateCtorMethodEntryPoint,
object* pSubscriber,
nint pEventMethodCodePtr,
Exception* pException)
{
try
{
// Construct the delegate before invoking the provider method.
delegateCtorMethodEntryPoint(*pDelegate, *pSubscriber, pEventMethodCodePtr);

providerMethodEntryPoint(*pProvider, *pDelegate);
}
catch (Exception ex)
{
*pException = ex;
}
}
#endif

internal static object CreateCustomMarshaler(IntPtr pMD, int paramToken, IntPtr hndManagedType)
Expand Down
22 changes: 2 additions & 20 deletions src/coreclr/vm/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -1468,16 +1468,6 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
GetOptionalFields()->m_pCoClassForIntf = th;
}

OBJECTHANDLE GetOHDelegate()
{
LIMITED_METHOD_CONTRACT;
return m_ohDelegate;
}
void SetOHDelegate (OBJECTHANDLE _ohDelegate)
{
LIMITED_METHOD_CONTRACT;
m_ohDelegate = _ohDelegate;
}
// Set the COM interface type.
CorIfaceAttr GetComInterfaceType()
{
Expand Down Expand Up @@ -1688,16 +1678,8 @@ class EEClass // DO NOT CREATE A NEW EEClass USING NEW!
PTR_MethodDescChunk m_pChunks;

#ifdef FEATURE_COMINTEROP
union
{
// For CLR wrapper objects that extend an unmanaged class, this field
// may contain a delegate to be called to allocate the aggregated
// unmanaged class (instead of using CoCreateInstance).
OBJECTHANDLE m_ohDelegate;

// For interfaces this contains the COM interface type.
CorIfaceAttr m_ComInterfaceType;
};
// For interfaces this contains the COM interface type.
CorIfaceAttr m_ComInterfaceType;

ComCallWrapperTemplate *m_pccwTemplate; // points to interop data structures used when this type is exposed to COM
#endif // FEATURE_COMINTEROP
Expand Down
80 changes: 11 additions & 69 deletions src/coreclr/vm/comcallablewrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2314,52 +2314,6 @@ IUnknown* ComCallWrapper::GetBasicIP(bool inspectionOnly)
RETURN ((cbRef != 0xbadf00d) ? pIntf : NULL);
}

struct InvokeICustomQueryInterfaceGetInterfaceArgs
{
ComCallWrapper *pWrap;
GUID *pGuid;
IUnknown **ppUnk;
CustomQueryInterfaceResult *pRetVal;
};

VOID __stdcall InvokeICustomQueryInterfaceGetInterface_CallBack(LPVOID ptr)
{
CONTRACTL
{
THROWS;
GC_TRIGGERS;
MODE_ANY;
PRECONDITION(CheckPointer(ptr));
}
CONTRACTL_END;
InvokeICustomQueryInterfaceGetInterfaceArgs *pArgs = (InvokeICustomQueryInterfaceGetInterfaceArgs*)ptr;

{
GCX_COOP();
OBJECTREF pObj = pArgs->pWrap->GetObjectRef();

GCPROTECT_BEGIN(pObj);

// 1. Get MD
MethodDesc *pMD = pArgs->pWrap->GetSimpleWrapper()->GetComCallWrapperTemplate()->GetICustomQueryInterfaceGetInterfaceMD();

// 2. Get Object Handle
OBJECTHANDLE hndCustomQueryInterface = pArgs->pWrap->GetObjectHandle();

// 3 construct the MethodDescCallSite
MethodDescCallSite GetInterface(pMD, hndCustomQueryInterface);

ARG_SLOT Args[] = {
ObjToArgSlot(pObj),
PtrToArgSlot(pArgs->pGuid),
PtrToArgSlot(pArgs->ppUnk),
};

*(pArgs->pRetVal) = (CustomQueryInterfaceResult)GetInterface.Call_RetArgSlot(Args);
GCPROTECT_END();
}
}

//--------------------------------------------------------------------------
// check if the interface is supported, return a index into the IMap
// returns -1, if pIntfMT is not supported
Expand Down Expand Up @@ -2601,9 +2555,18 @@ static bool GetComIPFromCCW_HandleCustomQI(
guid = riid;
}

InvokeICustomQueryInterfaceGetInterfaceArgs args = {pWrap, &guid, ppUnkOut, &retVal};
{
GCX_COOP();
OBJECTREF pObj = pWrap->GetObjectRef();

InvokeICustomQueryInterfaceGetInterface_CallBack(&args);
GCPROTECT_BEGIN(pObj);

UnmanagedCallersOnlyCaller callICustomQueryInterface(METHOD__STUBHELPERS__CALL_ICUSTOM_QUERY_INTERFACE);
INT32 result = callICustomQueryInterface.InvokeThrowing_Ret<INT32>(&pObj, &guid, ppUnkOut);

retVal = static_cast<CustomQueryInterfaceResult>(result);
GCPROTECT_END();
}

// return if user already handle the QI
if (retVal == Handled)
Expand Down Expand Up @@ -4674,7 +4637,6 @@ ComCallWrapperTemplate* ComCallWrapperTemplate::CreateTemplate(TypeHandle thClas
pTemplate->m_pClassComMT = NULL; // Defer setting this up.
pTemplate->m_pBasicComMT = NULL;
pTemplate->m_pDefaultItf = NULL;
pTemplate->m_pICustomQueryInterfaceGetInterfaceMD = NULL;
pTemplate->m_flags = 0;

// Determine the COM visibility of classes in our hierarchy.
Expand Down Expand Up @@ -4794,7 +4756,6 @@ ComCallWrapperTemplate *ComCallWrapperTemplate::CreateTemplateForInterface(Metho
pTemplate->m_pClassComMT = NULL;
pTemplate->m_pBasicComMT = NULL;
pTemplate->m_pDefaultItf = pItfMT;
pTemplate->m_pICustomQueryInterfaceGetInterfaceMD = NULL;
pTemplate->m_flags = enum_RepresentsVariantInterface;

// Initialize the one ComMethodTable
Expand Down Expand Up @@ -4927,25 +4888,6 @@ ComMethodTable *ComCallWrapperTemplate::SetupComMethodTableForClass(MethodTable
RETURN pIClassXComMT;
}


MethodDesc * ComCallWrapperTemplate::GetICustomQueryInterfaceGetInterfaceMD()
{
CONTRACT (MethodDesc*)
{
THROWS;
GC_TRIGGERS;
MODE_ANY;
PRECONDITION(m_flags & enum_ImplementsICustomQueryInterface);
}
CONTRACT_END;

if (m_pICustomQueryInterfaceGetInterfaceMD == NULL)
m_pICustomQueryInterfaceGetInterfaceMD = m_thClass.GetMethodTable()->GetMethodDescForInterfaceMethod(
CoreLibBinder::GetMethod(METHOD__ICUSTOM_QUERYINTERFACE__GET_INTERFACE),
TRUE /* throwOnConflict */);
RETURN m_pICustomQueryInterfaceGetInterfaceMD;
}

//--------------------------------------------------------------------------
// Module* ComCallMethodDesc::GetModule()
// Get Module
Expand Down
3 changes: 0 additions & 3 deletions src/coreclr/vm/comcallablewrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,6 @@ class ComCallWrapperTemplate
// Sets up the class method table for the IClassX and also lays it out.
static ComMethodTable *SetupComMethodTableForClass(MethodTable *pMT, BOOL bLayOutComMT);

MethodDesc * GetICustomQueryInterfaceGetInterfaceMD();

BOOL HasInvisibleParent()
{
LIMITED_METHOD_CONTRACT;
Expand Down Expand Up @@ -328,7 +326,6 @@ class ComCallWrapperTemplate
enum_IsSafeTypeForMarshalling = 0x2000, // The class can be safely marshalled out of process via DCOM
};
DWORD m_flags;
MethodDesc* m_pICustomQueryInterfaceGetInterfaceMD;
ULONG m_cbInterfaces;
SLOT* m_rgpIPtr[1];
};
Expand Down
45 changes: 21 additions & 24 deletions src/coreclr/vm/comconnectionpoints.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,37 +539,34 @@ void ConnectionPoint::InvokeProviderMethod( OBJECTREF pProvider, OBJECTREF pSubs
// Retrieve the EE class representing the argument.
MethodTable *pDelegateCls = MethodSig.GetLastTypeHandleThrowing().GetMethodTable();

// Make sure we activate the assembly containing the target method desc
// Initialize the delegate using the arguments structure.
MethodDesc *pDlgCtorMD = MemberLoader::FindConstructor(pDelegateCls, &gsig_IM_Obj_IntPtr_RetVoid);
if (pDlgCtorMD == NULL)
pDlgCtorMD = MemberLoader::FindConstructor(pDelegateCls, &gsig_IM_Obj_UIntPtr_RetVoid);

// The loader is responsible for only accepting well-formed delegate classes.
_ASSERTE(pDlgCtorMD);

// Make sure we activate assemblies containing target method descs.
pProvMethodDesc->EnsureActive();
pDlgCtorMD->EnsureActive();
pEventMethodDesc->EnsureActive();

// Allocate an object based on the method table of the delegate class.
OBJECTREF pDelegate = pDelegateCls->Allocate();

GCPROTECT_BEGIN( pDelegate );
{
// Initialize the delegate using the arguments structure.
// <TODO>Generics: ensure we get the right MethodDesc here and in similar places</TODO>
// Accept both void (object, native int) and void (object, native uint)
MethodDesc *pDlgCtorMD = MemberLoader::FindConstructor(pDelegateCls, &gsig_IM_Obj_IntPtr_RetVoid);
if (pDlgCtorMD == NULL)
pDlgCtorMD = MemberLoader::FindConstructor(pDelegateCls, &gsig_IM_Obj_UIntPtr_RetVoid);

// The loader is responsible for only accepting well-formed delegate classes.
_ASSERTE(pDlgCtorMD);

MethodDescCallSite dlgCtor(pDlgCtorMD);

ARG_SLOT CtorArgs[3] = { ObjToArgSlot(pDelegate),
ObjToArgSlot(pSubscriber),
(ARG_SLOT)pEventMethodDesc->GetMultiCallableAddrOfCode()
};
dlgCtor.Call(CtorArgs);

MethodDescCallSite prov(pProvMethodDesc, &pProvider);

// Do the actual invocation of the method method.
ARG_SLOT Args[2] = { ObjToArgSlot( pProvider ), ObjToArgSlot( pDelegate ) };
prov.Call(Args);
UnmanagedCallersOnlyCaller invokeConnectionPointProviderMethod(METHOD__STUBHELPERS__INVOKE_CONNECTION_POINT_PROVIDER_METHOD);

// Construct the delegate and invoke the provider method in one helper.
invokeConnectionPointProviderMethod.InvokeThrowing(
&pProvider,
pProvMethodDesc->GetSingleCallableAddrOfCode(),
&pDelegate,
pDlgCtorMD->GetSingleCallableAddrOfCode(),
&pSubscriber,
pEventMethodDesc->GetMultiCallableAddrOfCode());
}
GCPROTECT_END();
}
Expand Down
3 changes: 3 additions & 0 deletions src/coreclr/vm/corelib.h
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,9 @@ DEFINE_METHOD(STUBHELPERS, GET_PENDING_EXCEPTION_OBJECT, GetPendingExce
DEFINE_METHOD(STUBHELPERS, CREATE_CUSTOM_MARSHALER, CreateCustomMarshaler, SM_IntPtr_Int_IntPtr_RetObj)
#ifdef FEATURE_COMINTEROP
DEFINE_METHOD(STUBHELPERS, GET_IENUMERATOR_TO_ENUM_VARIANT_MARSHALER, GetIEnumeratorToEnumVariantMarshaler, SM_PtrObj_PtrException_RetVoid)
DEFINE_METHOD(STUBHELPERS, GET_DISPATCH_EX_PROPERTY_FLAGS, GetDispatchExPropertyFlags, SM_PtrPropertyInfo_PtrInt_PtrException_RetVoid)
DEFINE_METHOD(STUBHELPERS, CALL_ICUSTOM_QUERY_INTERFACE, CallICustomQueryInterface, SM_PtrICustomQueryInterface_PtrGuid_PtrIntPtr_PtrException_RetInt)
DEFINE_METHOD(STUBHELPERS, INVOKE_CONNECTION_POINT_PROVIDER_METHOD, InvokeConnectionPointProviderMethod, NoSig)
#endif // FEATURE_COMINTEROP

DEFINE_METHOD(STUBHELPERS, CHECK_STRING_LENGTH, CheckStringLength, SM_Int_RetVoid)
Expand Down
4 changes: 4 additions & 0 deletions src/coreclr/vm/metasig.h
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,10 @@ DEFINE_METASIG(SM(RefByte_RefByte_UIntPtr_RetVoid, r(b) r(b) U, v))
DEFINE_METASIG(SM(RefByte_Byte_UIntPtr_RetVoid, r(b) b U, v))
DEFINE_METASIG(SM(RefByte_UIntPtr_RetVoid, r(b) U, v))
DEFINE_METASIG(SM(PtrVoid_Byte_UInt_RetVoid, P(v) b K, v))
#ifdef FEATURE_COMINTEROP
DEFINE_METASIG_T(SM(PtrICustomQueryInterface_PtrGuid_PtrIntPtr_PtrException_RetInt, P(C(ICUSTOM_QUERYINTERFACE)) P(g(GUID)) P(I) P(C(EXCEPTION)), i))
DEFINE_METASIG_T(SM(PtrPropertyInfo_PtrInt_PtrException_RetVoid, P(C(PROPERTY_INFO)) P(i) P(C(EXCEPTION)), v))
#endif // FEATURE_COMINTEROP
DEFINE_METASIG(SM(IntPtr_RefObj_IntPtr_RetVoid, I r(j) I, v))
DEFINE_METASIG(SM(IntPtr_RefObj_IntPtr_Int_RetVoid, I r(j) I i,v))
DEFINE_METASIG(SM(IntPtr_IntPtr_Int_Int_IntPtr_RetVoid, I I i i I, v))
Expand Down
Loading
Loading