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