Fixed Issue 387. The new implementation does not try to start a ring 0 driver that already exists, but could not be opened. It tries to delete the driver and install it new. The driver is now stored temporarily in the application folder. The driver is not correctly removed on system shutdown.
3 This Source Code Form is subject to the terms of the Mozilla Public
4 License, v. 2.0. If a copy of the MPL was not distributed with this
5 file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 Copyright (C) 2009-2012 Michael Möller <mmoeller@openhardwaremonitor.org>
8 Copyright (C) 2010 Paul Werelds
9 Copyright (C) 2011 Roland Reinl <roland-reinl@gmx.de>
14 using System.Collections.Generic;
15 using System.Globalization;
18 using OpenHardwareMonitor.Collections;
20 namespace OpenHardwareMonitor.Hardware.HDD {
21 internal abstract class AbstractHarddrive : Hardware {
23 private const int UPDATE_DIVIDER = 30; // update only every 30s
25 // array of all harddrive types, matching type is searched in this order
26 private static Type[] hddTypes = {
33 typeof(GenericHarddisk)
36 private string firmwareRevision;
37 private readonly ISmart smart;
39 private readonly IntPtr handle;
40 private readonly int index;
43 private IList<SmartAttribute> smartAttributes;
44 private IDictionary<SmartAttribute, Sensor> sensors;
46 private DriveInfo[] driveInfos;
47 private Sensor usageSensor;
49 protected AbstractHarddrive(ISmart smart, string name,
50 string firmwareRevision, int index,
51 IEnumerable<SmartAttribute> smartAttributes, ISettings settings)
52 : base(name, new Identifier("hdd",
53 index.ToString(CultureInfo.InvariantCulture)), settings)
55 this.firmwareRevision = firmwareRevision;
57 handle = smart.OpenDrive(index);
59 smart.EnableSmart(handle, index);
64 this.smartAttributes = new List<SmartAttribute>(smartAttributes);
66 string[] logicalDrives = smart.GetLogicalDrives(index);
67 List<DriveInfo> driveInfoList = new List<DriveInfo>(logicalDrives.Length);
68 foreach (string logicalDrive in logicalDrives) {
70 DriveInfo di = new DriveInfo(logicalDrive);
72 driveInfoList.Add(new DriveInfo(logicalDrive));
73 } catch (ArgumentException) { } catch (IOException) { }
75 driveInfos = driveInfoList.ToArray();
80 public static AbstractHarddrive CreateInstance(ISmart smart,
81 int driveIndex, ISettings settings)
83 IntPtr deviceHandle = smart.OpenDrive(driveIndex);
85 if (deviceHandle == smart.InvalidHandle)
89 string firmwareRevision;
90 bool nameValid = smart.ReadNameAndFirmwareRevision(deviceHandle,
91 driveIndex, out name, out firmwareRevision);
92 bool smartEnabled = smart.EnableSmart(deviceHandle, driveIndex);
94 DriveAttributeValue[] values = {};
96 values = smart.ReadSmartData(deviceHandle, driveIndex);
98 smart.CloseHandle(deviceHandle);
100 if (!nameValid || string.IsNullOrEmpty(name))
103 foreach (Type type in hddTypes) {
104 // get the array of name prefixes for the current type
105 NamePrefixAttribute[] namePrefixes = type.GetCustomAttributes(
106 typeof(NamePrefixAttribute), true) as NamePrefixAttribute[];
108 // get the array of the required SMART attributes for the current type
109 RequireSmartAttribute[] requiredAttributes = type.GetCustomAttributes(
110 typeof(RequireSmartAttribute), true) as RequireSmartAttribute[];
112 // check if all required attributes are present
113 bool allRequiredAttributesFound = true;
114 foreach (var requireAttribute in requiredAttributes) {
115 bool adttributeFound = false;
116 foreach (DriveAttributeValue value in values) {
117 if (value.Identifier == requireAttribute.AttributeId) {
118 adttributeFound = true;
122 if (!adttributeFound) {
123 allRequiredAttributesFound = false;
128 // if an attribute is missing, then try the next type
129 if (!allRequiredAttributesFound)
132 // check if there is a matching name prefix for this type
133 foreach (NamePrefixAttribute prefix in namePrefixes) {
134 if (name.StartsWith(prefix.Prefix, StringComparison.InvariantCulture))
135 return Activator.CreateInstance(type, smart, name, firmwareRevision,
136 driveIndex, settings) as AbstractHarddrive;
140 // no matching type has been found
144 private void CreateSensors() {
145 sensors = new Dictionary<SmartAttribute, Sensor>();
147 IList<Pair<SensorType, int>> sensorTypeAndChannels =
148 new List<Pair<SensorType, int>>();
150 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
152 foreach (SmartAttribute attribute in smartAttributes) {
153 if (!attribute.SensorType.HasValue)
157 foreach (DriveAttributeValue value in values) {
158 if (value.Identifier == attribute.Identifier) {
166 Pair<SensorType, int> pair = new Pair<SensorType, int>(
167 attribute.SensorType.Value, attribute.SensorChannel);
169 if (!sensorTypeAndChannels.Contains(pair)) {
170 Sensor sensor = new Sensor(attribute.Name,
171 attribute.SensorChannel, attribute.DefaultHiddenSensor,
172 attribute.SensorType.Value, this, attribute.ParameterDescriptions,
175 sensors.Add(attribute, sensor);
176 ActivateSensor(sensor);
177 sensorTypeAndChannels.Add(pair);
181 if (driveInfos.Length > 0) {
183 new Sensor("Used Space", 0, SensorType.Load, this, settings);
184 ActivateSensor(usageSensor);
188 public override HardwareType HardwareType {
189 get { return HardwareType.HDD; }
192 public virtual void UpdateAdditionalSensors(DriveAttributeValue[] values) {}
194 public override void Update() {
196 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
198 foreach (KeyValuePair<SmartAttribute, Sensor> keyValuePair in sensors) {
199 SmartAttribute attribute = keyValuePair.Key;
200 foreach (DriveAttributeValue value in values) {
201 if (value.Identifier == attribute.Identifier) {
202 Sensor sensor = keyValuePair.Value;
203 sensor.Value = attribute.ConvertValue(value, sensor.Parameters);
208 UpdateAdditionalSensors(values);
210 if (usageSensor != null) {
212 long totalFreeSpace = 0;
213 for (int i = 0; i < driveInfos.Length; i++) {
214 totalSize += driveInfos[i].TotalSize;
215 totalFreeSpace += driveInfos[i].TotalFreeSpace;
217 usageSensor.Value = 100.0f - (100.0f * totalFreeSpace) / totalSize;
222 count %= UPDATE_DIVIDER;
225 public override string GetReport() {
226 StringBuilder r = new StringBuilder();
227 DriveAttributeValue[] values = smart.ReadSmartData(handle, index);
228 DriveThresholdValue[] thresholds =
229 smart.ReadSmartThresholds(handle, index);
231 if (values.Length > 0) {
232 r.AppendLine(this.GetType().Name);
234 r.AppendLine("Drive name: " + name);
235 r.AppendLine("Firmware version: " + firmwareRevision);
237 r.AppendFormat(CultureInfo.InvariantCulture,
238 " {0}{1}{2}{3}{4}{5}{6}{7}",
240 ("Description").PadRight(35),
241 ("Raw Value").PadRight(13),
242 ("Worst").PadRight(6),
243 ("Value").PadRight(6),
244 ("Thres").PadRight(6),
245 ("Physical").PadRight(8),
246 Environment.NewLine);
248 foreach (DriveAttributeValue value in values) {
249 if (value.Identifier == 0x00)
252 byte? threshold = null;
253 foreach (DriveThresholdValue t in thresholds) {
254 if (t.Identifier == value.Identifier) {
255 threshold = t.Threshold;
259 string description = "Unknown";
260 float? physical = null;
261 foreach (SmartAttribute a in smartAttributes) {
262 if (a.Identifier == value.Identifier) {
263 description = a.Name;
264 if (a.HasRawValueConversion | a.SensorType.HasValue)
265 physical = a.ConvertValue(value, null);
271 string raw = BitConverter.ToString(value.RawValue);
272 r.AppendFormat(CultureInfo.InvariantCulture,
273 " {0}{1}{2}{3}{4}{5}{6}{7}",
274 value.Identifier.ToString("X2").PadRight(3),
275 description.PadRight(35),
276 raw.Replace("-", "").PadRight(13),
277 value.WorstValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
278 value.AttrValue.ToString(CultureInfo.InvariantCulture).PadRight(6),
279 (threshold.HasValue ? threshold.Value.ToString(
280 CultureInfo.InvariantCulture) : "-").PadRight(6),
281 (physical.HasValue ? physical.Value.ToString(
282 CultureInfo.InvariantCulture) : "-").PadRight(8),
283 Environment.NewLine);
288 foreach (DriveInfo di in driveInfos) {
289 r.AppendLine("Logical drive name: " + di.Name);
290 r.AppendLine("Format: " + di.DriveFormat);
291 r.AppendLine("Total size: " + di.TotalSize);
292 r.AppendLine("Total free space: " + di.TotalFreeSpace);
299 protected static float RawToInt(byte[] raw, byte value,
300 IReadOnlyArray<IParameter> parameters)
302 return (raw[3] << 24) | (raw[2] << 16) | (raw[1] << 8) | raw[0];
305 public override void Close() {
306 smart.CloseHandle(handle);
310 public override void Traverse(IVisitor visitor) {
311 foreach (ISensor sensor in Sensors)
312 sensor.Accept(visitor);