diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs index d483c76a0ac36..b52b48282e218 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/Internal/MsQuicApi.cs @@ -18,23 +18,8 @@ internal class MsQuicApi : IDisposable private readonly IntPtr _registrationContext; - private unsafe MsQuicApi() + private unsafe MsQuicApi(MsQuicNativeMethods.NativeApi* registration) { - MsQuicNativeMethods.NativeApi* registration; - - try - { - uint status = Interop.MsQuic.MsQuicOpen(out registration); - if (!MsQuicStatusHelper.SuccessfulStatusCode(status)) - { - throw new NotSupportedException(SR.net_quic_notsupported); - } - } - catch (DllNotFoundException) - { - throw new NotSupportedException(SR.net_quic_notsupported); - } - MsQuicNativeMethods.NativeApi nativeRegistration = *registration; RegistrationOpenDelegate = @@ -138,7 +123,7 @@ private unsafe MsQuicApi() internal static bool IsQuicSupported { get; } - static MsQuicApi() + static unsafe MsQuicApi() { // MsQuicOpen will succeed even if the platform will not support it. It will then fail with unspecified // platform-specific errors in subsequent callbacks. For now, check for the minimum build we've tested it on. @@ -150,14 +135,30 @@ static MsQuicApi() // TODO: try to initialize TLS 1.3 in SslStream. - try - { - Api = new MsQuicApi(); - IsQuicSupported = true; - } - catch (NotSupportedException) + // TODO: Consider updating all of these delegates to instead use function pointers. + + if (NativeLibrary.TryLoad(Interop.Libraries.MsQuic, out IntPtr msQuicHandle)) { - IsQuicSupported = false; + try + { + if (NativeLibrary.TryGetExport(msQuicHandle, "MsQuicOpen", out IntPtr msQuicOpenAddress)) + { + MsQuicNativeMethods.MsQuicOpenDelegate msQuicOpen = Marshal.GetDelegateForFunctionPointer(msQuicOpenAddress); + uint status = msQuicOpen(out MsQuicNativeMethods.NativeApi* registration); + if (MsQuicStatusHelper.SuccessfulStatusCode(status)) + { + IsQuicSupported = true; + Api = new MsQuicApi(registration); + } + } + } + finally + { + if (!IsQuicSupported) + { + NativeLibrary.Free(msQuicHandle); + } + } } } diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/Interop.MsQuic.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/Interop.MsQuic.cs deleted file mode 100644 index b873b789f1d22..0000000000000 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/Interop.MsQuic.cs +++ /dev/null @@ -1,15 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System; -using System.Net.Quic.Implementations.MsQuic.Internal; -using System.Runtime.InteropServices; - -internal static partial class Interop -{ - internal static class MsQuic - { - [DllImport(Libraries.MsQuic, CallingConvention = CallingConvention.Cdecl)] - internal static unsafe extern uint MsQuicOpen(out MsQuicNativeMethods.NativeApi* registration); - } -} diff --git a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/MsQuicNativeMethods.cs b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/MsQuicNativeMethods.cs index c8ff6d6a8422c..3027c402bb0ee 100644 --- a/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/MsQuicNativeMethods.cs +++ b/src/libraries/System.Net.Quic/src/System/Net/Quic/Interop/MsQuicNativeMethods.cs @@ -54,6 +54,10 @@ internal struct NativeApi internal IntPtr DatagramSend; } + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate uint MsQuicOpenDelegate( + out NativeApi* registration); + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] internal delegate uint SetContextDelegate( IntPtr handle,