add_subdirectory(DllImportAttribute/Simple)
if(WIN32)
+ # This test doesn't necessarily need to be Windows-only, but the implementation is very tied to Windows APIs
+ add_subdirectory(PInvoke/DateTime)
+
add_subdirectory(COM/NativeServer)
add_subdirectory(COM/NativeClients/Primitives)
add_subdirectory(IJW/FakeMscoree)
--- /dev/null
+cmake_minimum_required (VERSION 2.6)
+project (NativeDateTime)
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
+include_directories(${INC_PLATFORM_DIR})
+set(SOURCES
+ NativeDateTime.cpp
+)
+if(WIN32)
+ list(APPEND LINK_LIBRARIES_ADDITIONAL
+ OleAut32.lib
+ )
+endif(WIN32)
+# add the executable
+add_library (NativeDateTime SHARED ${SOURCES})
+target_link_libraries(NativeDateTime ${LINK_LIBRARIES_ADDITIONAL})
+# add the install targets
+install (TARGETS NativeDateTime DESTINATION bin)
--- /dev/null
+// 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.Text;
+using System.Runtime.InteropServices;
+using TestLibrary;
+
+#pragma warning disable 618
+[StructLayout(LayoutKind.Sequential)]
+public struct Stru_Seq_DateAsStructAsFld
+{
+ [MarshalAs(UnmanagedType.Struct)]
+ public DateTime dt;
+
+ public int iInt;
+
+ [MarshalAs(UnmanagedType.BStr)]
+ public string bstr;
+}
+
+[StructLayout(LayoutKind.Explicit)]
+public struct Stru_Exp_DateAsStructAsFld
+{
+
+ [FieldOffset(0)]
+ public int iInt;
+
+ [FieldOffset(8)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public DateTime dt;
+}
+
+class DatetimeTest
+{
+ private static DateTime ExpectedRetdate;
+
+ #region PInvoke
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.StdCall)]
+ private static extern bool Marshal_In_stdcall([In][MarshalAs(UnmanagedType.Struct)] DateTime t);
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern bool Marshal_InOut_cdecl([In, Out][MarshalAs(UnmanagedType.Struct)] ref DateTime t);
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.StdCall)]
+ private static extern bool Marshal_Out_stdcall([Out][MarshalAs(UnmanagedType.Struct)] out DateTime t);
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern bool MarshalSeqStruct_InOut_cdecl([In, Out][MarshalAs(UnmanagedType.Struct)] ref Stru_Seq_DateAsStructAsFld t);
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern bool MarshalExpStruct_InOut_cdecl([In, Out][MarshalAs(UnmanagedType.Struct)] ref Stru_Exp_DateAsStructAsFld t);
+ #endregion
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ delegate bool Del_Marshal_InOut_cdecl([In, Out][MarshalAs(UnmanagedType.Struct)] ref DateTime t);
+
+ #region delegatePinvoke
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.StdCall)]
+ [return: MarshalAs(UnmanagedType.FunctionPtr)]
+ private static extern Del_Marshal_InOut_cdecl GetDel_Marshal_InOut_cdecl();
+
+ [UnmanagedFunctionPointer(CallingConvention.StdCall)]
+ delegate bool Del_Marshal_Out_stdcall([Out][MarshalAs(UnmanagedType.Struct)] out DateTime t);
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.StdCall)]
+ private static extern Del_Marshal_Out_stdcall GetDel_Marshal_Out_stdcall();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ delegate bool Del_MarshalSeqStruct_InOut_cdecl([In, Out][MarshalAs(UnmanagedType.Struct)] ref Stru_Seq_DateAsStructAsFld t);
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.StdCall)]
+ private static extern Del_MarshalSeqStruct_InOut_cdecl GetDel_Del_MarshalSeqStruct_InOut_cdecl();
+
+ [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
+ delegate bool Del_MarshalExpStruct_InOut_cdecl([In, Out][MarshalAs(UnmanagedType.Struct)] ref Stru_Exp_DateAsStructAsFld t);
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.StdCall)]
+ private static extern Del_MarshalExpStruct_InOut_cdecl GetDel_Del_MarshalExpStruct_InOut_cdecl();
+
+ #endregion
+
+ #region ReversePInvoke
+
+ [DllImport("NativeDateTime.dll", CallingConvention = CallingConvention.Cdecl)]
+ private static extern bool RevP_Marshal_InOut_cdecl(Del_Marshal_InOut_cdecl d);
+
+ public static bool RevPMethod_Marshal_InOut_cdecl(ref DateTime d)
+ {
+ ExpectedRetdate = new DateTime(1947, 8, 15);
+ Assert.AreEqual(ExpectedRetdate, d, "RevPMethod_Marshal_InOut_cdecl : Date didn't match to expected date");
+ d = d.AddDays(-1);
+ return true;
+ }
+
+ #endregion
+
+ static int Main(string[] args)
+ {
+ try{
+ ExpectedRetdate = new DateTime(1947, 8, 15);
+
+ #region Pinvoke
+ DateTime Date1 = new DateTime(2008, 7, 4);
+ Assert.IsTrue(Marshal_In_stdcall(Date1), "Marshal_In_stdcall : Returned false");
+ Assert.IsTrue(Marshal_InOut_cdecl(ref Date1), "Marshal_InOut_cdecl : Returned false");
+ Assert.AreEqual(ExpectedRetdate, Date1, "Marshal_InOut_cdecl : Returned date is wrong");
+
+ DateTime Date2;
+ Assert.IsTrue(Marshal_Out_stdcall(out Date2), "Marshal_In_stdcall : Returned false");
+ Assert.AreEqual(ExpectedRetdate, Date2, "Marshal_InOut_cdecl : Returned date is wrong");
+
+ Stru_Seq_DateAsStructAsFld StDate1;
+ StDate1.dt = new DateTime(2008, 7, 4);
+ StDate1.iInt = 100;
+ StDate1.bstr = "Managed";
+ Assert.IsTrue(MarshalSeqStruct_InOut_cdecl(ref StDate1), "MarshalSeqStruct_InOut_cdecl : Native side check failed");
+ Assert.AreEqual(ExpectedRetdate, StDate1.dt, "MarshalSeqStruct_InOut_cdecl : Returned date is wrong");
+
+ Stru_Exp_DateAsStructAsFld StDate2;
+ StDate2.dt = new DateTime(2008, 7, 4);
+ StDate2.iInt = 100;
+ Assert.IsTrue(MarshalExpStruct_InOut_cdecl(ref StDate2), "MarshalExpStruct_InOut_cdecl : Native side check failed");
+ Assert.AreEqual(ExpectedRetdate, StDate2.dt, "MarshalExpStruct_InOut_cdecl : Returned date is wrong");
+
+ #endregion
+
+ #region DelegatePInvoke
+
+ Del_Marshal_InOut_cdecl del1 = GetDel_Marshal_InOut_cdecl();
+ DateTime Date4 = new DateTime(2008, 7, 4);
+ Assert.IsTrue(del1(ref Date4), "GetDel_Marshal_InOut_cdecl : Returned false");
+ Assert.AreEqual(ExpectedRetdate, Date4, "GetDel_Marshal_InOut_cdecl : Returned date is wrong");
+
+ Del_Marshal_Out_stdcall del3 = GetDel_Marshal_Out_stdcall();
+ DateTime Date6;
+ Assert.IsTrue(del3(out Date6), "GetDel_Marshal_Out_stdcall : Returned false");
+ Assert.AreEqual(ExpectedRetdate, Date6, "GetDel_Marshal_Out_stdcall : Returned date is wrong");
+
+ Stru_Seq_DateAsStructAsFld StDate3;
+ StDate3.dt = new DateTime(2008, 7, 4);
+ StDate3.iInt = 100;
+ StDate3.bstr = "Managed";
+ Del_MarshalSeqStruct_InOut_cdecl del4 = GetDel_Del_MarshalSeqStruct_InOut_cdecl();
+ Assert.IsTrue(del4(ref StDate3), "MarshalSeqStruct_InOut_cdecl : Native side check failed");
+ Assert.AreEqual(ExpectedRetdate, StDate3.dt, "MarshalSeqStruct_InOut_cdecl : Returned date is wrong");
+
+ Stru_Exp_DateAsStructAsFld StDate4;
+ StDate4.dt = new DateTime(2008, 7, 4);
+ StDate4.iInt = 100;
+
+ Del_MarshalExpStruct_InOut_cdecl del5 = GetDel_Del_MarshalExpStruct_InOut_cdecl();
+ Assert.IsTrue(del5(ref StDate4), "MarshalExpStruct_InOut_cdecl : Native side check failed");
+ Assert.AreEqual(ExpectedRetdate, StDate4.dt, "MarshalExpStruct_InOut_cdecl : Returned date is wrong");
+
+ #endregion
+
+ #region ReversePInvoke
+ Assert.IsTrue(RevP_Marshal_InOut_cdecl(new Del_Marshal_InOut_cdecl(RevPMethod_Marshal_InOut_cdecl)), "RevP_Marshal_InOut_cdecl : Returned false");
+ #endregion
+
+ return 100;
+ } catch (Exception e){
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+}
+#pragma warning restore 618
+
--- /dev/null
+<?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" />
+ <PropertyGroup>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <AssemblyName>DateTimeTest</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>
+ <DefineConstants>$(DefineConstants);STATIC</DefineConstants>
+ <!-- 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="DateTimeTest.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="CMakeLists.txt" />
+ </ItemGroup>
+ <Import Project="../../Interop.settings.targets" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
--- /dev/null
+// 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.
+
+// NativeDateTime.cpp : Defines the exported functions for the DLL application.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <windows.h>
+#include <oleauto.h>
+#include <xplatform.h>
+
+#define LCID_ENGLISH MAKELCID(MAKELANGID(0x09, 0x01), SORT_DEFAULT)
+
+#pragma pack (push)
+#pragma pack (8)
+struct Stru_Seq_DateAsStructAsFld // size = 16 bytes
+{
+ DATE dt;
+ INT iInt;
+ BSTR bstr;
+};
+#pragma pack (pop)
+
+#pragma pack (push)
+#pragma pack (1)
+struct Stru_Exp_DateAsStructAsFld // size = 16 bytes
+{
+ INT iInt;
+ INT padding;
+ DATE dt;
+};
+#pragma pack (pop)
+
+extern "C" BOOL VerifySeqStruct(struct Stru_Seq_DateAsStructAsFld* StDate)
+{
+ BSTR str;
+ VarBstrFromDate(StDate->dt, LCID_ENGLISH, VAR_FOURDIGITYEARS, &str);
+ if(wcscmp(L"7/4/2008", (wchar_t *)str) != 0 )
+ {
+ wprintf(L"FAILURE! InDATE expected '07/04/2008' but received: %s\n", str);
+ return FALSE;
+ }
+ if(StDate->iInt != 100)
+ {
+ wprintf(L"FAILURE! iInt expected 100 but received: %d\n", StDate->iInt);
+ return FALSE;
+ }
+ if(wcscmp(L"Managed", (wchar_t *)(StDate->bstr)) != 0 )
+ {
+ wprintf(L"FAILURE! bstr expected 'Managed' but received: %s\n", StDate->bstr);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C" BOOL VerifyExpStruct(struct Stru_Exp_DateAsStructAsFld* StDate)
+{
+ BSTR str;
+ VarBstrFromDate(StDate->dt, LCID_ENGLISH, VAR_FOURDIGITYEARS, &str);
+ if(wcscmp(L"7/4/2008", (wchar_t *)str) != 0 )
+ {
+ wprintf(L"FAILURE! InDATE expected '07/04/2008' but received: %s\n", str);
+ return FALSE;
+ }
+ if(StDate->iInt != 100)
+ {
+ wprintf(L"FAILURE! iInt expected 100 but received: %d\n", StDate->iInt);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C" void ChangeStru_Seq_DateAsStructAsFld(Stru_Seq_DateAsStructAsFld * StDate)
+{
+ VarDateFromStr(SysAllocString(L"8/15/1947"), 0, 0, &(StDate->dt));
+}
+
+extern "C" void ChangeStru_Exp_DateAsStructAsFld(Stru_Exp_DateAsStructAsFld * StDate)
+{
+ VarDateFromStr(SysAllocString(L"8/15/1947"), 0, 0, &(StDate->dt));
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall Marshal_In_stdcall(DATE d)
+{
+ BSTR str;
+ //DATE ptoD;
+
+ // always use the ENGLISH locale so that the string comes out as 11/16/1977 as opposed to
+ // say 16/11/1977 for German locale; otherwise this test would fail on non-ENU locales
+
+ VarBstrFromDate(d, LCID_ENGLISH, VAR_FOURDIGITYEARS, &str);
+
+ if(wcscmp(L"7/4/2008", (wchar_t *)str) != 0 )
+ {
+ wprintf(L"FAILURE! InDATE expected '07/04/2008' but received: %s\n", str);
+ return FALSE;
+ }
+
+ VarDateFromStr(SysAllocString(L"8/15/1947"), 0, 0, &d);
+ return TRUE;
+
+}
+
+extern "C" DLL_EXPORT BOOL __cdecl Marshal_InOut_cdecl(/*[in,out]*/ DATE* d)
+{
+ BSTR str;
+ //DATE ptoD;
+
+ // always use the ENGLISH locale so that the string comes out as 11/16/1977 as opposed to
+ // say 16/11/1977 for German locale; otherwise this test would fail on non-ENU locales
+
+ VarBstrFromDate(*d, LCID_ENGLISH, VAR_FOURDIGITYEARS, &str);
+
+ if(wcscmp(L"7/4/2008", (wchar_t *)str) != 0 )
+ {
+ wprintf(L"FAILURE! InDATE expected '07/04/2008' but received: %s\n", str);
+ return FALSE;
+ }
+
+ VarDateFromStr(SysAllocString(L"8/15/1947"), 0, 0, d);
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall Marshal_Out_stdcall(/*[out]*/ DATE* d)
+{
+ VarDateFromStr(SysAllocString(L"8/15/1947"), 0, 0, d);
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT DATE __stdcall Marshal_Ret_stdcall()
+{
+ DATE d;
+ VarDateFromStr(SysAllocString(L"8/15/1947"), 0, 0, &d);
+ return d;
+}
+
+typedef BOOL (__cdecl * Datetime_Del_Marshal_InOut_cdecl)(/*[in,out]*/ DATE* t);
+extern "C" DLL_EXPORT Datetime_Del_Marshal_InOut_cdecl __stdcall GetDel_Marshal_InOut_cdecl()
+{
+ return Marshal_InOut_cdecl;
+}
+
+typedef DATE (__stdcall * Datetime_Del_Marshal_Ret_stdcall)();
+extern "C" DLL_EXPORT Datetime_Del_Marshal_Ret_stdcall __stdcall GetDel_Marshal_Ret_stdcall()
+{
+ return Marshal_Ret_stdcall;
+}
+
+
+typedef BOOL (__stdcall * Datetime_Del_Marshal_Out_stdcall)(/*[out]*/ DATE* t);
+extern "C" DLL_EXPORT Datetime_Del_Marshal_Out_stdcall __stdcall GetDel_Marshal_Out_stdcall()
+{
+ return Marshal_Out_stdcall;
+}
+
+extern "C" DLL_EXPORT BOOL __cdecl RevP_Marshal_InOut_cdecl(Datetime_Del_Marshal_InOut_cdecl d)
+{
+ DATE ptoD;
+ BSTR str;
+
+ VarDateFromStr(SysAllocString(L"8/15/1947"), 0, 0, &ptoD);
+ if(d(&ptoD) == FALSE)
+ {
+ wprintf(L"FAILURE! RevP_Marshal_InOut_cdecl : Date on managed side didn't match\n");
+ return FALSE;
+ }
+
+ //Verify the changes are visible
+ VarBstrFromDate(ptoD, LCID_ENGLISH, VAR_FOURDIGITYEARS, &str);
+ if(wcscmp(L"8/14/1947", (wchar_t *)str) != 0 )
+ {
+ wprintf(L"FAILURE! RevP_Marshal_InOut_cdecl : InDATE expected '8/14/1947' but received: %s\n", str);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+
+extern "C" DLL_EXPORT BOOL __stdcall RevP_Marshal_Ret_stdcall(Datetime_Del_Marshal_Ret_stdcall d)
+{
+ DATE date;
+ BSTR str;
+
+ date = d();
+
+ VarBstrFromDate(date, LCID_ENGLISH, VAR_FOURDIGITYEARS, &str);
+ if(wcscmp(L"7/4/2008", (wchar_t *)str) != 0 )
+ {
+ wprintf(L"FAILURE! RevP_Marshal_Ret_stdcall : InDATE expected '07/04/2008' but received: %s\n", str);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __cdecl MarshalSeqStruct_InOut_cdecl(/*[in,out]*/ struct Stru_Seq_DateAsStructAsFld * t)
+{
+ if(!VerifySeqStruct(t))
+ return FALSE;
+
+ ChangeStru_Seq_DateAsStructAsFld(t);
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __cdecl MarshalExpStruct_InOut_cdecl(/*[in,out]*/ struct Stru_Exp_DateAsStructAsFld * t)
+{
+ if(!VerifyExpStruct(t))
+ return FALSE;
+
+ ChangeStru_Exp_DateAsStructAsFld(t);
+ return TRUE;
+}
+
+
+typedef BOOL (__cdecl * Datetime_Del_MarshalExpStruct_InOut_cdecl)(/*[in,out]*/ struct Stru_Exp_DateAsStructAsFld * t);
+extern "C" DLL_EXPORT Datetime_Del_MarshalExpStruct_InOut_cdecl __stdcall GetDel_Del_MarshalExpStruct_InOut_cdecl()
+{
+ return MarshalExpStruct_InOut_cdecl;
+}
+
+
+typedef BOOL (__cdecl * Datetime_Del_MarshalSeqStruct_InOut_cdecl)(/*[in,out]*/ struct Stru_Seq_DateAsStructAsFld * t);
+extern "C" DLL_EXPORT Datetime_Del_MarshalSeqStruct_InOut_cdecl __stdcall GetDel_Del_MarshalSeqStruct_InOut_cdecl()
+{
+ return MarshalSeqStruct_InOut_cdecl;
+}