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