Update certain Marshal APIs to match exception thrown on .NET Framework (#18791)
[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         // People should instead use the IntPtr overloads
557         //====================================================================
558         private static unsafe T ReadValueSlow<T>(object ptr, int ofs, Func<IntPtr, int, T> readValueHelper)
559         {
560             // Consumers of this method are documented to throw AccessViolationException on any AV
561             if (ptr == null)
562                 throw new AccessViolationException();
563
564             int dwFlags = 
565                 (int)AsAnyMarshaler.AsAnyFlags.In | 
566                 (int)AsAnyMarshaler.AsAnyFlags.IsAnsi | 
567                 (int)AsAnyMarshaler.AsAnyFlags.IsBestFit;
568
569             MngdNativeArrayMarshaler.MarshalerState nativeArrayMarshalerState = new MngdNativeArrayMarshaler.MarshalerState();
570             AsAnyMarshaler marshaler = new AsAnyMarshaler(new IntPtr(&nativeArrayMarshalerState));
571
572             IntPtr pNativeHome = IntPtr.Zero;
573
574             try
575             {
576                 pNativeHome = marshaler.ConvertToNative(ptr, dwFlags);
577                 return readValueHelper(pNativeHome, ofs);
578             }
579             finally
580             {
581                 marshaler.ClearNative(pNativeHome);
582             }
583         }
584
585         //====================================================================
586         // Write to memory
587         //====================================================================
588         public static unsafe void WriteByte(IntPtr ptr, int ofs, byte val)
589         {
590             try
591             {
592                 byte* addr = (byte*)ptr + ofs;
593                 *addr = val;
594             }
595             catch (NullReferenceException)
596             {
597                 // this method is documented to throw AccessViolationException on any AV
598                 throw new AccessViolationException();
599             }
600         }
601
602         public static void WriteByte(object ptr, int ofs, byte val)
603         {
604             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, byte value) => Marshal.WriteByte(nativeHome, offset, value));
605         }
606
607         public static void WriteByte(IntPtr ptr, byte val)
608         {
609             WriteByte(ptr, 0, val);
610         }
611
612         public static unsafe void WriteInt16(IntPtr ptr, int ofs, short val)
613         {
614             try
615             {
616                 byte* addr = (byte*)ptr + ofs;
617                 if ((unchecked((int)addr) & 0x1) == 0)
618                 {
619                     // aligned write
620                     *((short*)addr) = val;
621                 }
622                 else
623                 {
624                     // unaligned write
625                     byte* valPtr = (byte*)&val;
626                     addr[0] = valPtr[0];
627                     addr[1] = valPtr[1];
628                 }
629             }
630             catch (NullReferenceException)
631             {
632                 // this method is documented to throw AccessViolationException on any AV
633                 throw new AccessViolationException();
634             }
635         }
636
637         public static void WriteInt16(object ptr, int ofs, short val)
638         {
639             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, short value) => Marshal.WriteInt16(nativeHome, offset, value));
640         }
641
642         public static void WriteInt16(IntPtr ptr, short val)
643         {
644             WriteInt16(ptr, 0, val);
645         }
646
647         public static void WriteInt16(IntPtr ptr, int ofs, char val)
648         {
649             WriteInt16(ptr, ofs, (short)val);
650         }
651
652         public static void WriteInt16([In, Out]object ptr, int ofs, char val)
653         {
654             WriteInt16(ptr, ofs, (short)val);
655         }
656
657         public static void WriteInt16(IntPtr ptr, char val)
658         {
659             WriteInt16(ptr, 0, (short)val);
660         }
661
662         public static unsafe void WriteInt32(IntPtr ptr, int ofs, int val)
663         {
664             try
665             {
666                 byte* addr = (byte*)ptr + ofs;
667                 if ((unchecked((int)addr) & 0x3) == 0)
668                 {
669                     // aligned write
670                     *((int*)addr) = val;
671                 }
672                 else
673                 {
674                     // unaligned write
675                     byte* valPtr = (byte*)&val;
676                     addr[0] = valPtr[0];
677                     addr[1] = valPtr[1];
678                     addr[2] = valPtr[2];
679                     addr[3] = valPtr[3];
680                 }
681             }
682             catch (NullReferenceException)
683             {
684                 // this method is documented to throw AccessViolationException on any AV
685                 throw new AccessViolationException();
686             }
687         }
688
689         public static void WriteInt32(object ptr, int ofs, int val)
690         {
691             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, int value) => Marshal.WriteInt32(nativeHome, offset, value));
692         }
693
694         public static void WriteInt32(IntPtr ptr, int val)
695         {
696             WriteInt32(ptr, 0, val);
697         }
698
699         public static void WriteIntPtr(IntPtr ptr, int ofs, IntPtr val)
700         {
701 #if BIT64
702             WriteInt64(ptr, ofs, (long)val);
703 #else // 32
704             WriteInt32(ptr, ofs, (int)val);
705 #endif
706         }
707
708         public static void WriteIntPtr(object ptr, int ofs, IntPtr val)
709         {
710 #if BIT64
711             WriteInt64(ptr, ofs, (long)val);
712 #else // 32
713             WriteInt32(ptr, ofs, (int)val);
714 #endif
715         }
716
717         public static void WriteIntPtr(IntPtr ptr, IntPtr val)
718         {
719 #if BIT64
720             WriteInt64(ptr, 0, (long)val);
721 #else // 32
722             WriteInt32(ptr, 0, (int)val);
723 #endif
724         }
725
726         public static unsafe void WriteInt64(IntPtr ptr, int ofs, long val)
727         {
728             try
729             {
730                 byte* addr = (byte*)ptr + ofs;
731                 if ((unchecked((int)addr) & 0x7) == 0)
732                 {
733                     // aligned write
734                     *((long*)addr) = val;
735                 }
736                 else
737                 {
738                     // unaligned write
739                     byte* valPtr = (byte*)&val;
740                     addr[0] = valPtr[0];
741                     addr[1] = valPtr[1];
742                     addr[2] = valPtr[2];
743                     addr[3] = valPtr[3];
744                     addr[4] = valPtr[4];
745                     addr[5] = valPtr[5];
746                     addr[6] = valPtr[6];
747                     addr[7] = valPtr[7];
748                 }
749             }
750             catch (NullReferenceException)
751             {
752                 // this method is documented to throw AccessViolationException on any AV
753                 throw new AccessViolationException();
754             }
755         }
756
757         public static void WriteInt64(object ptr, int ofs, long val)
758         {
759             WriteValueSlow(ptr, ofs, val, (IntPtr nativeHome, int offset, long value) => Marshal.WriteInt64(nativeHome, offset, value));
760         }
761
762         public static void WriteInt64(IntPtr ptr, long val)
763         {
764             WriteInt64(ptr, 0, val);
765         }
766
767         //====================================================================
768         // Write value into marshaled object (marshaled using AsAny) and
769         // propagate the value back
770         // It's quite slow and can return back dangling pointers
771         // It's only there for backcompact
772         // People should instead use the IntPtr overloads
773         //====================================================================
774         private static unsafe void WriteValueSlow<T>(object ptr, int ofs, T val, Action<IntPtr, int, T> writeValueHelper)
775         {
776             // Consumers of this method are documented to throw AccessViolationException on any AV
777             if (ptr == null)
778                 throw new AccessViolationException();
779
780             int dwFlags = 
781                 (int)AsAnyMarshaler.AsAnyFlags.In | 
782                 (int)AsAnyMarshaler.AsAnyFlags.Out | 
783                 (int)AsAnyMarshaler.AsAnyFlags.IsAnsi | 
784                 (int)AsAnyMarshaler.AsAnyFlags.IsBestFit;
785
786             MngdNativeArrayMarshaler.MarshalerState nativeArrayMarshalerState = new MngdNativeArrayMarshaler.MarshalerState();
787             AsAnyMarshaler marshaler = new AsAnyMarshaler(new IntPtr(&nativeArrayMarshalerState));
788
789             IntPtr pNativeHome = IntPtr.Zero;
790
791             try
792             {
793                 pNativeHome = marshaler.ConvertToNative(ptr, dwFlags);
794                 writeValueHelper(pNativeHome, ofs, val);
795                 marshaler.ConvertToManaged(ptr, pNativeHome);
796             }
797             finally
798             {
799                 marshaler.ClearNative(pNativeHome);
800             }
801         }
802
803         //====================================================================
804         // GetLastWin32Error
805         //====================================================================
806         [MethodImplAttribute(MethodImplOptions.InternalCall)]
807         public static extern int GetLastWin32Error();
808
809
810         //====================================================================
811         // SetLastWin32Error
812         //====================================================================
813         [MethodImplAttribute(MethodImplOptions.InternalCall)]
814         internal static extern void SetLastWin32Error(int error);
815
816
817         //====================================================================
818         // GetHRForLastWin32Error
819         //====================================================================
820         public static int GetHRForLastWin32Error()
821         {
822             int dwLastError = GetLastWin32Error();
823             if ((dwLastError & 0x80000000) == 0x80000000)
824                 return dwLastError;
825             else
826                 return (dwLastError & 0x0000FFFF) | unchecked((int)0x80070000);
827         }
828
829
830         //====================================================================
831         // Prelink
832         //====================================================================
833         public static void Prelink(MethodInfo m)
834         {
835             if (m == null)
836                 throw new ArgumentNullException(nameof(m));
837
838             RuntimeMethodInfo rmi = m as RuntimeMethodInfo;
839
840             if (rmi == null)
841                 throw new ArgumentException(SR.Argument_MustBeRuntimeMethodInfo);
842
843             InternalPrelink(rmi);
844         }
845
846         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
847         private static extern void InternalPrelink(IRuntimeMethodInfo m);
848
849         public static void PrelinkAll(Type c)
850         {
851             if (c == null)
852                 throw new ArgumentNullException(nameof(c));
853
854             MethodInfo[] mi = c.GetMethods();
855             if (mi != null)
856             {
857                 for (int i = 0; i < mi.Length; i++)
858                 {
859                     Prelink(mi[i]);
860                 }
861             }
862         }
863
864         [MethodImplAttribute(MethodImplOptions.InternalCall)]
865         public static extern /* struct _EXCEPTION_POINTERS* */ IntPtr GetExceptionPointers();
866         
867         [MethodImplAttribute(MethodImplOptions.InternalCall)]
868         public static extern int GetExceptionCode();
869
870
871         //====================================================================
872         // Marshals data from a structure class to a native memory block.
873         // If the structure contains pointers to allocated blocks and
874         // "fDeleteOld" is true, this routine will call DestroyStructure() first. 
875         //====================================================================
876         [MethodImplAttribute(MethodImplOptions.InternalCall), ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
877         public static extern void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld);
878
879         public static void StructureToPtr<T>(T structure, IntPtr ptr, bool fDeleteOld)
880         {
881             StructureToPtr((object)structure, ptr, fDeleteOld);
882         }
883
884         //====================================================================
885         // Marshals data from a native memory block to a preallocated structure class.
886         //====================================================================
887         public static void PtrToStructure(IntPtr ptr, object structure)
888         {
889             PtrToStructureHelper(ptr, structure, false);
890         }
891
892         public static void PtrToStructure<T>(IntPtr ptr, T structure)
893         {
894             PtrToStructure(ptr, (object)structure);
895         }
896
897         //====================================================================
898         // Creates a new instance of "structuretype" and marshals data from a
899         // native memory block to it.
900         //====================================================================
901         public static object PtrToStructure(IntPtr ptr, Type structureType)
902         {
903             if (ptr == IntPtr.Zero) return null;
904
905             if (structureType == null)
906                 throw new ArgumentNullException(nameof(structureType));
907
908             if (structureType.IsGenericType)
909                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(structureType));
910
911             RuntimeType rt = structureType.UnderlyingSystemType as RuntimeType;
912
913             if (rt == null)
914                 throw new ArgumentException(SR.Arg_MustBeType, nameof(structureType));
915
916             object structure = rt.CreateInstanceDefaultCtor(false /*publicOnly*/, false /*skipCheckThis*/, false /*fillCache*/, true /*wrapExceptions*/);
917             PtrToStructureHelper(ptr, structure, true);
918             return structure;
919         }
920
921         public static T PtrToStructure<T>(IntPtr ptr)
922         {
923             return (T)PtrToStructure(ptr, typeof(T));
924         }
925
926         //====================================================================
927         // Helper function to copy a pointer into a preallocated structure.
928         //====================================================================
929         [MethodImplAttribute(MethodImplOptions.InternalCall)]
930         private static extern void PtrToStructureHelper(IntPtr ptr, object structure, bool allowValueClasses);
931
932
933         //====================================================================
934         // Freeds all substructures pointed to by the native memory block.
935         // "structureclass" is used to provide layout information.
936         //====================================================================
937         [MethodImplAttribute(MethodImplOptions.InternalCall)]
938         public static extern void DestroyStructure(IntPtr ptr, Type structuretype);
939
940         public static void DestroyStructure<T>(IntPtr ptr)
941         {
942             DestroyStructure(ptr, typeof(T));
943         }
944
945 #if FEATURE_COMINTEROP
946         //====================================================================
947         // Returns the HInstance for this module.  Returns -1 if the module 
948         // doesn't have an HInstance.  In Memory (Dynamic) Modules won't have 
949         // an HInstance.
950         //====================================================================
951         public static IntPtr GetHINSTANCE(Module m)
952         {
953             if (m == null)
954                 throw new ArgumentNullException(nameof(m));
955
956             RuntimeModule rtModule = m as RuntimeModule;
957             if (rtModule == null)
958             {
959                 ModuleBuilder mb = m as ModuleBuilder;
960                 if (mb != null)
961                     rtModule = mb.InternalModule;
962             }
963
964             if (rtModule == null)
965                 throw new ArgumentNullException(nameof(m), SR.Argument_MustBeRuntimeModule);
966
967             return GetHINSTANCE(rtModule.GetNativeHandle());
968         }
969
970         [DllImport(JitHelpers.QCall, CharSet = CharSet.Unicode)]
971         private static extern IntPtr GetHINSTANCE(RuntimeModule m);
972
973 #endif // FEATURE_COMINTEROP
974         //====================================================================
975         // Throws a CLR exception based on the HRESULT.
976         //====================================================================
977         public static void ThrowExceptionForHR(int errorCode)
978         {
979             if (errorCode < 0)
980                 ThrowExceptionForHRInternal(errorCode, IntPtr.Zero);
981         }
982         public static void ThrowExceptionForHR(int errorCode, IntPtr errorInfo)
983         {
984             if (errorCode < 0)
985                 ThrowExceptionForHRInternal(errorCode, errorInfo);
986         }
987
988         [MethodImplAttribute(MethodImplOptions.InternalCall)]
989         internal static extern void ThrowExceptionForHRInternal(int errorCode, IntPtr errorInfo);
990
991
992         //====================================================================
993         // Converts the HRESULT to a CLR exception.
994         //====================================================================
995         public static Exception GetExceptionForHR(int errorCode)
996         {
997             if (errorCode < 0)
998                 return GetExceptionForHRInternal(errorCode, IntPtr.Zero);
999             else
1000                 return null;
1001         }
1002         public static Exception GetExceptionForHR(int errorCode, IntPtr errorInfo)
1003         {
1004             if (errorCode < 0)
1005                 return GetExceptionForHRInternal(errorCode, errorInfo);
1006             else
1007                 return null;
1008         }
1009
1010         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1011         internal static extern Exception GetExceptionForHRInternal(int errorCode, IntPtr errorInfo);
1012
1013
1014         //====================================================================
1015         // Memory allocation and deallocation.
1016         //====================================================================
1017         public static IntPtr AllocHGlobal(IntPtr cb)
1018         {
1019             // For backwards compatibility on 32 bit platforms, ensure we pass values between 
1020             // int.MaxValue and uint.MaxValue to Windows.  If the binary has had the 
1021             // LARGEADDRESSAWARE bit set in the PE header, it may get 3 or 4 GB of user mode
1022             // address space.  It is remotely that those allocations could have succeeded,
1023             // though I couldn't reproduce that.  In either case, that means we should continue
1024             // throwing an OOM instead of an ArgumentOutOfRangeException for "negative" amounts of memory.
1025             UIntPtr numBytes;
1026 #if BIT64
1027             numBytes = new UIntPtr(unchecked((ulong)cb.ToInt64()));
1028 #else // 32
1029             numBytes = new UIntPtr(unchecked((uint)cb.ToInt32()));
1030 #endif
1031
1032             IntPtr pNewMem = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, unchecked(numBytes));
1033
1034             if (pNewMem == IntPtr.Zero)
1035             {
1036                 throw new OutOfMemoryException();
1037             }
1038             return pNewMem;
1039         }
1040
1041         public static IntPtr AllocHGlobal(int cb)
1042         {
1043             return AllocHGlobal((IntPtr)cb);
1044         }
1045
1046         public static void FreeHGlobal(IntPtr hglobal)
1047         {
1048             if (IsNotWin32Atom(hglobal))
1049             {
1050                 if (IntPtr.Zero != Win32Native.LocalFree(hglobal))
1051                 {
1052                     ThrowExceptionForHR(GetHRForLastWin32Error());
1053                 }
1054             }
1055         }
1056
1057         public static IntPtr ReAllocHGlobal(IntPtr pv, IntPtr cb)
1058         {
1059             IntPtr pNewMem = Win32Native.LocalReAlloc(pv, cb, LMEM_MOVEABLE);
1060             if (pNewMem == IntPtr.Zero)
1061             {
1062                 throw new OutOfMemoryException();
1063             }
1064             return pNewMem;
1065         }
1066
1067
1068         //====================================================================
1069         // String convertions.
1070         //====================================================================          
1071         public static unsafe IntPtr StringToHGlobalAnsi(string s)
1072         {
1073             if (s == null)
1074             {
1075                 return IntPtr.Zero;
1076             }
1077             else
1078             {
1079                 int nb = (s.Length + 1) * SystemMaxDBCSCharSize;
1080
1081                 // Overflow checking
1082                 if (nb < s.Length)
1083                     throw new ArgumentOutOfRangeException(nameof(s));
1084
1085                 UIntPtr len = new UIntPtr((uint)nb);
1086                 IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len);
1087
1088                 if (hglobal == IntPtr.Zero)
1089                 {
1090                     throw new OutOfMemoryException();
1091                 }
1092                 else
1093                 {
1094                     s.ConvertToAnsi((byte*)hglobal, nb, false, false);
1095                     return hglobal;
1096                 }
1097             }
1098         }
1099
1100         public static unsafe IntPtr StringToHGlobalUni(string s)
1101         {
1102             if (s == null)
1103             {
1104                 return IntPtr.Zero;
1105             }
1106             else
1107             {
1108                 int nb = (s.Length + 1) * 2;
1109
1110                 // Overflow checking
1111                 if (nb < s.Length)
1112                     throw new ArgumentOutOfRangeException(nameof(s));
1113
1114                 UIntPtr len = new UIntPtr((uint)nb);
1115                 IntPtr hglobal = Win32Native.LocalAlloc_NoSafeHandle(LMEM_FIXED, len);
1116
1117                 if (hglobal == IntPtr.Zero)
1118                 {
1119                     throw new OutOfMemoryException();
1120                 }
1121                 else
1122                 {
1123                     fixed (char* firstChar = s)
1124                     {
1125                         string.wstrcpy((char*)hglobal, firstChar, s.Length + 1);
1126                     }
1127                     return hglobal;
1128                 }
1129             }
1130         }
1131
1132         public static IntPtr StringToHGlobalAuto(string s)
1133         {
1134             // Ansi platforms are no longer supported
1135             return StringToHGlobalUni(s);
1136         }
1137
1138 #if FEATURE_COMINTEROP
1139
1140         //====================================================================
1141         // Converts the CLR exception to an HRESULT. This function also sets
1142         // up an IErrorInfo for the exception.
1143         //====================================================================
1144         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1145         public static extern int GetHRForException(Exception e);
1146
1147         //====================================================================
1148         // Converts the CLR exception to an HRESULT. This function also sets
1149         // up an IErrorInfo for the exception.
1150         // This function is only used in WinRT and converts ObjectDisposedException
1151         // to RO_E_CLOSED
1152         //====================================================================
1153         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1154         internal static extern int GetHRForException_WinRT(Exception e);
1155
1156         internal static readonly Guid ManagedNameGuid = new Guid("{0F21F359-AB84-41E8-9A78-36D110E6D2F9}");
1157
1158         //====================================================================
1159         // Given a managed object that wraps an ITypeInfo, return its name
1160         //====================================================================
1161         public static string GetTypeInfoName(ITypeInfo typeInfo)
1162         {
1163             if (typeInfo == null)
1164                 throw new ArgumentNullException(nameof(typeInfo));
1165
1166             string strTypeLibName = null;
1167             string strDocString = null;
1168             int dwHelpContext = 0;
1169             string strHelpFile = null;
1170
1171             typeInfo.GetDocumentation(-1, out strTypeLibName, out strDocString, out dwHelpContext, out strHelpFile);
1172
1173             return strTypeLibName;
1174         }
1175
1176         // This method is identical to Type.GetTypeFromCLSID. Since it's interop specific, we expose it
1177         // on Marshal for more consistent API surface.
1178         public static Type GetTypeFromCLSID(Guid clsid)
1179         {
1180             return RuntimeType.GetTypeFromCLSIDImpl(clsid, null, false);
1181         }
1182
1183         //====================================================================
1184         // return the IUnknown* for an Object if the current context
1185         // is the one where the RCW was first seen. Will return null 
1186         // otherwise.
1187         //====================================================================
1188         public static IntPtr /* IUnknown* */ GetIUnknownForObject(object o)
1189         {
1190             return GetIUnknownForObjectNative(o, false);
1191         }
1192
1193         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1194         private static extern IntPtr /* IUnknown* */ GetIUnknownForObjectNative(object o, bool onlyInContext);
1195
1196         //====================================================================
1197         // return the raw IUnknown* for a COM Object not related to current 
1198         // context
1199         // Does not call AddRef
1200         //====================================================================
1201         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1202         internal static extern IntPtr /* IUnknown* */ GetRawIUnknownForComObjectNoAddRef(object o);
1203 #endif // FEATURE_COMINTEROP
1204
1205         //====================================================================
1206         // return the IDispatch* for an Object
1207         //====================================================================
1208         public static IntPtr /* IDispatch */ GetIDispatchForObject(object o)
1209         {
1210             throw new PlatformNotSupportedException();
1211         }
1212
1213 #if FEATURE_COMINTEROP
1214
1215         //====================================================================
1216         // return the IUnknown* representing the interface for the Object
1217         // Object o should support Type T
1218         //====================================================================
1219         public static IntPtr /* IUnknown* */ GetComInterfaceForObject(object o, Type T)
1220         {
1221             return GetComInterfaceForObjectNative(o, T, false, true);
1222         }
1223
1224         public static IntPtr GetComInterfaceForObject<T, TInterface>(T o)
1225         {
1226             return GetComInterfaceForObject(o, typeof(TInterface));
1227         }
1228
1229         //====================================================================
1230         // return the IUnknown* representing the interface for the Object
1231         // Object o should support Type T, it refer the value of mode to 
1232         // invoke customized QueryInterface or not
1233         //====================================================================
1234         public static IntPtr /* IUnknown* */ GetComInterfaceForObject(object o, Type T, CustomQueryInterfaceMode mode)
1235         {
1236             bool bEnableCustomizedQueryInterface = ((mode == CustomQueryInterfaceMode.Allow) ? true : false);
1237             return GetComInterfaceForObjectNative(o, T, false, bEnableCustomizedQueryInterface);
1238         }
1239
1240         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1241         private static extern IntPtr /* IUnknown* */ GetComInterfaceForObjectNative(object o, Type t, bool onlyInContext, bool fEnalbeCustomizedQueryInterface);
1242
1243         //====================================================================
1244         // return an Object for IUnknown
1245         //====================================================================
1246         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1247         public static extern object GetObjectForIUnknown(IntPtr /* IUnknown* */ pUnk);
1248
1249         //====================================================================
1250         // Return a unique Object given an IUnknown.  This ensures that you
1251         //  receive a fresh object (we will not look in the cache to match up this
1252         //  IUnknown to an already existing object).  This is useful in cases
1253         //  where you want to be able to call ReleaseComObject on a RCW
1254         //  and not worry about other active uses of said RCW.
1255         //====================================================================
1256         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1257         public static extern object GetUniqueObjectForIUnknown(IntPtr unknown);
1258
1259         //====================================================================
1260         // return an Object for IUnknown, using the Type T, 
1261         //  NOTE: 
1262         //  Type T should be either a COM imported Type or a sub-type of COM 
1263         //  imported Type
1264         //====================================================================
1265         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1266         public static extern object GetTypedObjectForIUnknown(IntPtr /* IUnknown* */ pUnk, Type t);
1267
1268         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1269         public static extern IntPtr CreateAggregatedObject(IntPtr pOuter, object o);
1270
1271         public static IntPtr CreateAggregatedObject<T>(IntPtr pOuter, T o)
1272         {
1273             return CreateAggregatedObject(pOuter, (object)o);
1274         }
1275
1276         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1277         public static extern void CleanupUnusedObjectsInCurrentContext();
1278
1279         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1280         public static extern bool AreComObjectsAvailableForCleanup();
1281
1282         //====================================================================
1283         // check if the object is classic COM component
1284         //====================================================================
1285         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1286         public static extern bool IsComObject(object o);
1287
1288 #endif // FEATURE_COMINTEROP
1289
1290         public static IntPtr AllocCoTaskMem(int cb)
1291         {
1292             IntPtr pNewMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)cb));
1293             if (pNewMem == IntPtr.Zero)
1294             {
1295                 throw new OutOfMemoryException();
1296             }
1297             return pNewMem;
1298         }
1299
1300         public static unsafe IntPtr StringToCoTaskMemUni(string s)
1301         {
1302             if (s == null)
1303             {
1304                 return IntPtr.Zero;
1305             }
1306             else
1307             {
1308                 int nb = (s.Length + 1) * 2;
1309
1310                 // Overflow checking
1311                 if (nb < s.Length)
1312                     throw new ArgumentOutOfRangeException(nameof(s));
1313
1314                 IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb));
1315
1316                 if (hglobal == IntPtr.Zero)
1317                 {
1318                     throw new OutOfMemoryException();
1319                 }
1320                 else
1321                 {
1322                     fixed (char* firstChar = s)
1323                     {
1324                         string.wstrcpy((char*)hglobal, firstChar, s.Length + 1);
1325                     }
1326                     return hglobal;
1327                 }
1328             }
1329         }
1330
1331         public static unsafe IntPtr StringToCoTaskMemUTF8(string s)
1332         {
1333             if (s == null)
1334             {
1335                 return IntPtr.Zero;
1336             }
1337             else
1338             {
1339                 int nb = Encoding.UTF8.GetMaxByteCount(s.Length);
1340
1341                 IntPtr pMem = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb + 1));
1342
1343                 if (pMem == IntPtr.Zero)
1344                 {
1345                     throw new OutOfMemoryException();
1346                 }
1347                 else
1348                 {
1349                     fixed (char* firstChar = s)
1350                     {
1351                         byte* pbMem = (byte*)pMem;
1352                         int nbWritten = Encoding.UTF8.GetBytes(firstChar, s.Length, pbMem, nb);
1353                         pbMem[nbWritten] = 0;
1354                     }
1355                     return pMem;
1356                 }
1357             }
1358         }
1359
1360         public static IntPtr StringToCoTaskMemAuto(string s)
1361         {
1362             // Ansi platforms are no longer supported
1363             return StringToCoTaskMemUni(s);
1364         }
1365
1366         public static unsafe IntPtr StringToCoTaskMemAnsi(string s)
1367         {
1368             if (s == null)
1369             {
1370                 return IntPtr.Zero;
1371             }
1372             else
1373             {
1374                 int nb = (s.Length + 1) * SystemMaxDBCSCharSize;
1375
1376                 // Overflow checking
1377                 if (nb < s.Length)
1378                     throw new ArgumentOutOfRangeException(nameof(s));
1379
1380                 IntPtr hglobal = Win32Native.CoTaskMemAlloc(new UIntPtr((uint)nb));
1381
1382                 if (hglobal == IntPtr.Zero)
1383                 {
1384                     throw new OutOfMemoryException();
1385                 }
1386                 else
1387                 {
1388                     s.ConvertToAnsi((byte*)hglobal, nb, false, false);
1389                     return hglobal;
1390                 }
1391             }
1392         }
1393
1394         public static void FreeCoTaskMem(IntPtr ptr)
1395         {
1396             if (IsNotWin32Atom(ptr))
1397             {
1398                 Win32Native.CoTaskMemFree(ptr);
1399             }
1400         }
1401
1402         public static IntPtr ReAllocCoTaskMem(IntPtr pv, int cb)
1403         {
1404             IntPtr pNewMem = Win32Native.CoTaskMemRealloc(pv, new UIntPtr((uint)cb));
1405             if (pNewMem == IntPtr.Zero && cb != 0)
1406             {
1407                 throw new OutOfMemoryException();
1408             }
1409             return pNewMem;
1410         }
1411
1412         //====================================================================
1413         // BSTR allocation and dealocation.
1414         //====================================================================      
1415         public static void FreeBSTR(IntPtr ptr)
1416         {
1417             if (IsNotWin32Atom(ptr))
1418             {
1419                 Win32Native.SysFreeString(ptr);
1420             }
1421         }
1422
1423         public static IntPtr StringToBSTR(string s)
1424         {
1425             if (s == null)
1426                 return IntPtr.Zero;
1427
1428             // Overflow checking
1429             if (s.Length + 1 < s.Length)
1430                 throw new ArgumentOutOfRangeException(nameof(s));
1431
1432             IntPtr bstr = Win32Native.SysAllocStringLen(s, s.Length);
1433             if (bstr == IntPtr.Zero)
1434                 throw new OutOfMemoryException();
1435
1436             return bstr;
1437         }
1438
1439         public static string PtrToStringBSTR(IntPtr ptr)
1440         {
1441             return PtrToStringUni(ptr, (int)Win32Native.SysStringLen(ptr));
1442         }
1443
1444 #if FEATURE_COMINTEROP
1445         //====================================================================
1446         // release the COM component and if the reference hits 0 zombie this object
1447         // further usage of this Object might throw an exception
1448         //====================================================================
1449         public static int ReleaseComObject(object o)
1450         {
1451             __ComObject co = null;
1452
1453             // Make sure the obj is an __ComObject.
1454             try
1455             {
1456                 co = (__ComObject)o;
1457             }
1458             catch (InvalidCastException)
1459             {
1460                 throw new ArgumentException(SR.Argument_ObjNotComObject, nameof(o));
1461             }
1462
1463             return co.ReleaseSelf();
1464         }
1465
1466         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1467         internal static extern int InternalReleaseComObject(object o);
1468
1469
1470         //====================================================================
1471         // release the COM component and zombie this object
1472         // further usage of this Object might throw an exception
1473         //====================================================================
1474         public static int FinalReleaseComObject(object o)
1475         {
1476             if (o == null)
1477                 throw new ArgumentNullException(nameof(o));
1478
1479             __ComObject co = null;
1480
1481             // Make sure the obj is an __ComObject.
1482             try
1483             {
1484                 co = (__ComObject)o;
1485             }
1486             catch (InvalidCastException)
1487             {
1488                 throw new ArgumentException(SR.Argument_ObjNotComObject, nameof(o));
1489             }
1490
1491             co.FinalReleaseSelf();
1492
1493             return 0;
1494         }
1495
1496         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1497         internal static extern void InternalFinalReleaseComObject(object o);
1498 #endif // FEATURE_COMINTEROP
1499
1500         //====================================================================
1501         // This method retrieves data from the COM object.
1502         //====================================================================
1503         public static object GetComObjectData(object obj, object key)
1504         {
1505             throw new PlatformNotSupportedException(SR.Arg_PlatformNotSupported);
1506         }
1507
1508         //====================================================================
1509         // This method sets data on the COM object. The data can only be set 
1510         // once for a given key and cannot be removed. This function returns
1511         // true if the data has been added, false if the data could not be
1512         // added because there already was data for the specified key.
1513         //====================================================================
1514         public static bool SetComObjectData(object obj, object key, object data)
1515         {
1516             throw new PlatformNotSupportedException(SR.Arg_PlatformNotSupported);
1517         }
1518
1519 #if FEATURE_COMINTEROP
1520         //====================================================================
1521         // This method takes the given COM object and wraps it in an object
1522         // of the specified type. The type must be derived from __ComObject.
1523         //====================================================================
1524         public static object CreateWrapperOfType(object o, Type t)
1525         {
1526             // Validate the arguments.
1527             if (t == null)
1528                 throw new ArgumentNullException(nameof(t));
1529             if (!t.IsCOMObject)
1530                 throw new ArgumentException(SR.Argument_TypeNotComObject, nameof(t));
1531             if (t.IsGenericType)
1532                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
1533
1534             if (t.IsWindowsRuntimeObject)
1535                 throw new ArgumentException(SR.Argument_TypeIsWinRTType, nameof(t));
1536
1537             // Check for the null case.
1538             if (o == null)
1539                 return null;
1540
1541             // Make sure the object is a COM object.
1542             if (!o.GetType().IsCOMObject)
1543                 throw new ArgumentException(SR.Argument_ObjNotComObject, nameof(o));
1544             if (o.GetType().IsWindowsRuntimeObject)
1545                 throw new ArgumentException(SR.Argument_ObjIsWinRTObject, nameof(o));
1546
1547             // Check to see if the type of the object is the requested type.
1548             if (o.GetType() == t)
1549                 return o;
1550
1551             // Check to see if we already have a cached wrapper for this type.
1552             object Wrapper = GetComObjectData(o, t);
1553             if (Wrapper == null)
1554             {
1555                 // Create the wrapper for the specified type.
1556                 Wrapper = InternalCreateWrapperOfType(o, t);
1557
1558                 // Attempt to cache the wrapper on the object.
1559                 if (!SetComObjectData(o, t, Wrapper))
1560                 {
1561                     // Another thead already cached the wrapper so use that one instead.
1562                     Wrapper = GetComObjectData(o, t);
1563                 }
1564             }
1565
1566             return Wrapper;
1567         }
1568
1569         public static TWrapper CreateWrapperOfType<T, TWrapper>(T o)
1570         {
1571             return (TWrapper)CreateWrapperOfType(o, typeof(TWrapper));
1572         }
1573
1574         //====================================================================
1575         // Helper method called from CreateWrapperOfType.
1576         //====================================================================
1577         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1578         private static extern object InternalCreateWrapperOfType(object o, Type t);
1579
1580         //====================================================================
1581         // IUnknown Helpers
1582         //====================================================================
1583         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1584         public static extern int /* HRESULT */ QueryInterface(IntPtr /* IUnknown */ pUnk, ref Guid iid, out IntPtr ppv);
1585
1586         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1587         public static extern int /* ULONG */ AddRef(IntPtr /* IUnknown */ pUnk);
1588         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1589         public static extern int /* ULONG */ Release(IntPtr /* IUnknown */ pUnk);
1590
1591         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1592         public static extern void GetNativeVariantForObject(object obj, /* VARIANT * */ IntPtr pDstNativeVariant);
1593
1594         public static void GetNativeVariantForObject<T>(T obj, IntPtr pDstNativeVariant)
1595         {
1596             GetNativeVariantForObject((object)obj, pDstNativeVariant);
1597         }
1598
1599         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1600         public static extern object GetObjectForNativeVariant(/* VARIANT * */ IntPtr pSrcNativeVariant);
1601
1602         public static T GetObjectForNativeVariant<T>(IntPtr pSrcNativeVariant)
1603         {
1604             return (T)GetObjectForNativeVariant(pSrcNativeVariant);
1605         }
1606
1607         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1608         public static extern object[] GetObjectsForNativeVariants(/* VARIANT * */ IntPtr aSrcNativeVariant, int cVars);
1609
1610         public static T[] GetObjectsForNativeVariants<T>(IntPtr aSrcNativeVariant, int cVars)
1611         {
1612             object[] objects = GetObjectsForNativeVariants(aSrcNativeVariant, cVars);
1613             T[] result = null;
1614
1615             if (objects != null)
1616             {
1617                 result = new T[objects.Length];
1618                 Array.Copy(objects, result, objects.Length);
1619             }
1620
1621             return result;
1622         }
1623
1624         /// <summary>
1625         /// <para>Returns the first valid COM slot that GetMethodInfoForSlot will work on
1626         /// This will be 3 for IUnknown based interfaces and 7 for IDispatch based interfaces. </para>
1627         /// </summary>
1628         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1629         public static extern int GetStartComSlot(Type t);
1630
1631 #endif // FEATURE_COMINTEROP
1632
1633         //====================================================================
1634         // This method generates a GUID for the specified type. If the type
1635         // has a GUID in the metadata then it is returned otherwise a stable
1636         // guid GUID is generated based on the fully qualified name of the 
1637         // type.
1638         //====================================================================
1639         public static Guid GenerateGuidForType(Type type)
1640         {
1641             return type.GUID;
1642         }
1643
1644         //====================================================================
1645         // This method generates a PROGID for the specified type. If the type
1646         // has a PROGID in the metadata then it is returned otherwise a stable
1647         // PROGID is generated based on the fully qualified name of the 
1648         // type.
1649         //====================================================================
1650         public static string GenerateProgIdForType(Type type)
1651         {
1652             if (type == null)
1653                 throw new ArgumentNullException(nameof(type));
1654             if (type.IsImport)
1655                 throw new ArgumentException(SR.Argument_TypeMustNotBeComImport, nameof(type));
1656             if (type.IsGenericType)
1657                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(type));
1658
1659             IList<CustomAttributeData> cas = CustomAttributeData.GetCustomAttributes(type);
1660             for (int i = 0; i < cas.Count; i++)
1661             {
1662                 if (cas[i].Constructor.DeclaringType == typeof(ProgIdAttribute))
1663                 {
1664                     // Retrieve the PROGID string from the ProgIdAttribute.
1665                     IList<CustomAttributeTypedArgument> caConstructorArgs = cas[i].ConstructorArguments;
1666                     Debug.Assert(caConstructorArgs.Count == 1, "caConstructorArgs.Count == 1");
1667
1668                     CustomAttributeTypedArgument progIdConstructorArg = caConstructorArgs[0];
1669                     Debug.Assert(progIdConstructorArg.ArgumentType == typeof(string), "progIdConstructorArg.ArgumentType == typeof(String)");
1670
1671                     string strProgId = (string)progIdConstructorArg.Value;
1672
1673                     if (strProgId == null)
1674                         strProgId = string.Empty;
1675
1676                     return strProgId;
1677                 }
1678             }
1679
1680             // If there is no prog ID attribute then use the full name of the type as the prog id.
1681             return type.FullName;
1682         }
1683
1684 #if FEATURE_COMINTEROP
1685         //====================================================================
1686         // This method binds to the specified moniker.
1687         //====================================================================
1688         public static object BindToMoniker(string monikerName)
1689         {
1690             object obj = null;
1691             IBindCtx bindctx = null;
1692             CreateBindCtx(0, out bindctx);
1693
1694             uint cbEaten;
1695             IMoniker pmoniker = null;
1696             MkParseDisplayName(bindctx, monikerName, out cbEaten, out pmoniker);
1697
1698             BindMoniker(pmoniker, 0, ref IID_IUnknown, out obj);
1699             return obj;
1700         }
1701
1702         [DllImport(Interop.Libraries.Ole32, PreserveSig = false)]
1703         private static extern void CreateBindCtx(uint reserved, out IBindCtx ppbc);
1704
1705         [DllImport(Interop.Libraries.Ole32, PreserveSig = false)]
1706         private static extern void MkParseDisplayName(IBindCtx pbc, [MarshalAs(UnmanagedType.LPWStr)] string szUserName, out uint pchEaten, out IMoniker ppmk);
1707
1708         [DllImport(Interop.Libraries.Ole32, PreserveSig = false)]
1709         private static extern void BindMoniker(IMoniker pmk, uint grfOpt, ref Guid iidResult, [MarshalAs(UnmanagedType.Interface)] out object ppvResult);
1710
1711         //========================================================================
1712         // Private method called from EE upon use of license/ICF2 marshaling.
1713         //========================================================================
1714         private static IntPtr LoadLicenseManager()
1715         {
1716             Type t = Type.GetType("System.ComponentModel.LicenseManager, System", throwOnError: true);
1717             return t.TypeHandle.Value;
1718         }
1719
1720         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1721         public static extern void ChangeWrapperHandleStrength(object otp, bool fIsWeak);
1722
1723         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1724         internal static extern void InitializeWrapperForWinRT(object o, ref IntPtr pUnk);
1725
1726 #if FEATURE_COMINTEROP_WINRT_MANAGED_ACTIVATION
1727         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1728         internal static extern void InitializeManagedWinRTFactoryObject(object o, RuntimeType runtimeClassType);
1729 #endif
1730
1731         //========================================================================
1732         // Create activation factory and wraps it with a unique RCW
1733         //========================================================================
1734         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1735         internal static extern object GetNativeActivationFactory(Type type);
1736
1737 #endif // FEATURE_COMINTEROP
1738
1739         public static Delegate GetDelegateForFunctionPointer(IntPtr ptr, Type t)
1740         {
1741             // Validate the parameters
1742             if (ptr == IntPtr.Zero)
1743                 throw new ArgumentNullException(nameof(ptr));
1744
1745             if (t == null)
1746                 throw new ArgumentNullException(nameof(t));
1747
1748             if ((t as RuntimeType) == null)
1749                 throw new ArgumentException(SR.Argument_MustBeRuntimeType, nameof(t));
1750
1751             if (t.IsGenericType)
1752                 throw new ArgumentException(SR.Argument_NeedNonGenericType, nameof(t));
1753
1754             Type c = t.BaseType;
1755             if (c == null || (c != typeof(Delegate) && c != typeof(MulticastDelegate)))
1756                 throw new ArgumentException(SR.Arg_MustBeDelegate, nameof(t));
1757
1758             return GetDelegateForFunctionPointerInternal(ptr, t);
1759         }
1760
1761         public static TDelegate GetDelegateForFunctionPointer<TDelegate>(IntPtr ptr)
1762         {
1763             return (TDelegate)(object)GetDelegateForFunctionPointer(ptr, typeof(TDelegate));
1764         }
1765
1766         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1767         internal static extern Delegate GetDelegateForFunctionPointerInternal(IntPtr ptr, Type t);
1768
1769         public static IntPtr GetFunctionPointerForDelegate(Delegate d)
1770         {
1771             if (d == null)
1772                 throw new ArgumentNullException(nameof(d));
1773
1774             return GetFunctionPointerForDelegateInternal(d);
1775         }
1776
1777         public static IntPtr GetFunctionPointerForDelegate<TDelegate>(TDelegate d)
1778         {
1779             return GetFunctionPointerForDelegate((Delegate)(object)d);
1780         }
1781
1782         [MethodImplAttribute(MethodImplOptions.InternalCall)]
1783         internal static extern IntPtr GetFunctionPointerForDelegateInternal(Delegate d);
1784
1785         public static IntPtr SecureStringToBSTR(SecureString s)
1786         {
1787             if (s == null)
1788             {
1789                 throw new ArgumentNullException(nameof(s));
1790             }
1791
1792             return s.MarshalToBSTR();
1793         }
1794
1795         public static IntPtr SecureStringToCoTaskMemAnsi(SecureString s)
1796         {
1797             if (s == null)
1798             {
1799                 throw new ArgumentNullException(nameof(s));
1800             }
1801
1802             return s.MarshalToString(globalAlloc: false, unicode: false);
1803         }
1804
1805         public static IntPtr SecureStringToCoTaskMemUnicode(SecureString s)
1806         {
1807             if (s == null)
1808             {
1809                 throw new ArgumentNullException(nameof(s));
1810             }
1811
1812             return s.MarshalToString(globalAlloc: false, unicode: true);
1813         }
1814         
1815         public static void ZeroFreeBSTR(IntPtr s)
1816         {
1817             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.SysStringLen(s) * 2));
1818             FreeBSTR(s);
1819         }
1820
1821         public static void ZeroFreeCoTaskMemAnsi(IntPtr s)
1822         {
1823             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s)));
1824             FreeCoTaskMem(s);
1825         }
1826
1827         public static void ZeroFreeCoTaskMemUnicode(IntPtr s)
1828         {
1829             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2));
1830             FreeCoTaskMem(s);
1831         }
1832
1833         public static unsafe void ZeroFreeCoTaskMemUTF8(IntPtr s)
1834         {
1835             RuntimeImports.RhZeroMemory(s, (UIntPtr)System.StubHelpers.StubHelpers.strlen((sbyte*)s));
1836             FreeCoTaskMem(s);
1837         }
1838
1839         public static IntPtr SecureStringToGlobalAllocAnsi(SecureString s)
1840         {
1841             if (s == null)
1842             {
1843                 throw new ArgumentNullException(nameof(s));
1844             }
1845
1846             return s.MarshalToString(globalAlloc: true, unicode: false);
1847         }
1848
1849         public static IntPtr SecureStringToGlobalAllocUnicode(SecureString s)
1850         {
1851             if (s == null)
1852             {
1853                 throw new ArgumentNullException(nameof(s));
1854             }
1855
1856             return s.MarshalToString(globalAlloc: true, unicode: true); ;
1857         }
1858
1859         public static void ZeroFreeGlobalAllocAnsi(IntPtr s)
1860         {
1861             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenA(s)));
1862             FreeHGlobal(s);
1863         }
1864
1865         public static void ZeroFreeGlobalAllocUnicode(IntPtr s)
1866         {
1867             RuntimeImports.RhZeroMemory(s, (UIntPtr)(Win32Native.lstrlenW(s) * 2));
1868             FreeHGlobal(s);
1869         }
1870     }
1871 }
1872