diff --git a/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs b/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs index 6f7af83..6b51c39 100644 --- a/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs +++ b/RGB.NET.Devices.CoolerMaster/Native/_CoolerMasterSDK.cs @@ -16,14 +16,14 @@ internal static class _CoolerMasterSDK { #region Libary Management - private static IntPtr _dllHandle = IntPtr.Zero; + private static IntPtr _handle = IntPtr.Zero; /// /// Reloads the SDK. /// internal static void Reload() { - if (_dllHandle != IntPtr.Zero) + if (_handle != IntPtr.Zero) { foreach (CoolerMasterDevicesIndexes index in Enum.GetValues(typeof(CoolerMasterDevicesIndexes))) EnableLedControl(false, index); @@ -34,7 +34,7 @@ internal static class _CoolerMasterSDK private static void LoadCMSDK() { - if (_dllHandle != IntPtr.Zero) return; + if (_handle != IntPtr.Zero) return; // HACK: Load library at runtime to support both, x86 and x64 with one managed dll List possiblePathList = (Environment.Is64BitProcess ? CoolerMasterDeviceProvider.PossibleX64NativePaths : CoolerMasterDeviceProvider.PossibleX86NativePaths) @@ -43,22 +43,43 @@ internal static class _CoolerMasterSDK string? dllPath = possiblePathList.FirstOrDefault(File.Exists); if (dllPath == null) throw new RGBDeviceException($"Can't find the CoolerMaster-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); - _dllHandle = LoadLibrary(dllPath); - if (_dllHandle == IntPtr.Zero) throw new RGBDeviceException($"CoolerMaster LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); + _handle = LoadLibrary(dllPath); +#if NET6_0 + if (_handle == IntPtr.Zero) throw new RGBDeviceException($"CoolerMaster LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}"); +#else + if (_handle == IntPtr.Zero) throw new RGBDeviceException($"CoolerMaster LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); +#endif - _getSDKVersionPointer = (GetSDKVersionPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "GetCM_SDK_DllVer"), typeof(GetSDKVersionPointer)); - _setControlDevicenPointer = (SetControlDevicePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "SetControlDevice"), typeof(SetControlDevicePointer)); - _isDevicePlugPointer = (IsDevicePlugPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "IsDevicePlug"), typeof(IsDevicePlugPointer)); - _getDeviceLayoutPointer = (GetDeviceLayoutPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "GetDeviceLayout"), typeof(GetDeviceLayoutPointer)); - _enableLedControlPointer = (EnableLedControlPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "EnableLedControl"), typeof(EnableLedControlPointer)); - _refreshLedPointer = (RefreshLedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "RefreshLed"), typeof(RefreshLedPointer)); - _setLedColorPointer = (SetLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "SetLedColor"), typeof(SetLedColorPointer)); - _setAllLedColorPointer = (SetAllLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "SetAllLedColor"), typeof(SetAllLedColorPointer)); + _getSDKVersionPointer = (GetSDKVersionPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "GetCM_SDK_DllVer"), typeof(GetSDKVersionPointer)); + _setControlDevicenPointer = (SetControlDevicePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "SetControlDevice"), typeof(SetControlDevicePointer)); + _isDevicePlugPointer = (IsDevicePlugPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "IsDevicePlug"), typeof(IsDevicePlugPointer)); + _getDeviceLayoutPointer = (GetDeviceLayoutPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "GetDeviceLayout"), typeof(GetDeviceLayoutPointer)); + _enableLedControlPointer = (EnableLedControlPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "EnableLedControl"), typeof(EnableLedControlPointer)); + _refreshLedPointer = (RefreshLedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "RefreshLed"), typeof(RefreshLedPointer)); + _setLedColorPointer = (SetLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "SetLedColor"), typeof(SetLedColorPointer)); + _setAllLedColorPointer = (SetAllLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_handle, "SetAllLedColor"), typeof(SetAllLedColorPointer)); + } + + internal static void UnloadCMSDK() + { + if (_handle == IntPtr.Zero) return; + + _getSDKVersionPointer = null; + _setControlDevicenPointer = null; + _isDevicePlugPointer = null; + _getDeviceLayoutPointer = null; + _enableLedControlPointer = null; + _refreshLedPointer = null; + _setLedColorPointer = null; + _setAllLedColorPointer = null; + + NativeLibrary.Free(_handle); + _handle = IntPtr.Zero; } [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr LoadLibrary(string dllToLoad); - + [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name); diff --git a/RGB.NET.Devices.Corsair/Native/_CUESDK.cs b/RGB.NET.Devices.Corsair/Native/_CUESDK.cs index 1026ecb..9455cb3 100644 --- a/RGB.NET.Devices.Corsair/Native/_CUESDK.cs +++ b/RGB.NET.Devices.Corsair/Native/_CUESDK.cs @@ -16,7 +16,7 @@ internal static class _CUESDK { #region Libary Management - private static IntPtr _dllHandle = IntPtr.Zero; + private static IntPtr _handle = IntPtr.Zero; /// /// Reloads the SDK. @@ -29,113 +29,88 @@ internal static class _CUESDK private static void LoadCUESDK() { - if (_dllHandle != IntPtr.Zero) return; + if (_handle != IntPtr.Zero) return; + + List possiblePathList = GetPossibleLibraryPaths().ToList(); - // HACK: Load library at runtime to support both, x86 and x64 with one managed dll - List possiblePathList = (Environment.Is64BitProcess ? CorsairDeviceProvider.PossibleX64NativePaths : CorsairDeviceProvider.PossibleX86NativePaths) - .Select(Environment.ExpandEnvironmentVariables) - .ToList(); string? dllPath = possiblePathList.FirstOrDefault(File.Exists); if (dllPath == null) throw new RGBDeviceException($"Can't find the CUE-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); - _dllHandle = LoadLibrary(dllPath); - if (_dllHandle == IntPtr.Zero) throw new RGBDeviceException($"Corsair LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); + if (!NativeLibrary.TryLoad(dllPath, out _handle)) +#if NET6_0 + throw new RGBDeviceException($"Corsair LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}"); +#else + throw new RGBDeviceException($"Corsair LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); +#endif - _corsairSetLedsColorsBufferByDeviceIndexPointer = (CorsairSetLedsColorsBufferByDeviceIndexPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairSetLedsColorsBufferByDeviceIndex"), typeof(CorsairSetLedsColorsBufferByDeviceIndexPointer)); - _corsairSetLedsColorsFlushBufferPointer = (CorsairSetLedsColorsFlushBufferPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairSetLedsColorsFlushBuffer"), typeof(CorsairSetLedsColorsFlushBufferPointer)); - _corsairGetLedsColorsByDeviceIndexPointer = (CorsairGetLedsColorsByDeviceIndexPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetLedsColorsByDeviceIndex"), typeof(CorsairGetLedsColorsByDeviceIndexPointer)); - _corsairSetLayerPriorityPointer = (CorsairSetLayerPriorityPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairSetLayerPriority"), typeof(CorsairSetLayerPriorityPointer)); - _corsairGetDeviceCountPointer = (CorsairGetDeviceCountPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetDeviceCount"), typeof(CorsairGetDeviceCountPointer)); - _corsairGetDeviceInfoPointer = (CorsairGetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetDeviceInfo"), typeof(CorsairGetDeviceInfoPointer)); - _corsairGetLedPositionsByDeviceIndexPointer = (CorsairGetLedPositionsByDeviceIndexPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetLedPositionsByDeviceIndex"), typeof(CorsairGetLedPositionsByDeviceIndexPointer)); - _corsairGetLedIdForKeyNamePointer = (CorsairGetLedIdForKeyNamePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetLedIdForKeyName"), typeof(CorsairGetLedIdForKeyNamePointer)); - _corsairRequestControlPointer = (CorsairRequestControlPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairRequestControl"), typeof(CorsairRequestControlPointer)); - _corsairReleaseControlPointer = (CorsairReleaseControlPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairReleaseControl"), typeof(CorsairReleaseControlPointer)); - _corsairPerformProtocolHandshakePointer = (CorsairPerformProtocolHandshakePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairPerformProtocolHandshake"), typeof(CorsairPerformProtocolHandshakePointer)); - _corsairGetLastErrorPointer = (CorsairGetLastErrorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CorsairGetLastError"), typeof(CorsairGetLastErrorPointer)); + if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLedsColorsBufferByDeviceIndex", out _corsairSetLedsColorsBufferByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLedsColorsBufferByDeviceIndex'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLedsColorsFlushBuffer", out _corsairSetLedsColorsFlushBufferPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLedsColorsFlushBuffer'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedsColorsByDeviceIndex", out _corsairGetLedsColorsByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedsColorsByDeviceIndex'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairSetLayerPriority", out _corsairSetLayerPriorityPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairSetLayerPriority'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairGetDeviceCount", out _corsairGetDeviceCountPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetDeviceCount'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairGetDeviceInfo", out _corsairGetDeviceInfoPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetDeviceInfo'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedIdForKeyName", out _corsairGetLedIdForKeyNamePointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedIdForKeyName'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLedPositionsByDeviceIndex", out _corsairGetLedPositionsByDeviceIndexPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLedPositionsByDeviceIndex'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairRequestControl", out _corsairRequestControlPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairRequestControl'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairReleaseControl", out _corsairReleaseControlPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairReleaseControl'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairPerformProtocolHandshake", out _corsairPerformProtocolHandshakePointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairPerformProtocolHandshake'"); + if (!NativeLibrary.TryGetExport(_handle, "CorsairGetLastError", out _corsairGetLastErrorPointer)) throw new RGBDeviceException("Failed to load Corsair function 'CorsairGetLastError'"); + } + + private static IEnumerable GetPossibleLibraryPaths() + { + IEnumerable possibleLibraryPaths; + + if (OperatingSystem.IsWindows()) + possibleLibraryPaths = Environment.Is64BitProcess ? CorsairDeviceProvider.PossibleX64NativePaths : CorsairDeviceProvider.PossibleX86NativePaths; + else + possibleLibraryPaths = Enumerable.Empty(); + + return possibleLibraryPaths.Select(Environment.ExpandEnvironmentVariables); } internal static void UnloadCUESDK() { - if (_dllHandle == IntPtr.Zero) return; + if (_handle == IntPtr.Zero) return; - // ReSharper disable once EmptyEmbeddedStatement - DarthAffe 20.02.2016: We might need to reduce the internal reference counter more than once to set the library free - while (FreeLibrary(_dllHandle)) ; - _dllHandle = IntPtr.Zero; + _corsairSetLedsColorsBufferByDeviceIndexPointer = IntPtr.Zero; + _corsairSetLedsColorsFlushBufferPointer = IntPtr.Zero; + _corsairGetLedsColorsByDeviceIndexPointer = IntPtr.Zero; + _corsairSetLayerPriorityPointer = IntPtr.Zero; + _corsairGetDeviceCountPointer = IntPtr.Zero; + _corsairGetDeviceInfoPointer = IntPtr.Zero; + _corsairGetLedIdForKeyNamePointer = IntPtr.Zero; + _corsairGetLedPositionsByDeviceIndexPointer = IntPtr.Zero; + _corsairRequestControlPointer = IntPtr.Zero; + _corsairReleaseControlPointer = IntPtr.Zero; + _corsairPerformProtocolHandshakePointer = IntPtr.Zero; + _corsairGetLastErrorPointer = IntPtr.Zero; + + NativeLibrary.Free(_handle); + _handle = IntPtr.Zero; } - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern IntPtr LoadLibrary(string dllToLoad); - - [DllImport("kernel32.dll")] - private static extern bool FreeLibrary(IntPtr dllHandle); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] - private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name); - #endregion #region SDK-METHODS #region Pointers - private static CorsairSetLedsColorsBufferByDeviceIndexPointer? _corsairSetLedsColorsBufferByDeviceIndexPointer; - private static CorsairSetLedsColorsFlushBufferPointer? _corsairSetLedsColorsFlushBufferPointer; - private static CorsairGetLedsColorsByDeviceIndexPointer? _corsairGetLedsColorsByDeviceIndexPointer; - private static CorsairSetLayerPriorityPointer? _corsairSetLayerPriorityPointer; - private static CorsairGetDeviceCountPointer? _corsairGetDeviceCountPointer; - private static CorsairGetDeviceInfoPointer? _corsairGetDeviceInfoPointer; - private static CorsairGetLedIdForKeyNamePointer? _corsairGetLedIdForKeyNamePointer; - private static CorsairGetLedPositionsByDeviceIndexPointer? _corsairGetLedPositionsByDeviceIndexPointer; - private static CorsairRequestControlPointer? _corsairRequestControlPointer; - private static CorsairReleaseControlPointer? _corsairReleaseControlPointer; - private static CorsairPerformProtocolHandshakePointer? _corsairPerformProtocolHandshakePointer; - private static CorsairGetLastErrorPointer? _corsairGetLastErrorPointer; + private static IntPtr _corsairSetLedsColorsBufferByDeviceIndexPointer; + private static IntPtr _corsairSetLedsColorsFlushBufferPointer; + private static IntPtr _corsairGetLedsColorsByDeviceIndexPointer; + private static IntPtr _corsairSetLayerPriorityPointer; + private static IntPtr _corsairGetDeviceCountPointer; + private static IntPtr _corsairGetDeviceInfoPointer; + private static IntPtr _corsairGetLedIdForKeyNamePointer; + private static IntPtr _corsairGetLedPositionsByDeviceIndexPointer; + private static IntPtr _corsairRequestControlPointer; + private static IntPtr _corsairReleaseControlPointer; + private static IntPtr _corsairPerformProtocolHandshakePointer; + private static IntPtr _corsairGetLastErrorPointer; #endregion - #region Delegates - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool CorsairSetLedsColorsBufferByDeviceIndexPointer(int deviceIndex, int size, IntPtr ledsColors); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool CorsairSetLedsColorsFlushBufferPointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool CorsairGetLedsColorsByDeviceIndexPointer(int deviceIndex, int size, IntPtr ledsColors); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool CorsairSetLayerPriorityPointer(int priority); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate int CorsairGetDeviceCountPointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate IntPtr CorsairGetDeviceInfoPointer(int deviceIndex); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate IntPtr CorsairGetLedPositionsByDeviceIndexPointer(int deviceIndex); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate CorsairLedId CorsairGetLedIdForKeyNamePointer(char keyName); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool CorsairRequestControlPointer(CorsairAccessMode accessMode); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool CorsairReleaseControlPointer(CorsairAccessMode accessMode); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate _CorsairProtocolDetails CorsairPerformProtocolHandshakePointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate CorsairError CorsairGetLastErrorPointer(); - - #endregion - - // ReSharper disable EventExceptionNotDocumented - /// /// CUE-SDK: set specified LEDs to some colors. /// This function set LEDs colors in the buffer which is written to the devices via CorsairSetLedsColorsFlushBuffer or CorsairSetLedsColorsFlushBufferAsync. @@ -143,72 +118,76 @@ internal static class _CUESDK /// and follows after one or more calls of CorsairSetLedsColorsBufferByDeviceIndex to set the LEDs buffer. /// This function does not take logical layout into account. /// - internal static bool CorsairSetLedsColorsBufferByDeviceIndex(int deviceIndex, int size, IntPtr ledsColors) - => (_corsairSetLedsColorsBufferByDeviceIndexPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(deviceIndex, size, ledsColors); + internal static unsafe bool CorsairSetLedsColorsBufferByDeviceIndex(int deviceIndex, int size, IntPtr ledsColors) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLedsColorsBufferByDeviceIndexPointer))(deviceIndex, size, ledsColors); /// /// CUE-SDK: writes to the devices LEDs colors buffer which is previously filled by the CorsairSetLedsColorsBufferByDeviceIndex function. /// This function executes synchronously, if you are concerned about delays consider using CorsairSetLedsColorsFlushBufferAsync /// - internal static bool CorsairSetLedsColorsFlushBuffer() => (_corsairSetLedsColorsFlushBufferPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(); + internal static unsafe bool CorsairSetLedsColorsFlushBuffer() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLedsColorsFlushBufferPointer))(); /// /// CUE-SDK: get current color for the list of requested LEDs. /// The color should represent the actual state of the hardware LED, which could be a combination of SDK and/or CUE input. /// This function works for keyboard, mouse, mousemat, headset, headset stand and DIY-devices. /// - internal static bool CorsairGetLedsColorsByDeviceIndex(int deviceIndex, int size, IntPtr ledsColors) - => (_corsairGetLedsColorsByDeviceIndexPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(deviceIndex, size, ledsColors); + internal static unsafe bool CorsairGetLedsColorsByDeviceIndex(int deviceIndex, int size, IntPtr ledsColors) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedsColorsByDeviceIndexPointer))(deviceIndex, size, ledsColors); /// /// CUE-SDK: set layer priority for this shared client. /// By default CUE has priority of 127 and all shared clients have priority of 128 if they don’t call this function. /// Layers with higher priority value are shown on top of layers with lower priority. /// - internal static bool CorsairSetLayerPriority(int priority) => (_corsairSetLayerPriorityPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(priority); + internal static unsafe bool CorsairSetLayerPriority(int priority) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairSetLayerPriorityPointer))(priority); /// /// CUE-SDK: returns number of connected Corsair devices that support lighting control. /// - internal static int CorsairGetDeviceCount() => (_corsairGetDeviceCountPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(); + internal static unsafe int CorsairGetDeviceCount() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetDeviceCountPointer))(); /// /// CUE-SDK: returns information about device at provided index. /// - internal static IntPtr CorsairGetDeviceInfo(int deviceIndex) => (_corsairGetDeviceInfoPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(deviceIndex); + internal static unsafe IntPtr CorsairGetDeviceInfo(int deviceIndex) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetDeviceInfoPointer))(deviceIndex); /// /// CUE-SDK: provides list of keyboard or mousepad LEDs with their physical positions. /// - internal static IntPtr CorsairGetLedPositionsByDeviceIndex(int deviceIndex) => (_corsairGetLedPositionsByDeviceIndexPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(deviceIndex); + internal static unsafe IntPtr CorsairGetLedPositionsByDeviceIndex(int deviceIndex) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedPositionsByDeviceIndexPointer))(deviceIndex); /// /// CUE-SDK: retrieves led id for key name taking logical layout into account. /// - internal static CorsairLedId CorsairGetLedIdForKeyName(char keyName) => (_corsairGetLedIdForKeyNamePointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(keyName); + internal static unsafe CorsairLedId CorsairGetLedIdForKeyName(char keyName) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLedIdForKeyNamePointer))(keyName); /// /// CUE-SDK: requestes control using specified access mode. /// By default client has shared control over lighting so there is no need to call CorsairRequestControl unless client requires exclusive control. /// - internal static bool CorsairRequestControl(CorsairAccessMode accessMode) => (_corsairRequestControlPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(accessMode); + internal static unsafe bool CorsairRequestControl(CorsairAccessMode accessMode) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairRequestControlPointer))(accessMode); /// /// CUE-SDK: releases previously requested control for specified access mode. /// - internal static bool CorsairReleaseControl(CorsairAccessMode accessMode) => (_corsairReleaseControlPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(accessMode); + internal static unsafe bool CorsairReleaseControl(CorsairAccessMode accessMode) => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairReleaseControlPointer))(accessMode); /// /// CUE-SDK: checks file and protocol version of CUE to understand which of SDK functions can be used with this version of CUE. /// - internal static _CorsairProtocolDetails CorsairPerformProtocolHandshake() => (_corsairPerformProtocolHandshakePointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(); + internal static unsafe _CorsairProtocolDetails CorsairPerformProtocolHandshake() => ((delegate* unmanaged[Cdecl]<_CorsairProtocolDetails>)ThrowIfZero(_corsairPerformProtocolHandshakePointer))(); /// /// CUE-SDK: returns last error that occured while using any of Corsair* functions. /// - internal static CorsairError CorsairGetLastError() => (_corsairGetLastErrorPointer ?? throw new RGBDeviceException("The Corsair-SDK is not initialized.")).Invoke(); + internal static unsafe CorsairError CorsairGetLastError() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_corsairGetLastErrorPointer))(); - // ReSharper restore EventExceptionNotDocumented + private static IntPtr ThrowIfZero(IntPtr ptr) + { + if (ptr == IntPtr.Zero) throw new RGBDeviceException("The Corsair-SDK is not initialized."); + return ptr; + } #endregion } \ No newline at end of file diff --git a/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj b/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj index 9165e9c..09f7e28 100644 --- a/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj +++ b/RGB.NET.Devices.Corsair/RGB.NET.Devices.Corsair.csproj @@ -36,6 +36,7 @@ True portable snupkg + true diff --git a/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs b/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs index 1293549..76efa36 100644 --- a/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs +++ b/RGB.NET.Devices.Logitech/Native/_LogitechGSDK.cs @@ -13,11 +13,11 @@ using RGB.NET.Core; namespace RGB.NET.Devices.Logitech.Native; // ReSharper disable once InconsistentNaming -internal class _LogitechGSDK +internal static class _LogitechGSDK { #region Libary Management - private static IntPtr _dllHandle = IntPtr.Zero; + private static IntPtr _handle = IntPtr.Zero; /// /// Reloads the SDK. @@ -30,110 +30,90 @@ internal class _LogitechGSDK private static void LoadLogitechGSDK() { - if (_dllHandle != IntPtr.Zero) return; + if (_handle != IntPtr.Zero) return; + + List possiblePathList = GetPossibleLibraryPaths().ToList(); - // HACK: Load library at runtime to support both, x86 and x64 with one managed dll - List possiblePathList = (Environment.Is64BitProcess ? LogitechDeviceProvider.PossibleX64NativePaths : LogitechDeviceProvider.PossibleX86NativePaths) - .Select(Environment.ExpandEnvironmentVariables) - .ToList(); string? dllPath = possiblePathList.FirstOrDefault(File.Exists); if (dllPath == null) throw new RGBDeviceException($"Can't find the Logitech-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); - _dllHandle = LoadLibrary(dllPath); - if (_dllHandle == IntPtr.Zero) throw new RGBDeviceException($"Logitech LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); + if (!NativeLibrary.TryLoad(dllPath, out _handle)) +#if NET6_0 + throw new RGBDeviceException($"Logitech LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}"); +#else + throw new RGBDeviceException($"Logitech LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); +#endif - _logiLedInitPointer = (LogiLedInitPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedInit"), typeof(LogiLedInitPointer)); - _logiLedShutdownPointer = (LogiLedShutdownPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedShutdown"), typeof(LogiLedShutdownPointer)); - _logiLedSetTargetDevicePointer = (LogiLedSetTargetDevicePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedSetTargetDevice"), typeof(LogiLedSetTargetDevicePointer)); - _logiLedGetSdkVersionPointer = (LogiLedGetSdkVersionPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedGetSdkVersion"), typeof(LogiLedGetSdkVersionPointer)); - _lgiLedSaveCurrentLightingPointer = (LogiLedSaveCurrentLightingPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedSaveCurrentLighting"), typeof(LogiLedSaveCurrentLightingPointer)); - _logiLedRestoreLightingPointer = (LogiLedRestoreLightingPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedRestoreLighting"), typeof(LogiLedRestoreLightingPointer)); - _logiLedSetLightingPointer = (LogiLedSetLightingPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedSetLighting"), typeof(LogiLedSetLightingPointer)); - _logiLedSetLightingForKeyWithKeyNamePointer = (LogiLedSetLightingForKeyWithKeyNamePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedSetLightingForKeyWithKeyName"), typeof(LogiLedSetLightingForKeyWithKeyNamePointer)); - _logiLedSetLightingFromBitmapPointer = (LogiLedSetLightingFromBitmapPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedSetLightingFromBitmap"), typeof(LogiLedSetLightingFromBitmapPointer)); - _logiLedSetLightingForTargetZonePointer = (LogiLedSetLightingForTargetZonePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "LogiLedSetLightingForTargetZone"), typeof(LogiLedSetLightingForTargetZonePointer)); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedInit", out _logiLedInitPointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedInit'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedShutdown", out _logiLedShutdownPointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedShutdown'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedSetTargetDevice", out _logiLedSetTargetDevicePointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedSetTargetDevice'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedGetSdkVersion", out _logiLedGetSdkVersionPointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedGetSdkVersion'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedSaveCurrentLighting", out _lgiLedSaveCurrentLightingPointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedSaveCurrentLighting'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedRestoreLighting", out _logiLedRestoreLightingPointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedRestoreLighting'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedSetLighting", out _logiLedSetLightingPointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedSetLighting'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedSetLightingForKeyWithKeyName", out _logiLedSetLightingForKeyWithKeyNamePointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedSetLightingForKeyWithKeyName'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedSetLightingFromBitmap", out _logiLedSetLightingFromBitmapPointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedSetLightingFromBitmap'"); + if (!NativeLibrary.TryGetExport(_handle, "LogiLedSetLightingForTargetZone", out _logiLedSetLightingForTargetZonePointer)) throw new RGBDeviceException("Failed to load Logitech function 'LogiLedSetLightingForTargetZone'"); + } + + private static IEnumerable GetPossibleLibraryPaths() + { + IEnumerable possibleLibraryPaths; + + if (OperatingSystem.IsWindows()) + possibleLibraryPaths = Environment.Is64BitProcess ? LogitechDeviceProvider.PossibleX64NativePaths : LogitechDeviceProvider.PossibleX86NativePaths; + else + possibleLibraryPaths = Enumerable.Empty(); + + return possibleLibraryPaths.Select(Environment.ExpandEnvironmentVariables); } internal static void UnloadLogitechGSDK() { - if (_dllHandle == IntPtr.Zero) return; + if (_handle == IntPtr.Zero) return; - LogiLedShutdown(); + _logiLedInitPointer = IntPtr.Zero; + _logiLedShutdownPointer = IntPtr.Zero; + _logiLedSetTargetDevicePointer = IntPtr.Zero; + _logiLedGetSdkVersionPointer = IntPtr.Zero; + _lgiLedSaveCurrentLightingPointer = IntPtr.Zero; + _logiLedRestoreLightingPointer = IntPtr.Zero; + _logiLedSetLightingPointer = IntPtr.Zero; + _logiLedSetLightingForKeyWithKeyNamePointer = IntPtr.Zero; + _logiLedSetLightingFromBitmapPointer = IntPtr.Zero; + _logiLedSetLightingForTargetZonePointer = IntPtr.Zero; - // ReSharper disable once EmptyEmbeddedStatement - DarthAffe 20.02.2016: We might need to reduce the internal reference counter more than once to set the library free - while (FreeLibrary(_dllHandle)) ; - _dllHandle = IntPtr.Zero; + NativeLibrary.Free(_handle); + _handle = IntPtr.Zero; } - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern IntPtr LoadLibrary(string dllToLoad); - - [DllImport("kernel32.dll")] - private static extern bool FreeLibrary(IntPtr dllHandle); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] - private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name); - #endregion #region SDK-METHODS #region Pointers - private static LogiLedInitPointer? _logiLedInitPointer; - private static LogiLedShutdownPointer? _logiLedShutdownPointer; - private static LogiLedSetTargetDevicePointer? _logiLedSetTargetDevicePointer; - private static LogiLedGetSdkVersionPointer? _logiLedGetSdkVersionPointer; - private static LogiLedSaveCurrentLightingPointer? _lgiLedSaveCurrentLightingPointer; - private static LogiLedRestoreLightingPointer? _logiLedRestoreLightingPointer; - private static LogiLedSetLightingPointer? _logiLedSetLightingPointer; - private static LogiLedSetLightingForKeyWithKeyNamePointer? _logiLedSetLightingForKeyWithKeyNamePointer; - private static LogiLedSetLightingFromBitmapPointer? _logiLedSetLightingFromBitmapPointer; - private static LogiLedSetLightingForTargetZonePointer? _logiLedSetLightingForTargetZonePointer; + private static IntPtr _logiLedInitPointer; + private static IntPtr _logiLedShutdownPointer; + private static IntPtr _logiLedSetTargetDevicePointer; + private static IntPtr _logiLedGetSdkVersionPointer; + private static IntPtr _lgiLedSaveCurrentLightingPointer; + private static IntPtr _logiLedRestoreLightingPointer; + private static IntPtr _logiLedSetLightingPointer; + private static IntPtr _logiLedSetLightingForKeyWithKeyNamePointer; + private static IntPtr _logiLedSetLightingFromBitmapPointer; + private static IntPtr _logiLedSetLightingForTargetZonePointer; #endregion - #region Delegates + internal static unsafe bool LogiLedInit() + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedInitPointer))(); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedInitPointer(); + internal static unsafe void LogiLedShutdown() + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedShutdownPointer))(); - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate void LogiLedShutdownPointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedSetTargetDevicePointer(int targetDevice); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedGetSdkVersionPointer(ref int majorNum, ref int minorNum, ref int buildNum); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedSaveCurrentLightingPointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedRestoreLightingPointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedSetLightingPointer(int redPercentage, int greenPercentage, int bluePercentage); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedSetLightingForKeyWithKeyNamePointer(int keyCode, int redPercentage, int greenPercentage, int bluePercentage); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedSetLightingFromBitmapPointer(byte[] bitmap); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate bool LogiLedSetLightingForTargetZonePointer(LogitechDeviceType deviceType, int zone, int redPercentage, int greenPercentage, int bluePercentage); - - #endregion - - // ReSharper disable EventExceptionNotDocumented - - internal static bool LogiLedInit() => (_logiLedInitPointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(); - - internal static void LogiLedShutdown() => (_logiLedShutdownPointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(); - - internal static bool LogiLedSetTargetDevice(LogitechDeviceCaps targetDevice) => (_logiLedSetTargetDevicePointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke((int)targetDevice); + internal static unsafe bool LogiLedSetTargetDevice(LogitechDeviceCaps targetDevice) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedSetTargetDevicePointer))((int)targetDevice); internal static string LogiLedGetSdkVersion() { @@ -145,25 +125,32 @@ internal class _LogitechGSDK return $"{major}.{minor}.{build}"; } - internal static bool LogiLedGetSdkVersion(ref int majorNum, ref int minorNum, ref int buildNum) => - (_logiLedGetSdkVersionPointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(ref majorNum, ref minorNum, ref buildNum); + internal static unsafe bool LogiLedGetSdkVersion(ref int majorNum, ref int minorNum, ref int buildNum) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedGetSdkVersionPointer))(ref majorNum, ref minorNum, ref buildNum); - internal static bool LogiLedSaveCurrentLighting() => (_lgiLedSaveCurrentLightingPointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(); + internal static unsafe bool LogiLedSaveCurrentLighting() + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_lgiLedSaveCurrentLightingPointer))(); - internal static bool LogiLedRestoreLighting() => (_logiLedRestoreLightingPointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(); + internal static unsafe bool LogiLedRestoreLighting() + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedRestoreLightingPointer))(); - internal static bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercentage) => - (_logiLedSetLightingPointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(redPercentage, greenPercentage, bluePercentage); + internal static unsafe bool LogiLedSetLighting(int redPercentage, int greenPercentage, int bluePercentage) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedSetLightingPointer))(redPercentage, greenPercentage, bluePercentage); - internal static bool LogiLedSetLightingForKeyWithKeyName(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) - => (_logiLedSetLightingForKeyWithKeyNamePointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(keyCode, redPercentage, greenPercentage, bluePercentage); + internal static unsafe bool LogiLedSetLightingForKeyWithKeyName(int keyCode, int redPercentage, int greenPercentage, int bluePercentage) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedSetLightingForKeyWithKeyNamePointer))(keyCode, redPercentage, greenPercentage, bluePercentage); - internal static bool LogiLedSetLightingFromBitmap(byte[] bitmap) => (_logiLedSetLightingFromBitmapPointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(bitmap); + internal static unsafe bool LogiLedSetLightingFromBitmap(byte[] bitmap) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedSetLightingFromBitmapPointer))(bitmap); - internal static bool LogiLedSetLightingForTargetZone(LogitechDeviceType deviceType, int zone, int redPercentage, int greenPercentage, int bluePercentage) - => (_logiLedSetLightingForTargetZonePointer ?? throw new RGBDeviceException("The Logitech-GSDK is not initialized.")).Invoke(deviceType, zone, redPercentage, greenPercentage, bluePercentage); + internal static unsafe bool LogiLedSetLightingForTargetZone(LogitechDeviceType deviceType, int zone, int redPercentage, int greenPercentage, int bluePercentage) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_logiLedSetLightingForTargetZonePointer))(deviceType, zone, redPercentage, greenPercentage, bluePercentage); - // ReSharper restore EventExceptionNotDocumented + private static IntPtr ThrowIfZero(IntPtr ptr) + { + if (ptr == IntPtr.Zero) throw new RGBDeviceException("The Logitech-SDK is not initialized."); + return ptr; + } #endregion } \ No newline at end of file diff --git a/RGB.NET.Devices.Logitech/RGB.NET.Devices.Logitech.csproj b/RGB.NET.Devices.Logitech/RGB.NET.Devices.Logitech.csproj index a71a607..a34aa70 100644 --- a/RGB.NET.Devices.Logitech/RGB.NET.Devices.Logitech.csproj +++ b/RGB.NET.Devices.Logitech/RGB.NET.Devices.Logitech.csproj @@ -36,6 +36,7 @@ True portable snupkg + true diff --git a/RGB.NET.Devices.Msi/Native/_MsiSDK.cs b/RGB.NET.Devices.Msi/Native/_MsiSDK.cs index 90303fb..c13ef81 100644 --- a/RGB.NET.Devices.Msi/Native/_MsiSDK.cs +++ b/RGB.NET.Devices.Msi/Native/_MsiSDK.cs @@ -16,7 +16,7 @@ internal static class _MsiSDK { #region Libary Management - private static IntPtr _dllHandle = IntPtr.Zero; + private static IntPtr _handle = IntPtr.Zero; /// /// Reloads the SDK. @@ -29,57 +29,76 @@ internal static class _MsiSDK private static void LoadMsiSDK() { - if (_dllHandle != IntPtr.Zero) return; + if (_handle != IntPtr.Zero) return; + + List possiblePathList = GetPossibleLibraryPaths().ToList(); - // HACK: Load library at runtime to support both, x86 and x64 with one managed dll - List possiblePathList = (Environment.Is64BitProcess ? MsiDeviceProvider.PossibleX64NativePaths : MsiDeviceProvider.PossibleX86NativePaths) - .Select(Environment.ExpandEnvironmentVariables) - .ToList(); string? dllPath = possiblePathList.FirstOrDefault(File.Exists); - if (dllPath == null) throw new RGBDeviceException($"Can't find the Msi-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); - + if (dllPath == null) throw new RGBDeviceException($"Can't find the CUE-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); + SetDllDirectory(Path.GetDirectoryName(Path.GetFullPath(dllPath))!); - _dllHandle = LoadLibrary(dllPath); - if (_dllHandle == IntPtr.Zero) throw new RGBDeviceException($"MSI LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); + if (!NativeLibrary.TryLoad(dllPath, out _handle)) +#if NET6_0 + throw new RGBDeviceException($"MSI LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}"); +#else + throw new RGBDeviceException($"MSI LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); +#endif - _initializePointer = (InitializePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_Initialize"), typeof(InitializePointer)); - _getDeviceInfoPointer = (GetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetDeviceInfo"), typeof(GetDeviceInfoPointer)); - _getLedInfoPointer = (GetLedInfoPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedInfo"), typeof(GetLedInfoPointer)); - _getLedColorPointer = (GetLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedColor"), typeof(GetLedColorPointer)); - _getLedStylePointer = (GetLedStylePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedStyle"), typeof(GetLedStylePointer)); - _getLedMaxBrightPointer = (GetLedMaxBrightPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedMaxBright"), typeof(GetLedMaxBrightPointer)); - _getLedBrightPointer = (GetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedBright"), typeof(GetLedBrightPointer)); - _getLedMaxSpeedPointer = (GetLedMaxSpeedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedMaxSpeed"), typeof(GetLedMaxSpeedPointer)); - _getLedSpeedPointer = (GetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetLedSpeed"), typeof(GetLedSpeedPointer)); - _setLedColorPointer = (SetLedColorPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedColor"), typeof(SetLedColorPointer)); - _setLedStylePointer = (SetLedStylePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedStyle"), typeof(SetLedStylePointer)); - _setLedBrightPointer = (SetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedBright"), typeof(SetLedBrightPointer)); - _setLedSpeedPointer = (SetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_SetLedSpeed"), typeof(SetLedSpeedPointer)); - _getErrorMessagePointer = (GetErrorMessagePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "MLAPI_GetErrorMessage"), typeof(GetErrorMessagePointer)); + _initializePointer = (InitializePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_Initialize"), typeof(InitializePointer)); + _getDeviceInfoPointer = (GetDeviceInfoPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetDeviceInfo"), typeof(GetDeviceInfoPointer)); + _getLedInfoPointer = (GetLedInfoPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedInfo"), typeof(GetLedInfoPointer)); + _getLedColorPointer = (GetLedColorPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedColor"), typeof(GetLedColorPointer)); + _getLedStylePointer = (GetLedStylePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedStyle"), typeof(GetLedStylePointer)); + _getLedMaxBrightPointer = (GetLedMaxBrightPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedMaxBright"), typeof(GetLedMaxBrightPointer)); + _getLedBrightPointer = (GetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedBright"), typeof(GetLedBrightPointer)); + _getLedMaxSpeedPointer = (GetLedMaxSpeedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedMaxSpeed"), typeof(GetLedMaxSpeedPointer)); + _getLedSpeedPointer = (GetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetLedSpeed"), typeof(GetLedSpeedPointer)); + _setLedColorPointer = (SetLedColorPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedColor"), typeof(SetLedColorPointer)); + _setLedStylePointer = (SetLedStylePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedStyle"), typeof(SetLedStylePointer)); + _setLedBrightPointer = (SetLedBrightPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedBright"), typeof(SetLedBrightPointer)); + _setLedSpeedPointer = (SetLedSpeedPointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_SetLedSpeed"), typeof(SetLedSpeedPointer)); + _getErrorMessagePointer = (GetErrorMessagePointer)Marshal.GetDelegateForFunctionPointer(NativeLibrary.GetExport(_handle, "MLAPI_GetErrorMessage"), typeof(GetErrorMessagePointer)); + } + + private static IEnumerable GetPossibleLibraryPaths() + { + IEnumerable possibleLibraryPaths; + + if (OperatingSystem.IsWindows()) + possibleLibraryPaths = Environment.Is64BitProcess ? MsiDeviceProvider.PossibleX64NativePaths : MsiDeviceProvider.PossibleX86NativePaths; + else + possibleLibraryPaths = Enumerable.Empty(); + + return possibleLibraryPaths.Select(Environment.ExpandEnvironmentVariables); } internal static void UnloadMsiSDK() { - if (_dllHandle == IntPtr.Zero) return; + if (_handle == IntPtr.Zero) return; - // ReSharper disable once EmptyEmbeddedStatement - DarthAffe 07.10.2017: We might need to reduce the internal reference counter more than once to set the library free - while (FreeLibrary(_dllHandle)) ; - _dllHandle = IntPtr.Zero; + _initializePointer = null; + _getDeviceInfoPointer = null; + _getLedColorPointer = null; + _getLedColorPointer = null; + _getLedStylePointer = null; + _getLedMaxBrightPointer = null; + _getLedBrightPointer = null; + _getLedMaxSpeedPointer = null; + _getLedSpeedPointer = null; + _setLedColorPointer = null; + _setLedStylePointer = null; + _setLedBrightPointer = null; + _setLedSpeedPointer = null; + _getErrorMessagePointer = null; + + NativeLibrary.Free(_handle); + _handle = IntPtr.Zero; } [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] private static extern bool SetDllDirectory(string lpPathName); - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern IntPtr LoadLibrary(string dllToLoad); - - [DllImport("kernel32.dll")] - private static extern bool FreeLibrary(IntPtr dllHandle); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] - private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name); - #endregion #region SDK-METHODS diff --git a/RGB.NET.Devices.Razer/Native/_RazerSDK.cs b/RGB.NET.Devices.Razer/Native/_RazerSDK.cs index cd2ad8e..a94143d 100644 --- a/RGB.NET.Devices.Razer/Native/_RazerSDK.cs +++ b/RGB.NET.Devices.Razer/Native/_RazerSDK.cs @@ -16,7 +16,7 @@ internal static class _RazerSDK { #region Libary Management - private static IntPtr _dllHandle = IntPtr.Zero; + private static IntPtr _handle = IntPtr.Zero; /// /// Reloads the SDK. @@ -29,132 +29,108 @@ internal static class _RazerSDK private static void LoadRazerSDK() { - if (_dllHandle != IntPtr.Zero) return; + if (_handle != IntPtr.Zero) return; + + List possiblePathList = GetPossibleLibraryPaths().ToList(); - // HACK: Load library at runtime to support both, x86 and x64 with one managed dll - List possiblePathList = (Environment.Is64BitProcess ? RazerDeviceProvider.PossibleX64NativePaths : RazerDeviceProvider.PossibleX86NativePaths) - .Select(Environment.ExpandEnvironmentVariables) - .ToList(); string? dllPath = possiblePathList.FirstOrDefault(File.Exists); if (dllPath == null) throw new RGBDeviceException($"Can't find the Razer-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); - _dllHandle = LoadLibrary(dllPath); - if (_dllHandle == IntPtr.Zero) throw new RGBDeviceException($"Razer LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); + if (!NativeLibrary.TryLoad(dllPath, out _handle)) +#if NET6_0 + throw new RGBDeviceException($"Razer LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}"); +#else + throw new RGBDeviceException($"Razer LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); +#endif - _initPointer = (InitPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "Init"), typeof(InitPointer)); - _unInitPointer = (UnInitPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "UnInit"), typeof(UnInitPointer)); - _queryDevicePointer = (QueryDevicePointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "QueryDevice"), typeof(QueryDevicePointer)); - _createEffectPointer = (CreateEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateEffect"), typeof(CreateEffectPointer)); - _createHeadsetEffectPointer = (CreateHeadsetEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateHeadsetEffect"), typeof(CreateHeadsetEffectPointer)); - _createChromaLinkEffectPointer = (CreateChromaLinkEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateChromaLinkEffect"), typeof(CreateChromaLinkEffectPointer)); - _createKeyboardEffectPointer = (CreateKeyboardEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateKeyboardEffect"), typeof(CreateKeyboardEffectPointer)); - _createKeypadEffectPointer = (CreateKeypadEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateKeypadEffect"), typeof(CreateKeypadEffectPointer)); - _createMouseEffectPointer = (CreateMouseEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateMouseEffect"), typeof(CreateMouseEffectPointer)); - _createMousepadEffectPointer = (CreateMousepadEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "CreateMousepadEffect"), typeof(CreateMousepadEffectPointer)); - _setEffectPointer = (SetEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "SetEffect"), typeof(SetEffectPointer)); - _deleteEffectPointer = (DeleteEffectPointer)Marshal.GetDelegateForFunctionPointer(GetProcAddress(_dllHandle, "DeleteEffect"), typeof(DeleteEffectPointer)); + if (!NativeLibrary.TryGetExport(_handle, "Init", out _initPointer)) throw new RGBDeviceException("Failed to load Razer function 'Init'"); + if (!NativeLibrary.TryGetExport(_handle, "UnInit", out _unInitPointer)) throw new RGBDeviceException("Failed to load Razer function 'UnInit'"); + if (!NativeLibrary.TryGetExport(_handle, "QueryDevice", out _queryDevicePointer)) throw new RGBDeviceException("Failed to load Razer function 'QueryDevice'"); + if (!NativeLibrary.TryGetExport(_handle, "CreateEffect", out _createEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'CreateEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "CreateHeadsetEffect", out _createHeadsetEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'CreateHeadsetEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "CreateChromaLinkEffect", out _createChromaLinkEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'CreateChromaLinkEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "CreateKeyboardEffect", out _createKeyboardEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'CreateKeyboardEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "CreateKeypadEffect", out _createKeypadEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'CreateKeypadEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "CreateMouseEffect", out _createMouseEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'CreateMouseEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "CreateMousepadEffect", out _createMousepadEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'CreateMousepadEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "SetEffect", out _setEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'SetEffect'"); + if (!NativeLibrary.TryGetExport(_handle, "DeleteEffect", out _deleteEffectPointer)) throw new RGBDeviceException("Failed to load Razer function 'DeleteEffect'"); + } + + private static IEnumerable GetPossibleLibraryPaths() + { + IEnumerable possibleLibraryPaths; + + if (OperatingSystem.IsWindows()) + possibleLibraryPaths = Environment.Is64BitProcess ? RazerDeviceProvider.PossibleX64NativePaths : RazerDeviceProvider.PossibleX86NativePaths; + else + possibleLibraryPaths = Enumerable.Empty(); + + return possibleLibraryPaths.Select(Environment.ExpandEnvironmentVariables); } internal static void UnloadRazerSDK() { - if (_dllHandle == IntPtr.Zero) return; + if (_handle == IntPtr.Zero) return; - // ReSharper disable once EmptyEmbeddedStatement - DarthAffe 09.11.2017: We might need to reduce the internal reference counter more than once to set the library free - while (FreeLibrary(_dllHandle)) ; - _dllHandle = IntPtr.Zero; + _initPointer = IntPtr.Zero; + _unInitPointer = IntPtr.Zero; + _queryDevicePointer = IntPtr.Zero; + _createEffectPointer = IntPtr.Zero; + _createHeadsetEffectPointer = IntPtr.Zero; + _createChromaLinkEffectPointer = IntPtr.Zero; + _createKeyboardEffectPointer = IntPtr.Zero; + _createKeypadEffectPointer = IntPtr.Zero; + _createMouseEffectPointer = IntPtr.Zero; + _createMousepadEffectPointer = IntPtr.Zero; + _setEffectPointer = IntPtr.Zero; + _deleteEffectPointer = IntPtr.Zero; + + NativeLibrary.Free(_handle); + _handle = IntPtr.Zero; } - [DllImport("kernel32.dll", CharSet = CharSet.Unicode)] - private static extern IntPtr LoadLibrary(string dllToLoad); - - [DllImport("kernel32.dll")] - private static extern bool FreeLibrary(IntPtr dllHandle); - - [DllImport("kernel32.dll", CharSet = CharSet.Ansi)] - private static extern IntPtr GetProcAddress(IntPtr dllHandle, string name); - #endregion #region SDK-METHODS #region Pointers - private static InitPointer? _initPointer; - private static UnInitPointer? _unInitPointer; - private static QueryDevicePointer? _queryDevicePointer; - private static CreateEffectPointer? _createEffectPointer; - private static CreateHeadsetEffectPointer? _createHeadsetEffectPointer; - private static CreateChromaLinkEffectPointer? _createChromaLinkEffectPointer; - private static CreateKeyboardEffectPointer? _createKeyboardEffectPointer; - private static CreateKeypadEffectPointer? _createKeypadEffectPointer; - private static CreateMouseEffectPointer? _createMouseEffectPointer; - private static CreateMousepadEffectPointer? _createMousepadEffectPointer; - private static SetEffectPointer? _setEffectPointer; - private static DeleteEffectPointer? _deleteEffectPointer; + private static IntPtr _initPointer; + private static IntPtr _unInitPointer; + private static IntPtr _queryDevicePointer; + private static IntPtr _createEffectPointer; + private static IntPtr _createHeadsetEffectPointer; + private static IntPtr _createChromaLinkEffectPointer; + private static IntPtr _createKeyboardEffectPointer; + private static IntPtr _createKeypadEffectPointer; + private static IntPtr _createMouseEffectPointer; + private static IntPtr _createMousepadEffectPointer; + private static IntPtr _setEffectPointer; + private static IntPtr _deleteEffectPointer; #endregion - #region Delegates - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError InitPointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError UnInitPointer(); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError QueryDevicePointer(Guid deviceId, IntPtr deviceInfo); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError CreateEffectPointer(Guid deviceId, int effectType, IntPtr param, ref Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError CreateHeadsetEffectPointer(int effectType, IntPtr param, ref Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError CreateChromaLinkEffectPointer(int effectType, IntPtr param, ref Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError CreateKeyboardEffectPointer(int effectType, IntPtr param, ref Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError CreateKeypadEffectPointer(int effectType, IntPtr param, ref Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError CreateMouseEffectPointer(int effectType, IntPtr param, ref Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError CreateMousepadEffectPointer(int effectType, IntPtr param, ref Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError SetEffectPointer(Guid effectId); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - private delegate RazerError DeleteEffectPointer(Guid effectId); - - #endregion - - // ReSharper disable EventExceptionNotDocumented - /// /// Razer-SDK: Initialize Chroma SDK. /// - internal static RazerError Init() => (_initPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(); + internal static unsafe RazerError Init() => ((delegate* unmanaged[Cdecl])ThrowIfZero(_initPointer))(); /// /// Razer-SDK: UnInitialize Chroma SDK. /// - internal static RazerError UnInit() => (_unInitPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(); + internal static unsafe RazerError UnInit() + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_unInitPointer))(); /// /// Razer-SDK: Query for device information. /// - internal static RazerError QueryDevice(Guid deviceId, out _DeviceInfo deviceInfo) + internal static unsafe RazerError QueryDevice(Guid deviceId, out _DeviceInfo deviceInfo) { int structSize = Marshal.SizeOf(typeof(_DeviceInfo)); IntPtr deviceInfoPtr = Marshal.AllocHGlobal(structSize); - RazerError error = (_queryDevicePointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(deviceId, deviceInfoPtr); + RazerError error = ((delegate* unmanaged[Cdecl])ThrowIfZero(_queryDevicePointer))(deviceId, deviceInfoPtr); deviceInfo = (_DeviceInfo)Marshal.PtrToStructure(deviceInfoPtr, typeof(_DeviceInfo))!; Marshal.FreeHGlobal(deviceInfoPtr); @@ -162,25 +138,38 @@ internal static class _RazerSDK return error; } - internal static RazerError CreateEffect(Guid deviceId, int effectType, IntPtr param, ref Guid effectId) => (_createEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(deviceId, effectType, param, ref effectId); + internal static unsafe RazerError CreateEffect(Guid deviceId, int effectType, IntPtr param, ref Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_createEffectPointer))(deviceId, effectType, param, ref effectId); - internal static RazerError CreateHeadsetEffect(int effectType, IntPtr param, ref Guid effectId) => (_createHeadsetEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectType, param, ref effectId); + internal static unsafe RazerError CreateHeadsetEffect(int effectType, IntPtr param, ref Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_createHeadsetEffectPointer))(effectType, param, ref effectId); - internal static RazerError CreateChromaLinkEffect(int effectType, IntPtr param, ref Guid effectId) => (_createChromaLinkEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectType, param, ref effectId); + internal static unsafe RazerError CreateChromaLinkEffect(int effectType, IntPtr param, ref Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_createChromaLinkEffectPointer))(effectType, param, ref effectId); - internal static RazerError CreateKeyboardEffect(int effectType, IntPtr param, ref Guid effectId) => (_createKeyboardEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectType, param, ref effectId); + internal static unsafe RazerError CreateKeyboardEffect(int effectType, IntPtr param, ref Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_createKeyboardEffectPointer))(effectType, param, ref effectId); - internal static RazerError CreateKeypadEffect(int effectType, IntPtr param, ref Guid effectId) => (_createKeypadEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectType, param, ref effectId); + internal static unsafe RazerError CreateKeypadEffect(int effectType, IntPtr param, ref Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_createKeypadEffectPointer))(effectType, param, ref effectId); - internal static RazerError CreateMouseEffect(int effectType, IntPtr param, ref Guid effectId) => (_createMouseEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectType, param, ref effectId); + internal static unsafe RazerError CreateMouseEffect(int effectType, IntPtr param, ref Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_createMouseEffectPointer))(effectType, param, ref effectId); - internal static RazerError CreateMousepadEffect(int effectType, IntPtr param, ref Guid effectId) => (_createMousepadEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectType, param, ref effectId); + internal static unsafe RazerError CreateMousepadEffect(int effectType, IntPtr param, ref Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_createMousepadEffectPointer))(effectType, param, ref effectId); - internal static RazerError SetEffect(Guid effectId) => (_setEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectId); + internal static unsafe RazerError SetEffect(Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_setEffectPointer))(effectId); - internal static RazerError DeleteEffect(Guid effectId) => (_deleteEffectPointer ?? throw new RGBDeviceException("The Razer-SDK is not initialized.")).Invoke(effectId); + internal static unsafe RazerError DeleteEffect(Guid effectId) + => ((delegate* unmanaged[Cdecl])ThrowIfZero(_deleteEffectPointer))(effectId); - // ReSharper restore EventExceptionNotDocumented + private static IntPtr ThrowIfZero(IntPtr ptr) + { + if (ptr == IntPtr.Zero) throw new RGBDeviceException("The Razer-SDK is not initialized."); + return ptr; + } #endregion } \ No newline at end of file diff --git a/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj b/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj index 0896a9d..e152099 100644 --- a/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj +++ b/RGB.NET.Devices.Razer/RGB.NET.Devices.Razer.csproj @@ -36,6 +36,7 @@ True portable snupkg + true diff --git a/RGB.NET.Devices.Wooting/Native/_WootingSDK.cs b/RGB.NET.Devices.Wooting/Native/_WootingSDK.cs index 96a184a..7e894ef 100644 --- a/RGB.NET.Devices.Wooting/Native/_WootingSDK.cs +++ b/RGB.NET.Devices.Wooting/Native/_WootingSDK.cs @@ -36,7 +36,12 @@ internal static class _WootingSDK string? dllPath = possiblePathList.FirstOrDefault(File.Exists); if (dllPath == null) throw new RGBDeviceException($"Can't find the Wooting-SDK at one of the expected locations:\r\n '{string.Join("\r\n", possiblePathList.Select(Path.GetFullPath))}'"); - if (!NativeLibrary.TryLoad(dllPath, out _handle)) throw new RGBDeviceException($"Wooting LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); + if (!NativeLibrary.TryLoad(dllPath, out _handle)) +#if NET6_0 + throw new RGBDeviceException($"Wooting LoadLibrary failed with error code {Marshal.GetLastPInvokeError()}"); +#else + throw new RGBDeviceException($"Wooting LoadLibrary failed with error code {Marshal.GetLastWin32Error()}"); +#endif if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_device_info", out _getDeviceInfoPointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_device_info'"); if (!NativeLibrary.TryGetExport(_handle, "wooting_rgb_kbd_connected", out _keyboardConnectedPointer)) throw new RGBDeviceException("Failed to load wooting function 'wooting_rgb_kbd_connected'");