DarthAffe / RGB.NET

The one-stop SDK for RGB-peripherals
http://lib.arge.be
GNU Lesser General Public License v2.1
402 stars 72 forks source link

AccessViolationException thrown for MSI #37

Closed broken closed 3 years ago

broken commented 5 years ago

I'm getting the error:

Exception thrown: 'System.AccessViolationException' in RGB.NET.Devices.Msi.dll
An unhandled exception of type 'System.AccessViolationException' occurred in RGB.NET.Devices.Msi.dll
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.

This occurs when trying to load the device. My code:

static void Main(string[] argv)
        {
            RGBSurface surface = RGBSurface.Instance;
            surface.Exception += args => Debug.Print(args.Exception.Message);
            surface.LoadDevices(MsiDeviceProvider.Instance, throwExceptions: true);
...
}

The exception is thrown in the MsiDeviceProvider at line 98:

if ((errorCode = _MsiSDK.GetDeviceInfo(out string[] deviceTypes, out int[] ledCounts)) != 0)

What's odd is that it should be successfully initialized by this point, and GetDevicesInfo throws an exception rather than returning an error code.

I've tried x86 & x64 builds, and running VS as administrator and not as admin.

I installed the RGB.NET.Resources.* using the "NuGet Package Manager" using RBG.NET as the package source. While I'm new to Visual Studio, I believe this was done properly as I see the dlls in the correct file locations.

My MSI hardware:

From other threads I realize you have no MSI hardware to test with, but still wanted to start an issue in hopes others have found a solution, or maybe a place for future me to write how I fixed it. :)

As a side note, the Corsair dll appears to load correctly, but it cannot find my RGB Vengeance RAM. I'm simply not having any luck..

akmadian commented 5 years ago

I've had similar issues with the ASUS device provider that I haven't been able to fix (even try catch doesn't work), my guess is that the manufacturer's SDK is broken somewhere. Not much we can do unless MSI/ ASUS fix their SDKs...

DarthAffe commented 5 years ago

Hey, that's somehow interesting. the fact that you're getting an exception is at least different to what we got until now. Just to verify that it's really something in the SDK (which is not too unlikely) could you run this test-application? http://uploads.wyrez.org/MsiSDKTest.zip While running it's expected to run, return two error-codes (please report back which one) and a led-count if it's able to get a device (but we never got that to work until now).

broken commented 5 years ago

My apologies, but I'm just now seeing the end of a house move and surgery recovery, so while I haven't gotten my pc back up and running yet, I should be able to run your test after a couple weeks.

deckertron9000 commented 5 years ago

@DarthAffe I just started playing around with this project today. I've noticed that I'm only able to get a non-zero pointer for the sdk dll if I run in x86. I downloaded your sdk test and ran that. Here's the output:

Starting ... Initialized! (ErrorCode: 0)

Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt. at System.StubHelpers.MngdNativeArrayMarshaler.ConvertContentsToManaged(IntPtr pMarshalState, Object& pManagedHome, IntPtr pNativeHome) at MsiSDKTest.Program.MLAPI_GetDeviceInfo(String[]& pDevType, Int32[]& pLedCount) at MsiSDKTest.Program.Main(String[] args)

deckertron9000 commented 5 years ago

Okay, more info from playing around with the marshaling.

[UnmanagedFunctionPointer(CallingConvention.Cdecl, CharSet = CharSet.Ansi)]
private delegate int GetDeviceInfoPointer([Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pDevType, 
[Out, MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out int[] pLedCount);

Marshaling as safe arrays is required to get this to work as you would expect.

DarthAffe commented 5 years ago

Yeah, i just changed that too and uploaded a new test-version^^ does it work like this? I thought about that

[DllImport("MysticLight_SDK.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern int MLAPI_GetDeviceInfo([MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] out string[] pDevType,
                                             [MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_INT)] out int[] pLedCount);
deckertron9000 commented 5 years ago

I can't get it to work with the SafeArraySubType = VarEnum.VT_INT on the pLedCount. I've only been able to get that working with VT_BSTR. But then you have a mismatched array (pLedCount thinks it's an array of int but it's actually an array of string). To work around that I modified GetDeviceInfo to parse the int:

internal static int GetDeviceInfo(out string[] pDevType, out int[] pLedCount)
{    
    int result = _getDeviceInfoPointer(out pDevType, out string[] pLedCount1);
    pLedCount = new int[pLedCount1.Length];

    for (int i = 0; i < pLedCount1.Length; i++)
    pLedCount[i] = int.Parse(pLedCount1[i]);

    return result;
}
DarthAffe commented 5 years ago

Hmm ok that's weird - but as long as it works ... Are you getting a reasonable result if you call it?

deckertron9000 commented 5 years ago

Yeah, the only compatible MSI device in my current system is the MPG Z390 Gaming Pro Carbon. The pDevType on that is "MSI_MB" and the ledCount is 9. Calling GetLedInfo with each of the various indexes 0-8 gives the various RGB locations on the motherboard currently as well as motherboard headers that can be connected to various RGB products.

DarthAffe commented 5 years ago

Ok, sounds good. With that knowledge it should be possible to get this further. Are you working on it? If not I'll continue implementing it based on the documentation.

deckertron9000 commented 5 years ago

I can submit a PR with my updates to _MsiSDK class if that would help.

DarthAffe commented 5 years ago

Hey, finally got some time to continue on what you've done. Since the documentation doesn't describe the parameters at all I'd like to make sure I got it correct before integrating it in RGB.NET. Could you compile/run http://uploads.wyrez.org/MsiSDKTest.zip and see if it correctly sets LED-colors and copy me the output? That should be all of the SDK-methods we need (at least I hope so^^)

deckertron9000 commented 5 years ago

I'll give it a shot hopefully today sometime and report back!

deckertron9000 commented 5 years ago

Starting ... Initialized! (ErrorCode: 0) Got devices: (ErrorCode: 0) MSI_MB - LedCount: 9 Set ColorsDevice: MSI_MBLED 0: IO Cover - Off, Rainbow, Meteor, Stack, Breathing, Flashing, Double Flashing, Steady, Lightning, CPU Temperature, Random, POP, RAP, JAZZ, Play, Movie, Planetary, Double Meteor, Energy, Blink, Clock, Color Pulse, Color Shift, Color Wave, Marquee, Rainbow Wave, Visor, Rainbow Flashing, Rainbow Double Flashing, Default Get ColorsDevice: MSI_MBLED 0: [255, 0, 0]

Note that I had to build the application and then run as administrator from command line. Debugging straight from VS 2019 seems to not run the program as admin. Also, pretty sure x64 is not supported based on the readme here.

deckertron9000 commented 5 years ago

Another thing worth noting is that you'll need to set the led style to one that supports direct color setting otherwise you'll get an "unsupported" error. "Steady" is the only one I've tried so far that works but there may be others.

Also in the inner loop you need to check j < ledCounts[i] to correctly loop through all addressable leds.