Add workaround to correctly display device serials

Some devices on windows (especially, apparently, SATA devices
behind a bridge chip) report their serial number as a string
of hex bytes instead of ASCII.
This patch tries to detect that and transparently fix it.
This commit is contained in:
Michael D
2017-12-20 20:10:28 +01:00
parent 6184a82926
commit cfd0b2655f

View File

@@ -41,6 +41,19 @@ namespace DiscImageChef.Devices.Windows
{ {
static class ListDevices static class ListDevices
{ {
internal static string HexStringToString(string hex)
{
StringBuilder result = new StringBuilder();
const string hextable = "0123456789abcdef";
for (int i = 0; i < hex.Length / 2; i++)
{
result.Append((char)(16 * hextable.IndexOf(hex[2 * i]) + hextable.IndexOf(hex[2 * i + 1])));
}
return result.ToString();
}
internal static DeviceInfo[] GetList() internal static DeviceInfo[] GetList()
{ {
List<string> deviceIDs = new List<string>(); List<string> deviceIDs = new List<string>();
@@ -130,11 +143,20 @@ namespace DiscImageChef.Devices.Windows
info.Model = info.Model =
StringHandlers.CToString(descriptorB, Encoding.ASCII, start: (int)descriptor.ProductIdOffset); StringHandlers.CToString(descriptorB, Encoding.ASCII, start: (int)descriptor.ProductIdOffset);
// TODO: Get serial number of SCSI and USB devices, probably also FireWire (untested) // TODO: Get serial number of SCSI and USB devices, probably also FireWire (untested)
if(descriptor.SerialNumberOffset > 0) if (descriptor.SerialNumberOffset > 0)
{
info.Serial = info.Serial =
StringHandlers.CToString(descriptorB, Encoding.ASCII, StringHandlers.CToString(descriptorB, Encoding.ASCII,
start: (int)descriptor.SerialNumberOffset); start: (int)descriptor.SerialNumberOffset);
// fix any serial numbers that are returned as hex-strings
if (Array.TrueForAll(info.Serial.ToCharArray(), (char c) => "0123456789abcdef".IndexOf(c) >= 0)
&& (info.Serial.Length == 40))
{
info.Serial = HexStringToString(info.Serial).Trim();
}
}
if(string.IsNullOrEmpty(info.Vendor) || info.Vendor == "ATA") if(string.IsNullOrEmpty(info.Vendor) || info.Vendor == "ATA")
{ {
string[] pieces = info.Model.Split(' '); string[] pieces = info.Model.Split(' ');