diff options
author | Jeremy Koritzinsky <jkoritzinsky@gmail.com> | 2019-04-04 22:56:56 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-04-04 22:56:56 -0700 |
commit | 8241971dc93dca98992596a9396dee1a2031ea15 (patch) | |
tree | ac75247a13082544183134f946ecd185d00a4dd2 | |
parent | 3a058450784d6ceb2ca8fd4b7b1ca8d3d6d4e8a9 (diff) | |
download | coreclr-8241971dc93dca98992596a9396dee1a2031ea15.tar.gz coreclr-8241971dc93dca98992596a9396dee1a2031ea15.tar.bz2 coreclr-8241971dc93dca98992596a9396dee1a2031ea15.zip |
Disable marshalling delegates as _Delegate and enable marshalling delegates as IDispatch. (#23738)
* Disable marshalling delegates as _Delegate and enable marshalling delegates as IDispatch.
* ifdef out the new IDispatch marshalling on non-COM-supporting platforms.
* PR feedback.
8 files changed, 143 insertions, 97 deletions
diff --git a/src/dlls/mscorrc/mscorrc.rc b/src/dlls/mscorrc/mscorrc.rc index 4853f00789..7acfb09ecb 100644 --- a/src/dlls/mscorrc/mscorrc.rc +++ b/src/dlls/mscorrc/mscorrc.rc @@ -586,7 +586,8 @@ BEGIN IDS_EE_BADMARSHAL_R8 "Invalid managed/unmanaged type combination (Double must be paired with R8)." IDS_EE_BADMARSHAL_PTR "Invalid managed/unmanaged type combination (pointers must not have a MarshalAs attribute set)." IDS_EE_BADMARSHAL_NOLAYOUT "The type definition of this type has no layout information." - IDS_EE_BADMARSHAL_DELEGATE "Invalid managed/unmanaged type combination (Delegates must be paired with FunctionPtr or Interface)." + IDS_EE_BADMARSHAL_DELEGATE "Invalid managed/unmanaged type combination (Delegates must be paired with FunctionPtr or IDispatch)." + IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE ".NET Core does not support marshalling delegates to the _Delegate interface provided by the .NET Framework COM Type Library. To marshal a delegate as an interface, marshal it as an IDispatch pointer." IDS_EE_BADMARSHAL_FNPTR "Invalid managed/unmanaged type combination (function pointers must be paired with FunctionPtr)." IDS_EE_BADMARSHAL_INTERFACE "Invalid managed/unmanaged type combination (Interfaces must be paired with Interface)." IDS_EE_BADMARSHAL_CLASS "Invalid managed/unmanaged type combination (this type must be paired with LPStruct or Interface)." diff --git a/src/dlls/mscorrc/resource.h b/src/dlls/mscorrc/resource.h index 609a31d253..cc9e0e81f5 100644 --- a/src/dlls/mscorrc/resource.h +++ b/src/dlls/mscorrc/resource.h @@ -721,3 +721,4 @@ #define IDS_EE_BADMARSHAL_STRING_OUT 0x2646 #define IDS_EE_BADMARSHAL_COPYCTORRESTRICTION 0x2647 #define IDS_EE_BADMARSHAL_WINRT_COPYCTOR 0x2648 +#define IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE 0x2649 diff --git a/src/vm/fieldmarshaler.cpp b/src/vm/fieldmarshaler.cpp index 51d9b8b798..a8676d65bd 100644 --- a/src/vm/fieldmarshaler.cpp +++ b/src/vm/fieldmarshaler.cpp @@ -588,12 +588,16 @@ do \ { INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_WINRT_ILLEGAL_TYPE)); } + else if (COMDelegate::IsDelegate(thNestedType.GetMethodTable())) + { + INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE)); + } else { ItfMarshalInfo itfInfo; if (FAILED(MarshalInfo::TryGetItfMarshalInfo(thNestedType, FALSE, FALSE, &itfInfo))) break; - + INITFIELDMARSHALER(NFT_INTERFACE, FieldMarshaler_Interface, (itfInfo.thClass.GetMethodTable(), itfInfo.thItf.GetMethodTable(), itfInfo.dwFlags)); } } @@ -792,6 +796,16 @@ do \ { INITFIELDMARSHALER(NFT_DELEGATE, FieldMarshaler_Delegate, (thNestedType.GetMethodTable())); } +#ifdef FEATURE_COMINTEROP + else if (ntype == NATIVE_TYPE_IDISPATCH) + { + ItfMarshalInfo itfInfo; + if (FAILED(MarshalInfo::TryGetItfMarshalInfo(thNestedType, FALSE, FALSE, &itfInfo))) + break; + + INITFIELDMARSHALER(NFT_INTERFACE, FieldMarshaler_Interface, (itfInfo.thClass.GetMethodTable(), itfInfo.thItf.GetMethodTable(), itfInfo.dwFlags)); + } +#endif // FEATURE_COMINTEROP else { INITFIELDMARSHALER(NFT_ILLEGAL, FieldMarshaler_Illegal, (IDS_EE_BADMARSHAL_DELEGATE)); diff --git a/src/vm/mlinfo.cpp b/src/vm/mlinfo.cpp index f861c43cf8..cb512bb4f0 100644 --- a/src/vm/mlinfo.cpp +++ b/src/vm/mlinfo.cpp @@ -2003,16 +2003,27 @@ MarshalInfo::MarshalInfo(Module* pModule, IfFailGoto(E_FAIL, lFail); } - if (m_ms == MARSHAL_SCENARIO_WINRT && COMDelegate::IsDelegate(m_pMT)) + if (COMDelegate::IsDelegate(m_pMT)) { - // In WinRT scenarios delegates must be WinRT delegates - if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT)) + if (m_ms == MARSHAL_SCENARIO_WINRT) { - m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE; + // In WinRT scenarios delegates must be WinRT delegates + if (!m_pMT->IsProjectedFromWinRT() && !WinRTTypeNameConverter::IsRedirectedType(m_pMT)) + { + m_resID = IDS_EE_BADMARSHAL_WINRT_DELEGATE; + IfFailGoto(E_FAIL, lFail); + } + } + else + { + // UnmanagedType.Interface for delegates used to mean the .NET Framework _Delegate interface. + // We don't support that interface in .NET Core, so we disallow marshalling as it here. + // The user can specify UnmanagedType.IDispatch and use the delegate through the IDispatch interface + // if they need an interface pointer. + m_resID = IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE; IfFailGoto(E_FAIL, lFail); } } - m_type = MARSHAL_TYPE_INTERFACE; } else if (pDefaultMT != NULL && nativeType == NATIVE_TYPE_DEFAULT) @@ -2291,17 +2302,29 @@ MarshalInfo::MarshalInfo(Module* pModule, case NATIVE_TYPE_DEFAULT: #ifdef FEATURE_COMINTEROP - if (m_ms != MARSHAL_SCENARIO_NDIRECT) + if (m_ms == MARSHAL_SCENARIO_WINRT) { - _ASSERTE(m_ms == MARSHAL_SCENARIO_COMINTEROP || m_ms == MARSHAL_SCENARIO_WINRT); m_type = MARSHAL_TYPE_INTERFACE; } + else if (m_ms == MARSHAL_SCENARIO_COMINTEROP) + { + // Default for COM marshalling for delegates used to mean the .NET Framework _Delegate interface. + // We don't support that interface in .NET Core, so we disallow marshalling as it here. + // The user can specify UnmanagedType.IDispatch and use the delegate through the IDispatch interface + // if they need an interface pointer. + m_resID = IDS_EE_BADMARSHAL_DELEGATE_TLB_INTERFACE; + IfFailGoto(E_FAIL, lFail); + } else #endif // FEATURE_COMINTEROP m_type = MARSHAL_TYPE_DELEGATE; break; - +#ifdef FEATURE_COMINTEROP + case NATIVE_TYPE_IDISPATCH: + m_type = MARSHAL_TYPE_INTERFACE; + break; +#endif default: m_resID = IDS_EE_BADMARSHAL_DELEGATE; IfFailGoto(E_FAIL, lFail); diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFieldNative.cpp b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFieldNative.cpp index d5fdf86b55..9f43d63a0d 100644 --- a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFieldNative.cpp +++ b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/AsFieldNative.cpp @@ -113,9 +113,6 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE TakeDelegateAsFieldInClass_Exp(Clas * For MarshalDelegateAsField_AsInterface.cs * * * *-----------------------------------------------------------------------------*/ - -#import "mscorlib.tlb" no_namespace named_guids raw_interfaces_only rename("ReportEvent","ReportEventNew") - typedef struct{ int result1; int result2; @@ -167,7 +164,7 @@ bool STDMETHODCALLTYPE Verify(Result expectedR, Result resultR) typedef struct _Struct3_InterfacePtrAsField1_Seq{ BOOL verification; - _Delegate * p_dele; + IDispatch * p_dele; }Struct3_InterfacePtrAsField1_Seq; extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Seq(Struct3_InterfacePtrAsField1_Seq sis) @@ -183,14 +180,6 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Seq } else { - hr = sis.p_dele->DynamicInvoke( NULL, NULL); - if(FAILED(hr)) - { - return FALSE; - } - bool tempBool = sis.verification && Verify( expected, result); - - //IDispatch::Invoke ResetToZero(); @@ -234,14 +223,14 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Seq return FALSE; } - return tempBool && Verify(expected, result); + return Verify(expected, result); } } typedef struct _Struct3_InterfacePtrAsField2_Exp{ bool verification; int Padding; - _Delegate * p_dele; + IDispatch * p_dele; }Struct3_InterfacePtrAsField2_Exp; extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Exp(Struct3_InterfacePtrAsField2_Exp sie) @@ -255,18 +244,9 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Exp printf("NULL field member.\n"); return FALSE; } - else + else { - hr = sie.p_dele->DynamicInvoke(NULL, NULL); - if(FAILED(hr)) - { - return FALSE; - } - bool tempBool = sie.verification && Verify( expected, result); - - //IDispatch::Invoke - ResetToZero(); BSTR bstrNames[1]; bstrNames[0] = SysAllocString(L"DynamicInvoke"); @@ -307,7 +287,7 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInStruct_Exp return FALSE; } - return tempBool && Verify(expected, result); + return Verify(expected, result); } } @@ -315,7 +295,7 @@ class Class3_InterfacePtrAsField3_Seq { public: bool verification; - _Delegate * p_dele; + IDispatch * p_dele; }; extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Seq(Class3_InterfacePtrAsField3_Seq *cis) @@ -331,14 +311,6 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Seq( } else { - hr = (cis->p_dele)->DynamicInvoke(NULL, NULL); - if(FAILED(hr)) - { - return FALSE; - } - bool tempBool = cis->verification && Verify( expected, result); - - //IDispatch::Invoke BSTR bstrNames[1]; bstrNames[0] = SysAllocString(L"DynamicInvoke"); @@ -380,7 +352,7 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Seq( return FALSE; } - return tempBool && Verify(expected, result); + return Verify(expected, result); } } @@ -389,7 +361,7 @@ class Class3_InterfacePtrAsField4_Exp{ public: bool verification; int Padding; - _Delegate * p_dele; + IDispatch * p_dele; }; extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Exp(Class3_InterfacePtrAsField4_Exp *cie) @@ -405,14 +377,6 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Exp( } else { - hr = (cie->p_dele)->DynamicInvoke(NULL, NULL); - if(FAILED(hr)) - { - return FALSE; - } - bool tempBool = cie->verification && Verify( expected, result); - - //IDispatch::Invoke BSTR bstrNames[1]; bstrNames[0] = SysAllocString(L"DynamicInvoke"); @@ -453,7 +417,11 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrAsFieldInClass_Exp( return FALSE; } - return tempBool && Verify(expected, result); + return Verify(expected, result); } } + +extern "C" DLL_EXPORT void STDMETHODCALLTYPE TakeDelegateAsInterface(void* illegal) +{ +} #endif diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.cs index a89be582b3..37f74c9c87 100644 --- a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.cs +++ b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsField/RefLib/RefLib.cs @@ -107,7 +107,7 @@ public struct Struct3_InterfacePtrAsField1_Seq { public bool verification; - [MarshalAs(UnmanagedType.Interface)] + [MarshalAs(UnmanagedType.IDispatch)] public Dele2 dele; } @@ -121,7 +121,7 @@ public struct Struct3_InterfacePtrAsField2_Exp public Int32 Padding; [FieldOffset(8)] - [MarshalAs(UnmanagedType.Interface)] + [MarshalAs(UnmanagedType.IDispatch)] public Dele2 dele; } @@ -130,7 +130,7 @@ public class Class3_InterfacePtrAsField3_Seq { public bool verification; - [MarshalAs(UnmanagedType.Interface)] + [MarshalAs(UnmanagedType.IDispatch)] public Dele2 dele; } @@ -144,7 +144,7 @@ public class Class3_InterfacePtrAsField4_Exp public Int32 Padding; [FieldOffset(8)] - [MarshalAs(UnmanagedType.Interface)] + [MarshalAs(UnmanagedType.IDispatch)] public Dele2 dele; } -#endregion
\ No newline at end of file +#endregion diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.cs b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.cs index b06260bf79..7e43687511 100644 --- a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.cs +++ b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsInterface/AsInterfaceTest.cs @@ -11,32 +11,35 @@ class AsInterfaceTest public delegate void Dele(); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByValParam([MarshalAs(UnmanagedType.Interface)] Dele dele); + extern static bool Take_DelegatePtrByValParam([MarshalAs(UnmanagedType.IDispatch)] Dele dele); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByRefParam([MarshalAs(UnmanagedType.Interface)] ref Dele dele); + extern static bool Take_DelegatePtrByRefParam([MarshalAs(UnmanagedType.IDispatch)] ref Dele dele); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByInValParam([In, MarshalAs(UnmanagedType.Interface)] Dele dele); + extern static bool Take_DelegatePtrByInValParam([In, MarshalAs(UnmanagedType.IDispatch)] Dele dele); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByInRefParam([In, MarshalAs(UnmanagedType.Interface)] ref Dele dele); + extern static bool Take_DelegatePtrByInRefParam([In, MarshalAs(UnmanagedType.IDispatch)] ref Dele dele); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByOutValParam([Out, MarshalAs(UnmanagedType.Interface)] Dele dele); + extern static bool Take_DelegatePtrByOutValParam([Out, MarshalAs(UnmanagedType.IDispatch)] Dele dele); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByOutRefParam([Out, MarshalAs(UnmanagedType.Interface)]out Dele dele, [MarshalAs(UnmanagedType.Interface)] Dele deleHelper); + extern static bool Take_DelegatePtrByOutRefParam([Out, MarshalAs(UnmanagedType.IDispatch)]out Dele dele, [MarshalAs(UnmanagedType.IDispatch)] Dele deleHelper); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByInOutValParam([In, Out, MarshalAs(UnmanagedType.Interface)] Dele dele); + extern static bool Take_DelegatePtrByInOutValParam([In, Out, MarshalAs(UnmanagedType.IDispatch)] Dele dele); [DllImport("PInvoke_Delegate_AsParam")] - extern static bool Take_DelegatePtrByInOutRefParam([In, Out, MarshalAs(UnmanagedType.Interface)] ref Dele dele); + extern static bool Take_DelegatePtrByInOutRefParam([In, Out, MarshalAs(UnmanagedType.IDispatch)] ref Dele dele); [DllImport("PInvoke_Delegate_AsParam")] - [return: MarshalAs(UnmanagedType.Interface)] - extern static Dele ReturnDelegatePtrByVal([MarshalAs(UnmanagedType.Interface)] Dele dele); + [return: MarshalAs(UnmanagedType.IDispatch)] + extern static Dele ReturnDelegatePtrByVal([MarshalAs(UnmanagedType.IDispatch)] Dele dele); + + [DllImport("PInvoke_Delegate_AsParam")] + extern static void TakeDelegateAsInterface([MarshalAs(UnmanagedType.Interface)] Dele dele); [DllImport("PInvoke_Delegate_AsParam")] extern static int RetFieldResult1(); @@ -63,40 +66,40 @@ class AsInterfaceTest static int Main() { try{ - Console.WriteLine("Scenario 1 : Delegate marshaled by val with attribute [MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("Scenario 1 : Delegate marshaled by val with attribute [MarshalAs(UnmanagedType.IDispatch)]."); Dele dele1 = new Dele(CommonMethod1); dele1 += CommonMethod2; dele1 += CommonMethod3; Assert.IsTrue(Take_DelegatePtrByValParam(dele1), "Take_DelegatePtrByValParam"); - Console.WriteLine("\n\nScenario 2 : Delegate marshaled by ref with attribute [MarshalAs(MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 2 : Delegate marshaled by ref with attribute [MarshalAs(MarshalAs(UnmanagedType.IDispatch)]."); Dele dele2 = new Dele(CommonMethod1); dele2 += CommonMethod2; dele2 += CommonMethod3; Assert.IsTrue(Take_DelegatePtrByRefParam(ref dele2), "Take_DelegatePtrByRefParam"); Assert.IsNull( dele2, "dele2 should equal to null"); - Console.WriteLine("\n\nScenario 3 : Delegate marshaled by val with attribute [In,MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 3 : Delegate marshaled by val with attribute [In,MarshalAs(UnmanagedType.IDispatch)]."); Dele dele3 = new Dele(CommonMethod1); dele3 += CommonMethod2; dele3 += CommonMethod3; Assert.IsTrue(Take_DelegatePtrByInValParam(dele3), "Take_DelegatePtrByInValParam"); - Console.WriteLine("\n\nScenario 4 : Delegate marshaled by ref with attribute [In,MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 4 : Delegate marshaled by ref with attribute [In,MarshalAs(UnmanagedType.IDispatch)]."); Dele dele4 = new Dele(CommonMethod1); dele4 += CommonMethod2; dele4 += CommonMethod3; Assert.IsTrue(Take_DelegatePtrByInRefParam(ref dele4), "Take_DelegatePtrByInRefParam"); Assert.IsNotNull(dele4, "dele4 does't set to null correctly."); - Console.WriteLine("\n\nScenario 5 : Delegate marshaled by val with attribute [Out,MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 5 : Delegate marshaled by val with attribute [Out,MarshalAs(UnmanagedType.IDispatch)]."); Dele dele5 = new Dele(CommonMethod1); dele5 += CommonMethod2; dele5 += CommonMethod3; Assert.IsTrue(Take_DelegatePtrByOutValParam(dele5), "Take_DelegatePtrByOutValParam"); Assert.IsNotNull(dele5, "dele5 does't set to null correctly"); - Console.WriteLine("\n\nScenario 6 : Delegate marshaled by ref with attribute [Out,MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 6 : Delegate marshaled by ref with attribute [Out,MarshalAs(UnmanagedType.IDispatch)]."); Dele dele6 = null; Dele deleHelper = new Dele(CommonMethod1); deleHelper += CommonMethod2; @@ -105,20 +108,20 @@ class AsInterfaceTest Assert.AreEqual(COMMONMETHOD1_RESULT, RetFieldResult1(), "RetFieldResult1 return value is wrong"); Assert.AreEqual(COMMONMETHOD2_RESULT, RetFieldResult2(), "RetFieldResult2 return value is wrong "); - Console.WriteLine("\n\nScenario 7 : Delegate marshaled by val with attribute [In,OutMarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 7 : Delegate marshaled by val with attribute [In,OutMarshalAs(UnmanagedType.IDispatch)]."); Dele dele7 = new Dele(CommonMethod1); dele7 += CommonMethod2; dele7 += CommonMethod3; Assert.IsTrue(Take_DelegatePtrByInOutValParam(dele7), "Take_DelegatePtrByInOutValParam"); - Console.WriteLine("\n\nScenario 8 : Delegate marshaled by ref with attribute [In,OutMarshalAs(MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 8 : Delegate marshaled by ref with attribute [In,OutMarshalAs(MarshalAs(UnmanagedType.IDispatch)]."); Dele dele8 = new Dele(CommonMethod1); dele8 += CommonMethod2; dele8 += CommonMethod3; Assert.IsTrue(Take_DelegatePtrByInOutRefParam(ref dele8), "Take_DelegatePtrByInOutRefParam"); Assert.IsTrue(dele8 == null, "dele8 does't set to null correctly."); - Console.WriteLine("\n\nScenario 9 : return Delegate marshaled by val with attribute [return:MarshalAs(UnmanagedType.Interface)]."); + Console.WriteLine("\n\nScenario 9 : return Delegate marshaled by val with attribute [return:MarshalAs(UnmanagedType.IDispatch)]."); Dele dele9 = new Dele(CommonMethod1); dele9 += CommonMethod2; dele9 += CommonMethod3; @@ -128,6 +131,8 @@ class AsInterfaceTest Assert.AreEqual(COMMONMETHOD2_RESULT, RetFieldResult2(), "RetFieldResult2() return value is wrong"); Assert.AreEqual(COMMONMETHOD3_RESULT, RetFieldResult3(), "RetFieldResult3() return value is wrong"); + Assert.Throws<MarshalDirectiveException>(() => TakeDelegateAsInterface(new Dele(CommonMethod1))); + return 100; } catch (Exception e){ Console.WriteLine($"Test Failure: {e}"); diff --git a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsParamNative.cpp b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsParamNative.cpp index d85babb923..c3f2084b3c 100644 --- a/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsParamNative.cpp +++ b/tests/src/Interop/PInvoke/Delegate/MarshalDelegateAsParam/AsParamNative.cpp @@ -240,8 +240,6 @@ extern "C" DLL_EXPORT DelegateParam STDMETHODCALLTYPE ReturnDelegateByVal() * * * -----------------------------------------------------------------------------*/ -#import "mscorlib.tlb" no_namespace named_guids raw_interfaces_only rename("ReportEvent","ReportEventNew") - typedef struct{ int result1; int result2; @@ -290,24 +288,60 @@ BOOL STDMETHODCALLTYPE Verify(Result expectedR, Result resultR) && expectedR.result3 == resultR.result3; } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByValParam(_Delegate * p_dele) +HRESULT InvokeDelegate(IDispatch* dele) +{ + HRESULT hr; + BSTR bstrNames[1]; + bstrNames[0] = SysAllocString(L"DynamicInvoke"); + DISPID dispid = 0; + hr = dele->GetIDsOfNames( + IID_NULL, + bstrNames, + sizeof(bstrNames) / sizeof(bstrNames[0]), + GetUserDefaultLCID(), + &dispid); + + SysFreeString(bstrNames[0]); + + if (FAILED(hr)) + { + printf("\nERROR: Invoke failed: 0x%x\n", (unsigned int)hr); + return hr; + } + + DISPPARAMS params = { NULL, NULL, 0, 0 }; + + hr = dele->Invoke( + dispid, + IID_NULL, + GetUserDefaultLCID(), + DISPATCH_METHOD, + ¶ms, + NULL, + NULL, + NULL); + + return hr; +} + +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByValParam(IDispatch * p_dele) { ResetToZero(); HRESULT hr; - hr = p_dele->DynamicInvoke(NULL, NULL); + hr = InvokeDelegate(p_dele); if(FAILED(hr)) return FALSE; else return Verify(expected, result); } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByRefParam(_Delegate **pp_dele) +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByRefParam(IDispatch **pp_dele) { ResetToZero(); HRESULT hr; - hr = (*pp_dele)->DynamicInvoke(NULL, NULL); + hr = InvokeDelegate(*pp_dele); if(FAILED(hr)) { return FALSE; @@ -319,12 +353,12 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByRefParam(_Delegat } } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInValParam(_Delegate * p_dele) +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInValParam(IDispatch * p_dele) { ResetToZero(); HRESULT hr; - hr = p_dele->DynamicInvoke(NULL, NULL); + hr = InvokeDelegate(p_dele); if(FAILED(hr)) { return FALSE; @@ -335,12 +369,12 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInValParam(_Deleg } } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInRefParam(_Delegate **pp_dele) +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInRefParam(IDispatch **pp_dele) { ResetToZero(); HRESULT hr; - hr = (*pp_dele)->DynamicInvoke(NULL, NULL); + hr = InvokeDelegate(*pp_dele); if(FAILED(hr)) { return FALSE; @@ -352,12 +386,12 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInRefParam(_Deleg } } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByOutValParam(_Delegate * p_dele) +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByOutValParam(IDispatch * p_dele) { ResetToZero(); HRESULT hr; - hr = p_dele->DynamicInvoke(NULL, NULL); + hr = InvokeDelegate(p_dele); if(FAILED(hr)) { return FALSE; @@ -385,7 +419,7 @@ extern "C" DLL_EXPORT int STDMETHODCALLTYPE RetFieldResult3() return result.result3; } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByOutRefParam(_Delegate ** pp_dele, _Delegate * pdeleHelper) +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByOutRefParam(IDispatch ** pp_dele, IDispatch * pdeleHelper) { printf("In Take_DelegatePtrByOutRefParam native side \n"); ResetToZero(); @@ -402,12 +436,12 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByOutRefParam(_Dele } } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutValParam(_Delegate * p_dele) +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutValParam(IDispatch * p_dele) { ResetToZero(); HRESULT hr; - hr = p_dele->DynamicInvoke(NULL, NULL); + hr = InvokeDelegate(p_dele); if(FAILED(hr)) { return FALSE; @@ -418,12 +452,12 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutValParam(_De } } -extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutRefParam(_Delegate **pp_dele) +extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutRefParam(IDispatch **pp_dele) { ResetToZero(); HRESULT hr; - hr = (*pp_dele)->DynamicInvoke(NULL, NULL); + hr = InvokeDelegate(*pp_dele); if(FAILED(hr)) { return FALSE; @@ -435,7 +469,7 @@ extern "C" DLL_EXPORT BOOL STDMETHODCALLTYPE Take_DelegatePtrByInOutRefParam(_De } } -extern "C" DLL_EXPORT _Delegate* ReturnDelegatePtrByVal(_Delegate * pdeleHelper) +extern "C" DLL_EXPORT IDispatch* ReturnDelegatePtrByVal(IDispatch * pdeleHelper) { pdeleHelper->AddRef(); return pdeleHelper; |