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]
SizeOf_Class_LayoutSequential()55 		public void SizeOf_Class_LayoutSequential ()
56 		{
57 			Marshal.SizeOf (typeof (ClsSequential));
58 		}
59 
60 		[Test]
SizeOf_Class_LayoutNotSet()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]
SizeOf_Class_LayoutExplicit()77 		public void SizeOf_Class_LayoutExplicit ()
78 		{
79 			Marshal.SizeOf (typeof (ClsExplicit));
80 		}
81 
82 		[Test]
SizeOf_Struct_LayoutSequential()83 		public void SizeOf_Struct_LayoutSequential ()
84 		{
85 			Marshal.SizeOf (typeof (StrSequential));
86 		}
87 
88 		[Test]
SizeOf_Struct_LayoutNotSet()89 		public void SizeOf_Struct_LayoutNotSet ()
90 		{
91 			Marshal.SizeOf (typeof (StrNoLayout));
92 		}
93 
94 		[Test]
SizeOf_Struct_LayoutExplicit()95 		public void SizeOf_Struct_LayoutExplicit ()
96 		{
97 			Marshal.SizeOf (typeof (StrExplicit));
98 		}
99 
100 		[Test]
SizeOf_Array()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]
Sizeof_Pointer()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]
PtrToStringWithNull()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]
PtrToStringAnsi_Ptr_Zero()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]
PtrToStringWithUni_Ptr_Zero()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]
PtrToStringUTF8_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]
UnsafeAddrOfPinnedArrayElement()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]
AllocHGlobalZeroSize()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]
AllocCoTaskMemZeroSize()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]
OffsetOf_FieldName_Static()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]
GetHINSTANCE()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]
GetHINSTANCE_Module_Dynamic()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]
GetHINSTANCE_Module_Null()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]
GetHRForException()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
StringToHGlobalUni()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]
ReadIntByte()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]
ReadInt16()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]
ReadInt32()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]
ReadInt32_Endian()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]
ReadInt64()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]
BSTR_Roundtrip()419 		public void BSTR_Roundtrip ()
420 		{
421 			string s = "mono";
422 			IntPtr ptr = Marshal.StringToBSTR (s);
423 			string s2 = Marshal.PtrToStringBSTR (ptr);
424 			Assert.AreEqual (s, s2, "string");
425 		}
426 
427 		[Test]
StringToBSTRWithNullValues()428 		public void StringToBSTRWithNullValues ()
429 		{
430 			int size = 128;
431 			string s = String.Empty.PadLeft (size, '\0');
432 			Assert.AreEqual (size, s.Length, "Length-1");
433 
434 			IntPtr ptr = Marshal.StringToBSTR (s);
435 			try {
436 				for (int i = 0; i < size; i += 4)
437 					Marshal.WriteInt32 (ptr, i, 0);
438 
439 				string s2 = Marshal.PtrToStringBSTR (ptr);
440 				Assert.AreEqual (128, s2.Length, "Length-2");
441 			} finally {
442 				Marshal.FreeBSTR (ptr);
443 			}
444 		}
445 
446 		[Test]
StringToHGlobalAnsiWithNullValues()447 		public void StringToHGlobalAnsiWithNullValues ()
448 		{
449 			int size = 128;
450 			string s = String.Empty.PadLeft (size, '\0');
451 			Assert.AreEqual (size, s.Length, "Length-1");
452 
453 			IntPtr ptr = Marshal.StringToHGlobalAnsi (s);
454 			try {
455 				for (int i = 0; i < size; i += 4)
456 					Marshal.WriteInt32 (ptr, i, 0);
457 
458 				string s2 = Marshal.PtrToStringAnsi (ptr);
459 				Assert.AreEqual (0, s2.Length, "Length-2");
460 			} finally {
461 				Marshal.FreeHGlobal (ptr);
462 			}
463 		}
464 
465 		[Test]
StringToHGlobalAutoWithNullValues()466 		public void StringToHGlobalAutoWithNullValues ()
467 		{
468 			int size = 128;
469 			string s = String.Empty.PadLeft (size, '\0');
470 			Assert.AreEqual (size, s.Length, "Length-1");
471 
472 			IntPtr ptr = Marshal.StringToHGlobalAuto (s);
473 			try {
474 				for (int i = 0; i < size; i += 4)
475 					Marshal.WriteInt32 (ptr, i, 0);
476 
477 				string s2 = Marshal.PtrToStringAuto (ptr);
478 				Assert.AreEqual (0, s2.Length, "Length-2");
479 			} finally {
480 				Marshal.FreeHGlobal (ptr);
481 			}
482 		}
483 
484 		[Test]
StringToHGlobalUniWithNullValues()485 		public void StringToHGlobalUniWithNullValues ()
486 		{
487 			int size = 128;
488 			string s = String.Empty.PadLeft (size, '\0');
489 			Assert.AreEqual (size, s.Length, "Length-1");
490 
491 			IntPtr ptr = Marshal.StringToHGlobalUni (s);
492 			try {
493 				for (int i = 0; i < size; i += 4)
494 					Marshal.WriteInt32 (ptr, i, 0);
495 
496 				string s2 = Marshal.PtrToStringUni (ptr);
497 				Assert.AreEqual (0, s2.Length, "Length-2");
498 			} finally {
499 				Marshal.FreeHGlobal (ptr);
500 			}
501 		}
502 
503 		[Test]
StringToCoTaskMemAnsiWithNullValues()504 		public void StringToCoTaskMemAnsiWithNullValues ()
505 		{
506 			int size = 128;
507 			string s = String.Empty.PadLeft (size, '\0');
508 			Assert.AreEqual (size, s.Length, "Length-1");
509 
510 			IntPtr ptr = Marshal.StringToCoTaskMemAnsi (s);
511 			try {
512 				for (int i = 0; i < size; i += 4)
513 					Marshal.WriteInt32 (ptr, i, 0);
514 
515 				string s2 = Marshal.PtrToStringAnsi (ptr);
516 				Assert.AreEqual (0, s2.Length, "Length-2");
517 			} finally {
518 				Marshal.FreeCoTaskMem (ptr);
519 			}
520 		}
521 
522 		[Test]
StringToCoTaskMemAutoWithNullValues()523 		public void StringToCoTaskMemAutoWithNullValues ()
524 		{
525 			int size = 128;
526 			string s = String.Empty.PadLeft (size, '\0');
527 			Assert.AreEqual (size, s.Length, "Length-1");
528 
529 			IntPtr ptr = Marshal.StringToCoTaskMemAuto (s);
530 			try {
531 				for (int i = 0; i < size; i += 4)
532 					Marshal.WriteInt32 (ptr, i, 0);
533 
534 				string s2 = Marshal.PtrToStringAuto (ptr);
535 				Assert.AreEqual (0, s2.Length, "Length-2");
536 			} finally {
537 				Marshal.FreeCoTaskMem (ptr);
538 			}
539 		}
540 
541 		[Test]
StringToCoTaskMemUniWithNullValues()542 		public void StringToCoTaskMemUniWithNullValues ()
543 		{
544 			int size = 128;
545 			string s = String.Empty.PadLeft (size, '\0');
546 			Assert.AreEqual (size, s.Length, "Length-1");
547 
548 			IntPtr ptr = Marshal.StringToCoTaskMemUni (s);
549 			try {
550 				for (int i = 0; i < size; i += 4)
551 					Marshal.WriteInt32 (ptr, i, 0);
552 
553 				string s2 = Marshal.PtrToStringUni (ptr);
554 				Assert.AreEqual (0, s2.Length, "Length-2");
555 			} finally {
556 				Marshal.FreeCoTaskMem (ptr);
557 			}
558 		}
559 		private const string NotSupported = "Not supported before Windows 2000 Service Pack 3";
560 		private static char[] PlainText = new char[] { 'a', 'b', 'c' };
561 		private static byte[] AsciiPlainText = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c' };
562 
GetSecureString()563 		private unsafe SecureString GetSecureString ()
564 		{
565 			fixed (char* p = &PlainText[0]) {
566 				return new SecureString (p, PlainText.Length);
567 			}
568 		}
569 
570 		[Test]
SecureStringToBSTR_Null()571 		public void SecureStringToBSTR_Null ()
572 		{
573 			try {
574 				Marshal.SecureStringToBSTR (null);
575 				Assert.Fail ("#1");
576 			} catch (ArgumentNullException ex) {
577 				Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
578 				Assert.IsNull (ex.InnerException, "#3");
579 				Assert.IsNotNull (ex.Message, "#4");
580 				Assert.AreEqual ("s", ex.ParamName, "#5");
581 			}
582 		}
583 
584 		[Test]
SecureStringToBSTR()585 		public void SecureStringToBSTR ()
586 		{
587 			try {
588 				SecureString ss = GetSecureString ();
589 				IntPtr p = Marshal.SecureStringToBSTR (ss);
590 
591 				char[] decrypted = new char[ss.Length];
592 				Marshal.Copy (p, decrypted, 0, decrypted.Length);
593 				Assert.AreEqual (PlainText, decrypted, "Decrypted");
594 
595 				Marshal.ZeroFreeBSTR (p);
596 			} catch (NotSupportedException) {
597 				Assert.Ignore (NotSupported);
598 			}
599 		}
600 
601 		[Test]
SecureStringToCoTaskMemAnsi_Null()602 		public void SecureStringToCoTaskMemAnsi_Null ()
603 		{
604 			try {
605 				Marshal.SecureStringToCoTaskMemAnsi (null);
606 				Assert.Fail ("#1");
607 			} catch (ArgumentNullException ex) {
608 				Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
609 				Assert.IsNull (ex.InnerException, "#3");
610 				Assert.IsNotNull (ex.Message, "#4");
611 				Assert.AreEqual ("s", ex.ParamName, "#5");
612 			}
613 		}
614 
615 		[Test]
SecureStringToCoTaskMemAnsi()616 		public void SecureStringToCoTaskMemAnsi ()
617 		{
618 			try {
619 				SecureString ss = GetSecureString ();
620 				IntPtr p = Marshal.SecureStringToCoTaskMemAnsi (ss);
621 
622 				byte[] decrypted = new byte[ss.Length];
623 				Marshal.Copy (p, decrypted, 0, decrypted.Length);
624 				Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
625 
626 				Marshal.ZeroFreeCoTaskMemAnsi (p);
627 			} catch (NotSupportedException) {
628 				Assert.Ignore (NotSupported);
629 			}
630 		}
631 
632 		[Test]
SecureStringToCoTaskMemUnicode_Null()633 		public void SecureStringToCoTaskMemUnicode_Null ()
634 		{
635 			try {
636 				Marshal.SecureStringToCoTaskMemUnicode (null);
637 				Assert.Fail ("#1");
638 			} catch (ArgumentNullException ex) {
639 				Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
640 				Assert.IsNull (ex.InnerException, "#3");
641 				Assert.IsNotNull (ex.Message, "#4");
642 				Assert.AreEqual ("s", ex.ParamName, "#5");
643 			}
644 		}
645 
646 		[Test]
SecureStringToCoTaskMemUnicode()647 		public void SecureStringToCoTaskMemUnicode ()
648 		{
649 			try {
650 				SecureString ss = GetSecureString ();
651 				IntPtr p = Marshal.SecureStringToCoTaskMemUnicode (ss);
652 
653 				char[] decrypted = new char[ss.Length];
654 				Marshal.Copy (p, decrypted, 0, decrypted.Length);
655 				Assert.AreEqual (PlainText, decrypted, "Decrypted");
656 
657 				Marshal.ZeroFreeCoTaskMemUnicode (p);
658 			} catch (NotSupportedException) {
659 				Assert.Ignore (NotSupported);
660 			}
661 		}
662 
663 		[Test]
SecureStringToGlobalAllocAnsi_Null()664 		public void SecureStringToGlobalAllocAnsi_Null ()
665 		{
666 			try {
667 				Marshal.SecureStringToGlobalAllocAnsi (null);
668 				Assert.Fail ("#1");
669 			} catch (ArgumentNullException ex) {
670 				Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
671 				Assert.IsNull (ex.InnerException, "#3");
672 				Assert.IsNotNull (ex.Message, "#4");
673 				Assert.AreEqual ("s", ex.ParamName, "#5");
674 			}
675 		}
676 
677 		[Test]
SecureStringToGlobalAllocAnsi()678 		public void SecureStringToGlobalAllocAnsi ()
679 		{
680 			try {
681 				SecureString ss = GetSecureString ();
682 				IntPtr p = Marshal.SecureStringToGlobalAllocAnsi (ss);
683 
684 				byte[] decrypted = new byte[ss.Length];
685 				Marshal.Copy (p, decrypted, 0, decrypted.Length);
686 				Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
687 
688 				Marshal.ZeroFreeGlobalAllocAnsi (p);
689 			} catch (NotSupportedException) {
690 				Assert.Ignore (NotSupported);
691 			}
692 		}
693 
694 		[Test]
SecureStringToGlobalAllocUnicode_Null()695 		public void SecureStringToGlobalAllocUnicode_Null ()
696 		{
697 			try {
698 				Marshal.SecureStringToGlobalAllocUnicode (null);
699 				Assert.Fail ("#1");
700 			} catch (ArgumentNullException ex) {
701 				Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
702 				Assert.IsNull (ex.InnerException, "#3");
703 				Assert.IsNotNull (ex.Message, "#4");
704 				Assert.AreEqual ("s", ex.ParamName, "#5");
705 			}
706 		}
707 
708 		[Test]
SecureStringToGlobalAllocUnicode()709 		public void SecureStringToGlobalAllocUnicode ()
710 		{
711 			try {
712 				SecureString ss = GetSecureString ();
713 				IntPtr p = Marshal.SecureStringToGlobalAllocUnicode (ss);
714 
715 				char[] decrypted = new char[ss.Length];
716 				Marshal.Copy (p, decrypted, 0, decrypted.Length);
717 				Assert.AreEqual (PlainText, decrypted, "Decrypted");
718 
719 				Marshal.ZeroFreeGlobalAllocUnicode (p);
720 			} catch (NotSupportedException) {
721 				Assert.Ignore (NotSupported);
722 			}
723 		}
724 
725 #if !MOBILE
726 		[Test]
TestGetComSlotForMethodInfo()727 		public void TestGetComSlotForMethodInfo ()
728 		{
729 			Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDefault).GetMethod("DoNothing")));
730 			Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDual).GetMethod("DoNothing")));
731 			Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo (typeof(ITestDefault).GetMethod ("DoNothing")));
732 			Assert.AreEqual (3, Marshal.GetComSlotForMethodInfo (typeof(ITestUnknown).GetMethod ("DoNothing")));
733 
734 			for (int i = 0; i < 10; i++)
735 				Assert.AreEqual (7+i, Marshal.GetComSlotForMethodInfo(typeof(ITestInterface).GetMethod ("Method"+i.ToString())));
736 		}
737 
738 		[Test]
TestGetComSlotForMethod_Method_Null()739 		public void TestGetComSlotForMethod_Method_Null ()
740 		{
741 			try {
742 				Marshal.GetComSlotForMethodInfo (null);
743 				Assert.Fail ("#1");
744 			} catch (ArgumentNullException ex) {
745 				Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
746 				Assert.IsNull (ex.InnerException, "#3");
747 				Assert.IsNotNull (ex.Message, "#4");
748 				Assert.AreEqual ("m", ex.ParamName, "#5");
749 			}
750 		}
751 
752 		[Test]
TestGetComSlotForMethodInfo_Method_NotOnInterface()753 		public void TestGetComSlotForMethodInfo_Method_NotOnInterface ()
754 		{
755 			MethodInfo m = typeof(TestCoClass).GetMethod ("DoNothing");
756 			try {
757 				Marshal.GetComSlotForMethodInfo (m);
758 				Assert.Fail ("#1");
759 			} catch (ArgumentException ex) {
760 				// The MemberInfo must be an interface method
761 				Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
762 				Assert.IsNull (ex.InnerException, "#3");
763 				Assert.IsNotNull (ex.Message, "#4");
764 				Assert.AreEqual ("m", ex.ParamName, "#5");
765 			}
766 		}
767 #endif
768 		[Test]
TestPtrToStringAuto()769 		public void TestPtrToStringAuto ()
770 		{
771 			string input = Guid.NewGuid ().ToString ();
772 			string output;
773 			string output2;
774 			int len = 4;
775 			IntPtr ptr;
776 
777 			if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
778 				// Auto -> Uni
779 				ptr = Marshal.StringToHGlobalAuto (input);
780 				output = Marshal.PtrToStringUni (ptr);
781 				output2 = Marshal.PtrToStringUni (ptr, len);
782 			} else {
783 				// Auto -> Ansi
784 				ptr = Marshal.StringToHGlobalAuto (input);
785 				output = Marshal.PtrToStringAnsi (ptr);
786 				output2 = Marshal.PtrToStringAnsi (ptr, len);
787 			}
788 
789 			try {
790 				Assert.AreEqual (input, output, "#1");
791 				Assert.AreEqual (input.Substring (0, len), output2, "#2");
792 			} finally {
793 				Marshal.FreeHGlobal (ptr);
794 			}
795 		}
796 #if !MOBILE
797 		[Test]
TestGenerateProgIdForType()798 		public void TestGenerateProgIdForType()
799 		{
800 			string output;
801 
802 			output = Marshal.GenerateProgIdForType(typeof(TestCoClass));
803 			Assert.AreEqual ("MonoTests.System.Runtime.InteropServices.TestCoClass", output, "#1");
804 
805 			output = Marshal.GenerateProgIdForType(typeof(TestCoClassWithProgId));
806 			Assert.AreEqual ("CoClassWithProgId", output, "#2");
807 		}
808 #endif
809 		[Test]
TestGlobalAlloc()810 		public void TestGlobalAlloc ()
811 		{
812 			IntPtr mem = Marshal.AllocHGlobal (100);
813 			mem = Marshal.ReAllocHGlobal (mem, (IntPtr) 1000000);
814 			Marshal.FreeHGlobal (mem);
815 		}
816 
817 		[Test]
FreeHGlobal()818 		public void FreeHGlobal ()
819 		{
820 			// clear user doubts on assistly #6749
821 			for (int i = 0; i < 1024; i++) {
822 				IntPtr p = Marshal.AllocHGlobal (1024 * 1024);
823 				Assert.AreNotEqual (IntPtr.Zero, p, i.ToString ());
824 				Marshal.FreeHGlobal (p);
825 			}
826 		}
827 
828 		[StructLayout (LayoutKind.Sequential)]
829 		public struct SimpleStruct2 {
830 			public int a;
831 			public int b;
832 		}
833 
834 		[Test]
PtrToStructureNull()835 		public void PtrToStructureNull ()
836 		{
837 			Assert.IsNull (Marshal.PtrToStructure (IntPtr.Zero, typeof (SimpleStruct2)));
838 		}
839 
840 		[Test]
TestGetExceptionForHR()841 		public void TestGetExceptionForHR ()
842 		{
843 			const int E_OUTOFMEMORY = unchecked ((int) 0x8007000E);
844 			const int E_INVALIDARG = unchecked ((int) 0X80070057);
845 
846 			Exception ex = Marshal.GetExceptionForHR (E_OUTOFMEMORY);
847 			Assert.AreEqual (typeof (OutOfMemoryException), ex.GetType (), "E_OUTOFMEMORY");
848 
849 			ex = Marshal.GetExceptionForHR (E_INVALIDARG);
850 			Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "E_INVALIDARG");
851 		}
852 		bool RunningOnMono {
853 			get {
854 				return (Type.GetType ("System.MonoType", false) != null);
855 			}
856 		}
857 
858 #if !MOBILE
859 		[DllImport ("kernel32.dll", SetLastError = true)]
860 		[PreserveSig]
GetModuleFileName( [In] IntPtr hModule, [Out] StringBuilder lpFilename, [In] [MarshalAs (UnmanagedType.U4)] int nSize )861 		static extern uint GetModuleFileName (
862 			[In]
863 			IntPtr hModule,
864 			[Out]
865 			StringBuilder lpFilename,
866 			[In]
867 			[MarshalAs (UnmanagedType.U4)]
868 			int nSize
869 		);
870 #endif
871 
872 #if !FULL_AOT_RUNTIME
873 		[StructLayout( LayoutKind.Sequential, Pack = 1 )]
874 		public class FourByteStruct
875 		{
876 			public UInt16 value1;
877 			public UInt16 value2;
878 		}
879 
880 		[StructLayout( LayoutKind.Sequential, Pack = 1 )]
881 		public class ByteArrayFourByteStruct : FourByteStruct
882 		{
883 			[MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
884 			public byte[] array;
885 		}
886 
887 		[StructLayout( LayoutKind.Sequential, Pack = 1 )]
888 		public class SingleByteStruct
889 		{
890 			public byte value1;
891 		}
892 
893 		[StructLayout( LayoutKind.Sequential, Pack = 1 )]
894 		public class ByteArraySingleByteStruct : SingleByteStruct
895 		{
896 			[MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
897 			public byte[] array1;
898 			public byte value2;
899 		}
900 
901 		[StructLayout( LayoutKind.Sequential, Pack = 1 )]
902 		public class ByteArraySingleByteChildStruct : ByteArraySingleByteStruct
903 		{
904 			[MarshalAs( UnmanagedType.ByValArray, SizeConst = 5 )]
905 			public byte[] array2;
906 		}
907 
908 		[Test]
CheckByteArrayFourByteStruct()909 		public void CheckByteArrayFourByteStruct()
910 		{
911 			ByteArrayFourByteStruct myStruct = new ByteArrayFourByteStruct
912 			{ value1 = 42, value2 = 53, array = Encoding.UTF8.GetBytes( "Hello" ) };
913 
914 			byte[] buffer = Serialize (myStruct);
915 
916 			UInt16 value1 = BitConverter.ToUInt16 (buffer, 0);
917 			UInt16 value2 = BitConverter.ToUInt16 (buffer, 2);
918 			string array = Encoding.UTF8.GetString (buffer, 4, 5);
919 
920 			Assert.AreEqual((UInt16)42, value1);
921 			Assert.AreEqual((UInt16)53, value2);
922 			Assert.AreEqual ("Hello", array);
923 		}
924 
925 		[Test]
CheckByteArraySingleByteChildStruct()926 		public void CheckByteArraySingleByteChildStruct()
927 		{
928 			ByteArraySingleByteChildStruct myStruct = new ByteArraySingleByteChildStruct
929 			{ value1 = 42, array1 = Encoding.UTF8.GetBytes( "Hello" ), value2 = 53,  array2 = Encoding.UTF8.GetBytes( "World" ) };
930 
931 			byte[] array = Serialize (myStruct);
932 
933 			byte value1 = array [0];
934 			string array1 = Encoding.UTF8.GetString (array, 1, 5);
935 			byte value2 = array [6];
936 			string array2 = Encoding.UTF8.GetString (array, 7, 5);
937 
938 			Assert.AreEqual((byte)42, value1);
939 			Assert.AreEqual ("Hello", array1);
940 			Assert.AreEqual((byte)53, value2);
941 			Assert.AreEqual ("World", array2);
942 		}
943 
944 		[StructLayout(LayoutKind.Sequential, Pack = 1)]
945 		public struct FiveByteStruct
946 		{
947 			public uint uIntField;
948 			public byte byteField;
949 		};
950 
951 		[StructLayout(LayoutKind.Sequential, Pack = 1)]
952 		public class Base
953 		{
954 			public ushort firstUShortField;
955 			public ushort secondUShortField;
956 		}
957 
958 		[StructLayout(LayoutKind.Sequential, Pack = 1)]
959 		public class Derived : Base
960 		{
961 			[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
962 			public FiveByteStruct[] arrayField;
963 		}
964 
965 		[Test]
966 		[Category ("InterpreterNotWorking")]
CheckPtrToStructureWithFixedArrayAndBaseClassFields()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 
Serialize( object obj )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 
Deserialize(byte[] buffer)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 #endif
1019 	}
1020 #if !MOBILE
1021 	[ComImport()]
1022 	[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1023 	interface ITestDefault
1024 	{
DoNothing()1025 		void DoNothing ();
1026 	}
1027 
1028 	[ComImport()]
1029 	[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1030 	[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
1031 	interface ITestDispatch
1032 	{
DoNothing()1033 		void DoNothing ();
1034 	}
1035 
1036 	[ComImport()]
1037 	[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1038 	[InterfaceType(ComInterfaceType.InterfaceIsDual)]
1039 	interface ITestDual
1040 	{
DoNothing()1041 		void DoNothing ();
1042 	}
1043 
1044 	[ComImport()]
1045 	[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1046 	[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
1047 	interface ITestUnknown
1048 	{
DoNothing()1049 		void DoNothing ();
1050 	}
1051 
1052 	[ComImport()]
1053 	[Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
1054 	interface ITestInterface
1055 	{
Method0()1056 		void Method0 ();
Method1()1057 		void Method1 ();
Method2()1058 		void Method2 ();
Method3()1059 		void Method3 ();
Method4()1060 		void Method4 ();
Method5()1061 		void Method5 ();
Method6()1062 		void Method6 ();
Method7()1063 		void Method7 ();
Method8()1064 		void Method8 ();
Method9()1065 		void Method9 ();
1066 	}
1067 
1068 	public class TestCoClass : ITestDispatch
1069 	{
DoNothing()1070 		public void DoNothing ()
1071 		{
1072 		}
1073 	}
1074 
1075 	[ProgId("CoClassWithProgId")]
1076 	public class TestCoClassWithProgId : ITestDispatch
1077 	{
DoNothing()1078 		public void DoNothing ()
1079 		{
1080 		}
1081 	}
1082 #endif
1083 }
1084