MrTimcakes / Unity-DirectInput

Unity Native Plugin to expose DirectX DirectInput ForceFeedback
GNU Lesser General Public License v3.0
31 stars 11 forks source link

Error strings not passed through #11

Open Risto-Paasivirta opened 9 months ago

Risto-Paasivirta commented 9 months ago

Error codes from the DLL plugin does not pass through.

Unable to get error code string from System -> System.ExecutionEngineException: String conversion error: Illegal byte sequence encounted in the input. at (wrapper managed-to-native) System.Runtime.InteropServices.Marshal.PtrToStringAnsi(intptr)

MrTimcakes commented 9 months ago

Hey, Could you add a little more information about your setup? What device are you trying to use? It would be great if you could provide a snippet of the offending code too.

Risto-Paasivirta commented 9 months ago

Actually I think we managed to find out why. It's probably because you are using the string sRet = Marshal.PtrToStringAnsi(lpMsgBuf); In the GetSystemMessage(int errorCode)

Which works fine on English devices but break if there are special characters like in case of our machines which some of them were in Finnish localization.

Windows messages should always be treated as UTF encoded I believe (they have been moving from ANSI to UTF over time and I think most if not all is now UTF). This has been quite invisible for English users since ANSI==UTF when dealing with only English alphabet.

We are still testing and I will keep you informed on how it goes, I think you can test and break the system if you switch localization some European language with umlaut characters (we have ä and ö in Finnish).

We are running on Windows Home and Pro 64-bit, nothing special. My dev machine was doing fine (I have US-EN localization on this computer, but many of our target machines are Finnish).

Risto-Paasivirta commented 9 months ago

One more update:

So running as a test GetSystemMessage(2) will cause the problem (error code 1 does not contain special characters in Finnish so it works).

For the error code 2 The Finnish error would be "Määritettyä tiedostoa ei löydy." = "The system cannot find the file specified."

If using the Marshal.PtrToStringAnsi(lpMsgBuf) method it won't work because of the ä and ö characters.

I noticed that just changing it to Marshal.PtrToStringUTF8(lpMsgBuf) won't work either, because the Unity managed-to-native wrapper will try to internally call the Ansi method still so the problem persists.

However making a method to do the conversion is quite easy so I added a function

private static string PtrToStringUTF8(IntPtr ptr)
        {
            int len = 0;
            while (Marshal.ReadByte(ptr, len) != 0) ++len;
            if (len == 0) return "";
            byte[] array = new byte[len];
            Marshal.Copy(ptr, array, 0, len);
            return Encoding.UTF8.GetString(array);
        }

that I use to convert it and it works. Unity won't still show the ä and ö properly, but that is because of the font asset. At least the string gets through without issues using that.

I hope this helps.