From: Zeng Jiang Date: Fri, 16 Nov 2018 00:31:38 +0000 (+0800) Subject: Add PInvoke/SizeParamIndex tests (#19348) X-Git-Tag: accepted/tizen/unified/20190422.045933~634 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=243116831430aa73338b05cdeba94bbd347df0fe;p=platform%2Fupstream%2Fcoreclr.git Add PInvoke/SizeParamIndex tests (#19348) * Add PInvoke/SizeParamIndex tests * Fix compile warnings * First pass cleaning up native code. * Get ParamSizeIndex tests working xplat (excluding the BSTR array tests) * Fix incorrect definition of ULONG off-windows. * Disable reverse-PInvoke throwing test off-Windows. --- diff --git a/tests/src/Common/Platform/platformdefines.h b/tests/src/Common/Platform/platformdefines.h index 1cc334c..e1e84b6 100644 --- a/tests/src/Common/Platform/platformdefines.h +++ b/tests/src/Common/Platform/platformdefines.h @@ -39,7 +39,7 @@ typedef const WCHAR *LPCWSTR, *PCWSTR; typedef int HRESULT; #define LONGLONG long long #define ULONGLONG unsigned LONGLONG -typedef unsigned long ULONG, *PULONG; +typedef unsigned int ULONG, *PULONG; #define S_OK 0x0 #define SUCCEEDED(_hr) ((HRESULT)(_hr) >= 0) #define FAILED(_hr) ((HRESULT)(_hr) < 0) diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt index 9825873..5d9c27b 100644 --- a/tests/src/Interop/CMakeLists.txt +++ b/tests/src/Interop/CMakeLists.txt @@ -18,6 +18,10 @@ add_subdirectory(PInvoke/BestFitMapping/LPStr) add_subdirectory(PInvoke/Delegate/MarshalDelegateAsField) add_subdirectory(PInvoke/Delegate/MarshalDelegateAsParam) add_subdirectory(PInvoke/Primitives/Int) +add_subdirectory(PInvoke/SizeParamIndex/PInvoke/PassingByOut) +add_subdirectory(PInvoke/SizeParamIndex/PInvoke/PassingByRef) +add_subdirectory(PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut) +add_subdirectory(PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef) add_subdirectory(PInvoke/Array/MarshalArrayAsField/LPArrayNative) add_subdirectory(PInvoke/Array/MarshalArrayAsParam/LPArrayNative) add_subdirectory(PInvoke/Miscellaneous/HandleRef) diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/CMakeLists.txt b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/CMakeLists.txt new file mode 100644 index 0000000..90058da --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required (VERSION 2.6) +project (PInvokePassingByOutNative) +include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") +include_directories("..") +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES + PInvokePassingByOutNative.cpp +) +# add the executable +add_library (PInvokePassingByOutNative SHARED ${SOURCES}) +target_link_libraries(PInvokePassingByOutNative ${LINK_LIBRARIES_ADDITIONAL}) +# add the install targets +install (TARGETS PInvokePassingByOutNative DESTINATION bin) diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/PInvokePassingByOutNative.cpp b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/PInvokePassingByOutNative.cpp new file mode 100644 index 0000000..5b3e9b6 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/PInvokePassingByOutNative.cpp @@ -0,0 +1,100 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// PInvokePassingByOutNative.cpp : Defines the entry point for the DLL application. +// +#include +#include +#include "platformdefines.h" +#include "helper.h" + +//##################################################################### +//ByOut Array, ByRef SizeParamIndex +//##################################################################### + +//BYTE 0 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayByte_AsByOut_AsSizeParamIndex(BYTE* arrSize, BYTE** ppActual) +{ + return CheckAndChangeArrayByOut(ppActual, arrSize, (BYTE)1); +} + +//CHAR 1 ==> CHAR.Max size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArraySbyte_AsByOut_AsSizeParamIndex(CHAR* arrSize, CHAR** ppActual) +{ + return CheckAndChangeArrayByOut(ppActual, arrSize, (CHAR)SCHAR_MAX); +} + +//SHORT -1 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayShort_AsByOut_AsSizeParamIndex(/*out*/SHORT* arrSize, SHORT** ppActual) +{ + short shortArray_Size = 16384;//SHRT_MAX+1/2 + + *ppActual = (SHORT*)CoreClrAlloc(sizeof(SHORT)*shortArray_Size); + + *arrSize = shortArray_Size; + + for(SHORT i = 0; i < shortArray_Size; ++i) + { + (*ppActual)[i] = shortArray_Size - 1 - i; + } + return TRUE; +} + +//SHORT 10 ==> -1 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayShortReturnNegative_AsByOut_AsSizeParamIndex(SHORT* arrSize, SHORT** ppActual) +{ + *ppActual = (SHORT*)CoreClrAlloc(sizeof(SHORT)*CArray_Size); + *arrSize = -1; + + for(SHORT i = 0; i < CArray_Size; ++i) + { + (*ppActual)[i] = CArray_Size - 1 - i; + } + return TRUE; +} + +//USHORT ? ==> ushort.Max ==> size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayUshort_AsByOut_AsSizeParamIndex(USHORT** ppActual, USHORT* arrSize) +{ + return CheckAndChangeArrayByOut(ppActual, arrSize, (USHORT)USHRT_MAX); +} + +//Int32 ? ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayInt_AsByOut_AsSizeParamIndex(LONG* arrSize,LONG** ppActual) +{ + return CheckAndChangeArrayByOut(ppActual, arrSize, (LONG)0); +} + +//ULONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayUInt_AsByOut_AsSizeParamIndex(ULONG* arrSize, ULONG** ppActual) +{ + return CheckAndChangeArrayByOut(ppActual, arrSize, (ULONG)20); +} + +//LONGLONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayLong_AsByOut_AsSizeParamIndex(LONGLONG* arrSize, LONGLONG** ppActual) +{ + return CheckAndChangeArrayByOut(ppActual, arrSize, (LONGLONG)20); +} + +//ULONGLONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayUlong_AsByOut_AsSizeParamIndex(ULONGLONG** ppActual,ULONGLONG* arrSize,ULONGLONG _unused) +{ + return CheckAndChangeArrayByOut(ppActual, arrSize, (ULONGLONG)1000); +} +#ifdef _WIN32 +//String 10 size Array ==> BSTR 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayString_AsByOut_AsSizeParamIndex(BSTR** ppBSTR,short* arrSize) +{ + *ppBSTR = (BSTR*)CoreClrAlloc(sizeof(BSTR)*CArray_Size); + for(int i = 0;i +/// Pass Array Size by out keyword using SizeParamIndex Attributes +/// +public class ClientMarshalArrayAsSizeParamIndexByOutTest +{ + + #region ByOut + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayByte_AsByOut_AsSizeParamIndex( + out byte arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out byte[] arrByte); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArraySbyte_AsByOut_AsSizeParamIndex( + out sbyte arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out sbyte[] arrSbyte); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayShort_AsByOut_AsSizeParamIndex( + out short arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out short[] arrShort); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayShortReturnNegative_AsByOut_AsSizeParamIndex( + out short arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out short[] arrShort); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayUshort_AsByOut_AsSizeParamIndex( + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out ushort[] arrUshort, out ushort arrSize); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayInt_AsByOut_AsSizeParamIndex( + out Int32 arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out Int32[] arrInt32); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayUInt_AsByOut_AsSizeParamIndex( + out UInt32 arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out UInt32[] arrUInt32); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayLong_AsByOut_AsSizeParamIndex( + out long arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out long[] arrLong); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayUlong_AsByOut_AsSizeParamIndex( + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out ulong[] arrUlong, out ulong arrSize, ulong unused); + + [DllImport("PInvokePassingByOutNative")] + private static extern bool MarshalCStyleArrayString_AsByOut_AsSizeParamIndex( + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1, ArraySubType = UnmanagedType.BStr)] out string[] arrInt32, out int arrSize); + + #endregion + + static void SizeParamTypeIsByte() + { + string strDescription = "Scenario(byte ==> BYTE): Array_Size(N->M) = 1"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + byte byte_Array_Size; + byte[] arrByte; + Assert.IsTrue(MarshalCStyleArrayByte_AsByOut_AsSizeParamIndex(out byte_Array_Size, out arrByte)); + + //Construct Expected array + int expected_ByteArray_Size = 1; + byte[] expectedArrByte = Helper.GetExpChangeArray(expected_ByteArray_Size); + Assert.IsTrue(Helper.EqualArray(arrByte, (int)byte_Array_Size, expectedArrByte, (int)expectedArrByte.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsSByte() + { + string strDescription = "Scenario(sbyte ==> CHAR):Array_Size(N->M) = sbyte.Max"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + sbyte sbyte_Array_Size; + sbyte[] arrSbyte; + Assert.IsTrue(MarshalCStyleArraySbyte_AsByOut_AsSizeParamIndex(out sbyte_Array_Size, out arrSbyte)); + + sbyte[] expectedArrSbyte = Helper.GetExpChangeArray(sbyte.MaxValue); + Assert.IsTrue(Helper.EqualArray(arrSbyte, (int)sbyte_Array_Size, expectedArrSbyte, (int)expectedArrSbyte.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsShort1() + { + string strDescription = "Scenario(short ==> SHORT)1,Array_Size(M->N) = -1, Array_Size(N->M)=(ShortMax+1)/2"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + short shortArray_Size = (short)-1; + short[] arrShort = Helper.InitArray(10); + Assert.IsTrue(MarshalCStyleArrayShort_AsByOut_AsSizeParamIndex(out shortArray_Size, out arrShort)); + + //Construct Expected Array + int expected_ShortArray_Size = 16384;//(SHRT_MAX+1)/2 + short[] expectedArrShort = Helper.GetExpChangeArray(expected_ShortArray_Size); + Assert.IsTrue(Helper.EqualArray(arrShort, (int)shortArray_Size, expectedArrShort, (int)expectedArrShort.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsShort2() + { + string strDescription = "Scenario(short ==> SHORT)2, Array_Size = 10, Array_Size(N->M) = -1"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + short short_Array_Size = (short)10; + short[] arrShort = Helper.InitArray(short_Array_Size); + Assert.Throws(() => MarshalCStyleArrayShortReturnNegative_AsByOut_AsSizeParamIndex(out short_Array_Size, out arrShort)); + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsUShort() + { + string strDescription = "Scenario(ushort==>USHORT): Array_Size(N->M) = ushort.MaxValue"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + ushort ushort_Array_Size; + ushort[] arrUshort; + Assert.IsTrue(MarshalCStyleArrayUshort_AsByOut_AsSizeParamIndex(out arrUshort, out ushort_Array_Size)); + + //Expected Array + ushort[] expectedArrUshort = Helper.GetExpChangeArray(ushort.MaxValue); + Assert.IsTrue(Helper.EqualArray(arrUshort, (int)ushort_Array_Size, expectedArrUshort, (ushort)expectedArrUshort.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsInt32() + { + string strDescription = "Scenario(Int32 ==> LONG): Array_Size(N->M) = 0 "; + + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + Int32 Int32_Array_Size; + Int32[] arrInt32; + Assert.IsTrue(MarshalCStyleArrayInt_AsByOut_AsSizeParamIndex(out Int32_Array_Size, out arrInt32)); + + //Expected Array + Int32[] expectedArrInt32 = Helper.GetExpChangeArray(0); + Assert.IsTrue(Helper.EqualArray(arrInt32, Int32_Array_Size, expectedArrInt32, expectedArrInt32.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsUInt32() + { + string strDescription = "Scenario(UInt32 ==> ULONG): Array_Size(N->M) = 20"; + + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + int expected_UInt32ArraySize = 20; + + UInt32 UInt32_Array_Size = (UInt32)10; + UInt32[] arrUInt32 = Helper.InitArray((Int32)UInt32_Array_Size); + Assert.IsTrue(MarshalCStyleArrayUInt_AsByOut_AsSizeParamIndex(out UInt32_Array_Size, out arrUInt32)); + + //Construct expected + UInt32[] expectedArrUInt32 = Helper.GetExpChangeArray(expected_UInt32ArraySize); + Assert.IsTrue(Helper.EqualArray(arrUInt32, (Int32)UInt32_Array_Size, expectedArrUInt32, (Int32)expectedArrUInt32.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsLong() + { + string strDescription = "Scenario(long ==> LONGLONG): Array_Size(N->M) = 20"; + + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + int expected_LongArraySize = 20; + + long long_Array_Size = (long)10; + long[] arrLong = Helper.InitArray((Int32)long_Array_Size); + Assert.IsTrue(MarshalCStyleArrayLong_AsByOut_AsSizeParamIndex(out long_Array_Size, out arrLong)); + + long[] expectedArrLong = Helper.GetExpChangeArray(expected_LongArraySize); + Assert.IsTrue(Helper.EqualArray(arrLong, (Int32)long_Array_Size, expectedArrLong, (Int32)expectedArrLong.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsULong() + { + string strDescription = "Scenario(ulong ==> ULONGLONG): Array_Size(N->M) = 1000"; + + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + int expected_ULongArraySize = 1000; + + ulong ulong_Array_Size = (ulong)10; + ulong[] arrUlong = Helper.InitArray((Int32)ulong_Array_Size); + Assert.IsTrue(MarshalCStyleArrayUlong_AsByOut_AsSizeParamIndex(out arrUlong, out ulong_Array_Size, ulong_Array_Size)); + + ulong[] expectedArrUlong = Helper.GetExpChangeArray(expected_ULongArraySize); + Assert.IsTrue(Helper.EqualArray(arrUlong, (Int32)ulong_Array_Size, expectedArrUlong, (Int32)expectedArrUlong.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsString() + { + string strDescription = "Scenario(String ==> BSTR): Array_Size(N->M) = 20"; + + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + int expected_StringArraySize = 20; + int string_Array_Size = 10; + String[] arrString = Helper.InitArray(string_Array_Size); + Assert.IsTrue(MarshalCStyleArrayString_AsByOut_AsSizeParamIndex(out arrString, out string_Array_Size)); + + String[] expArrString = Helper.GetExpChangeArray(expected_StringArraySize); + Assert.IsTrue(Helper.EqualArray(arrString, string_Array_Size, expArrString, expArrString.Length)); + Console.WriteLine(strDescription + " Ends!"); + } + + static int Main() + { + try{ + SizeParamTypeIsByte(); + SizeParamTypeIsSByte(); + SizeParamTypeIsShort1(); + SizeParamTypeIsShort2(); + SizeParamTypeIsUShort(); + SizeParamTypeIsInt32(); + SizeParamTypeIsUInt32(); + SizeParamTypeIsLong(); + SizeParamTypeIsULong(); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + SizeParamTypeIsString(); + } + return 100; + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/PassingByOutTest.csproj b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/PassingByOutTest.csproj new file mode 100644 index 0000000..5344935 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByOut/PassingByOutTest.csproj @@ -0,0 +1,35 @@ + + + + + Debug + AnyCPU + PassingByOutTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/CMakeLists.txt b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/CMakeLists.txt new file mode 100644 index 0000000..f3349b1 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/CMakeLists.txt @@ -0,0 +1,13 @@ +cmake_minimum_required (VERSION 2.6) +project (PInvokePassingByRefNative) +include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") +include_directories("..") +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES + PInvokePassingByRefNative.cpp +) +# add the executable +add_library (PInvokePassingByRefNative SHARED ${SOURCES}) +target_link_libraries(PInvokePassingByRefNative ${LINK_LIBRARIES_ADDITIONAL}) +# add the install targets +install (TARGETS PInvokePassingByRefNative DESTINATION bin) diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PInvokePassingByRefNative.cpp b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PInvokePassingByRefNative.cpp new file mode 100644 index 0000000..e0ac16e --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PInvokePassingByRefNative.cpp @@ -0,0 +1,133 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// PInvokePassingByRefNative.cpp : Defines the entry point for the DLL application. +// +#include +#include +#include "helper.h" + +//##################################################################### +//ByRef Array, ByRef SizeParamIndex +//##################################################################### + +//BYTE 1 ==> 0 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayByte_AsByRef_AsSizeParamIndex(BYTE* arrSize, BYTE** ppActual) +{ + return CheckAndChangeArrayByRef(ppActual, arrSize, (BYTE)1, (BYTE)0); +} + +//CHAR 10 ==> CHAR.Max size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArraySbyte_AsByRef_AsSizeParamIndex(CHAR* arrSize, CHAR** ppActual) +{ + return CheckAndChangeArrayByRef(ppActual, arrSize, (CHAR)10, (CHAR)CHAR_MAX); +} + +//SHORT -1 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayShort_AsByRef_AsSizeParamIndex(SHORT* arrSize, SHORT** ppActual) +{ + if(*arrSize != -1) + { + printf("%s,ManagedtoNative Error!\n",__FUNCTION__); + printf("arrSize != -1"); + return FALSE; + } + + SHORT* pExpectedArr = InitArray((SHORT)Array_Size); + + if(!EqualArray(*ppActual, (SHORT)Array_Size, pExpectedArr, (SHORT)Array_Size)) + { + printf("%s,ManagedtoNative Error!\n",__FUNCTION__); + return FALSE; + } + + CoreClrFree(*ppActual); + *ppActual = (SHORT*)CoreClrAlloc(sizeof(SHORT)*CArray_Size); + + *arrSize = CArray_Size; + + for(SHORT i = 0; i < CArray_Size; ++i) + { + (*ppActual)[i] = CArray_Size - 1 - i; + } + return TRUE; +} + +//SHORT 10 ==> -1 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayShortReturnNegative_AsByRef_AsSizeParamIndex(SHORT* arrSize, SHORT** ppActual) +{ + SHORT* pExpectedArr = InitArray((SHORT)Array_Size); + + if(!EqualArray(*ppActual, (SHORT)Array_Size, pExpectedArr, (SHORT)Array_Size)) + { + printf("%s,ManagedtoNative Error!\n",__FUNCTION__); + return FALSE; + } + + CoreClrFree(*ppActual); + *ppActual = (SHORT*)CoreClrAlloc(sizeof(SHORT)*CArray_Size); + + *arrSize = (SHORT)-1; + + for(SHORT i = 0; i < CArray_Size; ++i) + { + (*ppActual)[i] = CArray_Size - 1 - i; + } + return TRUE; +} + +//USHORT 20 ==> ushort.Max size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayUshort_AsByRef_AsSizeParamIndex(USHORT** ppActual, USHORT* arrSize) +{ + return CheckAndChangeArrayByRef(ppActual, arrSize, (USHORT)20, (USHORT)65535); +} + +//Int32 10 ==> 1 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayInt_AsByRef_AsSizeParamIndex(LONG* arrSize,LONG unused,LONG** ppActual) +{ + return CheckAndChangeArrayByRef(ppActual, arrSize, (LONG)10, (LONG)1); +} + +//ULONG 1234 ==> 4321 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayUInt_AsByRef_AsSizeParamIndex(ULONG** ppActual,ULONG unused, ULONG* arrSize) +{ + return CheckAndChangeArrayByRef(ppActual, arrSize, (ULONG)1234, (ULONG)4321); +} + +//LONGLONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayLong_AsByRef_AsSizeParamIndex(LONGLONG* arrSize, LONGLONG** ppActual) +{ + return CheckAndChangeArrayByRef(ppActual, arrSize, (LONGLONG)10, (LONGLONG)20); +} + +//ULONGLONG 0 ==> 0 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayUlong_AsByRef_AsSizeParamIndex(ULONGLONG* arrSize, ULONGLONG** ppActual) +{ + return CheckAndChangeArrayByRef(ppActual, arrSize, (ULONGLONG)0, (ULONGLONG)0); +} +#ifdef _WIN32 +//String size Array 20 ==> BSTR 10 size Array +extern "C" DLL_EXPORT BOOL __stdcall MarshalCStyleArrayString_AsByRef_AsSizeParamIndex(short* arrSize, BSTR** ppBSTR,char *** pppStr) +{ + BSTR* pExpectedArr = InitArrayBSTR(20); + + if(!EqualArrayBSTR(*ppBSTR,*arrSize,pExpectedArr,20)) + { + printf("%s,ManagedtoNative Error!\n",__FUNCTION__); + return FALSE; + } + + CoreClrFree(*ppBSTR); + + *ppBSTR = (BSTR*)CoreClrAlloc(sizeof(BSTR)*10); + for(int i = 0;i<10;++i) + { + (*ppBSTR)[i] = ToBSTR(10 - 1 - i); + } + + *arrSize = 10; + + return TRUE; +} +#endif diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PassingByRefTest.cs b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PassingByRefTest.cs new file mode 100644 index 0000000..c562e13 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PassingByRefTest.cs @@ -0,0 +1,265 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using TestLibrary; + +/// +/// Pass LPArray Size by ref keyword using SizeParamIndex Attributes +/// + +public class ClientMarshalArrayAsSizeParamIndexByRefTest +{ + + #region ByRef + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayByte_AsByRef_AsSizeParamIndex( + ref byte arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref byte[] arrByte); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArraySbyte_AsByRef_AsSizeParamIndex( + ref sbyte arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref sbyte[] arrSbyte); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayShort_AsByRef_AsSizeParamIndex( + ref short arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref short[] arrShort); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayShortReturnNegative_AsByRef_AsSizeParamIndex( + ref short arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref short[] arrShort); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayUshort_AsByRef_AsSizeParamIndex( + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ushort[] arrUshort, ref ushort arrSize); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayInt_AsByRef_AsSizeParamIndex( + ref Int32 arrSize, Int32 unused, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref Int32[] arrInt32); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayUInt_AsByRef_AsSizeParamIndex( + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 2)] ref UInt32[] arrUInt32, UInt32 unused, ref UInt32 arrSize); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayLong_AsByRef_AsSizeParamIndex( + ref long arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref long[] arrLong); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayUlong_AsByRef_AsSizeParamIndex( + ref ulong arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref ulong[] arrUlong); + + [DllImport("PInvokePassingByRefNative")] + private static extern bool MarshalCStyleArrayString_AsByRef_AsSizeParamIndex( + ref int arrSize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, ArraySubType = UnmanagedType.BStr)] ref string[] arrStr, + [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0, ArraySubType = UnmanagedType.LPStr)] ref string[] arrStr2); + + #endregion + + static void SizeParamTypeIsByte() + { + string strDescription = "Scenario(byte==>BYTE):Array_Size(M->N)=1,Array_Size(N->M)= byte.MinValue"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + byte byte_Array_Size = 1; + byte[] arrByte = Helper.InitArray(byte_Array_Size); + Assert.IsTrue(MarshalCStyleArrayByte_AsByRef_AsSizeParamIndex(ref byte_Array_Size, ref arrByte)); + + //Construct Expected array + int expected_ByteArray_Size = Byte.MinValue; + byte[] expectedArrByte = Helper.GetExpChangeArray(expected_ByteArray_Size); + Assert.IsTrue(Helper.EqualArray(arrByte, (int)byte_Array_Size, expectedArrByte, (int)expectedArrByte.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsSByte() + { + string strDescription = "Scenario(sbyte==>CHAR): Array_Size(M->N) = 10, Array_Size(N->M) = sbyte.Max"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + sbyte sbyte_Array_Size = (sbyte)10; + sbyte[] arrSbyte = Helper.InitArray(sbyte_Array_Size); + + Assert.IsTrue(MarshalCStyleArraySbyte_AsByRef_AsSizeParamIndex(ref sbyte_Array_Size, ref arrSbyte)); + + //Construct Expected + sbyte[] expectedArrSbyte = Helper.GetExpChangeArray(sbyte.MaxValue); + Assert.IsTrue(Helper.EqualArray(arrSbyte, (int)sbyte_Array_Size, expectedArrSbyte, (int)sbyte.MaxValue)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsShort1() + { + string strDescription = "Scenario(short==>SHORT)1: Array_Size(M->N) = -1, Array_Size(N->M) = 20"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + short short_Array_Size = (short)-1; + short[] arrShort = Helper.InitArray(10); + int expected_ByteArraySize = 20; + + Assert.IsTrue(MarshalCStyleArrayShort_AsByRef_AsSizeParamIndex(ref short_Array_Size, ref arrShort)); + + //Construct Expected + short[] expectedArrShort = Helper.GetExpChangeArray(expected_ByteArraySize); + Assert.IsTrue(Helper.EqualArray(arrShort, (int)short_Array_Size, expectedArrShort, expectedArrShort.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsShort2() + { + string strDescription = "Scenario(short==>SHORT)2: Array_Size(M->N) = 10, Array_Size(N->M) = -1"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + short short_Array_Size = (short)10; + short[] arrShort = Helper.InitArray(10); + Assert.Throws(() => MarshalCStyleArrayShortReturnNegative_AsByRef_AsSizeParamIndex(ref short_Array_Size, ref arrShort)); + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsUShort() + { + string strDescription = "Scenario(ushort==>USHORT): Array_Size(M->N) = 0, Array_Size(N->M) = ushort.MaxValue"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + ushort ushort_Array_Size = 20; + ushort[] arrUshort = Helper.InitArray(ushort_Array_Size); + + int expected_UshortArraySize = ushort.MaxValue; + Assert.IsTrue(MarshalCStyleArrayUshort_AsByRef_AsSizeParamIndex(ref arrUshort, ref ushort_Array_Size)); + + //Construct Expected + ushort[] expectedArrShort = Helper.GetExpChangeArray(expected_UshortArraySize); + Assert.IsTrue(Helper.EqualArray(arrUshort, (int)ushort_Array_Size, expectedArrShort, expectedArrShort.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsInt32() + { + string strDescription = "Scenario(Int32==>LONG):Array_Size(M->N)=10, Array_Size(N->M)=1"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + Int32 Int32_Array_Size = (Int32)10; + Int32[] arrInt32 = Helper.InitArray(Int32_Array_Size); + + Assert.IsTrue(MarshalCStyleArrayInt_AsByRef_AsSizeParamIndex(ref Int32_Array_Size, Int32.MaxValue, ref arrInt32)); + + //Construct Expected + int expected_UshortArraySize = 1; + Int32[] expectedArrInt32 = Helper.GetExpChangeArray(expected_UshortArraySize); + Assert.IsTrue(Helper.EqualArray(arrInt32, Int32_Array_Size, expectedArrInt32, expectedArrInt32.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsUInt32() + { + string strDescription = "Scenario(UInt32==>ULONG):Array_Size(M->N)=1234,Array_Size(N->M)=4321"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + UInt32 UInt32_Array_Size = (UInt32)1234; + UInt32[] arrUInt32 = Helper.InitArray((Int32)UInt32_Array_Size); + Assert.IsTrue(MarshalCStyleArrayUInt_AsByRef_AsSizeParamIndex(ref arrUInt32, 1234, ref UInt32_Array_Size)); + + //Construct Expected + int expected_UInt32ArraySize = 4321; + UInt32[] expectedArrUInt32 = Helper.GetExpChangeArray(expected_UInt32ArraySize); + Assert.IsTrue(Helper.EqualArray(arrUInt32, (Int32)UInt32_Array_Size, expectedArrUInt32, (Int32)expectedArrUInt32.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsLong() + { + string strDescription = "Scenario(long==>LONGLONG):Array_Size(M->N)=10,Array_Size(N->M)=20"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + long long_Array_Size = (long)10; + long[] arrLong = Helper.InitArray((Int32)long_Array_Size); + Assert.IsTrue(MarshalCStyleArrayLong_AsByRef_AsSizeParamIndex(ref long_Array_Size, ref arrLong)); + + //Construct Expected Array + int expected_LongArraySize = 20; + long[] expectedArrLong = Helper.GetExpChangeArray(expected_LongArraySize); + Assert.IsTrue(Helper.EqualArray(arrLong, (Int32)long_Array_Size, expectedArrLong, (Int32)expectedArrLong.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsULong() + { + string strDescription = "Scenario(ulong==>ULONGLONG):Array_Size(M->N)=0, Array_Size(N->M)=0"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + ulong ulong_Array_Size = (ulong)0; + ulong[] arrUlong = Helper.InitArray((Int32)ulong_Array_Size); + + Assert.IsTrue(MarshalCStyleArrayUlong_AsByRef_AsSizeParamIndex(ref ulong_Array_Size, ref arrUlong)); + + //Construct Expected + int expected_ULongArraySize = 0; + ulong[] expectedArrUlong = Helper.GetExpChangeArray(expected_ULongArraySize); + Assert.IsTrue(Helper.EqualArray(arrUlong, (Int32)ulong_Array_Size, expectedArrUlong, (Int32)expectedArrUlong.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static void SizeParamTypeIsString() + { + string strDescription = "Scenario(String==>BSTR):Array_Size(M->N)= 20, Array_Size(N->M)=10"; + Console.WriteLine(); + Console.WriteLine(strDescription + " Starts!"); + + int array_Size = 20; + String[] arrString = Helper.InitArray(array_Size); + String[] arrString2 = Helper.InitArray(array_Size); + + Assert.IsTrue(MarshalCStyleArrayString_AsByRef_AsSizeParamIndex(ref array_Size, ref arrString, ref arrString2)); + + //Construct Expected + int expected_StringArraySize = 10; + String[] expArrString = Helper.GetExpChangeArray(expected_StringArraySize); + Assert.IsTrue(Helper.EqualArray(arrString, array_Size, expArrString, expArrString.Length)); + + Console.WriteLine(strDescription + " Ends!"); + } + + static int Main() + { + try{ + SizeParamTypeIsByte(); + SizeParamTypeIsSByte(); + SizeParamTypeIsShort1(); + SizeParamTypeIsShort2(); + SizeParamTypeIsUShort(); + SizeParamTypeIsInt32(); + SizeParamTypeIsUInt32(); + SizeParamTypeIsLong(); + SizeParamTypeIsULong(); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + SizeParamTypeIsString(); + } + return 100; + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PassingByRefTest.csproj b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PassingByRefTest.csproj new file mode 100644 index 0000000..349b063 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/PassingByRef/PassingByRefTest.csproj @@ -0,0 +1,35 @@ + + + + + Debug + AnyCPU + PassingByRefTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/helper.cs b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/helper.cs new file mode 100644 index 0000000..7074c9e --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/helper.cs @@ -0,0 +1,85 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +public class Helper +{ + + #region General method + + public static T[] InitArray(int arrSize) + { + T[] array = new T[arrSize]; + for (int i = 0; i < array.Length; i++) + { + array[i] = (T)Convert.ChangeType(i, typeof(T)); + } + return array; + } + + public static bool EqualArray(T[] actualArray, int actualSize, T[] expectedArray, int expectedSize) + { + int failures = 0; + if (actualArray == null && expectedArray == null) + { + Console.WriteLine("\tTwo array are equal.Both of them null"); + return true; + } + else if (actualArray == null && expectedArray != null) + { + Console.WriteLine("\tTwo array are not equal.The sourcArr is null,but the expectedArray is not null"); + return false; + } + else if (actualArray != null && expectedArray == null) + { + Console.WriteLine("\tTwo array are not equal.The sourcArr is not null but the expectedArray is null"); + return false; + } + else if (!actualSize.Equals(expectedSize)) + { + Console.WriteLine("\tTwo array are not equal.The sizes are not equal:Expected:{0},Actaul:{1}", expectedSize, actualSize); + return false; + } + for (int i = 0; i < expectedSize; ++i) + { + if (!actualArray[i].Equals(expectedArray[i])) + { + Console.WriteLine("\tTwo array are not equal.The values of index {0} are not equal!", i); + Console.WriteLine("\t\tThe actualArray is {0},the expectedArray is {1}", actualArray[i].ToString(), expectedArray[i].ToString()); + failures++; + } + } + if (failures > 0) + return false; + return true; + } + + public static T[] GetExpChangeArray(int cSize) + { + T[] array = new T[cSize]; + + for (int i = array.Length - 1; i >= 0; --i) + array[i] = (T)Convert.ChangeType(array.Length - 1 - i, typeof(T)); + + return array; + } + + public static bool CheckAndChangeArray(ref T[] arrArg, ref T arrSize, int actualArrSize, int expectedArrSize) + { + T[] actualArr = InitArray(actualArrSize); + if (!EqualArray(arrArg, actualArrSize, actualArr, actualArrSize)) + { + return false; + } + + arrSize = (T)Convert.ChangeType(expectedArrSize, typeof(T)); + arrArg = GetExpChangeArray(expectedArrSize); + return true; + } + + #endregion + +} \ No newline at end of file diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/helper.h b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/helper.h new file mode 100644 index 0000000..ca93822 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/PInvoke/helper.h @@ -0,0 +1,225 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// helper.h : Defines helper functions +#include +#include "platformdefines.h" + + +const LONG Array_Size = 10; +const LONG CArray_Size = 20; + +////////////////////////////////////////////////////////////////////////////// +// Verify helper methods +////////////////////////////////////////////////////////////////////////////// +template BOOL IsObjectEquals(T o1, T o2) +{ + // T::operator== required. + return o1 == o2; +} + +//Int32 helper +template +T* InitArray(SIZE_T arrSize) +{ + T* pExpectArr = (T*)CoreClrAlloc(sizeof(T)*arrSize); + for(SIZE_T i = 0;i +T* InitExpectedArray(SIZE_T arrSize) +{ + T* pExpectArr = (T*)CoreClrAlloc(sizeof(T)*arrSize); + for(SIZE_T i = 0;i +BOOL EqualArray(T* actualArray, SIZE_T actualSize, T* expectedArray, SIZE_T expectedSize) +{ + int failures = 0; + + if(actualArray == NULL && expectedArray == NULL) + { + printf("Two arrays are equal. Both of them are NULL\n"); + return TRUE; + } + else if(actualArray == NULL && expectedArray != NULL) + { + printf("Two arrays aren't equal. Array from Managed to Native is NULL,but the Compared is not NULL!\n"); + return FALSE; + } + else if(actualArray != NULL && expectedArray == NULL) + { + printf("Two arrays aren't equal. Array from Managed to Native is not NULL,but the Compared is NULL!\n"); + return FALSE; + } + else if(actualSize != expectedSize) + { + printf("Two arrays aren't equal. The arrays size are not equal. Expected:%d, Actual:%d!\n",(int)expectedSize,(int)actualSize); + return FALSE; + } + for(SIZE_T i = 0;i0) + return FALSE; + return TRUE; +} + +template +BOOL CheckAndChangeArrayByRef(T ** ppActual, T* Actual_Array_Size, SIZE_T Expected_Array_Size, SIZE_T Return_Array_Size) +{ + T* pExpectedArr = InitArray(Expected_Array_Size); + if(!EqualArray(*ppActual, (SIZE_T)*Actual_Array_Size, pExpectedArr, Expected_Array_Size)) + { + printf("ManagedtoNative Error in Method: %s!\n",__FUNCTION__); + return FALSE; + } + + CoreClrFree(pExpectedArr); + CoreClrFree(*ppActual); + *ppActual = (T*)CoreClrAlloc(sizeof(T)*Return_Array_Size); + + *Actual_Array_Size = ((T)Return_Array_Size); + for(SIZE_T i = 0; i < Return_Array_Size; ++i) + { + (*ppActual)[i] = (T)(Return_Array_Size - 1 - i); + } + return TRUE; +} + +template +BOOL CheckAndChangeArrayByOut(T ** ppActual, T* Actual_Array_Size, SIZE_T Array_Size) +{ + *ppActual = (T*)CoreClrAlloc(sizeof(T)*Array_Size); + *Actual_Array_Size = ((T)Array_Size); + + for(SIZE_T i = 0; i < Array_Size; ++i) + { + (*ppActual)[i] = (T)(Array_Size - 1 - i); + } + return TRUE; +} + +//template +//BOOL CheckReturnArray(T* pReturnArr, T Actual_Array_Size, T Expected_Array_Size) +//{ +// T* pExpectedArr = InitExpectedArray(Expected_Array_Size); +// +// if(!EqualArray(pReturnArr, Actual_Array_Size, pExpectedArr, Expected_Array_Size)) +// { +// printf("ManagedtoNative Error in Method: %s!\n",__FUNCTION__); +// CoreClrFree(pExpectedArr); +// return FALSE; +// } +// else +// { +// //printf("Managed to Native:Passed!\n"); +// CoreClrFree(pExpectedArr); +// return TRUE; +// } +//} + +//BSTR helper +#ifdef _WIN32 +template<> BOOL IsObjectEquals(BSTR o1, BSTR o2) +{ + if ( o1 == NULL && o2 == NULL ) + return TRUE; + else if ( o1 == NULL && o2 != NULL ) + return FALSE; + else if ( o1 != NULL && o2 == NULL ) + return FALSE; + + UINT uLen1 = SysStringLen(o1); + UINT uLen2 = SysStringLen(o2); + + if (uLen1 != uLen2 ) + return FALSE; + + return memcmp(o1, o2, uLen1) == 0; +} + +BSTR ToBSTR(int i) +{ + BSTR bstrRet = NULL; + VarBstrFromI4(i, 0, 0, &bstrRet); + + return bstrRet; +} + +BOOL CmpBSTR(BSTR bstr1, BSTR bstr2) +{ + UINT uLen1 = SysStringLen(bstr1); + UINT uLen2 = SysStringLen(bstr2); + + if (uLen1 != uLen2 ) + return FALSE; + return memcmp(bstr1, bstr2, uLen1) == 0; +} + +BSTR* InitArrayBSTR(LONG arrSize) +{ + BSTR* pExpectArr = (BSTR*)CoreClrAlloc(sizeof(BSTR)*arrSize); + for(LONG i = 0;i0) + return FALSE; + return TRUE; +} +#endif diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/CMakeLists.txt b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/CMakeLists.txt new file mode 100644 index 0000000..4dbfc7c --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required (VERSION 2.6) +project (ReversePInvokePassingByOutNative) +include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") +include_directories("..") +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES + ReversePInvokePassingByOutNative.cpp +) +# Additional files to reference: +# add the executable +add_library (ReversePInvokePassingByOutNative SHARED ${SOURCES}) +target_link_libraries(ReversePInvokePassingByOutNative ${LINK_LIBRARIES_ADDITIONAL}) +# add the install targets +install (TARGETS ReversePInvokePassingByOutNative DESTINATION bin) diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/PassingByOutTest.cs b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/PassingByOutTest.cs new file mode 100644 index 0000000..ab0f37a --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/PassingByOutTest.cs @@ -0,0 +1,208 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using TestLibrary; + +public class ReversePInvoke_MashalArrayByOut_AsManagedTest +{ + public static int arrSize = 10; + + public static int failures = 0; + + #region Func Sig + + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalByteArray_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelByteArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalSbyteArray_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelSbyteArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalShortArray_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelShortArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelShortArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalUshortArray_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelUshortArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalInt32Array_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelInt32ArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalUint32Array_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelUint32ArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalLongArray_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelLongArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalUlongArray_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelUlongArrByOutAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByOutNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalStringArray_AsParam_AsByOut([MarshalAs(UnmanagedType.FunctionPtr)]DelStringArrByOutAsCdeclCaller caller); + + #endregion + + #region Delegate Method + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelByteArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out byte[] arrArg, out byte arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelSbyteArrByOutAsCdeclCaller(out sbyte arraySize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out sbyte[] arrArg); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelShortArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out short[] arrArg, out short arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelUshortArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out ushort[] arrArg, out ushort arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelInt32ArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out Int32[] arrArg, out Int32 arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelUint32ArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out UInt32[] arrArg, out UInt32 arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelLongArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out long[] arrArg, out long arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelUlongArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out ulong[] arrArg, out ulong arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelStringArrByOutAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1, ArraySubType = UnmanagedType.BStr)] out string[] arrArg, out Int32 arraySize); + + #endregion + + #region Test Method + + //Type: byte ==> BYTE Array Size: byte.MinValue ==> 20 + public static bool TestMethodForByteArray_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out byte[] arrArg, out byte arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + //Type: sbyte ==> CHAR Array Size: 1 ==> sbyte.MaxValue + public static bool TestMethodForSbyteArray_AsReversePInvokeByOut_AsCdecl(out sbyte arraySize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] out sbyte[] arrArg) + { + arrArg = Helper.GetExpChangeArray(sbyte.MaxValue); + arraySize = sbyte.MaxValue; + return true; + } + + //Type: short ==> SHORT Array Size: -1 ==> 20(Actual 10 ==> 20) + public static bool TestMethodForShortArray_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out short[] arrArg, out short arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + //Type: short ==> SHORT Array Size: 10 ==> -1(Actual 10 ==> 20) + public static bool TestMethodForShortArrayReturnNegativeSize_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out short[] arrArg, out short arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = -1; + return true; + } + + //Type: ushort ==> USHORT Array Size: ushort.MaxValue ==> 20 + public static bool TestMethodForUshortArray_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out ushort[] arrArg, out ushort arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + //Type: Int32 ==> LONG Array Size: 10 ==> 20 + public static bool TestMethodForInt32Array_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out Int32[] arrArg, out Int32 arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + //Type: UInt32 ==> ULONG Array Size: 10 ==> 20 + public static bool TestMethodForUint32Array_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out UInt32[] arrArg, out UInt32 arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + //Type: long ==> LONGLONG Array Size: 10 ==> 20 + public static bool TestMethodForLongArray_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out long[] arrArg, out long arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + //Type: ulong ==> ULONGLONG Array Size: 10 ==> 20 + public static bool TestMethodForUlongArray_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] out ulong[] arrArg, out ulong arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + //Type: string ==> BSTR Array Size: 10 ==> 20 + public static bool TestMethodForStringArray_AsReversePInvokeByOut_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1, ArraySubType = UnmanagedType.BStr)] out string[] arrArg, out Int32 arraySize) + { + arrArg = Helper.GetExpChangeArray(20); + arraySize = 20; + return true; + } + + #endregion + + public static void RunTestByOut() + { + Console.WriteLine("ReversePInvoke C-Style Array marshaled by out with SizeParamIndex attribute(by out Array size)."); + + //Common value type + Console.WriteLine("\tScenario 1 : byte ==> BYTE, Array_Size = byte.MinValue, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalByteArray_AsParam_AsByOut(new DelByteArrByOutAsCdeclCaller(TestMethodForByteArray_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalByteArray_AsReversePInvokeByOut_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 2 : sbyte ==> CHAR, Array_Size = 1, Return_Array_Size = sbyte.Max"); + Assert.IsTrue(DoCallBack_MarshalSbyteArray_AsParam_AsByOut(new DelSbyteArrByOutAsCdeclCaller(TestMethodForSbyteArray_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalSbyteArray_AsReversePInvokeByOut_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 3 : short ==> SHORT, Array_Size = -1, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalShortArray_AsParam_AsByOut(new DelShortArrByOutAsCdeclCaller(TestMethodForShortArray_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalShortArray_AsReversePInvokeByOut_AsCdecl Failed!"); + + Console.WriteLine("\tScenario 4 : short ==> SHORT, Array_Size = 10, Return_Array_Size = -1"); + Assert.IsTrue(DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByOut(new DelShortArrByOutAsCdeclCaller(TestMethodForShortArrayReturnNegativeSize_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalShortArray_AsReversePInvokeByOut_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 5 : ushort ==> USHORT, Array_Size = ushort.MaxValue, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalUshortArray_AsParam_AsByOut(new DelUshortArrByOutAsCdeclCaller(TestMethodForUshortArray_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalUshortArray_AsReversePInvokeByOut_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 6 : Int32 ==> LONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalInt32Array_AsParam_AsByOut(new DelInt32ArrByOutAsCdeclCaller(TestMethodForInt32Array_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalInt32Array_AsReversePInvokeByOut_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 7 : UInt32 ==> ULONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalUint32Array_AsParam_AsByOut(new DelUint32ArrByOutAsCdeclCaller(TestMethodForUint32Array_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalUint32Array_AsReversePInvokeByOut_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 8 : long ==> LONGLONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalLongArray_AsParam_AsByOut(new DelLongArrByOutAsCdeclCaller(TestMethodForLongArray_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalLongArray_AsReversePInvokeByOut_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 9 : ulong ==> ULONGLONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalUlongArray_AsParam_AsByOut(new DelUlongArrByOutAsCdeclCaller(TestMethodForUlongArray_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalUlongArray_AsReversePInvokeByOut_AsCdecl Passed!"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Console.WriteLine("\tScenario 10 : string ==> BSTR, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalStringArray_AsParam_AsByOut(new DelStringArrByOutAsCdeclCaller(TestMethodForStringArray_AsReversePInvokeByOut_AsCdecl))); + Console.WriteLine("\t\tMarshalStringArray_AsReversePInvokeByOut_AsCdecl Passed!"); + } + } + + public static int Main() + { + try{ + RunTestByOut(); + return 100; + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/PassingByOutTest.csproj b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/PassingByOutTest.csproj new file mode 100644 index 0000000..5344935 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/PassingByOutTest.csproj @@ -0,0 +1,35 @@ + + + + + Debug + AnyCPU + PassingByOutTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/ReversePInvokePassingByOutNative.cpp b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/ReversePInvokePassingByOutNative.cpp new file mode 100644 index 0000000..f95d2a6 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByOut/ReversePInvokePassingByOutNative.cpp @@ -0,0 +1,205 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ReversePInvokePassingByOutNative.cpp : Defines the entry point for the DLL application. +// +#include +#include +#include "platformdefines.h" +#include "helper.h" + +//Func Pointer +typedef BOOL (__cdecl *DelByteArrByOutAsCdeclCaller)(BYTE** arrByte, BYTE* arraySize); +typedef BOOL (__cdecl *DelSbyteArrByOutAsCdeclCaller)(CHAR* arraySize, CHAR** arrSbyte); +typedef BOOL (__cdecl *DelShortArrByOutAsCdeclCaller)(SHORT** arrShort, SHORT* arraySize); +typedef BOOL (__cdecl *DelUshortArrByOutAsCdeclCaller)(USHORT** arrUshort, USHORT* arraySize); +typedef BOOL (__cdecl *DelInt32ArrByOutAsCdeclCaller)(LONG** arrInt32, LONG* arraySize); +typedef BOOL (__cdecl *DelUint32ArrByOutAsCdeclCaller)(ULONG** arrUint32, ULONG* arraySize); +typedef BOOL (__cdecl *DelLongArrByOutAsCdeclCaller)(LONGLONG** arrLong, LONGLONG* arraySize); +typedef BOOL (__cdecl *DelUlongArrByOutAsCdeclCaller)(ULONGLONG** arrUlong, ULONGLONG* arraySize); +typedef BOOL (__cdecl *DelStringArrByOutAsCdeclCaller)(BSTR** arrString, LONG* arraySize); + +//####################################################### +//Test Method +//####################################################### + +//BYTE 0 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalByteArray_AsParam_AsByOut(DelByteArrByOutAsCdeclCaller caller) +{ + BYTE arrSize = 0; + BYTE* arrByte = InitArray(arrSize); + + if(!caller(&arrByte, &arrSize)) + { + printf("DoCallBack_MarshalByteArray_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrByte); + return FALSE; + } + + return CheckArray(arrByte, arrSize, (BYTE)20); +} + +//CHAR 1 ==> CHAR.Max size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalSbyteArray_AsParam_AsByOut(DelSbyteArrByOutAsCdeclCaller caller) +{ + CHAR arrSize = 1; + CHAR* arrSbyte = InitArray((size_t)arrSize); + + if(!caller(&arrSize, &arrSbyte)) + { + printf("DoCallBack_MarshalSbyteArray_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrSbyte); + return FALSE; + } + + return CheckArray(arrSbyte, (size_t)arrSize, (CHAR)127); +} + +//SHORT -1 ==> 20 size Array(Actual: 10 ==> 20) +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalShortArray_AsParam_AsByOut(DelShortArrByOutAsCdeclCaller caller) +{ + SHORT arrSize = -1; + SHORT* arrShort = InitArray(SHORT(10)); + + if(!caller(&arrShort, &arrSize)) + { + printf("DoCallBack_MarshalShortArray_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrShort); + return FALSE; + } + + return CheckArray(arrShort, (size_t)arrSize, (SHORT)20); +} + +//SHORT 10 ==> -1 size Array(Actual: 10 ==> 20) +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByOut(DelShortArrByOutAsCdeclCaller caller) +{ + SHORT arrSize = 10; + SHORT* arrShort = InitArray((size_t)arrSize); + + if(!caller(&arrShort, &arrSize)) + { + printf("DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrShort); + return FALSE; + } + + if(arrSize == -1) + return CheckArray(arrShort, (SHORT)20, (SHORT)20); + else + return FALSE; +} + +//USHORT ushort.Max ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalUshortArray_AsParam_AsByOut(DelUshortArrByOutAsCdeclCaller caller) +{ + USHORT arrSize = 65535; + USHORT* arrUshort = InitArray(arrSize); + + if(!caller(&arrUshort, &arrSize)) + { + printf("DoCallBack_MarshalUshortArray_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrUshort); + return FALSE; + } + + return CheckArray(arrUshort, arrSize, (USHORT)20); +} + +//Int32 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalInt32Array_AsParam_AsByOut(DelInt32ArrByOutAsCdeclCaller caller) +{ + LONG arrSize = 10; + LONG* arrInt32 = InitArray((size_t)arrSize); + + if(!caller(&arrInt32, &arrSize)) + { + printf("DoCallBack_MarshalInt32Array_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrInt32); + return FALSE; + } + + return CheckArray(arrInt32, (size_t)arrSize, (LONG)20); +} + +//UInt32 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalUint32Array_AsParam_AsByOut(DelUint32ArrByOutAsCdeclCaller caller) +{ + ULONG arrSize = 10; + ULONG* arrUint32 = InitArray(arrSize); + + if(!caller(&arrUint32, &arrSize)) + { + printf("DoCallBack_MarshalUint32Array_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrUint32); + return FALSE; + } + + return CheckArray(arrUint32, arrSize, (ULONG)20); +} + +//LONGLONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalLongArray_AsParam_AsByOut(DelLongArrByOutAsCdeclCaller caller) +{ + LONGLONG arrSize = 10; + LONGLONG* arrLong = InitArray((SIZE_T)arrSize); + + if(!caller(&arrLong, &arrSize)) + { + printf("DoCallBack_MarshalLongArray_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrLong); + return FALSE; + } + + return CheckArray(arrLong, (SIZE_T)arrSize, 20); +} + +//ULONGLONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalUlongArray_AsParam_AsByOut(DelUlongArrByOutAsCdeclCaller caller) +{ + ULONGLONG arrSize = 10; + ULONGLONG* arrUlong = InitArray((SIZE_T)arrSize); + + if(!caller(&arrUlong, &arrSize)) + { + printf("DoCallBack_MarshalUlongArray_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrUlong); + return FALSE; + } + + return CheckArray(arrUlong, (SIZE_T)arrSize, 20); +} + +#ifdef _WIN32 +//BSTR 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalStringArray_AsParam_AsByOut(DelStringArrByOutAsCdeclCaller caller) +{ + LONG arrSize = 10; + BSTR* arrString = InitArrayBSTR(arrSize); + + if(!caller(&arrString, &arrSize)) + { + printf("DoCallBack_MarshalStringArray_AsParam_AsByOut:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrString); + return FALSE; + } + + LONG ExpectedArraySize = 20; + BSTR* pExpectedArr = (BSTR*)CoreClrAlloc(sizeof(BSTR)*ExpectedArraySize); + for(LONG i = 0; i < ExpectedArraySize; ++i) + { + pExpectedArr[i] = ToBSTR(ExpectedArraySize - 1 - i); + } + + if(!EqualArrayBSTR(arrString, arrSize, pExpectedArr, ExpectedArraySize)) + { + printf("ManagedtoNative Error in Method: %s!\n",__FUNCTION__); + return FALSE; + } + + CoreClrFree(arrString); + CoreClrFree(pExpectedArr); + return TRUE; +} +#endif diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/CMakeLists.txt b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/CMakeLists.txt new file mode 100644 index 0000000..34e702b6 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required (VERSION 2.6) +project (ReversePInvokePassingByRefNative) +include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake") +include_directories("..") +include_directories(${INC_PLATFORM_DIR}) +set(SOURCES + ReversePInvokePassingByRefNative.cpp +) +# Additional files to reference: +# add the executable +add_library (ReversePInvokePassingByRefNative SHARED ${SOURCES}) +target_link_libraries(ReversePInvokePassingByRefNative ${LINK_LIBRARIES_ADDITIONAL}) +# add the install targets +install (TARGETS ReversePInvokePassingByRefNative DESTINATION bin) diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/PassingByRefTest.cs b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/PassingByRefTest.cs new file mode 100644 index 0000000..e6864c2 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/PassingByRefTest.cs @@ -0,0 +1,223 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using TestLibrary; + +public class ReversePInvoke_MashalArrayByRef_AsManagedTest +{ + public static int arrSize = 10; + + public static int failures = 0; + + #region Func Sig + + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalByteArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelByteArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalSbyteArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelSbyteArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalShortArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelShortArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelShortArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalUshortArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelUshortArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalInt32Array_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelInt32ArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalUint32Array_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelUint32ArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalLongArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelLongArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalUlongArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelUlongArrByRefAsCdeclCaller caller); + [DllImport("ReversePInvokePassingByRefNative", CallingConvention = CallingConvention.Cdecl)] + private static extern bool DoCallBack_MarshalStringArray_AsParam_AsByRef([MarshalAs(UnmanagedType.FunctionPtr)]DelStringArrByRefAsCdeclCaller caller); + + #endregion + + #region Delegate Method + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelByteArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref byte[] arrArg, ref byte arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelSbyteArrByRefAsCdeclCaller(ref sbyte arraySize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref sbyte[] arrArg); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelShortArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref short[] arrArg, ref short arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelUshortArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ushort[] arrArg, ref ushort arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelInt32ArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref Int32[] arrArg, ref Int32 arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelUint32ArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref UInt32[] arrArg, ref UInt32 arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelLongArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref long[] arrArg, ref long arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelUlongArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ulong[] arrArg, ref ulong arraySize); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool DelStringArrByRefAsCdeclCaller([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1, ArraySubType = UnmanagedType.BStr)] ref string[] arrArg, ref Int32 arraySize); + + #endregion + + #region Test Method + + //Type: byte ==> BYTE Array Size: byte.MinValue ==> 20 + public static bool TestMethodForByteArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref byte[] arrArg, ref byte arraySize) + { + if (arraySize == byte.MinValue) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, (Int32)byte.MinValue, 20); + return false; + } + + //Type: sbyte ==> CHAR Array Size: 1 ==> sbyte.MaxValue + public static bool TestMethodForSbyteArray_AsReversePInvokeByRef_AsCdecl(ref sbyte arraySize, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 0)] ref sbyte[] arrArg) + { + if (arraySize == 1) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, 1, (Int32)sbyte.MaxValue); + return false; + } + + //Type: short ==> SHORT Array Size: -1 ==> 20(Actual 10 ==> 20) + public static bool TestMethodForShortArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref short[] arrArg, ref short arraySize) + { + if (arraySize == -1) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, 10, 20); + return false; + } + + //Type: short ==> SHORT Array Size: 10 ==> -1(Actual 10 ==> 20) + public static bool TestMethodForShortArrayReturnNegativeSize_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref short[] arrArg, ref short arraySize) + { + if (arraySize == 10) + { + Helper.CheckAndChangeArray(ref arrArg, ref arraySize, 10, 20); + arraySize = -1; + return true; + } + return false; + } + + //Type: ushort ==> USHORT Array Size: ushort.MaxValue ==> 20 + public static bool TestMethodForUshortArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ushort[] arrArg, ref ushort arraySize) + { + if (arraySize == ushort.MaxValue) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, (Int32)ushort.MaxValue, 20); + return false; + } + + //Type: Int32 ==> LONG Array Size: 10 ==> 20 + public static bool TestMethodForInt32Array_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref Int32[] arrArg, ref Int32 arraySize) + { + if (arraySize == 10) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, 10, 20); + return false; + } + + //Type: UInt32 ==> ULONG Array Size: 10 ==> 20 + public static bool TestMethodForUint32Array_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref UInt32[] arrArg, ref UInt32 arraySize) + { + if (arraySize == 10) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, 10, 20); + return false; + } + + //Type: long ==> LONGLONG Array Size: 10 ==> 20 + public static bool TestMethodForLongArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref long[] arrArg, ref long arraySize) + { + if (arraySize == 10) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, 10, 20); + return false; + } + + //Type: ulong ==> ULONGLONG Array Size: 10 ==> 20 + public static bool TestMethodForUlongArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] ref ulong[] arrArg, ref ulong arraySize) + { + if (arraySize == 10) + return Helper.CheckAndChangeArray(ref arrArg, ref arraySize, 10, 20); + return false; + } + + //Type: string ==> BSTR Array Size: 10 ==> 20 + public static bool TestMethodForStringArray_AsReversePInvokeByRef_AsCdecl([MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1, ArraySubType = UnmanagedType.BStr)] ref string[] arrArg, ref Int32 arraySize) + { + string[] actualArr = Helper.InitArray(10); + if (!Helper.EqualArray(arrArg, arraySize, actualArr, 10)) + { + return false; + } + + arraySize = 20; + arrArg = Helper.GetExpChangeArray(20); + return true; + } + + #endregion + + public static void RunTestByRef() + { + Console.WriteLine("ReversePInvoke C-Style Array marshaled by ref with SizeParamIndex attribute(by ref Array size)."); + + //Common value type + Console.WriteLine("\tScenario 1 : byte ==> BYTE, Array_Size = byte.MinValue, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalByteArray_AsParam_AsByRef(new DelByteArrByRefAsCdeclCaller(TestMethodForByteArray_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalByteArray_AsReversePInvokeByRef_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 2 : sbyte ==> CHAR, Array_Size = 1, Return_Array_Size = sbyte.Max"); + Assert.IsTrue(DoCallBack_MarshalSbyteArray_AsParam_AsByRef(new DelSbyteArrByRefAsCdeclCaller(TestMethodForSbyteArray_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalSbyteArray_AsReversePInvokeByRef_AsCdecl Passed!"); + + // We don't support exception interop in .NET Core off-Windows. + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Console.WriteLine("\tScenario 3 : short ==> SHORT, Array_Size = -1, Return_Array_Size = 20"); + Assert.Throws(() => DoCallBack_MarshalShortArray_AsParam_AsByRef(new DelShortArrByRefAsCdeclCaller(TestMethodForShortArray_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalShortArray_AsReversePInvokeByRef_AsCdecl Passed!"); + } + + + Console.WriteLine("\tScenario 4 : short ==> SHORT, Array_Size = 10, Return_Array_Size = -1"); + Assert.IsTrue(DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByRef(new DelShortArrByRefAsCdeclCaller(TestMethodForShortArrayReturnNegativeSize_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalShortArray_AsReversePInvokeByRef_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 5 : ushort ==> USHORT, Array_Size = ushort.MaxValue, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalUshortArray_AsParam_AsByRef(new DelUshortArrByRefAsCdeclCaller(TestMethodForUshortArray_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalUshortArray_AsReversePInvokeByRef_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 6 : Int32 ==> LONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalInt32Array_AsParam_AsByRef(new DelInt32ArrByRefAsCdeclCaller(TestMethodForInt32Array_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalInt32Array_AsReversePInvokeByRef_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 7 : UInt32 ==> ULONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalUint32Array_AsParam_AsByRef(new DelUint32ArrByRefAsCdeclCaller(TestMethodForUint32Array_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalUint32Array_AsReversePInvokeByRef_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 8 : long ==> LONGLONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalLongArray_AsParam_AsByRef(new DelLongArrByRefAsCdeclCaller(TestMethodForLongArray_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalLongArray_AsReversePInvokeByRef_AsCdecl Passed!"); + + Console.WriteLine("\tScenario 9 : ulong ==> ULONGLONG, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalUlongArray_AsParam_AsByRef(new DelUlongArrByRefAsCdeclCaller(TestMethodForUlongArray_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalUlongArray_AsReversePInvokeByRef_AsCdecl Passed!"); + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + Console.WriteLine("\tScenario 10 : string ==> BSTR, Array_Size = 10, Return_Array_Size = 20"); + Assert.IsTrue(DoCallBack_MarshalStringArray_AsParam_AsByRef(new DelStringArrByRefAsCdeclCaller(TestMethodForStringArray_AsReversePInvokeByRef_AsCdecl))); + Console.WriteLine("\t\tMarshalStringArray_AsReversePInvokeByRef_AsCdecl Passed!"); + } + } + + public static int Main() + { + try{ + RunTestByRef(); + return 100; + } + catch (Exception e) + { + Console.WriteLine($"Test Failure: {e}"); + return 101; + } + } +} diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/PassingByRefTest.csproj b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/PassingByRefTest.csproj new file mode 100644 index 0000000..349b063 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/PassingByRefTest.csproj @@ -0,0 +1,35 @@ + + + + + Debug + AnyCPU + PassingByRefTest + 2.0 + {F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0} + Exe + {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + ..\..\..\..\ + $(DefineConstants);STATIC + + + + + + + False + + + + + + + + + + + + + + + diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/ReversePInvokePassingByRefNative.cpp b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/ReversePInvokePassingByRefNative.cpp new file mode 100644 index 0000000..a51ecef --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/PassingByRef/ReversePInvokePassingByRefNative.cpp @@ -0,0 +1,203 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// ReversePInvokePassingByRefNative.cpp : Defines the entry point for the DLL application. +#include +#include +#include "platformdefines.h" +#include "helper.h" + +//Func Pointer +typedef BOOL (__cdecl *DelByteArrByRefAsCdeclCaller)(BYTE** arrByte, BYTE* arraySize); +typedef BOOL (__cdecl *DelSbyteArrByRefAsCdeclCaller)(CHAR* arraySize, CHAR** arrSbyte); +typedef BOOL (__cdecl *DelShortArrByRefAsCdeclCaller)(SHORT** arrShort, SHORT* arraySize); +typedef BOOL (__cdecl *DelUshortArrByRefAsCdeclCaller)(USHORT** arrUshort, USHORT* arraySize); +typedef BOOL (__cdecl *DelInt32ArrByRefAsCdeclCaller)(LONG** arrInt32, LONG* arraySize); +typedef BOOL (__cdecl *DelUint32ArrByRefAsCdeclCaller)(ULONG** arrUint32, ULONG* arraySize); +typedef BOOL (__cdecl *DelLongArrByRefAsCdeclCaller)(LONGLONG** arrLong, LONGLONG* arraySize); +typedef BOOL (__cdecl *DelUlongArrByRefAsCdeclCaller)(ULONGLONG** arrUlong, ULONGLONG* arraySize); +typedef BOOL (__cdecl *DelStringArrByRefAsCdeclCaller)(BSTR** arrString, LONG* arraySize); + +//####################################################### +//Test Method +//####################################################### + +//BYTE 0 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalByteArray_AsParam_AsByRef(DelByteArrByRefAsCdeclCaller caller) +{ + BYTE arrSize = 0; + BYTE* arrByte = InitArray(arrSize); + + if(!caller(&arrByte, &arrSize)) + { + printf("DoCallBack_MarshalByteArray_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrByte); + return FALSE; + } + + return CheckArray(arrByte, arrSize, (BYTE)20); +} + +//CHAR 1 ==> CHAR.Max size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalSbyteArray_AsParam_AsByRef(DelSbyteArrByRefAsCdeclCaller caller) +{ + CHAR arrSize = 1; + CHAR* arrSbyte = InitArray((size_t)arrSize); + + if(!caller(&arrSize, &arrSbyte)) + { + printf("DoCallBack_MarshalSbyteArray_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrSbyte); + return FALSE; + } + + return CheckArray(arrSbyte, (size_t)arrSize, (CHAR)127); +} + +//SHORT -1 ==> 20 size Array(Actual: 10 ==> 20) +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalShortArray_AsParam_AsByRef(DelShortArrByRefAsCdeclCaller caller) +{ + SHORT arrSize = -1; + SHORT* arrShort = InitArray(SHORT(10)); + + if(!caller(&arrShort, &arrSize)) + { + printf("DoCallBack_MarshalShortArray_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrShort); + return FALSE; + } + + return CheckArray(arrShort, (size_t)arrSize, (SHORT)20); +} + +//SHORT 10 ==> -1 size Array(Actual: 10 ==> 20) +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByRef(DelShortArrByRefAsCdeclCaller caller) +{ + SHORT arrSize = 10; + SHORT* arrShort = InitArray((size_t)arrSize); + + if(!caller(&arrShort, &arrSize)) + { + printf("DoCallBack_MarshalShortArrayReturnNegativeSize_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrShort); + return FALSE; + } + + if(arrSize == -1) + return CheckArray(arrShort, (SHORT)20, (SHORT)20); + else + return FALSE; +} + +//USHORT ushort.Max ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalUshortArray_AsParam_AsByRef(DelUshortArrByRefAsCdeclCaller caller) +{ + USHORT arrSize = 65535; + USHORT* arrUshort = InitArray(arrSize); + + if(!caller(&arrUshort, &arrSize)) + { + printf("DoCallBack_MarshalUshortArray_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrUshort); + return FALSE; + } + + return CheckArray(arrUshort, arrSize, (USHORT)20); +} + +//Int32 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalInt32Array_AsParam_AsByRef(DelInt32ArrByRefAsCdeclCaller caller) +{ + LONG arrSize = 10; + LONG* arrInt32 = InitArray((size_t)arrSize); + + if(!caller(&arrInt32, &arrSize)) + { + printf("DoCallBack_MarshalInt32Array_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrInt32); + return FALSE; + } + + return CheckArray(arrInt32, (size_t)arrSize, (LONG)20); +} + +//UInt32 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalUint32Array_AsParam_AsByRef(DelUint32ArrByRefAsCdeclCaller caller) +{ + ULONG arrSize = 10; + ULONG* arrUint32 = InitArray(arrSize); + + if(!caller(&arrUint32, &arrSize)) + { + printf("DoCallBack_MarshalUint32Array_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrUint32); + return FALSE; + } + + return CheckArray(arrUint32, arrSize, (ULONG)20); +} + +//LONGLONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalLongArray_AsParam_AsByRef(DelLongArrByRefAsCdeclCaller caller) +{ + LONGLONG arrSize = 10; + LONGLONG* arrLong = InitArray(SIZE_T(arrSize)); + + if(!caller(&arrLong, &arrSize)) + { + printf("DoCallBack_MarshalLongArray_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrLong); + return FALSE; + } + + return CheckArray(arrLong, (SIZE_T)arrSize, 20); +} + +//ULONGLONG 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalUlongArray_AsParam_AsByRef(DelUlongArrByRefAsCdeclCaller caller) +{ + ULONGLONG arrSize = 10; + ULONGLONG* arrUlong = InitArray(SIZE_T(arrSize)); + + if(!caller(&arrUlong, &arrSize)) + { + printf("DoCallBack_MarshalUlongArray_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrUlong); + return FALSE; + } + + return CheckArray(arrUlong, (SIZE_T)arrSize, 20); +} +#ifdef _WIN32 +//BSTR 10 ==> 20 size Array +extern "C" DLL_EXPORT BOOL __cdecl DoCallBack_MarshalStringArray_AsParam_AsByRef(DelStringArrByRefAsCdeclCaller caller) +{ + LONG arrSize = 10; + BSTR* arrString = InitArrayBSTR(arrSize); + + if(!caller(&arrString, &arrSize)) + { + printf("DoCallBack_MarshalStringArray_AsParam_AsByRef:\n\tThe Caller returns wrong value\n"); + CoreClrFree(arrString); + return FALSE; + } + + LONG ExpectedArraySize = 20; + BSTR* pExpectedArr = (BSTR*)CoreClrAlloc(sizeof(BSTR)*ExpectedArraySize); + for(LONG i = 0; i < ExpectedArraySize; ++i) + { + pExpectedArr[i] = ToBSTR(ExpectedArraySize - 1 - i); + } + + if(!EqualArrayBSTR(arrString, arrSize, pExpectedArr, ExpectedArraySize)) + { + printf("ManagedtoNative Error in Method: %s!\n",__FUNCTION__); + return FALSE; + } + + CoreClrFree(arrString); + CoreClrFree(pExpectedArr); + return TRUE; +} +#endif diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/helper.cs b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/helper.cs new file mode 100644 index 0000000..a02e219 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/helper.cs @@ -0,0 +1,83 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; + +public class Helper +{ + #region General method + + public static T[] InitArray(int arrSize) + { + T[] array = new T[arrSize]; + for (int i = 0; i < array.Length; i++) + { + array[i] = (T)Convert.ChangeType(i, typeof(T)); + } + return array; + } + + public static bool EqualArray(T[] actualArray, int actualSize, T[] expArr, int arrSize2) + { + int failures = 0; + if (actualArray == null && expArr == null) + { + Console.WriteLine("\tTwo array are equal.Both of them null"); + return true; + } + else if (actualArray == null && expArr != null) + { + Console.WriteLine("\tTwo array are not equal.The sourcArr is null,but the expArr is not null"); + return false; + } + else if (actualArray != null && expArr == null) + { + Console.WriteLine("\tTwo array are not equal.The sourcArr is not null but the expArr is null"); + return false; + } + else if (!actualSize.Equals(arrSize2)) + { + Console.WriteLine("\tTwo array are not equal.The sizes are not equal"); + return false; + } + for (int i = 0; i < arrSize2; ++i) + { + if (!actualArray[i].Equals(expArr[i])) + { + Console.WriteLine("\tTwo array are not equal.The values of index {0} are not equal!", i); + Console.WriteLine("\t\tThe actualArray is {0},the expArr is {1}", actualArray[i].ToString(), expArr[i].ToString()); + failures++; + } + } + if (failures > 0) + return false; + return true; + } + + public static T[] GetExpChangeArray(int cSize) + { + T[] array = new T[cSize]; + + for (int i = array.Length - 1; i >= 0; --i) + array[i] = (T)Convert.ChangeType(array.Length - 1 - i, typeof(T)); + + return array; + } + + public static bool CheckAndChangeArray(ref T[] arrArg, ref T arrSize, int actualArrSize, int expectedArrSize) + { + T[] actualArr = InitArray(actualArrSize); + if (!EqualArray(arrArg, actualArrSize, actualArr, actualArrSize)) + { + return false; + } + + arrSize = (T)Convert.ChangeType(expectedArrSize, typeof(T)); + arrArg = GetExpChangeArray(expectedArrSize); + return true; + } + + #endregion +} \ No newline at end of file diff --git a/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/helper.h b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/helper.h new file mode 100644 index 0000000..9b0a6b0 --- /dev/null +++ b/tests/src/Interop/PInvoke/SizeParamIndex/ReversePInvoke/helper.h @@ -0,0 +1,229 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +// helper.h : Defines helper functions +#include + +const LONG Array_Size = 10; +const LONG CArray_Size = 20; + +////////////////////////////////////////////////////////////////////////////// +// Verify helper methods +////////////////////////////////////////////////////////////////////////////// +template +BOOL IsObjectEquals(T o1, T o2) +{ + // T::operator== required. + return o1 == o2; +} + +//Int32 helper +template +T* InitArray(SIZE_T arrSize) +{ + T* pExpectArr = (T*)CoreClrAlloc(sizeof(T)*arrSize); + for(SIZE_T i = 0;i +T* InitExpectedArray(SIZE_T arrSize) +{ + T* pExpectArr = (T*)CoreClrAlloc(sizeof(T)*arrSize); + for(SIZE_T i = 0;i +BOOL EqualArray(T* actualArray, SIZE_T actualSize, T* expectedArray, SIZE_T expectedSize) +{ + int failures = 0; + + if(actualArray == NULL && expectedArray == NULL) + { + printf("Two arrays are equal. Both of them NULL\n"); + return TRUE; + } + else if(actualArray == NULL && expectedArray != NULL) + { + printf("Two arrays aren't equal. Array from Managed to Native is NULL,but the Compared is not NULL!\n"); + return FALSE; + } + else if(actualArray != NULL && expectedArray == NULL) + { + printf("Two arrays aren't equal. Array from Managed to Native is not NULL,but the Compared is NULL!\n"); + return FALSE; + } + else if(actualSize != expectedSize) + { + printf("Two arrays aren't equal. The arrays size are not equal!\n"); + return FALSE; + } + for(SIZE_T i = 0;i < actualSize; ++i) + { + if(actualArray[i] != expectedArray[i]) + { + printf("Two arrays aren't equal.The value of index of %d isn't equal!\n",(int)i); + printf("\tThe value in actual rray is %d\n",(int)actualArray[i]); + printf("\tThe value in expected array is %d\n",(int)expectedArray[i]); + failures++; + } + } + if( failures > 0 ) + return FALSE; + return TRUE; +} + +template +BOOL CheckAndChangeArrayByRef(T ** ppActual, T* Actual_Array_Size, SIZE_T Expected_Array_Size, SIZE_T Return_Array_Size) +{ + T* pExpectedArr = InitArray(Expected_Array_Size); + if(!EqualArray(*ppActual, *Actual_Array_Size, pExpectedArr, Expected_Array_Size)) + { + printf("ManagedtoNative Error in Method: %s!\n",__FUNCTION__); + return FALSE; + } + + CoreClrFree(pExpectedArr); + CoreClrFree(*ppActual); + *ppActual = (T*)CoreClrAlloc(sizeof(T)*Return_Array_Size); + + *Actual_Array_Size = ((T)Return_Array_Size); + for(SIZE_T i = 0; i < Return_Array_Size; ++i) + { + (*ppActual)[i] = Return_Array_Size - 1 - i; + } + return TRUE; +} + +template +BOOL CheckAndChangeArrayByOut(T ** ppActual, T* Actual_Array_Size, SIZE_T Return_Array_Size) +{ + if(*ppActual != NULL ) + { + printf("ManagedtoNative Error in Method: %s!\n",__FUNCTION__); + printf("Array is not NULL"); + return FALSE; + } + + CoreClrFree(*ppActual); + *ppActual = (T*)CoreClrAlloc(sizeof(T)*Return_Array_Size); + + *Actual_Array_Size = ((T)Return_Array_Size); + for(SIZE_T i = 0; i < Return_Array_Size; ++i) + { + (*ppActual)[i] = Return_Array_Size - 1 - i; + } + return TRUE; +} + +template +BOOL CheckArray(T* pReturnArr, SIZE_T actualArraySize, SIZE_T expectedArraySize) +{ + T* pExpectedArr = InitExpectedArray(expectedArraySize); + + if(!EqualArray(pReturnArr, actualArraySize, pExpectedArr, expectedArraySize)) + { + printf("ManagedtoNative Error in Method: %s!\n",__FUNCTION__); + CoreClrFree(pExpectedArr); + return FALSE; + } + else + { + CoreClrFree(pExpectedArr); + return TRUE; + } +} + +//BSTR helper +#ifdef _WIN32 +template<> +BOOL IsObjectEquals(BSTR o1, BSTR o2) +{ + if ( o1 == NULL && o2 == NULL ) + return TRUE; + else if ( o1 == NULL && o2 != NULL ) + return FALSE; + else if ( o1 != NULL && o2 == NULL ) + return FALSE; + + UINT uLen1 = SysStringLen(o1); + UINT uLen2 = SysStringLen(o2); + + if (uLen1 != uLen2 ) + return FALSE; + + return memcmp(o1, o2, uLen1) == 0; +} + +BSTR ToBSTR(int i) +{ + BSTR bstrRet = NULL; + VarBstrFromI4(i, 0, 0, &bstrRet); + + return bstrRet; +} +BOOL CmpBSTR(BSTR bstr1, BSTR bstr2) +{ + UINT uLen1 = SysStringLen(bstr1); + UINT uLen2 = SysStringLen(bstr2); + + if (uLen1 != uLen2 ) + return FALSE; + return memcmp(bstr1, bstr2, uLen1) == 0; +} +BSTR* InitArrayBSTR(LONG arrSize) +{ + BSTR* pExpectArr = (BSTR*)CoreClrAlloc(sizeof(BSTR)*arrSize); + for(LONG i = 0;i0) + return FALSE; + return TRUE; +} +#endif diff --git a/tests/src/Interop/common/types.h b/tests/src/Interop/common/types.h index 26b49ac..140150a 100755 --- a/tests/src/Interop/common/types.h +++ b/tests/src/Interop/common/types.h @@ -36,6 +36,9 @@ typedef char CHAR, *PCHAR; typedef unsigned short USHORT; typedef signed short SHORT; typedef unsigned short WORD, *PWORD, *LPWORD; +typedef int LONG; + +typedef size_t SIZE_T; #ifndef TRUE #define TRUE 1