3 // Copyright (c) Microsoft Corporation. All rights reserved.
7 namespace System.StubHelpers {
10 using Microsoft.Win32;
11 using System.Security;
12 using System.Collections.Generic;
14 using System.Runtime.InteropServices;
15 #if FEATURE_COMINTEROP
16 using System.Runtime.InteropServices.WindowsRuntime;
17 #endif // FEATURE_COMINTEROP
18 using System.Runtime.CompilerServices;
19 using System.Runtime.ConstrainedExecution;
20 using System.Diagnostics.Contracts;
22 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
23 internal static class AnsiCharMarshaler
25 // The length of the returned array is an approximation based on the length of the input string and the system
26 // character set. It is only guaranteed to be larger or equal to cbLength, don't depend on the exact value.
27 [System.Security.SecurityCritical]
28 unsafe static internal byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength)
30 byte[] buffer = new byte[(str.Length + 1) * Marshal.SystemMaxDBCSCharSize];
31 fixed (byte *bufferPtr = buffer)
33 cbLength = str.ConvertToAnsi(bufferPtr, buffer.Length, fBestFit, fThrowOnUnmappableChar);
38 [System.Security.SecurityCritical]
39 unsafe static internal byte ConvertToNative(char managedChar, bool fBestFit, bool fThrowOnUnmappableChar)
41 int cbAllocLength = (1 + 1) * Marshal.SystemMaxDBCSCharSize;
42 byte* bufferPtr = stackalloc byte[cbAllocLength];
44 int cbLength = managedChar.ToString().ConvertToAnsi(bufferPtr, cbAllocLength, fBestFit, fThrowOnUnmappableChar);
46 BCLDebug.Assert(cbLength > 0, "Zero bytes returned from DoAnsiConversion in AnsiCharMarshaler.ConvertToNative");
50 static internal char ConvertToManaged(byte nativeChar)
52 byte[] bytes = new byte[1] { nativeChar };
53 string str = Encoding.Default.GetString(bytes);
56 } // class AnsiCharMarshaler
58 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
59 internal static class CSTRMarshaler
61 [System.Security.SecurityCritical] // auto-generated
62 static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer)
64 if (null == strManaged)
69 StubHelpers.CheckStringLength(strManaged.Length);
72 byte *pbNativeBuffer = (byte *)pNativeBuffer;
74 if (pbNativeBuffer != null || Marshal.SystemMaxDBCSCharSize == 1)
76 // If we are marshaling into a stack buffer or we can accurately estimate the size of the required heap
77 // space, we will use a "1-pass" mode where we convert the string directly into the unmanaged buffer.
79 // + 1 for the null character from the user
80 nb = (strManaged.Length + 1) * Marshal.SystemMaxDBCSCharSize;
82 // Use the pre-allocated buffer (allocated by localloc IL instruction) if not NULL,
83 // otherwise fallback to AllocCoTaskMem
84 if (pbNativeBuffer == null)
86 // + 1 for the null character we put in
87 pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 1);
90 nb = strManaged.ConvertToAnsi(pbNativeBuffer, nb + 1, 0 != (flags & 0xFF), 0 != (flags >> 8));
94 // Otherwise we use a slower "2-pass" mode where we first marshal the string into an intermediate buffer
95 // (managed byte array) and then allocate exactly the right amount of unmanaged memory. This is to avoid
96 // wasting memory on systems with multibyte character sets where the buffer we end up with is often much
97 // smaller than the upper bound for the given managed string.
99 byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xFF), 0 != (flags >> 8), out nb);
101 // + 1 for the null character from the user. + 1 for the null character we put in.
102 pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 2);
104 Buffer.Memcpy(pbNativeBuffer, 0, bytes, 0, nb);
107 pbNativeBuffer[nb] = 0x00;
108 pbNativeBuffer[nb + 1] = 0x00;
110 return (IntPtr)pbNativeBuffer;
113 [System.Security.SecurityCritical] // auto-generated
114 static internal unsafe string ConvertToManaged(IntPtr cstr)
116 if (IntPtr.Zero == cstr)
119 return new String((sbyte*)cstr);
122 [System.Security.SecurityCritical] // auto-generated
123 static internal void ClearNative(IntPtr pNative)
125 Win32Native.CoTaskMemFree(pNative);
127 } // class CSTRMarshaler
129 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
130 internal static class BSTRMarshaler
132 [System.Security.SecurityCritical] // auto-generated
133 static internal unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeBuffer)
135 if (null == strManaged)
141 StubHelpers.CheckStringLength(strManaged.Length);
144 bool hasTrailByte = strManaged.TryGetTrailByte(out trailByte);
146 uint lengthInBytes = (uint)strManaged.Length * 2;
150 // this is an odd-sized string with a trailing byte stored in its sync block
154 byte *ptrToFirstChar;
156 if (pNativeBuffer != IntPtr.Zero)
158 // If caller provided a buffer, construct the BSTR manually. The size
159 // of the buffer must be at least (lengthInBytes + 6) bytes.
161 uint length = *((uint *)pNativeBuffer.ToPointer());
162 BCLDebug.Assert(length >= lengthInBytes + 6, "BSTR localloc'ed buffer is too small");
166 *((uint *)pNativeBuffer.ToPointer()) = lengthInBytes;
168 ptrToFirstChar = (byte *)pNativeBuffer.ToPointer() + 4;
172 // If not provided, allocate the buffer using SysAllocStringByteLen so
173 // that odd-sized strings will be handled as well.
174 ptrToFirstChar = (byte *)Win32Native.SysAllocStringByteLen(null, lengthInBytes).ToPointer();
177 // copy characters from the managed string
178 fixed (char* ch = strManaged)
183 (strManaged.Length + 1) * 2);
186 // copy the trail byte if present
189 ptrToFirstChar[lengthInBytes - 1] = trailByte;
192 // return ptr to first character
193 return (IntPtr)ptrToFirstChar;
197 [System.Security.SecurityCritical] // auto-generated
198 static internal unsafe string ConvertToManaged(IntPtr bstr)
200 if (IntPtr.Zero == bstr)
206 uint length = Win32Native.SysStringByteLen(bstr);
208 // Intentionally checking the number of bytes not characters to match the behavior
209 // of ML marshalers. This prevents roundtripping of very large strings as the check
210 // in the managed->native direction is done on String length but considering that
211 // it's completely moot on 32-bit and not expected to be important on 64-bit either,
212 // the ability to catch random garbage in the BSTR's length field outweighs this
213 // restriction. If an ordinary null-terminated string is passed instead of a BSTR,
214 // chances are that the length field - possibly being unallocated memory - contains
215 // a heap fill pattern that will have the highest bit set, caught by the check.
216 StubHelpers.CheckStringLength(length);
221 // In the empty string case, we need to use FastAllocateString rather than the
222 // String .ctor, since newing up a 0 sized string will always return String.Emtpy.
223 // When we marshal that out as a bstr, it can wind up getting modified which
224 // corrupts String.Empty.
225 ret = String.FastAllocateString(0);
229 ret = new String((char*)bstr, 0, (int)(length / 2));
232 if ((length & 1) == 1)
234 // odd-sized strings need to have the trailing byte saved in their sync block
235 ret.SetTrailByte(((byte *)bstr.ToPointer())[length - 1]);
242 [System.Security.SecurityCritical] // auto-generated
243 static internal void ClearNative(IntPtr pNative)
245 if (IntPtr.Zero != pNative)
247 Win32Native.SysFreeString(pNative);
250 } // class BSTRMarshaler
252 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
253 internal static class VBByValStrMarshaler
255 [System.Security.SecurityCritical] // auto-generated
256 static internal unsafe IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch)
258 if (null == strManaged)
265 cch = strManaged.Length;
267 StubHelpers.CheckStringLength(cch);
269 // length field at negative offset + (# of characters incl. the terminator) * max ANSI char size
270 int nbytes = sizeof(uint) + ((cch + 1) * Marshal.SystemMaxDBCSCharSize);
272 pNative = (byte*)Marshal.AllocCoTaskMem(nbytes);
273 int* pLength = (int*)pNative;
275 pNative = pNative + sizeof(uint);
285 byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, fBestFit, fThrowOnUnmappableChar, out nbytesused);
287 BCLDebug.Assert(nbytesused < nbytes, "Insufficient buffer allocated in VBByValStrMarshaler.ConvertToNative");
288 Buffer.Memcpy(pNative, 0, bytes, 0, nbytesused);
290 pNative[nbytesused] = 0;
291 *pLength = nbytesused;
294 return new IntPtr(pNative);
297 [System.Security.SecurityCritical] // auto-generated
298 static internal unsafe string ConvertToManaged(IntPtr pNative, int cch)
300 if (IntPtr.Zero == pNative)
305 return new String((sbyte*)pNative, 0, cch);
308 [System.Security.SecurityCritical] // auto-generated
309 static internal unsafe void ClearNative(IntPtr pNative)
311 if (IntPtr.Zero != pNative)
313 Win32Native.CoTaskMemFree((IntPtr)(((long)pNative) - sizeof(uint)));
316 } // class VBByValStrMarshaler
318 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
319 internal static class AnsiBSTRMarshaler
321 [System.Security.SecurityCritical] // auto-generated
322 static internal unsafe IntPtr ConvertToNative(int flags, string strManaged)
324 if (null == strManaged)
329 int length = strManaged.Length;
331 StubHelpers.CheckStringLength(length);
338 bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xFF), 0 != (flags >> 8), out nb);
341 return Win32Native.SysAllocStringByteLen(bytes, (uint)nb);
344 [System.Security.SecurityCritical] // auto-generated
345 static internal unsafe string ConvertToManaged(IntPtr bstr)
347 if (IntPtr.Zero == bstr)
353 // We intentionally ignore the length field of the BSTR for back compat reasons.
354 // Unfortunately VB.NET uses Ansi BSTR marshaling when a string is passed ByRef
355 // and we cannot afford to break this common scenario.
356 return new String((sbyte*)bstr);
360 [System.Security.SecurityCritical] // auto-generated
361 static internal unsafe void ClearNative(IntPtr pNative)
363 if (IntPtr.Zero != pNative)
365 Win32Native.SysFreeString(pNative);
368 } // class AnsiBSTRMarshaler
370 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
371 internal static class WSTRBufferMarshaler
373 static internal IntPtr ConvertToNative(string strManaged)
375 Contract.Assert(false, "NYI");
379 static internal unsafe string ConvertToManaged(IntPtr bstr)
381 Contract.Assert(false, "NYI");
385 static internal void ClearNative(IntPtr pNative)
387 Contract.Assert(false, "NYI");
389 } // class WSTRBufferMarshaler
392 #if FEATURE_COMINTEROP
395 [StructLayout(LayoutKind.Sequential)]
396 internal struct DateTimeNative
398 public Int64 UniversalTime;
401 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
402 internal static class DateTimeOffsetMarshaler {
404 // Numer of ticks counted between 0001-01-01, 00:00:00 and 1601-01-01, 00:00:00.
405 // You can get this through: (new DateTimeOffset(1601, 1, 1, 0, 0, 1, TimeSpan.Zero)).Ticks;
406 private const Int64 ManagedUtcTicksAtNativeZero = 504911232000000000;
409 internal static void ConvertToNative(ref DateTimeOffset managedDTO, out DateTimeNative dateTime) {
411 Int64 managedUtcTicks = managedDTO.UtcTicks;
412 dateTime.UniversalTime = managedUtcTicks - ManagedUtcTicksAtNativeZero;
416 internal static void ConvertToManaged(out DateTimeOffset managedLocalDTO, ref DateTimeNative nativeTicks) {
418 Int64 managedUtcTicks = ManagedUtcTicksAtNativeZero + nativeTicks.UniversalTime;
419 DateTimeOffset managedUtcDTO = new DateTimeOffset(managedUtcTicks, TimeSpan.Zero);
421 // Some Utc times cannot be represented in local time in certain timezones. E.g. 0001-01-01 12:00:00 AM cannot
422 // be represented in any timezones with a negative offset from Utc. We throw an ArgumentException in that case.
423 managedLocalDTO = managedUtcDTO.ToLocalTime(true);
425 } // class DateTimeOffsetMarshaler
427 #endif // FEATURE_COMINTEROP
430 #if FEATURE_COMINTEROP
431 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
432 internal static class HStringMarshaler
434 // Slow-path, which requires making a copy of the managed string into the resulting HSTRING
436 internal static unsafe IntPtr ConvertToNative(string managed)
438 if (!Environment.IsWinRTSupported)
439 throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
441 throw new ArgumentNullException(); // We don't have enough information to get the argument name just yet - that support will be coming in M3
444 int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString(managed, managed.Length, &hstring);
445 Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
449 // Fast-path, which creates a reference over a pinned managed string. This may only be used if the
450 // pinned string and HSTRING_HEADER will outlive the HSTRING produced (for instance, as an in parameter).
452 // Note that the managed string input to this method MUST be pinned, and stay pinned for the lifetime of
453 // the returned HSTRING object. If the string is not pinned, or becomes unpinned before the HSTRING's
454 // lifetime ends, the HSTRING instance will be corrupted.
456 internal static unsafe IntPtr ConvertToNativeReference(string managed,
457 [Out] HSTRING_HEADER *hstringHeader)
459 if (!Environment.IsWinRTSupported)
460 throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
462 throw new ArgumentNullException(); // We don't have enough information to get the argument name just yet - that support will be coming in M3
464 // The string must also be pinned by the caller to ConvertToNativeReference, which also owns
465 // the HSTRING_HEADER.
466 fixed (char *pManaged = managed)
469 int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateStringReference(pManaged, managed.Length, hstringHeader, &hstring);
470 Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
476 internal static string ConvertToManaged(IntPtr hstring)
478 if (!Environment.IsWinRTSupported)
480 throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
483 return WindowsRuntimeMarshal.HStringToString(hstring);
487 internal static void ClearNative(IntPtr hstring)
489 Contract.Assert(Environment.IsWinRTSupported);
491 if (hstring != IntPtr.Zero)
493 System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString(hstring);
496 } // class HStringMarshaler
498 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
499 internal static class ObjectMarshaler
501 [MethodImplAttribute(MethodImplOptions.InternalCall)]
502 static internal extern void ConvertToNative(object objSrc, IntPtr pDstVariant);
504 [MethodImplAttribute(MethodImplOptions.InternalCall)]
505 static internal extern object ConvertToManaged(IntPtr pSrcVariant);
507 [MethodImplAttribute(MethodImplOptions.InternalCall)]
508 static internal extern void ClearNative(IntPtr pVariant);
509 } // class ObjectMarshaler
511 #endif // FEATURE_COMINTEROP
513 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
514 internal static class ValueClassMarshaler
517 [MethodImplAttribute(MethodImplOptions.InternalCall)]
518 static internal extern void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkList pCleanupWorkList);
520 [MethodImplAttribute(MethodImplOptions.InternalCall)]
521 static internal extern void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT);
523 [MethodImplAttribute(MethodImplOptions.InternalCall)]
524 static internal extern void ClearNative(IntPtr dst, IntPtr pMT);
525 } // class ValueClassMarshaler
527 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
528 internal static class DateMarshaler
530 [MethodImplAttribute(MethodImplOptions.InternalCall)]
531 static internal extern double ConvertToNative(DateTime managedDate);
533 // The return type is really DateTime but we use long to avoid the pain associated with returning structures.
534 [MethodImplAttribute(MethodImplOptions.InternalCall)]
535 static internal extern long ConvertToManaged(double nativeDate);
536 } // class DateMarshaler
538 #if FEATURE_COMINTEROP
539 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
540 [FriendAccessAllowed]
541 internal static class InterfaceMarshaler
543 [MethodImplAttribute(MethodImplOptions.InternalCall)]
544 static internal extern IntPtr ConvertToNative(object objSrc, IntPtr itfMT, IntPtr classMT, int flags);
546 [MethodImplAttribute(MethodImplOptions.InternalCall)]
547 static internal extern object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags);
550 [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity]
551 static internal extern void ClearNative(IntPtr pUnk);
553 [FriendAccessAllowed]
554 [MethodImplAttribute(MethodImplOptions.InternalCall)]
555 static internal extern object ConvertToManagedWithoutUnboxing(IntPtr pNative);
556 } // class InterfaceMarshaler
557 #endif // FEATURE_COMINTEROP
559 #if FEATURE_COMINTEROP
560 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
561 internal static class UriMarshaler
563 [MethodImplAttribute(MethodImplOptions.InternalCall)]
564 static internal extern string GetRawUriFromNative(IntPtr pUri);
566 [MethodImplAttribute(MethodImplOptions.InternalCall)]
567 [System.Security.SecurityCritical]
568 static unsafe internal extern IntPtr CreateNativeUriInstanceHelper(char* rawUri, int strLen);
570 [System.Security.SecurityCritical]
571 static unsafe internal IntPtr CreateNativeUriInstance(string rawUri)
573 fixed(char* pManaged = rawUri)
575 return CreateNativeUriInstanceHelper(pManaged, rawUri.Length);
579 } // class InterfaceMarshaler
581 [FriendAccessAllowed]
582 internal static class EventArgsMarshaler
585 [FriendAccessAllowed]
586 static internal IntPtr CreateNativeNCCEventArgsInstance(int action, object newItems, object oldItems, int newIndex, int oldIndex)
588 IntPtr newItemsIP = IntPtr.Zero;
589 IntPtr oldItemsIP = IntPtr.Zero;
591 RuntimeHelpers.PrepareConstrainedRegions();
594 if (newItems != null)
595 newItemsIP = Marshal.GetComInterfaceForObject(newItems, typeof(IBindableVector));
596 if (oldItems != null)
597 oldItemsIP = Marshal.GetComInterfaceForObject(oldItems, typeof(IBindableVector));
599 return CreateNativeNCCEventArgsInstanceHelper(action, newItemsIP, oldItemsIP, newIndex, oldIndex);
603 if (!oldItemsIP.IsNull())
604 Marshal.Release(oldItemsIP);
605 if (!newItemsIP.IsNull())
606 Marshal.Release(newItemsIP);
611 [FriendAccessAllowed]
612 [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity]
613 static extern internal IntPtr CreateNativePCEventArgsInstance([MarshalAs(UnmanagedType.HString)]string name);
616 [DllImport(JitHelpers.QCall), SuppressUnmanagedCodeSecurity]
617 static extern internal IntPtr CreateNativeNCCEventArgsInstanceHelper(int action, IntPtr newItem, IntPtr oldItem, int newIndex, int oldIndex);
619 #endif // FEATURE_COMINTEROP
621 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
622 internal static class MngdNativeArrayMarshaler
624 [MethodImplAttribute(MethodImplOptions.InternalCall)]
625 static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags);
627 [MethodImplAttribute(MethodImplOptions.InternalCall)]
628 static internal extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
630 [MethodImplAttribute(MethodImplOptions.InternalCall)]
631 static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
633 [MethodImplAttribute(MethodImplOptions.InternalCall)]
634 static internal extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome,
637 [MethodImplAttribute(MethodImplOptions.InternalCall)]
638 static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
640 [MethodImplAttribute(MethodImplOptions.InternalCall)]
641 static internal extern void ClearNative(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
643 [MethodImplAttribute(MethodImplOptions.InternalCall)]
644 static internal extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
645 } // class MngdNativeArrayMarshaler
647 #if FEATURE_COMINTEROP
648 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
649 internal static class MngdSafeArrayMarshaler
651 [MethodImplAttribute(MethodImplOptions.InternalCall)]
652 static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int iRank, int dwFlags);
654 [MethodImplAttribute(MethodImplOptions.InternalCall)]
655 static internal extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
657 [MethodImplAttribute(MethodImplOptions.InternalCall)]
658 static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, object pOriginalManaged);
660 [MethodImplAttribute(MethodImplOptions.InternalCall)]
661 static internal extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
663 [MethodImplAttribute(MethodImplOptions.InternalCall)]
664 static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
666 [MethodImplAttribute(MethodImplOptions.InternalCall)]
667 static internal extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
668 } // class MngdSafeArrayMarshaler
670 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
671 internal static class MngdHiddenLengthArrayMarshaler
674 [MethodImplAttribute(MethodImplOptions.InternalCall)]
675 static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt);
678 [MethodImplAttribute(MethodImplOptions.InternalCall)]
679 internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
682 [MethodImplAttribute(MethodImplOptions.InternalCall)]
683 internal static extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
686 internal static unsafe void ConvertContentsToNative_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome)
688 if (managedArray != null)
690 DateTimeNative *nativeBuffer = *(DateTimeNative **)pNativeHome;
691 for (int i = 0; i < managedArray.Length; i++)
693 DateTimeOffsetMarshaler.ConvertToNative(ref managedArray[i], out nativeBuffer[i]);
699 internal static unsafe void ConvertContentsToNative_Type(ref System.Type[] managedArray, IntPtr pNativeHome)
701 if (managedArray != null)
703 TypeNameNative *nativeBuffer = *(TypeNameNative **)pNativeHome;
704 for (int i = 0; i < managedArray.Length; i++)
706 SystemTypeMarshaler.ConvertToNative(managedArray[i], &nativeBuffer[i]);
712 internal static unsafe void ConvertContentsToNative_Exception(ref Exception[] managedArray, IntPtr pNativeHome)
714 if (managedArray != null)
716 Int32 *nativeBuffer = *(Int32 **)pNativeHome;
717 for (int i = 0; i < managedArray.Length; i++)
719 nativeBuffer[i] = HResultExceptionMarshaler.ConvertToNative(managedArray[i]);
725 internal static unsafe void ConvertContentsToNative_Nullable<T>(ref Nullable<T>[] managedArray, IntPtr pNativeHome)
728 if (managedArray != null)
730 IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
731 for (int i = 0; i < managedArray.Length; i++)
733 nativeBuffer[i] = NullableMarshaler.ConvertToNative<T>(ref managedArray[i]);
739 internal static unsafe void ConvertContentsToNative_KeyValuePair<K, V>(ref KeyValuePair<K, V>[] managedArray, IntPtr pNativeHome)
741 if (managedArray != null)
743 IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
744 for (int i = 0; i < managedArray.Length; i++)
746 nativeBuffer[i] = KeyValuePairMarshaler.ConvertToNative<K, V>(ref managedArray[i]);
752 [MethodImplAttribute(MethodImplOptions.InternalCall)]
753 internal static extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int elementCount);
756 [MethodImplAttribute(MethodImplOptions.InternalCall)]
757 internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
760 internal static unsafe void ConvertContentsToManaged_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome)
762 if (managedArray != null)
764 DateTimeNative *nativeBuffer = *(DateTimeNative **)pNativeHome;
765 for (int i = 0; i < managedArray.Length; i++)
767 DateTimeOffsetMarshaler.ConvertToManaged(out managedArray[i], ref nativeBuffer[i]);
773 internal static unsafe void ConvertContentsToManaged_Type(ref System.Type[] managedArray, IntPtr pNativeHome)
775 if (managedArray != null)
777 TypeNameNative *nativeBuffer = *(TypeNameNative **)pNativeHome;
778 for (int i = 0; i < managedArray.Length; i++)
780 SystemTypeMarshaler.ConvertToManaged(&nativeBuffer[i], ref managedArray[i]);
786 internal static unsafe void ConvertContentsToManaged_Exception(ref Exception[] managedArray, IntPtr pNativeHome)
788 if (managedArray != null)
790 Int32 *nativeBuffer = *(Int32 **)pNativeHome;
791 for (int i = 0; i < managedArray.Length; i++)
793 managedArray[i] = HResultExceptionMarshaler.ConvertToManaged(nativeBuffer[i]);
799 internal static unsafe void ConvertContentsToManaged_Nullable<T>(ref Nullable<T>[] managedArray, IntPtr pNativeHome)
802 if (managedArray != null)
804 IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
805 for (int i = 0; i < managedArray.Length; i++)
807 managedArray[i] = NullableMarshaler.ConvertToManaged<T>(nativeBuffer[i]);
813 internal static unsafe void ConvertContentsToManaged_KeyValuePair<K, V>(ref KeyValuePair<K, V>[] managedArray, IntPtr pNativeHome)
815 if (managedArray != null)
817 IntPtr *nativeBuffer = *(IntPtr **)pNativeHome;
818 for (int i = 0; i < managedArray.Length; i++)
820 managedArray[i] = KeyValuePairMarshaler.ConvertToManaged<K, V>(nativeBuffer[i]);
826 [MethodImplAttribute(MethodImplOptions.InternalCall)]
827 internal static extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
830 internal static unsafe void ClearNativeContents_Type(IntPtr pNativeHome, int cElements)
832 Contract.Assert(Environment.IsWinRTSupported);
834 TypeNameNative *pNativeTypeArray = *(TypeNameNative **)pNativeHome;
835 if (pNativeTypeArray != null)
837 for (int i = 0; i < cElements; ++i)
839 SystemTypeMarshaler.ClearNative(pNativeTypeArray);
844 } // class MngdHiddenLengthArrayMarshaler
846 #endif // FEATURE_COMINTEROP
848 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
849 internal static class MngdRefCustomMarshaler
851 [MethodImplAttribute(MethodImplOptions.InternalCall)]
852 static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pCMHelper);
854 [MethodImplAttribute(MethodImplOptions.InternalCall)]
855 static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
857 [MethodImplAttribute(MethodImplOptions.InternalCall)]
858 static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
860 [MethodImplAttribute(MethodImplOptions.InternalCall)]
861 static internal extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
863 [MethodImplAttribute(MethodImplOptions.InternalCall)]
864 static internal extern void ClearManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
865 } // class MngdRefCustomMarshaler
867 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
868 [System.Security.SecurityCritical]
869 internal struct AsAnyMarshaler
871 private const ushort VTHACK_ANSICHAR = 253;
872 private const ushort VTHACK_WINBOOL = 254;
874 private enum BackPropAction
883 // Pointer to MngdNativeArrayMarshaler, ownership not assumed.
884 private IntPtr pvArrayMarshaler;
886 // Type of action to perform after the CLR-to-unmanaged call.
887 private BackPropAction backPropAction;
889 // The managed layout type for BackPropAction.Layout.
890 private Type layoutType;
892 // Cleanup list to be destroyed when clearing the native view (for layouts with SafeHandles).
893 private CleanupWorkList cleanupWorkList;
895 private static bool IsIn(int dwFlags) { return ((dwFlags & 0x10000000) != 0); }
896 private static bool IsOut(int dwFlags) { return ((dwFlags & 0x20000000) != 0); }
897 private static bool IsAnsi(int dwFlags) { return ((dwFlags & 0x00FF0000) != 0); }
898 private static bool IsThrowOn(int dwFlags) { return ((dwFlags & 0x0000FF00) != 0); }
899 private static bool IsBestFit(int dwFlags) { return ((dwFlags & 0x000000FF) != 0); }
901 internal AsAnyMarshaler(IntPtr pvArrayMarshaler)
903 // we need this in case the value being marshaled turns out to be array
904 BCLDebug.Assert(pvArrayMarshaler != IntPtr.Zero, "pvArrayMarshaler must not be null");
906 this.pvArrayMarshaler = pvArrayMarshaler;
907 this.backPropAction = BackPropAction.None;
908 this.layoutType = null;
909 this.cleanupWorkList = null;
912 #region ConvertToNative helpers
914 [System.Security.SecurityCritical]
915 private unsafe IntPtr ConvertArrayToNative(object pManagedHome, int dwFlags)
917 Type elementType = pManagedHome.GetType().GetElementType();
918 VarEnum vt = VarEnum.VT_EMPTY;
920 switch (Type.GetTypeCode(elementType))
922 case TypeCode.SByte: vt = VarEnum.VT_I1; break;
923 case TypeCode.Byte: vt = VarEnum.VT_UI1; break;
924 case TypeCode.Int16: vt = VarEnum.VT_I2; break;
925 case TypeCode.UInt16: vt = VarEnum.VT_UI2; break;
926 case TypeCode.Int32: vt = VarEnum.VT_I4; break;
927 case TypeCode.UInt32: vt = VarEnum.VT_UI4; break;
928 case TypeCode.Int64: vt = VarEnum.VT_I8; break;
929 case TypeCode.UInt64: vt = VarEnum.VT_UI8; break;
930 case TypeCode.Single: vt = VarEnum.VT_R4; break;
931 case TypeCode.Double: vt = VarEnum.VT_R8; break;
932 case TypeCode.Char: vt = (IsAnsi(dwFlags) ? (VarEnum)VTHACK_ANSICHAR : VarEnum.VT_UI2); break;
933 case TypeCode.Boolean: vt = (VarEnum)VTHACK_WINBOOL; break;
935 case TypeCode.Object:
937 if (elementType == typeof(IntPtr))
939 vt = (IntPtr.Size == 4 ? VarEnum.VT_I4 : VarEnum.VT_I8);
941 else if (elementType == typeof(UIntPtr))
943 vt = (IntPtr.Size == 4 ? VarEnum.VT_UI4 : VarEnum.VT_UI8);
950 throw new ArgumentException(Environment.GetResourceString("Arg_NDirectBadObject"));
953 // marshal the object as C-style array (UnmanagedType.LPArray)
954 int dwArrayMarshalerFlags = (int)vt;
955 if (IsBestFit(dwFlags)) dwArrayMarshalerFlags |= (1 << 16);
956 if (IsThrowOn(dwFlags)) dwArrayMarshalerFlags |= (1 << 24);
958 MngdNativeArrayMarshaler.CreateMarshaler(
960 IntPtr.Zero, // not needed as we marshal primitive VTs only
961 dwArrayMarshalerFlags);
964 IntPtr pNativeHomeAddr = new IntPtr(&pNativeHome);
966 MngdNativeArrayMarshaler.ConvertSpaceToNative(
973 MngdNativeArrayMarshaler.ConvertContentsToNative(
980 backPropAction = BackPropAction.Array;
986 [System.Security.SecurityCritical]
987 private static IntPtr ConvertStringToNative(string pManagedHome, int dwFlags)
991 // IsIn, IsOut are ignored for strings - they're always in-only
994 // marshal the object as Ansi string (UnmanagedType.LPStr)
995 pNativeHome = CSTRMarshaler.ConvertToNative(
996 dwFlags & 0xFFFF, // (throw on unmappable char << 8 | best fit)
998 IntPtr.Zero); // unmanaged buffer will be allocated
1002 // marshal the object as Unicode string (UnmanagedType.LPWStr)
1003 StubHelpers.CheckStringLength(pManagedHome.Length);
1005 int allocSize = (pManagedHome.Length + 1) * 2;
1006 pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1008 String.InternalCopy(pManagedHome, pNativeHome, allocSize);
1014 [System.Security.SecurityCritical]
1015 private unsafe IntPtr ConvertStringBuilderToNative(StringBuilder pManagedHome, int dwFlags)
1019 // P/Invoke can be used to call Win32 apis that don't strictly follow CLR in/out semantics and thus may
1020 // leave garbage in the buffer in circumstances that we can't detect. To prevent us from crashing when
1021 // converting the contents back to managed, put a hidden NULL terminator past the end of the official buffer.
1023 // Unmanaged layout:
1024 // +====================================+
1025 // | Extra hidden NULL |
1026 // +====================================+ \
1028 // | [Converted] NULL-terminated string | |- buffer that the target may change
1030 // +====================================+ / <-- native home
1032 // Note that StringBuilder.Capacity is the number of characters NOT including any terminators.
1034 if (IsAnsi(dwFlags))
1036 StubHelpers.CheckStringLength(pManagedHome.Capacity);
1038 // marshal the object as Ansi string (UnmanagedType.LPStr)
1039 int allocSize = (pManagedHome.Capacity * Marshal.SystemMaxDBCSCharSize) + 4;
1040 pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1042 byte* ptr = (byte*)pNativeHome;
1043 *(ptr + allocSize - 3) = 0;
1044 *(ptr + allocSize - 2) = 0;
1045 *(ptr + allocSize - 1) = 0;
1051 byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(
1052 pManagedHome.ToString(),
1064 // null-terminate the native string
1065 *(ptr + length) = 0;
1069 backPropAction = BackPropAction.StringBuilderAnsi;
1074 // marshal the object as Unicode string (UnmanagedType.LPWStr)
1075 int allocSize = (pManagedHome.Capacity * 2) + 4;
1076 pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1078 byte* ptr = (byte*)pNativeHome;
1079 *(ptr + allocSize - 1) = 0;
1080 *(ptr + allocSize - 2) = 0;
1084 int length = pManagedHome.Length * 2;
1085 pManagedHome.InternalCopy(pNativeHome, length);
1087 // null-terminate the native string
1088 *(ptr + length + 0) = 0;
1089 *(ptr + length + 1) = 0;
1093 backPropAction = BackPropAction.StringBuilderUnicode;
1100 [System.Security.SecurityCritical]
1101 private unsafe IntPtr ConvertLayoutToNative(object pManagedHome, int dwFlags)
1103 // Note that the following call will not throw exception if the type
1104 // of pManagedHome is not marshalable. That's intentional because we
1105 // want to maintain the original behavior where this was indicated
1106 // by TypeLoadException during the actual field marshaling.
1107 int allocSize = Marshal.SizeOfHelper(pManagedHome.GetType(), false);
1108 IntPtr pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1110 // marshal the object as class with layout (UnmanagedType.LPStruct)
1113 StubHelpers.FmtClassUpdateNativeInternal(pManagedHome, (byte *)pNativeHome.ToPointer(), ref cleanupWorkList);
1117 backPropAction = BackPropAction.Layout;
1119 layoutType = pManagedHome.GetType();
1126 [System.Security.SecurityCritical]
1127 internal IntPtr ConvertToNative(object pManagedHome, int dwFlags)
1129 if (pManagedHome == null)
1132 if (pManagedHome is ArrayWithOffset)
1133 throw new ArgumentException(Environment.GetResourceString("Arg_MarshalAsAnyRestriction"));
1137 if (pManagedHome.GetType().IsArray)
1140 pNativeHome = ConvertArrayToNative(pManagedHome, dwFlags);
1145 StringBuilder sbValue;
1147 if ((strValue = pManagedHome as string) != null)
1149 // string (LPStr or LPWStr)
1150 pNativeHome = ConvertStringToNative(strValue, dwFlags);
1152 else if ((sbValue = pManagedHome as StringBuilder) != null)
1154 // StringBuilder (LPStr or LPWStr)
1155 pNativeHome = ConvertStringBuilderToNative(sbValue, dwFlags);
1157 else if (pManagedHome.GetType().IsLayoutSequential || pManagedHome.GetType().IsExplicitLayout)
1159 // layout (LPStruct)
1160 pNativeHome = ConvertLayoutToNative(pManagedHome, dwFlags);
1164 // this type is not supported for AsAny marshaling
1165 throw new ArgumentException(Environment.GetResourceString("Arg_NDirectBadObject"));
1172 [System.Security.SecurityCritical]
1173 internal unsafe void ConvertToManaged(object pManagedHome, IntPtr pNativeHome)
1175 switch (backPropAction)
1177 case BackPropAction.Array:
1179 MngdNativeArrayMarshaler.ConvertContentsToManaged(
1182 new IntPtr(&pNativeHome));
1186 case BackPropAction.Layout:
1188 StubHelpers.FmtClassUpdateCLRInternal(pManagedHome, (byte *)pNativeHome.ToPointer());
1192 case BackPropAction.StringBuilderAnsi:
1194 sbyte* ptr = (sbyte*)pNativeHome.ToPointer();
1195 ((StringBuilder)pManagedHome).ReplaceBufferAnsiInternal(ptr, Win32Native.lstrlenA(pNativeHome));
1199 case BackPropAction.StringBuilderUnicode:
1201 char* ptr = (char*)pNativeHome.ToPointer();
1202 ((StringBuilder)pManagedHome).ReplaceBufferInternal(ptr, Win32Native.lstrlenW(pNativeHome));
1206 // nothing to do for BackPropAction.None
1210 [System.Security.SecurityCritical]
1211 internal void ClearNative(IntPtr pNativeHome)
1213 if (pNativeHome != IntPtr.Zero)
1215 if (layoutType != null)
1217 // this must happen regardless of BackPropAction
1218 Marshal.DestroyStructure(pNativeHome, layoutType);
1220 Win32Native.CoTaskMemFree(pNativeHome);
1222 StubHelpers.DestroyCleanupList(ref cleanupWorkList);
1224 } // struct AsAnyMarshaler
1226 #if FEATURE_COMINTEROP
1227 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1228 internal static class NullableMarshaler
1231 static internal IntPtr ConvertToNative<T>(ref Nullable<T> pManaged) where T : struct
1233 if (pManaged.HasValue)
1235 object impl = IReferenceFactory.CreateIReference(pManaged);
1236 return Marshal.GetComInterfaceForObject(impl, typeof(IReference<T>));
1245 static internal void ConvertToManagedRetVoid<T>(IntPtr pNative, ref Nullable<T> retObj) where T : struct
1247 retObj = ConvertToManaged<T>(pNative);
1252 static internal Nullable<T> ConvertToManaged<T>(IntPtr pNative) where T : struct
1254 if (pNative != IntPtr.Zero)
1256 object wrapper = InterfaceMarshaler.ConvertToManagedWithoutUnboxing(pNative);
1257 return (Nullable<T>)CLRIReferenceImpl<T>.UnboxHelper(wrapper);
1261 return new Nullable<T>();
1264 } // class NullableMarshaler
1266 // Corresponds to Windows.UI.Xaml.Interop.TypeName
1267 [StructLayout(LayoutKind.Sequential)]
1268 internal struct TypeNameNative
1271 internal IntPtr typeName; // HSTRING
1272 internal TypeKind typeKind; // TypeKind enum
1275 // Corresponds to Windows.UI.Xaml.TypeSource
1276 internal enum TypeKind
1283 internal static class WinRTTypeNameConverter
1285 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1286 internal static extern string ConvertToWinRTTypeName(System.Type managedType, out bool isPrimitive);
1288 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1289 internal static extern System.Type GetTypeFromWinRTTypeName(string typeName, out bool isPrimitive);
1292 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1293 internal static class SystemTypeMarshaler
1296 internal static unsafe void ConvertToNative(System.Type managedType, TypeNameNative *pNativeType)
1298 if (!Environment.IsWinRTSupported)
1300 throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
1304 if (managedType != null)
1306 if (managedType.GetType() != typeof(System.RuntimeType))
1307 { // The type should be exactly System.RuntimeType (and not its child System.ReflectionOnlyType, or other System.Type children)
1308 throw new ArgumentException(Environment.GetResourceString("Argument_WinRTSystemRuntimeType", managedType.GetType().ToString()));
1312 string winrtTypeName = WinRTTypeNameConverter.ConvertToWinRTTypeName(managedType, out isPrimitive);
1313 if (winrtTypeName != null)
1315 // Must be a WinRT type, either in a WinMD or a Primitive
1316 typeName = winrtTypeName;
1318 pNativeType->typeKind = TypeKind.Primitive;
1320 pNativeType->typeKind = TypeKind.Metadata;
1325 typeName = managedType.AssemblyQualifiedName;
1326 pNativeType->typeKind = TypeKind.Projection;
1330 { // Marshal null as empty string + Projection
1332 pNativeType->typeKind = TypeKind.Projection;
1335 int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString(typeName, typeName.Length, &pNativeType->typeName);
1336 Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
1340 internal static unsafe void ConvertToManaged(TypeNameNative *pNativeType, ref System.Type managedType)
1342 if (!Environment.IsWinRTSupported)
1344 throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
1347 string typeName = WindowsRuntimeMarshal.HStringToString(pNativeType->typeName);
1348 if (String.IsNullOrEmpty(typeName))
1354 if (pNativeType->typeKind == TypeKind.Projection)
1356 managedType = Type.GetType(typeName, /* throwOnError = */ true);
1361 managedType = WinRTTypeNameConverter.GetTypeFromWinRTTypeName(typeName, out isPrimitive);
1363 // TypeSource must match
1364 if (isPrimitive != (pNativeType->typeKind == TypeKind.Primitive))
1365 throw new ArgumentException(Environment.GetResourceString("Argument_Unexpected_TypeSource"));
1370 internal static unsafe void ClearNative(TypeNameNative *pNativeType)
1372 Contract.Assert(Environment.IsWinRTSupported);
1374 if (pNativeType->typeName != null)
1376 System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString(pNativeType->typeName);
1379 } // class SystemTypeMarshaler
1381 // For converting WinRT's Windows.Foundation.HResult into System.Exception and vice versa.
1382 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1383 internal static class HResultExceptionMarshaler
1385 static internal unsafe int ConvertToNative(Exception ex)
1387 if (!Environment.IsWinRTSupported)
1389 throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
1398 [SecuritySafeCritical]
1399 static internal unsafe Exception ConvertToManaged(int hr)
1401 Contract.Ensures(Contract.Result<Exception>() != null || hr >= 0);
1403 if (!Environment.IsWinRTSupported)
1405 throw new PlatformNotSupportedException(Environment.GetResourceString("PlatformNotSupported_WinRT"));
1411 e = StubHelpers.InternalGetCOMHRExceptionObject(hr, IntPtr.Zero, null, /* fForWinRT */ true);
1414 // S_OK should be marshaled as null. WinRT API's should not return S_FALSE by convention.
1415 // We've chosen to treat S_FALSE as success and return null.
1416 Contract.Assert(e != null || hr == 0 || hr == 1, "Unexpected HRESULT - it is a success HRESULT (without the high bit set) other than S_OK & S_FALSE.");
1419 } // class HResultExceptionMarshaler
1421 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1422 internal static class KeyValuePairMarshaler
1425 internal static IntPtr ConvertToNative<K, V>([In] ref KeyValuePair<K, V> pair)
1427 IKeyValuePair<K, V> impl = new CLRIKeyValuePairImpl<K, V>(ref pair);
1428 return Marshal.GetComInterfaceForObject(impl, typeof(IKeyValuePair<K, V>));
1432 internal static KeyValuePair<K, V> ConvertToManaged<K, V>(IntPtr pInsp)
1434 object obj = InterfaceMarshaler.ConvertToManagedWithoutUnboxing(pInsp);
1436 IKeyValuePair<K, V> pair = (IKeyValuePair<K, V>)obj;
1437 return new KeyValuePair<K, V>(pair.Key, pair.Value);
1440 // Called from COMInterfaceMarshaler
1442 internal static object ConvertToManagedBox<K, V>(IntPtr pInsp)
1444 return (object)ConvertToManaged<K, V>(pInsp);
1446 } // class KeyValuePairMarshaler
1448 #endif // FEATURE_COMINTEROP
1450 [StructLayout(LayoutKind.Sequential)]
1451 internal struct NativeVariant
1458 // The union portion of the structure contains at least one 64-bit type that on some 32-bit platforms
1459 // (notably ARM) requires 64-bit alignment. So on 32-bit platforms we'll actually size the variant
1460 // portion of the struct with an Int64 so the type loader notices this requirement (a no-op on x86,
1461 // but on ARM it will allow us to correctly determine the layout of native argument lists containing
1462 // VARIANTs). Note that the field names here don't matter: none of the code refers to these fields,
1463 // the structure just exists to provide size information to the IL marshaler.
1470 } // struct NativeVariant
1472 #if !WIN64 && !FEATURE_CORECLR
1473 // Structure filled by IL stubs if copy constructor(s) and destructor(s) need to be called
1474 // on value types pushed on the stack. The structure is stored in s_copyCtorStubDesc by
1475 // SetCopyCtorCookieChain and fetched by CopyCtorCallStubWorker. Must be stack-allocated.
1476 [StructLayout(LayoutKind.Sequential)]
1477 unsafe internal struct CopyCtorStubCookie
1479 public void SetData(IntPtr srcInstancePtr, uint dstStackOffset, IntPtr ctorPtr, IntPtr dtorPtr)
1481 m_srcInstancePtr = srcInstancePtr;
1482 m_dstStackOffset = dstStackOffset;
1483 m_ctorPtr = ctorPtr;
1484 m_dtorPtr = dtorPtr;
1487 public void SetNext(IntPtr pNext)
1492 public IntPtr m_srcInstancePtr; // pointer to the source instance
1493 public uint m_dstStackOffset; // offset from the start of stack arguments of the pushed 'this' instance
1495 public IntPtr m_ctorPtr; // fnptr to the managed copy constructor, result of ldftn
1496 public IntPtr m_dtorPtr; // fnptr to the managed destructor, result of ldftn
1498 public IntPtr m_pNext; // pointer to next cookie in the chain or IntPtr.Zero
1499 } // struct CopyCtorStubCookie
1501 // Aggregates pointer to CopyCtorStubCookie and the target of the interop call.
1502 [StructLayout(LayoutKind.Sequential)]
1503 unsafe internal struct CopyCtorStubDesc
1505 public IntPtr m_pCookie;
1506 public IntPtr m_pTarget;
1507 } // struct CopyCtorStubDes
1508 #endif // !WIN64 && !FEATURE_CORECLR
1510 // Aggregates SafeHandle and the "owned" bit which indicates whether the SafeHandle
1511 // has been successfully AddRef'ed. This allows us to do realiable cleanup (Release)
1512 // if and only if it is needed.
1513 [System.Security.SecurityCritical]
1514 internal sealed class CleanupWorkListElement
1516 public CleanupWorkListElement(SafeHandle handle)
1521 public SafeHandle m_handle;
1523 // This field is passed by-ref to SafeHandle.DangerousAddRef.
1524 // CleanupWorkList.Destroy ignores this element if m_owned is not set to true.
1525 public bool m_owned;
1526 } // class CleanupWorkListElement
1528 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1529 [System.Security.SecurityCritical]
1530 internal sealed class CleanupWorkList
1532 private List<CleanupWorkListElement> m_list = new List<CleanupWorkListElement>();
1534 public void Add(CleanupWorkListElement elem)
1536 BCLDebug.Assert(elem.m_owned == false, "m_owned is supposed to be false and set later by DangerousAddRef");
1540 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
1541 public void Destroy()
1543 for (int i = m_list.Count - 1; i >= 0; i--)
1545 if (m_list[i].m_owned)
1546 StubHelpers.SafeHandleRelease(m_list[i].m_handle);
1549 } // class CleanupWorkList
1551 [System.Security.SecurityCritical] // auto-generated
1552 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
1553 [SuppressUnmanagedCodeSecurityAttribute()]
1554 internal static class StubHelpers
1556 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1557 static internal extern bool IsQCall(IntPtr pMD);
1559 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1560 static internal extern void InitDeclaringType(IntPtr pMD);
1562 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1563 static internal extern IntPtr GetNDirectTarget(IntPtr pMD);
1565 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1566 static internal extern IntPtr GetDelegateTarget(Delegate pThis, ref IntPtr pStubArg);
1568 #if !WIN64 && !FEATURE_CORECLR
1569 // Written to by a managed stub helper, read by CopyCtorCallStubWorker in VM.
1571 static CopyCtorStubDesc s_copyCtorStubDesc;
1573 static internal void SetCopyCtorCookieChain(IntPtr pStubArg, IntPtr pUnmngThis, int dwStubFlags, IntPtr pCookie)
1575 // we store both the cookie chain head and the target of the copy ctor stub to a thread
1576 // static field to be accessed by the copy ctor (see code:CopyCtorCallStubWorker)
1577 s_copyCtorStubDesc.m_pCookie = pCookie;
1578 s_copyCtorStubDesc.m_pTarget = GetFinalStubTarget(pStubArg, pUnmngThis, dwStubFlags);
1581 // Returns the final unmanaged stub target, ignores interceptors.
1582 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1583 static internal extern IntPtr GetFinalStubTarget(IntPtr pStubArg, IntPtr pUnmngThis, int dwStubFlags);
1584 #endif // !FEATURE_CORECLR && !WIN64
1586 #if !FEATURE_CORECLR
1587 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1588 static internal extern void DemandPermission(IntPtr pNMD);
1589 #endif // !FEATURE_CORECLR
1591 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1592 static internal extern void SetLastError();
1594 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1595 static internal extern void ThrowInteropParamException(int resID, int paramIdx);
1597 [System.Security.SecurityCritical]
1598 static internal IntPtr AddToCleanupList(ref CleanupWorkList pCleanupWorkList, SafeHandle handle)
1600 if (pCleanupWorkList == null)
1601 pCleanupWorkList = new CleanupWorkList();
1603 CleanupWorkListElement element = new CleanupWorkListElement(handle);
1604 pCleanupWorkList.Add(element);
1606 // element.m_owned will be true iff the AddRef succeeded
1607 return SafeHandleAddRef(handle, ref element.m_owned);
1610 [System.Security.SecurityCritical]
1611 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
1612 static internal void DestroyCleanupList(ref CleanupWorkList pCleanupWorkList)
1614 if (pCleanupWorkList != null)
1616 pCleanupWorkList.Destroy();
1617 pCleanupWorkList = null;
1621 static internal Exception GetHRExceptionObject(int hr)
1623 Exception ex = InternalGetHRExceptionObject(hr);
1624 ex.InternalPreserveStackTrace();
1628 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1629 static internal extern Exception InternalGetHRExceptionObject(int hr);
1631 #if FEATURE_COMINTEROP
1632 static internal Exception GetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object pThis)
1634 Exception ex = InternalGetCOMHRExceptionObject(hr, pCPCMD, pThis, false);
1635 ex.InternalPreserveStackTrace();
1639 static internal Exception GetCOMHRExceptionObject_WinRT(int hr, IntPtr pCPCMD, object pThis)
1641 Exception ex = InternalGetCOMHRExceptionObject(hr, pCPCMD, pThis, true);
1642 ex.InternalPreserveStackTrace();
1646 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1647 static internal extern Exception InternalGetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object pThis, bool fForWinRT);
1649 #endif // FEATURE_COMINTEROP
1651 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1652 static internal extern IntPtr CreateCustomMarshalerHelper(IntPtr pMD, int paramToken, IntPtr hndManagedType);
1654 //-------------------------------------------------------
1655 // SafeHandle Helpers
1656 //-------------------------------------------------------
1658 // AddRefs the SH and returns the underlying unmanaged handle.
1659 [System.Security.SecurityCritical] // auto-generated
1660 static internal IntPtr SafeHandleAddRef(SafeHandle pHandle, ref bool success)
1662 if (pHandle == null)
1664 throw new ArgumentNullException(Environment.GetResourceString("ArgumentNull_SafeHandle"));
1666 Contract.EndContractBlock();
1668 pHandle.DangerousAddRef(ref success);
1670 return (success ? pHandle.DangerousGetHandle() : IntPtr.Zero);
1673 // Releases the SH (to be called from finally block).
1674 [System.Security.SecurityCritical] // auto-generated
1675 [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
1676 static internal void SafeHandleRelease(SafeHandle pHandle)
1678 if (pHandle == null)
1680 throw new ArgumentNullException(Environment.GetResourceString("ArgumentNull_SafeHandle"));
1682 Contract.EndContractBlock();
1686 pHandle.DangerousRelease();
1689 catch (Exception ex)
1691 Mda.ReportErrorSafeHandleRelease(ex);
1693 #else // MDA_SUPPORTED
1696 #endif // MDA_SUPPORTED
1699 #if FEATURE_COMINTEROP
1700 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1701 static internal extern IntPtr GetCOMIPFromRCW(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget, out bool pfNeedsRelease);
1703 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1704 static internal extern IntPtr GetCOMIPFromRCW_WinRT(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
1706 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1707 static internal extern IntPtr GetCOMIPFromRCW_WinRTSharedGeneric(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
1709 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1710 static internal extern IntPtr GetCOMIPFromRCW_WinRTDelegate(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
1712 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1713 static internal extern bool ShouldCallWinRTInterface(object objSrc, IntPtr pCPCMD);
1715 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1716 static internal extern Delegate GetTargetForAmbiguousVariantCall(object objSrc, IntPtr pMT, out bool fUseString);
1718 //-------------------------------------------------------
1719 // Helper for the MDA ----OnRCWCleanup
1720 //-------------------------------------------------------
1722 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1723 static internal extern void StubRegisterRCW(object pThis);
1725 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1726 static internal extern void StubUnregisterRCW(object pThis);
1728 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1729 static internal extern IntPtr GetDelegateInvokeMethod(Delegate pThis);
1731 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1732 [System.Security.SecurityCritical]
1733 static internal extern object GetWinRTFactoryObject(IntPtr pCPCMD);
1735 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1736 [System.Security.SecurityCritical]
1737 static internal extern IntPtr GetWinRTFactoryReturnValue(object pThis, IntPtr pCtorEntry);
1739 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1740 [System.Security.SecurityCritical]
1741 static internal extern IntPtr GetOuterInspectable(object pThis, IntPtr pCtorMD);
1744 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1745 static internal extern Exception TriggerExceptionSwallowedMDA(Exception ex, IntPtr pManagedTarget);
1746 #endif // MDA_SUPPORTED
1748 #endif // FEATURE_COMINTEROP
1751 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1752 static internal extern void CheckCollectedDelegateMDA(IntPtr pEntryThunk);
1753 #endif // MDA_SUPPORTED
1755 //-------------------------------------------------------
1757 //-------------------------------------------------------
1758 #if PROFILING_SUPPORTED
1759 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1760 static internal extern IntPtr ProfilerBeginTransitionCallback(IntPtr pSecretParam, IntPtr pThread, object pThis);
1762 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1763 static internal extern void ProfilerEndTransitionCallback(IntPtr pMD, IntPtr pThread);
1764 #endif // PROFILING_SUPPORTED
1766 //------------------------------------------------------
1768 //------------------------------------------------------
1769 static internal void CheckStringLength(int length)
1771 CheckStringLength((uint)length);
1774 static internal void CheckStringLength(uint length)
1776 if (length > 0x7ffffff0)
1778 throw new MarshalDirectiveException(Environment.GetResourceString("Marshaler_StringTooLong"));
1782 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1783 static internal unsafe extern int strlen(sbyte* ptr);
1785 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1786 static internal extern void DecimalCanonicalizeInternal(ref Decimal dec);
1788 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1789 static internal unsafe extern void FmtClassUpdateNativeInternal(object obj, byte* pNative, ref CleanupWorkList pCleanupWorkList);
1790 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1791 static internal unsafe extern void FmtClassUpdateCLRInternal(object obj, byte* pNative);
1792 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1793 static internal unsafe extern void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
1794 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1795 static internal extern object AllocateInternal(IntPtr typeHandle);
1797 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1798 static internal extern void MarshalToUnmanagedVaListInternal(IntPtr va_list, uint vaListSize, IntPtr pArgIterator);
1800 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1801 static internal extern void MarshalToManagedVaListInternal(IntPtr va_list, IntPtr pArgIterator);
1803 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1804 static internal extern uint CalcVaListSize(IntPtr va_list);
1806 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1807 static internal extern void ValidateObject(object obj, IntPtr pMD, object pThis);
1809 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1810 static internal extern void LogPinnedArgument(IntPtr localDesc, IntPtr nativeArg);
1812 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1813 static internal extern void ValidateByref(IntPtr byref, IntPtr pMD, object pThis); // the byref is pinned so we can safely "cast" it to IntPtr
1815 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1816 static internal extern IntPtr GetStubContext();
1819 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1820 static internal extern IntPtr GetStubContextAddr();
1824 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1825 static internal extern void TriggerGCForMDA();
1826 #endif // MDA_SUPPORTED
1828 #if FEATURE_ARRAYSTUB_AS_IL
1829 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1830 internal static extern void ArrayTypeCheck(object o, Object[] arr);
1833 #if FEATURE_STUBS_AS_IL
1834 [MethodImplAttribute(MethodImplOptions.InternalCall)]
1835 internal static extern void MulticastDebuggerTraceHelper(object o, Int32 count);
1837 } // class StubHelpers