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