0875d0d9cd
Former-commit-id: 090371aae4deb2cffdeada14f23b6a47fbe7f087
1090 lines
29 KiB
C#
1090 lines
29 KiB
C#
//
|
|
// System.Runtime.InteropServices.Marshal Test Cases
|
|
//
|
|
// Authors:
|
|
// Gonzalo Paniagua Javier (gonzalo@ximian.com)
|
|
// Sebastien Pouliot <sebastien@ximian.com>
|
|
//
|
|
// Copyright (C) 2004-2007 Novell, Inc (http://www.novell.com)
|
|
//
|
|
using NUnit.Framework;
|
|
using System;
|
|
using System.IO;
|
|
using System.Reflection;
|
|
#if !MOBILE
|
|
using System.Reflection.Emit;
|
|
#endif
|
|
using System.Runtime.InteropServices;
|
|
using System.Security;
|
|
using System.Text;
|
|
|
|
namespace MonoTests.System.Runtime.InteropServices
|
|
{
|
|
[TestFixture]
|
|
public class MarshalTest
|
|
{
|
|
[StructLayout (LayoutKind.Sequential)]
|
|
class ClsSequential {
|
|
public int field;
|
|
}
|
|
|
|
public class ClsNoLayout {
|
|
public int field;
|
|
}
|
|
|
|
[StructLayout (LayoutKind.Explicit)]
|
|
class ClsExplicit {
|
|
[FieldOffset (0)] public int field;
|
|
}
|
|
|
|
[StructLayout (LayoutKind.Sequential)]
|
|
struct StrSequential {
|
|
public int field;
|
|
}
|
|
|
|
struct StrNoLayout {
|
|
public int field;
|
|
}
|
|
|
|
[StructLayout (LayoutKind.Explicit)]
|
|
struct StrExplicit {
|
|
[FieldOffset (0)] public int field;
|
|
}
|
|
|
|
[Test]
|
|
public void SizeOf_Class_LayoutSequential ()
|
|
{
|
|
Marshal.SizeOf (typeof (ClsSequential));
|
|
}
|
|
|
|
[Test]
|
|
public void SizeOf_Class_LayoutNotSet ()
|
|
{
|
|
try {
|
|
Marshal.SizeOf (typeof (ClsNoLayout));
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentException ex) {
|
|
// Type '...MarshalTest+ClsNoLayout' cannot be
|
|
// marshaled as an unmanaged structure; no
|
|
// meaningful size or offset can be computed
|
|
Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SizeOf_Class_LayoutExplicit ()
|
|
{
|
|
Marshal.SizeOf (typeof (ClsExplicit));
|
|
}
|
|
|
|
[Test]
|
|
public void SizeOf_Struct_LayoutSequential ()
|
|
{
|
|
Marshal.SizeOf (typeof (StrSequential));
|
|
}
|
|
|
|
[Test]
|
|
public void SizeOf_Struct_LayoutNotSet ()
|
|
{
|
|
Marshal.SizeOf (typeof (StrNoLayout));
|
|
}
|
|
|
|
[Test]
|
|
public void SizeOf_Struct_LayoutExplicit ()
|
|
{
|
|
Marshal.SizeOf (typeof (StrExplicit));
|
|
}
|
|
|
|
[Test]
|
|
public void SizeOf_Array ()
|
|
{
|
|
try {
|
|
Marshal.SizeOf (typeof (string []));
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentException ex) {
|
|
// Type 'System.String[]' cannot be marshaled
|
|
// as an unmanaged structure; no meaningful
|
|
// size or offset can be computed
|
|
Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public unsafe void Sizeof_Pointer ()
|
|
{
|
|
int size = Marshal.SizeOf (typeof (char*));
|
|
Assert.IsTrue (size == 4 || size == 8);
|
|
}
|
|
|
|
[Test]
|
|
public unsafe void Sizeof_Void ()
|
|
{
|
|
int size = Marshal.SizeOf (typeof (void));
|
|
Assert.AreEqual (1, size);
|
|
}
|
|
|
|
[Test]
|
|
public void PtrToStringWithNull ()
|
|
{
|
|
Assert.IsNull (Marshal.PtrToStringAnsi (IntPtr.Zero), "A");
|
|
Assert.IsNull (Marshal.PtrToStringUni (IntPtr.Zero), "C");
|
|
}
|
|
|
|
[Test]
|
|
public void PtrToStringAnsi_Ptr_Zero ()
|
|
{
|
|
try {
|
|
Marshal.PtrToStringAnsi (IntPtr.Zero, 0);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("ptr", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void PtrToStringWithUni_Ptr_Zero ()
|
|
{
|
|
try {
|
|
Marshal.PtrToStringUni (IntPtr.Zero, 0);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("ptr", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
readonly String[] TestStrings = new String[] {
|
|
"", //Empty String
|
|
"Test String",
|
|
"A", //Single character string
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself. " +
|
|
"This is a very long string as it repeats itself.",
|
|
"This \n is \n a \n multiline \n string",
|
|
"This \0 is \0 a \0 string \0 with \0 nulls",
|
|
"\0string",
|
|
"string\0",
|
|
"\0\0\0\0\0\0\0\0"
|
|
};
|
|
|
|
[Test]
|
|
public unsafe void PtrToStringUTF8_Test ()
|
|
{
|
|
int i = 0;
|
|
foreach (String srcString in TestStrings)
|
|
{
|
|
i++;
|
|
// we assume string null terminated
|
|
if (srcString.Contains("\0"))
|
|
continue;
|
|
|
|
IntPtr ptrString = Marshal.StringToAllocatedMemoryUTF8(srcString);
|
|
string retString = Marshal.PtrToStringUTF8(ptrString);
|
|
|
|
Assert.AreEqual (srcString, retString, "#" + i);
|
|
if (srcString.Length > 0)
|
|
{
|
|
string retString2 = Marshal.PtrToStringUTF8(ptrString, srcString.Length - 1);
|
|
Assert.AreEqual (srcString.Substring(0, srcString.Length - 1), retString2, "#s" + i);
|
|
}
|
|
Marshal.FreeHGlobal(ptrString);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public unsafe void UnsafeAddrOfPinnedArrayElement ()
|
|
{
|
|
short[] sarr = new short [5];
|
|
sarr [2] = 3;
|
|
|
|
IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement (sarr, 2);
|
|
Assert.AreEqual (3, *(short*) ptr.ToPointer ());
|
|
}
|
|
|
|
[Test]
|
|
public void AllocHGlobalZeroSize ()
|
|
{
|
|
IntPtr ptr = Marshal.AllocHGlobal (0);
|
|
Assert.IsTrue (ptr != IntPtr.Zero);
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
|
|
[Test]
|
|
public void AllocCoTaskMemZeroSize ()
|
|
{
|
|
IntPtr ptr = Marshal.AllocCoTaskMem (0);
|
|
Assert.IsTrue (ptr != IntPtr.Zero);
|
|
Marshal.FreeCoTaskMem (ptr);
|
|
}
|
|
|
|
public struct Foo {
|
|
public int a;
|
|
public static int b;
|
|
public long c;
|
|
public static char d;
|
|
public int e;
|
|
}
|
|
|
|
[Test]
|
|
public void OffsetOf_FieldName_Static ()
|
|
{
|
|
try {
|
|
Marshal.OffsetOf (typeof (Foo), "b");
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentException ex) {
|
|
// Field passed in is not a marshaled member of
|
|
// the type '...MarshalTest+Foo'
|
|
Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("fieldName", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
#if !MOBILE
|
|
[Test]
|
|
public void GetHINSTANCE ()
|
|
{
|
|
if (RunningOnMono)
|
|
Assert.Ignore ("GetHINSTANCE only applies to .NET on Windows.");
|
|
|
|
Assembly a;
|
|
IntPtr hinstance;
|
|
StringBuilder fileName;
|
|
|
|
fileName = new StringBuilder (255);
|
|
a = Assembly.GetExecutingAssembly ();
|
|
hinstance = Marshal.GetHINSTANCE (a.GetModules () [0]);
|
|
Assert.IsTrue (GetModuleFileName (hinstance, fileName,
|
|
fileName.Capacity) > 0, "#A1");
|
|
Assert.AreEqual (a.Location, fileName.ToString (), "#A2");
|
|
|
|
fileName.Length = 0;
|
|
a = typeof (int).Assembly;
|
|
hinstance = Marshal.GetHINSTANCE (a.GetModules () [0]);
|
|
Assert.IsTrue (GetModuleFileName (hinstance, fileName,
|
|
fileName.Capacity) > 0, "#B1");
|
|
Assert.IsTrue (File.Exists (fileName.ToString ()), "#B3");
|
|
Assert.AreEqual ("mscorlib.dll", Path.GetFileName (fileName.ToString ()), "#B4");
|
|
}
|
|
|
|
[Test]
|
|
public void GetHINSTANCE_Module_Dynamic ()
|
|
{
|
|
AssemblyName aname = new AssemblyName ();
|
|
aname.Name = "foo";
|
|
|
|
AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (
|
|
aname, AssemblyBuilderAccess.Save,
|
|
Path.GetTempPath ());
|
|
ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", false);
|
|
|
|
IntPtr hinstance = Marshal.GetHINSTANCE (mb);
|
|
Assert.AreEqual (-1, hinstance.ToInt32 ());
|
|
}
|
|
|
|
[Test]
|
|
public void GetHINSTANCE_Module_Null ()
|
|
{
|
|
try {
|
|
Marshal.GetHINSTANCE ((Module) null);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("m", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
[Test]
|
|
public void GetHRForException ()
|
|
{
|
|
Assert.AreEqual (0, Marshal.GetHRForException (null));
|
|
Assert.IsTrue (Marshal.GetHRForException (new Exception ()) < 0);
|
|
Assert.AreEqual (12345, Marshal.GetHRForException (new IOException ("test message", 12345)));
|
|
}
|
|
|
|
[Test] // bug #319009
|
|
public void StringToHGlobalUni ()
|
|
{
|
|
IntPtr handle = Marshal.StringToHGlobalUni ("unicode data");
|
|
string s = Marshal.PtrToStringUni (handle);
|
|
Assert.AreEqual (12, s.Length, "#1");
|
|
|
|
handle = Marshal.StringToHGlobalUni ("unicode data string");
|
|
s = Marshal.PtrToStringUni (handle);
|
|
Assert.AreEqual (19, s.Length, "#2");
|
|
}
|
|
|
|
[Test]
|
|
public void ReadIntByte ()
|
|
{
|
|
IntPtr ptr = Marshal.AllocHGlobal (4);
|
|
try {
|
|
Marshal.WriteByte (ptr, 0, 0x1);
|
|
Marshal.WriteByte (ptr, 1, 0x2);
|
|
Assert.AreEqual (0x1, Marshal.ReadByte (ptr));
|
|
Assert.AreEqual (0x1, Marshal.ReadByte (ptr, 0));
|
|
Assert.AreEqual (0x2, Marshal.ReadByte (ptr, 1));
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ReadInt16 ()
|
|
{
|
|
IntPtr ptr = Marshal.AllocHGlobal (64);
|
|
try {
|
|
Marshal.WriteInt16 (ptr, 0, 0x1234);
|
|
Marshal.WriteInt16 (ptr, 2, 0x4567);
|
|
Marshal.WriteInt16 (ptr, 5, 0x4567);
|
|
Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr));
|
|
Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr, 0));
|
|
Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 2));
|
|
Assert.AreEqual (0x4567, Marshal.ReadInt16 ((ptr + 5)));
|
|
Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 5));
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ReadInt32 ()
|
|
{
|
|
IntPtr ptr = Marshal.AllocHGlobal (64);
|
|
try {
|
|
Marshal.WriteInt32 (ptr, 0, 0x12345678);
|
|
Marshal.WriteInt32 (ptr, 4, 0x77654321);
|
|
Marshal.WriteInt32 (ptr, 10, 0x77654321);
|
|
Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr));
|
|
Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr, 0));
|
|
Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 4));
|
|
Assert.AreEqual (0x77654321, Marshal.ReadInt32 ((ptr + 10)));
|
|
Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 10));
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ReadInt32_Endian ()
|
|
{
|
|
IntPtr ptr = Marshal.AllocHGlobal (4);
|
|
try {
|
|
Marshal.WriteByte (ptr, 0, 0x01);
|
|
Marshal.WriteByte (ptr, 1, 0x02);
|
|
Marshal.WriteByte (ptr, 2, 0x03);
|
|
Marshal.WriteByte (ptr, 3, 0x04);
|
|
// Marshal MUST use the native CPU data
|
|
if (BitConverter.IsLittleEndian){
|
|
Assert.AreEqual (0x04030201, Marshal.ReadInt32 (ptr), "ReadInt32");
|
|
} else {
|
|
Assert.AreEqual (0x01020304, Marshal.ReadInt32 (ptr), "ReadInt32");
|
|
}
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void ReadInt64 ()
|
|
{
|
|
IntPtr ptr = Marshal.AllocHGlobal (16);
|
|
try {
|
|
Marshal.WriteInt64 (ptr, 0, 0x12345678ABCDEFL);
|
|
Marshal.WriteInt64 (ptr, 8, 0x87654321ABCDEFL);
|
|
Assert.AreEqual (0x12345678ABCDEFL, Marshal.ReadInt64 (ptr));
|
|
Assert.AreEqual (0x12345678ABCDEFL, Marshal.ReadInt64 (ptr, 0));
|
|
Assert.AreEqual (0x87654321ABCDEFL, Marshal.ReadInt64 (ptr, 8));
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void BSTR_Roundtrip ()
|
|
{
|
|
string s = "mono";
|
|
IntPtr ptr = Marshal.StringToBSTR (s);
|
|
string s2 = Marshal.PtrToStringBSTR (ptr);
|
|
Assert.AreEqual (s, s2, "string");
|
|
}
|
|
|
|
[Test]
|
|
public void StringToBSTRWithNullValues ()
|
|
{
|
|
int size = 128;
|
|
string s = String.Empty.PadLeft (size, '\0');
|
|
Assert.AreEqual (size, s.Length, "Length-1");
|
|
|
|
IntPtr ptr = Marshal.StringToBSTR (s);
|
|
try {
|
|
for (int i = 0; i < size; i += 4)
|
|
Marshal.WriteInt32 (ptr, i, 0);
|
|
|
|
string s2 = Marshal.PtrToStringBSTR (ptr);
|
|
Assert.AreEqual (128, s2.Length, "Length-2");
|
|
} finally {
|
|
Marshal.FreeBSTR (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void StringToHGlobalAnsiWithNullValues ()
|
|
{
|
|
int size = 128;
|
|
string s = String.Empty.PadLeft (size, '\0');
|
|
Assert.AreEqual (size, s.Length, "Length-1");
|
|
|
|
IntPtr ptr = Marshal.StringToHGlobalAnsi (s);
|
|
try {
|
|
for (int i = 0; i < size; i += 4)
|
|
Marshal.WriteInt32 (ptr, i, 0);
|
|
|
|
string s2 = Marshal.PtrToStringAnsi (ptr);
|
|
Assert.AreEqual (0, s2.Length, "Length-2");
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void StringToHGlobalAutoWithNullValues ()
|
|
{
|
|
int size = 128;
|
|
string s = String.Empty.PadLeft (size, '\0');
|
|
Assert.AreEqual (size, s.Length, "Length-1");
|
|
|
|
IntPtr ptr = Marshal.StringToHGlobalAuto (s);
|
|
try {
|
|
for (int i = 0; i < size; i += 4)
|
|
Marshal.WriteInt32 (ptr, i, 0);
|
|
|
|
string s2 = Marshal.PtrToStringAuto (ptr);
|
|
Assert.AreEqual (0, s2.Length, "Length-2");
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void StringToHGlobalUniWithNullValues ()
|
|
{
|
|
int size = 128;
|
|
string s = String.Empty.PadLeft (size, '\0');
|
|
Assert.AreEqual (size, s.Length, "Length-1");
|
|
|
|
IntPtr ptr = Marshal.StringToHGlobalUni (s);
|
|
try {
|
|
for (int i = 0; i < size; i += 4)
|
|
Marshal.WriteInt32 (ptr, i, 0);
|
|
|
|
string s2 = Marshal.PtrToStringUni (ptr);
|
|
Assert.AreEqual (0, s2.Length, "Length-2");
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void StringToCoTaskMemAnsiWithNullValues ()
|
|
{
|
|
int size = 128;
|
|
string s = String.Empty.PadLeft (size, '\0');
|
|
Assert.AreEqual (size, s.Length, "Length-1");
|
|
|
|
IntPtr ptr = Marshal.StringToCoTaskMemAnsi (s);
|
|
try {
|
|
for (int i = 0; i < size; i += 4)
|
|
Marshal.WriteInt32 (ptr, i, 0);
|
|
|
|
string s2 = Marshal.PtrToStringAnsi (ptr);
|
|
Assert.AreEqual (0, s2.Length, "Length-2");
|
|
} finally {
|
|
Marshal.FreeCoTaskMem (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void StringToCoTaskMemAutoWithNullValues ()
|
|
{
|
|
int size = 128;
|
|
string s = String.Empty.PadLeft (size, '\0');
|
|
Assert.AreEqual (size, s.Length, "Length-1");
|
|
|
|
IntPtr ptr = Marshal.StringToCoTaskMemAuto (s);
|
|
try {
|
|
for (int i = 0; i < size; i += 4)
|
|
Marshal.WriteInt32 (ptr, i, 0);
|
|
|
|
string s2 = Marshal.PtrToStringAuto (ptr);
|
|
Assert.AreEqual (0, s2.Length, "Length-2");
|
|
} finally {
|
|
Marshal.FreeCoTaskMem (ptr);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void StringToCoTaskMemUniWithNullValues ()
|
|
{
|
|
int size = 128;
|
|
string s = String.Empty.PadLeft (size, '\0');
|
|
Assert.AreEqual (size, s.Length, "Length-1");
|
|
|
|
IntPtr ptr = Marshal.StringToCoTaskMemUni (s);
|
|
try {
|
|
for (int i = 0; i < size; i += 4)
|
|
Marshal.WriteInt32 (ptr, i, 0);
|
|
|
|
string s2 = Marshal.PtrToStringUni (ptr);
|
|
Assert.AreEqual (0, s2.Length, "Length-2");
|
|
} finally {
|
|
Marshal.FreeCoTaskMem (ptr);
|
|
}
|
|
}
|
|
private const string NotSupported = "Not supported before Windows 2000 Service Pack 3";
|
|
private static char[] PlainText = new char[] { 'a', 'b', 'c' };
|
|
private static byte[] AsciiPlainText = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c' };
|
|
|
|
private unsafe SecureString GetSecureString ()
|
|
{
|
|
fixed (char* p = &PlainText[0]) {
|
|
return new SecureString (p, PlainText.Length);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToBSTR_Null ()
|
|
{
|
|
try {
|
|
Marshal.SecureStringToBSTR (null);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("s", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToBSTR ()
|
|
{
|
|
try {
|
|
SecureString ss = GetSecureString ();
|
|
IntPtr p = Marshal.SecureStringToBSTR (ss);
|
|
|
|
char[] decrypted = new char[ss.Length];
|
|
Marshal.Copy (p, decrypted, 0, decrypted.Length);
|
|
Assert.AreEqual (PlainText, decrypted, "Decrypted");
|
|
|
|
Marshal.ZeroFreeBSTR (p);
|
|
} catch (NotSupportedException) {
|
|
Assert.Ignore (NotSupported);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToCoTaskMemAnsi_Null ()
|
|
{
|
|
try {
|
|
Marshal.SecureStringToCoTaskMemAnsi (null);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("s", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToCoTaskMemAnsi ()
|
|
{
|
|
try {
|
|
SecureString ss = GetSecureString ();
|
|
IntPtr p = Marshal.SecureStringToCoTaskMemAnsi (ss);
|
|
|
|
byte[] decrypted = new byte[ss.Length];
|
|
Marshal.Copy (p, decrypted, 0, decrypted.Length);
|
|
Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
|
|
|
|
Marshal.ZeroFreeCoTaskMemAnsi (p);
|
|
} catch (NotSupportedException) {
|
|
Assert.Ignore (NotSupported);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToCoTaskMemUnicode_Null ()
|
|
{
|
|
try {
|
|
Marshal.SecureStringToCoTaskMemUnicode (null);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("s", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToCoTaskMemUnicode ()
|
|
{
|
|
try {
|
|
SecureString ss = GetSecureString ();
|
|
IntPtr p = Marshal.SecureStringToCoTaskMemUnicode (ss);
|
|
|
|
char[] decrypted = new char[ss.Length];
|
|
Marshal.Copy (p, decrypted, 0, decrypted.Length);
|
|
Assert.AreEqual (PlainText, decrypted, "Decrypted");
|
|
|
|
Marshal.ZeroFreeCoTaskMemUnicode (p);
|
|
} catch (NotSupportedException) {
|
|
Assert.Ignore (NotSupported);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToGlobalAllocAnsi_Null ()
|
|
{
|
|
try {
|
|
Marshal.SecureStringToGlobalAllocAnsi (null);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("s", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToGlobalAllocAnsi ()
|
|
{
|
|
try {
|
|
SecureString ss = GetSecureString ();
|
|
IntPtr p = Marshal.SecureStringToGlobalAllocAnsi (ss);
|
|
|
|
byte[] decrypted = new byte[ss.Length];
|
|
Marshal.Copy (p, decrypted, 0, decrypted.Length);
|
|
Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
|
|
|
|
Marshal.ZeroFreeGlobalAllocAnsi (p);
|
|
} catch (NotSupportedException) {
|
|
Assert.Ignore (NotSupported);
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToGlobalAllocUnicode_Null ()
|
|
{
|
|
try {
|
|
Marshal.SecureStringToGlobalAllocUnicode (null);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("s", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void SecureStringToGlobalAllocUnicode ()
|
|
{
|
|
try {
|
|
SecureString ss = GetSecureString ();
|
|
IntPtr p = Marshal.SecureStringToGlobalAllocUnicode (ss);
|
|
|
|
char[] decrypted = new char[ss.Length];
|
|
Marshal.Copy (p, decrypted, 0, decrypted.Length);
|
|
Assert.AreEqual (PlainText, decrypted, "Decrypted");
|
|
|
|
Marshal.ZeroFreeGlobalAllocUnicode (p);
|
|
} catch (NotSupportedException) {
|
|
Assert.Ignore (NotSupported);
|
|
}
|
|
}
|
|
|
|
#if !MOBILE
|
|
[Test]
|
|
public void TestGetComSlotForMethodInfo ()
|
|
{
|
|
Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDefault).GetMethod("DoNothing")));
|
|
Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDual).GetMethod("DoNothing")));
|
|
Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo (typeof(ITestDefault).GetMethod ("DoNothing")));
|
|
Assert.AreEqual (3, Marshal.GetComSlotForMethodInfo (typeof(ITestUnknown).GetMethod ("DoNothing")));
|
|
|
|
for (int i = 0; i < 10; i++)
|
|
Assert.AreEqual (7+i, Marshal.GetComSlotForMethodInfo(typeof(ITestInterface).GetMethod ("Method"+i.ToString())));
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetComSlotForMethod_Method_Null ()
|
|
{
|
|
try {
|
|
Marshal.GetComSlotForMethodInfo (null);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentNullException ex) {
|
|
Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("m", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetComSlotForMethodInfo_Method_NotOnInterface ()
|
|
{
|
|
MethodInfo m = typeof(TestCoClass).GetMethod ("DoNothing");
|
|
try {
|
|
Marshal.GetComSlotForMethodInfo (m);
|
|
Assert.Fail ("#1");
|
|
} catch (ArgumentException ex) {
|
|
// The MemberInfo must be an interface method
|
|
Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
|
|
Assert.IsNull (ex.InnerException, "#3");
|
|
Assert.IsNotNull (ex.Message, "#4");
|
|
Assert.AreEqual ("m", ex.ParamName, "#5");
|
|
}
|
|
}
|
|
#endif
|
|
[Test]
|
|
public void TestPtrToStringAuto ()
|
|
{
|
|
string input = Guid.NewGuid ().ToString ();
|
|
string output;
|
|
string output2;
|
|
int len = 4;
|
|
IntPtr ptr;
|
|
|
|
if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
|
|
// Auto -> Uni
|
|
ptr = Marshal.StringToHGlobalAuto (input);
|
|
output = Marshal.PtrToStringUni (ptr);
|
|
output2 = Marshal.PtrToStringUni (ptr, len);
|
|
} else {
|
|
// Auto -> Ansi
|
|
ptr = Marshal.StringToHGlobalAuto (input);
|
|
output = Marshal.PtrToStringAnsi (ptr);
|
|
output2 = Marshal.PtrToStringAnsi (ptr, len);
|
|
}
|
|
|
|
try {
|
|
Assert.AreEqual (input, output, "#1");
|
|
Assert.AreEqual (input.Substring (0, len), output2, "#2");
|
|
} finally {
|
|
Marshal.FreeHGlobal (ptr);
|
|
}
|
|
}
|
|
#if !MOBILE
|
|
[Test]
|
|
public void TestGenerateProgIdForType()
|
|
{
|
|
string output;
|
|
|
|
output = Marshal.GenerateProgIdForType(typeof(TestCoClass));
|
|
Assert.AreEqual ("MonoTests.System.Runtime.InteropServices.TestCoClass", output, "#1");
|
|
|
|
output = Marshal.GenerateProgIdForType(typeof(TestCoClassWithProgId));
|
|
Assert.AreEqual ("CoClassWithProgId", output, "#2");
|
|
}
|
|
#endif
|
|
[Test]
|
|
public void TestGlobalAlloc ()
|
|
{
|
|
IntPtr mem = Marshal.AllocHGlobal (100);
|
|
mem = Marshal.ReAllocHGlobal (mem, (IntPtr) 1000000);
|
|
Marshal.FreeHGlobal (mem);
|
|
}
|
|
|
|
[Test]
|
|
public void FreeHGlobal ()
|
|
{
|
|
// clear user doubts on assistly #6749
|
|
for (int i = 0; i < 1024; i++) {
|
|
IntPtr p = Marshal.AllocHGlobal (1024 * 1024);
|
|
Assert.AreNotEqual (IntPtr.Zero, p, i.ToString ());
|
|
Marshal.FreeHGlobal (p);
|
|
}
|
|
}
|
|
|
|
[StructLayout (LayoutKind.Sequential)]
|
|
public struct SimpleStruct2 {
|
|
public int a;
|
|
public int b;
|
|
}
|
|
|
|
[Test]
|
|
public void PtrToStructureNull ()
|
|
{
|
|
Assert.IsNull (Marshal.PtrToStructure (IntPtr.Zero, typeof (SimpleStruct2)));
|
|
}
|
|
|
|
[Test]
|
|
public void TestGetExceptionForHR ()
|
|
{
|
|
const int E_OUTOFMEMORY = unchecked ((int) 0x8007000E);
|
|
const int E_INVALIDARG = unchecked ((int) 0X80070057);
|
|
|
|
Exception ex = Marshal.GetExceptionForHR (E_OUTOFMEMORY);
|
|
Assert.AreEqual (typeof (OutOfMemoryException), ex.GetType (), "E_OUTOFMEMORY");
|
|
|
|
ex = Marshal.GetExceptionForHR (E_INVALIDARG);
|
|
Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "E_INVALIDARG");
|
|
}
|
|
bool RunningOnMono {
|
|
get {
|
|
return (Type.GetType ("System.MonoType", false) != null);
|
|
}
|
|
}
|
|
|
|
#if !MOBILE
|
|
[DllImport ("kernel32.dll", SetLastError = true)]
|
|
[PreserveSig]
|
|
static extern uint GetModuleFileName (
|
|
[In]
|
|
IntPtr hModule,
|
|
[Out]
|
|
StringBuilder lpFilename,
|
|
[In]
|
|
[MarshalAs (UnmanagedType.U4)]
|
|
int nSize
|
|
);
|
|
#endif
|
|
|
|
#if !FULL_AOT_RUNTIME
|
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
|
public class FourByteStruct
|
|
{
|
|
public UInt16 value1;
|
|
public UInt16 value2;
|
|
}
|
|
|
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
|
public class ByteArrayFourByteStruct : FourByteStruct
|
|
{
|
|
[MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
|
|
public byte[] array;
|
|
}
|
|
|
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
|
public class SingleByteStruct
|
|
{
|
|
public byte value1;
|
|
}
|
|
|
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
|
public class ByteArraySingleByteStruct : SingleByteStruct
|
|
{
|
|
[MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
|
|
public byte[] array1;
|
|
public byte value2;
|
|
}
|
|
|
|
[StructLayout( LayoutKind.Sequential, Pack = 1 )]
|
|
public class ByteArraySingleByteChildStruct : ByteArraySingleByteStruct
|
|
{
|
|
[MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
|
|
public byte[] array2;
|
|
}
|
|
|
|
[Test]
|
|
public void CheckByteArrayFourByteStruct()
|
|
{
|
|
ByteArrayFourByteStruct myStruct = new ByteArrayFourByteStruct
|
|
{ value1 = 42, value2 = 53, array = Encoding.UTF8.GetBytes( "Hello" ) };
|
|
|
|
byte[] buffer = Serialize (myStruct);
|
|
|
|
UInt16 value1 = BitConverter.ToUInt16 (buffer, 0);
|
|
UInt16 value2 = BitConverter.ToUInt16 (buffer, 2);
|
|
string array = Encoding.UTF8.GetString (buffer, 4, 5);
|
|
|
|
Assert.AreEqual((UInt16)42, value1);
|
|
Assert.AreEqual((UInt16)53, value2);
|
|
Assert.AreEqual ("Hello", array);
|
|
}
|
|
|
|
[Test]
|
|
public void CheckByteArraySingleByteChildStruct()
|
|
{
|
|
ByteArraySingleByteChildStruct myStruct = new ByteArraySingleByteChildStruct
|
|
{ value1 = 42, array1 = Encoding.UTF8.GetBytes( "Hello" ), value2 = 53, array2 = Encoding.UTF8.GetBytes( "World" ) };
|
|
|
|
byte[] array = Serialize (myStruct);
|
|
|
|
byte value1 = array [0];
|
|
string array1 = Encoding.UTF8.GetString (array, 1, 5);
|
|
byte value2 = array [6];
|
|
string array2 = Encoding.UTF8.GetString (array, 7, 5);
|
|
|
|
Assert.AreEqual((byte)42, value1);
|
|
Assert.AreEqual ("Hello", array1);
|
|
Assert.AreEqual((byte)53, value2);
|
|
Assert.AreEqual ("World", array2);
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public struct FiveByteStruct
|
|
{
|
|
public uint uIntField;
|
|
public byte byteField;
|
|
};
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public class Base
|
|
{
|
|
public ushort firstUShortField;
|
|
public ushort secondUShortField;
|
|
}
|
|
|
|
[StructLayout(LayoutKind.Sequential, Pack = 1)]
|
|
public class Derived : Base
|
|
{
|
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
|
|
public FiveByteStruct[] arrayField;
|
|
}
|
|
|
|
[Test]
|
|
public void CheckPtrToStructureWithFixedArrayAndBaseClassFields()
|
|
{
|
|
const int arraySize = 6;
|
|
var derived = new Derived
|
|
{
|
|
arrayField = new FiveByteStruct[arraySize],
|
|
firstUShortField = 42,
|
|
secondUShortField = 43
|
|
};
|
|
|
|
for (var i = 0; i < arraySize; ++i)
|
|
{
|
|
derived.arrayField[i].byteField = (byte)i;
|
|
derived.arrayField[i].uIntField = (uint)i * 10;
|
|
}
|
|
|
|
var array = Serialize(derived);
|
|
var deserializedDerived = Deserialize<Derived>(array);
|
|
|
|
Assert.AreEqual(derived.firstUShortField, deserializedDerived.firstUShortField, "The firstUShortField differs, which is not expected.");
|
|
Assert.AreEqual(derived.secondUShortField, deserializedDerived.secondUShortField, "The secondUShortField differs, which is not expected.");
|
|
|
|
for (var i = 0; i < arraySize; ++i)
|
|
{
|
|
Assert.AreEqual(derived.arrayField[i].byteField, deserializedDerived.arrayField[i].byteField, string.Format("The byteField at index {0} differs, which is not expected.", i));
|
|
Assert.AreEqual(derived.arrayField[i].uIntField, deserializedDerived.arrayField[i].uIntField, string.Format("The uIntField at index {0} differs, which is not expected.", i));
|
|
}
|
|
}
|
|
|
|
public static byte[] Serialize( object obj )
|
|
{
|
|
int nTypeSize = Marshal.SizeOf( obj );
|
|
byte[] arrBuffer = new byte[nTypeSize];
|
|
|
|
GCHandle hGCHandle = GCHandle.Alloc( arrBuffer, GCHandleType.Pinned );
|
|
IntPtr pBuffer = hGCHandle.AddrOfPinnedObject();
|
|
Marshal.StructureToPtr( obj, pBuffer, false );
|
|
hGCHandle.Free();
|
|
|
|
return arrBuffer;
|
|
}
|
|
|
|
public static T Deserialize<T>(byte[] buffer)
|
|
{
|
|
var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
|
var pBuffer = handle.AddrOfPinnedObject();
|
|
var objResult = (T)Marshal.PtrToStructure(pBuffer, typeof(T));
|
|
handle.Free();
|
|
|
|
return objResult;
|
|
}
|
|
#endif
|
|
}
|
|
#if !MOBILE
|
|
[ComImport()]
|
|
[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
|
|
interface ITestDefault
|
|
{
|
|
void DoNothing ();
|
|
}
|
|
|
|
[ComImport()]
|
|
[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
|
|
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
|
|
interface ITestDispatch
|
|
{
|
|
void DoNothing ();
|
|
}
|
|
|
|
[ComImport()]
|
|
[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
|
|
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
|
|
interface ITestDual
|
|
{
|
|
void DoNothing ();
|
|
}
|
|
|
|
[ComImport()]
|
|
[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
|
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
interface ITestUnknown
|
|
{
|
|
void DoNothing ();
|
|
}
|
|
|
|
[ComImport()]
|
|
[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
|
|
interface ITestInterface
|
|
{
|
|
void Method0 ();
|
|
void Method1 ();
|
|
void Method2 ();
|
|
void Method3 ();
|
|
void Method4 ();
|
|
void Method5 ();
|
|
void Method6 ();
|
|
void Method7 ();
|
|
void Method8 ();
|
|
void Method9 ();
|
|
}
|
|
|
|
public class TestCoClass : ITestDispatch
|
|
{
|
|
public void DoNothing ()
|
|
{
|
|
}
|
|
}
|
|
|
|
[ProgId("CoClassWithProgId")]
|
|
public class TestCoClassWithProgId : ITestDispatch
|
|
{
|
|
public void DoNothing ()
|
|
{
|
|
}
|
|
}
|
|
#endif
|
|
}
|