summaryrefslogtreecommitdiff
path: root/tests/src/Interop
diff options
context:
space:
mode:
authorJeremy Koritzinsky <jkoritzinsky@gmail.com>2018-11-15 17:14:35 -0800
committerGitHub <noreply@github.com>2018-11-15 17:14:35 -0800
commita08a66902cdfb8e713c1e11f56c3aea9ca6ece6c (patch)
tree0ec9b4dca8d487aba8be6c578903ae8fccba7054 /tests/src/Interop
parentcd0fe8e2d781b21d18254b6414521f6399997f6e (diff)
downloadcoreclr-a08a66902cdfb8e713c1e11f56c3aea9ca6ece6c.tar.gz
coreclr-a08a66902cdfb8e713c1e11f56c3aea9ca6ece6c.tar.bz2
coreclr-a08a66902cdfb8e713c1e11f56c3aea9ca6ece6c.zip
Add tests for marshalling as VARIANT_BOOL or VARIANT (#20856)
* Add native side impl for VARIANT_BOOL test. * More bool native code. * Add VariantBool marshalling tests. * Add infrastructure for tests for object -> VARIANT marshalling. * Add variant tests for all built-in types. * Clean up Variant tests. * Add test for passing custom structure as object. * Add test for VARIANT_BOOL byref. * Added byref tests for VARIANT marshalling. * Add field marshalling tests for VARIANT. * Move ByValue tests to not have two sources of truth. * Make managed code the one source of truth. * Clean up formatting/unused methods. * Clean up some whitespace issues. * Add tests for BStrWrapper and CurrencyWrapper marshalling. * Add UnknownWrapper tests. * Add a test for VariantWrapper and PInvoke. * PR Feedback. * Remove ToString. * Fix visibility * Fix MSBuild import path. * Clean up Variant tests.
Diffstat (limited to 'tests/src/Interop')
-rw-r--r--tests/src/Interop/CMakeLists.txt1
-rw-r--r--tests/src/Interop/PInvoke/Variant/CMakeLists.txt18
-rw-r--r--tests/src/Interop/PInvoke/Variant/PInvokeDefs.cs200
-rw-r--r--tests/src/Interop/PInvoke/Variant/VariantNative.cpp1115
-rw-r--r--tests/src/Interop/PInvoke/Variant/VariantTest.cs294
-rw-r--r--tests/src/Interop/PInvoke/Variant/VariantTest.csproj35
-rw-r--r--tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp70
-rw-r--r--tests/src/Interop/PrimitiveMarshalling/Bool/BoolTest.cs100
-rw-r--r--tests/src/Interop/PrimitiveMarshalling/Bool/NativeMethodDef.cs54
9 files changed, 1858 insertions, 29 deletions
diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt
index 5d9c27b456..60fbde340c 100644
--- a/tests/src/Interop/CMakeLists.txt
+++ b/tests/src/Interop/CMakeLists.txt
@@ -56,6 +56,7 @@ add_subdirectory(DllImportAttribute/Simple)
add_subdirectory(ExecInDefAppDom)
if(WIN32)
+ add_subdirectory(PInvoke/Variant)
add_subdirectory(PInvoke/Varargs)
add_subdirectory(PInvoke/NativeCallManagedComVisible)
# This test doesn't necessarily need to be Windows-only, but the implementation is very tied to Windows APIs
diff --git a/tests/src/Interop/PInvoke/Variant/CMakeLists.txt b/tests/src/Interop/PInvoke/Variant/CMakeLists.txt
new file mode 100644
index 0000000000..536ffb3840
--- /dev/null
+++ b/tests/src/Interop/PInvoke/Variant/CMakeLists.txt
@@ -0,0 +1,18 @@
+cmake_minimum_required (VERSION 2.6)
+project (VariantNative)
+include_directories(${INC_PLATFORM_DIR})
+set(SOURCES VariantNative.cpp)
+
+# add the executable
+add_library (VariantNative SHARED ${SOURCES})
+
+if(WIN32)
+ list(APPEND LINK_LIBRARIES_ADDITIONAL
+ OleAut32.lib
+ )
+endif(WIN32)
+
+target_link_libraries(VariantNative ${LINK_LIBRARIES_ADDITIONAL})
+
+# add the install targets
+install (TARGETS VariantNative DESTINATION bin)
diff --git a/tests/src/Interop/PInvoke/Variant/PInvokeDefs.cs b/tests/src/Interop/PInvoke/Variant/PInvokeDefs.cs
new file mode 100644
index 0000000000..27e90ca2ff
--- /dev/null
+++ b/tests/src/Interop/PInvoke/Variant/PInvokeDefs.cs
@@ -0,0 +1,200 @@
+// 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;
+
+#pragma warning disable CS0612, CS0618
+class VariantNative
+{
+ public struct CustomStruct
+ {
+ }
+
+ public struct ObjectWrapper
+ {
+ [MarshalAs(UnmanagedType.Struct)]
+ public object value;
+ }
+
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Byte(object obj, byte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_SByte(object obj, sbyte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Int16(object obj, short expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_UInt16(object obj, ushort expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Int32(object obj, int expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_UInt32(object obj, uint expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Int64(object obj, long expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_UInt64(object obj, ulong expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Single(object obj, float expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Double(object obj, double expected);
+ [DllImport(nameof(VariantNative), CharSet = CharSet.Unicode)]
+ public static extern bool Marshal_ByValue_String(object obj, [MarshalAs(UnmanagedType.BStr)] string expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Char(object obj, char expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Boolean(object obj, [MarshalAs(UnmanagedType.VariantBool)] bool expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_DateTime(object obj, DateTime expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Decimal(object obj, decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Currency(object obj, [MarshalAs(UnmanagedType.Currency)] decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Missing(object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Object(object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Object_IUnknown(object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Empty(object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Null(object obj);
+
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByValue_Invalid(object obj);
+
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Byte(ref object obj, byte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_SByte(ref object obj, sbyte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Int16(ref object obj, short expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_UInt16(ref object obj, ushort expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Int32(ref object obj, int expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_UInt32(ref object obj, uint expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Int64(ref object obj, long expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_UInt64(ref object obj, ulong expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Single(ref object obj, float expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Double(ref object obj, double expected);
+ [DllImport(nameof(VariantNative), CharSet = CharSet.Unicode)]
+ public static extern bool Marshal_ByRef_String(ref object obj, [MarshalAs(UnmanagedType.BStr)] string expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Char(ref object obj, char expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Boolean(ref object obj, [MarshalAs(UnmanagedType.VariantBool)] bool expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_DateTime(ref object obj, DateTime expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Decimal(ref object obj, decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Currency(ref object obj, [MarshalAs(UnmanagedType.Currency)] decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Missing(ref object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Object(ref object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Object_IUnknown(ref object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Empty(ref object obj);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ByRef_Null(ref object obj);
+
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_ChangeVariantType(ref object obj, int expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Out(out object obj, int expected);
+
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Byte(ObjectWrapper wrapper, byte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_SByte(ObjectWrapper wrapper, sbyte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Int16(ObjectWrapper wrapper, short expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_UInt16(ObjectWrapper wrapper, ushort expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Int32(ObjectWrapper wrapper, int expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_UInt32(ObjectWrapper wrapper, uint expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Int64(ObjectWrapper wrapper, long expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_UInt64(ObjectWrapper wrapper, ulong expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Single(ObjectWrapper wrapper, float expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Double(ObjectWrapper wrapper, double expected);
+ [DllImport(nameof(VariantNative), CharSet = CharSet.Unicode)]
+ public static extern bool Marshal_Struct_ByValue_String(ObjectWrapper wrapper, [MarshalAs(UnmanagedType.BStr)] string expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Char(ObjectWrapper wrapper, char expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Boolean(ObjectWrapper wrapper, [MarshalAs(UnmanagedType.VariantBool)] bool expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_DateTime(ObjectWrapper wrapper, DateTime expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Decimal(ObjectWrapper wrapper, decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Currency(ObjectWrapper wrapper, [MarshalAs(UnmanagedType.Currency)] decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Missing(ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Object(ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Object_IUnknown(ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Empty(ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByValue_Null(ObjectWrapper wrapper);
+
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Byte(ref ObjectWrapper wrapper, byte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_SByte(ref ObjectWrapper wrapper, sbyte expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Int16(ref ObjectWrapper wrapper, short expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_UInt16(ref ObjectWrapper wrapper, ushort expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Int32(ref ObjectWrapper wrapper, int expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_UInt32(ref ObjectWrapper wrapper, uint expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Int64(ref ObjectWrapper wrapper, long expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_UInt64(ref ObjectWrapper wrapper, ulong expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Single(ref ObjectWrapper wrapper, float expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Double(ref ObjectWrapper wrapper, double expected);
+ [DllImport(nameof(VariantNative), CharSet = CharSet.Unicode)]
+ public static extern bool Marshal_Struct_ByRef_String(ref ObjectWrapper wrapper, [MarshalAs(UnmanagedType.BStr)] string expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Char(ref ObjectWrapper wrapper, char expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Boolean(ref ObjectWrapper wrapper, [MarshalAs(UnmanagedType.VariantBool)] bool expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_DateTime(ref ObjectWrapper wrapper, DateTime expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Decimal(ref ObjectWrapper wrapper, decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Currency(ref ObjectWrapper wrapper, [MarshalAs(UnmanagedType.Currency)] decimal expected);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Missing(ref ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Object(ref ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Object_IUnknown(ref ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Empty(ref ObjectWrapper wrapper);
+ [DllImport(nameof(VariantNative))]
+ public static extern bool Marshal_Struct_ByRef_Null(ref ObjectWrapper wrapper);
+}
diff --git a/tests/src/Interop/PInvoke/Variant/VariantNative.cpp b/tests/src/Interop/PInvoke/Variant/VariantNative.cpp
new file mode 100644
index 0000000000..aea8519f3d
--- /dev/null
+++ b/tests/src/Interop/PInvoke/Variant/VariantNative.cpp
@@ -0,0 +1,1115 @@
+// 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.
+
+#include <xplatform.h>
+#include "platformdefines.h"
+
+#define LCID_ENGLISH MAKELCID(MAKELANGID(0x09, 0x01), SORT_DEFAULT)
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Byte(VARIANT value, BYTE expected)
+{
+ if (value.vt != VT_UI1)
+ {
+ printf("Invalid format. Expected VT_UI1.\n");
+ return FALSE;
+ }
+
+ return value.bVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_SByte(VARIANT value, CHAR expected)
+{
+ if (value.vt != VT_I1)
+ {
+ printf("Invalid format. Expected VT_I1.\n");
+ return FALSE;
+ }
+
+ return value.cVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Int16(VARIANT value, SHORT expected)
+{
+ if (value.vt != VT_I2)
+ {
+ printf("Invalid format. Expected VT_I2.\n");
+ return FALSE;
+ }
+
+ return value.iVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_UInt16(VARIANT value, USHORT expected)
+{
+ if (value.vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return value.uiVal == expected ? TRUE : FALSE;
+}
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Int32(VARIANT value, LONG expected)
+{
+ if (value.vt != VT_I4)
+ {
+ printf("Invalid format. Expected VT_I4.\n");
+ return FALSE;
+ }
+
+ return value.lVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_UInt32(VARIANT value, ULONG expected)
+{
+ if (value.vt != VT_UI4)
+ {
+ printf("Invalid format. Expected VT_UI4.\n");
+ return FALSE;
+ }
+
+ return value.ulVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Int64(VARIANT value, LONGLONG expected)
+{
+ if (value.vt != VT_I8)
+ {
+ printf("Invalid format. Expected VT_I8.\n");
+ return FALSE;
+ }
+
+ return value.llVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_UInt64(VARIANT value, ULONGLONG expected)
+{
+ if (value.vt != VT_UI8)
+ {
+ printf("Invalid format. Expected VT_UI8.\n");
+ return FALSE;
+ }
+
+ return value.ullVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Single(VARIANT value, FLOAT expected)
+{
+ if (value.vt != VT_R4)
+ {
+ printf("Invalid format. Expected VT_R4.\n");
+ return FALSE;
+ }
+
+ return value.fltVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Double(VARIANT value, DOUBLE expected)
+{
+ if (value.vt != VT_R8)
+ {
+ printf("Invalid format. Expected VT_R8.\n");
+ return FALSE;
+ }
+
+ return value.dblVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Char(VARIANT value, WCHAR expected)
+{
+ if (value.vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return value.uiVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_String(VARIANT value, BSTR expected)
+{
+ if (value.vt != VT_BSTR)
+ {
+ printf("Invalid format. Expected VT_BSTR.\n");
+ return FALSE;
+ }
+
+ if (value.bstrVal == NULL || expected == NULL)
+ {
+ return value.bstrVal == NULL && expected == NULL;
+ }
+
+ size_t len = TP_SysStringByteLen(value.bstrVal);
+
+ return len == TP_SysStringByteLen(expected) && memcmp(value.bstrVal, expected, len) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Object(VARIANT value)
+{
+
+ if (value.vt != VT_DISPATCH)
+ {
+ printf("Invalid format. Expected VT_DISPATCH.\n");
+ return FALSE;
+ }
+
+
+ IDispatch* obj = value.pdispVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_ByValue (Native side) recieved an invalid IDispatch pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Object_IUnknown(VARIANT value)
+{
+
+ if (value.vt != VT_UNKNOWN)
+ {
+ printf("Invalid format. Expected VT_UNKNOWN.\n");
+ return FALSE;
+ }
+
+
+ IUnknown* obj = value.punkVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_ByValue (Native side) recieved an invalid IUnknown pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Missing(VARIANT value)
+{
+ if (value.vt != VT_ERROR)
+ {
+ printf("Invalid format. Expected VT_ERROR.\n");
+ return FALSE;
+ }
+
+ return value.scode == DISP_E_PARAMNOTFOUND ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Empty(VARIANT value)
+{
+ if (value.vt != VT_EMPTY)
+ {
+ printf("Invalid format. Expected VT_EMPTY. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Boolean(VARIANT value, VARIANT_BOOL expected)
+{
+ if (value.vt != VT_BOOL)
+ {
+ printf("Invalid format. Expected VT_BOOL.\n");
+ return FALSE;
+ }
+
+ return value.boolVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_DateTime(VARIANT value, DATE expected)
+{
+ if (value.vt != VT_DATE)
+ {
+ printf("Invalid format. Expected VT_BYREF.\n");
+ return FALSE;
+ }
+
+ return value.date == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Decimal(VARIANT value, DECIMAL expected)
+{
+ if (value.vt != VT_DECIMAL)
+ {
+ printf("Invalid format. Expected VT_DECIMAL.\n");
+ return FALSE;
+ }
+
+ expected.wReserved = VT_DECIMAL; // The wReserved field in DECIMAL overlaps with the vt field in VARIANT
+
+ return memcmp(&value.decVal, &expected, sizeof(DECIMAL)) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Currency(VARIANT value, CY expected)
+{
+ if (value.vt != VT_CY)
+ {
+ printf("Invalid format. Expected VT_CY.\n");
+ return FALSE;
+ }
+
+ return memcmp(&value.cyVal, &expected, sizeof(CY)) == 0;
+}
+
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Null(VARIANT value)
+{
+ if (value.vt != VT_NULL)
+ {
+ printf("Invalid format. Expected VT_NULL. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByValue_Invalid(VARIANT value)
+{
+ return FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Byte(VARIANT* value, BYTE expected)
+{
+ if (value->vt != VT_UI1)
+ {
+ printf("Invalid format. Expected VT_UI1.\n");
+ return FALSE;
+ }
+
+ return value->bVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_SByte(VARIANT* value, CHAR expected)
+{
+ if (value->vt != VT_I1)
+ {
+ printf("Invalid format. Expected VT_I1.\n");
+ return FALSE;
+ }
+
+ return value->cVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Int16(VARIANT* value, SHORT expected)
+{
+ if (value->vt != VT_I2)
+ {
+ printf("Invalid format. Expected VT_I2.\n");
+ return FALSE;
+ }
+
+ return value->iVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_UInt16(VARIANT* value, USHORT expected)
+{
+ if (value->vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return value->uiVal == expected ? TRUE : FALSE;
+}
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Int32(VARIANT* value, LONG expected)
+{
+ if (value->vt != VT_I4)
+ {
+ printf("Invalid format. Expected VT_I4.\n");
+ return FALSE;
+ }
+
+ return value->lVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_UInt32(VARIANT* value, ULONG expected)
+{
+ if (value->vt != VT_UI4)
+ {
+ printf("Invalid format. Expected VT_UI4.\n");
+ return FALSE;
+ }
+
+ return value->ulVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Int64(VARIANT* value, LONGLONG expected)
+{
+ if (value->vt != VT_I8)
+ {
+ printf("Invalid format. Expected VT_I8.\n");
+ return FALSE;
+ }
+
+ return value->llVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_UInt64(VARIANT* value, ULONGLONG expected)
+{
+ if (value->vt != VT_UI8)
+ {
+ printf("Invalid format. Expected VT_UI8.\n");
+ return FALSE;
+ }
+
+ return value->ullVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Single(VARIANT* value, FLOAT expected)
+{
+ if (value->vt != VT_R4)
+ {
+ printf("Invalid format. Expected VT_R4.\n");
+ return FALSE;
+ }
+
+ return value->fltVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Double(VARIANT* value, DOUBLE expected)
+{
+ if (value->vt != VT_R8)
+ {
+ printf("Invalid format. Expected VT_R8.\n");
+ return FALSE;
+ }
+
+ return value->dblVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Char(VARIANT* value, WCHAR expected)
+{
+ if (value->vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return value->uiVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_String(VARIANT* value, BSTR expected)
+{
+ if (value->vt != VT_BSTR)
+ {
+ printf("Invalid format. Expected VT_BSTR.\n");
+ return FALSE;
+ }
+
+ if (value->bstrVal == NULL || expected == NULL)
+ {
+ return value->bstrVal == NULL && expected == NULL;
+ }
+
+ size_t len = TP_SysStringByteLen(value->bstrVal);
+
+ return len == TP_SysStringByteLen(expected) && memcmp(value->bstrVal, expected, len) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Object(VARIANT* value)
+{
+
+ if (value->vt != VT_DISPATCH)
+ {
+ printf("Invalid format. Expected VT_DISPATCH.\n");
+ return FALSE;
+ }
+
+
+ IDispatch* obj = value->pdispVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_ByRef (Native side) recieved an invalid IDispatch pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Object_IUnknown(VARIANT* value)
+{
+
+ if (value->vt != VT_UNKNOWN)
+ {
+ printf("Invalid format. Expected VT_UNKNOWN.\n");
+ return FALSE;
+ }
+
+
+ IUnknown* obj = value->punkVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_ByRef (Native side) recieved an invalid IUnknown pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Missing(VARIANT* value)
+{
+ if (value->vt != VT_ERROR)
+ {
+ printf("Invalid format. Expected VT_ERROR.\n");
+ return FALSE;
+ }
+
+ return value->scode == DISP_E_PARAMNOTFOUND ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Empty(VARIANT* value)
+{
+ if (value->vt != VT_EMPTY)
+ {
+ printf("Invalid format. Expected VT_EMPTY. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Boolean(VARIANT* value, VARIANT_BOOL expected)
+{
+ if (value->vt != VT_BOOL)
+ {
+ printf("Invalid format. Expected VT_BOOL.\n");
+ return FALSE;
+ }
+
+ return value->boolVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_DateTime(VARIANT* value, DATE expected)
+{
+ if (value->vt != VT_DATE)
+ {
+ printf("Invalid format. Expected VT_BYREF.\n");
+ return FALSE;
+ }
+
+ return value->date == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Decimal(VARIANT* value, DECIMAL expected)
+{
+ if (value->vt != VT_DECIMAL)
+ {
+ printf("Invalid format. Expected VT_DECIMAL.\n");
+ return FALSE;
+ }
+
+ expected.wReserved = VT_DECIMAL; // The wReserved field in DECIMAL overlaps with the vt field in VARIANT*
+
+ return memcmp(&value->decVal, &expected, sizeof(DECIMAL)) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Currency(VARIANT* value, CY expected)
+{
+ if (value->vt != VT_CY)
+ {
+ printf("Invalid format. Expected VT_CY.\n");
+ return FALSE;
+ }
+
+ return memcmp(&value->cyVal, &expected, sizeof(CY)) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ByRef_Null(VARIANT* value)
+{
+ if (value->vt != VT_NULL)
+ {
+ printf("Invalid format. Expected VT_NULL. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Out(VARIANT* pValue, LONG expected)
+{
+ if (FAILED(VariantClear(pValue)))
+ {
+ printf("Failed to clear pValue.\n");
+ return FALSE;
+ }
+ pValue->vt = VT_I4;
+ pValue->lVal = expected;
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_ChangeVariantType(VARIANT* pValue, LONG expected)
+{
+ if (FAILED(VariantClear(pValue)))
+ {
+ printf("Failed to clear pValue.\n");
+ return FALSE;
+ }
+ pValue->vt = VT_I4;
+ pValue->lVal = expected;
+
+ return TRUE;
+}
+
+struct VariantWrapper
+{
+ VARIANT value;
+};
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Byte(VariantWrapper wrapper, BYTE expected)
+{
+ if (wrapper.value.vt != VT_UI1)
+ {
+ printf("Invalid format. Expected VT_UI1.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.bVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_SByte(VariantWrapper wrapper, CHAR expected)
+{
+ if (wrapper.value.vt != VT_I1)
+ {
+ printf("Invalid format. Expected VT_I1.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.cVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Int16(VariantWrapper wrapper, SHORT expected)
+{
+ if (wrapper.value.vt != VT_I2)
+ {
+ printf("Invalid format. Expected VT_I2.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.iVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_UInt16(VariantWrapper wrapper, USHORT expected)
+{
+ if (wrapper.value.vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.uiVal == expected ? TRUE : FALSE;
+}
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Int32(VariantWrapper wrapper, LONG expected)
+{
+ if (wrapper.value.vt != VT_I4)
+ {
+ printf("Invalid format. Expected VT_I4.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.lVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_UInt32(VariantWrapper wrapper, ULONG expected)
+{
+ if (wrapper.value.vt != VT_UI4)
+ {
+ printf("Invalid format. Expected VT_UI4.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.ulVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Int64(VariantWrapper wrapper, LONGLONG expected)
+{
+ if (wrapper.value.vt != VT_I8)
+ {
+ printf("Invalid format. Expected VT_I8.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.llVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_UInt64(VariantWrapper wrapper, ULONGLONG expected)
+{
+ if (wrapper.value.vt != VT_UI8)
+ {
+ printf("Invalid format. Expected VT_UI8.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.ullVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Single(VariantWrapper wrapper, FLOAT expected)
+{
+ if (wrapper.value.vt != VT_R4)
+ {
+ printf("Invalid format. Expected VT_R4.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.fltVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Double(VariantWrapper wrapper, DOUBLE expected)
+{
+ if (wrapper.value.vt != VT_R8)
+ {
+ printf("Invalid format. Expected VT_R8.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.dblVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Char(VariantWrapper wrapper, WCHAR expected)
+{
+ if (wrapper.value.vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.uiVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_String(VariantWrapper wrapper, BSTR expected)
+{
+ if (wrapper.value.vt != VT_BSTR)
+ {
+ printf("Invalid format. Expected VT_BSTR.\n");
+ return FALSE;
+ }
+
+ if (wrapper.value.bstrVal == NULL || expected == NULL)
+ {
+ return wrapper.value.bstrVal == NULL && expected == NULL;
+ }
+
+ size_t len = TP_SysStringByteLen(wrapper.value.bstrVal);
+
+ return len == TP_SysStringByteLen(expected) && memcmp(wrapper.value.bstrVal, expected, len) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Object(VariantWrapper wrapper)
+{
+
+ if (wrapper.value.vt != VT_DISPATCH)
+ {
+ printf("Invalid format. Expected VT_DISPATCH.\n");
+ return FALSE;
+ }
+
+
+ IDispatch* obj = wrapper.value.pdispVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_Struct_ByValue (Native side) recieved an invalid IDispatch pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Object_IUnknown(VariantWrapper wrapper)
+{
+
+ if (wrapper.value.vt != VT_UNKNOWN)
+ {
+ printf("Invalid format. Expected VT_UNKNOWN.\n");
+ return FALSE;
+ }
+
+
+ IUnknown* obj = wrapper.value.punkVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_Struct_ByValue (Native side) recieved an invalid IUnknown pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Missing(VariantWrapper wrapper)
+{
+ if (wrapper.value.vt != VT_ERROR)
+ {
+ printf("Invalid format. Expected VT_ERROR.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.scode == DISP_E_PARAMNOTFOUND ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Empty(VariantWrapper wrapper)
+{
+ if (wrapper.value.vt != VT_EMPTY)
+ {
+ printf("Invalid format. Expected VT_EMPTY. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Boolean(VariantWrapper wrapper, VARIANT_BOOL expected)
+{
+ if (wrapper.value.vt != VT_BOOL)
+ {
+ printf("Invalid format. Expected VT_BOOL.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.boolVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_DateTime(VariantWrapper wrapper, DATE expected)
+{
+ if (wrapper.value.vt != VT_DATE)
+ {
+ printf("Invalid format. Expected VT_Struct_ByValue.\n");
+ return FALSE;
+ }
+
+ return wrapper.value.date == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Decimal(VariantWrapper wrapper, DECIMAL expected)
+{
+ if (wrapper.value.vt != VT_DECIMAL)
+ {
+ printf("Invalid format. Expected VT_DECIMAL.\n");
+ return FALSE;
+ }
+
+ expected.wReserved = VT_DECIMAL; // The wReserved field in DECIMAL overlaps with the vt field in VARIANT*
+
+ return memcmp(&wrapper.value.decVal, &expected, sizeof(DECIMAL)) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Currency(VariantWrapper wrapper, CY expected)
+{
+ if (wrapper.value.vt != VT_CY)
+ {
+ printf("Invalid format. Expected VT_CY.\n");
+ return FALSE;
+ }
+
+ return memcmp(&wrapper.value.cyVal, &expected, sizeof(CY)) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByValue_Null(VariantWrapper wrapper)
+{
+ if (wrapper.value.vt != VT_NULL)
+ {
+ printf("Invalid format. Expected VT_NULL. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Byte(VariantWrapper* pWrapper, BYTE expected)
+{
+ if (pWrapper->value.vt != VT_UI1)
+ {
+ printf("Invalid format. Expected VT_UI1.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.bVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_SByte(VariantWrapper* pWrapper, CHAR expected)
+{
+ if (pWrapper->value.vt != VT_I1)
+ {
+ printf("Invalid format. Expected VT_I1.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.cVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Int16(VariantWrapper* pWrapper, SHORT expected)
+{
+ if (pWrapper->value.vt != VT_I2)
+ {
+ printf("Invalid format. Expected VT_I2.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.iVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_UInt16(VariantWrapper* pWrapper, USHORT expected)
+{
+ if (pWrapper->value.vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.uiVal == expected ? TRUE : FALSE;
+}
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Int32(VariantWrapper* pWrapper, LONG expected)
+{
+ if (pWrapper->value.vt != VT_I4)
+ {
+ printf("Invalid format. Expected VT_I4.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.lVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_UInt32(VariantWrapper* pWrapper, ULONG expected)
+{
+ if (pWrapper->value.vt != VT_UI4)
+ {
+ printf("Invalid format. Expected VT_UI4.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.ulVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Int64(VariantWrapper* pWrapper, LONGLONG expected)
+{
+ if (pWrapper->value.vt != VT_I8)
+ {
+ printf("Invalid format. Expected VT_I8.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.llVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_UInt64(VariantWrapper* pWrapper, ULONGLONG expected)
+{
+ if (pWrapper->value.vt != VT_UI8)
+ {
+ printf("Invalid format. Expected VT_UI8.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.ullVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Single(VariantWrapper* pWrapper, FLOAT expected)
+{
+ if (pWrapper->value.vt != VT_R4)
+ {
+ printf("Invalid format. Expected VT_R4.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.fltVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Double(VariantWrapper* pWrapper, DOUBLE expected)
+{
+ if (pWrapper->value.vt != VT_R8)
+ {
+ printf("Invalid format. Expected VT_R8.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.dblVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Char(VariantWrapper* pWrapper, WCHAR expected)
+{
+ if (pWrapper->value.vt != VT_UI2)
+ {
+ printf("Invalid format. Expected VT_UI2.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.uiVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_String(VariantWrapper* pWrapper, BSTR expected)
+{
+ if (pWrapper->value.vt != VT_BSTR)
+ {
+ printf("Invalid format. Expected VT_BSTR.\n");
+ return FALSE;
+ }
+
+ if (pWrapper->value.bstrVal == NULL || expected == NULL)
+ {
+ return pWrapper->value.bstrVal == NULL && expected == NULL;
+ }
+
+ size_t len = TP_SysStringByteLen(pWrapper->value.bstrVal);
+
+ return len == TP_SysStringByteLen(expected) && memcmp(pWrapper->value.bstrVal, expected, len) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Object(VariantWrapper* pWrapper)
+{
+
+ if (pWrapper->value.vt != VT_DISPATCH)
+ {
+ printf("Invalid format. Expected VT_DISPATCH.\n");
+ return FALSE;
+ }
+
+
+ IDispatch* obj = pWrapper->value.pdispVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_Struct_ByRef (Native side) recieved an invalid IDispatch pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Object_IUnknown(VariantWrapper* pWrapper)
+{
+
+ if (pWrapper->value.vt != VT_UNKNOWN)
+ {
+ printf("Invalid format. Expected VT_UNKNOWN.\n");
+ return FALSE;
+ }
+
+
+ IUnknown* obj = pWrapper->value.punkVal;
+
+ if (obj == NULL)
+ {
+ printf("Marshal_Struct_ByRef (Native side) recieved an invalid IUnknown pointer\n");
+ return FALSE;
+ }
+
+ obj->AddRef();
+
+ obj->Release();
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Missing(VariantWrapper* pWrapper)
+{
+ if (pWrapper->value.vt != VT_ERROR)
+ {
+ printf("Invalid format. Expected VT_ERROR.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.scode == DISP_E_PARAMNOTFOUND ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Empty(VariantWrapper* pWrapper)
+{
+ if (pWrapper->value.vt != VT_EMPTY)
+ {
+ printf("Invalid format. Expected VT_EMPTY. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Boolean(VariantWrapper* pWrapper, VARIANT_BOOL expected)
+{
+ if (pWrapper->value.vt != VT_BOOL)
+ {
+ printf("Invalid format. Expected VT_BOOL.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.boolVal == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_DateTime(VariantWrapper* pWrapper, DATE expected)
+{
+ if (pWrapper->value.vt != VT_DATE)
+ {
+ printf("Invalid format. Expected VT_Struct_ByRef.\n");
+ return FALSE;
+ }
+
+ return pWrapper->value.date == expected ? TRUE : FALSE;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Decimal(VariantWrapper* pWrapper, DECIMAL expected)
+{
+ if (pWrapper->value.vt != VT_DECIMAL)
+ {
+ printf("Invalid format. Expected VT_DECIMAL.\n");
+ return FALSE;
+ }
+
+ expected.wReserved = VT_DECIMAL; // The wReserved field in DECIMAL overlaps with the vt field in VARIANT*
+
+ return memcmp(&pWrapper->value.decVal, &expected, sizeof(DECIMAL)) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Currency(VariantWrapper* pWrapper, CY expected)
+{
+ if (pWrapper->value.vt != VT_CY)
+ {
+ printf("Invalid format. Expected VT_CY.\n");
+ return FALSE;
+ }
+
+ return memcmp(&pWrapper->value.cyVal, &expected, sizeof(CY)) == 0;
+}
+
+extern "C" BOOL DLL_EXPORT STDMETHODCALLTYPE Marshal_Struct_ByRef_Null(VariantWrapper* pWrapper)
+{
+ if (pWrapper->value.vt != VT_NULL)
+ {
+ printf("Invalid format. Expected VT_NULL. \n");
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
diff --git a/tests/src/Interop/PInvoke/Variant/VariantTest.cs b/tests/src/Interop/PInvoke/Variant/VariantTest.cs
new file mode 100644
index 0000000000..ab16781561
--- /dev/null
+++ b/tests/src/Interop/PInvoke/Variant/VariantTest.cs
@@ -0,0 +1,294 @@
+// 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;
+using static VariantNative;
+
+#pragma warning disable CS0612, CS0618
+class Test
+{
+ private const byte NumericValue = 15;
+
+ private const char CharValue = 'z';
+
+ private const string StringValue = "Abcdefg";
+
+ private const decimal DecimalValue = 74.25M;
+
+ private static readonly DateTime DateValue = new DateTime(2018, 11, 6);
+
+ private unsafe static void TestByValue()
+ {
+ Assert.IsTrue(Marshal_ByValue_Byte((byte)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_SByte((sbyte)NumericValue, (sbyte)NumericValue));
+ Assert.IsTrue(Marshal_ByValue_Int16((short)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_UInt16((ushort)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_Int32((int)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_UInt32((uint)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_Int64((long)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_UInt64((ulong)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_Single((float)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_Double((double)NumericValue, NumericValue));
+ Assert.IsTrue(Marshal_ByValue_String(StringValue, StringValue));
+ Assert.IsTrue(Marshal_ByValue_String(new BStrWrapper(null), null));
+ Assert.IsTrue(Marshal_ByValue_Char(CharValue, CharValue));
+ Assert.IsTrue(Marshal_ByValue_Boolean(true, true));
+ Assert.IsTrue(Marshal_ByValue_DateTime(DateValue, DateValue));
+ Assert.IsTrue(Marshal_ByValue_Decimal(DecimalValue, DecimalValue));
+ Assert.IsTrue(Marshal_ByValue_Currency(new CurrencyWrapper(DecimalValue), DecimalValue));
+ Assert.IsTrue(Marshal_ByValue_Null(DBNull.Value));
+ Assert.IsTrue(Marshal_ByValue_Missing(System.Reflection.Missing.Value));
+ Assert.IsTrue(Marshal_ByValue_Empty(null));
+ Assert.IsTrue(Marshal_ByValue_Object(new object()));
+ Assert.IsTrue(Marshal_ByValue_Object_IUnknown(new UnknownWrapper(new object())));
+ Assert.Throws<ArgumentException>(() => Marshal_ByValue_Invalid(TimeSpan.Zero));
+ Assert.Throws<NotSupportedException>(() => Marshal_ByValue_Invalid(new CustomStruct()));
+ Assert.Throws<ArgumentException>(() => Marshal_ByValue_Invalid(new VariantWrapper(CharValue)));
+ }
+
+ private unsafe static void TestByRef()
+ {
+ object obj;
+
+ obj = (byte)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_Byte(ref obj, NumericValue));
+
+ obj = (sbyte)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_SByte(ref obj, (sbyte)NumericValue));
+
+ obj = (short)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_Int16(ref obj, NumericValue));
+
+ obj = (ushort)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_UInt16(ref obj, NumericValue));
+
+ obj = (int)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_Int32(ref obj, NumericValue));
+
+ obj = (uint)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_UInt32(ref obj, NumericValue));
+
+ obj = (long)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_Int64(ref obj, NumericValue));
+
+ obj = (ulong)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_UInt64(ref obj, NumericValue));
+
+ obj = (float)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_Single(ref obj, NumericValue));
+
+ obj = (double)NumericValue;
+ Assert.IsTrue(Marshal_ByRef_Double(ref obj, NumericValue));
+
+ obj = StringValue;
+ Assert.IsTrue(Marshal_ByRef_String(ref obj, StringValue));
+
+ obj = new BStrWrapper(null);
+ Assert.IsTrue(Marshal_ByRef_String(ref obj, null));
+
+ obj = CharValue;
+ Assert.IsTrue(Marshal_ByRef_Char(ref obj, CharValue));
+
+ obj = true;
+ Assert.IsTrue(Marshal_ByRef_Boolean(ref obj, true));
+
+ obj = DateValue;
+ Assert.IsTrue(Marshal_ByRef_DateTime(ref obj, DateValue));
+
+ obj = DecimalValue;
+ Assert.IsTrue(Marshal_ByRef_Decimal(ref obj, DecimalValue));
+
+ obj = new CurrencyWrapper(DecimalValue);
+ Assert.IsTrue(Marshal_ByRef_Currency(ref obj, DecimalValue));
+
+ obj = DBNull.Value;
+ Assert.IsTrue(Marshal_ByRef_Null(ref obj));
+
+ obj = System.Reflection.Missing.Value;
+ Assert.IsTrue(Marshal_ByRef_Missing(ref obj));
+
+ obj = null;
+ Assert.IsTrue(Marshal_ByRef_Empty(ref obj));
+
+ obj = new object();
+ Assert.IsTrue(Marshal_ByRef_Object(ref obj));
+
+ obj = new UnknownWrapper(new object());
+ Assert.IsTrue(Marshal_ByRef_Object_IUnknown(ref obj));
+
+ obj = DecimalValue;
+ Assert.IsTrue(Marshal_ChangeVariantType(ref obj, NumericValue));
+ Assert.IsTrue(obj is int);
+ Assert.AreEqual(NumericValue, (int)obj);
+ }
+
+ private unsafe static void TestOut()
+ {
+ Assert.IsTrue(Marshal_Out(out object obj, NumericValue));
+ Assert.IsTrue(obj is int);
+ Assert.AreEqual(NumericValue, (int)obj);
+ }
+
+ private unsafe static void TestFieldByValue()
+ {
+ ObjectWrapper wrapper = new ObjectWrapper();
+
+ wrapper.value = (byte)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Byte(wrapper, NumericValue));
+
+ wrapper.value = (sbyte)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_SByte(wrapper, (sbyte)NumericValue));
+
+ wrapper.value = (short)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Int16(wrapper, NumericValue));
+
+ wrapper.value = (ushort)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_UInt16(wrapper, NumericValue));
+
+ wrapper.value = (int)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Int32(wrapper, NumericValue));
+
+ wrapper.value = (uint)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_UInt32(wrapper, NumericValue));
+
+ wrapper.value = (long)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Int64(wrapper, NumericValue));
+
+ wrapper.value = (ulong)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_UInt64(wrapper, NumericValue));
+
+ wrapper.value = (float)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Single(wrapper, NumericValue));
+
+ wrapper.value = (double)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Double(wrapper, NumericValue));
+
+ wrapper.value = StringValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_String(wrapper, StringValue));
+
+ wrapper.value = new BStrWrapper(null);
+ Assert.IsTrue(Marshal_Struct_ByValue_String(wrapper, null));
+
+ wrapper.value = CharValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Char(wrapper, CharValue));
+
+ wrapper.value = true;
+ Assert.IsTrue(Marshal_Struct_ByValue_Boolean(wrapper, true));
+
+ wrapper.value = DateValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_DateTime(wrapper, DateValue));
+
+ wrapper.value = DecimalValue;
+ Assert.IsTrue(Marshal_Struct_ByValue_Decimal(wrapper, DecimalValue));
+
+ wrapper.value = new CurrencyWrapper(DecimalValue);
+ Assert.IsTrue(Marshal_Struct_ByValue_Currency(wrapper, DecimalValue));
+
+ wrapper.value = DBNull.Value;
+ Assert.IsTrue(Marshal_Struct_ByValue_Null(wrapper));
+
+ wrapper.value = System.Reflection.Missing.Value;
+ Assert.IsTrue(Marshal_Struct_ByValue_Missing(wrapper));
+
+ wrapper.value = null;
+ Assert.IsTrue(Marshal_Struct_ByValue_Empty(wrapper));
+
+ wrapper.value = new object();
+ Assert.IsTrue(Marshal_Struct_ByValue_Object(wrapper));
+
+ wrapper.value = new UnknownWrapper(new object());
+ Assert.IsTrue(Marshal_Struct_ByValue_Object_IUnknown(wrapper));
+ }
+
+ private unsafe static void TestFieldByRef()
+ {
+ ObjectWrapper wrapper = new ObjectWrapper();
+
+ wrapper.value = (byte)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Byte(ref wrapper, NumericValue));
+
+ wrapper.value = (sbyte)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_SByte(ref wrapper, (sbyte)NumericValue));
+
+ wrapper.value = (short)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Int16(ref wrapper, NumericValue));
+
+ wrapper.value = (ushort)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_UInt16(ref wrapper, NumericValue));
+
+ wrapper.value = (int)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Int32(ref wrapper, NumericValue));
+
+ wrapper.value = (uint)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_UInt32(ref wrapper, NumericValue));
+
+ wrapper.value = (long)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Int64(ref wrapper, NumericValue));
+
+ wrapper.value = (ulong)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_UInt64(ref wrapper, NumericValue));
+
+ wrapper.value = (float)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Single(ref wrapper, NumericValue));
+
+ wrapper.value = (double)NumericValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Double(ref wrapper, NumericValue));
+
+ wrapper.value = StringValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_String(ref wrapper, StringValue));
+
+ wrapper.value = new BStrWrapper(null);
+ Assert.IsTrue(Marshal_Struct_ByRef_String(ref wrapper, null));
+
+ wrapper.value = CharValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Char(ref wrapper, CharValue));
+
+ wrapper.value = true;
+ Assert.IsTrue(Marshal_Struct_ByRef_Boolean(ref wrapper, true));
+
+ wrapper.value = DateValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_DateTime(ref wrapper, DateValue));
+
+ wrapper.value = DecimalValue;
+ Assert.IsTrue(Marshal_Struct_ByRef_Decimal(ref wrapper, DecimalValue));
+
+ wrapper.value = new CurrencyWrapper(DecimalValue);
+ Assert.IsTrue(Marshal_Struct_ByRef_Currency(ref wrapper, DecimalValue));
+
+ wrapper.value = DBNull.Value;
+ Assert.IsTrue(Marshal_Struct_ByRef_Null(ref wrapper));
+
+ wrapper.value = System.Reflection.Missing.Value;
+ Assert.IsTrue(Marshal_Struct_ByRef_Missing(ref wrapper));
+
+ wrapper.value = null;
+ Assert.IsTrue(Marshal_Struct_ByRef_Empty(ref wrapper));
+
+ wrapper.value = new object();
+ Assert.IsTrue(Marshal_Struct_ByRef_Object(ref wrapper));
+
+ wrapper.value = new UnknownWrapper(new object());
+ Assert.IsTrue(Marshal_Struct_ByRef_Object_IUnknown(ref wrapper));
+ }
+
+ public static int Main()
+ {
+ try
+ {
+ TestByValue();
+ TestByRef();
+ TestOut();
+ TestFieldByValue();
+ TestFieldByRef();
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test failed: {e}");
+ return 101;
+ }
+ return 100;
+ }
+}
diff --git a/tests/src/Interop/PInvoke/Variant/VariantTest.csproj b/tests/src/Interop/PInvoke/Variant/VariantTest.csproj
new file mode 100644
index 0000000000..3826f46dd8
--- /dev/null
+++ b/tests/src/Interop/PInvoke/Variant/VariantTest.csproj
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" />
+ <Import Project="../../Interop.settings.targets" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>VariantTest</AssemblyName>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid>
+ <OutputType>Exe</OutputType>
+ <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
+ <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir>
+ <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+
+ <!-- Test unsupported outside of windows -->
+ <TestUnsupportedOutsideWindows>true</TestUnsupportedOutsideWindows>
+ <DisableProjectBuild Condition="'$(TargetsUnix)' == 'true'">true</DisableProjectBuild>
+ </PropertyGroup>
+ <!-- Default configurations to help VS understand the configurations -->
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"></PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"></PropertyGroup>
+ <ItemGroup>
+ <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies">
+ <Visible>False</Visible>
+ </CodeAnalysisDependentAssemblyPaths>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="CMakeLists.txt" />
+ </ItemGroup>
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
diff --git a/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp b/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp
index 23eeb2f03b..edbc8cb92a 100644
--- a/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp
+++ b/tests/src/Interop/PrimitiveMarshalling/Bool/BoolNative.cpp
@@ -173,4 +173,74 @@ extern "C" DLL_EXPORT bool STDMETHODCALLTYPE Marshal_As_Out(/*[Out]*/bool boolVa
//Return
return true;
}
+
+#ifdef _WIN32
+extern "C" DLL_EXPORT bool STDMETHODCALLTYPE Marshal_ByValue_Variant(VARIANT_BOOL boolValue, bool expected)
+{
+ if (boolValue != (expected ? VARIANT_TRUE : VARIANT_FALSE))
+ {
+ printf("Error in function Marshal_ByValue_Variant(Native Client)\n");
+
+ printf("Expected %s ", expected ? "true" : "false");
+ printf("Actual %s (%hi)", boolValue == VARIANT_FALSE ? "false" : "(unknown variant value)", boolValue);
+
+ return false;
+ }
+
+ return true;
+}
+
+extern "C" DLL_EXPORT bool STDMETHODCALLTYPE Marshal_Ref_Variant(VARIANT_BOOL* pBoolValue)
+{
+ if (*pBoolValue != (boolManaged ? VARIANT_TRUE : VARIANT_FALSE))
+ {
+ printf("Error in function Marshal_ByValue_Variant(Native Client)\n");
+
+ printf("Expected %s ", boolManaged ? "true" : "false");
+ printf("Actual %s (%hi)", *pBoolValue == VARIANT_FALSE ? "false" : "(unknown variant value)", *pBoolValue);
+
+ return false;
+ }
+
+ *pBoolValue = (boolNative ? VARIANT_TRUE : VARIANT_FALSE);
+ return true;
+}
+
+struct ContainsVariantBool
+{
+ VARIANT_BOOL value;
+};
+
+extern "C" DLL_EXPORT bool STDMETHODCALLTYPE Marshal_ByValue_Struct_Variant(ContainsVariantBool value, bool expected)
+{
+ if (value.value != (expected ? VARIANT_TRUE : VARIANT_FALSE))
+ {
+ printf("Error in function Marshal_ByValue_Variant(Native Client)\n");
+
+ printf("Expected %s ", expected ? "true" : "false");
+ printf("Actual %s (%hi)", value.value == VARIANT_FALSE ? "false" : "(unknown variant value)", value.value);
+
+ return false;
+ }
+
+ return true;
+}
+
+extern "C" DLL_EXPORT bool STDMETHODCALLTYPE Marshal_Ref_Struct_Variant(ContainsVariantBool* pBoolValue)
+{
+ if (pBoolValue->value != (boolManaged ? VARIANT_TRUE : VARIANT_FALSE))
+ {
+ printf("Error in function Marshal_ByValue_Variant(Native Client)\n");
+
+ printf("Expected %s ", boolManaged ? "true" : "false");
+ printf("Actual %s (%hi)", pBoolValue->value == VARIANT_FALSE ? "false" : "(unknown variant value)", pBoolValue->value);
+
+ return false;
+ }
+
+ pBoolValue->value = (boolNative ? VARIANT_TRUE : VARIANT_FALSE);
+ return true;
+}
+
+#endif
#pragma warning(pop)
diff --git a/tests/src/Interop/PrimitiveMarshalling/Bool/BoolTest.cs b/tests/src/Interop/PrimitiveMarshalling/Bool/BoolTest.cs
index 72b80c0c2b..29db00a81c 100644
--- a/tests/src/Interop/PrimitiveMarshalling/Bool/BoolTest.cs
+++ b/tests/src/Interop/PrimitiveMarshalling/Bool/BoolTest.cs
@@ -9,6 +9,9 @@ using System.Text;
class Test
{
+ const bool boolManaged = true;
+ const bool boolNative = false;
+
static void ReportFailure(string describe, bool expect, bool actual)
{
throw new Exception(" === Fail: " + describe + "\n\tExpected:" + expect + "\n\tActual:" + actual);
@@ -16,12 +19,9 @@ class Test
public static int Main(string[] args)
{
- const bool boolManaged = true;
- const bool boolNative = false;
-
//Test Method1
bool boolValue1 = boolManaged;
- bool boolValueRet1 = NativeMethods.Marshal_In(boolValue1);
+ bool boolValueRet1 = BoolNative.Marshal_In(boolValue1);
if (!boolValueRet1)
{
ReportFailure("Method Marshal_In[Managed Side],The return value is wrong", true, boolValueRet1);
@@ -29,7 +29,7 @@ class Test
//TestMethod2
bool boolValue2 = boolManaged;
- bool boolValueRet2 = NativeMethods.Marshal_InOut(boolValue2);
+ bool boolValueRet2 = BoolNative.Marshal_InOut(boolValue2);
if (!boolValueRet2)
{
ReportFailure("Method Marshal_InOut[Managed Side],The return value is wrong", true, boolValueRet2);
@@ -41,7 +41,7 @@ class Test
//TestMethod3
bool boolValue3 = boolManaged;
- bool boolValueRet3 = NativeMethods.Marshal_Out(boolValue3);
+ bool boolValueRet3 = BoolNative.Marshal_Out(boolValue3);
if (!boolValueRet3)
{
ReportFailure("Method Marshal_Out[Managed Side],The return value is wrong", true, boolValueRet3);
@@ -53,7 +53,7 @@ class Test
//TestMethod4
bool boolValue4 = boolManaged;
- bool boolValueRet4 = NativeMethods.MarshalPointer_In(ref boolValue4);
+ bool boolValueRet4 = BoolNative.MarshalPointer_In(ref boolValue4);
if (!boolValueRet4)
{
ReportFailure("Method MarshalPointer_In[Managed Side],The return value is wrong", true, boolValueRet4);
@@ -65,7 +65,7 @@ class Test
//TestMethod5
bool boolValue5 = boolManaged;
- bool boolValueRet5 = NativeMethods.MarshalPointer_InOut(ref boolValue5);
+ bool boolValueRet5 = BoolNative.MarshalPointer_InOut(ref boolValue5);
if (!boolValueRet5)
{
ReportFailure("Method MarshalPointer_InOut[Managed Side],The return value is wrong", true, boolValueRet5);
@@ -77,7 +77,7 @@ class Test
//TestMethod6
bool boolValue6 = boolManaged;
- bool boolValueRet6 = NativeMethods.MarshalPointer_Out(out boolValue6);
+ bool boolValueRet6 = BoolNative.MarshalPointer_Out(out boolValue6);
if (!boolValueRet6)
{
ReportFailure("Method Marshal_Out[Managed Side],The return value is wrong", true, boolValueRet6);
@@ -89,18 +89,18 @@ class Test
//Test Method7
bool boolValue7 = boolManaged;
- bool boolValueRet7 = NativeMethods.Marshal_As_In(boolValue7);
+ bool boolValueRet7 = BoolNative.Marshal_As_In(boolValue7);
if (!boolValueRet7)
{
- ReportFailure("Method Marshal_As_In[Managed Side],The return value is wrong", true, boolValueRet1);
+ ReportFailure("Method Marshal_As_In[Managed Side],The return value is wrong", true, boolValueRet7);
}
//TestMethod8
bool boolValue8 = boolManaged;
- bool boolValueRet8 = NativeMethods.Marshal_As_InOut(boolValue8);
+ bool boolValueRet8 = BoolNative.Marshal_As_InOut(boolValue8);
if (!boolValueRet8)
{
- ReportFailure("Method Marshal_As_InOut[Managed Side],The return value is wrong", true, boolValueRet2);
+ ReportFailure("Method Marshal_As_InOut[Managed Side],The return value is wrong", true, boolValueRet8);
}
if (boolValue8 != boolManaged)
{
@@ -109,15 +109,83 @@ class Test
//TestMethod9
bool boolValue9 = boolManaged;
- bool boolValueRet9 = NativeMethods.Marshal_As_Out(boolValue9);
+ bool boolValueRet9 = BoolNative.Marshal_As_Out(boolValue9);
if (!boolValueRet9)
{
- ReportFailure("Method Marshal_As_Out[Managed Side],The return value is wrong", true, boolValueRet3);
+ ReportFailure("Method Marshal_As_Out[Managed Side],The return value is wrong", true, boolValueRet9);
}
if (boolValue9 != boolManaged)
{
- ReportFailure("Method Marshal_As_Out[Managed Side],The parameter value is changed", boolManaged, boolValue3);
+ ReportFailure("Method Marshal_As_Out[Managed Side],The parameter value is changed", boolManaged, boolValue9);
+ }
+
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ TestVariantBool();
}
+
return 100;
}
+
+ private static void TestVariantBool()
+ {
+
+ if (!BoolNative.Marshal_ByValue_Variant(true, true))
+ {
+ ReportFailure("Method Marshal_ByValue_Variant[Managed Side], The return value is wrong", true, true);
+ }
+
+ if (!BoolNative.Marshal_ByValue_Variant(false, false))
+ {
+ ReportFailure("Method Marshal_ByValue_Variant[Managed Side], The return value is wrong", false, false);
+ }
+
+ bool boolValue10 = boolManaged;
+ bool boolValueRet10 = BoolNative.Marshal_Ref_Variant(ref boolValue10);
+
+ if (!boolValueRet10)
+ {
+ ReportFailure("Method Marshal_Ref_Variant[Managed Side], The return value is wrong.", true, boolValueRet10);
+ }
+ if (boolValue10 != boolNative)
+ {
+ ReportFailure("Method Marshal_Ref_Variant[Managed Side],The passed value is wrong", boolNative, boolValue10);
+ }
+
+ var trueStruct = new BoolNative.ContainsVariantBool
+ {
+ value = true
+ };
+
+ var falseStruct = new BoolNative.ContainsVariantBool
+ {
+ value = false
+ };
+
+ if (!BoolNative.Marshal_ByValue_Struct_Variant(trueStruct, true))
+ {
+ ReportFailure("Method Marshal_ByValue_Variant[Managed Side], The return value is wrong", true, true);
+ }
+
+ if (!BoolNative.Marshal_ByValue_Struct_Variant(falseStruct, false))
+ {
+ ReportFailure("Method Marshal_ByValue_Variant[Managed Side], The return value is wrong", false, false);
+ }
+
+ var boolValue11 = new BoolNative.ContainsVariantBool
+ {
+ value = boolManaged
+ };
+
+ bool boolValueRet11 = BoolNative.Marshal_Ref_Struct_Variant(ref boolValue11);
+
+ if (!boolValueRet11)
+ {
+ ReportFailure("Method Marshal_Ref_Variant[Managed Side], The return value is wrong.", true, boolValueRet11);
+ }
+ if (boolValue11.value != boolNative)
+ {
+ ReportFailure("Method Marshal_Ref_Variant[Managed Side],The passed value is wrong", boolNative, boolValue11.value);
+ }
+ }
}
diff --git a/tests/src/Interop/PrimitiveMarshalling/Bool/NativeMethodDef.cs b/tests/src/Interop/PrimitiveMarshalling/Bool/NativeMethodDef.cs
index b46015fbd4..4d29f70d54 100644
--- a/tests/src/Interop/PrimitiveMarshalling/Bool/NativeMethodDef.cs
+++ b/tests/src/Interop/PrimitiveMarshalling/Bool/NativeMethodDef.cs
@@ -7,41 +7,69 @@ using System.Runtime.InteropServices;
using System.Reflection;
using System.Text;
-public class NativeMethods
+public class BoolNative
{
-
- public const string NativeSharedBinaryName = "BoolNative";
-
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
public static extern bool Marshal_In([In]bool boolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
public static extern bool Marshal_InOut([In, Out]bool boolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
public static extern bool Marshal_Out([Out]bool boolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
public static extern bool MarshalPointer_In([In]ref bool pboolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
public static extern bool MarshalPointer_InOut(ref bool pboolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
public static extern bool MarshalPointer_Out(out bool pboolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool Marshal_As_In(
[In, MarshalAs(UnmanagedType.U1)]bool boolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool Marshal_As_InOut(
[In, Out, MarshalAs(UnmanagedType.U1)]bool boolValue);
- [DllImport(NativeSharedBinaryName, CallingConvention = CallingConvention.StdCall)]
+ [DllImport(nameof(BoolNative))]
[return: MarshalAs(UnmanagedType.U1)]
public static extern bool Marshal_As_Out(
[Out, MarshalAs(UnmanagedType.U1)]bool boolValue);
+
+#pragma warning disable CS0612, CS0618
+ public struct ContainsVariantBool
+ {
+ [MarshalAs(UnmanagedType.VariantBool)]
+ public bool value;
+ }
+
+ [DllImport(nameof(BoolNative))]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static extern bool Marshal_ByValue_Variant(
+ [MarshalAs(UnmanagedType.VariantBool)] bool value,
+ [MarshalAs(UnmanagedType.U1)] bool expected);
+
+ [DllImport(nameof(BoolNative))]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static extern bool Marshal_Ref_Variant(
+ [MarshalAs(UnmanagedType.VariantBool)] ref bool value);
+
+ [DllImport(nameof(BoolNative))]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static extern bool Marshal_ByValue_Struct_Variant(
+ ContainsVariantBool value,
+ [MarshalAs(UnmanagedType.U1)] bool expected);
+
+ [DllImport(nameof(BoolNative))]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static extern bool Marshal_Ref_Struct_Variant(ref ContainsVariantBool value);
+
+#pragma warning restore CS0612, CS0618
+
}