Hardware/HDD/SMART.cs
changeset 324 c6ee430d6995
parent 323 3f2d9ebacf38
child 325 4c31341a4800
     1.1 --- a/Hardware/HDD/SMART.cs	Wed Aug 31 22:48:49 2011 +0000
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,508 +0,0 @@
     1.4 -/*
     1.5 -  
     1.6 -  Version: MPL 1.1/GPL 2.0/LGPL 2.1
     1.7 -
     1.8 -  The contents of this file are subject to the Mozilla Public License Version
     1.9 -  1.1 (the "License"); you may not use this file except in compliance with
    1.10 -  the License. You may obtain a copy of the License at
    1.11 - 
    1.12 -  http://www.mozilla.org/MPL/
    1.13 -
    1.14 -  Software distributed under the License is distributed on an "AS IS" basis,
    1.15 -  WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
    1.16 -  for the specific language governing rights and limitations under the License.
    1.17 -
    1.18 -  The Original Code is the Open Hardware Monitor code.
    1.19 -
    1.20 -  The Initial Developer of the Original Code is 
    1.21 -  Michael Möller <m.moeller@gmx.ch>.
    1.22 -  Portions created by the Initial Developer are Copyright (C) 2009-2011
    1.23 -  the Initial Developer. All Rights Reserved.
    1.24 -
    1.25 -  Contributor(s): Paul Werelds
    1.26 -
    1.27 -  Alternatively, the contents of this file may be used under the terms of
    1.28 -  either the GNU General Public License Version 2 or later (the "GPL"), or
    1.29 -  the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
    1.30 -  in which case the provisions of the GPL or the LGPL are applicable instead
    1.31 -  of those above. If you wish to allow use of your version of this file only
    1.32 -  under the terms of either the GPL or the LGPL, and not to allow others to
    1.33 -  use your version of this file under the terms of the MPL, indicate your
    1.34 -  decision by deleting the provisions above and replace them with the notice
    1.35 -  and other provisions required by the GPL or the LGPL. If you do not delete
    1.36 -  the provisions above, a recipient may use your version of this file under
    1.37 -  the terms of any one of the MPL, the GPL or the LGPL.
    1.38 - 
    1.39 -*/
    1.40 -
    1.41 -using System;
    1.42 -using System.Collections.Generic;
    1.43 -using System.Runtime.InteropServices;
    1.44 -
    1.45 -namespace OpenHardwareMonitor.Hardware.HDD {
    1.46 -
    1.47 -  internal class SMART {
    1.48 -
    1.49 -    [Flags]
    1.50 -    public enum Status : ushort {
    1.51 -      PreFailureWarranty = 0x01,
    1.52 -      OnLineCollection = 0x02,
    1.53 -      Performance = 0x04,
    1.54 -      ErrorRate = 0x08,
    1.55 -      EventCount = 0x10,
    1.56 -      SelfPreserving = 0x20
    1.57 -    }
    1.58 -
    1.59 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    1.60 -    public struct AttributeID {
    1.61 -      private byte value;
    1.62 -
    1.63 -      public AttributeID(byte value) {
    1.64 -        this.value = value;
    1.65 -      }
    1.66 -
    1.67 -      public override bool Equals(Object obj) {
    1.68 -        return obj is AttributeID && this == (AttributeID)obj;
    1.69 -      }
    1.70 -      public override int GetHashCode() {
    1.71 -        return value.GetHashCode() ^ value.GetHashCode();
    1.72 -      }
    1.73 -      public static bool operator ==(AttributeID a, AttributeID b) {
    1.74 -        return a.value == b.value;
    1.75 -      }
    1.76 -      public static bool operator !=(AttributeID a, AttributeID b) {
    1.77 -        return !(a == b);
    1.78 -      }
    1.79 -
    1.80 -      public string ToString(string format) {
    1.81 -        return value.ToString(format);
    1.82 -      }
    1.83 -
    1.84 -      public static readonly AttributeID None = new AttributeID(0x00);
    1.85 -    }
    1.86 -
    1.87 -    // These are the more-or-less standard S.M.A.R.T attributes
    1.88 -    // TODO: Filter out unused/obscure ones; some are interpreted differently
    1.89 -    // between manufacturers
    1.90 -    public static class CommonAttributes {
    1.91 -      public static readonly AttributeID
    1.92 -        ReadErrorRate = new AttributeID(0x01),
    1.93 -        ThroughputPerformance = new AttributeID(0x02),
    1.94 -        SpinUpTime = new AttributeID(0x03),
    1.95 -        StartStopCount = new AttributeID(0x04),
    1.96 -        ReallocatedSectorsCount = new AttributeID(0x05),
    1.97 -        ReadChannelMargin = new AttributeID(0x06),
    1.98 -        SeekErrorRate = new AttributeID(0x07),
    1.99 -        SeekTimePerformance = new AttributeID(0x08),
   1.100 -        PowerOnHours = new AttributeID(0x09),
   1.101 -        SpinRetryCount = new AttributeID(0x0A),
   1.102 -        RecalibrationRetries = new AttributeID(0x0B),
   1.103 -        PowerCycleCount = new AttributeID(0x0C),
   1.104 -        SoftReadErrorRate = new AttributeID(0x0D),
   1.105 -        SataDownshiftErrorCount = new AttributeID(0xB7),
   1.106 -        EndToEndError = new AttributeID(0xB8),
   1.107 -        HeadStability = new AttributeID(0xB9),
   1.108 -        InducedOpVibrationDetection = new AttributeID(0xBA),
   1.109 -        ReportedUncorrectableErrors = new AttributeID(0xBB),
   1.110 -        CommandTimeout = new AttributeID(0xBC),
   1.111 -        HighFlyWrites = new AttributeID(0xBD),
   1.112 -        AirflowTemperature = new AttributeID(0xBE),
   1.113 -        GSenseErrorRate = new AttributeID(0xBF),
   1.114 -        PowerOffRetractCount = new AttributeID(0xC0),
   1.115 -        LoadCycleCount = new AttributeID(0xC1),
   1.116 -        Temperature = new AttributeID(0xC2),
   1.117 -        HardwareEccRecovered = new AttributeID(0xC3),
   1.118 -        ReallocationEventCount = new AttributeID(0xC4),
   1.119 -        CurrentPendingSectorCount = new AttributeID(0xC5),
   1.120 -        UncorrectableSectorCount = new AttributeID(0xC6),
   1.121 -        UltraDmaCrcErrorCount = new AttributeID(0xC7),
   1.122 -        WriteErrorRate = new AttributeID(0xC8),
   1.123 -        DataAddressMarkerrors = new AttributeID(0xCA),
   1.124 -        RunOutCancel = new AttributeID(0xCB),
   1.125 -        SoftEccCorrection = new AttributeID(0xCC),
   1.126 -        ThermalAsperityRate = new AttributeID(0xCD),
   1.127 -        FlyingHeight = new AttributeID(0xCE),
   1.128 -        SpinHighCurrent = new AttributeID(0xCF),
   1.129 -        SpinBuzz = new AttributeID(0xD0),
   1.130 -        OfflineSeekPerformance = new AttributeID(0xD1),
   1.131 -        VibrationDuringWrite = new AttributeID(0xD3),
   1.132 -        ShockDuringWrite = new AttributeID(0xD4),
   1.133 -        DiskShift = new AttributeID(0xDC),
   1.134 -        GSenseErrorRateAlt = new AttributeID(0xDD), // Alternative to 0xBF
   1.135 -        LoadedHours = new AttributeID(0xDE),
   1.136 -        LoadUnloadRetryCount = new AttributeID(0xDF),
   1.137 -        LoadFriction = new AttributeID(0xE0),
   1.138 -        LoadUnloadCycleCount = new AttributeID(0xE1),
   1.139 -        LoadInTime = new AttributeID(0xE2),
   1.140 -        TorqueAmplificationCount = new AttributeID(0xE3),
   1.141 -        PowerOffRetractCycle = new AttributeID(0xE4),
   1.142 -        GMRHeadAmplitude = new AttributeID(0xE6),
   1.143 -        DriveTemperature = new AttributeID(0xE7),
   1.144 -        HeadFlyingHours = new AttributeID(0xF0),
   1.145 -        LBAsWrittenTotal = new AttributeID(0xF1),
   1.146 -        LBAsReadTotal = new AttributeID(0xF2),
   1.147 -        ReadErrorRetryRate = new AttributeID(0xFA),
   1.148 -        FreeFallProtection = new AttributeID(0xFE)
   1.149 -      ;
   1.150 -    }
   1.151 -
   1.152 -    // Indilinx SSD SMART attributes
   1.153 -    // TODO: Find out the purpose of attribute 0xD2
   1.154 -    // Seems to be unique to Indilinx drives, hence its name of UnknownUnique.
   1.155 -    public static class IndilinxAttributes {
   1.156 -      public static readonly AttributeID
   1.157 -        ReadErrorRate = CommonAttributes.ReadErrorRate,
   1.158 -        PowerOnHours = CommonAttributes.PowerOnHours,
   1.159 -        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.160 -        InitialBadBlockCount = new AttributeID(0xB8),
   1.161 -        RemainingLife = new AttributeID(0xD1),
   1.162 -        ProgramFailure = new AttributeID(0xC3),
   1.163 -        EraseFailure = new AttributeID(0xC4),
   1.164 -        ReadFailure = new AttributeID(0xC5),
   1.165 -        SectorsRead = new AttributeID(0xC6),
   1.166 -        SectorsWritten = new AttributeID(0xC7),
   1.167 -        ReadCommands = new AttributeID(0xC8),
   1.168 -        WriteCommands = new AttributeID(0xC9),
   1.169 -        BitErrors = new AttributeID(0xCA),
   1.170 -        CorrectedErrors = new AttributeID(0xCB),
   1.171 -        BadBlockFullFlag = new AttributeID(0xCC),
   1.172 -        MaxCellcycles = new AttributeID(0xCD),
   1.173 -        MinErase = new AttributeID(0xCE),
   1.174 -        MaxErase = new AttributeID(0xCF),
   1.175 -        AverageEraseCount = new AttributeID(0xD0),
   1.176 -        UnknownUnique = new AttributeID(0xD2),
   1.177 -        SataErrorCountCRC = new AttributeID(0xD3),
   1.178 -        SataErrorCountHandshake = new AttributeID(0xD4)
   1.179 -      ;
   1.180 -    }
   1.181 -
   1.182 -    // Intel SSD SMART attributes
   1.183 -    // TODO: Find out the meaning behind 0xE2, 0xE3 and 0xE4
   1.184 -    public static class IntelAttributes {
   1.185 -      public static readonly AttributeID
   1.186 -        ReadErrorRate = CommonAttributes.ReadErrorRate,
   1.187 -        SpinUpTime = CommonAttributes.SpinUpTime,
   1.188 -        StartStopCount = CommonAttributes.StartStopCount,
   1.189 -        ReallocatedSectorsCount = CommonAttributes.ReallocatedSectorsCount,
   1.190 -        PowerOnHours = CommonAttributes.PowerOnHours,
   1.191 -        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.192 -        EndToEndError = CommonAttributes.EndToEndError, // Only on G2 drives!
   1.193 -
   1.194 -        // Different from the common attribute PowerOffRetractCount, same ID
   1.195 -        UnsafeShutdownCount = new AttributeID(0xC0),
   1.196 -        HostWrites = new AttributeID(0xE1),
   1.197 -        RemainingLife = new AttributeID(0xE8),
   1.198 -        MediaWearOutIndicator = new AttributeID(0xE9)
   1.199 -      ;
   1.200 -    }
   1.201 -
   1.202 -    // Samsung SSD SMART attributes
   1.203 -    // TODO: AF, B0, B1, B5, B6, BB, C3, C6, C7, E8, E9
   1.204 -    public static class SamsungAttributes {
   1.205 -      public static readonly AttributeID
   1.206 -        PowerOnHours = CommonAttributes.PowerOnHours,
   1.207 -        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.208 -        UsedReservedBlockCountChip = new AttributeID(0xB2), // Unique
   1.209 -        UsedReservedBlockCountTotal = new AttributeID(0xB3), // Unique
   1.210 -        RemainingLife = new AttributeID(0xB4), // Unique
   1.211 -        RuntimeBadBlockTotal = new AttributeID(0xB7)
   1.212 -      ;
   1.213 -    }
   1.214 -
   1.215 -    // SandForce SSD SMART attributes
   1.216 -    // Note: 0xE9 and 0xEA are reserved attributes and unique
   1.217 -    public static class SandForceAttributes {
   1.218 -      public static readonly AttributeID
   1.219 -        ReadErrorRate = CommonAttributes.ReadErrorRate,
   1.220 -        RetiredBlockCount = new AttributeID(0x05),
   1.221 -        PowerOnHours = CommonAttributes.PowerOnHours,
   1.222 -        PowerCycleCount = CommonAttributes.PowerCycleCount,
   1.223 -        ProgramFailCount = new AttributeID(0xAB), // Unique
   1.224 -        EraseFailCount = new AttributeID(0xAC), // Unique
   1.225 -        UnexpectedPowerLossCount = new AttributeID(0xAE), // Unique
   1.226 -        WearRangeDelta = new AttributeID(0xB1), // Unique
   1.227 -        ProgramFailCountAlt = new AttributeID(0xB5), // Same as 0xAB
   1.228 -        EraseFailCountAlt = new AttributeID(0xB6), // Same as 0xAC
   1.229 -        ReportedUncorrectableErrors =
   1.230 -          CommonAttributes.ReportedUncorrectableErrors,
   1.231 -        
   1.232 -        Temperature = CommonAttributes.Temperature, // SF-1500 only!
   1.233 -        
   1.234 -        // Opposite of the common attribute HardwareECCRecovered
   1.235 -        UnrecoverableECC = new AttributeID(0xC3),
   1.236 -        ReallocationEventCount = new AttributeID(0xC4),
   1.237 -        RemainingLife = new AttributeID(0xE7),
   1.238 -        LifetimeWrites = new AttributeID(0xF1),
   1.239 -        LifetimeReads = new AttributeID(0xF2)
   1.240 -      ;
   1.241 -    }
   1.242 -
   1.243 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.244 -    public struct DriveAttribute {
   1.245 -      public AttributeID ID;
   1.246 -      public Status StatusFlags;
   1.247 -      public byte AttrValue;
   1.248 -      public byte WorstValue;
   1.249 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
   1.250 -      public byte[] RawValue;
   1.251 -      public byte Reserved;
   1.252 -    };
   1.253 -
   1.254 -    [Flags]
   1.255 -    protected enum AccessMode : uint {     
   1.256 -      Read = 0x80000000,    
   1.257 -      Write = 0x40000000,     
   1.258 -      Execute = 0x20000000,     
   1.259 -      All = 0x10000000
   1.260 -    }
   1.261 -
   1.262 -    [Flags]
   1.263 -    protected enum ShareMode : uint {
   1.264 -      None = 0,     
   1.265 -      Read = 1,     
   1.266 -      Write = 2,    
   1.267 -      Delete = 4
   1.268 -    }
   1.269 -
   1.270 -    protected enum CreationMode : uint {
   1.271 -      New = 1,
   1.272 -      CreateAlways = 2,    
   1.273 -      OpenExisting = 3,    
   1.274 -      OpenAlways = 4,    
   1.275 -      TruncateExisting = 5
   1.276 -    }
   1.277 -
   1.278 -    [Flags]
   1.279 -    protected enum FileAttribute : uint {
   1.280 -      Readonly = 0x00000001,
   1.281 -      Hidden = 0x00000002,
   1.282 -      System = 0x00000004,
   1.283 -      Directory = 0x00000010,
   1.284 -      Archive = 0x00000020,
   1.285 -      Device = 0x00000040,
   1.286 -      Normal = 0x00000080,
   1.287 -      Temporary = 0x00000100,
   1.288 -      SparseFile = 0x00000200,
   1.289 -      ReparsePoint = 0x00000400,
   1.290 -      Compressed = 0x00000800,
   1.291 -      Offline = 0x00001000,
   1.292 -      NotContentIndexed = 0x00002000,
   1.293 -      Encrypted = 0x00004000,
   1.294 -    }
   1.295 -
   1.296 -    protected enum DriveCommand : uint {
   1.297 -      GetVersion = 0x00074080,
   1.298 -      SendDriveCommand = 0x0007c084,
   1.299 -      ReceiveDriveData = 0x0007c088
   1.300 -    }
   1.301 -
   1.302 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.303 -    protected struct CommandBlockRegisters {
   1.304 -      public byte Features;         
   1.305 -      public byte SectorCount;      
   1.306 -      public byte LBALow;       
   1.307 -      public byte LBAMid;           
   1.308 -      public byte LBAHigh;        
   1.309 -      public byte Device;       
   1.310 -      public byte Command;           
   1.311 -      public byte Reserved;                  
   1.312 -    }
   1.313 -
   1.314 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.315 -    protected struct DriveCommandParameter {
   1.316 -      public uint BufferSize;           
   1.317 -      public CommandBlockRegisters Registers;           
   1.318 -      public byte DriveNumber;   
   1.319 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
   1.320 -      public byte[] Reserved;                                
   1.321 -    }
   1.322 -
   1.323 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.324 -    protected struct DriverStatus {
   1.325 -      public byte DriverError;   
   1.326 -      public byte IDEError;             
   1.327 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 10)]
   1.328 -      public byte[] Reserved;               
   1.329 -    }
   1.330 -
   1.331 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.332 -    protected struct DriveCommandResult {
   1.333 -      public uint BufferSize;
   1.334 -      public DriverStatus DriverStatus;
   1.335 -    } 
   1.336 -
   1.337 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.338 -    protected struct DriveSmartReadResult {
   1.339 -      public uint BufferSize;           
   1.340 -      public DriverStatus DriverStatus;
   1.341 -      public byte Version;
   1.342 -      public byte Reserved;
   1.343 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_DRIVE_ATTRIBUTES)]
   1.344 -      public DriveAttribute[] Attributes;                                                                                       
   1.345 -    }
   1.346 -
   1.347 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.348 -    protected struct Identify {
   1.349 -      public ushort GeneralConfiguration;
   1.350 -      public ushort NumberOfCylinders;
   1.351 -      public ushort Reserved;
   1.352 -      public ushort NumberOfHeads;
   1.353 -      public ushort UnformattedBytesPerTrack;
   1.354 -      public ushort UnformattedBytesPerSector;
   1.355 -      public ushort SectorsPerTrack;
   1.356 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
   1.357 -      public ushort[] VendorUnique;
   1.358 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
   1.359 -      public byte[] SerialNumber;
   1.360 -      public ushort BufferType;
   1.361 -      public ushort BufferSectorSize;
   1.362 -      public ushort NumberOfEccBytes;
   1.363 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
   1.364 -      public byte[] FirmwareRevision;
   1.365 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
   1.366 -      public byte[] ModelNumber;
   1.367 -      public ushort MoreVendorUnique;
   1.368 -      public ushort DoubleWordIo;
   1.369 -      public ushort Capabilities;
   1.370 -      public ushort MoreReserved;
   1.371 -      public ushort PioCycleTimingMode;
   1.372 -      public ushort DmaCycleTimingMode;
   1.373 -      [MarshalAs(UnmanagedType.ByValArray, SizeConst = 406)]
   1.374 -      public byte[] More;
   1.375 -    }
   1.376 -
   1.377 -    [StructLayout(LayoutKind.Sequential, Pack = 1)]
   1.378 -    protected struct DriveIdentifyResult {
   1.379 -      public uint BufferSize;
   1.380 -      public DriverStatus DriverStatus;
   1.381 -      public Identify Identify;
   1.382 -    } 
   1.383 -
   1.384 -    public static readonly IntPtr INVALID_HANDLE_VALUE = (IntPtr)(-1);
   1.385 -
   1.386 -    private const byte SMART_CMD = 0xB0;
   1.387 -    private const byte ID_CMD = 0xEC;
   1.388 -    
   1.389 -    private const byte SMART_READ_DATA = 0xD0;
   1.390 -    private const byte SMART_ENABLE_OPERATIONS = 0xD8;
   1.391 -    
   1.392 -    private const byte SMART_LBA_MID = 0x4F;
   1.393 -    private const byte SMART_LBA_HI = 0xC2;
   1.394 -
   1.395 -    private const int MAX_DRIVE_ATTRIBUTES = 512;
   1.396 -
   1.397 -    private SMART() { }
   1.398 -
   1.399 -    public static IntPtr OpenPhysicalDrive(int driveNumber) {
   1.400 -      return NativeMethods.CreateFile(@"\\.\PhysicalDrive" + driveNumber,
   1.401 -        AccessMode.Read | AccessMode.Write, ShareMode.Read | ShareMode.Write,
   1.402 -        IntPtr.Zero, CreationMode.OpenExisting, FileAttribute.Device,
   1.403 -        IntPtr.Zero);
   1.404 -    }
   1.405 -
   1.406 -    public static bool EnableSmart(IntPtr handle, int driveNumber) {
   1.407 -      DriveCommandParameter parameter = new DriveCommandParameter();
   1.408 -      DriveCommandResult result;
   1.409 -      uint bytesReturned;
   1.410 -
   1.411 -      parameter.DriveNumber = (byte)driveNumber;
   1.412 -      parameter.Registers.Features = SMART_ENABLE_OPERATIONS;
   1.413 -      parameter.Registers.LBAMid = SMART_LBA_MID;
   1.414 -      parameter.Registers.LBAHigh = SMART_LBA_HI;
   1.415 -      parameter.Registers.Command = SMART_CMD;
   1.416 -
   1.417 -      return NativeMethods.DeviceIoControl(handle, DriveCommand.SendDriveCommand, 
   1.418 -        ref parameter, Marshal.SizeOf(typeof(DriveCommandParameter)), out result,
   1.419 -        Marshal.SizeOf(typeof(DriveCommandResult)), out bytesReturned, 
   1.420 -        IntPtr.Zero);
   1.421 -    }
   1.422 -
   1.423 -    public static DriveAttribute[] ReadSmart(IntPtr handle,
   1.424 -      int driveNumber)
   1.425 -    {
   1.426 -      DriveCommandParameter parameter = new DriveCommandParameter();
   1.427 -      DriveSmartReadResult result;
   1.428 -      uint bytesReturned;
   1.429 -
   1.430 -      parameter.DriveNumber = (byte)driveNumber;
   1.431 -      parameter.Registers.Features = SMART_READ_DATA;
   1.432 -      parameter.Registers.LBAMid = SMART_LBA_MID;
   1.433 -      parameter.Registers.LBAHigh = SMART_LBA_HI;
   1.434 -      parameter.Registers.Command = SMART_CMD;
   1.435 -
   1.436 -      bool isValid = NativeMethods.DeviceIoControl(handle, 
   1.437 -        DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), 
   1.438 -        out result, Marshal.SizeOf(typeof(DriveSmartReadResult)), 
   1.439 -        out bytesReturned, IntPtr.Zero);
   1.440 -
   1.441 -      return (isValid) ? result.Attributes : new DriveAttribute[0];
   1.442 -    }
   1.443 -
   1.444 -    public static string ReadName(IntPtr handle, int driveNumber) {
   1.445 -      DriveCommandParameter parameter = new DriveCommandParameter();
   1.446 -      DriveIdentifyResult result;
   1.447 -      uint bytesReturned;
   1.448 -
   1.449 -      parameter.DriveNumber = (byte)driveNumber;
   1.450 -      parameter.Registers.Command = ID_CMD;
   1.451 -
   1.452 -      bool valid = NativeMethods.DeviceIoControl(handle, 
   1.453 -        DriveCommand.ReceiveDriveData, ref parameter, Marshal.SizeOf(parameter), 
   1.454 -        out result, Marshal.SizeOf(typeof(DriveIdentifyResult)), 
   1.455 -        out bytesReturned, IntPtr.Zero);
   1.456 -
   1.457 -      if (!valid)
   1.458 -        return null;
   1.459 -      else {
   1.460 -
   1.461 -        byte[] bytes = result.Identify.ModelNumber;
   1.462 -        char[] chars = new char[bytes.Length];
   1.463 -        for (int i = 0; i < bytes.Length; i += 2) {
   1.464 -          chars[i] = (char)bytes[i + 1];
   1.465 -          chars[i + 1] = (char)bytes[i];
   1.466 -        }
   1.467 -
   1.468 -        return new string(chars).Trim(new char[] {' ', '\0'});
   1.469 -      }
   1.470 -    }
   1.471 -
   1.472 -    public static int CloseHandle(IntPtr handle) {
   1.473 -      return NativeMethods.CloseHandle(handle);
   1.474 -    }
   1.475 -
   1.476 -    protected static class NativeMethods {
   1.477 -      private const string KERNEL = "kernel32.dll";
   1.478 -
   1.479 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi,
   1.480 -        CharSet = CharSet.Unicode)]
   1.481 -      public static extern IntPtr CreateFile(string fileName,
   1.482 -        AccessMode desiredAccess, ShareMode shareMode, IntPtr securityAttributes,
   1.483 -        CreationMode creationDisposition, FileAttribute flagsAndAttributes,
   1.484 -        IntPtr templateFilehandle);
   1.485 -
   1.486 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.487 -      public static extern int CloseHandle(IntPtr handle);
   1.488 -
   1.489 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.490 -      [return: MarshalAsAttribute(UnmanagedType.Bool)]
   1.491 -      public static extern bool DeviceIoControl(IntPtr handle,
   1.492 -        DriveCommand command, ref DriveCommandParameter parameter,
   1.493 -        int parameterSize, out DriveSmartReadResult result, int resultSize,
   1.494 -        out uint bytesReturned, IntPtr overlapped);
   1.495 -
   1.496 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.497 -      [return: MarshalAsAttribute(UnmanagedType.Bool)]
   1.498 -      public static extern bool DeviceIoControl(IntPtr handle,
   1.499 -        DriveCommand command, ref DriveCommandParameter parameter,
   1.500 -        int parameterSize, out DriveCommandResult result, int resultSize,
   1.501 -        out uint bytesReturned, IntPtr overlapped);
   1.502 -
   1.503 -      [DllImport(KERNEL, CallingConvention = CallingConvention.Winapi)]
   1.504 -      [return: MarshalAsAttribute(UnmanagedType.Bool)]
   1.505 -      public static extern bool DeviceIoControl(IntPtr handle,
   1.506 -        DriveCommand command, ref DriveCommandParameter parameter,
   1.507 -        int parameterSize, out DriveIdentifyResult result, int resultSize,
   1.508 -        out uint bytesReturned, IntPtr overlapped);
   1.509 -    }    
   1.510 -  }
   1.511 -}