Advertisement
3DotDev

Détecter si disque dur système est de type SSD

Aug 15th, 2013
510
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
VB.NET 11.45 KB | None | 0 0
  1. '########################################################
  2. ' Credits 3DotDev from http://3dotdevcoder.blogspot.fr/
  3. '########################################################
  4.  
  5. Imports System.Runtime.InteropServices
  6. Imports Microsoft.Win32.SafeHandles
  7. Imports System.IO
  8.  
  9. Namespace HardwareInfos
  10.  
  11.     ''' <summary>
  12.     '''     Original C++ langage by NyaRuRu from                   : http://nyaruru.hatenablog.com/entry/2012/09/29/063829
  13.     '''     Coded in C# language from                              : https://emoacht.wordpress.com/2012/11/06/csharp-ssd/
  14.     '''     This is the vbnet version improved for my personal use !
  15.     ''' </summary>
  16.     Public Class Disk
  17.  
  18. #Region " Constants "
  19.         ' For CreateFile to get handle to drive
  20.         Private Const GENERIC_READ As UInteger = &H80000000UI
  21.         Private Const GENERIC_WRITE As UInteger = &H40000000
  22.         Private Const FILE_SHARE_READ As UInteger = 1
  23.         Private Const FILE_SHARE_WRITE As UInteger = 2
  24.         Private Const OPEN_EXISTING As UInteger = 3
  25.         Private Const FILE_ATTRIBUTE_NORMAL As UInteger = 128
  26.  
  27.         ' For control codes
  28.         Private Const FILE_DEVICE_MASS_STORAGE As UInteger = 45
  29.         Private Const IOCTL_STORAGE_BASE As UInteger = FILE_DEVICE_MASS_STORAGE
  30.         Private Const FILE_DEVICE_CONTROLLER As UInteger = 4
  31.         Private Const IOCTL_SCSI_BASE As UInteger = FILE_DEVICE_CONTROLLER
  32.         Private Const IOCTL_VOLUME_BASE As UInteger = 86
  33.         Private Const METHOD_BUFFERED As UInteger = 0
  34.         Private Const FILE_ANY_ACCESS As UInteger = 0
  35.         Private Const FILE_READ_ACCESS As UInteger = 1
  36.         Private Const FILE_WRITE_ACCESS As UInteger = 2
  37.  
  38.         ' For DeviceIoControl to check nominal media rotation rate
  39.         Private Const ATA_FLAGS_DATA_IN As UInteger = 2
  40.  
  41.         ' For DeviceIoControl to check no seek penalty
  42.         Private Const StorageDeviceSeekPenaltyProperty As UInteger = 7
  43.         Private Const PropertyStandardQuery As UInteger = 0
  44. #End Region
  45.  
  46. #Region " Structures "
  47.  
  48.         Private Structure VOLUME_DISK_EXTENTS
  49.             Public NumberOfDiskExtents As UInteger
  50.             <MarshalAs(UnmanagedType.ByValArray)> _
  51.             Public Extents As DISK_EXTENT()
  52.         End Structure
  53.  
  54.         ' For DeviceIoControl to get disk extents
  55.         Private Structure DISK_EXTENT
  56.             Public DiskNumber As UInteger
  57.             Public StartingOffset As Long
  58.             Public ExtentLength As Long
  59.         End Structure
  60.  
  61.         Private Structure STORAGE_PROPERTY_QUERY
  62.             Public PropertyId As UInteger
  63.             Public QueryType As UInteger
  64.             <MarshalAs(UnmanagedType.ByValArray, SizeConst:=1)> _
  65.             Public AdditionalParameters As Byte()
  66.         End Structure
  67.  
  68.         Private Structure DEVICE_SEEK_PENALTY_DESCRIPTOR
  69.             Public Version As UInteger
  70.             Public Size As UInteger
  71.             <MarshalAs(UnmanagedType.U1)> _
  72.             Public IncursSeekPenalty As Boolean
  73.         End Structure
  74.  
  75.         Private Structure ATAIdentifyDeviceQuery
  76.             Public header As ATA_PASS_THROUGH_EX
  77.             <MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
  78.             Public data As UShort()
  79.         End Structure
  80.  
  81.         Private Structure ATA_PASS_THROUGH_EX
  82.             Public Length As UInt16
  83.             Public AtaFlags As UInt16
  84.             Public PathId As Byte
  85.             Public TargetId As Byte
  86.             Public Lun As Byte
  87.             Public ReservedAsUchar As Byte
  88.             Public DataTransferLength As UInt32
  89.             Public TimeOutValue As UInt32
  90.             Public ReservedAsUlong As UInt32
  91.             Public DataBufferOffset As IntPtr
  92.             <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
  93.             Public PreviousTaskFile As Byte()
  94.             <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
  95.             Public CurrentTaskFile As Byte()
  96.         End Structure
  97. #End Region
  98.  
  99. #Region " Native Methods "
  100.         ' CreateFile to get handle to drive
  101.         <DllImport("kernel32.dll", SetLastError:=True)> _
  102.         Private Shared Function CreateFileW(<MarshalAs(UnmanagedType.LPWStr)> lpFileName As String, dwDesiredAccess As UInteger, dwShareMode As UInteger, lpSecurityAttributes As IntPtr, dwCreationDisposition As UInteger, dwFlagsAndAttributes As UInteger, hTemplateFile As IntPtr) As SafeFileHandle
  103.         End Function
  104.         ' DeviceIoControl to get disk extents
  105.         <DllImport("kernel32.dll", SetLastError:=True)> _
  106.         Private Shared Function DeviceIoControl(hDevice As SafeFileHandle, dwIoControlCode As UInteger, lpInBuffer As IntPtr, nInBufferSize As UInteger, ByRef lpOutBuffer As VOLUME_DISK_EXTENTS, nOutBufferSize As UInteger, ByRef lpBytesReturned As UInteger, lpOverlapped As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
  107.         End Function
  108.         ' DeviceIoControl to check no seek penalty
  109.         <DllImport("kernel32.dll", EntryPoint:="DeviceIoControl", SetLastError:=True)> _
  110.         Private Shared Function DeviceIoControl(hDevice As SafeFileHandle, dwIoControlCode As UInt32, ByRef lpInBuffer As STORAGE_PROPERTY_QUERY, nInBufferSize As UInt32, ByRef lpOutBuffer As DEVICE_SEEK_PENALTY_DESCRIPTOR, nOutBufferSize As UInt32, ByRef lpBytesReturned As UInteger, lpOverlapped As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
  111.         End Function
  112.         ' DeviceIoControl to check nominal media rotation rate
  113.         <DllImport("kernel32.dll", EntryPoint:="DeviceIoControl", SetLastError:=True)> _
  114.         Private Shared Function DeviceIoControl(ByVal hDevice As SafeFileHandle, ByVal dwIoControlCode As UInt32, ByRef lpInBuffer As ATAIdentifyDeviceQuery, ByVal nInBufferSize As UInt32, ByRef lpOutBuffer As ATAIdentifyDeviceQuery, ByVal nOutBufferSize As UInt32, ByRef lpBytesReturned As UInteger, lpOverlapped As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
  115.         End Function
  116. #End Region
  117.  
  118. #Region " Public Methods "
  119.         Public Shared Function IsSSDDrive() As Boolean
  120.             Dim diskExtents As String = GetDiskExtents("c"c)
  121.             If (diskExtents = "") Then Return False
  122.             If (Not HasNoSeekPenalty(diskExtents) AndAlso Not HasNominalMediaRotationRate(diskExtents)) Then Return False
  123.             Return True
  124.         End Function
  125. #End Region
  126.  
  127. #Region " Private Methods "
  128.         Private Shared Function GetDiskExtents(cDrive As Char) As String
  129.             Try
  130.                 Dim info As New DriveInfo(cDrive.ToString)
  131.                 If (info.DriveType = DriveType.Fixed) Then
  132.                     Dim handle As SafeFileHandle = CreateFileW(("\\.\" & cDrive.ToString & ":"), 0, 3, IntPtr.Zero, 3, &H80, IntPtr.Zero)
  133.                     If ((Not handle Is Nothing) AndAlso Not handle.IsInvalid) Then
  134.                         Dim IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS As UInt32 = CTL_CODE(IOCTL_VOLUME_BASE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
  135.                         Dim query_disk_extents As New VOLUME_DISK_EXTENTS
  136.                         Dim returned_query_disk_extents_size As UInteger
  137.                         Dim query_disk_extents_result As Boolean = DeviceIoControl(handle, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, IntPtr.Zero, 0, query_disk_extents, CType(Marshal.SizeOf(query_disk_extents), UInt32), returned_query_disk_extents_size, IntPtr.Zero)
  138.                         handle.Close()
  139.                         If (query_disk_extents_result AndAlso (query_disk_extents.Extents.Length = 1)) Then
  140.                             Return ("\\.\PhysicalDrive" & query_disk_extents.Extents(0).DiskNumber.ToString)
  141.                         End If
  142.                         Return ""
  143.                     End If
  144.                 End If
  145.                 Return ""
  146.             Catch ex As Exception
  147.             End Try
  148.             Return ""
  149.         End Function
  150.  
  151.         Private Shared Function CTL_CODE(DeviceType As UInteger, Functione As UInteger, Method As UInteger, Access As UInteger) As UInteger
  152.             Return ((DeviceType << 16) Or (Access << 14) Or (Functione << 2) Or Method)
  153.         End Function
  154.  
  155.         Private Shared Function HasNoSeekPenalty(sDrive$) As Boolean
  156.             Try
  157.                 Dim handle As SafeFileHandle = CreateFileW(sDrive, 0, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)
  158.                 If ((Not handle Is Nothing) AndAlso Not handle.IsInvalid) Then
  159.                     Dim num2 As UInt32
  160.                     Dim IOCTL_STORAGE_QUERY_PROPERTY As UInt32 = CTL_CODE(IOCTL_STORAGE_BASE, &H500, METHOD_BUFFERED, FILE_ANY_ACCESS)
  161.                     Dim query_seek_penalty As New STORAGE_PROPERTY_QUERY With { _
  162.                         .PropertyId = StorageDeviceSeekPenaltyProperty, _
  163.                         .QueryType = PropertyStandardQuery _
  164.                     }
  165.                     Dim query_seek_penalty_desc As New DEVICE_SEEK_PENALTY_DESCRIPTOR
  166.                     Dim query_seek_penalty_result As Boolean = DeviceIoControl(handle, IOCTL_STORAGE_QUERY_PROPERTY, query_seek_penalty, CType(Marshal.SizeOf(query_seek_penalty), UInt32), query_seek_penalty_desc, CType(Marshal.SizeOf(query_seek_penalty_desc), UInt32), num2, IntPtr.Zero)
  167.                     handle.Close()
  168.                     If query_seek_penalty_result Then Return Not query_seek_penalty_desc.IncursSeekPenalty
  169.                 Else
  170.                     Return False
  171.                 End If
  172.             Catch ex As Exception
  173.             End Try
  174.             Return False
  175.         End Function
  176.  
  177.         Private Shared Function HasNominalMediaRotationRate(sDrive$) As Boolean
  178.             Try
  179.                 Dim handle As SafeFileHandle = CreateFileW(sDrive, GENERIC_READ Or GENERIC_WRITE, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)
  180.                 If ((Not handle Is Nothing) AndAlso Not handle.IsInvalid) Then
  181.  
  182.                     Dim IOCTL_ATA_PASS_THROUGH = CTL_CODE(IOCTL_SCSI_BASE, &H40B, METHOD_BUFFERED, FILE_READ_ACCESS Or FILE_WRITE_ACCESS)
  183.                     Dim id_query As New ATAIdentifyDeviceQuery With { _
  184.                         .data = New UInt16(&H100 - 1) {} _
  185.                     }
  186.                     With id_query.header
  187.                         .Length = CUShort(Marshal.SizeOf(id_query.header))
  188.                         .AtaFlags = ATA_FLAGS_DATA_IN
  189.                         .DataTransferLength = CType((id_query.data.Length * 2), UInt32)
  190.                         .TimeOutValue = 3
  191.                         .DataBufferOffset = Marshal.OffsetOf(GetType(ATA_PASS_THROUGH_EX), "data")
  192.                         .PreviousTaskFile = New Byte(8 - 1) {}
  193.                         .CurrentTaskFile = New Byte(8 - 1) {}
  194.                         .CurrentTaskFile(6) = &HEC
  195.                     End With
  196.  
  197.                     Dim retval_size As UInt32
  198.                     Dim result = DeviceIoControl(handle, IOCTL_ATA_PASS_THROUGH, id_query, CType(Marshal.SizeOf(id_query), UInt32), id_query, CType(Marshal.SizeOf(id_query), UInt32), retval_size, IntPtr.Zero)
  199.                     handle.Close()
  200.                     If result Then Return (id_query.data(&HD9) = 1)
  201.                 Else
  202.                     Return False
  203.                 End If
  204.             Catch ex As Exception
  205.             End Try
  206.             Return False
  207.         End Function
  208. #End Region
  209.  
  210.     End Class
  211.  
  212. End Namespace
  213.  
  214. '############################# Comment l'utiliser ##############################
  215.  
  216. MsgBox(HardwareInfos.Disk.IsSSDDrive.ToString())
  217.  
  218. '##############################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement