2 // System.Runtime.InteropServices.Marshal Test Cases
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 // Sebastien Pouliot <sebastien@ximian.com>
8 // Copyright (C) 2004-2007 Novell, Inc (http://www.novell.com)
11 using NUnit.Framework;
14 using System.Reflection;
15 using System.Reflection.Emit;
16 using System.Runtime.InteropServices;
17 using System.Security;
20 namespace MonoTests.System.Runtime.InteropServices
23 public class MarshalTest
25 [StructLayout (LayoutKind.Sequential)]
34 [StructLayout (LayoutKind.Explicit)]
36 [FieldOffset (0)] public int field;
39 [StructLayout (LayoutKind.Sequential)]
40 struct StrSequential {
48 [StructLayout (LayoutKind.Explicit)]
50 [FieldOffset (0)] public int field;
54 public void SizeOf_Class_LayoutSequential ()
56 Marshal.SizeOf (typeof (ClsSequential));
60 public void SizeOf_Class_LayoutNotSet ()
63 Marshal.SizeOf (typeof (ClsNoLayout));
65 } catch (ArgumentException ex) {
66 // Type '...MarshalTest+ClsNoLayout' cannot be
67 // marshaled as an unmanaged structure; no
68 // meaningful size or offset can be computed
69 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
70 Assert.IsNull (ex.InnerException, "#3");
71 Assert.IsNotNull (ex.Message, "#4");
76 public void SizeOf_Class_LayoutExplicit ()
78 Marshal.SizeOf (typeof (ClsExplicit));
82 public void SizeOf_Struct_LayoutSequential ()
84 Marshal.SizeOf (typeof (StrSequential));
88 public void SizeOf_Struct_LayoutNotSet ()
90 Marshal.SizeOf (typeof (StrNoLayout));
94 public void SizeOf_Struct_LayoutExplicit ()
96 Marshal.SizeOf (typeof (StrExplicit));
100 public void SizeOf_Array ()
103 Marshal.SizeOf (typeof (string []));
105 } catch (ArgumentException ex) {
106 // Type 'System.String[]' cannot be marshaled
107 // as an unmanaged structure; no meaningful
108 // size or offset can be computed
109 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
110 Assert.IsNull (ex.InnerException, "#3");
111 Assert.IsNotNull (ex.Message, "#4");
116 public void PtrToStringWithNull ()
118 Assert.IsNull (Marshal.PtrToStringAnsi (IntPtr.Zero), "A");
119 Assert.IsNull (Marshal.PtrToStringUni (IntPtr.Zero), "C");
123 public void PtrToStringAnsi_Ptr_Zero ()
126 Marshal.PtrToStringAnsi (IntPtr.Zero, 0);
128 } catch (ArgumentNullException ex) {
129 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
130 Assert.IsNull (ex.InnerException, "#3");
131 Assert.IsNotNull (ex.Message, "#4");
132 Assert.AreEqual ("ptr", ex.ParamName, "#5");
137 public void PtrToStringWithUni_Ptr_Zero ()
140 Marshal.PtrToStringUni (IntPtr.Zero, 0);
142 } catch (ArgumentNullException ex) {
143 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
144 Assert.IsNull (ex.InnerException, "#3");
145 Assert.IsNotNull (ex.Message, "#4");
146 Assert.AreEqual ("ptr", ex.ParamName, "#5");
151 public unsafe void UnsafeAddrOfPinnedArrayElement ()
153 short[] sarr = new short [5];
156 IntPtr ptr = Marshal.UnsafeAddrOfPinnedArrayElement (sarr, 2);
157 Assert.AreEqual (3, *(short*) ptr.ToPointer ());
161 public void AllocHGlobalZeroSize ()
163 IntPtr ptr = Marshal.AllocHGlobal (0);
164 Assert.IsTrue (ptr != IntPtr.Zero);
165 Marshal.FreeHGlobal (ptr);
177 public void OffsetOf_FieldName_Static ()
180 Marshal.OffsetOf (typeof (Foo), "b");
182 } catch (ArgumentException ex) {
183 // Field passed in is not a marshaled member of
184 // the type '...MarshalTest+Foo'
185 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
186 Assert.IsNull (ex.InnerException, "#3");
187 Assert.IsNotNull (ex.Message, "#4");
188 Assert.AreEqual ("fieldName", ex.ParamName, "#5");
193 public void GetHINSTANCE ()
196 Assert.Ignore ("GetHINSTANCE only applies to Windows.");
200 StringBuilder fileName;
202 fileName = new StringBuilder (255);
203 a = Assembly.GetExecutingAssembly ();
204 hinstance = Marshal.GetHINSTANCE (a.GetModules () [0]);
205 Assert.IsTrue (GetModuleFileName (hinstance, fileName,
206 fileName.Capacity) > 0, "#A1");
207 Assert.AreEqual (a.Location, fileName.ToString (), "#A2");
210 a = typeof (int).Assembly;
211 hinstance = Marshal.GetHINSTANCE (a.GetModules () [0]);
212 Assert.IsTrue (GetModuleFileName (hinstance, fileName,
213 fileName.Capacity) > 0, "#B1");
214 Assert.IsTrue (File.Exists (fileName.ToString ()), "#B3");
215 Assert.AreEqual ("mscorlib.dll", Path.GetFileName (fileName.ToString ()), "#B4");
219 public void GetHINSTANCE_Module_Dynamic ()
221 AssemblyName aname = new AssemblyName ();
224 AssemblyBuilder ab = AppDomain.CurrentDomain.DefineDynamicAssembly (
225 aname, AssemblyBuilderAccess.Save,
226 Path.GetTempPath ());
227 ModuleBuilder mb = ab.DefineDynamicModule ("foo.dll", false);
229 IntPtr hinstance = Marshal.GetHINSTANCE (mb);
230 Assert.AreEqual (-1, hinstance.ToInt32 ());
234 public void GetHINSTANCE_Module_Null ()
237 Marshal.GetHINSTANCE ((Module) null);
239 } catch (ArgumentNullException ex) {
240 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
241 Assert.IsNull (ex.InnerException, "#3");
242 Assert.IsNotNull (ex.Message, "#4");
243 Assert.AreEqual ("m", ex.ParamName, "#5");
247 [Test] // bug #319009
248 public void StringToHGlobalUni ()
250 IntPtr handle = Marshal.StringToHGlobalUni ("unicode data");
251 string s = Marshal.PtrToStringUni (handle);
252 Assert.AreEqual (12, s.Length, "#1");
254 handle = Marshal.StringToHGlobalUni ("unicode data string");
255 s = Marshal.PtrToStringUni (handle);
256 Assert.AreEqual (19, s.Length, "#2");
260 public void ReadInt32_Endian ()
262 IntPtr ptr = Marshal.AllocHGlobal (4);
264 Marshal.WriteByte (ptr, 0, 0x01);
265 Marshal.WriteByte (ptr, 1, 0x02);
266 Marshal.WriteByte (ptr, 2, 0x03);
267 Marshal.WriteByte (ptr, 3, 0x04);
268 // Marshal MUST use the native CPU data
269 if (BitConverter.IsLittleEndian){
270 Assert.AreEqual (0x04030201, Marshal.ReadInt32 (ptr), "ReadInt32");
272 Assert.AreEqual (0x01020304, Marshal.ReadInt32 (ptr), "ReadInt32");
275 Marshal.FreeHGlobal (ptr);
280 public void BSTR_Roundtrip ()
283 IntPtr ptr = Marshal.StringToBSTR (s);
284 string s2 = Marshal.PtrToStringBSTR (ptr);
285 Assert.AreEqual (s, s2, "string");
289 public void StringToBSTRWithNullValues ()
292 string s = String.Empty.PadLeft (size, '\0');
293 Assert.AreEqual (size, s.Length, "Length-1");
295 IntPtr ptr = Marshal.StringToBSTR (s);
297 for (int i = 0; i < size; i += 4)
298 Marshal.WriteInt32 (ptr, i, 0);
300 string s2 = Marshal.PtrToStringBSTR (ptr);
301 Assert.AreEqual (128, s2.Length, "Length-2");
303 Marshal.FreeBSTR (ptr);
308 public void StringToHGlobalAnsiWithNullValues ()
311 string s = String.Empty.PadLeft (size, '\0');
312 Assert.AreEqual (size, s.Length, "Length-1");
314 IntPtr ptr = Marshal.StringToHGlobalAnsi (s);
316 for (int i = 0; i < size; i += 4)
317 Marshal.WriteInt32 (ptr, i, 0);
319 string s2 = Marshal.PtrToStringAnsi (ptr);
320 Assert.AreEqual (0, s2.Length, "Length-2");
322 Marshal.FreeHGlobal (ptr);
327 public void StringToHGlobalAutoWithNullValues ()
330 string s = String.Empty.PadLeft (size, '\0');
331 Assert.AreEqual (size, s.Length, "Length-1");
333 IntPtr ptr = Marshal.StringToHGlobalAuto (s);
335 for (int i = 0; i < size; i += 4)
336 Marshal.WriteInt32 (ptr, i, 0);
338 string s2 = Marshal.PtrToStringAuto (ptr);
339 Assert.AreEqual (0, s2.Length, "Length-2");
341 Marshal.FreeHGlobal (ptr);
346 public void StringToHGlobalUniWithNullValues ()
349 string s = String.Empty.PadLeft (size, '\0');
350 Assert.AreEqual (size, s.Length, "Length-1");
352 IntPtr ptr = Marshal.StringToHGlobalUni (s);
354 for (int i = 0; i < size; i += 4)
355 Marshal.WriteInt32 (ptr, i, 0);
357 string s2 = Marshal.PtrToStringUni (ptr);
358 Assert.AreEqual (0, s2.Length, "Length-2");
360 Marshal.FreeHGlobal (ptr);
365 public void StringToCoTaskMemAnsiWithNullValues ()
368 string s = String.Empty.PadLeft (size, '\0');
369 Assert.AreEqual (size, s.Length, "Length-1");
371 IntPtr ptr = Marshal.StringToCoTaskMemAnsi (s);
373 for (int i = 0; i < size; i += 4)
374 Marshal.WriteInt32 (ptr, i, 0);
376 string s2 = Marshal.PtrToStringAnsi (ptr);
377 Assert.AreEqual (0, s2.Length, "Length-2");
379 Marshal.FreeCoTaskMem (ptr);
384 public void StringToCoTaskMemAutoWithNullValues ()
387 string s = String.Empty.PadLeft (size, '\0');
388 Assert.AreEqual (size, s.Length, "Length-1");
390 IntPtr ptr = Marshal.StringToCoTaskMemAuto (s);
392 for (int i = 0; i < size; i += 4)
393 Marshal.WriteInt32 (ptr, i, 0);
395 string s2 = Marshal.PtrToStringAuto (ptr);
396 Assert.AreEqual (0, s2.Length, "Length-2");
398 Marshal.FreeCoTaskMem (ptr);
403 public void StringToCoTaskMemUniWithNullValues ()
406 string s = String.Empty.PadLeft (size, '\0');
407 Assert.AreEqual (size, s.Length, "Length-1");
409 IntPtr ptr = Marshal.StringToCoTaskMemUni (s);
411 for (int i = 0; i < size; i += 4)
412 Marshal.WriteInt32 (ptr, i, 0);
414 string s2 = Marshal.PtrToStringUni (ptr);
415 Assert.AreEqual (0, s2.Length, "Length-2");
417 Marshal.FreeCoTaskMem (ptr);
421 private const string NotSupported = "Not supported before Windows 2000 Service Pack 3";
422 private static char[] PlainText = new char[] { 'a', 'b', 'c' };
423 private static byte[] AsciiPlainText = new byte[] { (byte) 'a', (byte) 'b', (byte) 'c' };
425 private unsafe SecureString GetSecureString ()
427 fixed (char* p = &PlainText[0]) {
428 return new SecureString (p, PlainText.Length);
433 public void SecureStringToBSTR_Null ()
436 Marshal.SecureStringToBSTR (null);
438 } catch (ArgumentNullException ex) {
439 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
440 Assert.IsNull (ex.InnerException, "#3");
441 Assert.IsNotNull (ex.Message, "#4");
442 Assert.AreEqual ("s", ex.ParamName, "#5");
447 public void SecureStringToBSTR ()
450 SecureString ss = GetSecureString ();
451 IntPtr p = Marshal.SecureStringToBSTR (ss);
453 char[] decrypted = new char[ss.Length];
454 Marshal.Copy (p, decrypted, 0, decrypted.Length);
455 Assert.AreEqual (PlainText, decrypted, "Decrypted");
457 Marshal.ZeroFreeBSTR (p);
458 } catch (NotSupportedException) {
459 Assert.Ignore (NotSupported);
464 public void SecureStringToCoTaskMemAnsi_Null ()
467 Marshal.SecureStringToCoTaskMemAnsi (null);
469 } catch (ArgumentNullException ex) {
470 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
471 Assert.IsNull (ex.InnerException, "#3");
472 Assert.IsNotNull (ex.Message, "#4");
473 Assert.AreEqual ("s", ex.ParamName, "#5");
478 public void SecureStringToCoTaskMemAnsi ()
481 SecureString ss = GetSecureString ();
482 IntPtr p = Marshal.SecureStringToCoTaskMemAnsi (ss);
484 byte[] decrypted = new byte[ss.Length];
485 Marshal.Copy (p, decrypted, 0, decrypted.Length);
486 Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
488 Marshal.ZeroFreeCoTaskMemAnsi (p);
489 } catch (NotSupportedException) {
490 Assert.Ignore (NotSupported);
495 public void SecureStringToCoTaskMemUnicode_Null ()
498 Marshal.SecureStringToCoTaskMemUnicode (null);
500 } catch (ArgumentNullException ex) {
501 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
502 Assert.IsNull (ex.InnerException, "#3");
503 Assert.IsNotNull (ex.Message, "#4");
504 Assert.AreEqual ("s", ex.ParamName, "#5");
509 public void SecureStringToCoTaskMemUnicode ()
512 SecureString ss = GetSecureString ();
513 IntPtr p = Marshal.SecureStringToCoTaskMemUnicode (ss);
515 char[] decrypted = new char[ss.Length];
516 Marshal.Copy (p, decrypted, 0, decrypted.Length);
517 Assert.AreEqual (PlainText, decrypted, "Decrypted");
519 Marshal.ZeroFreeCoTaskMemUnicode (p);
520 } catch (NotSupportedException) {
521 Assert.Ignore (NotSupported);
526 public void SecureStringToGlobalAllocAnsi_Null ()
529 Marshal.SecureStringToGlobalAllocAnsi (null);
531 } catch (ArgumentNullException ex) {
532 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
533 Assert.IsNull (ex.InnerException, "#3");
534 Assert.IsNotNull (ex.Message, "#4");
535 Assert.AreEqual ("s", ex.ParamName, "#5");
540 public void SecureStringToGlobalAllocAnsi ()
543 SecureString ss = GetSecureString ();
544 IntPtr p = Marshal.SecureStringToGlobalAllocAnsi (ss);
546 byte[] decrypted = new byte[ss.Length];
547 Marshal.Copy (p, decrypted, 0, decrypted.Length);
548 Assert.AreEqual (AsciiPlainText, decrypted, "Decrypted");
550 Marshal.ZeroFreeGlobalAllocAnsi (p);
551 } catch (NotSupportedException) {
552 Assert.Ignore (NotSupported);
557 public void SecureStringToGlobalAllocUnicode_Null ()
560 Marshal.SecureStringToGlobalAllocUnicode (null);
562 } catch (ArgumentNullException ex) {
563 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
564 Assert.IsNull (ex.InnerException, "#3");
565 Assert.IsNotNull (ex.Message, "#4");
566 Assert.AreEqual ("s", ex.ParamName, "#5");
571 public void SecureStringToGlobalAllocUnicode ()
574 SecureString ss = GetSecureString ();
575 IntPtr p = Marshal.SecureStringToGlobalAllocUnicode (ss);
577 char[] decrypted = new char[ss.Length];
578 Marshal.Copy (p, decrypted, 0, decrypted.Length);
579 Assert.AreEqual (PlainText, decrypted, "Decrypted");
581 Marshal.ZeroFreeGlobalAllocUnicode (p);
582 } catch (NotSupportedException) {
583 Assert.Ignore (NotSupported);
589 public void TestGetComSlotForMethodInfo ()
591 Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDefault).GetMethod("DoNothing")));
592 Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo(typeof(ITestDual).GetMethod("DoNothing")));
593 Assert.AreEqual (7, Marshal.GetComSlotForMethodInfo (typeof(ITestDefault).GetMethod ("DoNothing")));
594 Assert.AreEqual (3, Marshal.GetComSlotForMethodInfo (typeof(ITestUnknown).GetMethod ("DoNothing")));
596 for (int i = 0; i < 10; i++)
597 Assert.AreEqual (7+i, Marshal.GetComSlotForMethodInfo(typeof(ITestInterface).GetMethod ("Method"+i.ToString())));
601 public void TestGetComSlotForMethod_Method_Null ()
604 Marshal.GetComSlotForMethodInfo (null);
606 } catch (ArgumentNullException ex) {
607 Assert.AreEqual (typeof (ArgumentNullException), ex.GetType (), "#2");
608 Assert.IsNull (ex.InnerException, "#3");
609 Assert.IsNotNull (ex.Message, "#4");
611 Assert.AreEqual ("m", ex.ParamName, "#5");
613 Assert.IsNull (ex.ParamName, "#5");
619 public void TestGetComSlotForMethodInfo_Method_NotOnInterface ()
621 MethodInfo m = typeof(TestCoClass).GetMethod ("DoNothing");
623 Marshal.GetComSlotForMethodInfo (m);
625 } catch (ArgumentException ex) {
626 // The MemberInfo must be an interface method
627 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "#2");
628 Assert.IsNull (ex.InnerException, "#3");
629 Assert.IsNotNull (ex.Message, "#4");
630 Assert.AreEqual ("m", ex.ParamName, "#5");
635 public void TestPtrToStringAuto ()
637 string input = Guid.NewGuid ().ToString ();
643 if (Environment.OSVersion.Platform == PlatformID.Win32NT) {
645 ptr = Marshal.StringToHGlobalAuto (input);
646 output = Marshal.PtrToStringUni (ptr);
647 output2 = Marshal.PtrToStringUni (ptr, len);
650 ptr = Marshal.StringToHGlobalAuto (input);
651 output = Marshal.PtrToStringAnsi (ptr);
652 output2 = Marshal.PtrToStringAnsi (ptr, len);
656 Assert.AreEqual (input, output, "#1");
657 Assert.AreEqual (input.Substring (0, len), output2, "#2");
659 Marshal.FreeHGlobal (ptr);
664 public void TestGenerateProgIdForType()
668 output = Marshal.GenerateProgIdForType(typeof(TestCoClass));
669 Assert.AreEqual ("MonoTests.System.Runtime.InteropServices.TestCoClass", output, "#1");
671 output = Marshal.GenerateProgIdForType(typeof(TestCoClassWithProgId));
672 Assert.AreEqual ("CoClassWithProgId", output, "#2");
676 public void TestGlobalAlloc ()
678 IntPtr mem = Marshal.AllocHGlobal (100);
679 mem = Marshal.ReAllocHGlobal (mem, (IntPtr) 1000000);
680 Marshal.FreeHGlobal (mem);
684 public void TestGetExceptionForHR ()
686 const int E_OUTOFMEMORY = unchecked ((int) 0x8007000E);
687 const int E_INVALIDARG = unchecked ((int) 0X80070057);
689 Exception ex = Marshal.GetExceptionForHR (E_OUTOFMEMORY);
690 Assert.AreEqual (typeof (OutOfMemoryException), ex.GetType (), "E_OUTOFMEMORY");
692 ex = Marshal.GetExceptionForHR (E_INVALIDARG);
693 Assert.AreEqual (typeof (ArgumentException), ex.GetType (), "E_INVALIDARG");
698 int p = (int) Environment.OSVersion.Platform;
699 return ((p == 4) || (p == 128) || (p == 6));
703 [DllImport ("kernel32.dll", SetLastError = true)]
705 static extern uint GetModuleFileName (
709 StringBuilder lpFilename,
711 [MarshalAs (UnmanagedType.U4)]
717 [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
718 interface ITestDefault
724 [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
725 [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
726 interface ITestDispatch
732 [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
733 [InterfaceType(ComInterfaceType.InterfaceIsDual)]
740 [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
741 [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
742 interface ITestUnknown
748 [Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA")]
749 interface ITestInterface
763 public class TestCoClass : ITestDispatch
765 public void DoNothing ()
770 [ProgId("CoClassWithProgId")]
771 public class TestCoClassWithProgId : ITestDispatch
773 public void DoNothing ()