if(WIN32)
add_subdirectory(PInvoke/Variant)
add_subdirectory(PInvoke/Varargs)
+ add_subdirectory(PInvoke/SafeHandles)
+ add_subdirectory(PInvoke/SafeHandles/ReleaseHandle)
+ add_subdirectory(PInvoke/SafeHandles/Interface)
add_subdirectory(PInvoke/NativeCallManagedComVisible)
# This test doesn't necessarily need to be Windows-only, but the implementation is very tied to Windows APIs
add_subdirectory(PInvoke/DateTime)
--- /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.IO;
+using System.Runtime.InteropServices;
+using SafeHandlesTests;
+using TestLibrary;
+
+public abstract class AllMySafeHandles : SafeHandle
+{
+ private static readonly IntPtr _invalidHandleValue = new IntPtr(-1);
+
+ //0 or -1 considered invalid
+ public override bool IsInvalid
+ {
+ get { return handle == IntPtr.Zero || handle == _invalidHandleValue; }
+ }
+
+ protected AllMySafeHandles(bool ownsHandle) : base(IntPtr.Zero, ownsHandle) { }
+}
+
+public sealed class MySafeEventHandle : AllMySafeHandles
+{
+ private MySafeEventHandle() : base(true) { }
+
+ [DllImport("api-ms-win-core-synch-l1-2-0", SetLastError = true, EntryPoint = "CreateEventW")]
+ internal static extern MySafeEventHandle CreateEvent(IntPtr mustBeZero, bool isManualReset, bool initialState, String name);
+
+ [DllImport("api-ms-win-core-synch-l1-2-0", SetLastError = true)]
+ internal static extern bool SetEvent(MySafeEventHandle handle);
+
+ [DllImport("api-ms-win-core-handle-l1-1-0")]
+ private static extern bool CloseHandle(IntPtr handle);
+
+ override protected bool ReleaseHandle()
+ {
+ return CloseHandle(handle);
+ }
+}
+
+public class AbstractDerivedSHTester
+{
+ private static void ClassHierarchyTest()
+ {
+ Console.WriteLine("Class hierarchy test...");
+
+ //create an event
+ Console.WriteLine("\tCreate new event");
+ MySafeEventHandle sh = MySafeEventHandle.CreateEvent(IntPtr.Zero, true, false, null);
+ Assert.IsFalse(sh.IsInvalid, "CreateEvent returned an invalid SafeHandle!");
+ Assert.IsTrue(MySafeEventHandle.SetEvent(sh), "SetEvent failed on a SafeHandle!");
+
+ Console.WriteLine("\tFirst test: Call dispose on sh");
+ sh.Dispose();
+ Console.WriteLine("\tCall succeeded.\n");
+
+ // Now create another event and force the critical finalizer to run.
+ Console.WriteLine("\tCreate new event");
+ sh = MySafeEventHandle.CreateEvent(IntPtr.Zero, false, true, null);
+ Assert.IsFalse(sh.IsInvalid, "CreateEvent returned an invalid SafeHandle!");
+
+ Console.WriteLine("\tSecond test: Force critical finalizer to run");
+ sh = null;
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+ Console.WriteLine("\tSucceeded.\n");
+ }
+
+ private static int Main()
+ {
+ try
+ {
+ ClassHierarchyTest();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+}
\ No newline at end of file
--- /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>AbstractDerivedTest</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="AbstractDerivedTest.cs" />
+ <Compile Include="..\*.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
+#VCXPROJ
+cmake_minimum_required (VERSION 2.6)
+project (PInvoke_SafeHandle)
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
+include_directories(${INC_PLATFORM_DIR})
+set(SOURCES
+ SafeHandleNative.cpp
+)
+# Additional files to reference:
+# StructDefs.h
+# SafeHandleNative.def
+# add the executable
+add_library (PInvoke_SafeHandle SHARED ${SOURCES})
+# add the install targets
+install (TARGETS PInvoke_SafeHandle 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.Runtime.InteropServices;
+using SafeHandlesTests;
+using TestLibrary;
+
+public class SHTester
+{
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_In([In]SafeFileHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Out(out SFH_NoCloseHandle sh1);
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern SFH_NoCloseHandle SHParam_OutRetVal();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Ref(ref SFH_NoCloseHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Multiple([In]SafeFileHandle sh1, out SFH_NoCloseHandle sh2, ref SFH_NoCloseHandle sh3, Int32 sh1Value, Int32 sh3Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_In([In]StructWithSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Out(out StructWithSHFld s);
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern StructWithSHFld SHStructParam_OutRetVal();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref1(ref StructWithSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref2(ref StructWithSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple1([In]StructWithSHFld sh1, out StructWithSHFld sh2, ref StructWithSHFld sh3, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple2([In]StructWithSHFld sh1, ref StructWithSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple3([In]StructWithSHFld sh1, ref StructWithSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ public static int Main()
+ {
+ try
+ {
+ RunSHParamTests();
+ RunSHStructParamTests();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+
+ /// <summary>
+ ///passing SH subclass parameters to unmanaged code in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1- passing SH subclass parameters individually in separate methods (In, out, ref)
+ ///2- passing SH subclass parameters in combination in the same method
+ /// </summary>
+ public static void RunSHParamTests()
+ {
+ Console.WriteLine("\nRunSHParamTests():");
+ ///1- passing SH subclass parameters individually in separate methods (In, out, ref)
+ //get a new SH
+ SafeFileHandle hnd = Helper.NewSFH();
+ Int32 hndInt32 = Helper.SHInt32(hnd); //get the 32-bit value associated with hnd
+
+ Console.WriteLine("Testing SHParam_In...");
+ SHParam_In(hnd, hndInt32);
+ CheckCleanUp(hnd);
+
+ SFH_NoCloseHandle hndout = Helper.NewSFH_NoCloseHandle(); //get a new value
+ SafeHandle hnd_ref_backup = hndout;
+ hndInt32 = Helper.SHInt32(hndout);
+ Console.WriteLine("Testing SHParam_Ref...");
+ SHParam_Ref(ref hndout, hndInt32);
+ CheckCleanUp(hnd_ref_backup);
+
+ ///2- passing SH subclass parameters in combination in the same method
+ //initialize parameters
+ SafeFileHandle hnd1 = Helper.NewSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(hnd1); //get the 32-bit value associated with hnd1
+
+ SFH_NoCloseHandle hnd2 = null; //out parameter
+
+ SFH_NoCloseHandle hnd3 = Helper.NewSFH_NoCloseHandle();
+ SafeHandle hnd3_ref_backup = hnd3;
+ Int32 hnd3Int32 = Helper.SHInt32(hnd3); //get the 32-bit value associated with hnd3
+
+ Console.WriteLine("Testing SHParam_Multiple...");
+ SHParam_Multiple(hnd1, out hnd2, ref hnd3, hnd1Int32, hnd3Int32);
+ CheckCleanUp(hnd1);
+ CheckCleanUp(hnd2);
+ CheckCleanUp(hnd3_ref_backup);
+ }
+
+ /// <summary>
+ ///passing structures (with SH subclass fields) as parameters in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1- passing structures (In, out, ref) (with SH subclass fields) individually in separate methods
+ ///2- passing structures (In, out, ref) (with SH subclass fields) in combination in the same method
+ /// </summary>
+ public static void RunSHStructParamTests()
+ {
+ Console.WriteLine("\nRunSHStructParamTests():");
+ ///1- passing structures (In, out, ref) (with SH subclass fields) individually in separate methods
+ ///
+ ///
+
+ //initialize a new StructWithSHFld
+ StructWithSHFld s = new StructWithSHFld();
+ s.hnd = Helper.NewSFH(); //get a new SH
+ Int32 hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+
+ Console.WriteLine("Testing SHStructParam_In...");
+ SHStructParam_In(s, hndInt32);
+ CheckCleanUp(s.hnd);
+
+ s.hnd = Helper.NewSFH(); //get a new SH
+ SafeHandle hnd_ref_backup = s.hnd;
+ hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+ Console.WriteLine("Testing SHStructParam_Ref1 (does not change value of handle field)...");
+ SHStructParam_Ref1(ref s, hndInt32);
+ CheckCleanUp(hnd_ref_backup);
+
+ ///2- passing structures (In, out, ref) (with SH subclass fields) in combination in the same method
+ ///
+ ///
+ //initialize parameters
+ StructWithSHFld s1 = new StructWithSHFld();
+ s1.hnd = Helper.NewSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(s1.hnd); //get the 32-bit value associated with s1.hnd
+
+ StructWithSHFld s3 = new StructWithSHFld();
+ s3.hnd = Helper.NewSFH();
+ Int32 hnd3Int32 = Helper.SHInt32(s3.hnd); //get the 32-bit value associated with s3.hnd
+ SafeHandle hnd3_ref_backup = s3.hnd;
+ Console.WriteLine("Testing SHStructParam_Multiple2 (takes a ref struct as one of the params)...");
+ SHStructParam_Multiple2(s1, ref s3, hnd1Int32, hnd3Int32);
+ CheckCleanUp(s1.hnd);
+ CheckCleanUp(hnd3_ref_backup);
+ }
+
+ static void CheckCleanUp(SafeHandle hnd)
+ {
+ Assert.IsFalse(hnd.IsClosed, "Failed: SafeFileHandle Closed before calling close");
+ }
+}
\ No newline at end of file
--- /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>CleanUpCheckTest</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="CleanUpCheckTest.cs" />
+ <Compile Include="..\*.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.
+
+using System;
+using System.Runtime.InteropServices;
+using SafeHandlesTests;
+using TestLibrary;
+
+public class SHTester
+{
+ public static int Main()
+ {
+ try
+ {
+ RunSHParamTests();
+ RunSHStructParamTests();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_In([In]SafeFileHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Out(out SFH_NoCloseHandle sh1);
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern SFH_NoCloseHandle SHParam_OutRetVal();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Ref(ref SFH_NoCloseHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Multiple([In]SafeFileHandle sh1, out SFH_NoCloseHandle sh2, ref SFH_NoCloseHandle sh3, Int32 sh1Value, Int32 sh3Value);
+
+ /// <summary>
+ ///passing SH subclass parameters to unmanaged code in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1- passing SH subclass parameters individually in separate methods (In, out, ref)
+ ///2- passing SH subclass parameters in combination in the same method
+ /// </summary>
+ public static void RunSHParamTests()
+ {
+ Console.WriteLine("SHParam_In");
+ SafeFileHandle hnd = Helper.NewSFH(); //get a new SH
+ Int32 hndInt32 = Helper.SHInt32(hnd); //get the 32-bit value associated with hnd
+ Assert.IsTrue(SHParam_In(hnd, hndInt32), "SHParam_In did not receive hnd as expected");
+ Assert.IsTrue(!Helper.IsChanged(hnd), "SHParam_In did not return hnd as expected.");
+
+ Console.WriteLine("SHParam_Out");
+ SFH_NoCloseHandle hndout;
+ SHParam_Out(out hndout);
+ Assert.IsTrue(Helper.IsChanged(hndout), "SHParam_Out did not return hndout as expected. hndout = " + Helper.SHInt32(hndout));
+
+ Console.WriteLine("SHParam_OutRetVal");
+ hndout = null;
+ hndout = SHParam_OutRetVal();
+ Assert.IsTrue(Helper.IsChanged(hndout), "SHParam_OutRetVal did not return hndout as expected.");
+
+ Console.WriteLine("SHParam_Ref");
+ hndout = Helper.NewSFH_NoCloseHandle(); //get a new value
+ hndInt32 = Helper.SHInt32(hndout);
+ Assert.IsTrue(SHParam_Ref(ref hndout, hndInt32), "SHParam_Ref did not receive hndout as expected");
+ Assert.IsTrue(Helper.IsChanged(hndout), "SHParam_Ref did not return hndout as expected.");
+
+ Console.WriteLine("SHParam_Multiple");
+ SafeFileHandle hnd1 = Helper.NewSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(hnd1); //get the 32-bit value associated with hnd1
+ SFH_NoCloseHandle hnd2 = null; //out parameter
+ SFH_NoCloseHandle hnd3 = Helper.NewSFH_NoCloseHandle();
+ Int32 hnd3Int32 = Helper.SHInt32(hnd3); //get the 32-bit value associated with hnd3
+
+ Assert.IsTrue(SHParam_Multiple(hnd1, out hnd2, ref hnd3, hnd1Int32, hnd3Int32), "SHParam_Multiple did not receive parameter(s) as expected.");
+
+ Assert.IsTrue(Helper.IsChanged(hnd2), "HParam_Multiple did not return hnd2 as expected.");
+ Assert.IsTrue(Helper.IsChanged(hnd3), "HParam_Multiple did not return hnd3 as expected.");
+ }
+
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_In([In]StructWithSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Out(out StructWithSHFld s);
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern StructWithSHFld SHStructParam_OutRetVal();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref1(ref StructWithSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref2(ref StructWithSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple1([In]StructWithSHFld sh1, out StructWithSHFld sh2, ref StructWithSHFld sh3, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple2([In]StructWithSHFld sh1, ref StructWithSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple3([In]StructWithSHFld sh1, ref StructWithSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ /// <summary>
+ ///passing structures (with SH subclass fields) as parameters in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1- passing structures (In, out, ref) (with SH subclass fields) individually in separate methods
+ ///2- passing structures (In, out, ref) (with SH subclass fields) in combination in the same method
+ /// </summary>
+ public static void RunSHStructParamTests()
+ {
+ Console.WriteLine("\nRunSHStructParamTests():");
+
+ Console.WriteLine("SHStructParam_In");
+ StructWithSHFld s = new StructWithSHFld();//initialize a new StructWithSHFld
+ s.hnd = Helper.NewSFH(); //get a new SH
+ Int32 hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+ Assert.IsTrue(SHStructParam_In(s, hndInt32), "SHStructParam_In did not receive param as expected.");
+ Assert.IsTrue(!Helper.IsChanged(s.hnd), "SHStructParam_In did not return param as expected.");//check that the value of the HANDLE field did not change
+
+ Console.WriteLine("SHStructParam_Out");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Out(out s), "SHStructParam_Out");
+
+ Console.WriteLine("SHStructParam_OutRetVal");
+ //mangling the unmanaged signature and returning the structure should cause this exception since PInvoke does not support returning
+ //non-blittable value classes
+ Assert.Throws<MarshalDirectiveException>(() => SHStructParam_OutRetVal(), "SHStructParam_OutRetVal");
+
+ Console.WriteLine("SHStructParam_Ref1"); //Testing SHStructParam_Ref1 (does not change value of handle field)
+ s.hnd = Helper.NewSFH(); //get a new SH
+ hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+ Assert.IsTrue(SHStructParam_Ref1(ref s, hndInt32), "SHStructParam_Ref1 did not receive param as expected.");
+ Assert.IsTrue(!Helper.IsChanged(s.hnd), "SHStructParam_Ref1 did not return param as expected."); //check that the value of the HANDLE field is not changed
+
+ Console.WriteLine("SHStructParam_Ref2");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Ref2(ref s, hndInt32), "SHStructParam_Ref2");
+ ///
+ ///2- passing structures (In, out, ref) (with SH subclass fields) in combination in the same method
+ ///
+
+ StructWithSHFld s1 = new StructWithSHFld();//initialize parameters
+ s1.hnd = Helper.NewSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(s1.hnd); //get the 32-bit value associated with s1.hnd
+
+ StructWithSHFld s2; //out parameter
+
+ StructWithSHFld s3 = new StructWithSHFld();
+ s3.hnd = Helper.NewSFH();
+ Int32 hnd3Int32 = Helper.SHInt32(s3.hnd); //get the 32-bit value associated with s3.hnd
+
+ Console.WriteLine("SHStructParam_Multiple1: takes an out struct as one of the params and so is expected to result in an exception");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Multiple1(s1, out s2, ref s3, hnd1Int32, hnd3Int32), "SHStructParam_Multiple1");
+
+ Console.WriteLine("SHStructParam_Multiple2:takes a ref struct as one of the params");
+ s3.hnd = Helper.NewSFH();
+ hnd3Int32 = Helper.SHInt32(s3.hnd); //get the 32-bit value associated with s3.hnd
+ Assert.IsTrue(SHStructParam_Multiple2(s1, ref s3, hnd1Int32, hnd3Int32), "SHStructParam_Multiple2 did not receive parameter(s) as expected.");
+ Assert.IsTrue(!Helper.IsChanged(s1.hnd), "SHStructParam_Multiple2 did not return s1.hnd as expected.");
+ Assert.IsTrue(!Helper.IsChanged(s3.hnd), "SHStructParam_Multiple2 did not return s3.hnd as expected.");
+
+ Console.WriteLine("SHStructParam_Multiple3:takes a ref struct as one of the params aand changes its handle field and so is expected to result in an exception");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Multiple3(s1, ref s3, hnd1Int32, hnd3Int32), "SHStructParam_Multiple3");
+ }
+}
\ No newline at end of file
--- /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>DefaultTest</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="DefaultTest.cs" />
+ <Compile Include="..\*.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.
+
+using System;
+using System.Runtime.InteropServices;
+using SafeHandlesTests;
+
+namespace SafeHandlesTests{
+ public class Helper
+ {
+ public const int N = 3;
+ public const int ReturnValue = 123;
+
+ /// <summary>
+ /// Creates and returns a new SFH_NoCloseHandle
+ /// </summary>
+ /// <returns></returns>
+ public static SFH_NoCloseHandle NewSFH_NoCloseHandle()
+ {
+ String lpFileName = "C.txt";
+ DesiredAccess dwDesiredAccess = DesiredAccess.GENERIC_WRITE;
+ ShareMode dwShareMode = ShareMode.FILE_SHARE_WRITE;
+ IntPtr lpSecurityAttributes = IntPtr.Zero;
+ CreationDisposition dwCreationDisposition = CreationDisposition.CREATE_ALWAYS;
+ FlagsAndAttributes dwFlagsAndAttributes = FlagsAndAttributes.None;
+ IntPtr hTemplateFile = IntPtr.Zero;
+
+ //create the handle
+ SFH_NoCloseHandle hnd = SFH_NoCloseHandle.CreateFile(lpFileName, dwDesiredAccess, dwShareMode,
+ lpSecurityAttributes, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile);
+
+ return hnd;
+ }
+
+ /// <summary>
+ /// Creates and returns a new ChildSFH_NoCloseHandle
+ /// </summary>
+ /// <returns></returns>
+ public static ChildSFH_NoCloseHandle NewChildSFH_NoCloseHandle()
+ {
+ String lpFileName = "D.txt";
+ DesiredAccess dwDesiredAccess = DesiredAccess.GENERIC_WRITE;
+ ShareMode dwShareMode = ShareMode.FILE_SHARE_WRITE;
+ IntPtr lpSecurityAttributes = IntPtr.Zero;
+ CreationDisposition dwCreationDisposition = CreationDisposition.CREATE_ALWAYS;
+ FlagsAndAttributes dwFlagsAndAttributes = FlagsAndAttributes.None;
+ IntPtr hTemplateFile = IntPtr.Zero;
+
+ //create the handle
+ ChildSFH_NoCloseHandle hnd = ChildSFH_NoCloseHandle.CreateChildSafeFileHandle(lpFileName, dwDesiredAccess, dwShareMode,
+ lpSecurityAttributes, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile);
+
+ return hnd;
+ }
+
+ /// <summary>
+ /// Creates and returns a new ChildSafeFileHandle
+ /// </summary>
+ /// <returns></returns>
+ public static ChildSafeFileHandle NewChildSFH()
+ {
+ String lpFileName = "B.txt";
+ DesiredAccess dwDesiredAccess = DesiredAccess.GENERIC_WRITE;
+ ShareMode dwShareMode = ShareMode.FILE_SHARE_WRITE;
+ IntPtr lpSecurityAttributes = IntPtr.Zero;
+ CreationDisposition dwCreationDisposition = CreationDisposition.CREATE_ALWAYS;
+ FlagsAndAttributes dwFlagsAndAttributes = FlagsAndAttributes.None;
+ IntPtr hTemplateFile = IntPtr.Zero;
+
+ //create the handle
+ ChildSafeFileHandle hnd = ChildSafeFileHandle.CreateChildSafeFileHandle(lpFileName, dwDesiredAccess, dwShareMode,
+ lpSecurityAttributes, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile);
+
+ return hnd;
+ }
+
+ /// <summary>
+ /// Creates and returns a new SafeFileHandle
+ /// </summary>
+ /// <returns></returns>
+ public static SafeFileHandle NewSFH()
+ {
+ String lpFileName = "A.txt";
+ DesiredAccess dwDesiredAccess = DesiredAccess.GENERIC_WRITE;
+ ShareMode dwShareMode = ShareMode.FILE_SHARE_WRITE;
+ IntPtr lpSecurityAttributes = IntPtr.Zero;
+ CreationDisposition dwCreationDisposition = CreationDisposition.CREATE_ALWAYS;
+ FlagsAndAttributes dwFlagsAndAttributes = FlagsAndAttributes.None;
+ IntPtr hTemplateFile = IntPtr.Zero;
+
+ //create the handle
+ SafeFileHandle hnd = SafeFileHandle.CreateFile(lpFileName, dwDesiredAccess, dwShareMode,
+ lpSecurityAttributes, dwCreationDisposition,
+ dwFlagsAndAttributes, hTemplateFile);
+
+ return hnd;
+ }
+
+ /// <summary>
+ /// Returns the Int32 value associated with a SFH_NoCloseHandle
+ /// </summary>
+ /// <returns></returns>
+ public static Int32 SHInt32(SFH_NoCloseHandle hnd)
+ {
+ IntPtr hndIntPtr = hnd.DangerousGetHandle(); //get the IntPtr associated with hnd
+ return hndIntPtr.ToInt32(); //return the 32-bit value associated with hnd
+ }
+
+ /// <summary>
+ /// Returns the Int32 value associated with a ChildSFH_NoCloseHandle
+ /// </summary>
+ /// <returns></returns>
+ public static Int32 SHInt32(ChildSFH_NoCloseHandle hnd)
+ {
+ IntPtr hndIntPtr = hnd.DangerousGetHandle(); //get the IntPtr associated with hnd
+ return hndIntPtr.ToInt32(); //return the 32-bit value associated with hnd
+ }
+
+ /// <summary>
+ /// Returns the Int32 value associated with a ChildSafeFileHandle
+ /// </summary>
+ /// <returns></returns>
+ public static Int32 SHInt32(ChildSafeFileHandle hnd)
+ {
+ IntPtr hndIntPtr = hnd.DangerousGetHandle(); //get the IntPtr associated with hnd
+ return hndIntPtr.ToInt32(); //return the 32-bit value associated with hnd
+ }
+
+ /// <summary>
+ /// Returns the Int32 value associated with a SafeFileHandle
+ /// </summary>
+ /// <returns></returns>
+ public static Int32 SHInt32(SafeFileHandle hnd)
+ {
+ IntPtr hndIntPtr = hnd.DangerousGetHandle(); //get the IntPtr associated with hnd
+ return hndIntPtr.ToInt32(); //return the 32-bit value associated with hnd
+ }
+
+ /// <summary>
+ /// Returns the Int32 value associated with a SafeHandle
+ /// </summary>
+ /// <returns></returns>
+ public static Int32 SHInt32(SafeHandle hnd)
+ {
+ IntPtr hndIntPtr = hnd.DangerousGetHandle(); //get the IntPtr associated with hnd
+ return hndIntPtr.ToInt32(); //return the 32-bit value associated with hnd
+ }
+
+ /// <summary>
+ /// Returns true if SH subclass (SFH_NoCloseHandle) value has changed else returns false
+ /// </summary>
+ /// <returns></returns>
+ public static bool IsChanged(SFH_NoCloseHandle hnd)
+ {
+ Int32 hndInt32 = SHInt32(hnd); //get the 32-bit value associated with hnd
+ if (hndInt32 == ReturnValue)
+ return true;
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if ChildSFH_NoCloseHandle value has changed else returns false
+ /// </summary>
+ /// <returns></returns>
+ public static bool IsChanged(ChildSFH_NoCloseHandle hnd)
+ {
+ Int32 hndInt32 = SHInt32(hnd); //get the 32-bit value associated with hnd
+ if (hndInt32 == ReturnValue)
+ return true;
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if SafeFileHandle subclass value has changed else returns false
+ /// </summary>
+ /// <returns></returns>
+ public static bool IsChanged(ChildSafeFileHandle hnd)
+ {
+ Int32 hndInt32 = SHInt32(hnd); //get the 32-bit value associated with hnd
+ if (hndInt32 == ReturnValue)
+ return true;
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if SH subclass value has changed else returns false
+ /// </summary>
+ /// <returns></returns>
+ public static bool IsChanged(SafeFileHandle hnd)
+ {
+ Int32 hndInt32 = SHInt32(hnd); //get the 32-bit value associated with hnd
+ if (hndInt32 == ReturnValue)
+ return true;
+ return false;
+ }
+
+ /// <summary>
+ /// Returns true if SH value has changed else returns false
+ /// </summary>
+ /// <returns></returns>
+ public static bool IsChanged(SafeHandle hnd)
+ {
+ Int32 hndInt32 = SHInt32(hnd); //get the 32-bit value associated with hnd
+ if (hndInt32 == ReturnValue)
+ return true;
+ return false;
+ }
+
+ /// <summary>
+ /// Creates a new StructWithManySHFlds; Fills in arrInt32s with the 32-bit values
+ /// of the handle flds of the struct
+ /// </summary>
+ /// <returns>StructWithManySHFlds</returns>
+ public static StructWithManySHFlds NewStructWithManySHFlds(ref Int32[] arrInt32s)
+ {
+ arrInt32s = new Int32[15]; //size corresponds to the number of flds
+ StructWithManySHFlds s = new StructWithManySHFlds();
+ s.hnd1 = NewSFH(); //get a new SH
+ arrInt32s[0] = SHInt32(s.hnd1);
+ s.hnd2 = NewSFH(); //get a new SH
+ arrInt32s[1] = SHInt32(s.hnd2);
+ s.hnd3 = NewChildSFH(); //get a new SH
+ arrInt32s[2] = SHInt32(s.hnd3);
+ s.hnd4 = NewSFH(); //get a new SH
+ arrInt32s[3] = SHInt32(s.hnd4);
+ s.hnd5 = NewSFH(); //get a new SH
+ arrInt32s[4] = SHInt32(s.hnd5);
+ s.hnd6 = NewChildSFH(); //get a new SH
+ arrInt32s[5] = SHInt32(s.hnd6);
+ s.hnd7 = NewSFH(); //get a new SH
+ arrInt32s[6] = SHInt32(s.hnd7);
+ s.hnd8 = NewSFH(); //get a new SH
+ arrInt32s[7] = SHInt32(s.hnd8);
+ s.hnd9 = NewChildSFH(); //get a new SH
+ arrInt32s[8] = SHInt32(s.hnd9);
+ s.hnd10 = NewSFH(); //get a new SH
+ arrInt32s[9] = SHInt32(s.hnd10);
+ s.hnd11 = NewSFH(); //get a new SH
+ arrInt32s[10] = SHInt32(s.hnd11);
+ s.hnd12 = NewChildSFH(); //get a new SH
+ arrInt32s[11] = SHInt32(s.hnd12);
+ s.hnd13 = NewSFH(); //get a new SH
+ arrInt32s[12] = SHInt32(s.hnd13);
+ s.hnd14 = NewSFH(); //get a new SH
+ arrInt32s[13] = SHInt32(s.hnd14);
+ s.hnd15 = NewChildSFH(); //get a new SH
+ arrInt32s[14] = SHInt32(s.hnd15);
+
+ return s;
+ }
+
+ /// <summary>
+ /// Returns true if any of the handle flds has changed else returns false
+ /// </summary>
+ public static bool IsChangedStructWithManySHFlds(StructWithManySHFlds s, Int32[] arrInt32s)
+ {
+ if (SHInt32(s.hnd1) != arrInt32s[0] || SHInt32(s.hnd2) != arrInt32s[1] || SHInt32(s.hnd3) != arrInt32s[2] ||
+ SHInt32(s.hnd4) != arrInt32s[3] || SHInt32(s.hnd5) != arrInt32s[4] || SHInt32(s.hnd6) != arrInt32s[5] ||
+ SHInt32(s.hnd7) != arrInt32s[6] || SHInt32(s.hnd8) != arrInt32s[7] || SHInt32(s.hnd9) != arrInt32s[8] ||
+ SHInt32(s.hnd10) != arrInt32s[9] || SHInt32(s.hnd11) != arrInt32s[10] || SHInt32(s.hnd12) != arrInt32s[11] ||
+ SHInt32(s.hnd13) != arrInt32s[12] || SHInt32(s.hnd14) != arrInt32s[13] || SHInt32(s.hnd15) != arrInt32s[14])
+ return true;
+ return false;
+ }
+
+ } //end of class Helper
+}
--- /dev/null
+#VCXPROJ
+cmake_minimum_required (VERSION 2.6)
+project (PInvoke_SafeHandle_MarshalAs_Interface)
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
+include_directories("..")
+include_directories(${INC_PLATFORM_DIR})
+set(SOURCES
+ InterfaceNative.cpp
+)
+# Additional files to reference:
+# InterfaceNative.def
+# add the executable
+add_library (PInvoke_SafeHandle_MarshalAs_Interface SHARED ${SOURCES})
+# add the install targets
+install (TARGETS PInvoke_SafeHandle_MarshalAs_Interface 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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <oleauto.h>
+#include <xplatform.h>
+#include "StructDefs.h"
+
+/////////////////////////////////Internal Helper Methods
+/////////////////////////////////
+BOOL static CheckGetIDsOfNamesHR(HRESULT hr)
+{
+ if( FAILED(hr) )
+ {
+ printf("\t\t\tGetIDsOfNames Call FAILED!\n");
+ if( hr == E_OUTOFMEMORY )
+ printf("\t\t\thr == E_OUTOFMEMORY\n");
+ else if( hr == DISP_E_UNKNOWNNAME )
+ printf("\t\t\thr == DISP_E_UNKNOWNNAME\n");
+ else
+ printf("\t\t\thr == DISP_E_UNKNOWNLCID\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL static CheckInvokeHR(HRESULT hr)
+{
+ if( FAILED(hr) )
+ {
+ printf("\t\t\tInvoke FAILED!\n");
+ if( hr == DISP_E_BADPARAMCOUNT )
+ printf("\t\t\thr == DISP_E_BADPARAMCOUNT\n");
+ else if( hr == DISP_E_EXCEPTION )
+ printf("\t\t\thr == DISP_E_EXCEPTION\n");
+ else if( hr == DISP_E_MEMBERNOTFOUND )
+ printf("\t\t\thr == DISP_E_MEMBERNOTFOUND\n");
+ else if( hr == DISP_E_UNKNOWNINTERFACE )
+ printf("\t\t\thr == DISP_E_UNKNOWNINTERFACE\n");
+ else if( hr == DISP_E_BADVARTYPE )
+ printf("\t\t\thr == DISP_E_BADVARTYPE\n");
+ else if( hr == DISP_E_NONAMEDARGS )
+ printf("\t\t\thr == DISP_E_NONAMEDARGS\n");
+ else if( hr == DISP_E_OVERFLOW )
+ printf("\t\t\thr == DISP_E_OVERFLOW\n");
+ else if( hr == DISP_E_PARAMNOTFOUND )
+ printf("\t\t\thr == DISP_E_PARAMNOTFOUND\n");
+ else if( hr == DISP_E_TYPEMISMATCH )
+ printf("\t\t\thr == DISP_E_TYPEMISMATCH\n");
+ else if( hr == DISP_E_UNKNOWNLCID )
+ printf("\t\t\thr == DISP_E_UNKNOWNLCID\n");
+ else
+ printf("\t\t\thr == DISP_E_PARAMNOTOPTIONAL\n");
+ return FALSE;
+ }
+ return TRUE;
+}
+
+BOOL static InvokeAllFldsAndProps(IDispatch* ptoIntf, long shfld1Val, long shfld2Val)
+{
+ HRESULT hr;
+ DISPID dispid_DangerousGetHandle, dispid_IsInvalid, dispid_shfld1, dispid_shfld2_prop;
+ OLECHAR FAR* szMember;
+ VARIANTARG varargs;
+ DISPPARAMS DispParams = {&varargs, NULL, 0, 0};
+ VARIANT VarResult, VarResultBool, VarResultDangHnd;
+
+ printf("\t\t\tCalling GetIDsOfNames() for shfld1...\n");
+ szMember = (LPOLESTR)W("shfld1");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_shfld1);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\tCalling GetIDsOfNames() for shfld2_prop...\n");
+ szMember = (LPOLESTR)W("shfld2_prop");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_shfld2_prop);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ printf("\n");
+
+ //////////////////////////////////////////////////////////////////
+ //NOTE: The SH fld is being returned as type VT_DISPATCH
+ /* printf("\t\t\tInvoking shfld1...\n");
+ hr = ptoIntf->Invoke(dispid_shfld1,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYGET,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ if( VarResult.vt != VT_INT || VarResult.intVal != shfld1Val )
+ {
+ printf("\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+ */
+
+ //Get the property
+ printf("\t\t\tInvoking shfld2_prop (Getting)...\n");
+ hr = ptoIntf->Invoke(dispid_shfld2_prop,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYGET,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ if( VarResult.vt != VT_DISPATCH )
+ {
+ printf("\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+ else //invoke DangerousGetHandle on this SH property using VarResult.pdispVal
+ {
+ printf("\t\t\t\tCalling GetIDsOfNames() for IsInvalid (shfld2_prop)...\n");
+ szMember = (LPOLESTR)W("IsInvalid");
+ hr = (VarResult.pdispVal)->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_IsInvalid);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\t\tInvoking IsInValid (shfld2_prop)...\n");
+ hr = (VarResult.pdispVal)->Invoke(dispid_IsInvalid,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYGET,
+ &DispParams,
+ &VarResultBool,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\t\tCall completed successfully.\n");
+ if( VarResultBool.vt != VT_BOOL || VarResultBool.bVal != 0 ) //should be valid
+ {
+ printf("\t\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+
+ printf("\t\t\t\tCalling GetIDsOfNames() for DangerousGetHandle (shfld2_prop)...\n");
+ szMember = (LPOLESTR)W("DangerousGetHandle");
+ hr = (VarResult.pdispVal)->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_DangerousGetHandle);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\t\tInvoking DangerousGetHandle (shfld2_prop)...\n");
+ hr = (VarResult.pdispVal)->Invoke(dispid_DangerousGetHandle,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_METHOD,
+ &DispParams,
+ &VarResultDangHnd,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\t\tCall completed successfully.\n");
+ if( VarResultDangHnd.vt != VT_INT || VarResultDangHnd.intVal != shfld2Val )
+ {
+ printf("\t\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+
+ } //end of else
+
+ //Set the property to a SFH interface
+ DISPPARAMS DispParams_prop = {&varargs,NULL, 1, 0};
+ DispParams_prop.rgvarg[0].vt = VT_DISPATCH;
+ DispParams_prop.rgvarg[0].pdispVal = ptoIntf; //Set the value of the property to its parent pointer
+ printf("\t\t\tInvoking shfld2_prop (Setting)...\n");
+ hr = ptoIntf->Invoke(dispid_shfld2_prop,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYPUT,
+ &DispParams_prop,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+
+ return TRUE;
+} //end of InvokeAllFldsAndProps
+
+BOOL static InvokeAllInSHIntf(IDispatch* ptoIntf, long shVal, long shfld1Val, long shfld2Val)
+{
+ HRESULT hr;
+ DISPID dispid_DangerousGetHandle, dispid_IsClosed, dispid_IsInvalid, dispid_Close, dispid_Dispose, dispid_SetHandleAsInvalid;
+ OLECHAR FAR* szMember;
+ VARIANTARG varargs;
+ DISPPARAMS DispParams = {&varargs, NULL, 0, 0};
+ VARIANT VarResult;
+
+ ///////////////////////////////////////////////////////////////////
+ printf("\t\t\tCalling GetIDsOfNames() for DangerousGetHandle...\n");
+ szMember = (LPOLESTR)W("DangerousGetHandle");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_DangerousGetHandle);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\tCalling GetIDsOfNames() for IsClosed...\n");
+ szMember = (LPOLESTR)W("IsClosed");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_IsClosed);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\tCalling GetIDsOfNames() for IsInvalid...\n");
+ szMember = (LPOLESTR)W("IsInvalid");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_IsInvalid);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\tCalling GetIDsOfNames() for Close...\n");
+ szMember = (LPOLESTR)W("Close");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_Close);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\tCalling GetIDsOfNames() for Dispose...\n");
+ szMember = (LPOLESTR)W("Dispose");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_Dispose);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ printf("\t\t\tCalling GetIDsOfNames() for SetHandleAsInvalid...\n");
+ szMember = (LPOLESTR)W("SetHandleAsInvalid");
+ hr = ptoIntf->GetIDsOfNames(IID_NULL,
+ &szMember,
+ 1,
+ LOCALE_SYSTEM_DEFAULT,
+ &dispid_SetHandleAsInvalid);
+ if( !CheckGetIDsOfNamesHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+
+ printf("\n");
+ //////////////////////////////////////////////////////////////////
+ printf("\t\t\tInvoking IsInvalid...\n");
+ hr = ptoIntf->Invoke(dispid_IsInvalid,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYGET,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ if( VarResult.vt != VT_BOOL || VarResult.boolVal != 0 )
+ {
+ printf("\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+
+ //////////////////////////////////////////////////////////////////
+ printf("\t\t\tInvoking IsClosed...\n");
+ hr = ptoIntf->Invoke(dispid_IsClosed,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYGET,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ if( VarResult.vt != VT_BOOL || VarResult.boolVal != 0 )
+ {
+ printf("\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+
+ //////////////////////////////////////////////////////////////////
+ printf("\t\t\tInvoking DangerousGetHandle...\n");
+ hr = ptoIntf->Invoke(dispid_DangerousGetHandle,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_METHOD,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ if( VarResult.vt != VT_INT || VarResult.intVal != shVal )
+ {
+ printf("\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ //invoke close repetitively to make sure nothing out of the ordinary happens
+ for(int i = 0; i < 3; i++)
+ {
+ printf("\t\t\tInvoking Close...\n");
+ hr = ptoIntf->Invoke(dispid_Close,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_METHOD,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ }
+
+ /////////////////////////////////////////////////////////////////////
+ printf("\t\t\tInvoking Dispose...\n");
+ hr = ptoIntf->Invoke(dispid_Dispose,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_METHOD,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ /////////////////////////////////////////////////////////////////////
+ /* NOTE: This method should really be named SetHandleAsClosed since it
+ only closes the handle and does not set it to its invalid values; this
+ decision was taken because the runtime would have had to waste storage
+ on remembering what the invalid values for this handle were */
+ printf("\t\t\tInvoking SetHandleAsInvalid...\n");
+ hr = ptoIntf->Invoke(dispid_SetHandleAsInvalid,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_METHOD,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+
+ ////////////////////////////////////////////////////////////////////
+ /* 01/16/04 comment: This check is not needed (see note in previous
+ call); removing because I am also removing the IsClosed check in the
+ IsInvalid property of the handle; since we no longer check IsClosed,
+ calling IsInvalid after SetHandleAsInvalid returns false since
+ SetHandleAsInvalid only closes the handle
+
+ printf("\t\t\tInvoking IsInvalid...\n");
+ hr = ptoIntf->Invoke(dispid_IsInvalid,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYGET,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ if( VarResult.vt != VT_BOOL || VarResult.boolVal != -1 ) //should be invalid since we closed the handle
+ {
+ printf("\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+ */
+ //////////////////////////////////////////////////////////////////
+ printf("\t\t\tInvoking IsClosed...\n");
+ hr = ptoIntf->Invoke(dispid_IsClosed,
+ IID_NULL,
+ LOCALE_SYSTEM_DEFAULT,
+ DISPATCH_PROPERTYGET,
+ &DispParams,
+ &VarResult,
+ NULL,
+ NULL);
+ if( !CheckInvokeHR(hr) )
+ return FALSE;
+ else
+ printf("\t\t\tCall completed successfully.\n");
+ if( VarResult.vt != VT_BOOL || VarResult.boolVal != -1 ) //should be invalid since we closed the handle
+ {
+ printf("\t\t\t\tThe return Variant is incorrect!\n");
+ return FALSE;
+ }
+
+ printf("\n");
+ /////////////////////////////////////////////////////////////
+ ///Invoke SH fields and properties that are defined in SFH class
+ ///////////////////////////////////////////////////////////////////
+ if( !InvokeAllFldsAndProps(ptoIntf, shfld1Val, shfld2Val) )
+ return FALSE;
+
+
+ return TRUE;
+} //end of InvokeAllInSHIntf
+
+
+/////////////////////////////////Exported Methods
+/////////////////////////////////
+
+extern "C" DLL_EXPORT BOOL __stdcall SH_MAIntf(IDispatch* ptoIntf, long shIntfVal, long shfld1Val, long shfld2Val)
+{
+ printf("\t\tIN SH_MAIntf!\n");
+
+ return InvokeAllInSHIntf(ptoIntf, shIntfVal, shfld1Val, shfld2Val);
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SH_MAIntf_Ref(IDispatch** ptoIntf, long shIntfVal, long shfld1Val, long shfld2Val)
+{
+ printf("\t\tIN SH_MAIntf_Ref!\n");
+
+ return InvokeAllInSHIntf(*ptoIntf, shIntfVal, shfld1Val, shfld2Val);
+}
+
+
+extern "C" DLL_EXPORT BOOL __stdcall SHFld_MAIntf(StructMAIntf s, long shndVal, long shfld1Val, long shfld2Val)
+{
+ printf("\t\tIN SHFld_MAIntf!\n");
+
+ return InvokeAllInSHIntf(s.ptoIntf, shndVal, shfld1Val, shfld2Val);
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHObjectParam(VARIANT v, int shVal, int shfld1Val, int shfld2Val, LPSTR objtype)
+{
+ if( strcmp(objtype, "DispatchWrapper") == 0 )
+ {
+ if( v.vt != VT_DISPATCH )
+ {
+ printf("\tSHObjectParam: v.vt != VT_DISPATCH\n");
+ return FALSE;
+ }
+ else //use the IDispatch pointer to invoke some methods
+ return InvokeAllInSHIntf(v.pdispVal, shVal, shfld1Val, shfld2Val);
+ }
+ else if( strcmp(objtype, "UnknownWrapper") == 0 )
+ {
+ if( v.vt != VT_UNKNOWN )
+ {
+ printf("\tSHObjectParam: v.vt != VT_UNKNOWN\n");
+ return FALSE;
+ }
+ else //use the IDispatch pointer to invoke some methods
+ return InvokeAllInSHIntf(v.pdispVal, shVal, shfld1Val, shfld2Val);
+ }
+ else if( strcmp(objtype, "SafeFileHandle") == 0 )
+ {
+ if( v.vt != VT_DISPATCH ) //if the Object implements IDISPATCH, then it is marshaled to VT_DISPATCH
+ {
+ printf("\tSHObjectParam: v.vt != VT_DISPATCH\n");
+ return FALSE;
+ }
+ else //use the IUnknown pointer to QI for IDispatch
+ {
+ HRESULT hr;
+ IDispatch* pIDisp;
+
+ //QI for IDispatch pointer to SH
+ printf("\tSHObjectParam: QI for IDispatch using IUnknown pointer (v.punkVal)\n");
+ hr = v.punkVal->QueryInterface(IID_IDispatch, (void**)&pIDisp);
+ if( FAILED(hr) )
+ {
+ printf("\tSHObjectParam: hr = E_NOINTERFACE\n");
+ return FALSE;
+ }
+ printf("\tSHObjectParam: QI Done\n");
+
+ //use IDispatch pointer obtained from QI
+ return InvokeAllInSHIntf(pIDisp, shVal, shfld1Val, shfld2Val);
+ }
+ }
+ else
+ {
+ printf("\tSHObjectParam: ERROR! String param is not as expected!\n");
+ printf("\tSHObjectParam: objtype = %s\n",objtype);
+ return FALSE;
+ }
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHStructWithObjectFldParam(StructWithVARIANTFld s, int shVal, int shfld1Val, int shfld2Val, LPSTR objtype)
+{
+ if( strcmp(objtype, "DispatchWrapper") == 0 )
+ {
+ if( s.v.vt != VT_DISPATCH )
+ {
+ printf("\tSHStructWithObjectFldParam: s.v.vt != VT_DISPATCH\n");
+ return FALSE;
+ }
+ else //use the IDispatch pointer to invoke some methods
+ return InvokeAllInSHIntf(s.v.pdispVal, shVal, shfld1Val, shfld2Val);
+ }
+ else if( strcmp(objtype, "UnknownWrapper") == 0 )
+ {
+ if( s.v.vt != VT_UNKNOWN )
+ {
+ printf("\tSHStructWithObjectFldParam: s.v.vt != VT_UNKNOWN\n");
+ return FALSE;
+ }
+ else //use the IUnknown pointer to QI for IDispatch
+ {
+ HRESULT hr;
+ IDispatch* pIDisp;
+
+ //QI for IDispatch pointer to SH
+ printf("\tSHStructWithObjectFldParam: QI for IDispatch using IUnknown pointer (s.v.punkVal)\n");
+ hr = s.v.punkVal->QueryInterface(IID_IDispatch, (void**)&pIDisp);
+ if( FAILED(hr) )
+ {
+ printf("\tSHStructWithObjectFldParam: hr = E_NOINTERFACE\n");
+ return FALSE;
+ }
+ printf("\tSHStructWithObjectFldParam: QI Done\n");
+
+ //use IDispatch pointer obtained from QI
+ return InvokeAllInSHIntf(pIDisp, shVal, shfld1Val, shfld2Val);
+ }
+ }
+ else if( strcmp(objtype, "SafeFileHandle") == 0 )
+ {
+ if( s.v.vt != VT_DISPATCH )
+ {
+ printf("\tSHStructWithObjectFldParam: s.v.vt != VT_DISPATCH\n");
+ return FALSE;
+ }
+ else //use the IDispatch pointer to invoke some methods
+ return InvokeAllInSHIntf(s.v.pdispVal, shVal, shfld1Val, shfld2Val);
+ }
+ else
+ {
+ printf("\tSHStructWithObjectFldParam: ERROR! String param is not as expected!\n");
+ printf("\tSHStructWithObjectFldParam: objtype = %s\n",objtype);
+ return FALSE;
+ }
+}
--- /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.Runtime.InteropServices;
+using SafeHandlesTests;
+using System.Threading;
+using TestLibrary;
+
+[StructLayout(LayoutKind.Sequential)]
+public struct StructMAIntf
+{
+ [MarshalAs(UnmanagedType.Interface)]
+ public SafeFileHandle hnd;
+}
+
+public class SHtoIntfTester
+{
+ public static int Main()
+ {
+ try
+ {
+ RunTests();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+
+ [DllImport("PInvoke_SafeHandle_MarshalAs_Interface")]
+ public static extern bool SH_MAIntf([MarshalAs(UnmanagedType.Interface)]SafeFileHandle sh, Int32 shVal, Int32 shfld1Val, Int32 shfld2Val);
+
+ [DllImport("PInvoke_SafeHandle_MarshalAs_Interface")]
+ public static extern bool SH_MAIntf_Ref([MarshalAs(UnmanagedType.Interface)]ref SafeFileHandle sh, Int32 shVal, Int32 shfld1Val, Int32 shfld2Val);
+
+ [DllImport("PInvoke_SafeHandle_MarshalAs_Interface")]
+ public static extern bool SHFld_MAIntf(StructMAIntf s, Int32 shndVal, Int32 shfld1Val, Int32 shfld2Val);
+
+ public static void RunTests()
+ {
+ Console.WriteLine("RunTests started");
+
+ ////////////////////////////////////////////////////////
+ SafeFileHandle sh = Helper.NewSFH();
+ Int32 shVal = Helper.SHInt32(sh);
+ sh.shfld1 = Helper.NewSFH(); //SH field of SFH class
+ Int32 shfld1Val = Helper.SHInt32(sh.shfld1);
+ sh.shfld2 = Helper.NewSFH(); //SFH field of SFH class
+ Int32 shfld2Val = Helper.SHInt32(sh.shfld2);
+
+ //NOTE: SafeHandle is now ComVisible(false)...QIs for IDispatch or the class interface on a
+ // type with a ComVisible(false) type in its hierarchy are no longer allowed; so calling
+ // the DW ctor with a SH subclass causes an invalidoperationexception to be thrown since
+ // the ctor QIs for IDispatch
+ Console.WriteLine("Testing SH_MAIntf...");
+ Assert.Throws<InvalidOperationException>(() => SH_MAIntf(sh, shVal, shfld1Val, shfld2Val), "Did not throw InvalidOperationException!");
+
+ ////////////////////////////////////////////////////////
+ sh = Helper.NewSFH();
+ shVal = Helper.SHInt32(sh);
+ sh.shfld1 = Helper.NewSFH(); //SH field of SFH class
+ shfld1Val = Helper.SHInt32(sh.shfld1);
+ sh.shfld2 = Helper.NewSFH(); //SFH field of SFH class
+ shfld2Val = Helper.SHInt32(sh.shfld2);
+
+ //NOTE: SafeHandle is now ComVisible(false)...QIs for IDispatch or the class interface on a
+ // type with a ComVisible(false) type in its hierarchy are no longer allowed; so calling
+ // the DW ctor with a SH subclass causes an invalidoperationexception to be thrown since
+ // the ctor QIs for IDispatch
+ Console.WriteLine("Testing SH_MAIntf_Ref...");
+ Assert.Throws<InvalidOperationException>(() => SH_MAIntf_Ref(ref sh, shVal, shfld1Val, shfld2Val), "Did not throw InvalidOperationException!");
+
+ ////////////////////////////////////////////////////////
+ StructMAIntf s = new StructMAIntf();
+ s.hnd = Helper.NewSFH();
+ Int32 shndVal = Helper.SHInt32(s.hnd);
+ s.hnd.shfld1 = Helper.NewSFH(); //SH field of SFH field of struct
+ shfld1Val = Helper.SHInt32(s.hnd.shfld1);
+ s.hnd.shfld2 = Helper.NewSFH(); //SFH field of SFH field of struct
+ shfld2Val = Helper.SHInt32(s.hnd.shfld2);
+
+ //NOTE: SafeHandle is now ComVisible(false)...QIs for IDispatch or the class interface on a
+ // type with a ComVisible(false) type in its hierarchy are no longer allowed; so calling
+ // the DW ctor with a SH subclass causes an invalidoperationexception to be thrown since
+ // the ctor QIs for IDispatch
+ Console.WriteLine("Testing SHFld_MAIntf...");
+ Assert.Throws<InvalidOperationException>(() => SHFld_MAIntf(s, shndVal, shfld1Val, shfld2Val), "Did not throw InvalidOperationException!");
+
+ Console.WriteLine("RunTests end");
+ }
+}
\ No newline at end of file
--- /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>InterfaceTest</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="InterfaceTest.cs" />
+ <Compile Include="..\*.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.
+
+using System;
+using System.Runtime.InteropServices;
+using SafeHandlesTests;
+using TestLibrary;
+
+#pragma warning disable 618
+public class SHTester_MA
+{
+ public static int Main()
+ {
+ try
+ {
+ RunSHInvalidMATests();
+ RunSHInvalidretMATests();
+ RunSHFldInvalidMATests();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+
+ }
+
+ /// <summary>
+ /// All the invalid MarshalAs signatures follow
+ /// </summary>
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA1([MarshalAs(UnmanagedType.AnsiBStr)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA2([MarshalAs(UnmanagedType.AsAny)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA3([MarshalAs(UnmanagedType.Bool)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA4([MarshalAs(UnmanagedType.BStr)]SafeFileHandle sh);
+
+ // NOTE: Specified unmanaged type is only valid on fields.
+ //[DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError=true)]
+ //public static extern bool SHInvalid_MA5([MarshalAs(UnmanagedType.ByValArray)]SafeFileHandle sh);
+
+ //NOTE: Specified unmanaged type is only valid on fields.
+ //[DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError=true)]
+ //public static extern bool SHInvalid_MA6([MarshalAs(UnmanagedType.ByValTStr, SizeConst=10)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA7([MarshalAs(UnmanagedType.Currency)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA9([MarshalAs(UnmanagedType.Error)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA10([MarshalAs(UnmanagedType.FunctionPtr)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA11([MarshalAs(UnmanagedType.I1)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA12([MarshalAs(UnmanagedType.I2)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA13([MarshalAs(UnmanagedType.I4)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA14([MarshalAs(UnmanagedType.I8)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA15([MarshalAs(UnmanagedType.IDispatch)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA16([MarshalAs(UnmanagedType.Interface)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA17([MarshalAs(UnmanagedType.IUnknown)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA18([MarshalAs(UnmanagedType.LPArray)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA19([MarshalAs(UnmanagedType.LPStr)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA20([MarshalAs(UnmanagedType.LPStruct)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA21([MarshalAs(UnmanagedType.LPTStr)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA22([MarshalAs(UnmanagedType.LPWStr)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA23([MarshalAs(UnmanagedType.R4)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA24([MarshalAs(UnmanagedType.R8)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA25([MarshalAs(UnmanagedType.SafeArray)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA26([MarshalAs(UnmanagedType.Struct)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA27([MarshalAs(UnmanagedType.SysInt)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA28([MarshalAs(UnmanagedType.SysUInt)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA29([MarshalAs(UnmanagedType.TBStr)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA30([MarshalAs(UnmanagedType.U1)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA31([MarshalAs(UnmanagedType.U2)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA32([MarshalAs(UnmanagedType.U4)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA33([MarshalAs(UnmanagedType.U8)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA34([MarshalAs(UnmanagedType.VariantBool)]SafeFileHandle sh);
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_MA", SetLastError = true)]
+ public static extern bool SHInvalid_MA35([MarshalAs(UnmanagedType.VBByRefStr)]SafeFileHandle sh);
+
+ /// <summary>
+ ///runs all tests involving pinvoke signatures with invalid MarshalAs attributes
+ /// </summary>
+ public static void RunSHInvalidMATests()
+ {
+ Console.WriteLine("\nRunSHInvalidMATests():");
+
+ SafeFileHandle hnd = Helper.NewSFH();
+
+ Console.WriteLine("Testing SHInvalid_MA1...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA1(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA2...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA2(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA3...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA3(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA4...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA4(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("SHInvalid_MA5 cannot be tested (see PInvoke signatures in test source for comments)...");
+ Console.WriteLine("SHInvalid_MA6 cannot be tested (see PInvoke signatures in test source for comments)...");
+
+ Console.WriteLine("Testing SHInvalid_MA7...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA7(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("SHInvalid_MA8 cannot be tested (see PInvoke signatures in test source for comments)...");
+
+ Console.WriteLine("Testing SHInvalid_MA9...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA9(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA10...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA10(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA11...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA11(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA12...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA12(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA13...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA13(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA14...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA14(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA15...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA15(hnd), "FAILED! Exception not thrown.");
+
+ //NOTE: UnmanagedType.Interface is the only MA attribute that is valid
+ //Console.WriteLine("Testing SHInvalid_MA16...");
+
+ Console.WriteLine("Testing SHInvalid_MA17...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA17(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA18...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA18(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA19...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA19(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA20...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA20(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA21...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA21(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA22...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA22(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA23...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA23(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA24...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA24(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA25...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA25(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA26...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA26(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA27...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA27(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA28...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA28(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA29...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA29(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA30...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA30(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA31...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA31(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA32...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA32(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA33...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA33(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA34...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA34(hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_MA35...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_MA35(hnd), "FAILED! Exception not thrown.");
+ }
+
+ /// <summary>
+ /// All the invalid return MarshalAs signatures follow
+ /// </summary>
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.AnsiBStr)]
+ public static extern SafeFileHandle SHInvalid_retMA1();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.AsAny)]
+ public static extern SafeFileHandle SHInvalid_retMA2();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ public static extern SafeFileHandle SHInvalid_retMA3();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.BStr)]
+ public static extern SafeFileHandle SHInvalid_retMA4();
+
+ //NOTE: Specified unmanaged type is only valid on fields.
+ //[DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError=true)]
+ //[return:MarshalAs(UnmanagedType.ByValArray)]
+ //public static extern SafeFileHandle SHInvalid_retMA5();
+
+ //NOTE: Specified unmanaged type is only valid on fields.
+ //[DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError=true)]
+ //[return:MarshalAs(UnmanagedType.ByValTStr)]
+ //public static extern SafeFileHandle SHInvalid_retMA6();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Currency)]
+ public static extern SafeFileHandle SHInvalid_retMA7();
+
+ //NOTE: Specified unmanaged type also needs MarshalType or MarshalTypeRef which indicate the custom marshaler
+ //[DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError=true)]
+ //[return:MarshalAs(UnmanagedType.CustomMarshaler)]
+ //public static extern SafeFileHandle SHInvalid_retMA8();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Error)]
+ public static extern SafeFileHandle SHInvalid_retMA9();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.FunctionPtr)]
+ public static extern SafeFileHandle SHInvalid_retMA10();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.I1)]
+ public static extern SafeFileHandle SHInvalid_retMA11();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.I2)]
+ public static extern SafeFileHandle SHInvalid_retMA12();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.I4)]
+ public static extern SafeFileHandle SHInvalid_retMA13();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.I8)]
+ public static extern SafeFileHandle SHInvalid_retMA14();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.IDispatch)]
+ public static extern SafeFileHandle SHInvalid_retMA15();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Interface)]
+ public static extern SafeFileHandle SHInvalid_retMA16();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.IUnknown)]
+ public static extern SafeFileHandle SHInvalid_retMA17();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.LPArray)]
+ public static extern SafeFileHandle SHInvalid_retMA18();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.LPStr)]
+ public static extern SafeFileHandle SHInvalid_retMA19();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.LPStruct)]
+ public static extern SafeFileHandle SHInvalid_retMA20();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.LPTStr)]
+ public static extern SafeFileHandle SHInvalid_retMA21();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.LPWStr)]
+ public static extern SafeFileHandle SHInvalid_retMA22();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.R4)]
+ public static extern SafeFileHandle SHInvalid_retMA23();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.R8)]
+ public static extern SafeFileHandle SHInvalid_retMA24();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.SafeArray)]
+ public static extern SafeFileHandle SHInvalid_retMA25();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Struct)]
+ public static extern SafeFileHandle SHInvalid_retMA26();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.SysInt)]
+ public static extern SafeFileHandle SHInvalid_retMA27();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.SysUInt)]
+ public static extern SafeFileHandle SHInvalid_retMA28();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.TBStr)]
+ public static extern SafeFileHandle SHInvalid_retMA29();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.U1)]
+ public static extern SafeFileHandle SHInvalid_retMA30();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.U2)]
+ public static extern SafeFileHandle SHInvalid_retMA31();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.U4)]
+ public static extern SafeFileHandle SHInvalid_retMA32();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.U8)]
+ public static extern SafeFileHandle SHInvalid_retMA33();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.VariantBool)]
+ public static extern SafeFileHandle SHInvalid_retMA34();
+
+ [DllImport("PInvoke_SafeHandle", EntryPoint="SHInvalid_retMA", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.VBByRefStr)]
+ public static extern SafeFileHandle SHInvalid_retMA35();
+
+ /// <summary>
+ ///runs all tests involving pinvoke signatures with invalid return MarshalAs attributes
+ /// </summary>
+ public static void RunSHInvalidretMATests()
+ {
+ Console.WriteLine("\nRunSHInvalidretMATests():");
+
+ Console.WriteLine("Testing SHInvalid_retMA1...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA1(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA2...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA2(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA3...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA3(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA4...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA4(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("SHInvalid_retMA5 cannot be tested (see PInvoke signatures in test source for comments)...");
+ Console.WriteLine("SHInvalid_retMA6 cannot be tested (see PInvoke signatures in test source for comments)...");
+
+ Console.WriteLine("Testing SHInvalid_retMA7...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA7(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("SHInvalid_retMA8 cannot be tested (see PInvoke signatures in test source for comments)...");
+
+ Console.WriteLine("Testing SHInvalid_retMA9...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA9(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA10...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA10(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA11...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA11(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA12...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA12(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA13...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA13(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA14...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA14(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA15...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA15(), "FAILED! Exception not thrown.");
+
+ //NOTE: If the return type is marked as Unman.Intf, then the unmanaged code should return an Interface
+ // pointer and not an integer---doing so will cause unexpected behavior
+ /*
+ Console.WriteLine("Testing SHInvalid_retMA16...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA16(), "FAILED! Exception not thrown.");
+ */
+
+ Console.WriteLine("Testing SHInvalid_retMA17...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA17(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA18...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA18(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA19...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA19(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA20...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA20(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA21...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA21(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA22...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA22(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA23...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA23(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA24...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA24(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA25...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA25(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA26...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA26(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA27...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA27(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA28...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA28(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA29...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA29(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA30...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA30(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA31...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA31(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA32...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA32(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA33...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA33(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA34...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA34(), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHInvalid_retMA35...");
+ Assert.Throws<MarshalDirectiveException>(() => SHInvalid_retMA35(), "FAILED! Exception not thrown.");
+ }
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA1 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA2 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA3 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA4 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA5 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA6 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA7 s);
+
+ //NOTE: no corresponding struct definition
+ //[DllImport("PInvoke_SafeHandle", SetLastError=true)]
+ //public static extern bool SHFldInvalid_MA(StructMA8 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA9 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA10 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA11 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA12 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA13 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA14 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA15 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA16 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA17 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA18 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA19 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA20 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA21 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA22 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA23 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA24 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA25 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA26 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA27 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA28 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA29 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA30 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA31 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA32 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA33 s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHFldInvalid_MA(StructMA34 s);
+
+ /// <summary>
+ ///runs all tests involving pinvoke signatures passing/returning structures
+ ///containing SH fields with invalid MarshalAs attributes
+ /// </summary>
+ public static void RunSHFldInvalidMATests()
+ {
+ Console.WriteLine("\nRunSHFldInvalidMATests():");
+
+ StructMA1 s1 = new StructMA1();
+ s1.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA1...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s1), "FAILED! Exception not thrown.");
+
+ StructMA2 s2 = new StructMA2();
+ s2.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA2...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s2), "FAILED! Exception not thrown.");
+
+ StructMA3 s3 = new StructMA3();
+ s3.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA3...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s3), "FAILED! Exception not thrown.");
+
+ StructMA4 s4 = new StructMA4();
+ s4.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA4...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s4), "FAILED! Exception not thrown.");
+
+ StructMA5 s5 = new StructMA5();
+ s5.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA5...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s5), "FAILED! Exception not thrown.");
+
+ StructMA6 s6 = new StructMA6();
+ s6.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA6...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s6), "FAILED! Exception not thrown.");
+
+ StructMA7 s7 = new StructMA7();
+ s7.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA7...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s7), "FAILED! Exception not thrown.");
+
+ /*
+ StructMA8 s8 = new StructMA8();
+ s5.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA8...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s8), "FAILED! Exception not thrown.");
+ */
+
+ StructMA9 s9 = new StructMA9();
+ s9.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA9...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s9), "FAILED! Exception not thrown.");
+
+ StructMA10 s10 = new StructMA10();
+ s10.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA10...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s10), "FAILED! Exception not thrown.");
+
+ StructMA11 s11 = new StructMA11();
+ s11.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA11...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s11), "FAILED! Exception not thrown.");
+
+ StructMA12 s12 = new StructMA12();
+ s12.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA12...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s12), "FAILED! Exception not thrown.");
+
+ StructMA13 s13 = new StructMA13();
+ s13.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA13...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s13), "FAILED! Exception not thrown.");
+
+ StructMA14 s14 = new StructMA14();
+ s14.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA14...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s14), "FAILED! Exception not thrown.");
+
+ StructMA15 s15 = new StructMA15();
+ s15.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA15...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s15), "FAILED! Exception not thrown.");
+
+ //NOTE: UnmanagedType.Interface is the only MA attribute allowed
+ /*
+ StructMA16 s16 = new StructMA16();
+ s16.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA16...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s16), "FAILED! Exception not thrown.");
+ */
+
+ StructMA17 s17 = new StructMA17();
+ s17.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA17...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s17), "FAILED! Exception not thrown.");
+
+ StructMA18 s18 = new StructMA18();
+ s18.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA18...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s18), "FAILED! Exception not thrown.");
+
+ StructMA19 s19 = new StructMA19();
+ s19.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA19...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s19), "FAILED! Exception not thrown.");
+
+ StructMA20 s20 = new StructMA20();
+ s20.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA20...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s20), "FAILED! Exception not thrown.");
+
+ StructMA21 s21 = new StructMA21();
+ s21.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA21...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s21), "FAILED! Exception not thrown.");
+
+ StructMA22 s22 = new StructMA22();
+ s22.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA22...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s22), "FAILED! Exception not thrown.");
+
+ StructMA23 s23 = new StructMA23();
+ s23.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA23...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s23), "FAILED! Exception not thrown.");
+
+ StructMA24 s24 = new StructMA24();
+ s24.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA24...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s24), "FAILED! Exception not thrown.");
+
+ StructMA25 s25 = new StructMA25();
+ s25.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA25...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s25), "FAILED! Exception not thrown.");
+
+ StructMA26 s26 = new StructMA26();
+ s26.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA26...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s26), "FAILED! Exception not thrown.");
+
+ StructMA27 s27 = new StructMA27();
+ s27.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA27...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s27), "FAILED! Exception not thrown.");
+
+ StructMA28 s28 = new StructMA28();
+ s28.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA28...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s28), "FAILED! Exception not thrown.");
+
+ StructMA29 s29 = new StructMA29();
+ s29.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA29...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s29), "FAILED! Exception not thrown.");
+
+ StructMA30 s30 = new StructMA30();
+ s30.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA30...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s30), "FAILED! Exception not thrown.");
+
+ StructMA31 s31 = new StructMA31();
+ s31.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA31...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s31), "FAILED! Exception not thrown.");
+
+ StructMA32 s32 = new StructMA32();
+ s32.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA32...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s32), "FAILED! Exception not thrown.");
+
+ StructMA33 s33 = new StructMA33();
+ s33.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA33...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s33), "FAILED! Exception not thrown.");
+
+ StructMA34 s34 = new StructMA34();
+ s34.hnd = Helper.NewSFH();
+ Console.WriteLine("Testing StructMA34...");
+ Assert.Throws<TypeLoadException>(() => SHFldInvalid_MA(s34), "FAILED! Exception not thrown.");
+ }
+}
+#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>InvalidMarshalAsTest</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="InvalidMarshalAsTest.cs" />
+ <Compile Include="..\*.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.
+
+using System;
+using System.Runtime.InteropServices;
+using SafeHandlesTests;
+using TestLibrary;
+
+public class SHTester_Misc
+{
+ public static int Main()
+ {
+ try
+ {
+ RunSHMiscTests();
+ RunChildSHStructParamTests();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHArrayParam(SafeFileHandle[] arr, Int32[] arrInt32s, int length);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern StructWithSHFld SHReturnStruct();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_In2([In]StructWithSHArrayFld s, Int32[] arrInt32s, int length);
+
+ /// <summary>
+ ///runs all other miscellaneous tests;
+ ///it uses the PInvoke signatures defined above it
+ ///1-passing arrays of SHs as parameters
+ ///2-passing arrays of structures (with SH subclass fields) as parameters
+ ///3-returning SHs from unmanaged code as pure return values
+ ///4-returning structures (with SH subclass fields) from unmanaged code as pure return values
+ ///5-passing nested structures (with the nested structure having a SH subclass field)
+ ///6-passing structures with SH Array fields
+ ///7-passing mixed params (SH, SH subclass, subclass of SH subclass)
+ ///8-passing struct params that have many handle fields [in, ref (with and without changes to flds)]
+ ///9-passing SH subclass in Dispatch\UnknownWrapper, expecting a VARIANT (of type VT_DISPATCH or
+ ///VT_UNKNOWN) on the managed side; as params and as fields
+ /// </summary>
+ public static void RunSHMiscTests()
+ {
+ Console.WriteLine("\nRunSHMiscTests():");
+
+ ///1-passing arrays of SHs as parameters
+
+ SafeFileHandle[] hndArray = new SafeFileHandle[Helper.N];
+ //the following array will contain the 32-bit values corresponding to hndArray's elements
+ Int32[] hndArrayInt32s = new Int32[Helper.N];
+ for (int i = 0; i < Helper.N; i++)
+ {
+ hndArray[i] = Helper.NewSFH();
+ hndArrayInt32s[i] = Helper.SHInt32(hndArray[i]);
+ }
+ Console.WriteLine("Testing SHArrayParam...");
+ Assert.Throws<MarshalDirectiveException>(() => SHArrayParam(hndArray, hndArrayInt32s, Helper.N), "FAILED! Exception not thrown.");
+
+ //4-returning structures (with SH subclass fields) from unmanaged code as pure return values
+ Console.WriteLine("Testing SHReturnStruct...");
+ Assert.Throws<MarshalDirectiveException>(() => SHReturnStruct(), "FAILED! Exception not thrown.");
+
+ //6-passing structures with SH Array fields
+ hndArray = new SafeFileHandle[Helper.N];
+ //the following array will contain the 32-bit values corresponding to hndArray's elements
+ hndArrayInt32s = new Int32[Helper.N];
+ for (int i = 0; i < Helper.N; i++)
+ {
+ hndArray[i] = Helper.NewSFH();
+ hndArrayInt32s[i] = Helper.SHInt32(hndArray[i]);
+ }
+ StructWithSHArrayFld sWithArrFld = new StructWithSHArrayFld();
+ sWithArrFld.sharr = hndArray; //assign hnd array to hnd array field
+ Console.WriteLine("Testing SHStructParam_In2...");
+ Assert.Throws<TypeLoadException>(() => SHStructParam_In2(sWithArrFld, hndArrayInt32s, Helper.N), "FAILED! Exception not thrown.");
+ }
+
+ /// <summary>
+ ///passing SafeFileHandle subclass parameters to unmanaged code in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1-passing SafeFileHandle subclass parameters individually in separate methods (In, out, ref)
+ ///2-passing SafeFileHandle subclass parameters in combination in the same method
+ /// </summary>
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern StructWithChildSHFld SHStructParam_OutRetVal();
+
+ /// <summary>
+ ///passing structures (with SafeFileHandle subclass fields) as parameters in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1-passing structures (In, out, ref) (with SafeFileHandle subclass fields) individually in separate methods
+ ///2-passing structures (In, out, ref) (with SafeFileHandle subclass fields) in combination in the same method
+ /// </summary>
+ public static void RunChildSHStructParamTests()
+ {
+ Console.WriteLine("\nRunChildSHStructParamTests():");
+
+ StructWithChildSHFld s = new StructWithChildSHFld();
+ s.hnd = Helper.NewChildSFH(); //get a new SH
+ Int32 hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+
+ Console.WriteLine("Testing SHStructParam_OutRetVal...");
+ Assert.Throws<MarshalDirectiveException>(() => s = SHStructParam_OutRetVal(), "FAILED! Exception not thrown.");
+ }
+}
\ No newline at end of file
--- /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>MiscUnsupportedTest</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="MiscUnsupportedTest.cs" />
+ <Compile Include="..\*.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.
+
+using System;
+using System.Runtime.InteropServices;
+using SafeHandlesTests;
+using TestLibrary;
+
+#pragma warning disable 618
+public class SHTester_Misc
+{
+ public static int Main()
+ {
+ try
+ {
+ RunSHMiscTests();
+ RunChildSHParamTests();
+ RunChildSHStructParamTests();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructArrayParam(StructWithSHFld[] arr, Int32[] arrInt32s, int length);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern SFH_NoCloseHandle SHReturn();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructNestedParam(StructNestedParent sn, Int32 arrInt32s);
+
+ [DllImport("PInvoke_SafeHandle")]
+ public static extern bool SHMixedParam1(SafeHandle sh1, out SFH_NoCloseHandle sh2, ref ChildSFH_NoCloseHandle sh3, StructWithBaseSHFld s1,
+ StructWithSHFld s2, ref StructWithChildSHFld s3, Int32 sh1Value, Int32 sh3Value, Int32 s1fldValue, Int32 s2fldValue, Int32 s3fldValue);
+
+ [DllImport("PInvoke_SafeHandle")]
+ public static extern bool SHStructWithManySHFldsParam_In(StructWithManySHFlds s, Int32[] arrInt32s);
+
+ [DllImport("PInvoke_SafeHandle")]
+ public static extern bool SHStructWithManySHFldsParam_Ref1(ref StructWithManySHFlds s, Int32[] arrInt32s);
+
+ [DllImport("PInvoke_SafeHandle")]
+ public static extern bool SHStructWithManySHFldsParam_Ref2(ref StructWithManySHFlds s, Int32[] arrInt32s);
+
+ [DllImport(@"PInvoke_SafeHandle_MarshalAs_Interface.dll", CharSet = CharSet.Ansi)] //the MA attribute indicates that obj is to be marshaled as a VARIANT
+ public static extern bool SHObjectParam([MarshalAs(UnmanagedType.Struct)]Object obj, Int32 shValue, Int32 shfld1Value, Int32 shfld2Value, String wrapper);
+
+ [DllImport(@"PInvoke_SafeHandle_MarshalAs_Interface.dll", CharSet = CharSet.Ansi)]
+ public static extern bool SHStructWithObjectFldParam(StructWithObjFld s, Int32 shValue, Int32 shfld1Value, Int32 shfld2Value, String objtype);
+
+ /// <summary>
+ ///runs all other miscellaneous tests;
+ ///it uses the PInvoke signatures defined above it
+ ///1-passing arrays of SHs as parameters
+ ///2-passing arrays of structures (with SH subclass fields) as parameters
+ ///3-returning SHs from unmanaged code as pure return values
+ ///4-returning structures (with SH subclass fields) from unmanaged code as pure return values
+ ///5-passing nested structures (with the nested structure having a SH subclass field)
+ ///6-passing structures with SH Array fields
+ ///7-passing mixed params (SH, SH subclass, subclass of SH subclass)
+ ///8-passing struct params that have many handle fields [in, ref (with and without changes to flds)]
+ ///9-passing SH subclass in Dispatch\UnknownWrapper, expecting a VARIANT (of type VT_DISPATCH or
+ ///VT_UNKNOWN) on the managed side; as params and as fields
+ /// </summary>
+ public static void RunSHMiscTests()
+ {
+ Console.WriteLine("\nRunSHMiscTests():");
+
+ SafeFileHandle[] hndArray = new SafeFileHandle[Helper.N];
+ //the following array will contain the 32-bit values corresponding to hndArray's elements
+ Int32[] hndArrayInt32s = new Int32[Helper.N];
+
+ //2-passing arrays of structures (with SH subclass fields) as parameters
+ StructWithSHFld[] structArray = new StructWithSHFld[Helper.N];
+ //the following array will contain the 32-bit values corresponding to structArray's elements
+ Int32[] structArrayInt32s = new Int32[Helper.N];
+ for (int i = 0; i < Helper.N; i++)
+ {
+ structArray[i] = new StructWithSHFld();
+ structArray[i].hnd = Helper.NewSFH();
+ structArrayInt32s[i] = Helper.SHInt32(structArray[i].hnd);
+ }
+
+ Console.WriteLine("Testing SHStructArrayParam...");
+ Assert.Throws<InvalidOperationException>(() => SHStructArrayParam(structArray, structArrayInt32s, Helper.N), "FAILED! Expected Exception Not Thrown!");
+
+ //3-returning SHs from unmanaged code as pure return values
+ SFH_NoCloseHandle hnd;
+ Console.WriteLine("Testing SHReturn...");
+ hnd = SHReturn();
+ Assert.IsTrue(Helper.IsChanged(hnd), "FAILED! SHReturn did not return hnd as expected.");
+
+ //5-passing nested structures (with the nested structure having a SH subclass field)
+ StructNestedParent sn = new StructNestedParent();
+ sn.snOneDeep = new StructNestedOneDeep();
+ sn.snOneDeep.s = new StructWithSHFld();
+ sn.snOneDeep.s.hnd = Helper.NewSFH();
+ Int32 hndInt32 = Helper.SHInt32(sn.snOneDeep.s.hnd);
+ Console.WriteLine("Testing SHStructNestedParam...");
+ Assert.IsTrue(SHStructNestedParam(sn, hndInt32), "FAILED! SHStructNestedParam did not receive param as expected.");
+ //check that the value of the HANDLE field did not change
+ Assert.IsFalse(Helper.IsChanged(sn.snOneDeep.s.hnd), "FAILED! SHStructNestedParam did not return param as expected.");
+
+ //7-passing mixed params (SH, SH subclass, subclass of SH subclass)
+ SafeHandle sh1 = Helper.NewSFH();
+ SFH_NoCloseHandle sh2;
+ ChildSFH_NoCloseHandle sh3 = Helper.NewChildSFH_NoCloseHandle();
+ StructWithBaseSHFld s1 = new StructWithBaseSHFld(); s1.hnd = Helper.NewSFH();
+ StructWithSHFld s2 = new StructWithSHFld(); s2.hnd = Helper.NewSFH();
+ StructWithChildSHFld s3 = new StructWithChildSHFld(); s3.hnd = Helper.NewChildSFH();
+ Int32 sh1Value = Helper.SHInt32(sh1);
+ Int32 sh3Value = Helper.SHInt32(sh3);
+ Int32 s1fldValue = Helper.SHInt32(s1.hnd);
+ Int32 s2fldValue = Helper.SHInt32(s2.hnd);
+ Int32 s3fldValue = Helper.SHInt32(s3.hnd);
+
+ Console.WriteLine("Testing SHMixedParam1...");
+ Assert.IsTrue(SHMixedParam1(sh1, out sh2, ref sh3, s1, s2, ref s3, sh1Value, sh3Value, s1fldValue, s2fldValue, s3fldValue), "FAILED! SHMixedParam1 did not receive params as expected.");
+ //check the values after the call
+ Assert.IsFalse(Helper.IsChanged(sh1) || !Helper.IsChanged(sh2) || Helper.IsChanged(sh3) || Helper.IsChanged(s1.hnd) ||
+ Helper.IsChanged(s2.hnd) || Helper.IsChanged(s3.hnd), "FAILED! SHMixedParam1 did not return params as expected.");
+
+ //8-passing struct params that have many handle fields [in, ref (with and without changes to flds)]
+
+ //initialize a new StructWithManySHFlds
+ Int32[] arrInt32s = null;
+ StructWithManySHFlds s = Helper.NewStructWithManySHFlds(ref arrInt32s);
+
+ Console.WriteLine("Testing SHStructWithManySHFldsParam_In...");
+ Assert.IsTrue(SHStructWithManySHFldsParam_In(s, arrInt32s), "FAILED! SHStructWithManySHFldsaram_In did not receive param as expected.");
+ //check that the value of the HANDLE fields did not change
+ Assert.IsFalse(Helper.IsChangedStructWithManySHFlds(s, arrInt32s), "FAILED! SHStructWithManySHFldsParam_In did not return param as expected.");
+
+ Console.WriteLine("Testing SHStructWithManySHFldsParam_Ref1...");
+ Assert.IsTrue(SHStructWithManySHFldsParam_Ref1(ref s, arrInt32s), "FAILED! SHStructWithManySHFldsaram_Ref1 did not receive param as expected.");
+ //check that the value of the HANDLE fields did not change
+ Assert.IsFalse(Helper.IsChangedStructWithManySHFlds(s, arrInt32s), "FAILED! SHStructWithManySHFldsParam_Ref1 did not return param as expected.");
+
+ Console.WriteLine("Testing SHStructWithManySHFldsParam_Ref2...");
+ Assert.Throws<NotSupportedException>(() => SHStructWithManySHFldsParam_Ref2(ref s, arrInt32s), "FAILED! Expected Exception Not Thrown!");
+
+ //9-passing SH subclass in Dispatch\UnknownWrapper, expecting a VARIANT (of type VT_DISPATCH or
+ //VT_UNKNOWN) on the managed side
+ SafeFileHandle sfh = Helper.NewSFH(); //SafeFileHandle
+ sfh.shfld1 = Helper.NewSFH();
+ sfh.shfld2 = Helper.NewSFH();
+ Int32 shValue = Helper.SHInt32(sfh);
+ Int32 shfld1Value = Helper.SHInt32(sfh.shfld1);
+ Int32 shfld2Value = Helper.SHInt32(sfh.shfld2);
+
+ SafeFileHandle sfh2 = Helper.NewSFH(); //SafeFileHandle
+ sfh2.shfld1 = Helper.NewSFH();
+ sfh2.shfld2 = Helper.NewSFH();
+ Int32 sh2Value = Helper.SHInt32(sfh2);
+ Int32 sh2fld1Value = Helper.SHInt32(sfh2.shfld1);
+ Int32 sh2fld2Value = Helper.SHInt32(sfh2.shfld2);
+
+ //re-initialize
+ sfh = Helper.NewSFH(); //SafeFileHandle
+ sfh.shfld1 = Helper.NewSFH();
+ sfh.shfld2 = Helper.NewSFH();
+ shValue = Helper.SHInt32(sfh);
+ shfld1Value = Helper.SHInt32(sfh.shfld1);
+ shfld2Value = Helper.SHInt32(sfh.shfld2);
+ String sfhstr = "SafeFileHandle";
+
+ Console.WriteLine("Testing SHObjectParam with SFH...");
+ Assert.Throws<ArgumentException>(() => SHObjectParam(sfh, shValue, shfld1Value, shfld2Value, sfhstr), "FAILED! Expected Exception Not Thrown!");
+
+ //re-initialize SH's that will be wrapped for the structure fields
+ sfh = Helper.NewSFH(); //SafeFileHandle
+ sfh.shfld1 = Helper.NewSFH();
+ sfh.shfld2 = Helper.NewSFH();
+ shValue = Helper.SHInt32(sfh);
+ shfld1Value = Helper.SHInt32(sfh.shfld1);
+ shfld2Value = Helper.SHInt32(sfh.shfld2);
+
+ sfh2 = Helper.NewSFH(); //SafeFileHandle
+ sfh2.shfld1 = Helper.NewSFH();
+ sfh2.shfld2 = Helper.NewSFH();
+ sh2Value = Helper.SHInt32(sfh2);
+ sh2fld1Value = Helper.SHInt32(sfh2.shfld1);
+ sh2fld2Value = Helper.SHInt32(sfh2.shfld2);
+
+ //re-initialize
+ sfh = Helper.NewSFH(); //SafeFileHandle
+ sfh.shfld1 = Helper.NewSFH();
+ sfh.shfld2 = Helper.NewSFH();
+ shValue = Helper.SHInt32(sfh);
+ shfld1Value = Helper.SHInt32(sfh.shfld1);
+ shfld2Value = Helper.SHInt32(sfh.shfld2);
+
+ StructWithObjFld sWithSFHFld = new StructWithObjFld();
+ sWithSFHFld.obj = sfh;
+
+ Console.WriteLine("Testing SHStructWithObjectFldParam with sWithSFHFld...");
+ Assert.Throws<ArgumentException>(() => SHStructWithObjectFldParam(sWithSFHFld, shValue, shfld1Value, shfld2Value, sfhstr), "FAILED! Expected Exception Not Thrown!");
+ }
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_In([In]ChildSafeFileHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Out(out ChildSFH_NoCloseHandle sh1);
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern ChildSFH_NoCloseHandle SHParam_OutRetVal();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Ref(ref ChildSFH_NoCloseHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Multiple([In]ChildSafeFileHandle sh1, out ChildSFH_NoCloseHandle sh2, ref ChildSFH_NoCloseHandle sh3, Int32 sh1Value, Int32 sh3Value);
+
+ /// <summary>
+ ///passing SafeFileHandle subclass parameters to unmanaged code in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1-passing SafeFileHandle subclass parameters individually in separate methods (In, out, ref)
+ ///2-passing SafeFileHandle subclass parameters in combination in the same method
+ /// </summary>
+ public static void RunChildSHParamTests()
+ {
+ Console.WriteLine("\nRunChildSHParamTests():");
+
+ //1-passing SafeFileHandle subclass parameters individually in separate methods (In, out, ref)
+
+ //get a new SH
+ ChildSafeFileHandle hnd = Helper.NewChildSFH();
+ Int32 hndInt32 = Helper.SHInt32(hnd); //get the 32-bit value associated with hnd
+
+ Console.WriteLine("Testing SHParam_In...");
+ Assert.IsTrue(SHParam_In(hnd, hndInt32), "FAILED! SHParam_In did not receive hnd as expected.");
+ //check that the value of the HANDLE did not change
+ Assert.IsFalse(Helper.IsChanged(hnd), "FAILED! SHParam_In did not return hnd as expected.");
+
+ Console.WriteLine("Testing SHParam_Out...");
+ ChildSFH_NoCloseHandle hndout;
+ SHParam_Out(out hndout);
+ //check that the value of the HANDLE changed
+ Assert.IsTrue(Helper.IsChanged(hndout), "FAILED! SHParam_Out did not return hndout as expected.");
+
+ Console.WriteLine("Testing SHParam_OutRetVal...");
+ hndout = null;
+ hndout = SHParam_OutRetVal();
+ //check that the value of the HANDLE changed
+ Assert.IsTrue(Helper.IsChanged(hndout), "FAILED! SHParam_OutRetVal did not return hndout as expected.");
+
+ hndout = Helper.NewChildSFH_NoCloseHandle(); //get a new value
+ hndInt32 = Helper.SHInt32(hndout);
+ Console.WriteLine("Testing SHParam_Ref...");
+ Assert.IsTrue(SHParam_Ref(ref hndout, hndInt32), "FAILED! SHParam_Ref did not receive hndout as expected.");
+ //check that the value of the HANDLE changed
+ Assert.IsTrue(Helper.IsChanged(hndout), "FAILED! SHParam_Ref did not return hndout as expected.");
+
+ //2-passing SafeFileHandle subclass parameters in combination in the same method
+
+ //initialize parameters
+ ChildSafeFileHandle hnd1 = Helper.NewChildSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(hnd1); //get the 32-bit value associated with hnd1
+
+ ChildSFH_NoCloseHandle hnd2 = null; //out parameter
+
+ ChildSFH_NoCloseHandle hnd3 = Helper.NewChildSFH_NoCloseHandle();
+ Int32 hnd3Int32 = Helper.SHInt32(hnd3); //get the 32-bit value associated with hnd3
+
+ Console.WriteLine("Testing SHParam_Multiple...");
+ Assert.IsTrue(SHParam_Multiple(hnd1, out hnd2, ref hnd3, hnd1Int32, hnd3Int32), "FAILED! SHParam_Multiple did not receive parameter(s) as expected.");
+ //check that the value of the HANDLES are as expected
+ Assert.IsFalse(Helper.IsChanged(hnd1), "FAILED! SHParam_Multiple did not return handle:hnd1 as expected.");
+ Assert.IsTrue(Helper.IsChanged(hnd2), "FAILED! SHParam_Multiple did not return handle:hnd2 as expected.");
+ Assert.IsTrue(Helper.IsChanged(hnd3), "FAILED! SHParam_Multiple did not return handle:hnd3 as expected.");
+ }
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_In([In]StructWithChildSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Out(out StructWithChildSHFld s);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref1(ref StructWithChildSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref2(ref StructWithChildSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple1([In]StructWithChildSHFld sh1, out StructWithChildSHFld sh2,
+ ref StructWithChildSHFld sh3, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple2([In]StructWithChildSHFld sh1, ref StructWithChildSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple3([In]StructWithChildSHFld sh1, ref StructWithChildSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ /// <summary>
+ ///passing structures (with SafeFileHandle subclass fields) as parameters in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1-passing structures (In, out, ref) (with SafeFileHandle subclass fields) individually in separate methods
+ ///2-passing structures (In, out, ref) (with SafeFileHandle subclass fields) in combination in the same method
+ /// </summary>
+ public static void RunChildSHStructParamTests()
+ {
+ Console.WriteLine("\nRunChildSHStructParamTests():");
+
+ //1-passing structures (In, out, ref) (with SafeFileHandle subclass fields) individually in separate methods
+
+ //initialize a new StructWithChildSHFld
+ StructWithChildSHFld s = new StructWithChildSHFld();
+ s.hnd = Helper.NewChildSFH(); //get a new SH
+ Int32 hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+
+ Console.WriteLine("Testing SHStructParam_In...");
+ Assert.IsTrue(SHStructParam_In(s, hndInt32), "FAILED! SHStructParam_In did not receive param as expected.");
+ //check that the value of the HANDLE field did not change
+ Assert.IsFalse(Helper.IsChanged(s.hnd), "FAILED! SHStructParam_In did not return param as expected.");
+
+ Console.WriteLine("Testing SHStructParam_Out...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Out(out s), "FAILED! Expected Exception not thrown.");
+
+ s.hnd = Helper.NewChildSFH(); //get a new SH
+ hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+ Console.WriteLine("Testing SHStructParam_Ref1 (does not change value of handle field)...");
+ Assert.IsTrue(SHStructParam_Ref1(ref s, hndInt32), "FAILED! SHStructParam_Ref1 did not receive param as expected.");
+ //check that the value of the HANDLE field is not changed
+ Assert.IsFalse(Helper.IsChanged(s.hnd), "FAILED! SHStructParam_Ref1 did not return param as expected.");
+
+ Console.WriteLine("Testing SHStructParam_Ref2 (does change value of handle field)...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Ref2(ref s, hndInt32), "FAILED! Expected Exception not thrown.");
+
+ //2-passing structures (In, out, ref) (with SafeFileHandle subclass fields) in combination in the same method
+
+ //initialize parameters
+ StructWithChildSHFld s1 = new StructWithChildSHFld();
+ s1.hnd = Helper.NewChildSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(s1.hnd); //get the 32-bit value associated with s1.hnd
+
+ StructWithChildSHFld s2; //out parameter
+
+ StructWithChildSHFld s3 = new StructWithChildSHFld();
+ s3.hnd = Helper.NewChildSFH();
+ Int32 hnd3Int32 = Helper.SHInt32(s3.hnd); //get the 32-bit value associated with s3.hnd
+
+ Console.WriteLine("Testing SHStructParam_Multiple1 (takes an out struct as one of the params and so is expected to result in an exception)...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Multiple1(s1, out s2, ref s3, hnd1Int32, hnd3Int32), "FAILED! Exception not thrown.");
+
+ s3.hnd = Helper.NewChildSFH();
+ hnd3Int32 = Helper.SHInt32(s3.hnd); //get the 32-bit value associated with s3.hnd
+ Console.WriteLine("Testing SHStructParam_Multiple2 (takes a ref struct as one of the params)...");
+ Assert.IsTrue(SHStructParam_Multiple2(s1, ref s3, hnd1Int32, hnd3Int32), "FAILED! SHStructParam_Multiple2 did not receive parameter(s) as expected.");
+ //check that the value of the HANDLES are as expected
+ Assert.IsFalse(Helper.IsChanged(s1.hnd) || Helper.IsChanged(s3.hnd), "FAILED! SHStructParam_Multiple2 did not return handles as expected.");
+
+ Console.WriteLine("Testing SHStructParam_Multiple3 (takes a ref struct as one of the params and changes it and so is expected to result in an exception)...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Multiple3(s1, ref s3, hnd1Int32, hnd3Int32), "FAILED! Expected Exception not thrown.");
+ }
+}
+#pragma warning restore 618
\ No newline at end of file
--- /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>MiscTest</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="MiscTest.cs" />
+ <Compile Include="..\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CMakeLists.txt" />
+ <ProjectReference Include="..\Interface\CMakeLists.txt" />
+ </ItemGroup>
+ <Import Project="../../../Interop.settings.targets" />
+ <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" />
+</Project>
--- /dev/null
+#VCXPROJ
+cmake_minimum_required (VERSION 2.6)
+project (PInvoke_SafeHandle_ReleaseHandle)
+include ("${CLR_INTEROP_TEST_ROOT}/Interop.cmake")
+include_directories(${INC_PLATFORM_DIR})
+set(SOURCES
+ ReleaseHandleNative.cpp
+)
+# Additional files to reference:
+# ReleaseHandleNative.def
+# add the executable
+add_library (PInvoke_SafeHandle_ReleaseHandle SHARED ${SOURCES})
+# add the install targets
+install (TARGETS PInvoke_SafeHandle_ReleaseHandle 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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <xplatform.h>
+
+bool g_myResourceReleaseMethodCalled = false;
+
+extern "C" DLL_EXPORT void __stdcall MyResourceReleaseMethod(HANDLE hnd)
+{
+ g_myResourceReleaseMethodCalled = true;
+
+ //call CloseHandle to actually release the handle corresponding to the SafeFileHandle
+ CloseHandle(hnd);
+}
+
+extern "C" DLL_EXPORT bool GetMyResourceReleaseMethodCalled()
+{
+ return g_myResourceReleaseMethodCalled;
+}
+
+extern "C" DLL_EXPORT void ResetMyResourceReleaseMethodCalled()
+{
+ g_myResourceReleaseMethodCalled = false;
+}
+
+extern "C" DLL_EXPORT void __stdcall SHReleasing_OutParams(IUnknown* ppIUnknFOO, HANDLE* phnd, IUnknown** ppIUnknBAR, int* pInt)
+{
+ //initialize the hnd out param
+ *phnd = (HANDLE)123;
+
+ //initialize the IUnknBAR out param
+ *ppIUnknBAR = ppIUnknFOO;
+ ppIUnknFOO->AddRef(); //addref Foo
+
+ //initialize the int out param
+ *pInt = 123;
+}
--- /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.IO;
+using System.Runtime.InteropServices;
+using System.Runtime.ConstrainedExecution;
+using SafeHandlesTests;
+using TestLibrary;
+
+class SafeFileHandle : SafeHandle //SafeHandle subclass
+{
+ private static readonly IntPtr _invalidHandleValue = new IntPtr(-1);
+
+ //0 or -1 considered invalid
+ public override bool IsInvalid
+ {
+ get { return handle == IntPtr.Zero || handle == _invalidHandleValue; }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [DllImport("PInvoke_SafeHandle_ReleaseHandle")]
+ private static extern bool MyResourceReleaseMethod(IntPtr handle);
+
+ //default constructor which just calls the base class constructor
+ public SafeFileHandle()
+ : base(IntPtr.Zero, true)
+ {
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ // this method will not actually call any resource releasing API method
+ // since the out/ref SFH param is not actually initialized to an OS allocated
+ // HANDLE---instead the unmanaged side just initializes/changes it to some integer;
+ // If a resource releasing API method like CloseHandle were called then
+ // it would return false and an unhandled exception would be thrown by the
+ // runtime indicating that the release method failed
+ MyResourceReleaseMethod(handle);
+ return true;
+ }
+
+} //end of SafeFileHandle class
+
+class Foo
+{
+ int FooMethod(int x, int y) { return x + y; }
+}
+
+class Bar
+{
+ void BarMethod() { }
+}
+
+internal class SHReleasingTester
+{
+ [DllImport("PInvoke_SafeHandle_ReleaseHandle")]
+ private static extern void SHReleasing_OutParams(
+ [MarshalAs(UnmanagedType.Interface)]Foo foo,
+ out SafeFileHandle sh,
+ [MarshalAs(UnmanagedType.Interface)]out Bar bar, out int x);
+
+ [DllImport("PInvoke_SafeHandle_ReleaseHandle")]
+ [return:MarshalAs(UnmanagedType.I1)]private static extern bool GetMyResourceReleaseMethodCalled();
+
+ [DllImport("PInvoke_SafeHandle_ReleaseHandle")]
+ private static extern void ResetMyResourceReleaseMethodCalled();
+
+ public static int Main()
+ {
+ try{
+ Console.WriteLine("SHReleasing_OutParams");
+ SafeFileHandle sh;
+ Foo foo = new Foo();
+ Bar bar;
+ int x;
+
+ ResetMyResourceReleaseMethodCalled();
+
+ //this unmanaged method will try to set the out Bar parameter to a Foo type
+ //this should cause an InvalidCastException on the way back from unmanaged
+ Assert.Throws<InvalidCastException>(() => SHReleasing_OutParams(foo, out sh, out bar, out x), "SHReleasing_OutParams");
+
+ //force the finalizer for the SFH param to run
+ Console.WriteLine("\tForcing finalizer for the SFH param to run...");
+ sh = null;
+ GC.Collect();
+ GC.WaitForPendingFinalizers();
+
+ Assert.IsTrue(GetMyResourceReleaseMethodCalled(), "MyResourceReleaseMethod was NOT called");
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ }
+}
+
--- /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>ReleaseHandleTest</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="ReleaseHandleTest.cs" />
+ <Compile Include="..\*.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.
+
+using System;
+using System.Runtime.InteropServices;
+using System.Runtime.ConstrainedExecution;
+
+// special subclass for out/ref ChildSFH params that are changed in unmanaged code
+// (see comments above ReleaseHandle for details)
+namespace SafeHandlesTests{
+ public class ChildSFH_NoCloseHandle : SafeFileHandle
+ {
+ ///////////////////////////////////////////////////////////
+ private static readonly IntPtr _invalidHandleValue = new IntPtr(-1);
+
+ //0 or -1 considered invalid
+ public override bool IsInvalid
+ {
+ get { return handle == IntPtr.Zero || handle == _invalidHandleValue; }
+ }
+
+ //each SafeHandle subclass will expose a static method for instance creation
+ [DllImport("api-ms-win-core-file-l1-2-1", EntryPoint = "CreateFileW", SetLastError = true)]
+ public static extern ChildSFH_NoCloseHandle CreateChildSafeFileHandle(String lpFileName,
+ DesiredAccess dwDesiredAccess, ShareMode dwShareMode,
+ IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
+ FlagsAndAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ //default constructor which just calls the base class constructor
+ public ChildSFH_NoCloseHandle()
+ : base()
+ {
+ }
+
+ // this method will not actually call any resource releasing API method
+ // since the out/ref ChildSFH param is not actually initialized to an OS allocated
+ // HANDLE---instead the unmanaged side just initializes/changes it to some integer;
+ // If a resource releasing API method like CloseHandle were called then
+ // it would return false and an unhandled exception would be thrown by the
+ // runtime indicating that the release method failed
+ override protected bool ReleaseHandle()
+ {
+ return true;
+ }
+
+ } //end fo ChildSFH_NoCloseHandle
+
+ public class ChildSafeFileHandle : SafeFileHandle
+ {
+ //each SafeHandle subclass will expose a static method for instance creation
+ [DllImport("api-ms-win-core-file-l1-2-1", EntryPoint = "CreateFileW", SetLastError = true)]
+ public static extern ChildSafeFileHandle CreateChildSafeFileHandle(String lpFileName,
+ DesiredAccess dwDesiredAccess, ShareMode dwShareMode,
+ IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
+ FlagsAndAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ //default constructor which just calls the base class constructor
+ public ChildSafeFileHandle()
+ : base()
+ {
+ }
+
+ } //end fo ChildSafeFileHandle
+
+ // special subclass for out/ref SFH params that are changed in unmanaged code
+ // (see comments above ReleaseHandle for details)
+ public class SFH_NoCloseHandle : SafeHandle //SafeHandle subclass
+ {
+ ///////////////////////////////////////////////////////////
+ private static readonly IntPtr _invalidHandleValue = new IntPtr(-1);
+
+ //0 or -1 considered invalid
+ public override bool IsInvalid
+ {
+ get { return handle == IntPtr.Zero || handle == _invalidHandleValue; }
+ }
+
+ //each SafeHandle subclass will expose a static method for instance creation
+ [DllImport("api-ms-win-core-file-l1-2-1", EntryPoint = "CreateFileW", SetLastError = true)]
+ public static extern SFH_NoCloseHandle CreateFile(String lpFileName,
+ DesiredAccess dwDesiredAccess, ShareMode dwShareMode,
+ IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
+ FlagsAndAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ //default constructor which just calls the base class constructor
+ public SFH_NoCloseHandle()
+ : base(IntPtr.Zero, true)
+ {
+ }
+
+ // this method will not actually call any resource releasing API method
+ // since the out/ref SFH param is not actually initialized to an OS allocated
+ // HANDLE---instead the unmanaged side just initializes/changes it to some integer;
+ // If a resource releasing API method like CloseHandle were called then
+ // it would return false and an unhandled exception would be thrown by the
+ // runtime indicating that the release method failed
+ override protected bool ReleaseHandle()
+ {
+ return true;
+ }
+
+ } //end of SFH_NoCloseHandle class
+
+ public class SafeFileHandle : SafeHandle //SafeHandle subclass
+ {
+ //public fields and properties
+ public SafeHandle shfld1;
+
+ public SafeFileHandle shfld2;
+ public SafeFileHandle shfld2_prop
+ {
+ [return: MarshalAs(UnmanagedType.Interface)]
+ get { return shfld2; }
+ [param: MarshalAs(UnmanagedType.Interface)]
+ set { shfld2 = value; }
+ }
+
+ ///////////////////////////////////////////////////////////
+ private static readonly IntPtr _invalidHandleValue = new IntPtr(-1);
+
+ //0 or -1 considered invalid
+ public override bool IsInvalid
+ {
+ get { return handle == IntPtr.Zero || handle == _invalidHandleValue; }
+ }
+
+ [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
+ [DllImport("api-ms-win-core-handle-l1-1-0", SetLastError = true)]
+ private static extern bool CloseHandle(IntPtr handle);
+
+
+ //each SafeHandle subclass will expose a static method for instance creation
+ [DllImport("api-ms-win-core-file-l1-2-1", EntryPoint = "CreateFileW", SetLastError = true)]
+ public static extern SafeFileHandle CreateFile(String lpFileName,
+ DesiredAccess dwDesiredAccess, ShareMode dwShareMode,
+ IntPtr lpSecurityAttributes, CreationDisposition dwCreationDisposition,
+ FlagsAndAttributes dwFlagsAndAttributes, IntPtr hTemplateFile);
+
+ //default constructor which just calls the base class constructor
+ public SafeFileHandle()
+ : base(IntPtr.Zero, true)
+ {
+ }
+
+ override protected bool ReleaseHandle()
+ {
+ return CloseHandle(handle);
+ }
+
+ } //end of SafeFileHandle class
+
+ /// <summary>
+ /// The following public enums are for use in creating the
+ /// new file i.e. setting attributes etc. on the file
+ /// </summary>
+
+ // This enumeration defines the level of desired access. The
+ // enumeration contains a special member for querying the
+ // device without accessing it.
+ public enum DesiredAccess : uint
+ {
+ QueryDeviceOnly = 0,
+ GENERIC_READ = 0x80000000,
+ GENERIC_WRITE = 0x40000000,
+ GENERIC_EXECUTE = 0x20000000,
+ GENERIC_ALL = 0x10000000,
+ DELETE = 0x00010000,
+ READ_CONTROL = 0x00020000,
+ WRITE_DAC = 0x00040000,
+ WRITE_OWNER = 0x00080000,
+ SYNCHRONIZE = 0x00100000,
+ STANDARD_RIGHTS_REQUIRED = 0x000F0000,
+ STANDARD_RIGHTS_READ = READ_CONTROL,
+ STANDARD_RIGHTS_WRITE = READ_CONTROL,
+ STANDARD_RIGHTS_EXECUTE = READ_CONTROL,
+ STANDARD_RIGHTS_ALL = 0x001F0000,
+ SPECIFIC_RIGHTS_ALL = 0x0000FFFF,
+ ACCESS_SYSTEM_SECURITY = 0x01000000,
+ MAXIMUM_ALLOWED = 0x02000000
+ }
+
+ // This enumeration defines the type of sharing to support. It
+ // includes a special member for no sharing at all.
+ public enum ShareMode
+ {
+ NotShared = 0,
+ FILE_SHARE_READ = 0x00000001,
+ FILE_SHARE_WRITE = 0x00000002,
+ FILE_SHARE_DELETE = 0x00000004
+ }
+
+ // This enumeration defines how the call will treat files or
+ // other objects that already exist. You must provide one of
+ // these values as input.
+ public enum CreationDisposition
+ {
+ CREATE_NEW = 1,
+ CREATE_ALWAYS = 2,
+ OPEN_EXISTING = 3,
+ OPEN_ALWAYS = 4,
+ TRUNCATE_EXISTING = 5
+ }
+
+ // This enumeration defines additional flags and attributes the
+ // call will use when opening an object. This enumeration contains
+ // as special value for no flags or attributes.
+ public enum FlagsAndAttributes : uint
+ {
+ None = 0,
+ FILE_ATTRIBUTE_READONLY = 0x00000001,
+ FILE_ATTRIBUTE_HIDDEN = 0x00000002,
+ FILE_ATTRIBUTE_SYSTEM = 0x00000004,
+ FILE_ATTRIBUTE_ARCHIVE = 0x00000020,
+ FILE_ATTRIBUTE_NORMAL = 0x00000080,
+ FILE_ATTRIBUTE_TEMPORARY = 0x00000100,
+ FILE_ATTRIBUTE_OFFLINE = 0x00001000,
+ FILE_ATTRIBUTE_NOT_CONTENT_INDEXED = 0x00002000,
+ FILE_ATTRIBUTE_ENCRYPTED = 0x00004000,
+ FILE_FLAG_WRITE_THROUGH = 0x80000000,
+ FILE_FLAG_OVERLAPPED = 0x40000000,
+ FILE_FLAG_NO_BUFFERING = 0x20000000,
+ FILE_FLAG_RANDOM_ACCESS = 0x10000000,
+ FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000,
+ FILE_FLAG_DELETE_ON_CLOSE = 0x04000000,
+ FILE_FLAG_BACKUP_SEMANTICS = 0x02000000,
+ FILE_FLAG_POSIX_SEMANTICS = 0x01000000,
+ FILE_FLAG_OPEN_REPARSE_POINT = 0x00200000,
+ FILE_FLAG_OPEN_NO_RECALL = 0x00100000,
+ SECURITY_ANONYMOUS = 0x00000000,
+ SECURITY_IDENTIFICATION = 0x00010000,
+ SECURITY_IMPERSONATION = 0x00020000,
+ SECURITY_DELEGATION = 0x00030000,
+ SECURITY_CONTEXT_TRACKING = 0x00040000,
+ SECURITY_EFFECTIVE_ONLY = 0x00080000
+ }
+}
--- /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.
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <windows.h>
+#include <xplatform.h>
+#include "StructDefs.h" //all the unmanaged struct defs are in this file
+
+//Global Handle Return Value
+HANDLE returnHandleValue = (HANDLE)123;
+
+//Method for Invalid MarshalAs tests
+extern "C" DLL_EXPORT BOOL __stdcall SHFldInvalid_MA(StructWithSHFld s)
+{
+ printf("\t\tIN SHFldInvalid_MA!\n");
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT HANDLE __stdcall SHInvalid_retMA16()
+{
+ printf("\t\tIN SHInvalid_retMA16!\n");
+ HANDLE *hnd = (HANDLE*)GlobalAlloc(0, sizeof(HANDLE)); //new HANDLE
+ *hnd = returnHandleValue;
+ return (*hnd);
+}
+
+//////////////Methods used by RunParamTests
+///////////////////////////////////////////
+extern "C" DLL_EXPORT BOOL __stdcall SHParam_In(HANDLE sh1, int sh1Value)
+{
+ if( (intptr_t)sh1 != sh1Value )
+ return FALSE;
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHParam_Out(HANDLE* sh1)
+{
+ *sh1 = returnHandleValue;
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT HRESULT _stdcall SHParam_OutRetVal(HANDLE* sh1)
+{
+ *sh1 = returnHandleValue;
+ return S_OK;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHParam_Ref(HANDLE* sh1, int sh1Value)
+{
+ if( (intptr_t)*sh1 != sh1Value )
+ return FALSE;
+ //change the value of the HANDLE---this is equivalent to assigning a new HANDLE
+ *sh1 = returnHandleValue;
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHParam_Multiple(HANDLE sh1, HANDLE* sh2, HANDLE* sh3, int sh1Value, int sh3Value)
+{
+ if( (intptr_t)sh1 != sh1Value )
+ {
+ printf("\t\tIn SHParam_Multiple: sh1 value not received as expected.\n");
+ return FALSE;
+ }
+ else if( (intptr_t)*sh3 != sh3Value )
+ {
+ printf("\t\tIn SHParam_Multiple: sh3 value not received as expected.\n");
+ //printf("\t\t\t*sh3 = %d, sh3Value = %d\n", (int)*sh3, sh3Value);
+ return FALSE;
+ }
+ //change the out and ref values
+ *sh2 = returnHandleValue;
+ *sh3 = returnHandleValue;
+ return TRUE;
+}
+
+//////////////Methods used by RunStructParamTests
+/////////////////////////////////////////////////
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_In(StructWithSHFld s, int shndValue)
+{
+ if( (intptr_t)s.hnd != shndValue )
+ return FALSE;
+ s.hnd = returnHandleValue; //try to change hnd value; should not be reflected on managed side
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_Out(StructWithSHFld* ps)
+{
+ ps->hnd = returnHandleValue;
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT HRESULT _stdcall SHStructParam_OutRetVal(StructWithSHFld* ps)
+{
+ ps->hnd = returnHandleValue;
+ return S_OK;
+}
+
+//this method will NOT change the value of the ref SH subclass field
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_Ref1(StructWithSHFld* ps, int shndValue)
+{
+ if( (intptr_t)(ps->hnd) != shndValue )
+ return FALSE;
+ return TRUE;
+}
+
+//this method will change the value of the SH subclass field
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_Ref2(StructWithSHFld* ps, int shndValue)
+{
+ if( (intptr_t)(ps->hnd) != shndValue )
+ return FALSE;
+ //change the value of the HANDLE---this is equivalent to assigning a new HANDLE
+ ps->hnd = returnHandleValue;
+ return TRUE;
+}
+
+//this takes an out param and so is expected to result in an exception
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_Multiple1(StructWithSHFld s1, StructWithSHFld* ps2,
+ StructWithSHFld* ps3, int s1hndValue,
+ int s3hndValue)
+{
+ if( (intptr_t)s1.hnd != s1hndValue || (intptr_t)(ps3->hnd) != s3hndValue )
+ return FALSE;
+ //change the handle field of the out parameter
+ ps2->hnd = returnHandleValue;
+ return TRUE;
+}
+
+//this takes a ref param and does not change the SH subclass field
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_Multiple2(StructWithSHFld s1, StructWithSHFld* ps2,
+ int s1hndValue, int s2hndValue)
+{
+ if( (intptr_t)s1.hnd != s1hndValue || (intptr_t)(ps2->hnd) != s2hndValue )
+ return FALSE;
+ return TRUE;
+}
+
+//this takes a ref param and tries to change the SH subclass field and so is expected to result in an exception
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_Multiple3(StructWithSHFld s1, StructWithSHFld* ps2,
+ int s1hndValue, int s2hndValue)
+{
+ if( (intptr_t)s1.hnd != s1hndValue || (intptr_t)(ps2->hnd) != s2hndValue )
+ return FALSE;
+ //change the handle field of the ref parameter
+ ps2->hnd = returnHandleValue;
+ return TRUE;
+}
+
+//////////////Methods used by RunMiscellaneousTests
+///////////////////////////////////////////////////
+extern "C" DLL_EXPORT BOOL __stdcall SHArrayParam(HANDLE* ptoArr, int* ptoArrInt32s, int length)
+{
+ for(int i = 0; i < length; i++)
+ if( (intptr_t)ptoArr[i] != ptoArrInt32s[i] )
+ {
+ printf("\t\tptoArr[%d] = %d, ptoArrInt32s[%d] = %d\n", i, (int)(intptr_t)ptoArr[i], i, ptoArrInt32s[i]);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHStructArrayParam(StructWithSHFld* ptoArr, int* ptoArrInt32s, int length)
+{
+ for(int i = 0; i < length; i++)
+ if( (intptr_t)(ptoArr[i].hnd) != ptoArrInt32s[i] )
+ return FALSE;
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT HANDLE __stdcall SHReturn()
+{
+ HANDLE *hnd = (HANDLE*)GlobalAlloc(0, sizeof(HANDLE)); //new HANDLE
+ *hnd = returnHandleValue;
+ return (*hnd);
+}
+
+extern "C" DLL_EXPORT StructWithSHFld __stdcall SHReturnStruct()
+{
+ StructWithSHFld* ptoStruct = (StructWithSHFld*)GlobalAlloc(0, sizeof(StructWithSHFld));
+ ptoStruct->hnd = returnHandleValue;
+ return (*ptoStruct);
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHStructNestedParam(StructNestedParent sn, int shndValue)
+{
+ if( (intptr_t)sn.snOneDeep.s.hnd != shndValue )
+ return FALSE;
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHStructParam_In2(StructWithSHArrayFld s, int* ptoArrInt32s, int length)
+{
+ for(int i = 0; i < length; i++)
+ if( (intptr_t)s.sharr[i] != ptoArrInt32s[i] )
+ {
+ printf("\t\ts.sharr[%d] = %d, ptoArrInt32s[%d] = %d\n", i, (int)(intptr_t)s.sharr[i], i, ptoArrInt32s[i]);
+ return FALSE;
+ }
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT BOOL __stdcall SHMixedParam1(HANDLE sh1, HANDLE* sh2, HANDLE* sh3, StructWithSHFld s1, StructWithSHFld s2,
+ StructWithSHFld* s3, int sh1Value, int sh3Value, int s1fldValue, int s2fldValue,
+ int s3fldValue)
+{
+ if( (intptr_t)sh1 != sh1Value || (intptr_t)*sh3 != sh3Value || (intptr_t)s1.hnd != s1fldValue || (intptr_t)s2.hnd != s2fldValue
+ || (intptr_t)s3->hnd != s3fldValue )
+ return FALSE;
+ *sh2 = returnHandleValue; //the out parameter
+ return TRUE;
+}
+
+BOOL static CertifyStructWithManySHFlds(StructWithManySHFlds s, int* ptoArrInt32s)
+{
+ if( (intptr_t)s.hnd1 != ptoArrInt32s[0] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd1 != ptoArrInt32s[0]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd2 != ptoArrInt32s[1] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd2 != ptoArrInt32s[1]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd3 != ptoArrInt32s[2] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd3 != ptoArrInt32s[2]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd4 != ptoArrInt32s[3] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd4 != ptoArrInt32s[3]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd5 != ptoArrInt32s[4] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd5 != ptoArrInt32s[4]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd6 != ptoArrInt32s[5] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd6 != ptoArrInt32s[5]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd7 != ptoArrInt32s[6] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd7 != ptoArrInt32s[6]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd8 != ptoArrInt32s[7] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd8 != ptoArrInt32s[7]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd9 != ptoArrInt32s[8] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd9 != ptoArrInt32s[8]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd10 != ptoArrInt32s[9] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd10 != ptoArrInt32s[9]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd11 != ptoArrInt32s[10] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd11 != ptoArrInt32s[10]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd12 != ptoArrInt32s[11] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd12 != ptoArrInt32s[11]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd13 != ptoArrInt32s[12] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd13 != ptoArrInt32s[12]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd14 != ptoArrInt32s[13] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd14 != ptoArrInt32s[13]\n");
+ return FALSE;
+ }
+ else if( (intptr_t)s.hnd15 != ptoArrInt32s[14] )
+ {
+ printf("\t\tCertifyStructWithManySHFlds: s.hnd15 != ptoArrInt32s[14]\n");
+ return FALSE;
+ }
+ else
+ return TRUE;
+}
+
+//ptoArrInt32 is a pointer to an array of int32s---each element of which matches a fld of the struct
+extern "C" DLL_EXPORT BOOL __stdcall SHStructWithManySHFldsParam_In(StructWithManySHFlds s, int* ptoArrInt32s)
+{
+ if ( !CertifyStructWithManySHFlds(s, ptoArrInt32s) )
+ return FALSE;
+ s.hnd14 = returnHandleValue; //try to change a fld; should not be reflected on managed side
+ return TRUE;
+}
+
+//ptoArrInt32 is a pointer to an array of int32s---each element of which matches a fld of the struct
+//Ref1 will not change any of the flds
+extern "C" DLL_EXPORT BOOL __stdcall SHStructWithManySHFldsParam_Ref1(StructWithManySHFlds* ptos, int* ptoArrInt32s)
+{
+ return CertifyStructWithManySHFlds(*ptos, ptoArrInt32s);
+}
+
+//ptoArrInt32 is a pointer to an array of int32s---each element of which matches a fld of the struct
+//Ref2 will change one of the flds
+extern "C" DLL_EXPORT BOOL __stdcall SHStructWithManySHFldsParam_Ref2(StructWithManySHFlds* ptos, int* ptoArrInt32s)
+{
+ if( !CertifyStructWithManySHFlds(*ptos, ptoArrInt32s) )
+ return FALSE;
+ else
+ (*ptos).hnd14 = returnHandleValue; //change one of the flds
+ return TRUE;
+}
+
+extern "C" DLL_EXPORT int __stdcall SHInvalid_MA()
+{
+ // NOT REACHABLE from test because we are supposed to throw MarshalDirectionException from stubs
+ // This is needed to make ProjectN happy because ProjectN always do early binding
+ return 0;
+}
+
+extern "C" DLL_EXPORT int __stdcall SHInvalid_retMA()
+{
+ // NOT REACHABLE from test because we are supposed to throw MarshalDirectionException from stubs
+ // This is needed to make ProjectN happy because ProjectN always do early binding
+ return 0;
+}
--- /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.Runtime.InteropServices;
+using SafeHandlesTests;
+using TestLibrary;
+
+public class SHTester_SigDiff
+{
+ public static int Main()
+ {
+ try
+ {
+ RunSHParamTests();
+ RunSHStructParamTests();
+
+ return 100;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine($"Test Failure: {e}");
+ return 101;
+ }
+ } //end of Main
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_In([In]SafeHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Out(out SafeHandle sh1);
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern SafeHandle SHParam_OutRetVal();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Ref(ref SafeHandle sh1, Int32 sh1Value);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHParam_Multiple([In]SafeHandle sh1, out SafeHandle sh2, ref SafeHandle sh3, Int32 sh1Value, Int32 sh3Value);
+
+ /// <summary>
+ ///passing SH parameters to unmanaged code in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1- passing SH parameters individually in separate methods (In, out, ref)
+ ///2- passing SH parameters in combination in the same method
+ /// </summary>
+ public static void RunSHParamTests()
+ {
+ Console.WriteLine("\nRunSHParamTests():");
+
+ //1- passing SH parameters individually in separate methods (In, out, ref)
+
+ //get a new SH
+ SafeHandle hnd = Helper.NewSFH(); //NOTE that this is equivalent to SafeHandle = SafeFileHandle.CreateFile();
+ Int32 hndInt32 = Helper.SHInt32(hnd); //get the 32-bit value associated with hnd
+
+ Console.WriteLine("Testing SHParam_In...");
+ Assert.IsTrue(SHParam_In(hnd, hndInt32), "FAILED! SHParam_In did not receive hnd as expected.");
+ //check that the value of the HANDLE did not change
+ Assert.IsFalse(Helper.IsChanged(hnd), "FAILED! SHParam_In did not return hnd as expected.");
+
+ Console.WriteLine("Testing SHParam_Out...");
+ Assert.Throws<MarshalDirectiveException>(() => SHParam_Out(out hnd), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHParam_OutRetVal...");
+ hnd = null;
+ Assert.Throws<MarshalDirectiveException>(() => hnd = SHParam_OutRetVal(), "FAILED! Exception not thrown.");
+
+ hnd = Helper.NewSFH(); //get a new value
+ hndInt32 = Helper.SHInt32(hnd);
+ Console.WriteLine("Testing SHParam_Ref...");
+ Assert.Throws<MarshalDirectiveException>(() => SHParam_Ref(ref hnd, hndInt32), "FAILED! Exception not thrown.");
+
+ //2- passing SH parameters in combination in the same method
+
+ //initialize parameters
+ SafeHandle hnd1 = Helper.NewSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(hnd1); //get the 32-bit value associated with hnd1
+
+ SafeHandle hnd2 = null; //out parameter
+
+ SafeHandle hnd3 = Helper.NewSFH();
+ Int32 hnd3Int32 = Helper.SHInt32(hnd3); //get the 32-bit value associated with hnd3
+
+ Console.WriteLine("Testing SHParam_Multiple...");
+ Assert.Throws<MarshalDirectiveException>(() => SHParam_Multiple(hnd1, out hnd2, ref hnd3, hnd1Int32, hnd3Int32), "FAILED! Exception not thrown.");
+ } //end of static method RunParamTests
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_In([In]StructWithBaseSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Out(out StructWithBaseSHFld s);
+
+ [DllImport("PInvoke_SafeHandle", PreserveSig = false, SetLastError = true)]
+ public static extern StructWithBaseSHFld SHStructParam_OutRetVal();
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref1(ref StructWithBaseSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Ref2(ref StructWithBaseSHFld s, Int32 shfldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple1([In]StructWithBaseSHFld sh1, out StructWithBaseSHFld sh2,
+ ref StructWithBaseSHFld sh3, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple2([In]StructWithBaseSHFld sh1, ref StructWithBaseSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ [DllImport("PInvoke_SafeHandle", SetLastError = true)]
+ public static extern bool SHStructParam_Multiple3([In]StructWithBaseSHFld sh1, ref StructWithBaseSHFld sh2, Int32 sh1fldValue, Int32 sh2fldValue);
+
+ /// <summary>
+ ///passing structures (with SH fields) as parameters in various combinations and forms;
+ ///it uses the PInvoke signatures defined above it
+ ///1- passing structures (In, out, ref) (with SH fields) individually in separate methods
+ ///2- passing structures (In, out, ref) (with SH fields) in combination in the same method
+ /// </summary>
+ public static void RunSHStructParamTests()
+ {
+ Console.WriteLine("\nRunSHStructParamTests():");
+
+ //1- passing structures (In, out, ref) (with SH fields) individually in separate methods
+
+ //initialize a new StructWithBaseSHFld
+ StructWithBaseSHFld s = new StructWithBaseSHFld();
+ s.hnd = Helper.NewSFH(); //get a new SH
+ Int32 hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+
+ Console.WriteLine("Testing SHStructParam_In...");
+ Assert.IsTrue(SHStructParam_In(s, hndInt32), "FAILED! SHStructParam_In did not receive param as expected.");
+ Assert.IsFalse(Helper.IsChanged(s.hnd), "FAILED! SHStructParam_In did not return param as expected.");
+
+ Console.WriteLine("Testing SHStructParam_Out...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Out(out s), "FAILED! Exception not thrown.");
+
+ Console.WriteLine("Testing SHStructParam_OutRetVal...");
+ Assert.Throws<MarshalDirectiveException>(() => s = SHStructParam_OutRetVal(), "FAILED! Exception not thrown.");
+
+ s.hnd = Helper.NewSFH(); //get a new SH
+ hndInt32 = Helper.SHInt32(s.hnd); //get the 32-bit value associated with s.hnd
+ Console.WriteLine("Testing SHStructParam_Ref1 (does not change value of handle field)...");
+ Assert.IsTrue(SHStructParam_Ref1(ref s, hndInt32), "FAILED! SHStructParam_Ref1 did not receive param as expected.");
+ //check that the value of the HANDLE field is not changed
+ Assert.IsFalse(Helper.IsChanged(s.hnd), "FAILED! SHStructParam_Ref1 did not return param as expected.");
+
+ Console.WriteLine("Testing SHStructParam_Ref2 (does change value of handle field)...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Ref2(ref s, hndInt32), "FAILED! Exception not thrown.");
+
+ //2- passing structures (In, out, ref) (with SH fields) in combination in the same method
+
+ //initialize parameters
+ StructWithBaseSHFld s1 = new StructWithBaseSHFld();
+ s1.hnd = Helper.NewSFH();
+ Int32 hnd1Int32 = Helper.SHInt32(s1.hnd); //get the 32-bit value associated with s1.hnd
+ StructWithBaseSHFld s2; //out parameter
+ StructWithBaseSHFld s3 = new StructWithBaseSHFld();
+ s3.hnd = Helper.NewSFH();
+ Int32 hnd3Int32 = Helper.SHInt32(s3.hnd); //get the 32-bit value associated with s3.hnd
+
+ Console.WriteLine("Testing SHStructParam_Multiple1 (takes an out struct as one of the params and so is expected to result in an exception)...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Multiple1(s1, out s2, ref s3, hnd1Int32, hnd3Int32), "FAILED! Exception not thrown.");
+
+ s3.hnd = Helper.NewSFH();
+ hnd3Int32 = Helper.SHInt32(s3.hnd); //get the 32-bit value associated with s3.hnd
+ Console.WriteLine("Testing SHStructParam_Multiple2 (takes a ref struct as one of the params)...");
+ Assert.IsTrue(SHStructParam_Multiple2(s1, ref s3, hnd1Int32, hnd3Int32), "FAILED! SHStructParam_Multiple2 did not receive parameter(s) as expected.");
+ Assert.IsFalse(Helper.IsChanged(s1.hnd) || Helper.IsChanged(s3.hnd), "FAILED! SHStructParam_Multiple2 did not return handles as expected.");
+
+ Console.WriteLine("Testing SHStructParam_Multiple3 (takes a ref struct as one of the params and changes its handle field and so is expected to result in an exception)...");
+ Assert.Throws<NotSupportedException>(() => SHStructParam_Multiple3(s1, ref s3, hnd1Int32, hnd3Int32), "FAILED! Exception not thrown.");
+ }
+}
\ No newline at end of file
--- /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>SigDiffTest</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="SigDiffTest.cs" />
+ </ItemGroup><Import Project="../../../Interop.settings.targets" /><ItemGroup>
+ <Compile Include="..\*.cs" />
+ </ItemGroup>
+ <ItemGroup>
+ <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
+ </ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\CMakeLists.txt" />
+ </ItemGroup>
+ <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.
+
+using System;
+using System.Runtime.InteropServices;
+using SafeHandlesTests;
+
+#pragma warning disable 618
+namespace SafeHandlesTests{
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructWithSHFld
+ {
+ public SafeFileHandle hnd; //SH subclass field
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructWithBaseSHFld
+ {
+ public SafeHandle hnd; //SH field
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructWithChildSHFld
+ {
+ public ChildSafeFileHandle hnd; //SafeFileHandle subclass field
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructNestedParent
+ {
+ public StructNestedOneDeep snOneDeep;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructNestedOneDeep
+ {
+ public StructWithSHFld s;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructWithSHArrayFld
+ {
+ public SafeFileHandle[] sharr;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructWithManySHFlds
+ {
+ public SafeHandle hnd1;
+ public SafeFileHandle hnd2;
+ public ChildSafeFileHandle hnd3;
+
+ public SafeHandle hnd4;
+ public SafeFileHandle hnd5;
+ public ChildSafeFileHandle hnd6;
+
+ public SafeHandle hnd7;
+ public SafeFileHandle hnd8;
+ public ChildSafeFileHandle hnd9;
+
+ public SafeHandle hnd10;
+ public SafeFileHandle hnd11;
+ public ChildSafeFileHandle hnd12;
+
+ public SafeHandle hnd13;
+ public SafeFileHandle hnd14;
+ public ChildSafeFileHandle hnd15;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructWithObjFld
+ {
+ //the MA attribute indicates that obj is to be marshaled as a VARIANT
+ [MarshalAs(UnmanagedType.Struct)]
+ public Object obj;
+ }
+
+ ////The following Structure definitions are for negative testing purposes
+ ///
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA1
+ {
+ [MarshalAs(UnmanagedType.AnsiBStr)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA2
+ {
+ [MarshalAs(UnmanagedType.AsAny)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA3
+ {
+ [MarshalAs(UnmanagedType.Bool)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA4
+ {
+ [MarshalAs(UnmanagedType.BStr)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA5
+ {
+ [MarshalAs(UnmanagedType.ByValArray)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA6
+ {
+ [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA7
+ {
+ [MarshalAs(UnmanagedType.Currency)]
+ public SafeFileHandle hnd;
+ }
+
+ //NOTE: Specified unmanaged type also needs MarshalType or MarshalTypeRef which indicates the custom marshaler
+ //[StructLayout(LayoutKind.Sequential)]
+ //public struct StructMA8
+ //{
+ // [MarshalAs(UnmanagedType.CustomMarshaler)]
+ // public SafeFileHandle hnd;
+ //}
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA9
+ {
+ [MarshalAs(UnmanagedType.Error)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA10
+ {
+ [MarshalAs(UnmanagedType.FunctionPtr)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA11
+ {
+ [MarshalAs(UnmanagedType.I1)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA12
+ {
+ [MarshalAs(UnmanagedType.I2)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA13
+ {
+ [MarshalAs(UnmanagedType.I4)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA14
+ {
+ [MarshalAs(UnmanagedType.I8)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA15
+ {
+ [MarshalAs(UnmanagedType.IDispatch)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA16
+ {
+ [MarshalAs(UnmanagedType.Interface)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA17
+ {
+ [MarshalAs(UnmanagedType.IUnknown)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA18
+ {
+ [MarshalAs(UnmanagedType.LPArray)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA19
+ {
+ [MarshalAs(UnmanagedType.LPStr)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA20
+ {
+ [MarshalAs(UnmanagedType.LPStruct)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA21
+ {
+ [MarshalAs(UnmanagedType.LPTStr)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA22
+ {
+ [MarshalAs(UnmanagedType.LPWStr)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA23
+ {
+ [MarshalAs(UnmanagedType.R4)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA24
+ {
+ [MarshalAs(UnmanagedType.R8)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA25
+ {
+ [MarshalAs(UnmanagedType.SafeArray)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA26
+ {
+ [MarshalAs(UnmanagedType.Struct)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA27
+ {
+ [MarshalAs(UnmanagedType.SysInt)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA28
+ {
+ [MarshalAs(UnmanagedType.SysUInt)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA29
+ {
+ [MarshalAs(UnmanagedType.TBStr)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA30
+ {
+ [MarshalAs(UnmanagedType.U1)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA31
+ {
+ [MarshalAs(UnmanagedType.U2)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA32
+ {
+ [MarshalAs(UnmanagedType.U4)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA33
+ {
+ [MarshalAs(UnmanagedType.U8)]
+ public SafeFileHandle hnd;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct StructMA34
+ {
+ [MarshalAs(UnmanagedType.VariantBool)]
+ public SafeFileHandle hnd;
+ }
+
+ //NOTE: This unmanagedtype is not valid for fields
+ //[StructLayout(LayoutKind.Sequential)]
+ //public struct StructMA35
+ //{
+ // [MarshalAs(UnmanagedType.VBByRefStr)]
+ // public SafeFileHandle hnd;
+ //}
+}
+#pragma warning restore 618
+
+
+
--- /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.
+
+struct StructWithSHFld
+{
+ HANDLE hnd;
+};
+
+struct StructNestedOneDeep
+{
+ StructWithSHFld s;
+};
+
+struct StructNestedParent
+{
+ StructNestedOneDeep snOneDeep;
+};
+
+struct StructWithSHArrayFld
+{
+ HANDLE* sharr;
+};
+
+struct StructWithManySHFlds
+{
+ HANDLE hnd1;
+ HANDLE hnd2;
+ HANDLE hnd3;
+
+ HANDLE hnd4;
+ HANDLE hnd5;
+ HANDLE hnd6;
+
+ HANDLE hnd7;
+ HANDLE hnd8;
+ HANDLE hnd9;
+
+ HANDLE hnd10;
+ HANDLE hnd11;
+ HANDLE hnd12;
+
+ HANDLE hnd13;
+ HANDLE hnd14;
+ HANDLE hnd15;
+};
+
+struct StructMAIntf
+{
+ IDispatch* ptoIntf;
+};
+
+struct StructWithVARIANTFld
+{
+ VARIANT v;
+};
\ No newline at end of file