mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-23 07:45:37 +00:00
[Audio] Don't crash when Alc.GetString() returns null
Alc.GetString() could crash if the unmanaged code returned null due to any kind of failure. This is now fixed and better documented. Additionally, the array overload for Alc.GetString() will now correctly forward the ‘device’ parameter to unmanaged code.
This commit is contained in:
parent
19eb72b3a9
commit
7afe48c979
|
@ -9,6 +9,7 @@
|
|||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
|
@ -262,7 +263,13 @@ namespace OpenTK.Audio.OpenAL
|
|||
/// <returns>A string containing the name of the Device.</returns>
|
||||
public static string GetString(IntPtr device, AlcGetString param)
|
||||
{
|
||||
return Marshal.PtrToStringAnsi(GetStringPrivate(device, param));
|
||||
IntPtr pstr = GetStringPrivate(device, param);
|
||||
string str = String.Empty;
|
||||
if (pstr != IntPtr.Zero)
|
||||
{
|
||||
str = Marshal.PtrToStringAnsi(pstr);
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
/// <summary>This function returns a List of strings related to the context.</summary>
|
||||
|
@ -277,26 +284,54 @@ namespace OpenTK.Audio.OpenAL
|
|||
public static IList<string> GetString(IntPtr device, AlcGetStringList param)
|
||||
{
|
||||
List<string> result = new List<string>();
|
||||
IntPtr t = GetStringPrivate(IntPtr.Zero, (AlcGetString)param);
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
byte b;
|
||||
int offset = 0;
|
||||
do
|
||||
{
|
||||
b = Marshal.ReadByte(t, offset++);
|
||||
if (b != 0)
|
||||
sb.Append((char)b);
|
||||
if (b == 0)
|
||||
{
|
||||
result.Add(sb.ToString());
|
||||
if (Marshal.ReadByte(t, offset) == 0) // offset already properly increased through ++
|
||||
break; // 2x null
|
||||
else
|
||||
sb.Remove(0, sb.Length); // 1x null
|
||||
}
|
||||
} while (true);
|
||||
|
||||
return (IList<string>)result;
|
||||
// We cannot use Marshal.PtrToStringAnsi(),
|
||||
// because alcGetString is defined to return either a nul-terminated string,
|
||||
// or an array of nul-terminated strings terminated by an extra nul.
|
||||
// Marshal.PtrToStringAnsi() will fail in the latter case (it will only
|
||||
// return the very first string in the array.)
|
||||
// We'll have to marshal this ourselves.
|
||||
IntPtr t = GetStringPrivate(device, (AlcGetString)param);
|
||||
if (t != IntPtr.Zero)
|
||||
{
|
||||
System.Text.StringBuilder sb = new System.Text.StringBuilder();
|
||||
byte b;
|
||||
int offset = 0;
|
||||
do
|
||||
{
|
||||
b = Marshal.ReadByte(t, offset++);
|
||||
if (b != 0)
|
||||
{
|
||||
sb.Append((char)b);
|
||||
}
|
||||
else
|
||||
{
|
||||
// One string from the array is complete
|
||||
result.Add(sb.ToString());
|
||||
|
||||
// Check whether the array has finished
|
||||
// Note: offset already been increased through offset++ above
|
||||
if (Marshal.ReadByte(t, offset) == 0)
|
||||
{
|
||||
// 2x consecutive nuls, we've read the whole array
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Another string is starting, clear the StringBuilder
|
||||
sb.Remove(0, sb.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
while (true);
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.Print("[Audio] Alc.GetString({0}, {1}) returned null.",
|
||||
device, param);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
[DllImport(Alc.Lib, EntryPoint = "alcGetIntegerv", ExactSpelling = true, CallingConvention = Alc.Style, CharSet = CharSet.Ansi), SuppressUnmanagedCodeSecurity()]
|
||||
|
|
Loading…
Reference in a new issue