Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move all Platform APIs to WinRT.Runtime, remove leftover ones #1472

Merged
merged 8 commits into from
Jan 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions src/WinRT.Runtime/ActivationFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using WinRT.Interop;

namespace WinRT
Expand Down Expand Up @@ -57,13 +58,13 @@ private static bool TryCreate(string fileName, out DllModule module)
}

void* getActivationFactory = null;

ReadOnlySpan<byte> functionName =
#if NET7_0_OR_GREATER || CsWinRT_LANG_11_FEATURES
ReadOnlySpan<byte> functionName = "DllGetActivationFactory"u8;
"DllGetActivationFactory"u8;
#else
string functionName = "DllGetActivationFactory";
Encoding.ASCII.GetBytes("DllGetActivationFactory");
#endif
getActivationFactory = Platform.TryGetProcAddress(moduleHandle, functionName);
getActivationFactory = (void*)Platform.TryGetProcAddress(moduleHandle, functionName);
if (getActivationFactory == null)
{
module = null;
Expand All @@ -84,12 +85,13 @@ private DllModule(string fileName, IntPtr moduleHandle, void* getActivationFacto
_GetActivationFactory = (delegate* unmanaged[Stdcall]<IntPtr, IntPtr*, int>)getActivationFactory;

void* canUnloadNow = null;
ReadOnlySpan<byte> functionName =
#if NET7_0_OR_GREATER || CsWinRT_LANG_11_FEATURES
ReadOnlySpan<byte> functionName = "DllCanUnloadNow"u8;
"DllCanUnloadNow"u8;
#else
string functionName = "DllCanUnloadNow";
Encoding.ASCII.GetBytes("DllCanUnloadNow");
#endif
canUnloadNow = Platform.TryGetProcAddress(_moduleHandle, functionName);
canUnloadNow = (void*)Platform.TryGetProcAddress(_moduleHandle, functionName);

if (canUnloadNow != null)
{
Expand Down
11 changes: 3 additions & 8 deletions src/WinRT.Runtime/Context.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,29 +4,24 @@
using System;
using System.Runtime.InteropServices;
using ABI.WinRT.Interop;
using WinRT.Interop;

namespace WinRT
{
internal static partial class Context
{
[DllImport("api-ms-win-core-com-l1-1-0.dll")]
private static extern unsafe int CoGetContextToken(IntPtr* contextToken);

public unsafe static IntPtr GetContextToken()
{
IntPtr contextToken;
Marshal.ThrowExceptionForHR(CoGetContextToken(&contextToken));
Marshal.ThrowExceptionForHR(Platform.CoGetContextToken(&contextToken));
return contextToken;
}

[DllImport("api-ms-win-core-com-l1-1-0.dll")]
private static extern unsafe int CoGetObjectContext(Guid* riid, IntPtr* ppv);

public static unsafe IntPtr GetContextCallback()
{
Guid iid = InterfaceIIDs.IContextCallback_IID;
IntPtr contextCallbackPtr;
Marshal.ThrowExceptionForHR(CoGetObjectContext(&iid, &contextCallbackPtr));
Marshal.ThrowExceptionForHR(Platform.CoGetObjectContext(&iid, &contextCallbackPtr));
return contextCallbackPtr;
}

Expand Down
14 changes: 6 additions & 8 deletions src/WinRT.Runtime/ExceptionHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.IO;
using System.Runtime.ExceptionServices;
using System.Runtime.InteropServices;
using System.Text;
using WinRT.Interop;

namespace WinRT
Expand Down Expand Up @@ -51,9 +52,6 @@ static unsafe class ExceptionHelpers
private const int ERROR_CANCELLED = unchecked((int)0x800704c7);
private const int ERROR_TIMEOUT = unchecked((int)0x800705b4);

[DllImport("oleaut32.dll")]
private static extern int SetErrorInfo(uint dwReserved, IntPtr perrinfo);

private static delegate* unmanaged[Stdcall]<IntPtr*, int> getRestrictedErrorInfo;
private static delegate* unmanaged[Stdcall]<IntPtr, int> setRestrictedErrorInfo;
private static delegate* unmanaged[Stdcall]<int, IntPtr, IntPtr, int> roOriginateLanguageException;
Expand All @@ -70,8 +68,8 @@ private static bool Initialize()
ReadOnlySpan<byte> langExceptionString = "RoOriginateLanguageException"u8;
ReadOnlySpan<byte> reportUnhandledErrorString = "RoReportUnhandledError"u8;
#else
string langExceptionString = "RoOriginateLanguageException";
string reportUnhandledErrorString = "RoReportUnhandledError";
ReadOnlySpan<byte> langExceptionString = Encoding.ASCII.GetBytes("RoOriginateLanguageException");
ReadOnlySpan<byte> reportUnhandledErrorString = Encoding.ASCII.GetBytes("RoReportUnhandledError");
#endif

roOriginateLanguageException = (delegate* unmanaged[Stdcall]<int, IntPtr, IntPtr, int>)Platform.GetProcAddress(winRTErrorModule, langExceptionString);
Expand All @@ -88,8 +86,8 @@ private static bool Initialize()
ReadOnlySpan<byte> getRestrictedErrorInfoFuncName = "GetRestrictedErrorInfo"u8;
ReadOnlySpan<byte> setRestrictedErrorInfoFuncName = "SetRestrictedErrorInfo"u8;
#else
string getRestrictedErrorInfoFuncName = "GetRestrictedErrorInfo";
string setRestrictedErrorInfoFuncName = "SetRestrictedErrorInfo";
ReadOnlySpan<byte> getRestrictedErrorInfoFuncName = Encoding.ASCII.GetBytes("GetRestrictedErrorInfo");
ReadOnlySpan<byte> setRestrictedErrorInfoFuncName = Encoding.ASCII.GetBytes("SetRestrictedErrorInfo");
#endif
getRestrictedErrorInfo = (delegate* unmanaged[Stdcall]<IntPtr*, int>)Platform.GetProcAddress(winRTErrorModule, getRestrictedErrorInfoFuncName);
setRestrictedErrorInfo = (delegate* unmanaged[Stdcall]<IntPtr, int>)Platform.GetProcAddress(winRTErrorModule, setRestrictedErrorInfoFuncName);
Expand Down Expand Up @@ -351,7 +349,7 @@ public static unsafe void SetErrorInfo(Exception ex)
else
{
using var iErrorInfo = ComWrappersSupport.CreateCCWForObject(new ManagedExceptionErrorInfo(ex));
SetErrorInfo(0, iErrorInfo.ThisPtr);
Platform.SetErrorInfo(0, iErrorInfo.ThisPtr);
}
}

Expand Down
7 changes: 2 additions & 5 deletions src/WinRT.Runtime/Interop/IMarshal.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,7 @@ namespace ABI.WinRT.Interop
[Guid("00000003-0000-0000-c000-000000000046")]
internal sealed class IMarshal
{
internal static readonly Guid IID = InterfaceIIDs.IMarshal_IID;

[DllImport("api-ms-win-core-com-l1-1-0.dll")]
private static extern unsafe int CoCreateFreeThreadedMarshaler(IntPtr outer, IntPtr* marshalerPtr);
internal static readonly Guid IID = InterfaceIIDs.IMarshal_IID;

private static readonly string NotImplemented_NativeRoutineNotFound = "A native library routine was not found: {0}.";

Expand Down Expand Up @@ -119,7 +116,7 @@ private static void EnsureHasFreeThreadedMarshaler()
try
{
IntPtr proxyPtr;
Marshal.ThrowExceptionForHR(CoCreateFreeThreadedMarshaler(IntPtr.Zero, &proxyPtr));
Marshal.ThrowExceptionForHR(Platform.CoCreateFreeThreadedMarshaler(IntPtr.Zero, &proxyPtr));
using var objRef = ObjectReference<IUnknownVftbl>.Attach(ref proxyPtr);
IMarshal proxy = new IMarshal(objRef);
t_freeThreadedMarshaler = proxy;
Expand Down
1 change: 1 addition & 0 deletions src/WinRT.Runtime/MonoSupport.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using WinRT.Interop;

#pragma warning disable 0169 // The field 'xxx' is never used
#pragma warning disable 0649 // Field 'xxx' is never assigned to, and will always have its default value
Expand Down
175 changes: 175 additions & 0 deletions src/WinRT.Runtime/Platform.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
using System;
using System.Runtime.InteropServices;

namespace WinRT.Interop
{
// Direct P/Invoke for platform helpers
internal static partial class Platform
{
[DllImport("api-ms-win-core-com-l1-1-0.dll")]
public static extern unsafe int CoCreateInstance(Guid* clsid, IntPtr outer, uint clsContext, Guid* iid, IntPtr* instance);

[DllImport("api-ms-win-core-com-l1-1-0.dll")]
public static extern int CoDecrementMTAUsage(IntPtr cookie);

[DllImport("api-ms-win-core-com-l1-1-0.dll")]
public static extern unsafe int CoIncrementMTAUsage(IntPtr* cookie);

[DllImport("api-ms-win-core-winrt-l1-1-0.dll")]
public static extern unsafe int RoGetActivationFactory(IntPtr runtimeClassId, Guid* iid, IntPtr* factory);

[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int WindowsCreateString(ushort* sourceString, int length, IntPtr* hstring);

[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int WindowsCreateStringReference(
ushort* sourceString,
int length,
IntPtr* hstring_header,
IntPtr* hstring);

[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
public static extern int WindowsDeleteString(IntPtr hstring);

[DllImport("api-ms-win-core-winrt-string-l1-1-0.dll", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe char* WindowsGetStringRawBuffer(IntPtr hstring, uint* length);

[DllImport("api-ms-win-core-com-l1-1-1.dll", CallingConvention = CallingConvention.StdCall)]
public static extern unsafe int RoGetAgileReference(uint options, Guid* iid, IntPtr unknown, IntPtr* agileReference);

[DllImport("api-ms-win-core-com-l1-1-0.dll")]
public static extern unsafe int CoGetContextToken(IntPtr* contextToken);

[DllImport("api-ms-win-core-com-l1-1-0.dll")]
public static extern unsafe int CoGetObjectContext(Guid* riid, IntPtr* ppv);

[DllImport("oleaut32.dll")]
public static extern int SetErrorInfo(uint dwReserved, IntPtr perrinfo);

[DllImport("api-ms-win-core-com-l1-1-0.dll")]
public static extern unsafe int CoCreateFreeThreadedMarshaler(IntPtr outer, IntPtr* marshalerPtr);
}

// Handcrafted P/Invoke with TFM-specific handling, or thin high-level abstractions (eg. 'TryGetProcAddress'/'GetProcAddress')
partial class Platform
{
public static bool FreeLibrary(IntPtr moduleHandle)
{
#if NET6_0_OR_GREATER
return LibraryImportStubs.FreeLibrary(moduleHandle);
#else
return FreeLibrary(moduleHandle);

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool FreeLibrary(IntPtr moduleHandle);
#endif
}

public static unsafe IntPtr TryGetProcAddress(IntPtr moduleHandle, ReadOnlySpan<byte> functionName)
{
fixed (byte* lpFunctionName = functionName)
{
#if NET6_0_OR_GREATER
return LibraryImportStubs.GetProcAddress(moduleHandle, (sbyte*)lpFunctionName);
#else
return GetProcAddress(moduleHandle, (sbyte*)lpFunctionName);

[DllImport("kernel32.dll", SetLastError = true)]
static extern unsafe IntPtr GetProcAddress(IntPtr nativeModuleHandle, sbyte* nativeFunctionName);
#endif
}
}

public static IntPtr GetProcAddress(IntPtr moduleHandle, ReadOnlySpan<byte> functionName)
{
IntPtr functionPtr = TryGetProcAddress(moduleHandle, functionName);

if (functionPtr == IntPtr.Zero)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error(), new IntPtr(-1));
}

return functionPtr;
}

public static unsafe IntPtr LoadLibraryExW(string fileName, IntPtr fileHandle, uint flags)
{
fixed (char* lpFileName = fileName)
{
#if NET6_0_OR_GREATER
return LibraryImportStubs.LoadLibraryExW((ushort*)lpFileName, fileHandle, flags);
#else
return LoadLibraryExW((ushort*)lpFileName, fileHandle, flags);

[DllImport("kernel32.dll", SetLastError = true)]
static unsafe extern IntPtr LoadLibraryExW(ushort* fileName, IntPtr fileHandle, uint flags);
#endif
}
}
}

#if NET6_0_OR_GREATER
// Marshalling stubs from [LibraryImport], which are used to get the same semantics (eg. for setting
// the last P/Invoke errors, etc.) on .NET 6 as well ([LibraryImport] was only introduced in .NET 7).
internal static class LibraryImportStubs
{
public static bool FreeLibrary(IntPtr moduleHandle)
{
int lastError;
bool returnValue;
int nativeReturnValue;
{
Marshal.SetLastSystemError(0);
nativeReturnValue = PInvoke(moduleHandle);
lastError = Marshal.GetLastSystemError();
}

// Unmarshal - Convert native data to managed data.
returnValue = nativeReturnValue != 0;
Marshal.SetLastPInvokeError(lastError);
return returnValue;

// Local P/Invoke
[DllImport("kernel32.dll", EntryPoint = "FreeLibrary", ExactSpelling = true)]
static extern unsafe int PInvoke(IntPtr nativeModuleHandle);
}

public static unsafe IntPtr GetProcAddress(IntPtr moduleHandle, sbyte* functionName)
{
int lastError;
IntPtr returnValue;
{
Marshal.SetLastSystemError(0);
returnValue = PInvoke(moduleHandle, functionName);
lastError = Marshal.GetLastSystemError();
}

Marshal.SetLastPInvokeError(lastError);
return returnValue;

// Local P/Invoke
[DllImport("kernel32.dll", EntryPoint = "GetProcAddress", ExactSpelling = true)]
static extern unsafe IntPtr PInvoke(IntPtr nativeModuleHandle, sbyte* nativeFunctionName);
}

public static unsafe IntPtr LoadLibraryExW(ushort* fileName, IntPtr fileHandle, uint flags)
{
int lastError;
IntPtr returnValue;
{
Marshal.SetLastSystemError(0);
returnValue = PInvoke(fileName, fileHandle, flags);
lastError = Marshal.GetLastSystemError();
}

Marshal.SetLastPInvokeError(lastError);
return returnValue;

// Local P/Invoke
[DllImport("kernel32.dll", EntryPoint = "LoadLibraryExW", ExactSpelling = true)]
static extern unsafe IntPtr PInvoke(ushort* nativeFileName, IntPtr nativeFileHandle, uint nativeFlags);
}
}
#endif
}
Loading
Loading