Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- '########################################################
- ' Credits 3DotDev from http://3dotdevcoder.blogspot.fr/
- '########################################################
- Imports System.Runtime.InteropServices
- Imports Microsoft.Win32.SafeHandles
- Imports System.IO
- Namespace HardwareInfos
- ''' <summary>
- ''' Original C++ langage by NyaRuRu from : http://nyaruru.hatenablog.com/entry/2012/09/29/063829
- ''' Coded in C# language from : https://emoacht.wordpress.com/2012/11/06/csharp-ssd/
- ''' This is the vbnet version improved for my personal use !
- ''' </summary>
- Public Class Disk
- #Region " Constants "
- ' For CreateFile to get handle to drive
- Private Const GENERIC_READ As UInteger = &H80000000UI
- Private Const GENERIC_WRITE As UInteger = &H40000000
- Private Const FILE_SHARE_READ As UInteger = 1
- Private Const FILE_SHARE_WRITE As UInteger = 2
- Private Const OPEN_EXISTING As UInteger = 3
- Private Const FILE_ATTRIBUTE_NORMAL As UInteger = 128
- ' For control codes
- Private Const FILE_DEVICE_MASS_STORAGE As UInteger = 45
- Private Const IOCTL_STORAGE_BASE As UInteger = FILE_DEVICE_MASS_STORAGE
- Private Const FILE_DEVICE_CONTROLLER As UInteger = 4
- Private Const IOCTL_SCSI_BASE As UInteger = FILE_DEVICE_CONTROLLER
- Private Const IOCTL_VOLUME_BASE As UInteger = 86
- Private Const METHOD_BUFFERED As UInteger = 0
- Private Const FILE_ANY_ACCESS As UInteger = 0
- Private Const FILE_READ_ACCESS As UInteger = 1
- Private Const FILE_WRITE_ACCESS As UInteger = 2
- ' For DeviceIoControl to check nominal media rotation rate
- Private Const ATA_FLAGS_DATA_IN As UInteger = 2
- ' For DeviceIoControl to check no seek penalty
- Private Const StorageDeviceSeekPenaltyProperty As UInteger = 7
- Private Const PropertyStandardQuery As UInteger = 0
- #End Region
- #Region " Structures "
- Private Structure VOLUME_DISK_EXTENTS
- Public NumberOfDiskExtents As UInteger
- <MarshalAs(UnmanagedType.ByValArray)> _
- Public Extents As DISK_EXTENT()
- End Structure
- ' For DeviceIoControl to get disk extents
- Private Structure DISK_EXTENT
- Public DiskNumber As UInteger
- Public StartingOffset As Long
- Public ExtentLength As Long
- End Structure
- Private Structure STORAGE_PROPERTY_QUERY
- Public PropertyId As UInteger
- Public QueryType As UInteger
- <MarshalAs(UnmanagedType.ByValArray, SizeConst:=1)> _
- Public AdditionalParameters As Byte()
- End Structure
- Private Structure DEVICE_SEEK_PENALTY_DESCRIPTOR
- Public Version As UInteger
- Public Size As UInteger
- <MarshalAs(UnmanagedType.U1)> _
- Public IncursSeekPenalty As Boolean
- End Structure
- Private Structure ATAIdentifyDeviceQuery
- Public header As ATA_PASS_THROUGH_EX
- <MarshalAs(UnmanagedType.ByValArray, SizeConst:=256)> _
- Public data As UShort()
- End Structure
- Private Structure ATA_PASS_THROUGH_EX
- Public Length As UInt16
- Public AtaFlags As UInt16
- Public PathId As Byte
- Public TargetId As Byte
- Public Lun As Byte
- Public ReservedAsUchar As Byte
- Public DataTransferLength As UInt32
- Public TimeOutValue As UInt32
- Public ReservedAsUlong As UInt32
- Public DataBufferOffset As IntPtr
- <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
- Public PreviousTaskFile As Byte()
- <MarshalAs(UnmanagedType.ByValArray, SizeConst:=8)> _
- Public CurrentTaskFile As Byte()
- End Structure
- #End Region
- #Region " Native Methods "
- ' CreateFile to get handle to drive
- <DllImport("kernel32.dll", SetLastError:=True)> _
- 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
- End Function
- ' DeviceIoControl to get disk extents
- <DllImport("kernel32.dll", SetLastError:=True)> _
- 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
- End Function
- ' DeviceIoControl to check no seek penalty
- <DllImport("kernel32.dll", EntryPoint:="DeviceIoControl", SetLastError:=True)> _
- 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
- End Function
- ' DeviceIoControl to check nominal media rotation rate
- <DllImport("kernel32.dll", EntryPoint:="DeviceIoControl", SetLastError:=True)> _
- 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
- End Function
- #End Region
- #Region " Public Methods "
- Public Shared Function IsSSDDrive() As Boolean
- Dim diskExtents As String = GetDiskExtents("c"c)
- If (diskExtents = "") Then Return False
- If (Not HasNoSeekPenalty(diskExtents) AndAlso Not HasNominalMediaRotationRate(diskExtents)) Then Return False
- Return True
- End Function
- #End Region
- #Region " Private Methods "
- Private Shared Function GetDiskExtents(cDrive As Char) As String
- Try
- Dim info As New DriveInfo(cDrive.ToString)
- If (info.DriveType = DriveType.Fixed) Then
- Dim handle As SafeFileHandle = CreateFileW(("\\.\" & cDrive.ToString & ":"), 0, 3, IntPtr.Zero, 3, &H80, IntPtr.Zero)
- If ((Not handle Is Nothing) AndAlso Not handle.IsInvalid) Then
- Dim IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS As UInt32 = CTL_CODE(IOCTL_VOLUME_BASE, 0, METHOD_BUFFERED, FILE_ANY_ACCESS)
- Dim query_disk_extents As New VOLUME_DISK_EXTENTS
- Dim returned_query_disk_extents_size As UInteger
- 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)
- handle.Close()
- If (query_disk_extents_result AndAlso (query_disk_extents.Extents.Length = 1)) Then
- Return ("\\.\PhysicalDrive" & query_disk_extents.Extents(0).DiskNumber.ToString)
- End If
- Return ""
- End If
- End If
- Return ""
- Catch ex As Exception
- End Try
- Return ""
- End Function
- Private Shared Function CTL_CODE(DeviceType As UInteger, Functione As UInteger, Method As UInteger, Access As UInteger) As UInteger
- Return ((DeviceType << 16) Or (Access << 14) Or (Functione << 2) Or Method)
- End Function
- Private Shared Function HasNoSeekPenalty(sDrive$) As Boolean
- Try
- Dim handle As SafeFileHandle = CreateFileW(sDrive, 0, FILE_SHARE_READ Or FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, IntPtr.Zero)
- If ((Not handle Is Nothing) AndAlso Not handle.IsInvalid) Then
- Dim num2 As UInt32
- Dim IOCTL_STORAGE_QUERY_PROPERTY As UInt32 = CTL_CODE(IOCTL_STORAGE_BASE, &H500, METHOD_BUFFERED, FILE_ANY_ACCESS)
- Dim query_seek_penalty As New STORAGE_PROPERTY_QUERY With { _
- .PropertyId = StorageDeviceSeekPenaltyProperty, _
- .QueryType = PropertyStandardQuery _
- }
- Dim query_seek_penalty_desc As New DEVICE_SEEK_PENALTY_DESCRIPTOR
- 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)
- handle.Close()
- If query_seek_penalty_result Then Return Not query_seek_penalty_desc.IncursSeekPenalty
- Else
- Return False
- End If
- Catch ex As Exception
- End Try
- Return False
- End Function
- Private Shared Function HasNominalMediaRotationRate(sDrive$) As Boolean
- Try
- 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)
- If ((Not handle Is Nothing) AndAlso Not handle.IsInvalid) Then
- Dim IOCTL_ATA_PASS_THROUGH = CTL_CODE(IOCTL_SCSI_BASE, &H40B, METHOD_BUFFERED, FILE_READ_ACCESS Or FILE_WRITE_ACCESS)
- Dim id_query As New ATAIdentifyDeviceQuery With { _
- .data = New UInt16(&H100 - 1) {} _
- }
- With id_query.header
- .Length = CUShort(Marshal.SizeOf(id_query.header))
- .AtaFlags = ATA_FLAGS_DATA_IN
- .DataTransferLength = CType((id_query.data.Length * 2), UInt32)
- .TimeOutValue = 3
- .DataBufferOffset = Marshal.OffsetOf(GetType(ATA_PASS_THROUGH_EX), "data")
- .PreviousTaskFile = New Byte(8 - 1) {}
- .CurrentTaskFile = New Byte(8 - 1) {}
- .CurrentTaskFile(6) = &HEC
- End With
- Dim retval_size As UInt32
- 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)
- handle.Close()
- If result Then Return (id_query.data(&HD9) = 1)
- Else
- Return False
- End If
- Catch ex As Exception
- End Try
- Return False
- End Function
- #End Region
- End Class
- End Namespace
- '############################# Comment l'utiliser ##############################
- MsgBox(HardwareInfos.Disk.IsSSDDrive.ToString())
- '##############################################################################
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement