Skip to content

Commit e8440cf

Browse files
authored
Move all Platform APIs to WinRT.Runtime, remove leftover ones (#1472)
* Move platform exports to WinRT.Runtime * Remove unnecessary exports * Centralize all exports into Platform * Remove leftover export * Fix embedding scenario in ActivationFactory * Restructure Platform APIs * Move Platform type to WinRT.Interop * Fix ExceptionHelpers build error for embedding
1 parent ad4887b commit e8440cf

File tree

7 files changed

+196
-259
lines changed

7 files changed

+196
-259
lines changed

src/WinRT.Runtime/ActivationFactory.cs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Diagnostics.CodeAnalysis;
77
using System.Reflection;
88
using System.Runtime.InteropServices;
9+
using System.Text;
910
using WinRT.Interop;
1011

1112
namespace WinRT
@@ -57,13 +58,13 @@ private static bool TryCreate(string fileName, out DllModule module)
5758
}
5859

5960
void* getActivationFactory = null;
60-
61+
ReadOnlySpan<byte> functionName =
6162
#if NET7_0_OR_GREATER || CsWinRT_LANG_11_FEATURES
62-
ReadOnlySpan<byte> functionName = "DllGetActivationFactory"u8;
63+
"DllGetActivationFactory"u8;
6364
#else
64-
string functionName = "DllGetActivationFactory";
65+
Encoding.ASCII.GetBytes("DllGetActivationFactory");
6566
#endif
66-
getActivationFactory = Platform.TryGetProcAddress(moduleHandle, functionName);
67+
getActivationFactory = (void*)Platform.TryGetProcAddress(moduleHandle, functionName);
6768
if (getActivationFactory == null)
6869
{
6970
module = null;
@@ -84,12 +85,13 @@ private DllModule(string fileName, IntPtr moduleHandle, void* getActivationFacto
8485
_GetActivationFactory = (delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, int>)getActivationFactory;
8586

8687
void* canUnloadNow = null;
88+
ReadOnlySpan<byte> functionName =
8789
#if NET7_0_OR_GREATER || CsWinRT_LANG_11_FEATURES
88-
ReadOnlySpan<byte> functionName = "DllCanUnloadNow"u8;
90+
"DllCanUnloadNow"u8;
8991
#else
90-
string functionName = "DllCanUnloadNow";
92+
Encoding.ASCII.GetBytes("DllCanUnloadNow");
9193
#endif
92-
canUnloadNow = Platform.TryGetProcAddress(_moduleHandle, functionName);
94+
canUnloadNow = (void*)Platform.TryGetProcAddress(_moduleHandle, functionName);
9395

9496
if (canUnloadNow != null)
9597
{

src/WinRT.Runtime/Context.cs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,24 @@
44
using System;
55
using System.Runtime.InteropServices;
66
using ABI.WinRT.Interop;
7+
using WinRT.Interop;
78

89
namespace WinRT
910
{
1011
internal static partial class Context
1112
{
12-
[DllImport("api-ms-win-core-com-l1-1-0.dll")]
13-
private static extern unsafe int CoGetContextToken(IntPtr* contextToken);
14-
1513
public unsafe static IntPtr GetContextToken()
1614
{
1715
IntPtr contextToken;
18-
Marshal.ThrowExceptionForHR(CoGetContextToken(&contextToken));
16+
Marshal.ThrowExceptionForHR(Platform.CoGetContextToken(&contextToken));
1917
return contextToken;
2018
}
2119

22-
[DllImport("api-ms-win-core-com-l1-1-0.dll")]
23-
private static extern unsafe int CoGetObjectContext(Guid* riid, IntPtr* ppv);
24-
2520
public static unsafe IntPtr GetContextCallback()
2621
{
2722
Guid iid = InterfaceIIDs.IContextCallback_IID;
2823
IntPtr contextCallbackPtr;
29-
Marshal.ThrowExceptionForHR(CoGetObjectContext(&iid, &contextCallbackPtr));
24+
Marshal.ThrowExceptionForHR(Platform.CoGetObjectContext(&iid, &contextCallbackPtr));
3025
return contextCallbackPtr;
3126
}
3227

src/WinRT.Runtime/ExceptionHelpers.cs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO;
77
using System.Runtime.ExceptionServices;
88
using System.Runtime.InteropServices;
9+
using System.Text;
910
using WinRT.Interop;
1011

1112
namespace WinRT
@@ -51,9 +52,6 @@ static unsafe class ExceptionHelpers
5152
private const int ERROR_CANCELLED = unchecked((int)0x800704c7);
5253
private const int ERROR_TIMEOUT = unchecked((int)0x800705b4);
5354

54-
[DllImport("oleaut32.dll")]
55-
private static extern int SetErrorInfo(uint dwReserved, IntPtr perrinfo);
56-
5755
private static delegate* unmanaged[Stdcall]<IntPtr*, int> getRestrictedErrorInfo;
5856
private static delegate* unmanaged[Stdcall]<IntPtr, int> setRestrictedErrorInfo;
5957
private static delegate* unmanaged[Stdcall]<int, IntPtr, IntPtr, int> roOriginateLanguageException;
@@ -70,8 +68,8 @@ private static bool Initialize()
7068
ReadOnlySpan<byte> langExceptionString = "RoOriginateLanguageException"u8;
7169
ReadOnlySpan<byte> reportUnhandledErrorString = "RoReportUnhandledError"u8;
7270
#else
73-
string langExceptionString = "RoOriginateLanguageException";
74-
string reportUnhandledErrorString = "RoReportUnhandledError";
71+
ReadOnlySpan<byte> langExceptionString = Encoding.ASCII.GetBytes("RoOriginateLanguageException");
72+
ReadOnlySpan<byte> reportUnhandledErrorString = Encoding.ASCII.GetBytes("RoReportUnhandledError");
7573
#endif
7674

7775
roOriginateLanguageException = (delegate* unmanaged[Stdcall]<int, IntPtr, IntPtr, int>)Platform.GetProcAddress(winRTErrorModule, langExceptionString);
@@ -88,8 +86,8 @@ private static bool Initialize()
8886
ReadOnlySpan<byte> getRestrictedErrorInfoFuncName = "GetRestrictedErrorInfo"u8;
8987
ReadOnlySpan<byte> setRestrictedErrorInfoFuncName = "SetRestrictedErrorInfo"u8;
9088
#else
91-
string getRestrictedErrorInfoFuncName = "GetRestrictedErrorInfo";
92-
string setRestrictedErrorInfoFuncName = "SetRestrictedErrorInfo";
89+
ReadOnlySpan<byte> getRestrictedErrorInfoFuncName = Encoding.ASCII.GetBytes("GetRestrictedErrorInfo");
90+
ReadOnlySpan<byte> setRestrictedErrorInfoFuncName = Encoding.ASCII.GetBytes("SetRestrictedErrorInfo");
9391
#endif
9492
getRestrictedErrorInfo = (delegate* unmanaged[Stdcall]<IntPtr*, int>)Platform.GetProcAddress(winRTErrorModule, getRestrictedErrorInfoFuncName);
9593
setRestrictedErrorInfo = (delegate* unmanaged[Stdcall]<IntPtr, int>)Platform.GetProcAddress(winRTErrorModule, setRestrictedErrorInfoFuncName);
@@ -351,7 +349,7 @@ public static unsafe void SetErrorInfo(Exception ex)
351349
else
352350
{
353351
using var iErrorInfo = ComWrappersSupport.CreateCCWForObject(new ManagedExceptionErrorInfo(ex));
354-
SetErrorInfo(0, iErrorInfo.ThisPtr);
352+
Platform.SetErrorInfo(0, iErrorInfo.ThisPtr);
355353
}
356354
}
357355

src/WinRT.Runtime/Interop/IMarshal.cs

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,7 @@ namespace ABI.WinRT.Interop
3636
[Guid("00000003-0000-0000-c000-000000000046")]
3737
internal sealed class IMarshal
3838
{
39-
internal static readonly Guid IID = InterfaceIIDs.IMarshal_IID;
40-
41-
[DllImport("api-ms-win-core-com-l1-1-0.dll")]
42-
private static extern unsafe int CoCreateFreeThreadedMarshaler(IntPtr outer, IntPtr* marshalerPtr);
39+
internal static readonly Guid IID = InterfaceIIDs.IMarshal_IID;
4340

4441
private const string NotImplemented_NativeRoutineNotFound = "A native library routine was not found: {0}.";
4542

@@ -145,7 +142,7 @@ private static void EnsureHasFreeThreadedMarshaler()
145142
try
146143
{
147144
IntPtr proxyPtr;
148-
Marshal.ThrowExceptionForHR(CoCreateFreeThreadedMarshaler(IntPtr.Zero, &proxyPtr));
145+
Marshal.ThrowExceptionForHR(Platform.CoCreateFreeThreadedMarshaler(IntPtr.Zero, &proxyPtr));
149146
using var objRef = ObjectReference<IUnknownVftbl>.Attach(ref proxyPtr);
150147
IMarshal proxy = new IMarshal(objRef);
151148
t_freeThreadedMarshaler = proxy;

src/WinRT.Runtime/MonoSupport.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System;
55
using System.Collections.Generic;
66
using System.Runtime.InteropServices;
7+
using WinRT.Interop;
78

89
#pragma warning disable 0169 // The field 'xxx' is never used
910
#pragma warning disable 0649 // Field 'xxx' is never assigned to, and will always have its default value

src/WinRT.Runtime/Platform.cs

Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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

Comments
 (0)