diff --git a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs index 673390f94d9cb9..04829818b7d427 100644 --- a/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs +++ b/src/coreclr/System.Private.CoreLib/src/System/StubHelpers.cs @@ -1531,6 +1531,7 @@ internal static void SetPendingExceptionObject(Exception? exception) [SupportedOSPlatform("windows")] [UnmanagedCallersOnly] + [RequiresUnsafe] private static unsafe void GetIEnumeratorToEnumVariantMarshaler(object* pResult, Exception* pException) { try @@ -1542,6 +1543,78 @@ 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 int GetDispatchExPropertyFlags(PropertyInfo* pMemberInfo, Exception* pException) + { + try + { + int result = 0; + PropertyInfo property = *pMemberInfo; + if (property.CanRead) + { + result |= DispatchExPropertyCanRead; + } + + if (property.CanWrite) + { + result |= DispatchExPropertyCanWrite; + } + + return result; + } + catch (Exception ex) + { + *pException = ex; + return 0; + } + } + + [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* providerMethodEntryPoint, + object* pDelegate, + delegate* 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) diff --git a/src/coreclr/vm/class.h b/src/coreclr/vm/class.h index 9894f59da8f482..13d1ee37a8d3cd 100644 --- a/src/coreclr/vm/class.h +++ b/src/coreclr/vm/class.h @@ -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() { @@ -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 diff --git a/src/coreclr/vm/comcallablewrapper.cpp b/src/coreclr/vm/comcallablewrapper.cpp index 1b0c6eea5a4e45..d91459baf7b9b1 100644 --- a/src/coreclr/vm/comcallablewrapper.cpp +++ b/src/coreclr/vm/comcallablewrapper.cpp @@ -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 @@ -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(&pObj, &guid, ppUnkOut); + + retVal = static_cast(result); + GCPROTECT_END(); + } // return if user already handle the QI if (retVal == Handled) @@ -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. @@ -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 @@ -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 diff --git a/src/coreclr/vm/comcallablewrapper.h b/src/coreclr/vm/comcallablewrapper.h index 307b07d59dcdb7..a4bc88253781eb 100644 --- a/src/coreclr/vm/comcallablewrapper.h +++ b/src/coreclr/vm/comcallablewrapper.h @@ -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; @@ -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]; }; diff --git a/src/coreclr/vm/comconnectionpoints.cpp b/src/coreclr/vm/comconnectionpoints.cpp index 6442c534436567..cfc089c2651afd 100644 --- a/src/coreclr/vm/comconnectionpoints.cpp +++ b/src/coreclr/vm/comconnectionpoints.cpp @@ -539,7 +539,17 @@ 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. @@ -547,29 +557,16 @@ void ConnectionPoint::InvokeProviderMethod( OBJECTREF pProvider, OBJECTREF pSubs GCPROTECT_BEGIN( pDelegate ); { - // Initialize the delegate using the arguments structure. - // Generics: ensure we get the right MethodDesc here and in similar places - // 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); + + // Using GetMultiCallableAddrOfCode() for the event target since it is stored for future invokes. + invokeConnectionPointProviderMethod.InvokeThrowing( + &pProvider, + pProvMethodDesc->GetSingleCallableAddrOfCode(), + &pDelegate, + pDlgCtorMD->GetSingleCallableAddrOfCode(), + &pSubscriber, + pEventMethodDesc->GetMultiCallableAddrOfCode()); } GCPROTECT_END(); } diff --git a/src/coreclr/vm/corelib.h b/src/coreclr/vm/corelib.h index da160cf5412f26..51fd4dee8af33c 100644 --- a/src/coreclr/vm/corelib.h +++ b/src/coreclr/vm/corelib.h @@ -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_PtrException_RetInt) +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) diff --git a/src/coreclr/vm/metasig.h b/src/coreclr/vm/metasig.h index 7e4c1e101c073b..8dac8a5bba99e4 100644 --- a/src/coreclr/vm/metasig.h +++ b/src/coreclr/vm/metasig.h @@ -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_PtrException_RetInt, P(C(PROPERTY_INFO)) P(C(EXCEPTION)), i)) +#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)) diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index 9d609123829ca0..0234a880c986fe 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -708,44 +708,6 @@ MethodTable* CreateMinimalMethodTable(Module* pContainingModule, return pMT; } - -#ifdef FEATURE_COMINTEROP -//========================================================================================== -OBJECTREF MethodTable::GetObjCreateDelegate() -{ - CONTRACTL - { - MODE_COOPERATIVE; - GC_NOTRIGGER; - NOTHROW; - } - CONTRACTL_END; - _ASSERT(!IsInterface()); - if (GetOHDelegate()) - return ObjectFromHandle(GetOHDelegate()); - else - return NULL; -} - -//========================================================================================== -void MethodTable::SetObjCreateDelegate(OBJECTREF orDelegate) -{ - CONTRACTL - { - MODE_COOPERATIVE; - GC_NOTRIGGER; - THROWS; // From CreateHandle - } - CONTRACTL_END; - - if (GetOHDelegate()) - StoreObjectInHandle(GetOHDelegate(), orDelegate); - else - SetOHDelegate (GetAppDomain()->CreateHandle(orDelegate)); -} -#endif // FEATURE_COMINTEROP - - //========================================================================================== void MethodTable::SetInterfaceMap(WORD wNumInterfaces, InterfaceInfo_t* iMap) { @@ -4888,22 +4850,6 @@ BOOL MethodTable::IsExtensibleRCW() return IsComObjectType() && !GetClass()->IsComImport(); } -//========================================================================================== -OBJECTHANDLE MethodTable::GetOHDelegate() -{ - WRAPPER_NO_CONTRACT; - _ASSERTE(GetClass()); - return GetClass()->GetOHDelegate(); -} - -//========================================================================================== -void MethodTable::SetOHDelegate (OBJECTHANDLE _ohDelegate) -{ - LIMITED_METHOD_CONTRACT; - _ASSERTE(GetClass()); - GetClass()->SetOHDelegate(_ohDelegate); -} - //========================================================================================== // Helper to skip over COM class in the hierarchy MethodTable* MethodTable::GetComPlusParentMethodTable() diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index b99dcb293337be..23cc148a09fe57 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -1027,9 +1027,6 @@ class MethodTable CorIfaceAttr GetComInterfaceType(); void SetComInterfaceType(CorIfaceAttr ItfType); - OBJECTHANDLE GetOHDelegate(); - void SetOHDelegate (OBJECTHANDLE _ohDelegate); - CorClassIfaceAttr GetComClassInterfaceType(); TypeHandle GetDefItfForComClassItf(); @@ -1062,9 +1059,6 @@ class MethodTable BOOL SetComClassFactory(ClassFactoryBase *pFactory); #endif // FEATURE_COMINTEROP_UNMANAGED_ACTIVATION - OBJECTREF GetObjCreateDelegate(); - void SetObjCreateDelegate(OBJECTREF orDelegate); - private: // This is for COM Interop backwards compatibility BOOL InsertComInteropData(InteropMethodTableData *pData); diff --git a/src/coreclr/vm/runtimecallablewrapper.cpp b/src/coreclr/vm/runtimecallablewrapper.cpp index 91ed63aa8ce4fc..3993c5293f138b 100644 --- a/src/coreclr/vm/runtimecallablewrapper.cpp +++ b/src/coreclr/vm/runtimecallablewrapper.cpp @@ -282,9 +282,6 @@ OBJECTREF ComClassFactory::CreateAggregatedInstance(MethodTable* pMTClass, BOOL HRESULT hr = S_OK; NewRCWHolder pNewRCW; - BOOL bUseDelegate = FALSE; - - MethodTable *pCallbackMT = NULL; OBJECTREF oref = NULL; COMOBJECTREF cref = NULL; @@ -295,68 +292,14 @@ OBJECTREF ComClassFactory::CreateAggregatedInstance(MethodTable* pMTClass, BOOL //get wrapper for the object, this could enable GC CCWHolder pComWrap = ComCallWrapper::InlineGetWrapper((OBJECTREF *)&cref); - // Make sure the ClassInitializer has run, since the user might have - // wanted to set up a COM object creation callback. - pMTClass->CheckRunClassInitThrowing(); - - // If the user is going to use a delegate to allocate the COM object - // (rather than CoCreateInstance), we need to know now, before we enable - // preemptive GC mode (since we touch object references in the - // determination). - // We don't just check the current class to see if it has a cllabck - // registered, we check up the class chain to see if any of our parents - // did. - - pCallbackMT = pMTClass; - while ((pCallbackMT != NULL) && - (pCallbackMT->GetObjCreateDelegate() == NULL) && - !pCallbackMT->IsComImport()) - { - pCallbackMT = pCallbackMT->GetParentMethodTable(); - } - - if (pCallbackMT && !pCallbackMT->IsComImport()) - bUseDelegate = TRUE; - DebuggerExitFrame __def; // get the IUnknown interface for the managed object pOuter = ComCallWrapper::GetComIPFromCCW(pComWrap, IID_IUnknown, NULL); _ASSERTE(pOuter != NULL); - // If the user has set a delegate to allocate the COM object, use it. - // Otherwise we just CoCreateInstance it. - if (bUseDelegate) - { - ARG_SLOT args[2]; - - OBJECTREF orDelegate = pCallbackMT->GetObjCreateDelegate(); - MethodDesc *pMeth = COMDelegate::GetMethodDesc(orDelegate); - - GCPROTECT_BEGIN(orDelegate) - { - _ASSERTE(pMeth); - MethodDescCallSite delegateMethod(pMeth, &orDelegate); - - // Get the OR on which we are going to invoke the method and set it - // as the first parameter in arg above. - args[0] = (ARG_SLOT)OBJECTREFToObject(COMDelegate::GetTargetObject(orDelegate)); - - // Pass the IUnknown of the aggregator as the second argument. - args[1] = (ARG_SLOT)(IUnknown*)pOuter; - - // Call the method... - pUnk = (IUnknown *)delegateMethod.Call_RetArgSlot(args); - if (!pUnk) - COMPlusThrowHR(E_FAIL); - } - GCPROTECT_END(); - } - else - { - _ASSERTE(m_pClassMT); - pUnk = CreateInstanceInternal(pOuter, &fDidContainment); - } + _ASSERTE(m_pClassMT); + pUnk = CreateInstanceInternal(pOuter, &fDidContainment); __def.Pop(); diff --git a/src/coreclr/vm/stdinterfaces.cpp b/src/coreclr/vm/stdinterfaces.cpp index 50b39ed1eb3921..a7cb4e9ef35235 100644 --- a/src/coreclr/vm/stdinterfaces.cpp +++ b/src/coreclr/vm/stdinterfaces.cpp @@ -1887,34 +1887,17 @@ HRESULT __stdcall DispatchEx_GetMemberProperties ( case Property: { - BOOL bCanRead = FALSE; - BOOL bCanWrite = FALSE; - - // Find the MethodDesc's for the CanRead property. - MethodDesc *pCanReadMD = MemberLoader::FindPropertyMethod(MemberInfoObj->GetMethodTable(), PROPERTY_INFO_CAN_READ_PROP, PropertyGet); - _ASSERTE_MSG((pCanReadMD != NULL), "Unable to find getter method for property PropertyInfo::CanRead"); - MethodDescCallSite canRead(pCanReadMD, &MemberInfoObj); - - // Find the MethodDesc's for the CanWrite property. - MethodDesc *pCanWriteMD = MemberLoader::FindPropertyMethod(MemberInfoObj->GetMethodTable(), PROPERTY_INFO_CAN_WRITE_PROP, PropertyGet); - _ASSERTE_MSG((pCanWriteMD != NULL), "Unable to find setter method for property PropertyInfo::CanWrite"); - MethodDescCallSite canWrite(pCanWriteMD, &MemberInfoObj); - - // Check to see if the property can be read. - ARG_SLOT CanReadArgs[] = + enum : INT32 { - ObjToArgSlot(MemberInfoObj) + DispatchExPropertyCanRead = 1, + DispatchExPropertyCanWrite = 2, }; - bCanRead = canRead.Call_RetBool(CanReadArgs); - - // Check to see if the property can be written to. - ARG_SLOT CanWriteArgs[] = - { - ObjToArgSlot(MemberInfoObj) - }; + UnmanagedCallersOnlyCaller getDispatchExPropertyFlags(METHOD__STUBHELPERS__GET_DISPATCH_EX_PROPERTY_FLAGS); + INT32 propertyFlags = getDispatchExPropertyFlags.InvokeThrowing_Ret(&MemberInfoObj); - bCanWrite = canWrite.Call_RetBool(CanWriteArgs); + bool bCanRead = (propertyFlags & DispatchExPropertyCanRead) != 0; + bool bCanWrite = (propertyFlags & DispatchExPropertyCanWrite) != 0; *pgrfdex = (bCanRead ? fdexPropCanGet : fdexPropCannotGet) | (bCanWrite ? fdexPropCanPut : fdexPropCannotPut) |