Delete FriendAccessAllowedAttribute and associated dead code (#15101)
[platform/upstream/coreclr.git] / src / mscorlib / src / System / StubHelpers.cs
1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
4
5
6 namespace System.StubHelpers
7 {
8     using System.Text;
9     using Microsoft.Win32;
10     using System.Security;
11     using System.Collections.Generic;
12     using System.Runtime;
13     using System.Runtime.InteropServices;
14 #if FEATURE_COMINTEROP
15     using System.Runtime.InteropServices.WindowsRuntime;
16 #endif // FEATURE_COMINTEROP
17     using System.Runtime.CompilerServices;
18     using System.Runtime.ConstrainedExecution;
19     using System.Diagnostics;
20
21     internal static class AnsiCharMarshaler
22     {
23         // The length of the returned array is an approximation based on the length of the input string and the system
24         // character set. It is only guaranteed to be larger or equal to cbLength, don't depend on the exact value.
25         unsafe static internal byte[] DoAnsiConversion(string str, bool fBestFit, bool fThrowOnUnmappableChar, out int cbLength)
26         {
27             byte[] buffer = new byte[(str.Length + 1) * Marshal.SystemMaxDBCSCharSize];
28             Debug.Assert(buffer.Length != 0);
29             fixed (byte* bufferPtr = &buffer[0])
30             {
31                 cbLength = str.ConvertToAnsi(bufferPtr, buffer.Length, fBestFit, fThrowOnUnmappableChar);
32             }
33             return buffer;
34         }
35
36         unsafe static internal byte ConvertToNative(char managedChar, bool fBestFit, bool fThrowOnUnmappableChar)
37         {
38             int cbAllocLength = (1 + 1) * Marshal.SystemMaxDBCSCharSize;
39             byte* bufferPtr = stackalloc byte[cbAllocLength];
40
41             int cbLength = managedChar.ToString().ConvertToAnsi(bufferPtr, cbAllocLength, fBestFit, fThrowOnUnmappableChar);
42
43             Debug.Assert(cbLength > 0, "Zero bytes returned from DoAnsiConversion in AnsiCharMarshaler.ConvertToNative");
44             return bufferPtr[0];
45         }
46
47         static internal char ConvertToManaged(byte nativeChar)
48         {
49             byte[] bytes = new byte[1] { nativeChar };
50             string str = Encoding.Default.GetString(bytes);
51             return str[0];
52         }
53     }  // class AnsiCharMarshaler
54
55     internal static class CSTRMarshaler
56     {
57         static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer)
58         {
59             if (null == strManaged)
60             {
61                 return IntPtr.Zero;
62             }
63
64             StubHelpers.CheckStringLength(strManaged.Length);
65
66             int nb;
67             byte* pbNativeBuffer = (byte*)pNativeBuffer;
68
69             if (pbNativeBuffer != null || Marshal.SystemMaxDBCSCharSize == 1)
70             {
71                 // If we are marshaling into a stack buffer or we can accurately estimate the size of the required heap
72                 // space, we will use a "1-pass" mode where we convert the string directly into the unmanaged buffer.
73
74                 // + 1 for the null character from the user
75                 nb = (strManaged.Length + 1) * Marshal.SystemMaxDBCSCharSize;
76
77                 // Use the pre-allocated buffer (allocated by localloc IL instruction) if not NULL, 
78                 // otherwise fallback to AllocCoTaskMem
79                 if (pbNativeBuffer == null)
80                 {
81                     // + 1 for the null character we put in
82                     pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 1);
83                 }
84
85                 nb = strManaged.ConvertToAnsi(pbNativeBuffer, nb + 1, 0 != (flags & 0xFF), 0 != (flags >> 8));
86             }
87             else
88             {
89                 // Otherwise we use a slower "2-pass" mode where we first marshal the string into an intermediate buffer
90                 // (managed byte array) and then allocate exactly the right amount of unmanaged memory. This is to avoid
91                 // wasting memory on systems with multibyte character sets where the buffer we end up with is often much
92                 // smaller than the upper bound for the given managed string.
93
94                 byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xFF), 0 != (flags >> 8), out nb);
95
96                 // + 1 for the null character from the user.  + 1 for the null character we put in.
97                 pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 2);
98
99                 Buffer.Memcpy(pbNativeBuffer, 0, bytes, 0, nb);
100             }
101
102             pbNativeBuffer[nb] = 0x00;
103             pbNativeBuffer[nb + 1] = 0x00;
104
105             return (IntPtr)pbNativeBuffer;
106         }
107
108         static internal unsafe string ConvertToManaged(IntPtr cstr)
109         {
110             if (IntPtr.Zero == cstr)
111                 return null;
112             else
113                 return new String((sbyte*)cstr);
114         }
115
116         static internal void ClearNative(IntPtr pNative)
117         {
118             Win32Native.CoTaskMemFree(pNative);
119         }
120     }  // class CSTRMarshaler
121
122     internal static class UTF8Marshaler
123     {
124         private const int MAX_UTF8_CHAR_SIZE = 3;
125         static internal unsafe IntPtr ConvertToNative(int flags, string strManaged, IntPtr pNativeBuffer)
126         {
127             if (null == strManaged)
128             {
129                 return IntPtr.Zero;
130             }
131             StubHelpers.CheckStringLength(strManaged.Length);
132
133             int nb;
134             byte* pbNativeBuffer = (byte*)pNativeBuffer;
135
136             // If we are marshaling into a stack buffer allocated by the ILStub
137             // we will use a "1-pass" mode where we convert the string directly into the unmanaged buffer.   
138             // else we will allocate the precise native heap memory.
139             if (pbNativeBuffer != null)
140             {
141                 // this is the number of bytes allocated by the ILStub.
142                 nb = (strManaged.Length + 1) * MAX_UTF8_CHAR_SIZE;
143
144                 // nb is the actual number of bytes written by Encoding.GetBytes.
145                 // use nb to de-limit the string since we are allocating more than 
146                 // required on stack
147                 nb = strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
148             }
149             // required bytes > 260 , allocate required bytes on heap
150             else
151             {
152                 nb = Encoding.UTF8.GetByteCount(strManaged);
153                 // + 1 for the null character.
154                 pbNativeBuffer = (byte*)Marshal.AllocCoTaskMem(nb + 1);
155                 strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
156             }
157             pbNativeBuffer[nb] = 0x0;
158             return (IntPtr)pbNativeBuffer;
159         }
160
161         static internal unsafe string ConvertToManaged(IntPtr cstr)
162         {
163             if (IntPtr.Zero == cstr)
164                 return null;
165             int nbBytes = StubHelpers.strlen((sbyte*)cstr);
166             return String.CreateStringFromEncoding((byte*)cstr, nbBytes, Encoding.UTF8);
167         }
168
169         static internal void ClearNative(IntPtr pNative)
170         {
171             if (pNative != IntPtr.Zero)
172             {
173                 Win32Native.CoTaskMemFree(pNative);
174             }
175         }
176     }
177
178     internal static class UTF8BufferMarshaler
179     {
180         static internal unsafe IntPtr ConvertToNative(StringBuilder sb, IntPtr pNativeBuffer, int flags)
181         {
182             if (null == sb)
183             {
184                 return IntPtr.Zero;
185             }
186
187             // Convert to string first  
188             string strManaged = sb.ToString();
189
190             // Get byte count 
191             int nb = Encoding.UTF8.GetByteCount(strManaged);
192
193             // EmitConvertSpaceCLRToNative allocates memory
194             byte* pbNativeBuffer = (byte*)pNativeBuffer;
195             nb = strManaged.GetBytesFromEncoding(pbNativeBuffer, nb, Encoding.UTF8);
196
197             pbNativeBuffer[nb] = 0x0;
198             return (IntPtr)pbNativeBuffer;
199         }
200
201         static internal unsafe void ConvertToManaged(StringBuilder sb, IntPtr pNative)
202         {
203             if (pNative == null)
204                 return;
205
206             int nbBytes = StubHelpers.strlen((sbyte*)pNative);
207             int numChar = Encoding.UTF8.GetCharCount((byte*)pNative, nbBytes);
208
209             // +1 GetCharCount return 0 if the pNative points to a 
210             // an empty buffer.We still need to allocate an empty 
211             // buffer with a '\0' to distingiush it from null.
212             // Note that pinning on (char *pinned = new char[0])
213             // return null and  Encoding.UTF8.GetChars do not like 
214             // null argument.
215             char[] cCharBuffer = new char[numChar + 1];
216             cCharBuffer[numChar] = '\0';
217             fixed (char* pBuffer = &cCharBuffer[0])
218             {
219                 numChar = Encoding.UTF8.GetChars((byte*)pNative, nbBytes, pBuffer, numChar);
220                 // replace string builder internal buffer
221                 sb.ReplaceBufferInternal(pBuffer, numChar);
222             }
223         }
224     }
225
226 #if FEATURE_COMINTEROP
227
228     internal static class BSTRMarshaler
229     {
230         static internal unsafe IntPtr ConvertToNative(string strManaged, IntPtr pNativeBuffer)
231         {
232             if (null == strManaged)
233             {
234                 return IntPtr.Zero;
235             }
236             else
237             {
238                 StubHelpers.CheckStringLength(strManaged.Length);
239
240                 byte trailByte;
241                 bool hasTrailByte = strManaged.TryGetTrailByte(out trailByte);
242
243                 uint lengthInBytes = (uint)strManaged.Length * 2;
244
245                 if (hasTrailByte)
246                 {
247                     // this is an odd-sized string with a trailing byte stored in its sync block
248                     lengthInBytes++;
249                 }
250
251                 byte* ptrToFirstChar;
252
253                 if (pNativeBuffer != IntPtr.Zero)
254                 {
255                     // If caller provided a buffer, construct the BSTR manually. The size
256                     // of the buffer must be at least (lengthInBytes + 6) bytes.
257 #if DEBUG
258                     uint length = *((uint*)pNativeBuffer.ToPointer());
259                     Debug.Assert(length >= lengthInBytes + 6, "BSTR localloc'ed buffer is too small");
260 #endif
261
262                     // set length
263                     *((uint*)pNativeBuffer.ToPointer()) = lengthInBytes;
264
265                     ptrToFirstChar = (byte*)pNativeBuffer.ToPointer() + 4;
266                 }
267                 else
268                 {
269                     // If not provided, allocate the buffer using SysAllocStringByteLen so
270                     // that odd-sized strings will be handled as well.
271                     ptrToFirstChar = (byte*)Win32Native.SysAllocStringByteLen(null, lengthInBytes).ToPointer();
272
273                     if (ptrToFirstChar == null)
274                     {
275                         throw new OutOfMemoryException();
276                     }
277                 }
278
279                 // copy characters from the managed string
280                 fixed (char* ch = strManaged)
281                 {
282                     Buffer.Memcpy(
283                         ptrToFirstChar,
284                         (byte*)ch,
285                         (strManaged.Length + 1) * 2);
286                 }
287
288                 // copy the trail byte if present
289                 if (hasTrailByte)
290                 {
291                     ptrToFirstChar[lengthInBytes - 1] = trailByte;
292                 }
293
294                 // return ptr to first character
295                 return (IntPtr)ptrToFirstChar;
296             }
297         }
298
299         static internal unsafe string ConvertToManaged(IntPtr bstr)
300         {
301             if (IntPtr.Zero == bstr)
302             {
303                 return null;
304             }
305             else
306             {
307                 uint length = Win32Native.SysStringByteLen(bstr);
308
309                 // Intentionally checking the number of bytes not characters to match the behavior
310                 // of ML marshalers. This prevents roundtripping of very large strings as the check
311                 // in the managed->native direction is done on String length but considering that
312                 // it's completely moot on 32-bit and not expected to be important on 64-bit either,
313                 // the ability to catch random garbage in the BSTR's length field outweighs this
314                 // restriction. If an ordinary null-terminated string is passed instead of a BSTR,
315                 // chances are that the length field - possibly being unallocated memory - contains
316                 // a heap fill pattern that will have the highest bit set, caught by the check.
317                 StubHelpers.CheckStringLength(length);
318
319                 string ret;
320                 if (length == 1)
321                 {
322                     // In the empty string case, we need to use FastAllocateString rather than the
323                     // String .ctor, since newing up a 0 sized string will always return String.Emtpy.
324                     // When we marshal that out as a bstr, it can wind up getting modified which
325                     // corrupts String.Empty.
326                     ret = String.FastAllocateString(0);
327                 }
328                 else
329                 {
330                     ret = new String((char*)bstr, 0, (int)(length / 2));
331                 }
332
333                 if ((length & 1) == 1)
334                 {
335                     // odd-sized strings need to have the trailing byte saved in their sync block
336                     ret.SetTrailByte(((byte*)bstr.ToPointer())[length - 1]);
337                 }
338
339                 return ret;
340             }
341         }
342
343         static internal void ClearNative(IntPtr pNative)
344         {
345             if (IntPtr.Zero != pNative)
346             {
347                 Win32Native.SysFreeString(pNative);
348             }
349         }
350     }  // class BSTRMarshaler
351
352 #endif // FEATURE_COMINTEROP
353
354
355     internal static class VBByValStrMarshaler
356     {
357         static internal unsafe IntPtr ConvertToNative(string strManaged, bool fBestFit, bool fThrowOnUnmappableChar, ref int cch)
358         {
359             if (null == strManaged)
360             {
361                 return IntPtr.Zero;
362             }
363
364             byte* pNative;
365
366             cch = strManaged.Length;
367
368             StubHelpers.CheckStringLength(cch);
369
370             // length field at negative offset + (# of characters incl. the terminator) * max ANSI char size
371             int nbytes = sizeof(uint) + ((cch + 1) * Marshal.SystemMaxDBCSCharSize);
372
373             pNative = (byte*)Marshal.AllocCoTaskMem(nbytes);
374             int* pLength = (int*)pNative;
375
376             pNative = pNative + sizeof(uint);
377
378             if (0 == cch)
379             {
380                 *pNative = 0;
381                 *pLength = 0;
382             }
383             else
384             {
385                 int nbytesused;
386                 byte[] bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, fBestFit, fThrowOnUnmappableChar, out nbytesused);
387
388                 Debug.Assert(nbytesused < nbytes, "Insufficient buffer allocated in VBByValStrMarshaler.ConvertToNative");
389                 Buffer.Memcpy(pNative, 0, bytes, 0, nbytesused);
390
391                 pNative[nbytesused] = 0;
392                 *pLength = nbytesused;
393             }
394
395             return new IntPtr(pNative);
396         }
397
398         static internal unsafe string ConvertToManaged(IntPtr pNative, int cch)
399         {
400             if (IntPtr.Zero == pNative)
401             {
402                 return null;
403             }
404
405             return new String((sbyte*)pNative, 0, cch);
406         }
407
408         static internal unsafe void ClearNative(IntPtr pNative)
409         {
410             if (IntPtr.Zero != pNative)
411             {
412                 Win32Native.CoTaskMemFree((IntPtr)(((long)pNative) - sizeof(uint)));
413             }
414         }
415     }  // class VBByValStrMarshaler
416
417
418 #if FEATURE_COMINTEROP
419
420     internal static class AnsiBSTRMarshaler
421     {
422         static internal unsafe IntPtr ConvertToNative(int flags, string strManaged)
423         {
424             if (null == strManaged)
425             {
426                 return IntPtr.Zero;
427             }
428
429             int length = strManaged.Length;
430
431             StubHelpers.CheckStringLength(length);
432
433             byte[] bytes = null;
434             int nb = 0;
435
436             if (length > 0)
437             {
438                 bytes = AnsiCharMarshaler.DoAnsiConversion(strManaged, 0 != (flags & 0xFF), 0 != (flags >> 8), out nb);
439             }
440
441             return Win32Native.SysAllocStringByteLen(bytes, (uint)nb);
442         }
443
444         static internal unsafe string ConvertToManaged(IntPtr bstr)
445         {
446             if (IntPtr.Zero == bstr)
447             {
448                 return null;
449             }
450             else
451             {
452                 // We intentionally ignore the length field of the BSTR for back compat reasons.
453                 // Unfortunately VB.NET uses Ansi BSTR marshaling when a string is passed ByRef
454                 // and we cannot afford to break this common scenario.
455                 return new String((sbyte*)bstr);
456             }
457         }
458
459         static internal unsafe void ClearNative(IntPtr pNative)
460         {
461             if (IntPtr.Zero != pNative)
462             {
463                 Win32Native.SysFreeString(pNative);
464             }
465         }
466     }  // class AnsiBSTRMarshaler
467
468 #endif // FEATURE_COMINTEROP
469
470
471     internal static class WSTRBufferMarshaler
472     {
473         static internal IntPtr ConvertToNative(string strManaged)
474         {
475             Debug.Fail("NYI");
476             return IntPtr.Zero;
477         }
478
479         static internal unsafe string ConvertToManaged(IntPtr bstr)
480         {
481             Debug.Fail("NYI");
482             return null;
483         }
484
485         static internal void ClearNative(IntPtr pNative)
486         {
487             Debug.Fail("NYI");
488         }
489     }  // class WSTRBufferMarshaler
490
491
492 #if FEATURE_COMINTEROP
493
494
495     [StructLayout(LayoutKind.Sequential)]
496     internal struct DateTimeNative
497     {
498         public Int64 UniversalTime;
499     };
500
501     internal static class DateTimeOffsetMarshaler
502     {
503         // Numer of ticks counted between 0001-01-01, 00:00:00 and 1601-01-01, 00:00:00.
504         // You can get this through:  (new DateTimeOffset(1601, 1, 1, 0, 0, 1, TimeSpan.Zero)).Ticks;
505         private const Int64 ManagedUtcTicksAtNativeZero = 504911232000000000;
506
507         internal static void ConvertToNative(ref DateTimeOffset managedDTO, out DateTimeNative dateTime)
508         {
509             Int64 managedUtcTicks = managedDTO.UtcTicks;
510             dateTime.UniversalTime = managedUtcTicks - ManagedUtcTicksAtNativeZero;
511         }
512
513         internal static void ConvertToManaged(out DateTimeOffset managedLocalDTO, ref DateTimeNative nativeTicks)
514         {
515             Int64 managedUtcTicks = ManagedUtcTicksAtNativeZero + nativeTicks.UniversalTime;
516             DateTimeOffset managedUtcDTO = new DateTimeOffset(managedUtcTicks, TimeSpan.Zero);
517
518             // Some Utc times cannot be represented in local time in certain timezones. E.g. 0001-01-01 12:00:00 AM cannot 
519             // be represented in any timezones with a negative offset from Utc. We throw an ArgumentException in that case.
520             managedLocalDTO = managedUtcDTO.ToLocalTime(true);
521         }
522     }  // class DateTimeOffsetMarshaler
523
524 #endif  // FEATURE_COMINTEROP
525
526
527 #if FEATURE_COMINTEROP
528     internal static class HStringMarshaler
529     {
530         // Slow-path, which requires making a copy of the managed string into the resulting HSTRING
531         internal static unsafe IntPtr ConvertToNative(string managed)
532         {
533             if (!Environment.IsWinRTSupported)
534                 throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT);
535             if (managed == null)
536                 throw new ArgumentNullException(); // We don't have enough information to get the argument name 
537
538             IntPtr hstring;
539             int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString(managed, managed.Length, &hstring);
540             Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
541             return hstring;
542         }
543
544         // Fast-path, which creates a reference over a pinned managed string.  This may only be used if the
545         // pinned string and HSTRING_HEADER will outlive the HSTRING produced (for instance, as an in parameter).
546         //
547         // Note that the managed string input to this method MUST be pinned, and stay pinned for the lifetime of
548         // the returned HSTRING object.  If the string is not pinned, or becomes unpinned before the HSTRING's
549         // lifetime ends, the HSTRING instance will be corrupted.
550         internal static unsafe IntPtr ConvertToNativeReference(string managed,
551                                                                [Out] HSTRING_HEADER* hstringHeader)
552         {
553             if (!Environment.IsWinRTSupported)
554                 throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT);
555             if (managed == null)
556                 throw new ArgumentNullException();  // We don't have enough information to get the argument name 
557
558             // The string must also be pinned by the caller to ConvertToNativeReference, which also owns
559             // the HSTRING_HEADER.
560             fixed (char* pManaged = managed)
561             {
562                 IntPtr hstring;
563                 int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateStringReference(pManaged, managed.Length, hstringHeader, &hstring);
564                 Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
565                 return hstring;
566             }
567         }
568
569         internal static string ConvertToManaged(IntPtr hstring)
570         {
571             if (!Environment.IsWinRTSupported)
572             {
573                 throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT);
574             }
575
576             return WindowsRuntimeMarshal.HStringToString(hstring);
577         }
578
579         internal static void ClearNative(IntPtr hstring)
580         {
581             Debug.Assert(Environment.IsWinRTSupported);
582
583             if (hstring != IntPtr.Zero)
584             {
585                 System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString(hstring);
586             }
587         }
588     }  // class HStringMarshaler
589
590     internal static class ObjectMarshaler
591     {
592         [MethodImplAttribute(MethodImplOptions.InternalCall)]
593         static internal extern void ConvertToNative(object objSrc, IntPtr pDstVariant);
594
595         [MethodImplAttribute(MethodImplOptions.InternalCall)]
596         static internal extern object ConvertToManaged(IntPtr pSrcVariant);
597
598         [MethodImplAttribute(MethodImplOptions.InternalCall)]
599         static internal extern void ClearNative(IntPtr pVariant);
600     }  // class ObjectMarshaler
601
602 #endif // FEATURE_COMINTEROP
603
604     internal static class ValueClassMarshaler
605     {
606         [MethodImplAttribute(MethodImplOptions.InternalCall)]
607         static internal extern void ConvertToNative(IntPtr dst, IntPtr src, IntPtr pMT, ref CleanupWorkList pCleanupWorkList);
608
609         [MethodImplAttribute(MethodImplOptions.InternalCall)]
610         static internal extern void ConvertToManaged(IntPtr dst, IntPtr src, IntPtr pMT);
611
612         [MethodImplAttribute(MethodImplOptions.InternalCall)]
613         static internal extern void ClearNative(IntPtr dst, IntPtr pMT);
614     }  // class ValueClassMarshaler
615
616     internal static class DateMarshaler
617     {
618         [MethodImplAttribute(MethodImplOptions.InternalCall)]
619         static internal extern double ConvertToNative(DateTime managedDate);
620
621         // The return type is really DateTime but we use long to avoid the pain associated with returning structures.
622         [MethodImplAttribute(MethodImplOptions.InternalCall)]
623         static internal extern long ConvertToManaged(double nativeDate);
624     }  // class DateMarshaler
625
626 #if FEATURE_COMINTEROP
627     // [FriendAccessAllowed]
628     internal static class InterfaceMarshaler
629     {
630         [MethodImplAttribute(MethodImplOptions.InternalCall)]
631         static internal extern IntPtr ConvertToNative(object objSrc, IntPtr itfMT, IntPtr classMT, int flags);
632
633         [MethodImplAttribute(MethodImplOptions.InternalCall)]
634         static internal extern object ConvertToManaged(IntPtr pUnk, IntPtr itfMT, IntPtr classMT, int flags);
635
636         [DllImport(JitHelpers.QCall)]
637         static internal extern void ClearNative(IntPtr pUnk);
638
639         // [FriendAccessAllowed]
640         [MethodImplAttribute(MethodImplOptions.InternalCall)]
641         static internal extern object ConvertToManagedWithoutUnboxing(IntPtr pNative);
642     }  // class InterfaceMarshaler
643 #endif // FEATURE_COMINTEROP
644
645 #if FEATURE_COMINTEROP
646     internal static class UriMarshaler
647     {
648         [MethodImplAttribute(MethodImplOptions.InternalCall)]
649         static internal extern string GetRawUriFromNative(IntPtr pUri);
650
651         [MethodImplAttribute(MethodImplOptions.InternalCall)]
652         static unsafe internal extern IntPtr CreateNativeUriInstanceHelper(char* rawUri, int strLen);
653
654         static unsafe internal IntPtr CreateNativeUriInstance(string rawUri)
655         {
656             fixed (char* pManaged = rawUri)
657             {
658                 return CreateNativeUriInstanceHelper(pManaged, rawUri.Length);
659             }
660         }
661     }  // class InterfaceMarshaler
662
663     // [FriendAccessAllowed]
664     internal static class EventArgsMarshaler
665     {
666         // [FriendAccessAllowed]
667         static internal IntPtr CreateNativeNCCEventArgsInstance(int action, object newItems, object oldItems, int newIndex, int oldIndex)
668         {
669             IntPtr newItemsIP = IntPtr.Zero;
670             IntPtr oldItemsIP = IntPtr.Zero;
671
672             RuntimeHelpers.PrepareConstrainedRegions();
673             try
674             {
675                 if (newItems != null)
676                     newItemsIP = Marshal.GetComInterfaceForObject(newItems, typeof(IBindableVector));
677                 if (oldItems != null)
678                     oldItemsIP = Marshal.GetComInterfaceForObject(oldItems, typeof(IBindableVector));
679
680                 return CreateNativeNCCEventArgsInstanceHelper(action, newItemsIP, oldItemsIP, newIndex, oldIndex);
681             }
682             finally
683             {
684                 if (!oldItemsIP.IsNull())
685                     Marshal.Release(oldItemsIP);
686                 if (!newItemsIP.IsNull())
687                     Marshal.Release(newItemsIP);
688             }
689         }
690
691         // [FriendAccessAllowed]
692         [DllImport(JitHelpers.QCall)]
693         static extern internal IntPtr CreateNativePCEventArgsInstance([MarshalAs(UnmanagedType.HString)]string name);
694
695         [DllImport(JitHelpers.QCall)]
696         static extern internal IntPtr CreateNativeNCCEventArgsInstanceHelper(int action, IntPtr newItem, IntPtr oldItem, int newIndex, int oldIndex);
697     }
698 #endif // FEATURE_COMINTEROP
699
700     internal static class MngdNativeArrayMarshaler
701     {
702         // Needs to match exactly with MngdNativeArrayMarshaler in ilmarshalers.h
703         internal struct MarshalerState
704         {
705             IntPtr m_pElementMT;
706             IntPtr m_Array;
707             int m_NativeDataValid;
708             int m_BestFitMap;
709             int m_ThrowOnUnmappableChar;
710             short m_vt;
711         }
712
713         [MethodImplAttribute(MethodImplOptions.InternalCall)]
714         static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int dwFlags);
715
716         [MethodImplAttribute(MethodImplOptions.InternalCall)]
717         static internal extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
718
719         [MethodImplAttribute(MethodImplOptions.InternalCall)]
720         static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
721
722         [MethodImplAttribute(MethodImplOptions.InternalCall)]
723         static internal extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome,
724                                                           int cElements);
725
726         [MethodImplAttribute(MethodImplOptions.InternalCall)]
727         static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
728
729         [MethodImplAttribute(MethodImplOptions.InternalCall)]
730         static internal extern void ClearNative(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
731
732         [MethodImplAttribute(MethodImplOptions.InternalCall)]
733         static internal extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
734     }  // class MngdNativeArrayMarshaler
735
736 #if FEATURE_COMINTEROP
737     internal static class MngdSafeArrayMarshaler
738     {
739         [MethodImplAttribute(MethodImplOptions.InternalCall)]
740         static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, int iRank, int dwFlags);
741
742         [MethodImplAttribute(MethodImplOptions.InternalCall)]
743         static internal extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
744
745         [MethodImplAttribute(MethodImplOptions.InternalCall)]
746         static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, object pOriginalManaged);
747
748         [MethodImplAttribute(MethodImplOptions.InternalCall)]
749         static internal extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
750
751         [MethodImplAttribute(MethodImplOptions.InternalCall)]
752         static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
753
754         [MethodImplAttribute(MethodImplOptions.InternalCall)]
755         static internal extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
756     }  // class MngdSafeArrayMarshaler
757
758     internal static class MngdHiddenLengthArrayMarshaler
759     {
760         [MethodImplAttribute(MethodImplOptions.InternalCall)]
761         static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pMT, IntPtr cbElementSize, ushort vt);
762
763         [MethodImplAttribute(MethodImplOptions.InternalCall)]
764         internal static extern void ConvertSpaceToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
765
766         [MethodImplAttribute(MethodImplOptions.InternalCall)]
767         internal static extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
768
769         internal static unsafe void ConvertContentsToNative_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome)
770         {
771             if (managedArray != null)
772             {
773                 DateTimeNative* nativeBuffer = *(DateTimeNative**)pNativeHome;
774                 for (int i = 0; i < managedArray.Length; i++)
775                 {
776                     DateTimeOffsetMarshaler.ConvertToNative(ref managedArray[i], out nativeBuffer[i]);
777                 }
778             }
779         }
780
781         internal static unsafe void ConvertContentsToNative_Type(ref System.Type[] managedArray, IntPtr pNativeHome)
782         {
783             if (managedArray != null)
784             {
785                 TypeNameNative* nativeBuffer = *(TypeNameNative**)pNativeHome;
786                 for (int i = 0; i < managedArray.Length; i++)
787                 {
788                     SystemTypeMarshaler.ConvertToNative(managedArray[i], &nativeBuffer[i]);
789                 }
790             }
791         }
792
793         internal static unsafe void ConvertContentsToNative_Exception(ref Exception[] managedArray, IntPtr pNativeHome)
794         {
795             if (managedArray != null)
796             {
797                 Int32* nativeBuffer = *(Int32**)pNativeHome;
798                 for (int i = 0; i < managedArray.Length; i++)
799                 {
800                     nativeBuffer[i] = HResultExceptionMarshaler.ConvertToNative(managedArray[i]);
801                 }
802             }
803         }
804
805         internal static unsafe void ConvertContentsToNative_Nullable<T>(ref Nullable<T>[] managedArray, IntPtr pNativeHome)
806             where T : struct
807         {
808             if (managedArray != null)
809             {
810                 IntPtr* nativeBuffer = *(IntPtr**)pNativeHome;
811                 for (int i = 0; i < managedArray.Length; i++)
812                 {
813                     nativeBuffer[i] = NullableMarshaler.ConvertToNative<T>(ref managedArray[i]);
814                 }
815             }
816         }
817
818         internal static unsafe void ConvertContentsToNative_KeyValuePair<K, V>(ref KeyValuePair<K, V>[] managedArray, IntPtr pNativeHome)
819         {
820             if (managedArray != null)
821             {
822                 IntPtr* nativeBuffer = *(IntPtr**)pNativeHome;
823                 for (int i = 0; i < managedArray.Length; i++)
824                 {
825                     nativeBuffer[i] = KeyValuePairMarshaler.ConvertToNative<K, V>(ref managedArray[i]);
826                 }
827             }
828         }
829
830         [MethodImplAttribute(MethodImplOptions.InternalCall)]
831         internal static extern void ConvertSpaceToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome, int elementCount);
832
833         [MethodImplAttribute(MethodImplOptions.InternalCall)]
834         internal static extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
835
836         internal static unsafe void ConvertContentsToManaged_DateTime(ref DateTimeOffset[] managedArray, IntPtr pNativeHome)
837         {
838             if (managedArray != null)
839             {
840                 DateTimeNative* nativeBuffer = *(DateTimeNative**)pNativeHome;
841                 for (int i = 0; i < managedArray.Length; i++)
842                 {
843                     DateTimeOffsetMarshaler.ConvertToManaged(out managedArray[i], ref nativeBuffer[i]);
844                 }
845             }
846         }
847
848         internal static unsafe void ConvertContentsToManaged_Type(ref System.Type[] managedArray, IntPtr pNativeHome)
849         {
850             if (managedArray != null)
851             {
852                 TypeNameNative* nativeBuffer = *(TypeNameNative**)pNativeHome;
853                 for (int i = 0; i < managedArray.Length; i++)
854                 {
855                     SystemTypeMarshaler.ConvertToManaged(&nativeBuffer[i], ref managedArray[i]);
856                 }
857             }
858         }
859
860         internal static unsafe void ConvertContentsToManaged_Exception(ref Exception[] managedArray, IntPtr pNativeHome)
861         {
862             if (managedArray != null)
863             {
864                 Int32* nativeBuffer = *(Int32**)pNativeHome;
865                 for (int i = 0; i < managedArray.Length; i++)
866                 {
867                     managedArray[i] = HResultExceptionMarshaler.ConvertToManaged(nativeBuffer[i]);
868                 }
869             }
870         }
871
872         internal static unsafe void ConvertContentsToManaged_Nullable<T>(ref Nullable<T>[] managedArray, IntPtr pNativeHome)
873             where T : struct
874         {
875             if (managedArray != null)
876             {
877                 IntPtr* nativeBuffer = *(IntPtr**)pNativeHome;
878                 for (int i = 0; i < managedArray.Length; i++)
879                 {
880                     managedArray[i] = NullableMarshaler.ConvertToManaged<T>(nativeBuffer[i]);
881                 }
882             }
883         }
884
885         internal static unsafe void ConvertContentsToManaged_KeyValuePair<K, V>(ref KeyValuePair<K, V>[] managedArray, IntPtr pNativeHome)
886         {
887             if (managedArray != null)
888             {
889                 IntPtr* nativeBuffer = *(IntPtr**)pNativeHome;
890                 for (int i = 0; i < managedArray.Length; i++)
891                 {
892                     managedArray[i] = KeyValuePairMarshaler.ConvertToManaged<K, V>(nativeBuffer[i]);
893                 }
894             }
895         }
896
897         [MethodImplAttribute(MethodImplOptions.InternalCall)]
898         internal static extern void ClearNativeContents(IntPtr pMarshalState, IntPtr pNativeHome, int cElements);
899
900         internal static unsafe void ClearNativeContents_Type(IntPtr pNativeHome, int cElements)
901         {
902             Debug.Assert(Environment.IsWinRTSupported);
903
904             TypeNameNative* pNativeTypeArray = *(TypeNameNative**)pNativeHome;
905             if (pNativeTypeArray != null)
906             {
907                 for (int i = 0; i < cElements; ++i)
908                 {
909                     SystemTypeMarshaler.ClearNative(pNativeTypeArray);
910                     pNativeTypeArray++;
911                 }
912             }
913         }
914     }  // class MngdHiddenLengthArrayMarshaler
915
916 #endif // FEATURE_COMINTEROP
917
918     internal static class MngdRefCustomMarshaler
919     {
920         [MethodImplAttribute(MethodImplOptions.InternalCall)]
921         static internal extern void CreateMarshaler(IntPtr pMarshalState, IntPtr pCMHelper);
922
923         [MethodImplAttribute(MethodImplOptions.InternalCall)]
924         static internal extern void ConvertContentsToNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
925
926         [MethodImplAttribute(MethodImplOptions.InternalCall)]
927         static internal extern void ConvertContentsToManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
928
929         [MethodImplAttribute(MethodImplOptions.InternalCall)]
930         static internal extern void ClearNative(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
931
932         [MethodImplAttribute(MethodImplOptions.InternalCall)]
933         static internal extern void ClearManaged(IntPtr pMarshalState, ref object pManagedHome, IntPtr pNativeHome);
934     }  // class MngdRefCustomMarshaler
935
936     internal struct AsAnyMarshaler
937     {
938         private const ushort VTHACK_ANSICHAR = 253;
939         private const ushort VTHACK_WINBOOL = 254;
940
941         private enum BackPropAction
942         {
943             None,
944             Array,
945             Layout,
946             StringBuilderAnsi,
947             StringBuilderUnicode
948         }
949
950         // Pointer to MngdNativeArrayMarshaler, ownership not assumed.
951         private IntPtr pvArrayMarshaler;
952
953         // Type of action to perform after the CLR-to-unmanaged call.
954         private BackPropAction backPropAction;
955
956         // The managed layout type for BackPropAction.Layout.
957         private Type layoutType;
958
959         // Cleanup list to be destroyed when clearing the native view (for layouts with SafeHandles).
960         private CleanupWorkList cleanupWorkList;
961
962         [Flags]
963         internal enum AsAnyFlags
964         {
965             In = 0x10000000,
966             Out = 0x20000000,
967             IsAnsi = 0x00FF0000,
968             IsThrowOn = 0x0000FF00,
969             IsBestFit = 0x000000FF
970         }
971
972         private static bool IsIn(int dwFlags) { return ((dwFlags & (int)AsAnyFlags.In) != 0); }
973         private static bool IsOut(int dwFlags) { return ((dwFlags & (int)AsAnyFlags.Out) != 0); }
974         private static bool IsAnsi(int dwFlags) { return ((dwFlags & (int)AsAnyFlags.IsAnsi) != 0); }
975         private static bool IsThrowOn(int dwFlags) { return ((dwFlags & (int)AsAnyFlags.IsThrowOn) != 0); }
976         private static bool IsBestFit(int dwFlags) { return ((dwFlags & (int)AsAnyFlags.IsBestFit) != 0); }
977
978         internal AsAnyMarshaler(IntPtr pvArrayMarshaler)
979         {
980             // we need this in case the value being marshaled turns out to be array
981             Debug.Assert(pvArrayMarshaler != IntPtr.Zero, "pvArrayMarshaler must not be null");
982
983             this.pvArrayMarshaler = pvArrayMarshaler;
984             backPropAction = BackPropAction.None;
985             layoutType = null;
986             cleanupWorkList = null;
987         }
988
989         #region ConvertToNative helpers
990
991         private unsafe IntPtr ConvertArrayToNative(object pManagedHome, int dwFlags)
992         {
993             Type elementType = pManagedHome.GetType().GetElementType();
994             VarEnum vt = VarEnum.VT_EMPTY;
995
996             switch (Type.GetTypeCode(elementType))
997             {
998                 case TypeCode.SByte: vt = VarEnum.VT_I1; break;
999                 case TypeCode.Byte: vt = VarEnum.VT_UI1; break;
1000                 case TypeCode.Int16: vt = VarEnum.VT_I2; break;
1001                 case TypeCode.UInt16: vt = VarEnum.VT_UI2; break;
1002                 case TypeCode.Int32: vt = VarEnum.VT_I4; break;
1003                 case TypeCode.UInt32: vt = VarEnum.VT_UI4; break;
1004                 case TypeCode.Int64: vt = VarEnum.VT_I8; break;
1005                 case TypeCode.UInt64: vt = VarEnum.VT_UI8; break;
1006                 case TypeCode.Single: vt = VarEnum.VT_R4; break;
1007                 case TypeCode.Double: vt = VarEnum.VT_R8; break;
1008                 case TypeCode.Char: vt = (IsAnsi(dwFlags) ? (VarEnum)VTHACK_ANSICHAR : VarEnum.VT_UI2); break;
1009                 case TypeCode.Boolean: vt = (VarEnum)VTHACK_WINBOOL; break;
1010
1011                 case TypeCode.Object:
1012                     {
1013                         if (elementType == typeof(IntPtr))
1014                         {
1015                             vt = (IntPtr.Size == 4 ? VarEnum.VT_I4 : VarEnum.VT_I8);
1016                         }
1017                         else if (elementType == typeof(UIntPtr))
1018                         {
1019                             vt = (IntPtr.Size == 4 ? VarEnum.VT_UI4 : VarEnum.VT_UI8);
1020                         }
1021                         else goto default;
1022                         break;
1023                     }
1024
1025                 default:
1026                     throw new ArgumentException(SR.Arg_NDirectBadObject);
1027             }
1028
1029             // marshal the object as C-style array (UnmanagedType.LPArray)
1030             int dwArrayMarshalerFlags = (int)vt;
1031             if (IsBestFit(dwFlags)) dwArrayMarshalerFlags |= (1 << 16);
1032             if (IsThrowOn(dwFlags)) dwArrayMarshalerFlags |= (1 << 24);
1033
1034             MngdNativeArrayMarshaler.CreateMarshaler(
1035                 pvArrayMarshaler,
1036                 IntPtr.Zero,      // not needed as we marshal primitive VTs only
1037                 dwArrayMarshalerFlags);
1038
1039             IntPtr pNativeHome;
1040             IntPtr pNativeHomeAddr = new IntPtr(&pNativeHome);
1041
1042             MngdNativeArrayMarshaler.ConvertSpaceToNative(
1043                 pvArrayMarshaler,
1044                 ref pManagedHome,
1045                 pNativeHomeAddr);
1046
1047             if (IsIn(dwFlags))
1048             {
1049                 MngdNativeArrayMarshaler.ConvertContentsToNative(
1050                     pvArrayMarshaler,
1051                     ref pManagedHome,
1052                     pNativeHomeAddr);
1053             }
1054             if (IsOut(dwFlags))
1055             {
1056                 backPropAction = BackPropAction.Array;
1057             }
1058
1059             return pNativeHome;
1060         }
1061
1062         private static IntPtr ConvertStringToNative(string pManagedHome, int dwFlags)
1063         {
1064             IntPtr pNativeHome;
1065
1066             // IsIn, IsOut are ignored for strings - they're always in-only
1067             if (IsAnsi(dwFlags))
1068             {
1069                 // marshal the object as Ansi string (UnmanagedType.LPStr)
1070                 pNativeHome = CSTRMarshaler.ConvertToNative(
1071                     dwFlags & 0xFFFF, // (throw on unmappable char << 8 | best fit)
1072                     pManagedHome,     //
1073                     IntPtr.Zero);     // unmanaged buffer will be allocated
1074             }
1075             else
1076             {
1077                 // marshal the object as Unicode string (UnmanagedType.LPWStr)
1078                 StubHelpers.CheckStringLength(pManagedHome.Length);
1079
1080                 int allocSize = (pManagedHome.Length + 1) * 2;
1081                 pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1082
1083                 String.InternalCopy(pManagedHome, pNativeHome, allocSize);
1084             }
1085
1086             return pNativeHome;
1087         }
1088
1089         private unsafe IntPtr ConvertStringBuilderToNative(StringBuilder pManagedHome, int dwFlags)
1090         {
1091             IntPtr pNativeHome;
1092
1093             // P/Invoke can be used to call Win32 apis that don't strictly follow CLR in/out semantics and thus may
1094             // leave garbage in the buffer in circumstances that we can't detect. To prevent us from crashing when
1095             // converting the contents back to managed, put a hidden NULL terminator past the end of the official buffer.
1096
1097             // Unmanaged layout:
1098             // +====================================+
1099             // | Extra hidden NULL                  |
1100             // +====================================+ \
1101             // |                                    | |
1102             // | [Converted] NULL-terminated string | |- buffer that the target may change
1103             // |                                    | |
1104             // +====================================+ / <-- native home
1105
1106             // Note that StringBuilder.Capacity is the number of characters NOT including any terminators.
1107
1108             if (IsAnsi(dwFlags))
1109             {
1110                 StubHelpers.CheckStringLength(pManagedHome.Capacity);
1111
1112                 // marshal the object as Ansi string (UnmanagedType.LPStr)
1113                 int allocSize = (pManagedHome.Capacity * Marshal.SystemMaxDBCSCharSize) + 4;
1114                 pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1115
1116                 byte* ptr = (byte*)pNativeHome;
1117                 *(ptr + allocSize - 3) = 0;
1118                 *(ptr + allocSize - 2) = 0;
1119                 *(ptr + allocSize - 1) = 0;
1120
1121                 if (IsIn(dwFlags))
1122                 {
1123                     int length = pManagedHome.ToString().ConvertToAnsi(
1124                         ptr, allocSize,
1125                         IsBestFit(dwFlags),
1126                         IsThrowOn(dwFlags));
1127                     Debug.Assert(length < allocSize, "Expected a length less than the allocated size");
1128                 }
1129                 if (IsOut(dwFlags))
1130                 {
1131                     backPropAction = BackPropAction.StringBuilderAnsi;
1132                 }
1133             }
1134             else
1135             {
1136                 // marshal the object as Unicode string (UnmanagedType.LPWStr)
1137                 int allocSize = (pManagedHome.Capacity * 2) + 4;
1138                 pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1139
1140                 byte* ptr = (byte*)pNativeHome;
1141                 *(ptr + allocSize - 1) = 0;
1142                 *(ptr + allocSize - 2) = 0;
1143
1144                 if (IsIn(dwFlags))
1145                 {
1146                     int length = pManagedHome.Length * 2;
1147                     pManagedHome.InternalCopy(pNativeHome, length);
1148
1149                     // null-terminate the native string
1150                     *(ptr + length + 0) = 0;
1151                     *(ptr + length + 1) = 0;
1152                 }
1153                 if (IsOut(dwFlags))
1154                 {
1155                     backPropAction = BackPropAction.StringBuilderUnicode;
1156                 }
1157             }
1158
1159             return pNativeHome;
1160         }
1161
1162         private unsafe IntPtr ConvertLayoutToNative(object pManagedHome, int dwFlags)
1163         {
1164             // Note that the following call will not throw exception if the type
1165             // of pManagedHome is not marshalable. That's intentional because we
1166             // want to maintain the original behavior where this was indicated
1167             // by TypeLoadException during the actual field marshaling.
1168             int allocSize = Marshal.SizeOfHelper(pManagedHome.GetType(), false);
1169             IntPtr pNativeHome = Marshal.AllocCoTaskMem(allocSize);
1170
1171             // marshal the object as class with layout (UnmanagedType.LPStruct)
1172             if (IsIn(dwFlags))
1173             {
1174                 StubHelpers.FmtClassUpdateNativeInternal(pManagedHome, (byte*)pNativeHome.ToPointer(), ref cleanupWorkList);
1175             }
1176             if (IsOut(dwFlags))
1177             {
1178                 backPropAction = BackPropAction.Layout;
1179             }
1180             layoutType = pManagedHome.GetType();
1181
1182             return pNativeHome;
1183         }
1184
1185         #endregion
1186
1187         internal IntPtr ConvertToNative(object pManagedHome, int dwFlags)
1188         {
1189             if (pManagedHome == null)
1190                 return IntPtr.Zero;
1191
1192             if (pManagedHome is ArrayWithOffset)
1193                 throw new ArgumentException(SR.Arg_MarshalAsAnyRestriction);
1194
1195             IntPtr pNativeHome;
1196
1197             if (pManagedHome.GetType().IsArray)
1198             {
1199                 // array (LPArray)
1200                 pNativeHome = ConvertArrayToNative(pManagedHome, dwFlags);
1201             }
1202             else
1203             {
1204                 string strValue;
1205                 StringBuilder sbValue;
1206
1207                 if ((strValue = pManagedHome as string) != null)
1208                 {
1209                     // string (LPStr or LPWStr)
1210                     pNativeHome = ConvertStringToNative(strValue, dwFlags);
1211                 }
1212                 else if ((sbValue = pManagedHome as StringBuilder) != null)
1213                 {
1214                     // StringBuilder (LPStr or LPWStr)
1215                     pNativeHome = ConvertStringBuilderToNative(sbValue, dwFlags);
1216                 }
1217                 else if (pManagedHome.GetType().IsLayoutSequential || pManagedHome.GetType().IsExplicitLayout)
1218                 {
1219                     // layout (LPStruct)
1220                     pNativeHome = ConvertLayoutToNative(pManagedHome, dwFlags);
1221                 }
1222                 else
1223                 {
1224                     // this type is not supported for AsAny marshaling
1225                     throw new ArgumentException(SR.Arg_NDirectBadObject);
1226                 }
1227             }
1228
1229             return pNativeHome;
1230         }
1231
1232         internal unsafe void ConvertToManaged(object pManagedHome, IntPtr pNativeHome)
1233         {
1234             switch (backPropAction)
1235             {
1236                 case BackPropAction.Array:
1237                     {
1238                         MngdNativeArrayMarshaler.ConvertContentsToManaged(
1239                             pvArrayMarshaler,
1240                             ref pManagedHome,
1241                             new IntPtr(&pNativeHome));
1242                         break;
1243                     }
1244
1245                 case BackPropAction.Layout:
1246                     {
1247                         StubHelpers.FmtClassUpdateCLRInternal(pManagedHome, (byte*)pNativeHome.ToPointer());
1248                         break;
1249                     }
1250
1251                 case BackPropAction.StringBuilderAnsi:
1252                     {
1253                         sbyte* ptr = (sbyte*)pNativeHome.ToPointer();
1254                         ((StringBuilder)pManagedHome).ReplaceBufferAnsiInternal(ptr, Win32Native.lstrlenA(pNativeHome));
1255                         break;
1256                     }
1257
1258                 case BackPropAction.StringBuilderUnicode:
1259                     {
1260                         char* ptr = (char*)pNativeHome.ToPointer();
1261                         ((StringBuilder)pManagedHome).ReplaceBufferInternal(ptr, Win32Native.lstrlenW(pNativeHome));
1262                         break;
1263                     }
1264
1265                     // nothing to do for BackPropAction.None
1266             }
1267         }
1268
1269         internal void ClearNative(IntPtr pNativeHome)
1270         {
1271             if (pNativeHome != IntPtr.Zero)
1272             {
1273                 if (layoutType != null)
1274                 {
1275                     // this must happen regardless of BackPropAction
1276                     Marshal.DestroyStructure(pNativeHome, layoutType);
1277                 }
1278                 Win32Native.CoTaskMemFree(pNativeHome);
1279             }
1280             StubHelpers.DestroyCleanupList(ref cleanupWorkList);
1281         }
1282     }  // struct AsAnyMarshaler
1283
1284 #if FEATURE_COMINTEROP
1285     internal static class NullableMarshaler
1286     {
1287         static internal IntPtr ConvertToNative<T>(ref Nullable<T> pManaged) where T : struct
1288         {
1289             if (pManaged.HasValue)
1290             {
1291                 object impl = IReferenceFactory.CreateIReference(pManaged);
1292                 return Marshal.GetComInterfaceForObject(impl, typeof(IReference<T>));
1293             }
1294             else
1295             {
1296                 return IntPtr.Zero;
1297             }
1298         }
1299
1300         static internal void ConvertToManagedRetVoid<T>(IntPtr pNative, ref Nullable<T> retObj) where T : struct
1301         {
1302             retObj = ConvertToManaged<T>(pNative);
1303         }
1304
1305
1306         static internal Nullable<T> ConvertToManaged<T>(IntPtr pNative) where T : struct
1307         {
1308             if (pNative != IntPtr.Zero)
1309             {
1310                 object wrapper = InterfaceMarshaler.ConvertToManagedWithoutUnboxing(pNative);
1311                 return (Nullable<T>)CLRIReferenceImpl<T>.UnboxHelper(wrapper);
1312             }
1313             else
1314             {
1315                 return new Nullable<T>();
1316             }
1317         }
1318     }  // class NullableMarshaler
1319
1320     // Corresponds to Windows.UI.Xaml.Interop.TypeName
1321     [StructLayout(LayoutKind.Sequential)]
1322     internal struct TypeNameNative
1323     {
1324         internal IntPtr typeName;           // HSTRING
1325         internal TypeKind typeKind;           // TypeKind enum
1326     }
1327
1328     // Corresponds to Windows.UI.Xaml.TypeSource
1329     internal enum TypeKind
1330     {
1331         Primitive,
1332         Metadata,
1333         Projection
1334     };
1335
1336     internal static class WinRTTypeNameConverter
1337     {
1338         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1339         internal static extern string ConvertToWinRTTypeName(System.Type managedType, out bool isPrimitive);
1340
1341         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1342         internal static extern System.Type GetTypeFromWinRTTypeName(string typeName, out bool isPrimitive);
1343     }
1344
1345     internal static class SystemTypeMarshaler
1346     {
1347         internal static unsafe void ConvertToNative(System.Type managedType, TypeNameNative* pNativeType)
1348         {
1349             if (!Environment.IsWinRTSupported)
1350             {
1351                 throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT);
1352             }
1353
1354             string typeName;
1355             if (managedType != null)
1356             {
1357                 if (managedType.GetType() != typeof(System.RuntimeType))
1358                 {   // The type should be exactly System.RuntimeType (and not its child System.ReflectionOnlyType, or other System.Type children)
1359                     throw new ArgumentException(SR.Format(SR.Argument_WinRTSystemRuntimeType, managedType.GetType().ToString()));
1360                 }
1361
1362                 bool isPrimitive;
1363                 string winrtTypeName = WinRTTypeNameConverter.ConvertToWinRTTypeName(managedType, out isPrimitive);
1364                 if (winrtTypeName != null)
1365                 {
1366                     // Must be a WinRT type, either in a WinMD or a Primitive
1367                     typeName = winrtTypeName;
1368                     if (isPrimitive)
1369                         pNativeType->typeKind = TypeKind.Primitive;
1370                     else
1371                         pNativeType->typeKind = TypeKind.Metadata;
1372                 }
1373                 else
1374                 {
1375                     // Custom .NET type
1376                     typeName = managedType.AssemblyQualifiedName;
1377                     pNativeType->typeKind = TypeKind.Projection;
1378                 }
1379             }
1380             else
1381             {   // Marshal null as empty string + Projection
1382                 typeName = "";
1383                 pNativeType->typeKind = TypeKind.Projection;
1384             }
1385
1386             int hrCreate = System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsCreateString(typeName, typeName.Length, &pNativeType->typeName);
1387             Marshal.ThrowExceptionForHR(hrCreate, new IntPtr(-1));
1388         }
1389
1390         internal static unsafe void ConvertToManaged(TypeNameNative* pNativeType, ref System.Type managedType)
1391         {
1392             if (!Environment.IsWinRTSupported)
1393             {
1394                 throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT);
1395             }
1396
1397             string typeName = WindowsRuntimeMarshal.HStringToString(pNativeType->typeName);
1398             if (String.IsNullOrEmpty(typeName))
1399             {
1400                 managedType = null;
1401                 return;
1402             }
1403
1404             if (pNativeType->typeKind == TypeKind.Projection)
1405             {
1406                 managedType = Type.GetType(typeName, /* throwOnError = */ true);
1407             }
1408             else
1409             {
1410                 bool isPrimitive;
1411                 managedType = WinRTTypeNameConverter.GetTypeFromWinRTTypeName(typeName, out isPrimitive);
1412
1413                 // TypeSource must match
1414                 if (isPrimitive != (pNativeType->typeKind == TypeKind.Primitive))
1415                     throw new ArgumentException(SR.Argument_Unexpected_TypeSource);
1416             }
1417         }
1418
1419         internal static unsafe void ClearNative(TypeNameNative* pNativeType)
1420         {
1421             Debug.Assert(Environment.IsWinRTSupported);
1422
1423             if (pNativeType->typeName != IntPtr.Zero)
1424             {
1425                 System.Runtime.InteropServices.WindowsRuntime.UnsafeNativeMethods.WindowsDeleteString(pNativeType->typeName);
1426             }
1427         }
1428     }  // class SystemTypeMarshaler
1429
1430     // For converting WinRT's Windows.Foundation.HResult into System.Exception and vice versa.
1431     internal static class HResultExceptionMarshaler
1432     {
1433         static internal unsafe int ConvertToNative(Exception ex)
1434         {
1435             if (!Environment.IsWinRTSupported)
1436             {
1437                 throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT);
1438             }
1439
1440             if (ex == null)
1441                 return 0;  // S_OK;
1442
1443             return ex._HResult;
1444         }
1445
1446         static internal unsafe Exception ConvertToManaged(int hr)
1447         {
1448             if (!Environment.IsWinRTSupported)
1449             {
1450                 throw new PlatformNotSupportedException(SR.PlatformNotSupported_WinRT);
1451             }
1452
1453             Exception e = null;
1454             if (hr < 0)
1455             {
1456                 e = StubHelpers.InternalGetCOMHRExceptionObject(hr, IntPtr.Zero, null, /* fForWinRT */ true);
1457             }
1458
1459             // S_OK should be marshaled as null.  WinRT API's should not return S_FALSE by convention.
1460             // We've chosen to treat S_FALSE as success and return null.
1461             Debug.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.");
1462             return e;
1463         }
1464     }  // class HResultExceptionMarshaler
1465
1466     internal static class KeyValuePairMarshaler
1467     {
1468         internal static IntPtr ConvertToNative<K, V>([In] ref KeyValuePair<K, V> pair)
1469         {
1470             IKeyValuePair<K, V> impl = new CLRIKeyValuePairImpl<K, V>(ref pair);
1471             return Marshal.GetComInterfaceForObject(impl, typeof(IKeyValuePair<K, V>));
1472         }
1473
1474         internal static KeyValuePair<K, V> ConvertToManaged<K, V>(IntPtr pInsp)
1475         {
1476             object obj = InterfaceMarshaler.ConvertToManagedWithoutUnboxing(pInsp);
1477
1478             IKeyValuePair<K, V> pair = (IKeyValuePair<K, V>)obj;
1479             return new KeyValuePair<K, V>(pair.Key, pair.Value);
1480         }
1481
1482         // Called from COMInterfaceMarshaler
1483         internal static object ConvertToManagedBox<K, V>(IntPtr pInsp)
1484         {
1485             return (object)ConvertToManaged<K, V>(pInsp);
1486         }
1487     }  // class KeyValuePairMarshaler
1488
1489 #endif // FEATURE_COMINTEROP
1490
1491     [StructLayout(LayoutKind.Sequential)]
1492     internal struct NativeVariant
1493     {
1494         private ushort vt;
1495         private ushort wReserved1;
1496         private ushort wReserved2;
1497         private ushort wReserved3;
1498
1499         // The union portion of the structure contains at least one 64-bit type that on some 32-bit platforms
1500         // (notably  ARM) requires 64-bit alignment. So on 32-bit platforms we'll actually size the variant
1501         // portion of the struct with an Int64 so the type loader notices this requirement (a no-op on x86,
1502         // but on ARM it will allow us to correctly determine the layout of native argument lists containing
1503         // VARIANTs). Note that the field names here don't matter: none of the code refers to these fields,
1504         // the structure just exists to provide size information to the IL marshaler.
1505 #if BIT64
1506         private IntPtr data1;
1507         private IntPtr data2;
1508 #else
1509         Int64  data1;
1510 #endif
1511     }  // struct NativeVariant
1512
1513     // Aggregates SafeHandle and the "owned" bit which indicates whether the SafeHandle
1514     // has been successfully AddRef'ed. This allows us to do realiable cleanup (Release)
1515     // if and only if it is needed.
1516     internal sealed class CleanupWorkListElement
1517     {
1518         public CleanupWorkListElement(SafeHandle handle)
1519         {
1520             m_handle = handle;
1521         }
1522
1523         public SafeHandle m_handle;
1524
1525         // This field is passed by-ref to SafeHandle.DangerousAddRef.
1526         // CleanupWorkList.Destroy ignores this element if m_owned is not set to true.
1527         public bool m_owned;
1528     }  // class CleanupWorkListElement
1529
1530     internal sealed class CleanupWorkList
1531     {
1532         private List<CleanupWorkListElement> m_list = new List<CleanupWorkListElement>();
1533
1534         public void Add(CleanupWorkListElement elem)
1535         {
1536             Debug.Assert(elem.m_owned == false, "m_owned is supposed to be false and set later by DangerousAddRef");
1537             m_list.Add(elem);
1538         }
1539
1540         public void Destroy()
1541         {
1542             for (int i = m_list.Count - 1; i >= 0; i--)
1543             {
1544                 if (m_list[i].m_owned)
1545                     StubHelpers.SafeHandleRelease(m_list[i].m_handle);
1546             }
1547         }
1548     }  // class CleanupWorkList
1549
1550     internal static class StubHelpers
1551     {
1552         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1553         static internal extern bool IsQCall(IntPtr pMD);
1554
1555         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1556         static internal extern void InitDeclaringType(IntPtr pMD);
1557
1558         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1559         static internal extern IntPtr GetNDirectTarget(IntPtr pMD);
1560
1561         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1562         static internal extern IntPtr GetDelegateTarget(Delegate pThis, ref IntPtr pStubArg);
1563
1564         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1565         static internal extern void ClearLastError();
1566
1567         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1568         static internal extern void SetLastError();
1569
1570         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1571         static internal extern void ThrowInteropParamException(int resID, int paramIdx);
1572
1573         static internal IntPtr AddToCleanupList(ref CleanupWorkList pCleanupWorkList, SafeHandle handle)
1574         {
1575             if (pCleanupWorkList == null)
1576                 pCleanupWorkList = new CleanupWorkList();
1577
1578             CleanupWorkListElement element = new CleanupWorkListElement(handle);
1579             pCleanupWorkList.Add(element);
1580
1581             // element.m_owned will be true iff the AddRef succeeded
1582             return SafeHandleAddRef(handle, ref element.m_owned);
1583         }
1584
1585         static internal void DestroyCleanupList(ref CleanupWorkList pCleanupWorkList)
1586         {
1587             if (pCleanupWorkList != null)
1588             {
1589                 pCleanupWorkList.Destroy();
1590                 pCleanupWorkList = null;
1591             }
1592         }
1593
1594         static internal Exception GetHRExceptionObject(int hr)
1595         {
1596             Exception ex = InternalGetHRExceptionObject(hr);
1597             ex.InternalPreserveStackTrace();
1598             return ex;
1599         }
1600
1601         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1602         static internal extern Exception InternalGetHRExceptionObject(int hr);
1603
1604 #if FEATURE_COMINTEROP
1605         static internal Exception GetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object pThis)
1606         {
1607             Exception ex = InternalGetCOMHRExceptionObject(hr, pCPCMD, pThis, false);
1608             ex.InternalPreserveStackTrace();
1609             return ex;
1610         }
1611
1612         static internal Exception GetCOMHRExceptionObject_WinRT(int hr, IntPtr pCPCMD, object pThis)
1613         {
1614             Exception ex = InternalGetCOMHRExceptionObject(hr, pCPCMD, pThis, true);
1615             ex.InternalPreserveStackTrace();
1616             return ex;
1617         }
1618
1619         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1620         static internal extern Exception InternalGetCOMHRExceptionObject(int hr, IntPtr pCPCMD, object pThis, bool fForWinRT);
1621
1622 #endif // FEATURE_COMINTEROP
1623
1624         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1625         static internal extern IntPtr CreateCustomMarshalerHelper(IntPtr pMD, int paramToken, IntPtr hndManagedType);
1626
1627         //-------------------------------------------------------
1628         // SafeHandle Helpers
1629         //-------------------------------------------------------
1630
1631         // AddRefs the SH and returns the underlying unmanaged handle.
1632         static internal IntPtr SafeHandleAddRef(SafeHandle pHandle, ref bool success)
1633         {
1634             if (pHandle == null)
1635             {
1636                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.pHandle, ExceptionResource.ArgumentNull_SafeHandle);
1637             }
1638
1639             pHandle.DangerousAddRef(ref success);
1640             return pHandle.DangerousGetHandle();
1641         }
1642
1643         // Releases the SH (to be called from finally block).
1644         static internal void SafeHandleRelease(SafeHandle pHandle)
1645         {
1646             if (pHandle == null)
1647             {
1648                 ThrowHelper.ThrowArgumentNullException(ExceptionArgument.pHandle, ExceptionResource.ArgumentNull_SafeHandle);
1649             }
1650
1651             try
1652             {
1653                 pHandle.DangerousRelease();
1654             }
1655 #if MDA_SUPPORTED
1656             catch (Exception ex)
1657             {
1658                 Mda.ReportErrorSafeHandleRelease(ex);
1659             }
1660 #else // MDA_SUPPORTED
1661             catch (Exception)
1662             { }
1663 #endif // MDA_SUPPORTED
1664         }
1665
1666 #if FEATURE_COMINTEROP
1667         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1668         static internal extern IntPtr GetCOMIPFromRCW(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget, out bool pfNeedsRelease);
1669
1670         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1671         static internal extern IntPtr GetCOMIPFromRCW_WinRT(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
1672
1673         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1674         static internal extern IntPtr GetCOMIPFromRCW_WinRTSharedGeneric(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
1675
1676         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1677         static internal extern IntPtr GetCOMIPFromRCW_WinRTDelegate(object objSrc, IntPtr pCPCMD, out IntPtr ppTarget);
1678
1679         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1680         static internal extern bool ShouldCallWinRTInterface(object objSrc, IntPtr pCPCMD);
1681
1682         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1683         static internal extern Delegate GetTargetForAmbiguousVariantCall(object objSrc, IntPtr pMT, out bool fUseString);
1684
1685         //-------------------------------------------------------
1686         // Helper for the MDA RaceOnRCWCleanup
1687         //-------------------------------------------------------
1688
1689         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1690         static internal extern void StubRegisterRCW(object pThis);
1691
1692         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1693         static internal extern void StubUnregisterRCW(object pThis);
1694
1695         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1696         static internal extern IntPtr GetDelegateInvokeMethod(Delegate pThis);
1697
1698         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1699         static internal extern object GetWinRTFactoryObject(IntPtr pCPCMD);
1700
1701         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1702         static internal extern IntPtr GetWinRTFactoryReturnValue(object pThis, IntPtr pCtorEntry);
1703
1704         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1705         static internal extern IntPtr GetOuterInspectable(object pThis, IntPtr pCtorMD);
1706
1707 #if MDA_SUPPORTED
1708         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1709         static internal extern Exception TriggerExceptionSwallowedMDA(Exception ex, IntPtr pManagedTarget);
1710 #endif // MDA_SUPPORTED
1711
1712 #endif // FEATURE_COMINTEROP
1713
1714 #if MDA_SUPPORTED
1715         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1716         static internal extern void CheckCollectedDelegateMDA(IntPtr pEntryThunk);
1717 #endif // MDA_SUPPORTED
1718
1719         //-------------------------------------------------------
1720         // Profiler helpers
1721         //-------------------------------------------------------
1722 #if PROFILING_SUPPORTED
1723         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1724         static internal extern IntPtr ProfilerBeginTransitionCallback(IntPtr pSecretParam, IntPtr pThread, object pThis);
1725
1726         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1727         static internal extern void ProfilerEndTransitionCallback(IntPtr pMD, IntPtr pThread);
1728 #endif // PROFILING_SUPPORTED
1729
1730         //------------------------------------------------------
1731         // misc
1732         //------------------------------------------------------
1733         static internal void CheckStringLength(int length)
1734         {
1735             CheckStringLength((uint)length);
1736         }
1737
1738         static internal void CheckStringLength(uint length)
1739         {
1740             if (length > 0x7ffffff0)
1741             {
1742                 throw new MarshalDirectiveException(SR.Marshaler_StringTooLong);
1743             }
1744         }
1745
1746         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1747         static internal unsafe extern int strlen(sbyte* ptr);
1748
1749         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1750         static internal extern void DecimalCanonicalizeInternal(ref Decimal dec);
1751
1752         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1753         static internal unsafe extern void FmtClassUpdateNativeInternal(object obj, byte* pNative, ref CleanupWorkList pCleanupWorkList);
1754         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1755         static internal unsafe extern void FmtClassUpdateCLRInternal(object obj, byte* pNative);
1756         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1757         static internal unsafe extern void LayoutDestroyNativeInternal(byte* pNative, IntPtr pMT);
1758         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1759         static internal extern object AllocateInternal(IntPtr typeHandle);
1760
1761         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1762         static internal extern void MarshalToUnmanagedVaListInternal(IntPtr va_list, uint vaListSize, IntPtr pArgIterator);
1763
1764         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1765         static internal extern void MarshalToManagedVaListInternal(IntPtr va_list, IntPtr pArgIterator);
1766
1767         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1768         static internal extern uint CalcVaListSize(IntPtr va_list);
1769
1770         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1771         static internal extern void ValidateObject(object obj, IntPtr pMD, object pThis);
1772
1773         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1774         static internal extern void LogPinnedArgument(IntPtr localDesc, IntPtr nativeArg);
1775
1776         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1777         static internal extern void ValidateByref(IntPtr byref, IntPtr pMD, object pThis); // the byref is pinned so we can safely "cast" it to IntPtr
1778
1779         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1780         static internal extern IntPtr GetStubContext();
1781
1782 #if BIT64
1783         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1784         static internal extern IntPtr GetStubContextAddr();
1785 #endif // BIT64
1786
1787 #if MDA_SUPPORTED
1788         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1789         static internal extern void TriggerGCForMDA();        
1790 #endif // MDA_SUPPORTED
1791
1792 #if FEATURE_ARRAYSTUB_AS_IL
1793         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1794         internal static extern void ArrayTypeCheck(object o, Object[] arr);
1795 #endif
1796
1797 #if FEATURE_MULTICASTSTUB_AS_IL
1798         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1799         internal static extern void MulticastDebuggerTraceHelper(object o, Int32 count);
1800 #endif
1801     }  // class StubHelpers
1802 }