Merge pull request #4023 from lateralusX/jlorenss/test-driver-reporter
[mono.git] / mcs / class / corlib / Test / System.Runtime.InteropServices / MarshalTest.cs
1 //
2 // System.Runtime.InteropServices.Marshal Test Cases
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //      Sebastien Pouliot  <sebastien@ximian.com>
7 //
8 // Copyright (C) 2004-2007 Novell, Inc (http://www.novell.com)
9 //
10 using NUnit.Framework;
11 using System;
12 using System.IO;
13 using System.Reflection;
14 #if !MOBILE
15 using System.Reflection.Emit;
16 #endif
17 using System.Runtime.InteropServices;
18 using System.Security;
19 using System.Text;
20
21 namespace MonoTests.System.Runtime.InteropServices
22 {
23         [TestFixture]
24         public class MarshalTest
25         {
26                 [StructLayout (LayoutKind.Sequential)]
27                 class ClsSequential {
28                         public int field;
29                 }
30
31                 public class ClsNoLayout {
32                         public int field;
33                 }
34
35                 [StructLayout (LayoutKind.Explicit)]
36                 class ClsExplicit {
37                         [FieldOffset (0)] public int field;
38                 }
39
40                 [StructLayout (LayoutKind.Sequential)]
41                 struct StrSequential {
42                         public int field;
43                 }
44
45                 struct StrNoLayout {
46                         public int field;
47                 }
48
49                 [StructLayout (LayoutKind.Explicit)]
50                 struct StrExplicit {
51                         [FieldOffset (0)] public int field;
52                 }
53
54                 [Test]
55                 public void SizeOf_Class_LayoutSequential ()
56                 {
57                         Marshal.SizeOf (typeof (ClsSequential));
58                 }
59
60                 [Test]
61                 public void SizeOf_Class_LayoutNotSet ()
62                 {
63                         try {
64                                 Marshal.SizeOf (typeof (ClsNoLayout));
65                                 Assert.Fail ("#1");
66                         } catch (ArgumentException ex) {
67                                 // Type '...MarshalTest+ClsNoLayout' cannot be
68                                 // marshaled as an unmanaged structure; no
69                                 // meaningful size or offset can be computed
70                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
71                                 Assert.IsNull (ex.InnerException, "#3");
72                                 Assert.IsNotNull (ex.Message, "#4");
73                         }
74                 }
75
76                 [Test]
77                 public void SizeOf_Class_LayoutExplicit ()
78                 {
79                         Marshal.SizeOf (typeof (ClsExplicit));
80                 }
81
82                 [Test]
83                 public void SizeOf_Struct_LayoutSequential ()
84                 {
85                         Marshal.SizeOf (typeof (StrSequential));
86                 }
87
88                 [Test]
89                 public void SizeOf_Struct_LayoutNotSet ()
90                 {
91                         Marshal.SizeOf (typeof (StrNoLayout));
92                 }
93
94                 [Test]
95                 public void SizeOf_Struct_LayoutExplicit ()
96                 {
97                         Marshal.SizeOf (typeof (StrExplicit));
98                 }
99
100                 [Test]
101                 public void SizeOf_Array ()
102                 {
103                         try {
104                                 Marshal.SizeOf (typeof (string []));
105                                 Assert.Fail ("#1");
106                         } catch (ArgumentException ex) {
107                                 // Type 'System.String[]' cannot be marshaled
108                                 // as an unmanaged structure; no meaningful
109                                 // size or offset can be computed
110                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
111                                 Assert.IsNull (ex.InnerException, "#3");
112                                 Assert.IsNotNull (ex.Message, "#4");
113                         }
114                 }
115
116                 [Test]
117                 public unsafe void Sizeof_Pointer ()
118                 {
119                         int size = Marshal.SizeOf (typeof (char*));
120                         Assert.IsTrue (size == 4 || size == 8);
121                 }
122
123                 [Test]
124                 public void PtrToStringWithNull ()
125                 {
126                         Assert.IsNull (Marshal.PtrToStringAnsi (IntPtr.Zero), "A");
127                         Assert.IsNull (Marshal.PtrToStringUni (IntPtr.Zero), "C");
128                 }
129
130                 [Test]
131                 public void PtrToStringAnsi_Ptr_Zero ()
132                 {
133                         try {
134                                 Marshal.PtrToStringAnsi (IntPtr.Zero, 0);
135                                 Assert.Fail ("#1");
136                         } catch (ArgumentNullException ex) {
137                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
138                                 Assert.IsNull (ex.InnerException, "#3");
139                                 Assert.IsNotNull (ex.Message, "#4");
140                                 Assert.AreEqual ("ptr", ex.ParamName, "#5");
141                         }
142                 }
143
144                 [Test]
145                 public void PtrToStringWithUni_Ptr_Zero ()
146                 {
147                         try {
148                                 Marshal.PtrToStringUni (IntPtr.Zero, 0);
149                                 Assert.Fail ("#1");
150                         } catch (ArgumentNullException ex) {
151                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
152                                 Assert.IsNull (ex.InnerException, "#3");
153                                 Assert.IsNotNull (ex.Message, "#4");
154                                 Assert.AreEqual ("ptr", ex.ParamName, "#5");
155                         }
156                 }
157
158                 readonly String[] TestStrings = new String[] {
159                         "", //Empty String
160                         "Test String",
161                         "A", //Single character string
162                         "This is a very long string as it repeats itself. " +
163                         "This is a very long string as it repeats itself. " +
164                         "This is a very long string as it repeats itself. " +
165                         "This is a very long string as it repeats itself. " +
166                         "This is a very long string as it repeats itself. " +
167                         "This is a very long string as it repeats itself. " +
168                         "This is a very long string as it repeats itself. " +
169                         "This is a very long string as it repeats itself. " +
170                         "This is a very long string as it repeats itself. " +
171                         "This is a very long string as it repeats itself. " +
172                         "This is a very long string as it repeats itself. " +
173                         "This is a very long string as it repeats itself. " +
174                         "This is a very long string as it repeats itself.",
175                         "This \n is \n a \n multiline \n string",
176                         "This \0 is \0 a \0 string \0 with \0 nulls",
177                         "\0string",
178                         "string\0",
179                         "\0\0\0\0\0\0\0\0"
180                 };
181
182                 [Test]
183                 public unsafe void PtrToStringUTF8_Test ()
184                 {
185                         int i = 0; 
186                         foreach (String srcString in TestStrings)
187                         {
188                                 i++;
189                                 // we assume string null terminated
190                                 if (srcString.Contains("\0"))
191                                         continue;
192
193                                 IntPtr ptrString = Marshal.StringToAllocatedMemoryUTF8(srcString);
194                                 string retString = Marshal.PtrToStringUTF8(ptrString);
195
196                                 Assert.AreEqual (srcString, retString, "#" + i);
197                                 if (srcString.Length > 0)
198                                 {
199                                         string retString2 = Marshal.PtrToStringUTF8(ptrString, srcString.Length - 1);
200                                         Assert.AreEqual (srcString.Substring(0, srcString.Length - 1), retString2, "#s" + i);
201                                 }
202                                 Marshal.FreeHGlobal(ptrString);
203                         }                       
204                 }
205                 
206                 [Test]
207                 public unsafe void UnsafeAddrOfPinnedArrayElement ()
208                 {
209                         short[] sarr = new short [5];
210                         sarr [2] = 3;
211
212                         IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement (sarr, 2);
213                         Assert.AreEqual (3, *(short*) ptr.ToPointer ());
214                 }
215
216                 [Test]
217                 public void AllocHGlobalZeroSize ()
218                 {
219                         IntPtr ptr = Marshal.AllocHGlobal (0);
220                         Assert.IsTrue (ptr != IntPtr.Zero);
221                         Marshal.FreeHGlobal (ptr);
222                 }
223
224                 [Test]
225                 public void AllocCoTaskMemZeroSize ()
226                 {
227                         IntPtr ptr = Marshal.AllocCoTaskMem (0);
228                         Assert.IsTrue (ptr != IntPtr.Zero);
229                         Marshal.FreeCoTaskMem (ptr);
230                 }
231
232                 public struct Foo {
233                         public int a;
234                         public static int b;
235                         public long c;
236                         public static char d;
237                         public int e;
238                 }
239
240                 [Test]
241                 public void OffsetOf_FieldName_Static ()
242                 {
243                         try {
244                                 Marshal.OffsetOf (typeof (Foo), "b");
245                                 Assert.Fail ("#1");
246                         } catch (ArgumentException ex) {
247                                 // Field passed in is not a marshaled member of
248                                 // the type '...MarshalTest+Foo'
249                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
250                                 Assert.IsNull (ex.InnerException, "#3");
251                                 Assert.IsNotNull (ex.Message, "#4");
252                                 Assert.AreEqual ("fieldName", ex.ParamName, "#5");
253                         }
254                 }
255 #if !MOBILE
256                 [Test]
257                 public void GetHINSTANCE ()
258                 {
259                         if (RunningOnMono)
260                                 Assert.Ignore ("GetHINSTANCE only applies to .NET on Windows.");
261
262                         Assembly a;
263                         IntPtr hinstance;
264                         StringBuilder fileName;
265
266                         fileName = new StringBuilder (255);
267                         a = Assembly.GetExecutingAssembly ();
268                         hinstance = Marshal.GetHINSTANCE (a.GetModules () [0]);
269                         Assert.IsTrue (GetModuleFileName (hinstance, fileName,
270                                 fileName.Capacity) > 0, "#A1");
271                         Assert.AreEqual (a.Location, fileName.ToString (), "#A2");
272
273                         fileName.Length = 0;
274                         a = typeof (int).Assembly;
275                         hinstance = Marshal.GetHINSTANCE (a.GetModules () [0]);
276                         Assert.IsTrue (GetModuleFileName (hinstance, fileName,
277                                 fileName.Capacity) > 0, "#B1");
278                         Assert.IsTrue (File.Exists (fileName.ToString ()), "#B3");
279                         Assert.AreEqual ("mscorlib.dll", Path.GetFileName (fileName.ToString ()), "#B4");
280                 }
281
282                 [Test]
283                 public void GetHINSTANCE_Module_Dynamic ()
284                 {
285                         AssemblyName aname = new AssemblyName ();
286                         aname.Name = "foo";
287
288                         AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (
289                                 aname, AssemblyBuilderAccess.Save,
290                                 Path.GetTempPath ());
291                         ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", false);
292
293                         IntPtr hinstance = Marshal.GetHINSTANCE (mb);
294                         Assert.AreEqual (-1, hinstance.ToInt32 ());
295                 }
296
297                 [Test]
298                 public void GetHINSTANCE_Module_Null ()
299                 {
300                         try {
301                                 Marshal.GetHINSTANCE ((Module) null);
302                                 Assert.Fail ("#1");
303                         } catch (ArgumentNullException ex) {
304                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
305                                 Assert.IsNull (ex.InnerException, "#3");
306                                 Assert.IsNotNull (ex.Message, "#4");
307                                 Assert.AreEqual ("m", ex.ParamName, "#5");
308                         }
309                 }
310 #endif
311
312                 [Test]
313                 public void GetHRForException ()
314                 {
315                         Assert.AreEqual (0, Marshal.GetHRForException (null));
316                         Assert.IsTrue (Marshal.GetHRForException (new Exception ()) < 0);
317                         Assert.AreEqual (12345, Marshal.GetHRForException (new IOException ("test message", 12345)));
318                 }
319
320                 [Test] // bug #319009
321                 public void StringToHGlobalUni ()
322                 {
323                         IntPtr handle = Marshal.StringToHGlobalUni ("unicode data");
324                         string s = Marshal.PtrToStringUni (handle);
325                         Assert.AreEqual (12, s.Length, "#1");
326
327                         handle = Marshal.StringToHGlobalUni ("unicode data string");
328                         s = Marshal.PtrToStringUni (handle);
329                         Assert.AreEqual (19, s.Length, "#2");
330                 }
331
332                 [Test]
333                 public void ReadIntByte ()
334                 {
335                         IntPtr ptr = Marshal.AllocHGlobal (4);
336                         try {
337                                 Marshal.WriteByte (ptr, 0, 0x1);
338                                 Marshal.WriteByte (ptr, 1, 0x2);
339                                 Assert.AreEqual (0x1, Marshal.ReadByte (ptr));
340                                 Assert.AreEqual (0x1, Marshal.ReadByte (ptr, 0));
341                                 Assert.AreEqual (0x2, Marshal.ReadByte (ptr, 1));
342                         } finally {
343                                 Marshal.FreeHGlobal (ptr);
344                         }
345                 }
346
347                 [Test]
348                 public void ReadInt16 ()
349                 {
350                         IntPtr ptr = Marshal.AllocHGlobal (64);
351                         try {
352                                 Marshal.WriteInt16 (ptr, 0, 0x1234);
353                                 Marshal.WriteInt16 (ptr, 2, 0x4567);
354                                 Marshal.WriteInt16 (ptr, 5, 0x4567);
355                                 Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr));
356                                 Assert.AreEqual (0x1234, Marshal.ReadInt16 (ptr, 0));
357                                 Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 2));
358                                 Assert.AreEqual (0x4567, Marshal.ReadInt16 ((ptr + 5)));
359                                 Assert.AreEqual (0x4567, Marshal.ReadInt16 (ptr, 5));
360                         } finally {
361                                 Marshal.FreeHGlobal (ptr);
362                         }
363                 }
364
365                 [Test]
366                 public void ReadInt32 ()
367                 {
368                         IntPtr ptr = Marshal.AllocHGlobal (64);
369                         try {
370                                 Marshal.WriteInt32 (ptr, 0, 0x12345678);
371                                 Marshal.WriteInt32 (ptr, 4, 0x77654321);
372                                 Marshal.WriteInt32 (ptr, 10, 0x77654321);
373                                 Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr));
374                                 Assert.AreEqual (0x12345678, Marshal.ReadInt32 (ptr, 0));
375                                 Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 4));
376                                 Assert.AreEqual (0x77654321, Marshal.ReadInt32 ((ptr + 10)));
377                                 Assert.AreEqual (0x77654321, Marshal.ReadInt32 (ptr, 10));
378                         } finally {
379                                 Marshal.FreeHGlobal (ptr);
380                         }
381                 }
382
383                 [Test]
384                 public void ReadInt32_Endian ()
385                 {
386                         IntPtr ptr = Marshal.AllocHGlobal (4);
387                         try {
388                                 Marshal.WriteByte (ptr, 0, 0x01);
389                                 Marshal.WriteByte (ptr, 1, 0x02);
390                                 Marshal.WriteByte (ptr, 2, 0x03);
391                                 Marshal.WriteByte (ptr, 3, 0x04);
392                                 // Marshal MUST use the native CPU data
393                                 if (BitConverter.IsLittleEndian){
394                                         Assert.AreEqual (0x04030201, Marshal.ReadInt32 (ptr), "ReadInt32");
395                                 } else {
396                                         Assert.AreEqual (0x01020304, Marshal.ReadInt32 (ptr), "ReadInt32");
397                                 }
398                         } finally {
399                                 Marshal.FreeHGlobal (ptr);
400                         }
401                 }
402
403                 [Test]
404                 public void ReadInt64 ()
405                 {
406                         IntPtr ptr = Marshal.AllocHGlobal (16);
407                         try {
408                                 Marshal.WriteInt64 (ptr, 0, 0x12345678ABCDEFL);
409                                 Marshal.WriteInt64 (ptr, 8, 0x87654321ABCDEFL);
410                                 Assert.AreEqual (0x12345678ABCDEFL, Marshal.ReadInt64 (ptr));
411                                 Assert.AreEqual (0x12345678ABCDEFL, Marshal.ReadInt64 (ptr, 0));
412                                 Assert.AreEqual (0x87654321ABCDEFL, Marshal.ReadInt64 (ptr, 8));
413                         } finally {
414                                 Marshal.FreeHGlobal (ptr);
415                         }
416                 }
417
418                 [Test]
419                 public void BSTR_Roundtrip ()
420                 {
421                         string s = "mono";
422                         IntPtr ptr = Marshal.StringToBSTR (s);
423                         string s2 = Marshal.PtrToStringBSTR (ptr);
424                         Assert.AreEqual (s, s2, "string");
425                 }
426
427                 [Test]
428                 public void StringToBSTRWithNullValues ()
429                 {
430                         int size = 128;
431                         string s = String.Empty.PadLeft (size, '\0');
432                         Assert.AreEqual (size, s.Length, "Length-1");
433
434                         IntPtr ptr = Marshal.StringToBSTR (s);
435                         try {
436                                 for (int i = 0; i < size; i += 4)
437                                         Marshal.WriteInt32 (ptr, i, 0);
438
439                                 string s2 = Marshal.PtrToStringBSTR (ptr);
440                                 Assert.AreEqual (128, s2.Length, "Length-2");
441                         } finally {
442                                 Marshal.FreeBSTR (ptr);
443                         }
444                 }
445
446                 [Test]
447                 public void StringToHGlobalAnsiWithNullValues ()
448                 {
449                         int size = 128;
450                         string s = String.Empty.PadLeft (size, '\0');
451                         Assert.AreEqual (size, s.Length, "Length-1");
452
453                         IntPtr ptr = Marshal.StringToHGlobalAnsi (s);
454                         try {
455                                 for (int i = 0; i < size; i += 4)
456                                         Marshal.WriteInt32 (ptr, i, 0);
457
458                                 string s2 = Marshal.PtrToStringAnsi (ptr);
459                                 Assert.AreEqual (0, s2.Length, "Length-2");
460                         } finally {
461                                 Marshal.FreeHGlobal (ptr);
462                         }
463                 }
464
465                 [Test]
466                 public void StringToHGlobalAutoWithNullValues ()
467                 {
468                         int size = 128;
469                         string s = String.Empty.PadLeft (size, '\0');
470                         Assert.AreEqual (size, s.Length, "Length-1");
471
472                         IntPtr ptr = Marshal.StringToHGlobalAuto (s);
473                         try {
474                                 for (int i = 0; i < size; i += 4)
475                                         Marshal.WriteInt32 (ptr, i, 0);
476
477                                 string s2 = Marshal.PtrToStringAuto (ptr);
478                                 Assert.AreEqual (0, s2.Length, "Length-2");
479                         } finally {
480                                 Marshal.FreeHGlobal (ptr);
481                         }
482                 }
483
484                 [Test]
485                 public void StringToHGlobalUniWithNullValues ()
486                 {
487                         int size = 128;
488                         string s = String.Empty.PadLeft (size, '\0');
489                         Assert.AreEqual (size, s.Length, "Length-1");
490
491                         IntPtr ptr = Marshal.StringToHGlobalUni (s);
492                         try {
493                                 for (int i = 0; i < size; i += 4)
494                                         Marshal.WriteInt32 (ptr, i, 0);
495
496                                 string s2 = Marshal.PtrToStringUni (ptr);
497                                 Assert.AreEqual (0, s2.Length, "Length-2");
498                         } finally {
499                                 Marshal.FreeHGlobal (ptr);
500                         }
501                 }
502
503                 [Test]
504                 public void StringToCoTaskMemAnsiWithNullValues ()
505                 {
506                         int size = 128;
507                         string s = String.Empty.PadLeft (size, '\0');
508                         Assert.AreEqual (size, s.Length, "Length-1");
509
510                         IntPtr ptr = Marshal.StringToCoTaskMemAnsi (s);
511                         try {
512                                 for (int i = 0; i < size; i += 4)
513                                         Marshal.WriteInt32 (ptr, i, 0);
514
515                                 string s2 = Marshal.PtrToStringAnsi (ptr);
516                                 Assert.AreEqual (0, s2.Length, "Length-2");
517                         } finally {
518                                 Marshal.FreeCoTaskMem (ptr);
519                         }
520                 }
521
522                 [Test]
523                 public void StringToCoTaskMemAutoWithNullValues ()
524                 {
525                         int size = 128;
526                         string s = String.Empty.PadLeft (size, '\0');
527                         Assert.AreEqual (size, s.Length, "Length-1");
528
529                         IntPtr ptr = Marshal.StringToCoTaskMemAuto (s);
530                         try {
531                                 for (int i = 0; i < size; i += 4)
532                                         Marshal.WriteInt32 (ptr, i, 0);
533
534                                 string s2 = Marshal.PtrToStringAuto (ptr);
535                                 Assert.AreEqual (0, s2.Length, "Length-2");
536                         } finally {
537                                 Marshal.FreeCoTaskMem (ptr);
538                         }
539                 }
540
541                 [Test]
542                 public void StringToCoTaskMemUniWithNullValues ()
543                 {
544                         int size = 128;
545                         string s = String.Empty.PadLeft (size, '\0');
546                         Assert.AreEqual (size, s.Length, "Length-1");
547
548                         IntPtr ptr = Marshal.StringToCoTaskMemUni (s);
549                         try {
550                                 for (int i = 0; i < size; i += 4)
551                                         Marshal.WriteInt32 (ptr, i, 0);
552
553                                 string s2 = Marshal.PtrToStringUni (ptr);
554                                 Assert.AreEqual (0, s2.Length, "Length-2");
555                         } finally {
556                                 Marshal.FreeCoTaskMem (ptr);
557                         }
558                 }
559                 private const string NotSupported = "Not supported before Windows 2000 Service Pack 3";
560                 private static char[] PlainText = new char[] { 'a', 'b', 'c' };
561                 private static byte[] AsciiPlainText = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c' };
562
563                 private unsafe SecureString GetSecureString ()
564                 {
565                         fixed (char* p = &PlainText[0]) {
566                                 return new SecureString (p, PlainText.Length);
567                         }
568                 }
569
570                 [Test]
571                 public void SecureStringToBSTR_Null ()
572                 {
573                         try {
574                                 Marshal.SecureStringToBSTR (null);
575                                 Assert.Fail ("#1");
576                         } catch (ArgumentNullException ex) {
577                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
578                                 Assert.IsNull (ex.InnerException, "#3");
579                                 Assert.IsNotNull (ex.Message, "#4");
580                                 Assert.AreEqual ("s", ex.ParamName, "#5");
581                         }
582                 }
583
584                 [Test]
585                 public void SecureStringToBSTR ()
586                 {
587                         try {
588                                 SecureString ss = GetSecureString ();
589                                 IntPtr p = Marshal.SecureStringToBSTR (ss);
590
591                                 char[] decrypted = new char[ss.Length];
592                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
593                                 Assert.AreEqual (PlainText, decrypted, "Decrypted");
594
595                                 Marshal.ZeroFreeBSTR (p);
596                         } catch (NotSupportedException) {
597                                 Assert.Ignore (NotSupported);
598                         }
599                 }
600
601                 [Test]
602                 public void SecureStringToCoTaskMemAnsi_Null ()
603                 {
604                         try {
605                                 Marshal.SecureStringToCoTaskMemAnsi (null);
606                                 Assert.Fail ("#1");
607                         } catch (ArgumentNullException ex) {
608                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
609                                 Assert.IsNull (ex.InnerException, "#3");
610                                 Assert.IsNotNull (ex.Message, "#4");
611                                 Assert.AreEqual ("s", ex.ParamName, "#5");
612                         }
613                 }
614
615                 [Test]
616                 public void SecureStringToCoTaskMemAnsi ()
617                 {
618                         try {
619                                 SecureString ss = GetSecureString ();
620                                 IntPtr p = Marshal.SecureStringToCoTaskMemAnsi (ss);
621
622                                 byte[] decrypted = new byte[ss.Length];
623                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
624                                 Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
625
626                                 Marshal.ZeroFreeCoTaskMemAnsi (p);
627                         } catch (NotSupportedException) {
628                                 Assert.Ignore (NotSupported);
629                         }
630                 }
631
632                 [Test]
633                 public void SecureStringToCoTaskMemUnicode_Null ()
634                 {
635                         try {
636                                 Marshal.SecureStringToCoTaskMemUnicode (null);
637                                 Assert.Fail ("#1");
638                         } catch (ArgumentNullException ex) {
639                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
640                                 Assert.IsNull (ex.InnerException, "#3");
641                                 Assert.IsNotNull (ex.Message, "#4");
642                                 Assert.AreEqual ("s", ex.ParamName, "#5");
643                         }
644                 }
645
646                 [Test]
647                 public void SecureStringToCoTaskMemUnicode ()
648                 {
649                         try {
650                                 SecureString ss = GetSecureString ();
651                                 IntPtr p = Marshal.SecureStringToCoTaskMemUnicode (ss);
652
653                                 char[] decrypted = new char[ss.Length];
654                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
655                                 Assert.AreEqual (PlainText, decrypted, "Decrypted");
656
657                                 Marshal.ZeroFreeCoTaskMemUnicode (p);
658                         } catch (NotSupportedException) {
659                                 Assert.Ignore (NotSupported);
660                         }
661                 }
662
663                 [Test]
664                 public void SecureStringToGlobalAllocAnsi_Null ()
665                 {
666                         try {
667                                 Marshal.SecureStringToGlobalAllocAnsi (null);
668                                 Assert.Fail ("#1");
669                         } catch (ArgumentNullException ex) {
670                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
671                                 Assert.IsNull (ex.InnerException, "#3");
672                                 Assert.IsNotNull (ex.Message, "#4");
673                                 Assert.AreEqual ("s", ex.ParamName, "#5");
674                         }
675                 }
676
677                 [Test]
678                 public void SecureStringToGlobalAllocAnsi ()
679                 {
680                         try {
681                                 SecureString ss = GetSecureString ();
682                                 IntPtr p = Marshal.SecureStringToGlobalAllocAnsi (ss);
683
684                                 byte[] decrypted = new byte[ss.Length];
685                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
686                                 Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
687
688                                 Marshal.ZeroFreeGlobalAllocAnsi (p);
689                         } catch (NotSupportedException) {
690                                 Assert.Ignore (NotSupported);
691                         }
692                 }
693
694                 [Test]
695                 public void SecureStringToGlobalAllocUnicode_Null ()
696                 {
697                         try {
698                                 Marshal.SecureStringToGlobalAllocUnicode (null);
699                                 Assert.Fail ("#1");
700                         } catch (ArgumentNullException ex) {
701                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
702                                 Assert.IsNull (ex.InnerException, "#3");
703                                 Assert.IsNotNull (ex.Message, "#4");
704                                 Assert.AreEqual ("s", ex.ParamName, "#5");
705                         }
706                 }
707
708                 [Test]
709                 public void SecureStringToGlobalAllocUnicode ()
710                 {
711                         try {
712                                 SecureString ss = GetSecureString ();
713                                 IntPtr p = Marshal.SecureStringToGlobalAllocUnicode (ss);
714
715                                 char[] decrypted = new char[ss.Length];
716                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
717                                 Assert.AreEqual (PlainText, decrypted, "Decrypted");
718
719                                 Marshal.ZeroFreeGlobalAllocUnicode (p);
720                         } catch (NotSupportedException) {
721                                 Assert.Ignore (NotSupported);
722                         }
723                 }
724
725 #if !MOBILE
726                 [Test]
727                 public void TestGetComSlotForMethodInfo ()
728                 {
729                         Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDefault).GetMethod("DoNothing")));
730                         Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDual).GetMethod("DoNothing")));
731                         Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo (typeof(ITestDefault).GetMethod ("DoNothing")));
732                         Assert.AreEqual (3, Marshal.GetComSlotForMethodInfo (typeof(ITestUnknown).GetMethod ("DoNothing")));
733
734                         for (int i = 0; i < 10; i++)
735                                 Assert.AreEqual (7+i, Marshal.GetComSlotForMethodInfo(typeof(ITestInterface).GetMethod ("Method"+i.ToString())));
736                 }
737
738                 [Test]
739                 public void TestGetComSlotForMethod_Method_Null ()
740                 {
741                         try {
742                                 Marshal.GetComSlotForMethodInfo (null);
743                                 Assert.Fail ("#1");
744                         } catch (ArgumentNullException ex) {
745                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
746                                 Assert.IsNull (ex.InnerException, "#3");
747                                 Assert.IsNotNull (ex.Message, "#4");
748                                 Assert.AreEqual ("m", ex.ParamName, "#5");
749                         }
750                 }
751
752                 [Test]
753                 public void TestGetComSlotForMethodInfo_Method_NotOnInterface ()
754                 {
755                         MethodInfo m = typeof(TestCoClass).GetMethod ("DoNothing");
756                         try {
757                                 Marshal.GetComSlotForMethodInfo (m);
758                                 Assert.Fail ("#1");
759                         } catch (ArgumentException ex) {
760                                 // The MemberInfo must be an interface method
761                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
762                                 Assert.IsNull (ex.InnerException, "#3");
763                                 Assert.IsNotNull (ex.Message, "#4");
764                                 Assert.AreEqual ("m", ex.ParamName, "#5");
765                         }
766                 }
767 #endif
768                 [Test]
769                 public void TestPtrToStringAuto ()
770                 {
771                         string input = Guid.NewGuid ().ToString ();
772                         string output;
773                         string output2;
774                         int len = 4;
775                         IntPtr ptr;
776
777                         if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
778                                 // Auto -> Uni
779                                 ptr = Marshal.StringToHGlobalAuto (input);
780                                 output = Marshal.PtrToStringUni (ptr);
781                                 output2 = Marshal.PtrToStringUni (ptr, len);
782                         } else {
783                                 // Auto -> Ansi
784                                 ptr = Marshal.StringToHGlobalAuto (input);
785                                 output = Marshal.PtrToStringAnsi (ptr);
786                                 output2 = Marshal.PtrToStringAnsi (ptr, len);
787                         }
788
789                         try {
790                                 Assert.AreEqual (input, output, "#1");
791                                 Assert.AreEqual (input.Substring (0, len), output2, "#2");
792                         } finally {
793                                 Marshal.FreeHGlobal (ptr);
794                         }
795                 }
796 #if !MOBILE
797                 [Test]
798                 public void TestGenerateProgIdForType()
799                 {
800                         string output;
801                         
802                         output = Marshal.GenerateProgIdForType(typeof(TestCoClass));
803                         Assert.AreEqual ("MonoTests.System.Runtime.InteropServices.TestCoClass", output, "#1");
804                         
805                         output = Marshal.GenerateProgIdForType(typeof(TestCoClassWithProgId));
806                         Assert.AreEqual ("CoClassWithProgId", output, "#2");
807                 }
808 #endif
809                 [Test]
810                 public void TestGlobalAlloc ()
811                 {
812                         IntPtr mem = Marshal.AllocHGlobal (100);
813                         mem = Marshal.ReAllocHGlobal (mem, (IntPtr) 1000000);
814                         Marshal.FreeHGlobal (mem);
815                 }
816                 
817                 [Test]
818                 public void FreeHGlobal ()
819                 {
820                         // clear user doubts on assistly #6749
821                         for (int i = 0; i < 1024; i++) {
822                                 IntPtr p = Marshal.AllocHGlobal (1024 * 1024);
823                                 Assert.AreNotEqual (IntPtr.Zero, p, i.ToString ());
824                                 Marshal.FreeHGlobal (p);
825                         }
826                 }
827
828                 [StructLayout (LayoutKind.Sequential)]
829                 public struct SimpleStruct2 {
830                         public int a;
831                         public int b;
832                 }
833
834                 [Test]
835                 public void PtrToStructureNull ()
836                 {
837                         Assert.IsNull (Marshal.PtrToStructure (IntPtr.Zero, typeof (SimpleStruct2)));
838                 }
839                 
840                 [Test]
841                 public void TestGetExceptionForHR ()
842                 {
843                         const int E_OUTOFMEMORY = unchecked ((int) 0x8007000E);
844                         const int E_INVALIDARG = unchecked ((int) 0X80070057);
845                         
846                         Exception ex = Marshal.GetExceptionForHR (E_OUTOFMEMORY);
847                         Assert.AreEqual (typeof (OutOfMemoryException), ex.GetType (), "E_OUTOFMEMORY");
848                         
849                         ex = Marshal.GetExceptionForHR (E_INVALIDARG);
850                         Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "E_INVALIDARG");
851                 }
852                 bool RunningOnMono {
853                         get {
854                                 return (Type.GetType ("System.MonoType", false) != null);
855                         }
856                 }
857
858 #if !MOBILE
859                 [DllImport ("kernel32.dll", SetLastError = true)]
860                 [PreserveSig]
861                 static extern uint GetModuleFileName (
862                         [In]
863                         IntPtr hModule,
864                         [Out]
865                         StringBuilder lpFilename,
866                         [In]
867                         [MarshalAs (UnmanagedType.U4)]
868                         int nSize
869                 );
870 #endif
871
872 #if !FULL_AOT_RUNTIME
873                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
874                 public class FourByteStruct
875                 {
876                         public UInt16 value1;
877                         public UInt16 value2;
878                 }
879
880                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
881                 public class ByteArrayFourByteStruct : FourByteStruct
882                 {
883                         [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
884                         public byte[] array;
885                 }
886
887                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
888                 public class SingleByteStruct
889                 {
890                         public byte value1;
891                 }
892
893                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
894                 public class ByteArraySingleByteStruct : SingleByteStruct
895                 {
896                         [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
897                         public byte[] array1;
898                         public byte value2;
899                 }
900
901                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
902                 public class ByteArraySingleByteChildStruct : ByteArraySingleByteStruct
903                 {
904                         [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
905                         public byte[] array2;
906                 }
907
908                 [Test]
909                 public void CheckByteArrayFourByteStruct()
910                 {
911                         ByteArrayFourByteStruct myStruct = new ByteArrayFourByteStruct
912                         { value1 = 42, value2 = 53, array = Encoding.UTF8.GetBytes( "Hello" ) };
913
914                         byte[] buffer = Serialize (myStruct);
915
916                         UInt16 value1 = BitConverter.ToUInt16 (buffer, 0);
917                         UInt16 value2 = BitConverter.ToUInt16 (buffer, 2);
918                         string array = Encoding.UTF8.GetString (buffer, 4, 5);
919
920                         Assert.AreEqual((UInt16)42, value1);
921                         Assert.AreEqual((UInt16)53, value2);
922                         Assert.AreEqual ("Hello", array);
923                 }
924
925                 [Test]
926                 public void CheckByteArraySingleByteChildStruct()
927                 {
928                         ByteArraySingleByteChildStruct myStruct = new ByteArraySingleByteChildStruct
929                         { value1 = 42, array1 = Encoding.UTF8.GetBytes( "Hello" ), value2 = 53,  array2 = Encoding.UTF8.GetBytes( "World" ) };
930
931                         byte[] array = Serialize (myStruct);
932
933                         byte value1 = array [0];
934                         string array1 = Encoding.UTF8.GetString (array, 1, 5);
935                         byte value2 = array [6];
936                         string array2 = Encoding.UTF8.GetString (array, 7, 5);
937
938                         Assert.AreEqual((byte)42, value1);
939                         Assert.AreEqual ("Hello", array1);
940                         Assert.AreEqual((byte)53, value2);
941                         Assert.AreEqual ("World", array2);
942                 }
943
944                 [StructLayout(LayoutKind.Sequential, Pack = 1)]
945                 public struct FiveByteStruct
946                 {
947                         public uint uIntField;
948                         public byte byteField;
949                 };
950
951                 [StructLayout(LayoutKind.Sequential, Pack = 1)]
952                 public class Base
953                 {
954                         public ushort firstUShortField;
955                         public ushort secondUShortField;
956                 }
957
958                 [StructLayout(LayoutKind.Sequential, Pack = 1)]
959                 public class Derived : Base
960                 {
961                         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
962                         public FiveByteStruct[] arrayField;
963                 }
964
965                 [Test]
966                 public void CheckPtrToStructureWithFixedArrayAndBaseClassFields()
967                 {
968                         const int arraySize = 6;
969                         var derived = new Derived
970                         {
971                                 arrayField = new FiveByteStruct[arraySize],
972                                 firstUShortField = 42,
973                                 secondUShortField = 43
974                         };
975
976                         for (var i = 0; i < arraySize; ++i)
977                         {
978                                 derived.arrayField[i].byteField = (byte)i;
979                                 derived.arrayField[i].uIntField = (uint)i * 10;
980                         }
981
982                         var array = Serialize(derived);
983                         var deserializedDerived = Deserialize<Derived>(array);
984
985                         Assert.AreEqual(derived.firstUShortField, deserializedDerived.firstUShortField, "The firstUShortField differs, which is not expected.");
986                         Assert.AreEqual(derived.secondUShortField, deserializedDerived.secondUShortField, "The secondUShortField differs, which is not expected.");
987
988                         for (var i = 0; i < arraySize; ++i)
989                         {
990                                 Assert.AreEqual(derived.arrayField[i].byteField, deserializedDerived.arrayField[i].byteField, string.Format("The byteField at index {0} differs, which is not expected.", i));
991                                 Assert.AreEqual(derived.arrayField[i].uIntField, deserializedDerived.arrayField[i].uIntField, string.Format("The uIntField at index {0} differs, which is not expected.", i));
992                         }
993                 }
994
995                 public static byte[] Serialize( object obj )
996                 {
997                         int nTypeSize = Marshal.SizeOf( obj );
998                         byte[] arrBuffer = new byte[nTypeSize];
999
1000                         GCHandle hGCHandle = GCHandle.Alloc( arrBuffer, GCHandleType.Pinned );
1001                         IntPtr pBuffer = hGCHandle.AddrOfPinnedObject();
1002                         Marshal.StructureToPtr( obj, pBuffer, false );
1003                         hGCHandle.Free();
1004
1005                         return arrBuffer;
1006                 }
1007
1008                 public static T Deserialize<T>(byte[] buffer)
1009                 {
1010                         var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
1011                         var pBuffer = handle.AddrOfPinnedObject();
1012                         var objResult = (T)Marshal.PtrToStructure(pBuffer, typeof(T));
1013                         handle.Free();
1014
1015                         return objResult;
1016                 }
1017 #endif
1018         }
1019 #if !MOBILE
1020         [ComImport()]
1021         [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1022         interface ITestDefault
1023         {
1024                 void DoNothing ();
1025         }
1026
1027         [ComImport()]
1028         [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1029         [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
1030         interface ITestDispatch
1031         {
1032                 void DoNothing ();
1033         }
1034
1035         [ComImport()]
1036         [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1037         [InterfaceType(ComInterfaceType.InterfaceIsDual)]
1038         interface ITestDual
1039         {
1040                 void DoNothing ();
1041         }
1042
1043         [ComImport()]
1044         [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1045         [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
1046         interface ITestUnknown
1047         {
1048                 void DoNothing ();
1049         }
1050
1051         [ComImport()]
1052         [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1053         interface ITestInterface
1054         {
1055                 void Method0 ();
1056                 void Method1 ();
1057                 void Method2 ();
1058                 void Method3 ();
1059                 void Method4 ();
1060                 void Method5 ();
1061                 void Method6 ();
1062                 void Method7 ();
1063                 void Method8 ();
1064                 void Method9 ();
1065         }
1066
1067         public class TestCoClass : ITestDispatch
1068         {
1069                 public void DoNothing ()
1070                 {
1071                 }
1072         }
1073
1074         [ProgId("CoClassWithProgId")]
1075         public class TestCoClassWithProgId : ITestDispatch
1076         {
1077                 public void DoNothing ()
1078                 {
1079                 }
1080         }
1081 #endif
1082 }