|
| 1 | +using System; |
| 2 | +using System.Runtime.InteropServices; |
| 3 | + |
| 4 | +namespace WinRT.Interop |
| 5 | +{ |
| 6 | + // Direct P/Invoke for platform helpers |
| 7 | + internal static partial class Platform |
| 8 | + { |
| 9 | + [DllImport("api-ms-win-core-com-l1-1-0.dll")] |
| 10 | + public static extern unsafe int CoCreateInstance(Guid* clsid, IntPtr outer, uint clsContext, Guid* iid, IntPtr* instance); |
| 11 | + |
| 12 | + [DllImport("api-ms-win-core-com-l1-1-0.dll")] |
| 13 | + public static extern int CoDecrementMTAUsage(IntPtr cookie); |
| 14 | + |
| 15 | + [DllImport("api-ms-win-core-com-l1-1-0.dll")] |
| 16 | + public static extern unsafe int CoIncrementMTAUsage(IntPtr* cookie); |
| 17 | + |
| 18 | + [DllImport("api-ms-win-core-winrt-l1-1-0.dll")] |
| 19 | + public static extern unsafe int RoGetActivationFactory(IntPtr runtimeClassId, Guid* iid, IntPtr* factory); |
| 20 | + |
| 21 | + [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] |
| 22 | + public static extern unsafe int WindowsCreateString(ushort* sourceString, int length, IntPtr* hstring); |
| 23 | + |
| 24 | + [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] |
| 25 | + public static extern unsafe int WindowsCreateStringReference( |
| 26 | + ushort* sourceString, |
| 27 | + int length, |
| 28 | + IntPtr* hstring_header, |
| 29 | + IntPtr* hstring); |
| 30 | + |
| 31 | + [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] |
| 32 | + public static extern int WindowsDeleteString(IntPtr hstring); |
| 33 | + |
| 34 | + [DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)] |
| 35 | + public static extern unsafe char* WindowsGetStringRawBuffer(IntPtr hstring, uint* length); |
| 36 | + |
| 37 | + [DllImport("api-ms-win-core-com-l1-1-1.dll", CallingConvention = CallingConvention.StdCall)] |
| 38 | + public static extern unsafe int RoGetAgileReference(uint options, Guid* iid, IntPtr unknown, IntPtr* agileReference); |
| 39 | + |
| 40 | + [DllImport("api-ms-win-core-com-l1-1-0.dll")] |
| 41 | + public static extern unsafe int CoGetContextToken(IntPtr* contextToken); |
| 42 | + |
| 43 | + [DllImport("api-ms-win-core-com-l1-1-0.dll")] |
| 44 | + public static extern unsafe int CoGetObjectContext(Guid* riid, IntPtr* ppv); |
| 45 | + |
| 46 | + [DllImport("oleaut32.dll")] |
| 47 | + public static extern int SetErrorInfo(uint dwReserved, IntPtr perrinfo); |
| 48 | + |
| 49 | + [DllImport("api-ms-win-core-com-l1-1-0.dll")] |
| 50 | + public static extern unsafe int CoCreateFreeThreadedMarshaler(IntPtr outer, IntPtr* marshalerPtr); |
| 51 | + } |
| 52 | + |
| 53 | + // Handcrafted P/Invoke with TFM-specific handling, or thin high-level abstractions (eg. 'TryGetProcAddress'/'GetProcAddress') |
| 54 | + partial class Platform |
| 55 | + { |
| 56 | + public static bool FreeLibrary(IntPtr moduleHandle) |
| 57 | + { |
| 58 | +#if NET6_0_OR_GREATER |
| 59 | + return LibraryImportStubs.FreeLibrary(moduleHandle); |
| 60 | +#else |
| 61 | + return FreeLibrary(moduleHandle); |
| 62 | + |
| 63 | + [DllImport("kernel32.dll", SetLastError = true)] |
| 64 | + [return: MarshalAs(UnmanagedType.Bool)] |
| 65 | + static extern bool FreeLibrary(IntPtr moduleHandle); |
| 66 | +#endif |
| 67 | + } |
| 68 | + |
| 69 | + public static unsafe IntPtr TryGetProcAddress(IntPtr moduleHandle, ReadOnlySpan<byte> functionName) |
| 70 | + { |
| 71 | + fixed (byte* lpFunctionName = functionName) |
| 72 | + { |
| 73 | +#if NET6_0_OR_GREATER |
| 74 | + return LibraryImportStubs.GetProcAddress(moduleHandle, (sbyte*)lpFunctionName); |
| 75 | +#else |
| 76 | + return GetProcAddress(moduleHandle, (sbyte*)lpFunctionName); |
| 77 | + |
| 78 | + [DllImport("kernel32.dll", SetLastError = true)] |
| 79 | + static extern unsafe IntPtr GetProcAddress(IntPtr nativeModuleHandle, sbyte* nativeFunctionName); |
| 80 | +#endif |
| 81 | + } |
| 82 | + } |
| 83 | + |
| 84 | + public static IntPtr GetProcAddress(IntPtr moduleHandle, ReadOnlySpan<byte> functionName) |
| 85 | + { |
| 86 | + IntPtr functionPtr = TryGetProcAddress(moduleHandle, functionName); |
| 87 | + |
| 88 | + if (functionPtr == IntPtr.Zero) |
| 89 | + { |
| 90 | + Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error(), new IntPtr(-1)); |
| 91 | + } |
| 92 | + |
| 93 | + return functionPtr; |
| 94 | + } |
| 95 | + |
| 96 | + public static unsafe IntPtr LoadLibraryExW(string fileName, IntPtr fileHandle, uint flags) |
| 97 | + { |
| 98 | + fixed (char* lpFileName = fileName) |
| 99 | + { |
| 100 | +#if NET6_0_OR_GREATER |
| 101 | + return LibraryImportStubs.LoadLibraryExW((ushort*)lpFileName, fileHandle, flags); |
| 102 | +#else |
| 103 | + return LoadLibraryExW((ushort*)lpFileName, fileHandle, flags); |
| 104 | + |
| 105 | + [DllImport("kernel32.dll", SetLastError = true)] |
| 106 | + static unsafe extern IntPtr LoadLibraryExW(ushort* fileName, IntPtr fileHandle, uint flags); |
| 107 | +#endif |
| 108 | + } |
| 109 | + } |
| 110 | + } |
| 111 | + |
| 112 | +#if NET6_0_OR_GREATER |
| 113 | + // Marshalling stubs from [LibraryImport], which are used to get the same semantics (eg. for setting |
| 114 | + // the last P/Invoke errors, etc.) on .NET 6 as well ([LibraryImport] was only introduced in .NET 7). |
| 115 | + internal static class LibraryImportStubs |
| 116 | + { |
| 117 | + public static bool FreeLibrary(IntPtr moduleHandle) |
| 118 | + { |
| 119 | + int lastError; |
| 120 | + bool returnValue; |
| 121 | + int nativeReturnValue; |
| 122 | + { |
| 123 | + Marshal.SetLastSystemError(0); |
| 124 | + nativeReturnValue = PInvoke(moduleHandle); |
| 125 | + lastError = Marshal.GetLastSystemError(); |
| 126 | + } |
| 127 | + |
| 128 | + // Unmarshal - Convert native data to managed data. |
| 129 | + returnValue = nativeReturnValue != 0; |
| 130 | + Marshal.SetLastPInvokeError(lastError); |
| 131 | + return returnValue; |
| 132 | + |
| 133 | + // Local P/Invoke |
| 134 | + [DllImport("kernel32.dll", EntryPoint = "FreeLibrary", ExactSpelling = true)] |
| 135 | + static extern unsafe int PInvoke(IntPtr nativeModuleHandle); |
| 136 | + } |
| 137 | + |
| 138 | + public static unsafe IntPtr GetProcAddress(IntPtr moduleHandle, sbyte* functionName) |
| 139 | + { |
| 140 | + int lastError; |
| 141 | + IntPtr returnValue; |
| 142 | + { |
| 143 | + Marshal.SetLastSystemError(0); |
| 144 | + returnValue = PInvoke(moduleHandle, functionName); |
| 145 | + lastError = Marshal.GetLastSystemError(); |
| 146 | + } |
| 147 | + |
| 148 | + Marshal.SetLastPInvokeError(lastError); |
| 149 | + return returnValue; |
| 150 | + |
| 151 | + // Local P/Invoke |
| 152 | + [DllImport("kernel32.dll", EntryPoint = "GetProcAddress", ExactSpelling = true)] |
| 153 | + static extern unsafe IntPtr PInvoke(IntPtr nativeModuleHandle, sbyte* nativeFunctionName); |
| 154 | + } |
| 155 | + |
| 156 | + public static unsafe IntPtr LoadLibraryExW(ushort* fileName, IntPtr fileHandle, uint flags) |
| 157 | + { |
| 158 | + int lastError; |
| 159 | + IntPtr returnValue; |
| 160 | + { |
| 161 | + Marshal.SetLastSystemError(0); |
| 162 | + returnValue = PInvoke(fileName, fileHandle, flags); |
| 163 | + lastError = Marshal.GetLastSystemError(); |
| 164 | + } |
| 165 | + |
| 166 | + Marshal.SetLastPInvokeError(lastError); |
| 167 | + return returnValue; |
| 168 | + |
| 169 | + // Local P/Invoke |
| 170 | + [DllImport("kernel32.dll", EntryPoint = "LoadLibraryExW", ExactSpelling = true)] |
| 171 | + static extern unsafe IntPtr PInvoke(ushort* nativeFileName, IntPtr nativeFileHandle, uint nativeFlags); |
| 172 | + } |
| 173 | + } |
| 174 | +#endif |
| 175 | +} |
0 commit comments