Page 1 of 1
is drive a usb drive?
Posted: Thu Apr 21, 2016 3:51 pm
by jassing
Is there a way to detect if a drive is physically part of the machine (sata/ide) or connected via a USB / Firewire hub? (or internal/external)
Another related -- is there a way to tell if a drive is a solid state drive (vs mechanical)?
(bonus if there's a way to reliably read the drive's actual serial # (not volume id).
I would like to avoid using wsh for speed and possible policy conflicts; but if that's the only way; I will make adjustments.
Thanks.
-josh
Re: is drive a usb drive?
Posted: Thu Apr 21, 2016 3:55 pm
by RSBasic
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 1:49 am
by jassing
that's the volume id, not the drive's serial #.
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 10:59 am
by Marc56us
jassing wrote:Is there a way to detect if a drive is physically part of the machine (sata/ide) or connected via a USB / Firewire hub? (or internal/external)
GetDriveType function
Determines whether a disk drive is a removable, fixed, CD-ROM, RAM disk, or network drive.
https://msdn.microsoft.com/fr-fr/librar ... s.85).aspx
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 11:25 am
by DontTalkToMe
jassing wrote:
(bonus if there's a way to reliably read the drive's actual serial # (not volume id).
MS says
https://msdn.microsoft.com/en-us/librar ... 2147217396
This function returns the volume serial number that the operating system assigns when a hard disk is formatted. To programmatically obtain the hard disk's serial number that the manufacturer assigns, use the Windows Management Instrumentation (WMI) Win32_PhysicalMedia property SerialNumber.
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 2:58 pm
by blueb
Will this help?
Code: Select all
; German forum: http://www.purebasic.fr/german/viewtopic.php?t=1895&highlight=
; Author: DataMiner (updated for PB 4.00 by Andre)
; Date: 05. February 2005
; OS: Windows
; Demo: No
Define.l Serial, type, i
Define.s Lfwrk, FileSystem, VolName
For i=65 To 90
Lfwrk=Chr(i)+":\"
type =GetDriveType_(Lfwrk)
FileSystem = Space(256)
VolName= Space(256)
GetVolumeInformation_(@Lfwrk, @VolName, 255, @Serial, 0, 0, @FileSystem, 255)
Select type
Case 0
Debug Lfwrk+" The drive type cannot be determined."
Case 2
Debug Lfwrk+" = DRIVE_REMOVABLE, "+VolName+", "+FileSystem+", "+ Hex(Serial)
Case 3
Debug Lfwrk+" = DRIVE_FIXED, "+VolName+", "+FileSystem+", "+ Hex(Serial)
Case 4
Debug Lfwrk+" = DRIVE_REMOTE, "+VolName+", "+FileSystem+", "+ Hex(Serial)
Case 5
Debug Lfwrk+" = DRIVE_CDROM, "+VolName+", "+FileSystem+", "+ Hex(Serial)
Case 6
Debug Lfwrk+" = DRIVE_RAMDISK, "+VolName+", "+FileSystem+", "+ Hex(Serial)
EndSelect
Next
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 3:13 pm
by jassing
thanks; I'll use wmi... not ideal; but it'll work. thanks.
I'll poke around that too, to see if I can find a internal/external disk identifier too.
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 7:17 pm
by Thunder93
jassing wrote:Another related -- is there a way to tell if a drive is a solid state drive (vs mechanical)?
There is, I've thrown something together and is incomplete. Unfortunately I'm heading out for a few so here it is.
Code: Select all
#StorageDeviceTrimProperty = 8
Structure DEVICE_TRIM_DESCRIPTOR Align #PB_Structure_AlignC
Version.l
Size.l
TrimEnabled.b
EndStructure
#StorageDeviceSeekPenaltyProperty = 7
Structure DEVICE_SEEK_PENALTY_DESCRIPTOR Align #PB_Structure_AlignC
Version.l
Size.l
IncursSeekPenalty.b
EndStructure
Structure ATA_PASS_THROUGH_EX Align #PB_Structure_AlignC
length.w
AtaFlags.w
PathId.c
TargetId.c
Lun.c
ReservedAsUchar.c
DataTransferLength.l
TimeOutValue.l
ReservedAsUlong.l
DataBufferOffset.i
PreviousTaskFile.c[8]
CurrentTaskFile.c[8]
EndStructure
Structure ATAIdentifyDeviceQuery Align #PB_Structure_AlignC
header.ATA_PASS_THROUGH_EX
Data.w[256]
EndStructure
Structure STORAGE_PROPERTY_QUERY Align #PB_Structure_AlignC
PropertyId.l ;STORAGE_PROPERTY_ID
QueryType.l ;STORAGE_QUERY_TYPE
AdditionalParameters.l
EndStructure
#IOCTL_STORAGE_QUERY_PROPERTY = $2D1400
#IOCTL_ATA_PASS_THROUGH = $4D02C
#PropertyStandardQuery = 0
#ATA_FLAGS_DATA_IN = $02
bytesReturned.l
sDrive.s = "\\.\PhysicalDrive0"
hDevice = CreateFile_(sDrive,
0, ; No access To drive needed.
#FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null,
#OPEN_EXISTING, 0, #Null)
If hDevice <> #INVALID_HANDLE_VALUE
Debug sDrive
;Check TRIM -- should be Y for SSD
spqTrim.STORAGE_PROPERTY_QUERY
spqTrim\PropertyId = #StorageDeviceTrimProperty
spqTrim\QueryType = #PropertyStandardQuery
bytesReturned = 0
dtd.DEVICE_TRIM_DESCRIPTOR
If DeviceIoControl_(hDevice, #IOCTL_STORAGE_QUERY_PROPERTY,
@spqTrim, SizeOf(spqTrim), @dtd, SizeOf(dtd), @bytesReturned, #Null) And bytesReturned = SizeOf(dtd)
Debug "Retrieving TRIM"
If dtd\TrimEnabled = 1
Debug " Disk is SSD"
Else
Debug " Disk is non-SSD"
EndIf
Else
Debug "DeviceIoControl #1 failed: Error-Code: "+GetLastError_()
EndIf
;Check the seek-penalty value -- should be N For SSD
spqSeekP.STORAGE_PROPERTY_QUERY
spqSeekP\PropertyId = #StorageDeviceSeekPenaltyProperty
spqSeekP\QueryType = #PropertyStandardQuery
bytesReturned = 0
dspd.DEVICE_SEEK_PENALTY_DESCRIPTOR
If DeviceIoControl_(hDevice, #IOCTL_STORAGE_QUERY_PROPERTY,
@spqSeekP, SizeOf(spqSeekP), @dspd, SizeOf(dspd), @bytesReturned, #Null) And bytesReturned = SizeOf(dspd)
Debug "Retrieving SeekPenalty"
If dspd\IncursSeekPenalty = 0
Debug " Disk is SSD"
Else
Debug " Disk is non-SSD"
EndIf
Else
Debug #CRLF$+"DeviceIoControl #2 failed: Error-Code: "+GetLastError_()
EndIf
CloseHandle_(hDevice)
EndIf
; Administrative privileges required for the below code
hDevice = CreateFile_(sDrive,
#GENERIC_READ | #GENERIC_WRITE, ; Administrative privileges is required
#FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null,
#OPEN_EXISTING, 0, #Null)
If hDevice = -1 : Debug #CRLF$+"Requires Administrator Privileges for drive RPM reading." : End : EndIf
If hDevice <> #INVALID_HANDLE_VALUE
;Get drive's RPMs reading -- should be 1 for SSD
;CODE SOURCE: https://emoacht.wordpress.com/2012/11/06/csharp-ssd/
id_query.ATAIdentifyDeviceQuery
With id_query\header
\length = SizeOf(id_query\header)
\AtaFlags = #ATA_FLAGS_DATA_IN
\DataTransferLength = SizeOf(id_query\Data) * 2 ;Size of "data" in bytes
\TimeOutValue = 5 ;secs
\DataBufferOffset = OffsetOf(ATAIdentifyDeviceQuery\Data)
; \PreviousTaskFile = 0
; \CurrentTaskFile = 0
\CurrentTaskFile[6] = $EC ; ATA IDENTIFY DEVICE
EndWith
bytesReturned = 0 : dbsize.l = SizeOf(id_query)
If DeviceIoControl_(hDevice, #IOCTL_ATA_PASS_THROUGH,
@id_query, dbsize, @id_query, dbsize, @bytesReturned, #Null) ;And bytesReturned = SizeOf(id_query)
kNominalMediaRotRateWordIndex = 217
Debug "Retrieving Nominal media rotation rate"
If id_query\Data[kNominalMediaRotRateWordIndex] = 1
Debug "Disk is SSD"
Else
Debug "Disk is non-SSD"
EndIf
Else
Debug #CRLF$+"DeviceIoControl #3 failed: Error-Code: "+GetLastError_()
EndIf
CloseHandle_(hDevice)
EndIf
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 8:46 pm
by jassing
Thunder93 wrote:[I've thrown something together and is incomplete. Unfortunately I'm heading out for a few so here it is.
Thanks; I'll have a look at it tonight.
Re: is drive a usb drive?
Posted: Fri Apr 22, 2016 9:29 pm
by Thunder93
I've updated it. Administrator privileges isn't requirement for the first two methods. Third method, even though incomplete, does require Admin privileges.
Re: is drive a usb drive?
Posted: Sat Apr 23, 2016 12:08 am
by Thunder93
You want drive serials not volume Ids. You want to detect type of device (like USB or Firewire), and if its Solid-State drive. WMI isn't often appealing, so without WMI usage. Requires no administrator privileges.
GetDrivesINFO.pb - Revised on 2016-04-23 | #1
Code: Select all
IncludeFile "IsSSD.pbi"
Structure STORAGE_DEVICE_DESCRIPTOR ;Align #PB_Structure_AlignC
Version.l
Size.l
DeviceType.b
DeviceTypeModifier.b
RemovableMedia.b
CommandQueueing.b
VendorIdOffset.l
ProductIdOffset.l
ProductRevisionOffset.l
SerialNumberOffset.l
BusType.w
RawPropertiesLength.l
RawDeviceProperties.b
Reserved.b[1024]
EndStructure
#BusTypeUnknown = $00
#BusTypeScsi = $01
#BusTypeAtapi = $02
#BusTypeAta = $03
#BusType1394 = $04
#BusTypeSsa = $05
#BusTypeFibre = $06
#BusTypeUsb = $07
#BusTypeRAID = $08
#BusTypeiSCSI = $09
#BusTypeSas = $0A
#BusTypeSata = $0B
#BusTypeMaxReserved = $7F
#IOCTL_STORAGE_QUERY_PROPERTY = $2D1400
#IOCTL_STORAGE_GET_MEDIA_SERIAL_NUMBER = $2D0C10
strDrive.s
udtQuery.STORAGE_PROPERTY_QUERY
udtOut.STORAGE_DEVICE_DESCRIPTOR
OpenConsole()
PrintN("Enumerate devices")
For Drives=1 To 26
strDrive="\\.\" + Chr(64+Drives) + ":"
hDrive = CreateFile_(strDrive, 0,#FILE_SHARE_READ | #FILE_SHARE_WRITE, 0, #OPEN_EXISTING, 0, 0)
If hDrive <> #INVALID_HANDLE_VALUE
PrintN("--------------------------------------------------")
lngResult = DeviceIoControl_(hDrive, #IOCTL_STORAGE_QUERY_PROPERTY, udtQuery,SizeOf(udtQuery), @udtOut, SizeOf(udtOut), @dwOutBytes, 0)
If lngResult
PrintN("Drive " + Chr(64+Drives) + ": is a ")
Select(udtOut\Bustype)
Case #BusTypeUnknown
PrintN("Bustype: Unknown bus type")
Case #BusTypeScsi
PrintN("Bustype: SCSI bus")
Case #BusTypeAtapi
PrintN("Bustype: Atapi bus")
Case #BusTypeAta
PrintN("Bustype: Ata Device")
Case #BusType1394
PrintN("Bustype: IEEE-1394 bus")
Case #BusTypeSsa
PrintN("Bustype: SSA bus")
Case #BusTypeFibre
PrintN("Bustype: Fibre Channel bus")
Case #BusTypeUsb
PrintN("Bustype: USB bus")
Case #BusTypeRAID
PrintN("Bustype: RAID bus")
Case #BusTypeiSCSI
PrintN("Bustype: iSCSI bus")
Case #BusTypeSas
PrintN("Bustype: Sas bus")
Case #BusTypeSata
PrintN("Bustype: SATA bus")
Case #BusTypeMaxReserved
PrintN("Bustype: iSCSI bus")
Default
PrintN("Bustype = " + Str(udtOut\BusType))
EndSelect
If IsSSD(strDrive)
PrintN("Device is Solid-State Drive (SSD)")
EndIf
If udtout\RemovableMedia
PrintN("Device is Removable Media")
EndIf
If udtOut\ProductIdOffset > 0
PrintN("ProductID = " + PeekS(@udtOut + udtOut\ProductIdOffset, -1, #PB_Ascii))
EndIf
If udtOut\ProductRevisionOffset > 0
PrintN("ProductRevision = " + PeekS(@udtOut + udtOut\ProductRevisionOffset, -1, #PB_Ascii))
EndIf
If udtOut\VendorIdOffset > 0
PrintN("VendorID = " + PeekS(@udtOut + udtOut\VendorIdOffset, -1, #PB_Ascii))
EndIf
If udtOut\SerialNumberOffset > 0
Serial$ = Trim(PeekS(@udtOut + udtOut\SerialNumberOffset, -1, #PB_Ascii))
PrintN("Serial = " + Serial$)
EndIf
Else
PrintN("No Device-IO info available.. for "+Chr(64+Drives) + ":")
EndIf
ClearStructure(@udtQuery, STORAGE_PROPERTY_QUERY)
ClearStructure(@udtOut, STORAGE_DEVICE_DESCRIPTOR)
EndIf
CloseHandle_(hDrive)
Next Drives
wait.s=Input()
CloseConsole()
IsSSD.pbi
Code: Select all
#StorageDeviceSeekPenaltyProperty = 7
#StorageDeviceTrimProperty = 8
Structure DEVICE_TRIM_DESCRIPTOR Align #PB_Structure_AlignC
Version.l
Size.l
TrimEnabled.b
EndStructure
Structure DEVICE_SEEK_PENALTY_DESCRIPTOR Align #PB_Structure_AlignC
Version.l
Size.l
IncursSeekPenalty.b
EndStructure
Structure STORAGE_PROPERTY_QUERY Align #PB_Structure_AlignC
PropertyId.l ;STORAGE_PROPERTY_ID
QueryType.l ;STORAGE_QUERY_TYPE
AdditionalParameters.l
EndStructure
#IOCTL_STORAGE_QUERY_PROPERTY = $2D1400
#IOCTL_ATA_PASS_THROUGH = $4D02C
#PropertyStandardQuery = 0
Procedure.b IsSSD(sDrive.s)
Protected hDevice.i, bytesReturned.l, IsSSD.b
If sDrive = "" : ProcedureReturn 0 : EndIf
hDevice = CreateFile_(sDrive,
0, ; No access To drive needed.
#FILE_SHARE_READ | #FILE_SHARE_WRITE, #Null,
#OPEN_EXISTING, 0, #Null)
If hDevice <> #INVALID_HANDLE_VALUE
;Check TRIM -- should be Y for SSD
Protected spqTrim.STORAGE_PROPERTY_QUERY
spqTrim\PropertyId = #StorageDeviceTrimProperty
spqTrim\QueryType = #PropertyStandardQuery
bytesReturned = 0
Protected dtd.DEVICE_TRIM_DESCRIPTOR
If DeviceIoControl_(hDevice, #IOCTL_STORAGE_QUERY_PROPERTY,
@spqTrim, SizeOf(spqTrim), @dtd, SizeOf(dtd), @bytesReturned, #Null) And bytesReturned = SizeOf(dtd)
If dtd\TrimEnabled = 1 : IsSSD+1 : EndIf
EndIf
;Check the seek-penalty value -- should be N For SSD
Protected spqSeekP.STORAGE_PROPERTY_QUERY
spqSeekP\PropertyId = #StorageDeviceSeekPenaltyProperty
spqSeekP\QueryType = #PropertyStandardQuery
bytesReturned = 0
Protected dspd.DEVICE_SEEK_PENALTY_DESCRIPTOR
If DeviceIoControl_(hDevice, #IOCTL_STORAGE_QUERY_PROPERTY,
@spqSeekP, SizeOf(spqSeekP), @dspd, SizeOf(dspd), @bytesReturned, #Null) And bytesReturned = SizeOf(dspd)
If dspd\IncursSeekPenalty = 0 : IsSSD+2 : EndIf
EndIf
CloseHandle_(hDevice)
EndIf
ProcedureReturn IsSSD ; 0 = Non-SSD, 1 = SSD-byTRIM, 2 = SSD-bySEEKPENTALTY, 3 = SSD-byBOTH
EndProcedure
CompilerIf #PB_Compiler_IsMainFile
Debug IsSSD("\\.\C:")
CompilerEndIf
Re: is drive a usb drive?
Posted: Sat Apr 23, 2016 1:58 am
by jassing
... AWESOME!!!!
Thank you!!! That worked perfectly!!!!
Re: is drive a usb drive?
Posted: Sat Apr 23, 2016 3:42 am
by Thunder93
You're certainly welcome.
