|
Registriert seit: 11. Apr 2009 578 Beiträge Delphi 12 Athens |
#7
Ja, jetzt sind ja schlappe 4 Jährchen vergangen, ob Mattze immer noch über der Antwort brütet?
Jedenfalls brauchte ich auch eine funktionierende SSD-Erkennung und habe mich mal ungeniert ![]() Das funktioniert auch, hat aber einen großen Pferdefuß: Man braucht Administratorrechte für das CreateFile. Kennt jemand eine Lösung, wo es auch ohne geht? Oder ist das prinzipiell unmöglich?
Delphi-Quellcode:
uses Winapi.Windows,System.SysUtils,System.Types,System.UITypes,Vcl.Dialogs;
type { ATA_PASS_THROUGH_EX } _ATA_PASS_THROUGH_EX = packed record Length: Word; AtaFlags: Word; PathId: UCHAR; TargetId: UCHAR; Lun: UCHAR; ReservedAsUchar: UCHAR; DataTransferLength: ULONG; TimeOutValue: ULONG; ReservedAsUlong: ULONG; DataBufferOffset: ULONG_PTR; PreviousTaskFile: array [0..7] of UCHAR; CurrentTaskFile: array [0..7] of UCHAR; end; {$EXTERNALSYM _ATA_PASS_THROUGH_EX} ATA_PASS_THROUGH_EX = _ATA_PASS_THROUGH_EX; {$EXTERNALSYM ATA_PASS_THROUGH_EX} TAtaPassThroughEx = _ATA_PASS_THROUGH_EX; PAtaPassThroughEx = ^TAtaPassThroughEx; { ATAIdentifyDeviceQuery } TATAIdentifyDeviceQuery = packed record header: ATA_PASS_THROUGH_EX; data: array [0..255] of Word; end; const {$IF RTLVersion < 22.0} FILE_DEVICE_CONTROLLER = $00000004; {$EXTERNALSYM FILE_DEVICE_CONTROLLER} FILE_READ_ACCESS = $0001; {$EXTERNALSYM FILE_READ_ACCESS} FILE_WRITE_ACCESS = $0002; {$EXTERNALSYM FILE_WRITE_ACCESS} {$IFEND} ATA_FLAGS_DRDY_REQUIRED = $01; ATA_FLAGS_DATA_IN = $02; ATA_FLAGS_DATA_OUT = $04; ATA_FLAGS_48BIT_COMMAND = $08; ATA_FLAGS_USE_DMA = $10; ATA_FLAGS_NO_MULTIPLE = $20; IOCTL_SCSI_BASE = FILE_DEVICE_CONTROLLER; IOCTL_ATA_PASS_THROUGH = (IOCTL_SCSI_BASE shl 16) or ((FILE_READ_ACCESS or FILE_WRITE_ACCESS) shl 14) or ($040B shl 2) or (METHOD_BUFFERED); {$IF RTLversion < 22.0} const FILE_READ_DATA = $0001; {$EXTERNALSYM FILE_READ_DATA} FILE_READ_ATTRIBUTES = $0080; {$EXTERNALSYM FILE_READ_ATTRIBUTES} FILE_DEVICE_MASS_STORAGE = $0000002d; {$EXTERNALSYM FILE_DEVICE_MASS_STORAGE} IOCTL_STORAGE_BASE = FILE_DEVICE_MASS_STORAGE; {$EXTERNALSYM IOCTL_STORAGE_BASE} FILE_ANY_ACCESS = 0; {$EXTERNALSYM FILE_ANY_ACCESS} METHOD_BUFFERED = 0; {$EXTERNALSYM METHOD_BUFFERED} IOCTL_STORAGE_QUERY_PROPERTY = (IOCTL_STORAGE_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or ($0500 shl 2) or (METHOD_BUFFERED); {$EXTERNALSYM IOCTL_STORAGE_QUERY_PROPERTY} {$IFEND} type { STORAGE_PROPERTY_ID } _STORAGE_PROPERTY_ID = ( StorageDeviceProperty = 0, StorageAdapterProperty = 1, StorageDeviceIdProperty = 2, StorageDeviceUniqueIdProperty = 3, StorageDeviceWriteCacheProperty = 4, StorageMiniportProperty = 5, StorageAccessAlignmentProperty = 6, StorageDeviceSeekPenaltyProperty = 7, StorageDeviceTrimProperty = 8, StorageDeviceWriteAggregationProperty = 9, StorageDeviceDeviceTelemetryProperty = 10 ); {$EXTERNALSYM _STORAGE_PROPERTY_ID} STORAGE_PROPERTY_ID = _STORAGE_PROPERTY_ID; {$EXTERNALSYM STORAGE_PROPERTY_ID} TStoragePropertyId = _STORAGE_PROPERTY_ID; PStoragePropertyId = ^TStoragePropertyId; { STORAGE_QUERY_TYPE } _STORAGE_QUERY_TYPE = ( PropertyStandardQuery = 0, PropertyExistsQuery = 1, PropertyMaskQuery = 2, PropertyQueryMaxDefined = 3 ); {$EXTERNALSYM _STORAGE_QUERY_TYPE} STORAGE_QUERY_TYPE = _STORAGE_QUERY_TYPE; {$EXTERNALSYM STORAGE_QUERY_TYPE} TStorageQueryType = _STORAGE_QUERY_TYPE; PStorageQueryType = ^TStorageQueryType; { STORAGE_PROPERTY_QUERY } _STORAGE_PROPERTY_QUERY = packed record PropertyId: DWORD; QueryType: DWORD; AdditionalParameters: array[0..9] of Byte; end; {$EXTERNALSYM _STORAGE_PROPERTY_QUERY} STORAGE_PROPERTY_QUERY = _STORAGE_PROPERTY_QUERY; {$EXTERNALSYM STORAGE_PROPERTY_QUERY} TStoragePropertyQuery = _STORAGE_PROPERTY_QUERY; PStoragePropertyQuery = ^TStoragePropertyQuery; { DEVICE_SEEK_PENALTY_DESCRIPTOR } _DEVICE_SEEK_PENALTY_DESCRIPTOR = packed record Version: DWORD; Size: DWORD; IncursSeekPenalty: ByteBool; Reserved: array[0..2] of Byte; end; {$EXTERNALSYM _DEVICE_SEEK_PENALTY_DESCRIPTOR} DEVICE_SEEK_PENALTY_DESCRIPTOR = _DEVICE_SEEK_PENALTY_DESCRIPTOR; {$EXTERNALSYM DEVICE_SEEK_PENALTY_DESCRIPTOR} TDeviceSeekPenaltyDescriptor = _DEVICE_SEEK_PENALTY_DESCRIPTOR; PDeviceSeekPenaltyDescriptor = ^TDeviceSeekPenaltyDescriptor; type { DISK_EXTENT } _DISK_EXTENT = packed record DiskNumber: DWORD; StartingOffset: LARGE_INTEGER; ExtentLength: LARGE_INTEGER; Reserved: array [0..3] of Byte; end; {$EXTERNALSYM _DISK_EXTENT} DISK_EXTENT = _DISK_EXTENT; {$EXTERNALSYM DISK_EXTENT} TDiskExtent = _DISK_EXTENT; PDiskExtent = ^TDiskExtent; { VOLUME_DISK_EXTENTS } _VOLUME_DISK_EXTENTS = packed record NumberOfDiskExtents: DWORD; Reserved: array [0..3] of Byte; Extents: array [0..0] of DISK_EXTENT; end; {$EXTERNALSYM _VOLUME_DISK_EXTENTS} VOLUME_DISK_EXTENTS = _VOLUME_DISK_EXTENTS; {$EXTERNALSYM VOLUME_DISK_EXTENTS} TVolumeDiskExtents = VOLUME_DISK_EXTENTS; PVolumeDiskExtents = ^TVolumeDiskExtents; {$IF RTLVersion < 22.0} const IOCTL_VOLUME_BASE = $00000056; {$EXTERNALSYM IOCTL_VOLUME_BASE} IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS = (IOCTL_VOLUME_BASE shl 16) or (FILE_ANY_ACCESS shl 14) or (0 shl 2) or (METHOD_BUFFERED); {$EXTERNALSYM IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS} {$IFEND} function HasNominalMediaRotationRate(const PhysicalDrivePath: String): Boolean; function HasNoSeekPenalty(const PhysicalDrivePath: String): Boolean; procedure PathnameToPhysicalDriveNumber(const Path: String; var PhysicalDrives: TIntegerDynArray); function IstSSD(LW:Char):Boolean; implementation function HasNominalMediaRotationRate(const PhysicalDrivePath: String): Boolean; var h: THandle; ATAIdentifyDeviceQuery: TATAIdentifyDeviceQuery; RSize: DWORD; begin h := CreateFile(PChar(PhysicalDrivePath),GENERIC_READ or GENERIC_WRITE, FILE_SHARE_READ or FILE_SHARE_WRITE,nil, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if h = INVALID_HANDLE_VALUE then begin RaiseLastOSError; end; try FillChar(ATAIdentifyDeviceQuery,SizeOf(ATAIdentifyDeviceQuery),0); with ATAIdentifyDeviceQuery do begin header.Length := SizeOf(header); header.AtaFlags := ATA_FLAGS_DATA_IN; header.DataTransferLength := SizeOf(data); header.TimeOutValue := 3; // sec header.DataBufferOffset := SizeOf(header); header.CurrentTaskFile[6] := $EC; // ATA IDENTIFY DEVICE command end; RSize := 0; if DeviceIoControl(h,IOCTL_ATA_PASS_THROUGH, @ATAIdentifyDeviceQuery,SizeOf(ATAIdentifyDeviceQuery), @ATAIdentifyDeviceQuery,SizeOf(ATAIdentifyDeviceQuery), RSize,nil) = False then begin RaiseLastOSError; end; Result := (ATAIdentifyDeviceQuery.data[217] = 1); finally CloseHandle(h); end; end; function HasNoSeekPenalty(const PhysicalDrivePath: String): Boolean; var h :THandle; StoragePropertyQuery: TStoragePropertyQuery; DeviceSeekPenaltyDescriptor: TDeviceSeekPenaltyDescriptor; RSize: DWORD; begin h := CreateFile(PChar(PhysicalDrivePath),FILE_READ_ATTRIBUTES, FILE_SHARE_READ or FILE_SHARE_WRITE,nil, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if h = INVALID_HANDLE_VALUE then begin RaiseLastOSError; end; try with StoragePropertyQuery do begin PropertyId := Ord(StorageDeviceSeekPenaltyProperty); QueryType := Ord(PropertyStandardQuery); end; FillChar(DeviceSeekPenaltyDescriptor,SizeOf(DeviceSeekPenaltyDescriptor),0); RSize := 0; if DeviceIoControl(h,IOCTL_STORAGE_QUERY_PROPERTY, @StoragePropertyQuery,SizeOf(StoragePropertyQuery), @DeviceSeekPenaltyDescriptor,SizeOf(DeviceSeekPenaltyDescriptor), RSize,nil) = False then begin RaiseLastOSError; end; Result := not DeviceSeekPenaltyDescriptor.IncursSeekPenalty; finally CloseHandle(h); end; end; procedure PathnameToPhysicalDriveNumber(const Path: String; var PhysicalDrives: TIntegerDynArray); var h: THandle; I: Integer; MountPoint: String; VolumeName: String; Size: DWORD; RSize: DWORD; P: PVolumeDiskExtents; lpFilePart : PWideChar; lpBuffer : PWideChar; begin SetLength(PhysicalDrives,0); lpBuffer := nil; { Pathname to mount point } Size := GetFullPathName(PWideChar(Path),0,lpBuffer,lpFilePart); SetLength(MountPoint,Size); if GetVolumePathName(PAnsiChar(Path),PAnsiChar(MountPoint),Size) = False then begin RaiseLastOSError; end; SetLength(MountPoint,StrLen(PWideChar(MountPoint))); { Mount point to logical volume name } Size := 50; // Recomended size from http://msdn.microsoft.com/en-us/library/windows/desktop/aa364994.aspx SetLength(VolumeName,Size); if GetVolumeNameForVolumeMountPoint(PAnsiChar(MountPoint),PAnsiChar(VolumeName),Size) = False then begin RaiseLastOSError; end; SetLength(VolumeName,StrLen(PChar(VolumeName))); VolumeName := ExcludeTrailingPathDelimiter(VolumeName); { Open volume } h := CreateFile(PChar(VolumeName),FILE_READ_ATTRIBUTES, FILE_SHARE_READ or FILE_SHARE_WRITE,nil, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0); if h = INVALID_HANDLE_VALUE then begin RaiseLastOSError; end; try Size := SizeOf(TVolumeDiskExtents); P := AllocMem(Size); try FillChar(P^,Size,0); RSize := 0; if DeviceIoControl(h,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nil,0, P,Size, RSize,nil) = False then begin if GetLastError <> ERROR_MORE_DATA then begin RaiseLastOSError; end; Size := SizeOf(TVolumeDiskExtents) + SizeOf(DISK_EXTENT) * (P^.NumberOfDiskExtents - 1); ReallocMem(P,Size); FillChar(P^,Size,0); if DeviceIoControl(h,IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, nil,0, P,Size, RSize,nil) = False then begin RaiseLastOSError; end; end; SetLength(PhysicalDrives,P^.NumberOfDiskExtents); for I := 0 to P^.NumberOfDiskExtents - 1 do begin PhysicalDrives[I] := P^.Extents[I].DiskNumber; end; finally FreeMem(P); end; finally CloseHandle(h); end; end; function IstSSD(LW:Char):Boolean; var Index: Integer; Filename: String; PhysicalDrives: TIntegerDynArray; PhysicalDrivePath: String; IsSSD: Boolean; begin Result := False; Filename := LW + ':\'; SetLength(PhysicalDrives,0); PathnameToPhysicalDriveNumber(Filename,PhysicalDrives); try IsSSD := False; for Index := Low(PhysicalDrives) to High(PhysicalDrives) do begin PhysicalDrivePath := Format('\\.\PhysicalDrive%d',[PhysicalDrives[Index]]); try IsSSD := IsSSD or HasNominalMediaRotationRate(PhysicalDrivePath); except { Ignore } end; if IsSSD = True then begin exit(True); end; end; finally SetLength(PhysicalDrives,0); end; end; end. |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |