Merge pull request #3442 from lateralusX/jlorenss/win-atexit-commands
[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                 [Category ("MobileNotWorking")]
420                 public void BSTR_Roundtrip ()
421                 {
422                         string s = "mono";
423                         IntPtr ptr = Marshal.StringToBSTR (s);
424                         string s2 = Marshal.PtrToStringBSTR (ptr);
425                         Assert.AreEqual (s, s2, "string");
426                 }
427
428                 [Test]
429                 [Category ("MobileNotWorking")]
430                 public void StringToBSTRWithNullValues ()
431                 {
432                         int size = 128;
433                         string s = String.Empty.PadLeft (size, '\0');
434                         Assert.AreEqual (size, s.Length, "Length-1");
435
436                         IntPtr ptr = Marshal.StringToBSTR (s);
437                         try {
438                                 for (int i = 0; i < size; i += 4)
439                                         Marshal.WriteInt32 (ptr, i, 0);
440
441                                 string s2 = Marshal.PtrToStringBSTR (ptr);
442                                 Assert.AreEqual (128, s2.Length, "Length-2");
443                         } finally {
444                                 Marshal.FreeBSTR (ptr);
445                         }
446                 }
447
448                 [Test]
449                 public void StringToHGlobalAnsiWithNullValues ()
450                 {
451                         int size = 128;
452                         string s = String.Empty.PadLeft (size, '\0');
453                         Assert.AreEqual (size, s.Length, "Length-1");
454
455                         IntPtr ptr = Marshal.StringToHGlobalAnsi (s);
456                         try {
457                                 for (int i = 0; i < size; i += 4)
458                                         Marshal.WriteInt32 (ptr, i, 0);
459
460                                 string s2 = Marshal.PtrToStringAnsi (ptr);
461                                 Assert.AreEqual (0, s2.Length, "Length-2");
462                         } finally {
463                                 Marshal.FreeHGlobal (ptr);
464                         }
465                 }
466
467                 [Test]
468                 public void StringToHGlobalAutoWithNullValues ()
469                 {
470                         int size = 128;
471                         string s = String.Empty.PadLeft (size, '\0');
472                         Assert.AreEqual (size, s.Length, "Length-1");
473
474                         IntPtr ptr = Marshal.StringToHGlobalAuto (s);
475                         try {
476                                 for (int i = 0; i < size; i += 4)
477                                         Marshal.WriteInt32 (ptr, i, 0);
478
479                                 string s2 = Marshal.PtrToStringAuto (ptr);
480                                 Assert.AreEqual (0, s2.Length, "Length-2");
481                         } finally {
482                                 Marshal.FreeHGlobal (ptr);
483                         }
484                 }
485
486                 [Test]
487                 public void StringToHGlobalUniWithNullValues ()
488                 {
489                         int size = 128;
490                         string s = String.Empty.PadLeft (size, '\0');
491                         Assert.AreEqual (size, s.Length, "Length-1");
492
493                         IntPtr ptr = Marshal.StringToHGlobalUni (s);
494                         try {
495                                 for (int i = 0; i < size; i += 4)
496                                         Marshal.WriteInt32 (ptr, i, 0);
497
498                                 string s2 = Marshal.PtrToStringUni (ptr);
499                                 Assert.AreEqual (0, s2.Length, "Length-2");
500                         } finally {
501                                 Marshal.FreeHGlobal (ptr);
502                         }
503                 }
504
505                 [Test]
506                 public void StringToCoTaskMemAnsiWithNullValues ()
507                 {
508                         int size = 128;
509                         string s = String.Empty.PadLeft (size, '\0');
510                         Assert.AreEqual (size, s.Length, "Length-1");
511
512                         IntPtr ptr = Marshal.StringToCoTaskMemAnsi (s);
513                         try {
514                                 for (int i = 0; i < size; i += 4)
515                                         Marshal.WriteInt32 (ptr, i, 0);
516
517                                 string s2 = Marshal.PtrToStringAnsi (ptr);
518                                 Assert.AreEqual (0, s2.Length, "Length-2");
519                         } finally {
520                                 Marshal.FreeCoTaskMem (ptr);
521                         }
522                 }
523
524                 [Test]
525                 public void StringToCoTaskMemAutoWithNullValues ()
526                 {
527                         int size = 128;
528                         string s = String.Empty.PadLeft (size, '\0');
529                         Assert.AreEqual (size, s.Length, "Length-1");
530
531                         IntPtr ptr = Marshal.StringToCoTaskMemAuto (s);
532                         try {
533                                 for (int i = 0; i < size; i += 4)
534                                         Marshal.WriteInt32 (ptr, i, 0);
535
536                                 string s2 = Marshal.PtrToStringAuto (ptr);
537                                 Assert.AreEqual (0, s2.Length, "Length-2");
538                         } finally {
539                                 Marshal.FreeCoTaskMem (ptr);
540                         }
541                 }
542
543                 [Test]
544                 public void StringToCoTaskMemUniWithNullValues ()
545                 {
546                         int size = 128;
547                         string s = String.Empty.PadLeft (size, '\0');
548                         Assert.AreEqual (size, s.Length, "Length-1");
549
550                         IntPtr ptr = Marshal.StringToCoTaskMemUni (s);
551                         try {
552                                 for (int i = 0; i < size; i += 4)
553                                         Marshal.WriteInt32 (ptr, i, 0);
554
555                                 string s2 = Marshal.PtrToStringUni (ptr);
556                                 Assert.AreEqual (0, s2.Length, "Length-2");
557                         } finally {
558                                 Marshal.FreeCoTaskMem (ptr);
559                         }
560                 }
561                 private const string NotSupported = "Not supported before Windows 2000 Service Pack 3";
562                 private static char[] PlainText = new char[] { 'a', 'b', 'c' };
563                 private static byte[] AsciiPlainText = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c' };
564
565                 private unsafe SecureString GetSecureString ()
566                 {
567                         fixed (char* p = &PlainText[0]) {
568                                 return new SecureString (p, PlainText.Length);
569                         }
570                 }
571
572                 [Test]
573                 public void SecureStringToBSTR_Null ()
574                 {
575                         try {
576                                 Marshal.SecureStringToBSTR (null);
577                                 Assert.Fail ("#1");
578                         } catch (ArgumentNullException ex) {
579                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
580                                 Assert.IsNull (ex.InnerException, "#3");
581                                 Assert.IsNotNull (ex.Message, "#4");
582                                 Assert.AreEqual ("s", ex.ParamName, "#5");
583                         }
584                 }
585
586                 [Test]
587                 public void SecureStringToBSTR ()
588                 {
589                         try {
590                                 SecureString ss = GetSecureString ();
591                                 IntPtr p = Marshal.SecureStringToBSTR (ss);
592
593                                 char[] decrypted = new char[ss.Length];
594                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
595                                 Assert.AreEqual (PlainText, decrypted, "Decrypted");
596
597                                 Marshal.ZeroFreeBSTR (p);
598                         } catch (NotSupportedException) {
599                                 Assert.Ignore (NotSupported);
600                         }
601                 }
602
603                 [Test]
604                 public void SecureStringToCoTaskMemAnsi_Null ()
605                 {
606                         try {
607                                 Marshal.SecureStringToCoTaskMemAnsi (null);
608                                 Assert.Fail ("#1");
609                         } catch (ArgumentNullException ex) {
610                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
611                                 Assert.IsNull (ex.InnerException, "#3");
612                                 Assert.IsNotNull (ex.Message, "#4");
613                                 Assert.AreEqual ("s", ex.ParamName, "#5");
614                         }
615                 }
616
617                 [Test]
618                 public void SecureStringToCoTaskMemAnsi ()
619                 {
620                         try {
621                                 SecureString ss = GetSecureString ();
622                                 IntPtr p = Marshal.SecureStringToCoTaskMemAnsi (ss);
623
624                                 byte[] decrypted = new byte[ss.Length];
625                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
626                                 Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
627
628                                 Marshal.ZeroFreeCoTaskMemAnsi (p);
629                         } catch (NotSupportedException) {
630                                 Assert.Ignore (NotSupported);
631                         }
632                 }
633
634                 [Test]
635                 public void SecureStringToCoTaskMemUnicode_Null ()
636                 {
637                         try {
638                                 Marshal.SecureStringToCoTaskMemUnicode (null);
639                                 Assert.Fail ("#1");
640                         } catch (ArgumentNullException ex) {
641                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
642                                 Assert.IsNull (ex.InnerException, "#3");
643                                 Assert.IsNotNull (ex.Message, "#4");
644                                 Assert.AreEqual ("s", ex.ParamName, "#5");
645                         }
646                 }
647
648                 [Test]
649                 public void SecureStringToCoTaskMemUnicode ()
650                 {
651                         try {
652                                 SecureString ss = GetSecureString ();
653                                 IntPtr p = Marshal.SecureStringToCoTaskMemUnicode (ss);
654
655                                 char[] decrypted = new char[ss.Length];
656                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
657                                 Assert.AreEqual (PlainText, decrypted, "Decrypted");
658
659                                 Marshal.ZeroFreeCoTaskMemUnicode (p);
660                         } catch (NotSupportedException) {
661                                 Assert.Ignore (NotSupported);
662                         }
663                 }
664
665                 [Test]
666                 public void SecureStringToGlobalAllocAnsi_Null ()
667                 {
668                         try {
669                                 Marshal.SecureStringToGlobalAllocAnsi (null);
670                                 Assert.Fail ("#1");
671                         } catch (ArgumentNullException ex) {
672                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
673                                 Assert.IsNull (ex.InnerException, "#3");
674                                 Assert.IsNotNull (ex.Message, "#4");
675                                 Assert.AreEqual ("s", ex.ParamName, "#5");
676                         }
677                 }
678
679                 [Test]
680                 public void SecureStringToGlobalAllocAnsi ()
681                 {
682                         try {
683                                 SecureString ss = GetSecureString ();
684                                 IntPtr p = Marshal.SecureStringToGlobalAllocAnsi (ss);
685
686                                 byte[] decrypted = new byte[ss.Length];
687                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
688                                 Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
689
690                                 Marshal.ZeroFreeGlobalAllocAnsi (p);
691                         } catch (NotSupportedException) {
692                                 Assert.Ignore (NotSupported);
693                         }
694                 }
695
696                 [Test]
697                 public void SecureStringToGlobalAllocUnicode_Null ()
698                 {
699                         try {
700                                 Marshal.SecureStringToGlobalAllocUnicode (null);
701                                 Assert.Fail ("#1");
702                         } catch (ArgumentNullException ex) {
703                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
704                                 Assert.IsNull (ex.InnerException, "#3");
705                                 Assert.IsNotNull (ex.Message, "#4");
706                                 Assert.AreEqual ("s", ex.ParamName, "#5");
707                         }
708                 }
709
710                 [Test]
711                 public void SecureStringToGlobalAllocUnicode ()
712                 {
713                         try {
714                                 SecureString ss = GetSecureString ();
715                                 IntPtr p = Marshal.SecureStringToGlobalAllocUnicode (ss);
716
717                                 char[] decrypted = new char[ss.Length];
718                                 Marshal.Copy (p, decrypted, 0, decrypted.Length);
719                                 Assert.AreEqual (PlainText, decrypted, "Decrypted");
720
721                                 Marshal.ZeroFreeGlobalAllocUnicode (p);
722                         } catch (NotSupportedException) {
723                                 Assert.Ignore (NotSupported);
724                         }
725                 }
726
727 #if !MOBILE
728                 [Test]
729                 public void TestGetComSlotForMethodInfo ()
730                 {
731                         Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDefault).GetMethod("DoNothing")));
732                         Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDual).GetMethod("DoNothing")));
733                         Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo (typeof(ITestDefault).GetMethod ("DoNothing")));
734                         Assert.AreEqual (3, Marshal.GetComSlotForMethodInfo (typeof(ITestUnknown).GetMethod ("DoNothing")));
735
736                         for (int i = 0; i < 10; i++)
737                                 Assert.AreEqual (7+i, Marshal.GetComSlotForMethodInfo(typeof(ITestInterface).GetMethod ("Method"+i.ToString())));
738                 }
739
740                 [Test]
741                 public void TestGetComSlotForMethod_Method_Null ()
742                 {
743                         try {
744                                 Marshal.GetComSlotForMethodInfo (null);
745                                 Assert.Fail ("#1");
746                         } catch (ArgumentNullException ex) {
747                                 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
748                                 Assert.IsNull (ex.InnerException, "#3");
749                                 Assert.IsNotNull (ex.Message, "#4");
750                                 Assert.AreEqual ("m", ex.ParamName, "#5");
751                         }
752                 }
753
754                 [Test]
755                 public void TestGetComSlotForMethodInfo_Method_NotOnInterface ()
756                 {
757                         MethodInfo m = typeof(TestCoClass).GetMethod ("DoNothing");
758                         try {
759                                 Marshal.GetComSlotForMethodInfo (m);
760                                 Assert.Fail ("#1");
761                         } catch (ArgumentException ex) {
762                                 // The MemberInfo must be an interface method
763                                 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
764                                 Assert.IsNull (ex.InnerException, "#3");
765                                 Assert.IsNotNull (ex.Message, "#4");
766                                 Assert.AreEqual ("m", ex.ParamName, "#5");
767                         }
768                 }
769 #endif
770                 [Test]
771                 public void TestPtrToStringAuto ()
772                 {
773                         string input = Guid.NewGuid ().ToString ();
774                         string output;
775                         string output2;
776                         int len = 4;
777                         IntPtr ptr;
778
779                         if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
780                                 // Auto -> Uni
781                                 ptr = Marshal.StringToHGlobalAuto (input);
782                                 output = Marshal.PtrToStringUni (ptr);
783                                 output2 = Marshal.PtrToStringUni (ptr, len);
784                         } else {
785                                 // Auto -> Ansi
786                                 ptr = Marshal.StringToHGlobalAuto (input);
787                                 output = Marshal.PtrToStringAnsi (ptr);
788                                 output2 = Marshal.PtrToStringAnsi (ptr, len);
789                         }
790
791                         try {
792                                 Assert.AreEqual (input, output, "#1");
793                                 Assert.AreEqual (input.Substring (0, len), output2, "#2");
794                         } finally {
795                                 Marshal.FreeHGlobal (ptr);
796                         }
797                 }
798 #if !MOBILE
799                 [Test]
800                 public void TestGenerateProgIdForType()
801                 {
802                         string output;
803                         
804                         output = Marshal.GenerateProgIdForType(typeof(TestCoClass));
805                         Assert.AreEqual ("MonoTests.System.Runtime.InteropServices.TestCoClass", output, "#1");
806                         
807                         output = Marshal.GenerateProgIdForType(typeof(TestCoClassWithProgId));
808                         Assert.AreEqual ("CoClassWithProgId", output, "#2");
809                 }
810 #endif
811                 [Test]
812                 public void TestGlobalAlloc ()
813                 {
814                         IntPtr mem = Marshal.AllocHGlobal (100);
815                         mem = Marshal.ReAllocHGlobal (mem, (IntPtr) 1000000);
816                         Marshal.FreeHGlobal (mem);
817                 }
818                 
819                 [Test]
820                 public void FreeHGlobal ()
821                 {
822                         // clear user doubts on assistly #6749
823                         for (int i = 0; i < 1024; i++) {
824                                 IntPtr p = Marshal.AllocHGlobal (1024 * 1024);
825                                 Assert.AreNotEqual (IntPtr.Zero, p, i.ToString ());
826                                 Marshal.FreeHGlobal (p);
827                         }
828                 }
829
830                 [StructLayout (LayoutKind.Sequential)]
831                 public struct SimpleStruct2 {
832                         public int a;
833                         public int b;
834                 }
835
836                 [Test]
837                 public void PtrToStructureNull ()
838                 {
839                         Assert.IsNull (Marshal.PtrToStructure (IntPtr.Zero, typeof (SimpleStruct2)));
840                 }
841                 
842                 [Test]
843                 public void TestGetExceptionForHR ()
844                 {
845                         const int E_OUTOFMEMORY = unchecked ((int) 0x8007000E);
846                         const int E_INVALIDARG = unchecked ((int) 0X80070057);
847                         
848                         Exception ex = Marshal.GetExceptionForHR (E_OUTOFMEMORY);
849                         Assert.AreEqual (typeof (OutOfMemoryException), ex.GetType (), "E_OUTOFMEMORY");
850                         
851                         ex = Marshal.GetExceptionForHR (E_INVALIDARG);
852                         Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "E_INVALIDARG");
853                 }
854                 bool RunningOnMono {
855                         get {
856                                 return (Type.GetType ("System.MonoType", false) != null);
857                         }
858                 }
859
860 #if !MOBILE
861                 [DllImport ("kernel32.dll", SetLastError = true)]
862                 [PreserveSig]
863                 static extern uint GetModuleFileName (
864                         [In]
865                         IntPtr hModule,
866                         [Out]
867                         StringBuilder lpFilename,
868                         [In]
869                         [MarshalAs (UnmanagedType.U4)]
870                         int nSize
871                 );
872 #endif
873
874                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
875                 public class FourByteStruct
876                 {
877                         public UInt16 value1;
878                         public UInt16 value2;
879                 }
880
881                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
882                 public class ByteArrayFourByteStruct : FourByteStruct
883                 {
884                         [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
885                         public byte[] array;
886                 }
887
888                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
889                 public class SingleByteStruct
890                 {
891                         public byte value1;
892                 }
893
894                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
895                 public class ByteArraySingleByteStruct : SingleByteStruct
896                 {
897                         [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
898                         public byte[] array1;
899                         public byte value2;
900                 }
901
902                 [StructLayout( LayoutKind.Sequential, Pack = 1 )]
903                 public class ByteArraySingleByteChildStruct : ByteArraySingleByteStruct
904                 {
905                         [MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
906                         public byte[] array2;
907                 }
908
909                 [Test]
910                 public void CheckByteArrayFourByteStruct()
911                 {
912                         ByteArrayFourByteStruct myStruct = new ByteArrayFourByteStruct
913                         { value1 = 42, value2 = 53, array = Encoding.UTF8.GetBytes( "Hello" ) };
914
915                         byte[] buffer = Serialize (myStruct);
916
917                         UInt16 value1 = BitConverter.ToUInt16 (buffer, 0);
918                         UInt16 value2 = BitConverter.ToUInt16 (buffer, 2);
919                         string array = Encoding.UTF8.GetString (buffer, 4, 5);
920
921                         Assert.AreEqual((UInt16)42, value1);
922                         Assert.AreEqual((UInt16)53, value2);
923                         Assert.AreEqual ("Hello", array);
924                 }
925
926                 [Test]
927                 public void CheckByteArraySingleByteChildStruct()
928                 {
929                         ByteArraySingleByteChildStruct myStruct = new ByteArraySingleByteChildStruct
930                         { value1 = 42, array1 = Encoding.UTF8.GetBytes( "Hello" ), value2 = 53,  array2 = Encoding.UTF8.GetBytes( "World" ) };
931
932                         byte[] array = Serialize (myStruct);
933
934                         byte value1 = array [0];
935                         string array1 = Encoding.UTF8.GetString (array, 1, 5);
936                         byte value2 = array [6];
937                         string array2 = Encoding.UTF8.GetString (array, 7, 5);
938
939                         Assert.AreEqual((byte)42, value1);
940                         Assert.AreEqual ("Hello", array1);
941                         Assert.AreEqual((byte)53, value2);
942                         Assert.AreEqual ("World", array2);
943                 }
944
945                 [StructLayout(LayoutKind.Sequential, Pack = 1)]
946                 public struct FiveByteStruct
947                 {
948                         public uint uIntField;
949                         public byte byteField;
950                 };
951
952                 [StructLayout(LayoutKind.Sequential, Pack = 1)]
953                 public class Base
954                 {
955                         public ushort firstUShortField;
956                         public ushort secondUShortField;
957                 }
958
959                 [StructLayout(LayoutKind.Sequential, Pack = 1)]
960                 public class Derived : Base
961                 {
962                         [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
963                         public FiveByteStruct[] arrayField;
964                 }
965
966                 [Test]
967                 public void CheckPtrToStructureWithFixedArrayAndBaseClassFields()
968                 {
969                         const int arraySize = 6;
970                         var derived = new Derived
971                         {
972                                 arrayField = new FiveByteStruct[arraySize],
973                                 firstUShortField = 42,
974                                 secondUShortField = 43
975                         };
976
977                         for (var i = 0; i < arraySize; ++i)
978                         {
979                                 derived.arrayField[i].byteField = (byte)i;
980                                 derived.arrayField[i].uIntField = (uint)i * 10;
981                         }
982
983                         var array = Serialize(derived);
984                         var deserializedDerived = Deserialize<Derived>(array);
985
986                         Assert.AreEqual(derived.firstUShortField, deserializedDerived.firstUShortField, "The firstUShortField differs, which is not expected.");
987                         Assert.AreEqual(derived.secondUShortField, deserializedDerived.secondUShortField, "The secondUShortField differs, which is not expected.");
988
989                         for (var i = 0; i < arraySize; ++i)
990                         {
991                                 Assert.AreEqual(derived.arrayField[i].byteField, deserializedDerived.arrayField[i].byteField, string.Format("The byteField at index {0} differs, which is not expected.", i));
992                                 Assert.AreEqual(derived.arrayField[i].uIntField, deserializedDerived.arrayField[i].uIntField, string.Format("The uIntField at index {0} differs, which is not expected.", i));
993                         }
994                 }
995
996                 public static byte[] Serialize( object obj )
997                 {
998                         int nTypeSize = Marshal.SizeOf( obj );
999                         byte[] arrBuffer = new byte[nTypeSize];
1000
1001                         GCHandle hGCHandle = GCHandle.Alloc( arrBuffer, GCHandleType.Pinned );
1002                         IntPtr pBuffer = hGCHandle.AddrOfPinnedObject();
1003                         Marshal.StructureToPtr( obj, pBuffer, false );
1004                         hGCHandle.Free();
1005
1006                         return arrBuffer;
1007                 }
1008
1009                 public static T Deserialize<T>(byte[] buffer)
1010                 {
1011                         var handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
1012                         var pBuffer = handle.AddrOfPinnedObject();
1013                         var objResult = (T)Marshal.PtrToStructure(pBuffer, typeof(T));
1014                         handle.Free();
1015
1016                         return objResult;
1017                 }
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 }