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;
6 using System.Runtime.CompilerServices;
7 using System.Runtime.InteropServices;
8 
9 namespace System.Runtime.InteropServices
10 {
11 #if ENABLE_MIN_WINRT
12     public static partial class McgMarshal
13     {
14         /// <summary>
15         /// Creates a temporary HSTRING on the staack
16         /// NOTE: pchPinnedSourceString must be pinned before calling this function, making sure the pointer
17         /// is valid during the entire interop call
18         /// </summary>
19         [MethodImplAttribute(MethodImplOptions.NoInlining)]
StringToHStringReference( char* pchPinnedSourceString, string sourceString, HSTRING_HEADER* pHeader, HSTRING* phString)20         public static unsafe void StringToHStringReference(
21             char* pchPinnedSourceString,
22             string sourceString,
23             HSTRING_HEADER* pHeader,
24             HSTRING* phString)
25         {
26             if (sourceString == null)
27                 throw new ArgumentNullException(nameof(sourceString), SR.Null_HString);
28 
29             int hr = ExternalInterop.WindowsCreateStringReference(
30                 pchPinnedSourceString,
31                 (uint)sourceString.Length,
32                 pHeader,
33                 (void**)phString);
34 
35             if (hr < 0)
36                 throw Marshal.GetExceptionForHR(hr);
37         }
38 
39         [MethodImplAttribute(MethodImplOptions.NoInlining)]
HStringToString(IntPtr hString)40         internal static unsafe string HStringToString(IntPtr hString)
41         {
42             HSTRING hstring = new HSTRING(hString);
43             return HStringToString(hstring);
44         }
45 
46         [MethodImplAttribute(MethodImplOptions.NoInlining)]
HStringToString(HSTRING pHString)47         public static unsafe string HStringToString(HSTRING pHString)
48         {
49             if (pHString.handle == IntPtr.Zero)
50             {
51                 return String.Empty;
52             }
53 
54             uint length = 0;
55             char* pchBuffer = ExternalInterop.WindowsGetStringRawBuffer(pHString.handle.ToPointer(), &length);
56 
57             return new string(pchBuffer, 0, (int)length);
58         }
59 
60         [MethodImplAttribute(MethodImplOptions.NoInlining)]
FreeHString(IntPtr pHString)61         public static unsafe void FreeHString(IntPtr pHString)
62         {
63             ExternalInterop.WindowsDeleteString(pHString.ToPointer());
64         }
65     }
66 #endif
67 
68     public static partial class ExternalInterop
69     {
70 #if ENABLE_MIN_WINRT
71         [DllImport(Libraries.CORE_WINRT)]
72         [McgGeneratedNativeCallCodeAttribute]
73         [MethodImplAttribute(MethodImplOptions.NoInlining)]
RoGetActivationFactory(void* hstring_typeName, Guid* iid, void* ppv)74         public static extern unsafe int RoGetActivationFactory(void* hstring_typeName, Guid* iid, void* ppv);
75 
76 
77         [DllImport(Libraries.CORE_WINRT_STRING)]
78         [McgGeneratedNativeCallCodeAttribute]
79         [MethodImplAttribute(MethodImplOptions.NoInlining)]
WindowsCreateStringReference(char* sourceString, uint length, HSTRING_HEADER* phstringHeader, void* hstring)80         internal static extern unsafe int WindowsCreateStringReference(char* sourceString,
81                                                                        uint length,
82                                                                        HSTRING_HEADER* phstringHeader,
83                                                                        void* hstring);
84 #endif
85 
86         [DllImport(Libraries.CORE_COM)]
87         [McgGeneratedNativeCallCodeAttribute]
CoCreateFreeThreadedMarshaler(void* pOuter, void** ppunkMarshal)88         internal static extern unsafe int CoCreateFreeThreadedMarshaler(void* pOuter, void** ppunkMarshal);
89 
90         [DllImport(Libraries.CORE_COM)]
91         [McgGeneratedNativeCallCodeAttribute]
CoGetContextToken(IntPtr* ppToken)92         public static extern unsafe int CoGetContextToken(IntPtr* ppToken);
93 
94 
95         [DllImport(Libraries.CORE_COM)]
96         [McgGeneratedNativeCallCodeAttribute]
CoGetObjectContext(Guid* iid, void* ppv)97         internal static extern unsafe int CoGetObjectContext(Guid* iid, void* ppv);
98 
99         [DllImport(Libraries.CORE_COM)]
100         [McgGeneratedNativeCallCodeAttribute]
CoGetMarshalSizeMax(ulong* pulSize, Guid* iid, IntPtr pUnk, Interop.COM.MSHCTX dwDestContext, IntPtr pvDestContext, Interop.COM.MSHLFLAGS mshlflags)101         private static extern unsafe int CoGetMarshalSizeMax(ulong* pulSize, Guid* iid, IntPtr pUnk,
102                                                              Interop.COM.MSHCTX dwDestContext,
103                                                              IntPtr pvDestContext,
104                                                              Interop.COM.MSHLFLAGS mshlflags);
105         [DllImport(Libraries.CORE_COM)]
106         [McgGeneratedNativeCallCodeAttribute]
CoMarshalInterface(IntPtr pStream, Guid* iid, IntPtr pUnk, Interop.COM.MSHCTX dwDestContext, IntPtr pvDestContext, Interop.COM.MSHLFLAGS mshlflags)107         private extern static unsafe int CoMarshalInterface(IntPtr pStream, Guid* iid, IntPtr pUnk, Interop.COM.MSHCTX dwDestContext, IntPtr pvDestContext, Interop.COM.MSHLFLAGS mshlflags);
108 
109         [DllImport(Libraries.CORE_COM)]
110         [McgGeneratedNativeCallCodeAttribute]
CoUnmarshalInterface(IntPtr pStream, Guid* iid, void** ppv)111         private static extern unsafe int CoUnmarshalInterface(IntPtr pStream, Guid* iid, void** ppv);
112 
113 
114         [DllImport(Libraries.CORE_COM)]
115         [McgGeneratedNativeCallCodeAttribute]
116         [MethodImplAttribute(MethodImplOptions.NoInlining)]
CoReleaseMarshalData(IntPtr pStream)117         internal static extern int CoReleaseMarshalData(IntPtr pStream);
118 
119 
120         /// <summary>
121         /// Marshal IUnknown * into IStream*
122         /// </summary>
123         /// <returns>HResult</returns>
CoMarshalInterface(IntPtr pStream, ref Guid iid, IntPtr pUnk, Interop.COM.MSHCTX dwDestContext, IntPtr pvDestContext, Interop.COM.MSHLFLAGS mshlflags)124         internal static unsafe int CoMarshalInterface(IntPtr pStream, ref Guid iid, IntPtr pUnk, Interop.COM.MSHCTX dwDestContext, IntPtr pvDestContext, Interop.COM.MSHLFLAGS mshlflags)
125         {
126             fixed (Guid* unsafe_iid = &iid)
127             {
128                 return CoMarshalInterface(pStream, unsafe_iid, pUnk, dwDestContext, pvDestContext, mshlflags);
129             }
130         }
131 
132         /// <summary>
133         /// Marshal IStream* into IUnknown*
134         /// </summary>
135         /// <returns>HResult</returns>
CoUnmarshalInterface(IntPtr pStream, ref Guid iid, out IntPtr ppv)136         internal static unsafe int CoUnmarshalInterface(IntPtr pStream, ref Guid iid, out IntPtr ppv)
137         {
138             fixed (Guid* unsafe_iid = &iid)
139             {
140                 fixed (void* unsafe_ppv = &ppv)
141                 {
142                     return CoUnmarshalInterface(pStream, unsafe_iid, (void**)unsafe_ppv);
143                 }
144             }
145         }
146 
147         /// <summary>
148         /// Returns an upper bound on the number of bytes needed to marshal the specified interface pointer to the specified object.
149         /// </summary>
150         /// <returns>HResult</returns>
CoGetMarshalSizeMax(out ulong pulSize, ref Guid iid, IntPtr pUnk, Interop.COM.MSHCTX dwDestContext, IntPtr pvDestContext, Interop.COM.MSHLFLAGS mshlflags)151         internal static unsafe int CoGetMarshalSizeMax(out ulong pulSize, ref Guid iid, IntPtr pUnk, Interop.COM.MSHCTX dwDestContext, IntPtr pvDestContext, Interop.COM.MSHLFLAGS mshlflags)
152         {
153             fixed (ulong* unsafe_pulSize = &pulSize)
154             {
155                 fixed (Guid* unsafe_iid = &iid)
156                 {
157                     return CoGetMarshalSizeMax(unsafe_pulSize, unsafe_iid, pUnk, dwDestContext, pvDestContext, mshlflags);
158                 }
159             }
160         }
161 
162 #if ENABLE_MIN_WINRT
RoGetActivationFactory(string className, ref Guid iid, out IntPtr ppv)163         internal static unsafe void RoGetActivationFactory(string className, ref Guid iid, out IntPtr ppv)
164         {
165             fixed (char* unsafe_className = className)
166             {
167                 void* hstring_typeName = null;
168 
169                 HSTRING_HEADER hstringHeader;
170                 int hr =
171                     WindowsCreateStringReference(
172                         unsafe_className, (uint)className.Length, &hstringHeader, &hstring_typeName);
173 
174                 if (hr < 0)
175                     throw Marshal.GetExceptionForHR(hr);
176 
177                 fixed (Guid* unsafe_iid = &iid)
178                 {
179                     fixed (void* unsafe_ppv = &ppv)
180                     {
181                         hr = ExternalInterop.RoGetActivationFactory(
182                             hstring_typeName,
183                             unsafe_iid,
184                             unsafe_ppv);
185 
186                         if (hr < 0)
187                             throw Marshal.GetExceptionForHR(hr);
188                     }
189                 }
190             }
191         }
192 #endif
193 
CoGetContextToken(out IntPtr ppToken)194         public static unsafe int CoGetContextToken(out IntPtr ppToken)
195         {
196             ppToken = IntPtr.Zero;
197             fixed (IntPtr* unsafePpToken = &ppToken)
198             {
199                 return CoGetContextToken(unsafePpToken);
200             }
201         }
202 
CoGetObjectContext(ref Guid iid, out IntPtr ppv)203         internal static unsafe int CoGetObjectContext(ref Guid iid, out IntPtr ppv)
204         {
205             fixed (void* unsafe_ppv = &ppv)
206             {
207                 fixed (Guid* unsafe_iid = &iid)
208                 {
209                     return CoGetObjectContext(unsafe_iid, (void**)unsafe_ppv);
210                 }
211             }
212         }
213     }
214 }
215