Code cleanup and formatting for System.Memory files. (#17451)
[platform/upstream/coreclr.git] / src / System.Private.CoreLib / src / System / Runtime / InteropServices / Marshal.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 **
7 **
8 **
9 ** Purpose: This class contains methods that are mainly used to marshal 
10 **          between unmanaged and managed types.
11 **
12 **
13 =============================================================================*/
14
15 namespace System.Runtime.InteropServices
16 {
17     using System;
18     using System.Runtime;
19     using System.Collections.Generic;
20     using System.Reflection;
21     using System.Reflection.Emit;
22     using System.Security;
23     using System.Text;
24     using System.Threading;
25     using System.Runtime.CompilerServices;
26     using System.Globalization;
27     using System.Runtime.ConstrainedExecution;
28     using System.Runtime.Versioning;
29     using Win32Native = Microsoft.Win32.Win32Native;
30     using Microsoft.Win32.SafeHandles;
31     using System.Diagnostics;
32     using System.Runtime.InteropServices.ComTypes;
33     using System.StubHelpers;
34
35     public enum CustomQueryInterfaceMode
36     {
37         Ignore = 0,
38         Allow = 1
39     }
40
41     //========================================================================
42     // All public methods, including PInvoke, are protected with linkchecks.  
43     // Remove the default demands for all PInvoke methods with this global 
44     // declaration on the class.
45     //========================================================================
46
47     public static partial class Marshal
48     {
49         //====================================================================
50         // Defines used inside the Marshal class.
51         //====================================================================
52         private const int LMEM_FIXED = 0;
53         private const int LMEM_MOVEABLE = 2;
54 #if !FEATURE_PAL
55         private const long HIWORDMASK = unchecked((long)0xffffffffffff0000L);
56 #endif //!FEATURE_PAL
57 #if FEATURE_COMINTEROP
58         private static Guid IID_IUnknown = new Guid("00000000-0000-0000-C000-000000000046");
59 #endif //FEATURE_COMINTEROP
60
61         // Win32 has the concept of Atoms, where a pointer can either be a pointer
62         // or an int.  If it's less than 64K, this is guaranteed to NOT be a 
63         // pointer since the bottom 64K bytes are reserved in a process' page table.
64         // We should be careful about deallocating this stuff.  Extracted to
65         // a function to avoid C# problems with lack of support for IntPtr.
66         // We have 2 of these methods for slightly different semantics for NULL.
67         private static bool IsWin32Atom(IntPtr ptr)
68         {
69 #if FEATURE_PAL
70             return false;
71 #else
72             long lPtr = (long)ptr;
73             return 0 == (lPtr & HIWORDMASK);
74 #endif
75         }
76
77         private static bool IsNotWin32Atom(IntPtr ptr)
78         {
79 #if FEATURE_PAL
80             return true;
81 #else
82             long lPtr = (long)ptr;
83             return 0 != (lPtr & HIWORDMASK);
84 #endif
85         }
86
87         //====================================================================
88         // The default character size for the system. This is always 2 because
89         // the framework only runs on UTF-16 systems.
90         //====================================================================
91         public static readonly int SystemDefaultCharSize = 2;
92
93         //====================================================================
94         // The max DBCS character size for the system.
95         //====================================================================
96         public static readonly int SystemMaxDBCSCharSize = GetSystemMaxDBCSCharSize();
97
98
99         //====================================================================
100         // The name, title and description of the assembly that will contain 
101         // the dynamically generated interop types. 
102         //====================================================================
103         private const string s_strConvertedTypeInfoAssemblyName = "InteropDynamicTypes";
104         private const string s_strConvertedTypeInfoAssemblyTitle = "Interop Dynamic Types";
105         private const string s_strConvertedTypeInfoAssemblyDesc = "Type dynamically generated from ITypeInfo's";
106         private const string s_strConvertedTypeInfoNameSpace = "InteropDynamicTypes";
107
108
109         //====================================================================
110         // Helper method to retrieve the system's maximum DBCS character size.
111         //====================================================================
112         [MethodImplAttribute(MethodImplOptions.InternalCall)]
113         private static extern int GetSystemMaxDBCSCharSize();
114
115         public static unsafe string PtrToStringAnsi(IntPtr ptr)
116         {
117             if (IntPtr.Zero == ptr)
118             {
119                 return null;
120             }
121             else if (IsWin32Atom(ptr))
122             {
123                 return null;
124             }
125             else
126             {
127                 int nb = Win32Native.lstrlenA(ptr);
128                 if (nb == 0)
129                 {
130                     return string.Empty;
131                 }
132                 else
133                 {
134                     return new string((sbyte*)ptr);
135                 }
136             }
137         }
138
139         public static unsafe string PtrToStringAnsi(IntPtr ptr, int len)
140         {
141             if (ptr == IntPtr.Zero)
142                 throw new ArgumentNullException(nameof(ptr));
143             if (len < 0)
144                 throw new ArgumentException(null, nameof(len));
145
146             return new string((sbyte*)ptr, 0, len);
147         }
148
149         public static unsafe string PtrToStringUni(IntPtr ptr, int len)
150         {
151             if (ptr == IntPtr.Zero)
152                 throw new ArgumentNullException(nameof(ptr));
153             if (len < 0)
154                 throw new ArgumentException(null, nameof(len));
155
156             return new string((char*)ptr, 0, len);
157         }
158
159         public static string PtrToStringAuto(IntPtr ptr, int len)
160         {
161             // Ansi platforms are no longer supported
162             return PtrToStringUni(ptr, len);
163         }
164
165         public static unsafe string PtrToStringUni(IntPtr ptr)
166         {
167             if (IntPtr.Zero == ptr)
168             {
169                 return null;
170             }
171             else if (IsWin32Atom(ptr))
172             {
173                 return null;
174             }
175             else
176             {
177                 return new string((char*)ptr);
178             }
179         }
180
181         public static string PtrToStringAuto(IntPtr ptr)
182         {
183             // Ansi platforms are no longer supported
184             return PtrToStringUni(ptr);
185         }
186
187         public static unsafe string PtrToStringUTF8(IntPtr ptr)
188         {
189             if (IntPtr.Zero == ptr)
190             {
191                 return null;
192             }
193             else
194             {
195                 int nbBytes = System.StubHelpers.StubHelpers.strlen((sbyte*)ptr.ToPointer());
196                 return PtrToStringUTF8(ptr, nbBytes);
197             }
198         }
199
200         public static unsafe string PtrToStringUTF8(IntPtr ptr, int byteLen)
201         {
202             if (byteLen < 0)
203             {
204                 throw new ArgumentOutOfRangeException(nameof(byteLen), SR.ArgumentOutOfRange_NeedNonNegNum);
205             }
206             else if (IntPtr.Zero == ptr)
207             {
208                 return null;
209             }
210             else if (IsWin32Atom(ptr))
211             {
212                 return null;
213             }
214             else if (byteLen == 0)
215             {
216                 return string.Empty;
217             }
218             else
219             {
220                 byte* pByte = (byte*)ptr.ToPointer();
221                 return Encoding.UTF8.GetString(pByte, byteLen);
222             }
223         }
224
225         //====================================================================
226         // SizeOf()
227         //====================================================================
228         public static int SizeOf(Object structure)
229         {
230             if (structure == null)
231                 throw new ArgumentNullException(nameof(structure));
232             // we never had a check for generics here
233
234             return SizeOfHelper(structure.GetType(), true);
235         }
236
237         public static int SizeOf<T>(T structure)
238         {
239             return SizeOf((object)structure);
240         }
241
242         public static int SizeOf(Type t)
243         {
244             if (t == null)
245                 throw new ArgumentNullException(nameof(t));
246             if (!(t is RuntimeType))
247                 throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(t));
248             if (t.IsGenericType)
249                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
250
251             return SizeOfHelper(t, true);
252         }
253
254         public static int SizeOf<T>()
255         {
256             return SizeOf(typeof(T));
257         }
258
259         [MethodImplAttribute(MethodImplOptions.InternalCall)]
260         internal static extern int SizeOfHelper(Type t, bool throwIfNotMarshalable);
261
262         //====================================================================
263         // OffsetOf()
264         //====================================================================
265         public static IntPtr OffsetOf(Type t, string fieldName)
266         {
267             if (t == null)
268                 throw new ArgumentNullException(nameof(t));
269
270             FieldInfo f = t.GetField(fieldName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
271             if (f == null)
272                 throw new ArgumentException(SR.Format(SR.Argument_OffsetOfFieldNotFound, t.FullName), nameof(fieldName));
273             RtFieldInfo rtField = f as RtFieldInfo;
274             if (rtField == null)
275                 throw new ArgumentException(SR.Argument_MustBeRuntimeFieldInfo, nameof(fieldName));
276
277             return OffsetOfHelper(rtField);
278         }
279         public static IntPtr OffsetOf<T>(string fieldName)
280         {
281             return OffsetOf(typeof(T), fieldName);
282         }
283
284         [MethodImplAttribute(MethodImplOptions.InternalCall)]
285         private static extern IntPtr OffsetOfHelper(IRuntimeFieldInfo f);
286
287         //====================================================================
288         // UnsafeAddrOfPinnedArrayElement()
289         //
290         // IMPORTANT NOTICE: This method does not do any verification on the
291         // array. It must be used with EXTREME CAUTION since passing in 
292         // an array that is not pinned or in the fixed heap can cause 
293         // unexpected results !
294         //====================================================================
295         [MethodImplAttribute(MethodImplOptions.InternalCall)]
296         public static extern IntPtr UnsafeAddrOfPinnedArrayElement(Array arr, int index);
297
298         public static IntPtr UnsafeAddrOfPinnedArrayElement<T>(T[] arr, int index)
299         {
300             return UnsafeAddrOfPinnedArrayElement((Array)arr, index);
301         }
302
303         //====================================================================
304         // Copy blocks from CLR arrays to native memory.
305         //====================================================================
306         public static void Copy(int[] source, int startIndex, IntPtr destination, int length)
307         {
308             CopyToNative(source, startIndex, destination, length);
309         }
310         public static void Copy(char[] source, int startIndex, IntPtr destination, int length)
311         {
312             CopyToNative(source, startIndex, destination, length);
313         }
314         public static void Copy(short[] source, int startIndex, IntPtr destination, int length)
315         {
316             CopyToNative(source, startIndex, destination, length);
317         }
318         public static void Copy(long[] source, int startIndex, IntPtr destination, int length)
319         {
320             CopyToNative(source, startIndex, destination, length);
321         }
322         public static void Copy(float[] source, int startIndex, IntPtr destination, int length)
323         {
324             CopyToNative(source, startIndex, destination, length);
325         }
326         public static void Copy(double[] source, int startIndex, IntPtr destination, int length)
327         {
328             CopyToNative(source, startIndex, destination, length);
329         }
330         public static void Copy(byte[] source, int startIndex, IntPtr destination, int length)
331         {
332             CopyToNative(source, startIndex, destination, length);
333         }
334         public static void Copy(IntPtr[] source, int startIndex, IntPtr destination, int length)
335         {
336             CopyToNative(source, startIndex, destination, length);
337         }
338         [MethodImplAttribute(MethodImplOptions.InternalCall)]
339         private static extern void CopyToNative(Object source, int startIndex, IntPtr destination, int length);
340
341         //====================================================================
342         // Copy blocks from native memory to CLR arrays
343         //====================================================================
344         public static void Copy(IntPtr source, int[] destination, int startIndex, int length)
345         {
346             CopyToManaged(source, destination, startIndex, length);
347         }
348         public static void Copy(IntPtr source, char[] destination, int startIndex, int length)
349         {
350             CopyToManaged(source, destination, startIndex, length);
351         }
352         public static void Copy(IntPtr source, short[] destination, int startIndex, int length)
353         {
354             CopyToManaged(source, destination, startIndex, length);
355         }
356         public static void Copy(IntPtr source, long[] destination, int startIndex, int length)
357         {
358             CopyToManaged(source, destination, startIndex, length);
359         }
360         public static void Copy(IntPtr source, float[] destination, int startIndex, int length)
361         {
362             CopyToManaged(source, destination, startIndex, length);
363         }
364         public static void Copy(IntPtr source, double[] destination, int startIndex, int length)
365         {
366             CopyToManaged(source, destination, startIndex, length);
367         }
368         public static void Copy(IntPtr source, byte[] destination, int startIndex, int length)
369         {
370             CopyToManaged(source, destination, startIndex, length);
371         }
372         public static void Copy(IntPtr source, IntPtr[] destination, int startIndex, int length)
373         {
374             CopyToManaged(source, destination, startIndex, length);
375         }
376         [MethodImplAttribute(MethodImplOptions.InternalCall)]
377         private static extern void CopyToManaged(IntPtr source, Object destination, int startIndex, int length);
378
379         //====================================================================
380         // Read from memory
381         //====================================================================
382         public static byte ReadByte(Object ptr, int ofs)
383         {
384             return ReadValueSlow(ptr, ofs, (IntPtr nativeHome, int offset) => Marshal.ReadByte(nativeHome, offset));
385         }
386
387         public static unsafe byte ReadByte(IntPtr ptr, int ofs)
388         {
389             try
390             {
391                 byte* addr = (byte*)ptr + ofs;
392                 return *addr;
393             }
394             catch (NullReferenceException)
395             {
396                 // this method is documented to throw AccessViolationException on any AV
397                 throw new AccessViolationException();
398             }
399         }
400
401         public static byte ReadByte(IntPtr ptr)
402         {
403             return ReadByte(ptr, 0);
404         }
405
406         public static short ReadInt16(Object ptr, int ofs)
407         {
408             return ReadValueSlow(ptr, ofs, (IntPtr nativeHome, int offset) => Marshal.ReadInt16(nativeHome, offset));
409         }
410
411         public static unsafe short ReadInt16(IntPtr ptr, int ofs)
412         {
413             try
414             {
415                 byte* addr = (byte*)ptr + ofs;
416                 if ((unchecked((int)addr) & 0x1) == 0)
417                 {
418                     // aligned read
419                     return *((short*)addr);
420                 }
421                 else
422                 {
423                     // unaligned read
424                     short val;
425                     byte* valPtr = (byte*)&val;
426                     valPtr[0] = addr[0];
427                     valPtr[1] = addr[1];
428                     return val;
429                 }
430             }
431             catch (NullReferenceException)
432             {
433                 // this method is documented to throw AccessViolationException on any AV
434                 throw new AccessViolationException();
435             }
436         }
437
438         public static short ReadInt16(IntPtr ptr)
439         {
440             return ReadInt16(ptr, 0);
441         }
442
443         public static int ReadInt32(object ptr, int ofs)
444         {
445             return ReadValueSlow(ptr, ofs, (IntPtr nativeHome, int offset) => Marshal.ReadInt32(nativeHome, offset));
446         }
447
448         public static unsafe int ReadInt32(IntPtr ptr, int ofs)
449         {
450             try
451             {
452                 byte* addr = (byte*)ptr + ofs;
453                 if ((unchecked((int)addr) & 0x3) == 0)
454                 {
455                     // aligned read
456                     return *((int*)addr);
457                 }
458                 else
459                 {
460                     // unaligned read
461                     int val;
462                     byte* valPtr = (byte*)&val;
463                     valPtr[0] = addr[0];
464                     valPtr[1] = addr[1];
465                     valPtr[2] = addr[2];
466                     valPtr[3] = addr[3];
467                     return val;
468                 }
469             }
470             catch (NullReferenceException)
471             {
472                 // this method is documented to throw AccessViolationException on any AV
473                 throw new AccessViolationException();
474             }
475         }
476
477         public static int ReadInt32(IntPtr ptr)
478         {
479             return ReadInt32(ptr, 0);
480         }
481
482         public static IntPtr ReadIntPtr(Object ptr, int ofs)
483         {
484 #if BIT64
485             return (IntPtr)ReadInt64(ptr, ofs);
486 #else // 32
487                 return (IntPtr) ReadInt32(ptr, ofs);
488 #endif
489         }
490
491         public static IntPtr ReadIntPtr(IntPtr ptr, int ofs)
492         {
493 #if BIT64
494             return (IntPtr)ReadInt64(ptr, ofs);
495 #else // 32
496                 return (IntPtr) ReadInt32(ptr, ofs);
497 #endif
498         }
499
500         public static IntPtr ReadIntPtr(IntPtr ptr)
501         {
502 #if BIT64
503             return (IntPtr)ReadInt64(ptr, 0);
504 #else // 32
505                 return (IntPtr) ReadInt32(ptr, 0);
506 #endif
507         }
508
509         public static long ReadInt64([MarshalAs(UnmanagedType.AsAny), In] Object ptr, int ofs)
510         {
511             return ReadValueSlow(ptr, ofs, (IntPtr nativeHome, int offset) => Marshal.ReadInt64(nativeHome, offset));
512         }
513
514         public static unsafe long ReadInt64(IntPtr ptr, int ofs)
515         {
516             try
517             {
518                 byte* addr = (byte*)ptr + ofs;
519                 if ((unchecked((int)addr) & 0x7) == 0)
520                 {
521                     // aligned read
522                     return *((long*)addr);
523                 }
524                 else
525                 {
526                     // unaligned read
527                     long val;
528                     byte* valPtr = (byte*)&val;
529                     valPtr[0] = addr[0];
530                     valPtr[1] = addr[1];
531                     valPtr[2] = addr[2];
532                     valPtr[3] = addr[3];
533                     valPtr[4] = addr[4];
534                     valPtr[5] = addr[5];
535                     valPtr[6] = addr[6];
536                     valPtr[7] = addr[7];
537                     return val;
538                 }
539             }
540             catch (NullReferenceException)
541             {
542                 // this method is documented to throw AccessViolationException on any AV
543                 throw new AccessViolationException();
544             }
545         }
546
547         public static long ReadInt64(IntPtr ptr)
548         {
549             return ReadInt64(ptr, 0);
550         }
551
552         //====================================================================
553         // Read value from marshaled object (marshaled using AsAny)
554         // It's quite slow and can return back dangling pointers
555         // It's only there for backcompact
556         // I don't think we should spend time optimizing it
557         // People should really call the IntPtr overload instead
558         //====================================================================
559         private static unsafe T ReadValueSlow<T>(object ptr, int ofs, Func<IntPtr, int, T> readValueHelper)
560         {
561             // We AV on desktop if passing NULL. So this is technically a breaking change but is an improvement
562             if (ptr == null)
563                 throw new ArgumentNullException(nameof(ptr));
564
565             int dwFlags = 
566                 (int)AsAnyMarshaler.AsAnyFlags.In | 
567                 (int)AsAnyMarshaler.AsAnyFlags.IsAnsi | 
568                 (int)AsAnyMarshaler.AsAnyFlags.IsBestFit;
569
570             MngdNativeArrayMarshaler.MarshalerState nativeArrayMarshalerState = new MngdNativeArrayMarshaler.MarshalerState();                
571             AsAnyMarshaler marshaler = new AsAnyMarshaler(new IntPtr(&nativeArrayMarshalerState));
572                 
573             IntPtr pNativeHome = IntPtr.Zero;
574
575             try
576             {
577                 pNativeHome = marshaler.ConvertToNative(ptr, dwFlags);
578                 return readValueHelper(pNativeHome, ofs);
579             }
580             finally
581             {
582                 marshaler.ClearNative(pNativeHome);
583             }    
584         }
585
586
587
588         //====================================================================
589         // Write to memory
590         //====================================================================
591         public static unsafe void WriteByte(IntPtr ptr, int ofs, byte val)
592         {
593             try
594             {
595                 byte* addr = (byte*)ptr + ofs;
596                 *addr = val;
597             }
598             catch (NullReferenceException)
599             {
600                 // this method is documented to throw AccessViolationException on any AV
601                 throw new AccessViolationException();
602             }
603         }
604
605         public static void WriteByte(Object ptr, int ofs, byte val)
606         {
607             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, byte value) => Marshal.WriteByte(nativeHome, offset, value));
608         }
609
610         public static void WriteByte(IntPtr ptr, byte val)
611         {
612             WriteByte(ptr, 0, val);
613         }
614
615         public static unsafe void WriteInt16(IntPtr ptr, int ofs, short val)
616         {
617             try
618             {
619                 byte* addr = (byte*)ptr + ofs;
620                 if ((unchecked((int)addr) & 0x1) == 0)
621                 {
622                     // aligned write
623                     *((short*)addr) = val;
624                 }
625                 else
626                 {
627                     // unaligned write
628                     byte* valPtr = (byte*)&val;
629                     addr[0] = valPtr[0];
630                     addr[1] = valPtr[1];
631                 }
632             }
633             catch (NullReferenceException)
634             {
635                 // this method is documented to throw AccessViolationException on any AV
636                 throw new AccessViolationException();
637             }
638         }
639
640         public static void WriteInt16(Object ptr, int ofs, short val)
641         {
642             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, short value) => Marshal.WriteInt16(nativeHome, offset, value));
643         }
644
645         public static void WriteInt16(IntPtr ptr, short val)
646         {
647             WriteInt16(ptr, 0, val);
648         }
649
650         public static void WriteInt16(IntPtr ptr, int ofs, char val)
651         {
652             WriteInt16(ptr, ofs, (short)val);
653         }
654
655         public static void WriteInt16([In, Out]Object ptr, int ofs, char val)
656         {
657             WriteInt16(ptr, ofs, (short)val);
658         }
659
660         public static void WriteInt16(IntPtr ptr, char val)
661         {
662             WriteInt16(ptr, 0, (short)val);
663         }
664
665         public static unsafe void WriteInt32(IntPtr ptr, int ofs, int val)
666         {
667             try
668             {
669                 byte* addr = (byte*)ptr + ofs;
670                 if ((unchecked((int)addr) & 0x3) == 0)
671                 {
672                     // aligned write
673                     *((int*)addr) = val;
674                 }
675                 else
676                 {
677                     // unaligned write
678                     byte* valPtr = (byte*)&val;
679                     addr[0] = valPtr[0];
680                     addr[1] = valPtr[1];
681                     addr[2] = valPtr[2];
682                     addr[3] = valPtr[3];
683                 }
684             }
685             catch (NullReferenceException)
686             {
687                 // this method is documented to throw AccessViolationException on any AV
688                 throw new AccessViolationException();
689             }
690         }
691
692         public static void WriteInt32(Object ptr, int ofs, int val)
693         {
694             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, int value) => Marshal.WriteInt32(nativeHome, offset, value));
695         }
696
697         public static void WriteInt32(IntPtr ptr, int val)
698         {
699             WriteInt32(ptr, 0, val);
700         }
701
702         public static void WriteIntPtr(IntPtr ptr, int ofs, IntPtr val)
703         {
704 #if BIT64
705             WriteInt64(ptr, ofs, (long)val);
706 #else // 32
707                 WriteInt32(ptr, ofs, (int)val);
708 #endif
709         }
710
711         public static void WriteIntPtr(Object ptr, int ofs, IntPtr val)
712         {
713 #if BIT64
714             WriteInt64(ptr, ofs, (long)val);
715 #else // 32
716                 WriteInt32(ptr, ofs, (int)val);
717 #endif
718         }
719
720         public static void WriteIntPtr(IntPtr ptr, IntPtr val)
721         {
722 #if BIT64
723             WriteInt64(ptr, 0, (long)val);
724 #else // 32
725                 WriteInt32(ptr, 0, (int)val);
726 #endif
727         }
728
729         public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val)
730         {
731             try
732             {
733                 byte* addr = (byte*)ptr + ofs;
734                 if ((unchecked((int)addr) & 0x7) == 0)
735                 {
736                     // aligned write
737                     *((long*)addr) = val;
738                 }
739                 else
740                 {
741                     // unaligned write
742                     byte* valPtr = (byte*)&val;
743                     addr[0] = valPtr[0];
744                     addr[1] = valPtr[1];
745                     addr[2] = valPtr[2];
746                     addr[3] = valPtr[3];
747                     addr[4] = valPtr[4];
748                     addr[5] = valPtr[5];
749                     addr[6] = valPtr[6];
750                     addr[7] = valPtr[7];
751                 }
752             }
753             catch (NullReferenceException)
754             {
755                 // this method is documented to throw AccessViolationException on any AV
756                 throw new AccessViolationException();
757             }
758         }
759
760         public static void WriteInt64(Object ptr, int ofs, long val)
761         {
762             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, long value) => Marshal.WriteInt64(nativeHome, offset, value));
763         }
764
765         public static void WriteInt64(IntPtr ptr, long val)
766         {
767             WriteInt64(ptr, 0, val);
768         }
769
770         //====================================================================
771         // Write value into marshaled object (marshaled using AsAny) and
772         // propagate the value back
773         // It's quite slow and is only there for backcompact
774         // I don't think we should spend time optimizing it
775         // People should really call the IntPtr overload instead
776         //====================================================================
777         private static unsafe void WriteValueSlow<T>(object ptr, int ofs, T val, Action<IntPtr, int, T> writeValueHelper)
778         {
779             // We AV on desktop if passing NULL. So this is technically a breaking change but is an improvement
780             if (ptr == null)
781                 throw new ArgumentNullException(nameof(ptr));
782                             
783             int dwFlags = 
784                 (int)AsAnyMarshaler.AsAnyFlags.In | 
785                 (int)AsAnyMarshaler.AsAnyFlags.Out | 
786                 (int)AsAnyMarshaler.AsAnyFlags.IsAnsi | 
787                 (int)AsAnyMarshaler.AsAnyFlags.IsBestFit;
788
789             MngdNativeArrayMarshaler.MarshalerState nativeArrayMarshalerState = new MngdNativeArrayMarshaler.MarshalerState();                
790             AsAnyMarshaler marshaler = new AsAnyMarshaler(new IntPtr(&nativeArrayMarshalerState));
791                 
792             IntPtr pNativeHome = IntPtr.Zero;
793
794             try
795             {
796                 pNativeHome = marshaler.ConvertToNative(ptr, dwFlags);
797                 writeValueHelper(pNativeHome, ofs, val);
798                 marshaler.ConvertToManaged(ptr, pNativeHome);
799             }
800             finally
801             {
802                 marshaler.ClearNative(pNativeHome);
803             }            
804         }
805
806         //====================================================================
807         // GetLastWin32Error
808         //====================================================================
809         [MethodImplAttribute(MethodImplOptions.InternalCall)]
810         public static extern int GetLastWin32Error();
811
812
813         //====================================================================
814         // SetLastWin32Error
815         //====================================================================
816         [MethodImplAttribute(MethodImplOptions.InternalCall)]
817         internal static extern void SetLastWin32Error(int error);
818
819
820         //====================================================================
821         // GetHRForLastWin32Error
822         //====================================================================
823         public static int GetHRForLastWin32Error()
824         {
825             int dwLastError = GetLastWin32Error();
826             if ((dwLastError & 0x80000000) == 0x80000000)
827                 return dwLastError;
828             else
829                 return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000);
830         }
831
832
833         //====================================================================
834         // Prelink
835         //====================================================================
836         public static void Prelink(MethodInfo m)
837         {
838             if (m == null)
839                 throw new ArgumentNullException(nameof(m));
840
841             RuntimeMethodInfo rmi = m as RuntimeMethodInfo;
842
843             if (rmi == null)
844                 throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo);
845
846             InternalPrelink(rmi);
847         }
848
849         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
850         private static extern void InternalPrelink(IRuntimeMethodInfo m);
851
852         public static void PrelinkAll(Type c)
853         {
854             if (c == null)
855                 throw new ArgumentNullException(nameof(c));
856
857             MethodInfo[] mi = c.GetMethods();
858             if (mi != null)
859             {
860                 for (int i = 0; i < mi.Length; i++)
861                 {
862                     Prelink(mi[i]);
863                 }
864             }
865         }
866
867         [MethodImplAttribute(MethodImplOptions.InternalCall)]
868         public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers();
869         
870         [MethodImplAttribute(MethodImplOptions.InternalCall)]
871         public static extern int GetExceptionCode();
872
873
874         //====================================================================
875         // Marshals data from a structure class to a native memory block.
876         // If the structure contains pointers to allocated blocks and
877         // "fDeleteOld" is true, this routine will call DestroyStructure() first. 
878         //====================================================================
879         [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
880         public static extern void StructureToPtr(Object structure, IntPtr ptr, bool fDeleteOld);
881
882         public static void StructureToPtr<T>(T structure, IntPtr ptr, bool fDeleteOld)
883         {
884             StructureToPtr((object)structure, ptr, fDeleteOld);
885         }
886
887         //====================================================================
888         // Marshals data from a native memory block to a preallocated structure class.
889         //====================================================================
890         public static void PtrToStructure(IntPtr ptr, Object structure)
891         {
892             PtrToStructureHelper(ptr, structure, false);
893         }
894
895         public static void PtrToStructure<T>(IntPtr ptr, T structure)
896         {
897             PtrToStructure(ptr, (object)structure);
898         }
899
900         //====================================================================
901         // Creates a new instance of "structuretype" and marshals data from a
902         // native memory block to it.
903         //====================================================================
904         public static Object PtrToStructure(IntPtr ptr, Type structureType)
905         {
906             if (ptr == IntPtr.Zero) return null;
907
908             if (structureType == null)
909                 throw new ArgumentNullException(nameof(structureType));
910
911             if (structureType.IsGenericType)
912                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(structureType));
913
914             RuntimeType rt = structureType.UnderlyingSystemType as RuntimeType;
915
916             if (rt == null)
917                 throw new ArgumentException(SR.Arg_MustBeType, nameof(structureType));
918
919             Object structure = rt.CreateInstanceDefaultCtor(false /*publicOnly*/, false /*skipCheckThis*/, false /*fillCache*/, true /*wrapExceptions*/);
920             PtrToStructureHelper(ptr, structure, true);
921             return structure;
922         }
923
924         public static T PtrToStructure<T>(IntPtr ptr)
925         {
926             return (T)PtrToStructure(ptr, typeof(T));
927         }
928
929         //====================================================================
930         // Helper function to copy a pointer into a preallocated structure.
931         //====================================================================
932         [MethodImplAttribute(MethodImplOptions.InternalCall)]
933         private static extern void PtrToStructureHelper(IntPtr ptr, Object structure, bool allowValueClasses);
934
935
936         //====================================================================
937         // Freeds all substructures pointed to by the native memory block.
938         // "structureclass" is used to provide layout information.
939         //====================================================================
940         [MethodImplAttribute(MethodImplOptions.InternalCall)]
941         public static extern void DestroyStructure(IntPtr ptr, Type structuretype);
942
943         public static void DestroyStructure<T>(IntPtr ptr)
944         {
945             DestroyStructure(ptr, typeof(T));
946         }
947
948 #if FEATURE_COMINTEROP
949         //====================================================================
950         // Returns the HInstance for this module.  Returns -1 if the module 
951         // doesn't have an HInstance.  In Memory (Dynamic) Modules won't have 
952         // an HInstance.
953         //====================================================================
954         public static IntPtr GetHINSTANCE(Module m)
955         {
956             if (m == null)
957                 throw new ArgumentNullException(nameof(m));
958
959             RuntimeModule rtModule = m as RuntimeModule;
960             if (rtModule == null)
961             {
962                 ModuleBuilder mb = m as ModuleBuilder;
963                 if (mb != null)
964                     rtModule = mb.InternalModule;
965             }
966
967             if (rtModule == null)
968                 throw new ArgumentNullException(nameof(m), SR.Argument_MustBeRuntimeModule);
969
970             return GetHINSTANCE(rtModule.GetNativeHandle());
971         }
972
973         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
974         private static extern IntPtr GetHINSTANCE(RuntimeModule m);
975
976 #endif // FEATURE_COMINTEROP
977         //====================================================================
978         // Throws a CLR exception based on the HRESULT.
979         //====================================================================
980         public static void ThrowExceptionForHR(int errorCode)
981         {
982             if (errorCode < 0)
983                 ThrowExceptionForHRInternal(errorCode, IntPtr.Zero);
984         }
985         public static void ThrowExceptionForHR(int errorCode, IntPtr errorInfo)
986         {
987             if (errorCode < 0)
988                 ThrowExceptionForHRInternal(errorCode, errorInfo);
989         }
990
991         [MethodImplAttribute(MethodImplOptions.InternalCall)]
992         internal static extern void ThrowExceptionForHRInternal(int errorCode, IntPtr errorInfo);
993
994
995         //====================================================================
996         // Converts the HRESULT to a CLR exception.
997         //====================================================================
998         public static Exception GetExceptionForHR(int errorCode)
999         {
1000             if (errorCode < 0)
1001                 return GetExceptionForHRInternal(errorCode, IntPtr.Zero);
1002             else
1003                 return null;
1004         }
1005         public static Exception GetExceptionForHR(int errorCode, IntPtr errorInfo)
1006         {
1007             if (errorCode < 0)
1008                 return GetExceptionForHRInternal(errorCode, errorInfo);
1009             else
1010                 return null;
1011         }
1012
1013         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1014         internal static extern Exception GetExceptionForHRInternal(int errorCode, IntPtr errorInfo);
1015
1016
1017         //====================================================================
1018         // Memory allocation and deallocation.
1019         //====================================================================
1020         public static IntPtr AllocHGlobal(IntPtr cb)
1021         {
1022             // For backwards compatibility on 32 bit platforms, ensure we pass values between 
1023             // Int32.MaxValue and UInt32.MaxValue to Windows.  If the binary has had the 
1024             // LARGEADDRESSAWARE bit set in the PE header, it may get 3 or 4 GB of user mode
1025             // address space.  It is remotely that those allocations could have succeeded,
1026             // though I couldn't reproduce that.  In either case, that means we should continue
1027             // throwing an OOM instead of an ArgumentOutOfRangeException for "negative" amounts of memory.
1028             UIntPtr numBytes;
1029 #if BIT64
1030             numBytes = new UIntPtr(unchecked((ulong)cb.ToInt64()));
1031 #else // 32
1032             numBytes = new UIntPtr(unchecked((uint)cb.ToInt32()));
1033 #endif
1034
1035             IntPtr pNewMem = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, unchecked(numBytes));
1036
1037             if (pNewMem == IntPtr.Zero)
1038             {
1039                 throw new OutOfMemoryException();
1040             }
1041             return pNewMem;
1042         }
1043
1044         public static IntPtr AllocHGlobal(int cb)
1045         {
1046             return AllocHGlobal((IntPtr)cb);
1047         }
1048
1049         public static void FreeHGlobal(IntPtr hglobal)
1050         {
1051             if (IsNotWin32Atom(hglobal))
1052             {
1053                 if (IntPtr.Zero != Win32Native.LocalFree(hglobal))
1054                 {
1055                     ThrowExceptionForHR(GetHRForLastWin32Error());
1056                 }
1057             }
1058         }
1059
1060         public static IntPtr ReAllocHGlobal(IntPtr pv, IntPtr cb)
1061         {
1062             IntPtr pNewMem = Win32Native.LocalReAlloc(pv, cb, LMEM_MOVEABLE);
1063             if (pNewMem == IntPtr.Zero)
1064             {
1065                 throw new OutOfMemoryException();
1066             }
1067             return pNewMem;
1068         }
1069
1070
1071         //====================================================================
1072         // String convertions.
1073         //====================================================================          
1074         public static unsafe IntPtr StringToHGlobalAnsi(string s)
1075         {
1076             if (s == null)
1077             {
1078                 return IntPtr.Zero;
1079             }
1080             else
1081             {
1082                 int nb = (s.Length + 1) * SystemMaxDBCSCharSize;
1083
1084                 // Overflow checking
1085                 if (nb < s.Length)
1086                     throw new ArgumentOutOfRangeException(nameof(s));
1087
1088                 UIntPtr len = new UIntPtr((uint)nb);
1089                 IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len);
1090
1091                 if (hglobal == IntPtr.Zero)
1092                 {
1093                     throw new OutOfMemoryException();
1094                 }
1095                 else
1096                 {
1097                     s.ConvertToAnsi((byte*)hglobal, nb, false, false);
1098                     return hglobal;
1099                 }
1100             }
1101         }
1102
1103         public static unsafe IntPtr StringToHGlobalUni(string s)
1104         {
1105             if (s == null)
1106             {
1107                 return IntPtr.Zero;
1108             }
1109             else
1110             {
1111                 int nb = (s.Length + 1) * 2;
1112
1113                 // Overflow checking
1114                 if (nb < s.Length)
1115                     throw new ArgumentOutOfRangeException(nameof(s));
1116
1117                 UIntPtr len = new UIntPtr((uint)nb);
1118                 IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len);
1119
1120                 if (hglobal == IntPtr.Zero)
1121                 {
1122                     throw new OutOfMemoryException();
1123                 }
1124                 else
1125                 {
1126                     fixed (char* firstChar = s)
1127                     {
1128                         string.wstrcpy((char*)hglobal, firstChar, s.Length + 1);
1129                     }
1130                     return hglobal;
1131                 }
1132             }
1133         }
1134
1135         public static IntPtr StringToHGlobalAuto(string s)
1136         {
1137             // Ansi platforms are no longer supported
1138             return StringToHGlobalUni(s);
1139         }
1140
1141 #if FEATURE_COMINTEROP
1142
1143         //====================================================================
1144         // Converts the CLR exception to an HRESULT. This function also sets
1145         // up an IErrorInfo for the exception.
1146         //====================================================================
1147         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1148         public static extern int GetHRForException(Exception e);
1149
1150         //====================================================================
1151         // Converts the CLR exception to an HRESULT. This function also sets
1152         // up an IErrorInfo for the exception.
1153         // This function is only used in WinRT and converts ObjectDisposedException
1154         // to RO_E_CLOSED
1155         //====================================================================
1156         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1157         internal static extern int GetHRForException_WinRT(Exception e);
1158
1159         internal static readonly Guid ManagedNameGuid = new Guid("{0F21F359-AB84-41E8-9A78-36D110E6D2F9}");
1160
1161         //====================================================================
1162         // Given a managed object that wraps an ITypeInfo, return its name
1163         //====================================================================
1164         public static string GetTypeInfoName(ITypeInfo typeInfo)
1165         {
1166             if (typeInfo == null)
1167                 throw new ArgumentNullException(nameof(typeInfo));
1168
1169             string strTypeLibName = null;
1170             string strDocString = null;
1171             int dwHelpContext = 0;
1172             string strHelpFile = null;
1173
1174             typeInfo.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile);
1175
1176             return strTypeLibName;
1177         }
1178
1179         // This method is identical to Type.GetTypeFromCLSID. Since it's interop specific, we expose it
1180         // on Marshal for more consistent API surface.
1181         public static Type GetTypeFromCLSID(Guid clsid)
1182         {
1183             return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, false);
1184         }
1185
1186         //====================================================================
1187         // return the IUnknown* for an Object if the current context
1188         // is the one where the RCW was first seen. Will return null 
1189         // otherwise.
1190         //====================================================================
1191         public static IntPtr /* IUnknown* */ GetIUnknownForObject(Object o)
1192         {
1193             return GetIUnknownForObjectNative(o, false);
1194         }
1195
1196         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1197         private static extern IntPtr /* IUnknown* */ GetIUnknownForObjectNative(Object o, bool onlyInContext);
1198
1199         //====================================================================
1200         // return the raw IUnknown* for a COM Object not related to current 
1201         // context
1202         // Does not call AddRef
1203         //====================================================================
1204         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1205         internal static extern IntPtr /* IUnknown* */ GetRawIUnknownForComObjectNoAddRef(Object o);
1206 #endif // FEATURE_COMINTEROP
1207
1208         //====================================================================
1209         // return the IDispatch* for an Object
1210         //====================================================================
1211         public static IntPtr /* IDispatch */ GetIDispatchForObject(Object o)
1212         {
1213             throw new PlatformNotSupportedException();
1214         }
1215
1216 #if FEATURE_COMINTEROP
1217
1218         //====================================================================
1219         // return the IUnknown* representing the interface for the Object
1220         // Object o should support Type T
1221         //====================================================================
1222         public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T)
1223         {
1224             return GetComInterfaceForObjectNative(o, T, false, true);
1225         }
1226
1227         public static IntPtr GetComInterfaceForObject<T, TInterface>(T o)
1228         {
1229             return GetComInterfaceForObject(o, typeof(TInterface));
1230         }
1231
1232         //====================================================================
1233         // return the IUnknown* representing the interface for the Object
1234         // Object o should support Type T, it refer the value of mode to 
1235         // invoke customized QueryInterface or not
1236         //====================================================================
1237         public static IntPtr /* IUnknown* */ GetComInterfaceForObject(Object o, Type T, CustomQueryInterfaceMode mode)
1238         {
1239             bool bEnableCustomizedQueryInterface = ((mode == CustomQueryInterfaceMode.Allow) ? true : false);
1240             return GetComInterfaceForObjectNative(o, T, false, bEnableCustomizedQueryInterface);
1241         }
1242
1243         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1244         private static extern IntPtr /* IUnknown* */ GetComInterfaceForObjectNative(Object o, Type t, bool onlyInContext, bool fEnalbeCustomizedQueryInterface);
1245
1246         //====================================================================
1247         // return an Object for IUnknown
1248         //====================================================================
1249         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1250         public static extern Object GetObjectForIUnknown(IntPtr /* IUnknown* */ pUnk);
1251
1252         //====================================================================
1253         // Return a unique Object given an IUnknown.  This ensures that you
1254         //  receive a fresh object (we will not look in the cache to match up this
1255         //  IUnknown to an already existing object).  This is useful in cases
1256         //  where you want to be able to call ReleaseComObject on a RCW
1257         //  and not worry about other active uses of said RCW.
1258         //====================================================================
1259         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1260         public static extern Object GetUniqueObjectForIUnknown(IntPtr unknown);
1261
1262         //====================================================================
1263         // return an Object for IUnknown, using the Type T, 
1264         //  NOTE: 
1265         //  Type T should be either a COM imported Type or a sub-type of COM 
1266         //  imported Type
1267         //====================================================================
1268         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1269         public static extern Object GetTypedObjectForIUnknown(IntPtr /* IUnknown* */ pUnk, Type t);
1270
1271         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1272         public static extern IntPtr CreateAggregatedObject(IntPtr pOuter, Object o);
1273
1274         public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o)
1275         {
1276             return CreateAggregatedObject(pOuter, (object)o);
1277         }
1278
1279         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1280         public static extern void CleanupUnusedObjectsInCurrentContext();
1281
1282         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1283         public static extern bool AreComObjectsAvailableForCleanup();
1284
1285         //====================================================================
1286         // check if the object is classic COM component
1287         //====================================================================
1288         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1289         public static extern bool IsComObject(Object o);
1290
1291 #endif // FEATURE_COMINTEROP
1292
1293         public static IntPtr AllocCoTaskMem(int cb)
1294         {
1295             IntPtr pNewMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)cb));
1296             if (pNewMem == IntPtr.Zero)
1297             {
1298                 throw new OutOfMemoryException();
1299             }
1300             return pNewMem;
1301         }
1302
1303         public static unsafe IntPtr StringToCoTaskMemUni(string s)
1304         {
1305             if (s == null)
1306             {
1307                 return IntPtr.Zero;
1308             }
1309             else
1310             {
1311                 int nb = (s.Length + 1) * 2;
1312
1313                 // Overflow checking
1314                 if (nb < s.Length)
1315                     throw new ArgumentOutOfRangeException(nameof(s));
1316
1317                 IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb));
1318
1319                 if (hglobal == IntPtr.Zero)
1320                 {
1321                     throw new OutOfMemoryException();
1322                 }
1323                 else
1324                 {
1325                     fixed (char* firstChar = s)
1326                     {
1327                         string.wstrcpy((char*)hglobal, firstChar, s.Length + 1);
1328                     }
1329                     return hglobal;
1330                 }
1331             }
1332         }
1333
1334         public static unsafe IntPtr StringToCoTaskMemUTF8(string s)
1335         {
1336             if (s == null)
1337             {
1338                 return IntPtr.Zero;
1339             }
1340             else
1341             {
1342                 int nb = Encoding.UTF8.GetMaxByteCount(s.Length);
1343
1344                 IntPtr pMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb + 1));
1345
1346                 if (pMem == IntPtr.Zero)
1347                 {
1348                     throw new OutOfMemoryException();
1349                 }
1350                 else
1351                 {
1352                     fixed (char* firstChar = s)
1353                     {
1354                         byte* pbMem = (byte*)pMem;
1355                         int nbWritten = Encoding.UTF8.GetBytes(firstChar, s.Length, pbMem, nb);
1356                         pbMem[nbWritten] = 0;
1357                     }
1358                     return pMem;
1359                 }
1360             }
1361         }
1362
1363         public static IntPtr StringToCoTaskMemAuto(string s)
1364         {
1365             // Ansi platforms are no longer supported
1366             return StringToCoTaskMemUni(s);
1367         }
1368
1369         public static unsafe IntPtr StringToCoTaskMemAnsi(string s)
1370         {
1371             if (s == null)
1372             {
1373                 return IntPtr.Zero;
1374             }
1375             else
1376             {
1377                 int nb = (s.Length + 1) * SystemMaxDBCSCharSize;
1378
1379                 // Overflow checking
1380                 if (nb < s.Length)
1381                     throw new ArgumentOutOfRangeException(nameof(s));
1382
1383                 IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb));
1384
1385                 if (hglobal == IntPtr.Zero)
1386                 {
1387                     throw new OutOfMemoryException();
1388                 }
1389                 else
1390                 {
1391                     s.ConvertToAnsi((byte*)hglobal, nb, false, false);
1392                     return hglobal;
1393                 }
1394             }
1395         }
1396
1397         public static void FreeCoTaskMem(IntPtr ptr)
1398         {
1399             if (IsNotWin32Atom(ptr))
1400             {
1401                 Win32Native.CoTaskMemFree(ptr);
1402             }
1403         }
1404
1405         public static IntPtr ReAllocCoTaskMem(IntPtr pv, int cb)
1406         {
1407             IntPtr pNewMem = Win32Native.CoTaskMemRealloc(pv, new UIntPtr((uint)cb));
1408             if (pNewMem == IntPtr.Zero && cb != 0)
1409             {
1410                 throw new OutOfMemoryException();
1411             }
1412             return pNewMem;
1413         }
1414
1415         //====================================================================
1416         // BSTR allocation and dealocation.
1417         //====================================================================      
1418         public static void FreeBSTR(IntPtr ptr)
1419         {
1420             if (IsNotWin32Atom(ptr))
1421             {
1422                 Win32Native.SysFreeString(ptr);
1423             }
1424         }
1425
1426         public static IntPtr StringToBSTR(string s)
1427         {
1428             if (s == null)
1429                 return IntPtr.Zero;
1430
1431             // Overflow checking
1432             if (s.Length + 1 < s.Length)
1433                 throw new ArgumentOutOfRangeException(nameof(s));
1434
1435             IntPtr bstr = Win32Native.SysAllocStringLen(s, s.Length);
1436             if (bstr == IntPtr.Zero)
1437                 throw new OutOfMemoryException();
1438
1439             return bstr;
1440         }
1441
1442         public static string PtrToStringBSTR(IntPtr ptr)
1443         {
1444             return PtrToStringUni(ptr, (int)Win32Native.SysStringLen(ptr));
1445         }
1446
1447 #if FEATURE_COMINTEROP
1448         //====================================================================
1449         // release the COM component and if the reference hits 0 zombie this object
1450         // further usage of this Object might throw an exception
1451         //====================================================================
1452         public static int ReleaseComObject(Object o)
1453         {
1454             __ComObject co = null;
1455
1456             // Make sure the obj is an __ComObject.
1457             try
1458             {
1459                 co = (__ComObject)o;
1460             }
1461             catch (InvalidCastException)
1462             {
1463                 throw new ArgumentException(SR.Argument_ObjNotComObject, nameof(o));
1464             }
1465
1466             return co.ReleaseSelf();
1467         }
1468
1469         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1470         internal static extern int InternalReleaseComObject(Object o);
1471
1472
1473         //====================================================================
1474         // release the COM component and zombie this object
1475         // further usage of this Object might throw an exception
1476         //====================================================================
1477         public static Int32 FinalReleaseComObject(Object o)
1478         {
1479             if (o == null)
1480                 throw new ArgumentNullException(nameof(o));
1481
1482             __ComObject co = null;
1483
1484             // Make sure the obj is an __ComObject.
1485             try
1486             {
1487                 co = (__ComObject)o;
1488             }
1489             catch (InvalidCastException)
1490             {
1491                 throw new ArgumentException(SR.Argument_ObjNotComObject, nameof(o));
1492             }
1493
1494             co.FinalReleaseSelf();
1495
1496             return 0;
1497         }
1498
1499         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1500         internal static extern void InternalFinalReleaseComObject(Object o);
1501 #endif // FEATURE_COMINTEROP
1502
1503         //====================================================================
1504         // This method retrieves data from the COM object.
1505         //====================================================================
1506         public static Object GetComObjectData(Object obj, Object key)
1507         {
1508             throw new PlatformNotSupportedException(SR.Arg_PlatformNotSupported);
1509         }
1510
1511         //====================================================================
1512         // This method sets data on the COM object. The data can only be set 
1513         // once for a given key and cannot be removed. This function returns
1514         // true if the data has been added, false if the data could not be
1515         // added because there already was data for the specified key.
1516         //====================================================================
1517         public static bool SetComObjectData(Object obj, Object key, Object data)
1518         {
1519             throw new PlatformNotSupportedException(SR.Arg_PlatformNotSupported);
1520         }
1521
1522 #if FEATURE_COMINTEROP
1523         //====================================================================
1524         // This method takes the given COM object and wraps it in an object
1525         // of the specified type. The type must be derived from __ComObject.
1526         //====================================================================
1527         public static Object CreateWrapperOfType(Object o, Type t)
1528         {
1529             // Validate the arguments.
1530             if (t == null)
1531                 throw new ArgumentNullException(nameof(t));
1532             if (!t.IsCOMObject)
1533                 throw new ArgumentException(SR.Argument_TypeNotComObject, nameof(t));
1534             if (t.IsGenericType)
1535                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
1536
1537             if (t.IsWindowsRuntimeObject)
1538                 throw new ArgumentException(SR.Argument_TypeIsWinRTType, nameof(t));
1539
1540             // Check for the null case.
1541             if (o == null)
1542                 return null;
1543
1544             // Make sure the object is a COM object.
1545             if (!o.GetType().IsCOMObject)
1546                 throw new ArgumentException(SR.Argument_ObjNotComObject, nameof(o));
1547             if (o.GetType().IsWindowsRuntimeObject)
1548                 throw new ArgumentException(SR.Argument_ObjIsWinRTObject, nameof(o));
1549
1550             // Check to see if the type of the object is the requested type.
1551             if (o.GetType() == t)
1552                 return o;
1553
1554             // Check to see if we already have a cached wrapper for this type.
1555             Object Wrapper = GetComObjectData(o, t);
1556             if (Wrapper == null)
1557             {
1558                 // Create the wrapper for the specified type.
1559                 Wrapper = InternalCreateWrapperOfType(o, t);
1560
1561                 // Attempt to cache the wrapper on the object.
1562                 if (!SetComObjectData(o, t, Wrapper))
1563                 {
1564                     // Another thead already cached the wrapper so use that one instead.
1565                     Wrapper = GetComObjectData(o, t);
1566                 }
1567             }
1568
1569             return Wrapper;
1570         }
1571
1572         public static TWrapper CreateWrapperOfType<T, TWrapper>(T o)
1573         {
1574             return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper));
1575         }
1576
1577         //====================================================================
1578         // Helper method called from CreateWrapperOfType.
1579         //====================================================================
1580         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1581         private static extern Object InternalCreateWrapperOfType(Object o, Type t);
1582
1583         //====================================================================
1584         // IUnknown Helpers
1585         //====================================================================
1586         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1587         public static extern int /* HRESULT */ QueryInterface(IntPtr /* IUnknown */ pUnk, ref Guid iid, out IntPtr ppv);
1588
1589         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1590         public static extern int /* ULONG */ AddRef(IntPtr /* IUnknown */ pUnk);
1591         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1592         public static extern int /* ULONG */ Release(IntPtr /* IUnknown */ pUnk);
1593
1594         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1595         public static extern void GetNativeVariantForObject(Object obj, /* VARIANT * */ IntPtr pDstNativeVariant);
1596
1597         public static void GetNativeVariantForObject<T>(T obj, IntPtr pDstNativeVariant)
1598         {
1599             GetNativeVariantForObject((object)obj, pDstNativeVariant);
1600         }
1601
1602         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1603         public static extern Object GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant);
1604
1605         public static T GetObjectForNativeVariant<T>(IntPtr pSrcNativeVariant)
1606         {
1607             return (T)GetObjectForNativeVariant(pSrcNativeVariant);
1608         }
1609
1610         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1611         public static extern Object[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars);
1612
1613         public static T[] GetObjectsForNativeVariants<T>(IntPtr aSrcNativeVariant, int cVars)
1614         {
1615             object[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars);
1616             T[] result = null;
1617
1618             if (objects != null)
1619             {
1620                 result = new T[objects.Length];
1621                 Array.Copy(objects, result, objects.Length);
1622             }
1623
1624             return result;
1625         }
1626
1627         /// <summary>
1628         /// <para>Returns the first valid COM slot that GetMethodInfoForSlot will work on
1629         /// This will be 3 for IUnknown based interfaces and 7 for IDispatch based interfaces. </para>
1630         /// </summary>
1631         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1632         public static extern int GetStartComSlot(Type t);
1633
1634 #endif // FEATURE_COMINTEROP
1635
1636         //====================================================================
1637         // This method generates a GUID for the specified type. If the type
1638         // has a GUID in the metadata then it is returned otherwise a stable
1639         // guid GUID is generated based on the fully qualified name of the 
1640         // type.
1641         //====================================================================
1642         public static Guid GenerateGuidForType(Type type)
1643         {
1644             return type.GUID;
1645         }
1646
1647         //====================================================================
1648         // This method generates a PROGID for the specified type. If the type
1649         // has a PROGID in the metadata then it is returned otherwise a stable
1650         // PROGID is generated based on the fully qualified name of the 
1651         // type.
1652         //====================================================================
1653         public static string GenerateProgIdForType(Type type)
1654         {
1655             if (type == null)
1656                 throw new ArgumentNullException(nameof(type));
1657             if (type.IsImport)
1658                 throw new ArgumentException(SR.Argument_TypeMustNotBeComImport, nameof(type));
1659             if (type.IsGenericType)
1660                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type));
1661
1662             IList<CustomAttributeData> cas = CustomAttributeData.GetCustomAttributes(type);
1663             for (int i = 0; i < cas.Count; i++)
1664             {
1665                 if (cas[i].Constructor.DeclaringType == typeof(ProgIdAttribute))
1666                 {
1667                     // Retrieve the PROGID string from the ProgIdAttribute.
1668                     IList<CustomAttributeTypedArgument> caConstructorArgs = cas[i].ConstructorArguments;
1669                     Debug.Assert(caConstructorArgs.Count == 1, "caConstructorArgs.Count == 1");
1670
1671                     CustomAttributeTypedArgument progIdConstructorArg = caConstructorArgs[0];
1672                     Debug.Assert(progIdConstructorArg.ArgumentType == typeof(string), "progIdConstructorArg.ArgumentType == typeof(String)");
1673
1674                     string strProgId = (string)progIdConstructorArg.Value;
1675
1676                     if (strProgId == null)
1677                         strProgId = string.Empty;
1678
1679                     return strProgId;
1680                 }
1681             }
1682
1683             // If there is no prog ID attribute then use the full name of the type as the prog id.
1684             return type.FullName;
1685         }
1686
1687 #if FEATURE_COMINTEROP
1688         //====================================================================
1689         // This method binds to the specified moniker.
1690         //====================================================================
1691         public static Object BindToMoniker(string monikerName)
1692         {
1693             Object obj = null;
1694             IBindCtx bindctx = null;
1695             CreateBindCtx(0, out bindctx);
1696
1697             UInt32 cbEaten;
1698             IMoniker pmoniker = null;
1699             MkParseDisplayName(bindctx, monikerName, out cbEaten, out pmoniker);
1700
1701             BindMoniker(pmoniker, 0, ref IID_IUnknown, out obj);
1702             return obj;
1703         }
1704
1705         [DllImport(Interop.Libraries.Ole32, PreserveSig = false)]
1706         private static extern void CreateBindCtx(UInt32 reserved, out IBindCtx ppbc);
1707
1708         [DllImport(Interop.Libraries.Ole32, PreserveSig = false)]
1709         private static extern void MkParseDisplayName(IBindCtx pbc, [MarshalAs(UnmanagedType.LPWStr)] string szUserName, out UInt32 pchEaten, out IMoniker ppmk);
1710
1711         [DllImport(Interop.Libraries.Ole32, PreserveSig = false)]
1712         private static extern void BindMoniker(IMoniker pmk, UInt32 grfOpt, ref Guid iidResult, [MarshalAs(UnmanagedType.Interface)] out Object ppvResult);
1713
1714         //========================================================================
1715         // Private method called from EE upon use of license/ICF2 marshaling.
1716         //========================================================================
1717         private static IntPtr LoadLicenseManager()
1718         {
1719             Type t = Type.GetType("System.ComponentModel.LicenseManager, System", throwOnError: true);
1720             return t.TypeHandle.Value;
1721         }
1722
1723         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1724         public static extern void ChangeWrapperHandleStrength(Object otp, bool fIsWeak);
1725
1726         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1727         internal static extern void InitializeWrapperForWinRT(object o, ref IntPtr pUnk);
1728
1729 #if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
1730         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1731         internal static extern void InitializeManagedWinRTFactoryObject(object o, RuntimeType runtimeClassType);
1732 #endif
1733
1734         //========================================================================
1735         // Create activation factory and wraps it with a unique RCW
1736         //========================================================================
1737         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1738         internal static extern object GetNativeActivationFactory(Type type);
1739
1740 #endif // FEATURE_COMINTEROP
1741
1742         public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t)
1743         {
1744             // Validate the parameters
1745             if (ptr == IntPtr.Zero)
1746                 throw new ArgumentNullException(nameof(ptr));
1747
1748             if (t == null)
1749                 throw new ArgumentNullException(nameof(t));
1750
1751             if ((t as RuntimeType) == null)
1752                 throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(t));
1753
1754             if (t.IsGenericType)
1755                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
1756
1757             Type c = t.BaseType;
1758             if (c == null || (c != typeof(Delegate) && c != typeof(MulticastDelegate)))
1759                 throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(t));
1760
1761             return GetDelegateForFunctionPointerInternal(ptr, t);
1762         }
1763
1764         public static TDelegate GetDelegateForFunctionPointer<TDelegate>(IntPtr ptr)
1765         {
1766             return (TDelegate)(object)GetDelegateForFunctionPointer(ptr, typeof(TDelegate));
1767         }
1768
1769         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1770         internal static extern Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t);
1771
1772         public static IntPtr GetFunctionPointerForDelegate(Delegate d)
1773         {
1774             if (d == null)
1775                 throw new ArgumentNullException(nameof(d));
1776
1777             return GetFunctionPointerForDelegateInternal(d);
1778         }
1779
1780         public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d)
1781         {
1782             return GetFunctionPointerForDelegate((Delegate)(object)d);
1783         }
1784
1785         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1786         internal static extern IntPtr GetFunctionPointerForDelegateInternal(Delegate d);
1787
1788         public static IntPtr SecureStringToBSTR(SecureString s)
1789         {
1790             if (s == null)
1791             {
1792                 throw new ArgumentNullException(nameof(s));
1793             }
1794
1795             return s.MarshalToBSTR();
1796         }
1797
1798         public static IntPtr SecureStringToCoTaskMemAnsi(SecureString s)
1799         {
1800             if (s == null)
1801             {
1802                 throw new ArgumentNullException(nameof(s));
1803             }
1804
1805             return s.MarshalToString(globalAlloc: false, unicode: false);
1806         }
1807
1808         public static IntPtr SecureStringToCoTaskMemUnicode(SecureString s)
1809         {
1810             if (s == null)
1811             {
1812                 throw new ArgumentNullException(nameof(s));
1813             }
1814
1815             return s.MarshalToString(globalAlloc: false, unicode: true);
1816         }
1817         
1818         public static void ZeroFreeBSTR(IntPtr s)
1819         {
1820             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.SysStringLen(s) * 2));
1821             FreeBSTR(s);
1822         }
1823
1824         public static void ZeroFreeCoTaskMemAnsi(IntPtr s)
1825         {
1826             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s)));
1827             FreeCoTaskMem(s);
1828         }
1829
1830         public static void ZeroFreeCoTaskMemUnicode(IntPtr s)
1831         {
1832             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2));
1833             FreeCoTaskMem(s);
1834         }
1835
1836         public static unsafe void ZeroFreeCoTaskMemUTF8(IntPtr s)
1837         {
1838             RuntimeImports.RhZeroMemory(s, (UIntPtr)System.StubHelpers.StubHelpers.strlen((sbyte*)s));
1839             FreeCoTaskMem(s);
1840         }
1841
1842         public static IntPtr SecureStringToGlobalAllocAnsi(SecureString s)
1843         {
1844             if (s == null)
1845             {
1846                 throw new ArgumentNullException(nameof(s));
1847             }
1848
1849             return s.MarshalToString(globalAlloc: true, unicode: false);
1850         }
1851
1852         public static IntPtr SecureStringToGlobalAllocUnicode(SecureString s)
1853         {
1854             if (s == null)
1855             {
1856                 throw new ArgumentNullException(nameof(s));
1857             }
1858
1859             return s.MarshalToString(globalAlloc: true, unicode: true); ;
1860         }
1861
1862         public static void ZeroFreeGlobalAllocAnsi(IntPtr s)
1863         {
1864             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s)));
1865             FreeHGlobal(s);
1866         }
1867
1868         public static void ZeroFreeGlobalAllocUnicode(IntPtr s)
1869         {
1870             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2));
1871             FreeHGlobal(s);
1872         }
1873     }
1874 }
1875