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