Added the hard drive firmware version to the report. This could be important if the SMART attribute layout changes with firmware versions on some drives.
     1.1 --- a/Hardware/HDD/AbstractHarddrive.cs	Sat Dec 31 17:31:04 2011 +0000
     1.2 +++ b/Hardware/HDD/AbstractHarddrive.cs	Sun Jan 01 10:14:42 2012 +0000
     1.3 @@ -16,7 +16,7 @@
     1.4  
     1.5    The Initial Developer of the Original Code is 
     1.6    Michael Möller <m.moeller@gmx.ch>.
     1.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2011
     1.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2012
     1.9    the Initial Developer. All Rights Reserved.
    1.10  
    1.11    Contributor(s): 
    1.12 @@ -57,6 +57,7 @@
    1.13        typeof(GenericHarddisk)
    1.14      };
    1.15  
    1.16 +    private string firmwareRevision;
    1.17      private readonly ISmart smart;
    1.18  
    1.19      private readonly IntPtr handle;
    1.20 @@ -66,11 +67,13 @@
    1.21      private IList<SmartAttribute> smartAttributes;
    1.22      private IDictionary<SmartAttribute, Sensor> sensors;
    1.23  
    1.24 -    protected AbstractHarddrive(ISmart smart, string name, int index, 
    1.25 +    protected AbstractHarddrive(ISmart smart, string name, 
    1.26 +      string firmwareRevision, int index, 
    1.27        IEnumerable<SmartAttribute> smartAttributes, ISettings settings) 
    1.28        : base(name, new Identifier("hdd",
    1.29          index.ToString(CultureInfo.InvariantCulture)), settings)
    1.30      {
    1.31 +      this.firmwareRevision = firmwareRevision;
    1.32        this.smart = smart;
    1.33        handle = smart.OpenDrive(index);
    1.34  
    1.35 @@ -92,7 +95,10 @@
    1.36        if (deviceHandle == smart.InvalidHandle) 
    1.37          return null;
    1.38  
    1.39 -      string name = smart.ReadName(deviceHandle, driveIndex);
    1.40 +      string name;
    1.41 +      string firmwareRevision;
    1.42 +      bool nameValid = smart.ReadNameAndFirmwareRevision(deviceHandle, 
    1.43 +        driveIndex, out name, out firmwareRevision);
    1.44        bool smartEnabled = smart.EnableSmart(deviceHandle, driveIndex);
    1.45  
    1.46        DriveAttributeValue[] values = {};
    1.47 @@ -101,7 +107,7 @@
    1.48  
    1.49        smart.CloseHandle(deviceHandle);
    1.50  
    1.51 -      if (string.IsNullOrEmpty(name)) 
    1.52 +      if (!nameValid || string.IsNullOrEmpty(name)) 
    1.53          return null;
    1.54  
    1.55        foreach (Type type in hddTypes) {
    1.56 @@ -136,8 +142,8 @@
    1.57          // check if there is a matching name prefix for this type
    1.58          foreach (NamePrefixAttribute prefix in namePrefixes) {
    1.59            if (name.StartsWith(prefix.Prefix, StringComparison.InvariantCulture)) 
    1.60 -            return Activator.CreateInstance(type, smart, name, driveIndex, 
    1.61 -              settings) as AbstractHarddrive;
    1.62 +            return Activator.CreateInstance(type, smart, name, firmwareRevision,
    1.63 +              driveIndex, settings) as AbstractHarddrive;
    1.64          }
    1.65        }
    1.66  
    1.67 @@ -222,6 +228,7 @@
    1.68          r.AppendLine(this.GetType().Name);
    1.69          r.AppendLine();
    1.70          r.AppendLine("Drive name: " + name);
    1.71 +        r.AppendLine("Firmware version: " + firmwareRevision);
    1.72          r.AppendLine();
    1.73          r.AppendFormat(CultureInfo.InvariantCulture, 
    1.74            " {0}{1}{2}{3}{4}{5}{6}{7}",
     2.1 --- a/Hardware/HDD/DebugSmart.cs	Sat Dec 31 17:31:04 2011 +0000
     2.2 +++ b/Hardware/HDD/DebugSmart.cs	Sun Jan 01 10:14:42 2012 +0000
     2.3 @@ -16,7 +16,7 @@
     2.4  
     2.5    The Initial Developer of the Original Code is 
     2.6    Michael Möller <m.moeller@gmx.ch>.
     2.7 -  Portions created by the Initial Developer are Copyright (C) 2011
     2.8 +  Portions created by the Initial Developer are Copyright (C) 2011-2012
     2.9    the Initial Developer. All Rights Reserved.
    2.10  
    2.11    Contributor(s):
    2.12 @@ -219,11 +219,14 @@
    2.13        return drives[driveNumber].DriveThresholdValues;
    2.14      }
    2.15  
    2.16 -    public string ReadName(IntPtr handle, int driveNumber) {
    2.17 +    public bool ReadNameAndFirmwareRevision(IntPtr handle, int driveNumber, 
    2.18 +      out string name, out string firmwareRevision) {
    2.19        if (handle != (IntPtr)driveNumber)
    2.20          throw new ArgumentOutOfRangeException();
    2.21  
    2.22 -      return drives[driveNumber].Name;
    2.23 +      name = drives[driveNumber].Name;
    2.24 +      firmwareRevision = "";
    2.25 +      return true;
    2.26      }
    2.27  
    2.28      public void CloseHandle(IntPtr handle) { }
     3.1 --- a/Hardware/HDD/HDDGeneric.cs	Sat Dec 31 17:31:04 2011 +0000
     3.2 +++ b/Hardware/HDD/HDDGeneric.cs	Sun Jan 01 10:14:42 2012 +0000
     3.3 @@ -16,7 +16,7 @@
     3.4  
     3.5    The Initial Developer of the Original Code is 
     3.6    Roland Reinl <roland-reinl@gmx.de>.
     3.7 -  Portions created by the Initial Developer are Copyright (C) 2011
     3.8 +  Portions created by the Initial Developer are Copyright (C) 2011-2012
     3.9    the Initial Developer. All Rights Reserved.
    3.10  
    3.11    Contributor(s):
    3.12 @@ -116,8 +116,8 @@
    3.13          null, SensorType.Temperature, 0)
    3.14      };
    3.15  
    3.16 -    public GenericHarddisk(ISmart smart, string name, int index, 
    3.17 -      ISettings settings) 
    3.18 -      : base(smart, name, index, smartAttributes, settings) { }
    3.19 +    public GenericHarddisk(ISmart smart, string name, string firmwareRevision, 
    3.20 +      int index, ISettings settings)
    3.21 +      : base(smart, name, firmwareRevision, index, smartAttributes, settings) {}
    3.22    }
    3.23  }
     4.1 --- a/Hardware/HDD/ISmart.cs	Sat Dec 31 17:31:04 2011 +0000
     4.2 +++ b/Hardware/HDD/ISmart.cs	Sun Jan 01 10:14:42 2012 +0000
     4.3 @@ -16,7 +16,7 @@
     4.4  
     4.5    The Initial Developer of the Original Code is 
     4.6    Michael Möller <m.moeller@gmx.ch>.
     4.7 -  Portions created by the Initial Developer are Copyright (C) 2011
     4.8 +  Portions created by the Initial Developer are Copyright (C) 2011-2012
     4.9    the Initial Developer. All Rights Reserved.
    4.10  
    4.11    Contributor(s):
    4.12 @@ -51,7 +51,8 @@
    4.13  
    4.14      DriveThresholdValue[] ReadSmartThresholds(IntPtr handle, int driveNumber);
    4.15  
    4.16 -    string ReadName(IntPtr handle, int driveNumber);
    4.17 +    bool ReadNameAndFirmwareRevision(IntPtr handle, int driveNumber,
    4.18 +      out string name, out string firmwareRevision); 
    4.19  
    4.20      void CloseHandle(IntPtr handle);
    4.21  
     5.1 --- a/Hardware/HDD/SSDIndilinx.cs	Sat Dec 31 17:31:04 2011 +0000
     5.2 +++ b/Hardware/HDD/SSDIndilinx.cs	Sun Jan 01 10:14:42 2012 +0000
     5.3 @@ -16,7 +16,7 @@
     5.4  
     5.5    The Initial Developer of the Original Code is 
     5.6    Roland Reinl <roland-reinl@gmx.de>.
     5.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2011
     5.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2012
     5.9    the Initial Developer. All Rights Reserved.
    5.10  
    5.11    Contributor(s):
    5.12 @@ -68,8 +68,9 @@
    5.13       new SmartAttribute(0xD4, SmartAttributeNames.SataErrorCountHandshake),
    5.14      };
    5.15  
    5.16 -    public SSDIndilinx(ISmart smart, string name, int index, ISettings settings)
    5.17 -      : base(smart, name, index, smartAttributes, settings) { }
    5.18 +    public SSDIndilinx(ISmart smart, string name, string firmwareRevision, 
    5.19 +      int index, ISettings settings)
    5.20 +      : base(smart, name, firmwareRevision, index, smartAttributes, settings) {}
    5.21    }
    5.22  }
    5.23  
     6.1 --- a/Hardware/HDD/SSDIntel.cs	Sat Dec 31 17:31:04 2011 +0000
     6.2 +++ b/Hardware/HDD/SSDIntel.cs	Sun Jan 01 10:14:42 2012 +0000
     6.3 @@ -16,7 +16,7 @@
     6.4  
     6.5    The Initial Developer of the Original Code is 
     6.6    Michael Möller <m.moeller@gmx.ch>.
     6.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2011
     6.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2012
     6.9    the Initial Developer. All Rights Reserved.
    6.10  
    6.11    Contributor(s):
    6.12 @@ -72,7 +72,8 @@
    6.13          SensorType.Data, 1),      
    6.14      };
    6.15  
    6.16 -    public SSDIntel(ISmart smart, string name, int index, ISettings settings)
    6.17 -      : base(smart, name, index, smartAttributes, settings) { }
    6.18 +    public SSDIntel(ISmart smart, string name, string firmwareRevision, 
    6.19 +      int index, ISettings settings)
    6.20 +      : base(smart, name, firmwareRevision, index, smartAttributes, settings) {}
    6.21    }
    6.22  }
     7.1 --- a/Hardware/HDD/SSDPlextor.cs	Sat Dec 31 17:31:04 2011 +0000
     7.2 +++ b/Hardware/HDD/SSDPlextor.cs	Sun Jan 01 10:14:42 2012 +0000
     7.3 @@ -16,7 +16,7 @@
     7.4  
     7.5    The Initial Developer of the Original Code is 
     7.6    Michael Möller <m.moeller@gmx.ch>.
     7.7 -  Portions created by the Initial Developer are Copyright (C) 2011
     7.8 +  Portions created by the Initial Developer are Copyright (C) 2011-2012
     7.9    the Initial Developer. All Rights Reserved.
    7.10  
    7.11    Contributor(s):
    7.12 @@ -47,7 +47,8 @@
    7.13        new SmartAttribute(0x0C, SmartAttributeNames.PowerCycleCount, RawToInt),
    7.14      };
    7.15  
    7.16 -    public SSDPlextor(ISmart smart, string name, int index, ISettings settings)
    7.17 -      : base(smart, name, index, smartAttributes, settings) { }
    7.18 +    public SSDPlextor(ISmart smart, string name, string firmwareRevision, 
    7.19 +      int index, ISettings settings)
    7.20 +      : base(smart, name, firmwareRevision, index, smartAttributes, settings) {}
    7.21    }
    7.22  }
     8.1 --- a/Hardware/HDD/SSDSandforce.cs	Sat Dec 31 17:31:04 2011 +0000
     8.2 +++ b/Hardware/HDD/SSDSandforce.cs	Sun Jan 01 10:14:42 2012 +0000
     8.3 @@ -16,7 +16,7 @@
     8.4  
     8.5    The Initial Developer of the Original Code is 
     8.6    Michael Möller <m.moeller@gmx.ch>.
     8.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2011
     8.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2012
     8.9    the Initial Developer. All Rights Reserved.
    8.10  
    8.11    Contributor(s):
    8.12 @@ -65,8 +65,9 @@
    8.13          SensorType.Data, 1)
    8.14      };
    8.15  
    8.16 -    public SSDSandforce(ISmart smart, string name, int index, 
    8.17 -      ISettings settings) 
    8.18 -      : base(smart, name, index, smartAttributes, settings) { }
    8.19 +    public SSDSandforce(ISmart smart, string name, string firmwareRevision, 
    8.20 +      int index, ISettings settings) 
    8.21 +      : base(smart, name, firmwareRevision,  index, smartAttributes, settings) 
    8.22 +    { }
    8.23    }
    8.24  }
     9.1 --- a/Hardware/HDD/WindowsSmart.cs	Sat Dec 31 17:31:04 2011 +0000
     9.2 +++ b/Hardware/HDD/WindowsSmart.cs	Sun Jan 01 10:14:42 2012 +0000
     9.3 @@ -16,7 +16,7 @@
     9.4  
     9.5    The Initial Developer of the Original Code is 
     9.6    Michael Möller <m.moeller@gmx.ch>.
     9.7 -  Portions created by the Initial Developer are Copyright (C) 2009-2011
     9.8 +  Portions created by the Initial Developer are Copyright (C) 2009-2012
     9.9    the Initial Developer. All Rights Reserved.
    9.10  
    9.11    Contributor(s): 
    9.12 @@ -327,9 +327,20 @@
    9.13          out bytesReturned, IntPtr.Zero); 
    9.14  
    9.15        return (isValid) ? result.Thresholds : new DriveThresholdValue[0];
    9.16 -    } 
    9.17 +    }
    9.18  
    9.19 -    public string ReadName(IntPtr handle, int driveNumber) {
    9.20 +    private string GetString(byte[] bytes) {   
    9.21 +      char[] chars = new char[bytes.Length];
    9.22 +      for (int i = 0; i < bytes.Length; i += 2) {
    9.23 +        chars[i] = (char)bytes[i + 1];
    9.24 +        chars[i + 1] = (char)bytes[i];
    9.25 +      }
    9.26 +      return new string(chars).Trim(new char[] { ' ', '\0' });
    9.27 +    }
    9.28 +
    9.29 +    public bool ReadNameAndFirmwareRevision(IntPtr handle, int driveNumber, 
    9.30 +      out string name, out string firmwareRevision) 
    9.31 +    {
    9.32        DriveCommandParameter parameter = new DriveCommandParameter();
    9.33        DriveIdentifyResult result;
    9.34        uint bytesReturned;
    9.35 @@ -342,19 +353,15 @@
    9.36          out result, Marshal.SizeOf(typeof(DriveIdentifyResult)), 
    9.37          out bytesReturned, IntPtr.Zero);
    9.38  
    9.39 -      if (!valid)
    9.40 -        return null;
    9.41 -      else {
    9.42 +      if (!valid) {
    9.43 +        name = null;
    9.44 +        firmwareRevision = null;
    9.45 +        return false;
    9.46 +      }
    9.47  
    9.48 -        byte[] bytes = result.Identify.ModelNumber;
    9.49 -        char[] chars = new char[bytes.Length];
    9.50 -        for (int i = 0; i < bytes.Length; i += 2) {
    9.51 -          chars[i] = (char)bytes[i + 1];
    9.52 -          chars[i + 1] = (char)bytes[i];
    9.53 -        }
    9.54 -
    9.55 -        return new string(chars).Trim(new char[] {' ', '\0'});
    9.56 -      }
    9.57 +      name = GetString(result.Identify.ModelNumber);
    9.58 +      firmwareRevision = GetString(result.Identify.FirmwareRevision);
    9.59 +      return true;
    9.60      }
    9.61  
    9.62      public void CloseHandle(IntPtr handle) {