* Opt COM methods out of the new Windows instance-method handling.
* Add test for an HResult "struct" returned from a COM method.
* Update ErrorMarshalTesting.cs
* Update "is member function" check on the ilmarshalers.h side to only consider thiscall.
BOOL fMarshalReturnValueFirst = FALSE;
BOOL fReverseWithReturnBufferArg = FALSE;
- bool isInstanceMethod = fStubNeedsCOM || fThisCall;
+ // Only consider ThisCall methods to be instance methods.
+ // Techinically COM methods are also instance methods, but we don't want to change the behavior of the built-in
+ // COM abi work because there are many users that rely on the current behavior (for example WPF).
+ bool isInstanceMethod = fThisCall;
// We can only change fMarshalReturnValueFirst to true when we are NOT doing HRESULT-swapping!
// When we are HRESULT-swapping, the managed return type is actually the type of the last parameter and not the return type.
bool byrefNativeReturn = false;
CorElementType typ = ELEMENT_TYPE_VOID;
UINT32 nativeSize = 0;
- bool nativeMethodIsMemberFunction = (m_pslNDirect->TargetHasThis() && IsCLRToNative(m_dwMarshalFlags))
- || (m_pslNDirect->HasThis() && !IsCLRToNative(m_dwMarshalFlags))
- || ((CorInfoCallConv)m_pslNDirect->GetStubTargetCallingConv() == CORINFO_CALLCONV_THISCALL);
+ bool nativeMethodIsMemberFunction = (CorInfoCallConv)m_pslNDirect->GetStubTargetCallingConv() == CORINFO_CALLCONV_THISCALL;
// we need to convert value type return types to primitives as
// JIT does not inline P/Invoke calls that return structures
foreach (var hr in hrs)
{
Assert.AreEqual(hr, this.server.Return_As_HResult(hr));
+ Assert.AreEqual(hr, this.server.Return_As_HResult_Struct(hr).hr);
}
}
}
this.Marshal_Float(a / 100f, b / 100f);
this.Marshal_Double(a / 100.0, b / 100.0);
this.Marshal_ManyInts();
- this.Marshal_Struct_Return();
}
static private bool EqualByBound(float expected, float actual)
Console.WriteLine($"{expected.GetType().Name} 12 test invariant: 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 = {expected}");
Assert.IsTrue(expected == this.server.Add_ManyInts12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12));
}
-
- private void Marshal_Struct_Return()
- {
- Console.WriteLine("Struct return from member function marshalling with struct > 4 bytes");
- {
- var width = 1.0f;
- var height = 2.0f;
- Server.Contract.SizeF result = this.server.MakeSize(width, height);
-
- Assert.AreEqual(width, result.width);
- Assert.AreEqual(height, result.height);
- }
- Console.WriteLine("Struct return from member function marshalling with struct <= 4 bytes");
- {
- byte width = 1;
- byte height = 2;
- Server.Contract.Size result = this.server.MakeSizeSmall(width, height);
-
- Assert.AreEqual(width, result.width);
- Assert.AreEqual(height, result.height);
- }
- Console.WriteLine("Struct return from member function marshalling with struct > 8 bytes");
- {
- var x = 1.0f;
- var y = 2.0f;
- var z = 3.0f;
- var w = 4.0f;
- Server.Contract.HFA_4 result = this.server.MakeHFA(x, y ,z, w);
- Assert.AreEqual(x, result.x);
- Assert.AreEqual(y, result.y);
- Assert.AreEqual(z, result.z);
- Assert.AreEqual(w, result.w);
- }
- }
}
}
{
return hresultToReturn;
}
-}
\ No newline at end of file
+
+ [PreserveSig]
+ public Server.Contract.HResult Return_As_HResult_Struct(int hresultToReturn)
+ {
+ return new Server.Contract.HResult { hr = hresultToReturn };
+ }
+}
{
return i1 + i2 + i3 + i4 + i5 + i6 + i7 + i8 + i9 + i10 + i11 + i12;
}
-
- public Server.Contract.SizeF MakeSize(float width, float height)
- {
- return new Server.Contract.SizeF { width = width, height = height };
- }
-
- public Server.Contract.Size MakeSizeSmall(byte width, byte height)
- {
- return new Server.Contract.Size { width = width, height = height };
- }
-
- public Server.Contract.HFA_4 MakeHFA(float x, float y, float z, float w)
- {
- return new Server.Contract.HFA_4 {x = x, y = y, z = z, w = w};
- }
}
THROW_FAIL_IF_FALSE(hr == hrMaybe);
}
}
+
+ void VerifyReturnHResultStruct(_In_ IErrorMarshalTesting *et)
+ {
+ ::printf("Verify preserved function signature\n");
+
+ HRESULT hrs[] =
+ {
+ E_NOTIMPL,
+ E_POINTER,
+ E_ACCESSDENIED,
+ E_INVALIDARG,
+ E_UNEXPECTED,
+ HRESULT{-1},
+ S_FALSE,
+ HRESULT{2}
+ };
+
+ for (int i = 0; i < ARRAYSIZE(hrs); ++i)
+ {
+ HRESULT hr = hrs[i];
+ HRESULT hrMaybe = et->Return_As_HResult_Struct(hr);
+ THROW_FAIL_IF_FALSE(hr == hrMaybe);
+ }
+ }
}
void Run_ErrorTests()
VerifyExpectedException(errorMarshal);
VerifyReturnHResult(errorMarshal);
+ VerifyReturnHResultStruct(errorMarshal);
}
THROW_IF_FAILED(numericTesting->Add_ManyInts12(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, &result));
THROW_FAIL_IF_FALSE(result == expected);
}
-
- void MarshalStructReturn(_In_ INumericTesting* numericTesting)
- {
- {
- ::printf("Marshal struct return type with size > 4 bytes\n");
- float width = 1.0f;
- float height = 2.0f;
- SizeF size = numericTesting->MakeSize(width, height);
- THROW_FAIL_IF_FALSE(width == size.width);
- THROW_FAIL_IF_FALSE(height == size.height);
- }
- {
- ::printf("Marshal struct return type with size < 4 bytes\n");
- BYTE width = 1;
- BYTE height = 2;
- Size size = numericTesting->MakeSizeSmall(width, height);
- THROW_FAIL_IF_FALSE(width == size.width);
- THROW_FAIL_IF_FALSE(height == size.height);
- }
- }
}
void Run_NumericTests()
MarshalFloat(numericTesting, (float)a / 100.f, (float)b / 100.f);
MarshalDouble(numericTesting, (double)a / 100.0, (double)b / 100.0);
MarshalManyInts(numericTesting);
- MarshalStructReturn(numericTesting);
}
return hresultToReturn;
}
+ int STDMETHODCALLTYPE Return_As_HResult_Struct(
+ /*[in]*/ int hresultToReturn)
+ {
+ return hresultToReturn;
+ }
+
public: // IUnknown
STDMETHOD(QueryInterface)(
/* [in] */ REFIID riid,
return S_OK;
}
- virtual COM_DECLSPEC_NOTHROW SizeF STDMETHODCALLTYPE MakeSize(
- /*[in]*/ float width,
- /*[in]*/ float height)
- {
- return { width, height };
- }
-
- virtual COM_DECLSPEC_NOTHROW Size STDMETHODCALLTYPE MakeSizeSmall(
- /*[in]*/ BYTE width,
- /*[in]*/ BYTE height)
- {
- return { width, height };
- }
-
- virtual COM_DECLSPEC_NOTHROW HFA_4 STDMETHODCALLTYPE MakeHFA(
- /*[in]*/ float x,
- /*[in]*/ float y,
- /*[in]*/ float z,
- /*[in]*/ float w
- )
- {
- return { x, y, z, w };
- }
-
public: // IUnknown
STDMETHOD(QueryInterface)(
/* [in] */ REFIID riid,
using System.Runtime.InteropServices;
using System.Text;
- public struct SizeF
- {
- public float width;
- public float height;
- }
-
- public struct Size
- {
- public byte width;
- public byte height;
- }
-
[ComVisible(true)]
[Guid("05655A94-A915-4926-815D-A9EA648BAAD9")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
int Add_ManyInts11(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11);
int Add_ManyInts12(int i1, int i2, int i3, int i4, int i5, int i6, int i7, int i8, int i9, int i10, int i11, int i12);
-
- [PreserveSig]
- SizeF MakeSize(float width, float height);
- [PreserveSig]
- Size MakeSizeSmall(byte width, byte height);
-
- [PreserveSig]
- HFA_4 MakeHFA(float x, float y, float z, float w);
}
[ComVisible(true)]
void Reverse_BStr_OutAttr([MarshalAs(UnmanagedType.BStr)] string a, [Out][MarshalAs(UnmanagedType.BStr)] string b);
}
+ public struct HResult
+ {
+ public int hr;
+ }
+
[ComVisible(true)]
[Guid("592386A5-6837-444D-9DE3-250815D18556")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[PreserveSig]
int Return_As_HResult(int hresultToReturn);
+
+ [PreserveSig]
+ HResult Return_As_HResult_Struct(int hresultToReturn);
}
public enum IDispatchTesting_Exception
#include <comdef.h>
-struct SizeF
-{
- float width;
- float height;
-};
-
-struct Size
-{
- BYTE width;
- BYTE height;
-};
-
struct HFA_4
{
float x;
/*[in]*/ int i11,
/*[in]*/ int i12,
/*[out]*/ int * result ) = 0;
- virtual COM_DECLSPEC_NOTHROW SizeF STDMETHODCALLTYPE MakeSize(
- /*[in]*/ float width,
- /*[in]*/ float height) = 0;
- virtual COM_DECLSPEC_NOTHROW Size STDMETHODCALLTYPE MakeSizeSmall(
- /*[in]*/ BYTE width,
- /*[in]*/ BYTE height) = 0;
- virtual COM_DECLSPEC_NOTHROW HFA_4 STDMETHODCALLTYPE MakeHFA(
- /*[in]*/ float x,
- /*[in]*/ float y,
- /*[in]*/ float z,
- /*[in]*/ float w) = 0;
};
struct __declspec(uuid("7731cb31-e063-4cc8-bcd2-d151d6bc8f43"))
/*[in]*/ int hresultToReturn ) = 0;
virtual int STDMETHODCALLTYPE Return_As_HResult (
/*[in]*/ int hresultToReturn ) = 0;
+ virtual int STDMETHODCALLTYPE Return_As_HResult_Struct (
+ /*[in]*/ int hresultToReturn ) = 0;
};
enum IDispatchTesting_Exception