Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //Open drive as such: "\?PhysicalDriveX" where X is the drive number
- //INFO: To get drive number from a logical drive letter, check this method:
- // (But keep in mind that a single logical drive, or a volume,
- // can span across several physical drives, as a "spanned volume.")
- // http://stackoverflow.com/a/11683906/843732
- #include <WinIoCtl.h>
- #include <Ntddscsi.h>
- DWORD bytesReturned;
- //As an example, let's test 1st physical drive
- HANDLE hDevice = ::CreateFile(L"\\?\PhysicalDrive0",
- GENERIC_READ | GENERIC_WRITE, //We need write access to send ATA command to read RPMs
- FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
- OPEN_EXISTING, 0, NULL);
- if(hDevice != INVALID_HANDLE_VALUE)
- {
- //Check TRIM -- should be Y for SSD
- _tprintf(L"TRIM=");
- STORAGE_PROPERTY_QUERY spqTrim;
- spqTrim.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceTrimProperty;
- spqTrim.QueryType = PropertyStandardQuery;
- bytesReturned = 0;
- DEVICE_TRIM_DESCRIPTOR dtd = {0};
- if(::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
- &spqTrim, sizeof(spqTrim), &dtd, sizeof(dtd), &bytesReturned, NULL) &&
- bytesReturned == sizeof(dtd))
- {
- //Got it
- _tprintf(L"%s", dtd.TrimEnabled ? L"Y" : L"N");
- }
- else
- {
- //Failed
- int err = ::GetLastError();
- _tprintf(L"?");
- }
- //Check the seek-penalty value -- should be N for SSD
- _tprintf(L", seekPenalty=");
- STORAGE_PROPERTY_QUERY spqSeekP;
- spqSeekP.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceSeekPenaltyProperty;
- spqSeekP.QueryType = PropertyStandardQuery;
- bytesReturned = 0;
- DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {0};
- if(::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
- &spqSeekP, sizeof(spqSeekP), &dspd, sizeof(dspd), &bytesReturned, NULL) &&
- bytesReturned == sizeof(dspd))
- {
- //Got it
- _tprintf(L"%s", dspd.IncursSeekPenalty ? L"Y" : L"N");
- }
- else
- {
- //Failed
- int err = ::GetLastError();
- _tprintf(L"?");
- }
- //Get drive's RPMs reading -- should be 1 for SSD
- //CODE SOURCE: https://emoacht.wordpress.com/2012/11/06/csharp-ssd/
- _tprintf(L", RPM=");
- ATAIdentifyDeviceQuery id_query;
- memset(&id_query, 0, sizeof(id_query));
- id_query.header.Length = sizeof(id_query.header);
- id_query.header.AtaFlags = ATA_FLAGS_DATA_IN;
- id_query.header.DataTransferLength = sizeof(id_query.data);
- id_query.header.TimeOutValue = 5; //Timeout in seconds
- id_query.header.DataBufferOffset = offsetof(ATAIdentifyDeviceQuery, data[0]);
- id_query.header.CurrentTaskFile[6] = 0xec; // ATA IDENTIFY DEVICE
- bytesReturned = 0;
- if(::DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH,
- &id_query, sizeof(id_query), &id_query, sizeof(id_query), &bytesReturned, NULL) &&
- bytesReturned == sizeof(id_query))
- {
- //Got it
- //Index of nominal media rotation rate
- //SOURCE: http://www.t13.org/documents/UploadedDocuments/docs2009/d2015r1a-ATAATAPI_Command_Set_-_2_ACS-2.pdf
- // 7.18.7.81 Word 217
- //QUOTE: Word 217 indicates the nominal media rotation rate of the device and is defined in table:
- // Value Description
- // --------------------------------
- // 0000h Rate not reported
- // 0001h Non-rotating media (e.g., solid state device)
- // 0002h-0400h Reserved
- // 0401h-FFFEh Nominal media rotation rate in rotations per minute (rpm)
- // (e.g., 7 200 rpm = 1C20h)
- // FFFFh Reserved
- #define kNominalMediaRotRateWordIndex 217
- _tprintf(L"%d", (UINT)id_query.data[kNominalMediaRotRateWordIndex]);
- }
- else
- {
- //Failed
- int err = ::GetLastError();
- _tprintf(L"?");
- }
- _tprintf(L"n");
- ::CloseHandle(hDevice);
- }
- #ifndef StorageDeviceTrimProperty
- #define StorageDeviceTrimProperty 8
- #endif
- #ifndef DEVICE_TRIM_DESCRIPTOR
- typedef struct _DEVICE_TRIM_DESCRIPTOR {
- DWORD Version;
- DWORD Size;
- BOOLEAN TrimEnabled;
- } DEVICE_TRIM_DESCRIPTOR, *PDEVICE_TRIM_DESCRIPTOR;
- #endif
- #ifndef StorageDeviceSeekPenaltyProperty
- #define StorageDeviceSeekPenaltyProperty 7
- #endif
- #ifndef DEVICE_SEEK_PENALTY_DESCRIPTOR
- typedef struct _DEVICE_SEEK_PENALTY_DESCRIPTOR {
- DWORD Version;
- DWORD Size;
- BOOLEAN IncursSeekPenalty;
- } DEVICE_SEEK_PENALTY_DESCRIPTOR, *PDEVICE_SEEK_PENALTY_DESCRIPTOR;
- #endif
- struct ATAIdentifyDeviceQuery
- {
- ATA_PASS_THROUGH_EX header;
- WORD data[256];
- };
- Samsung SSD 256GB: TRIM=Y, seekPenalty=N, RPM=1
- Samsung SSD 500GB: TRIM=Y, seekPenalty=N, RPM=1
- PCIs SSD: TRIM=Y, seekPenalty=?, RPM=0
- Internal WD HDD: TRIM=N, seekPenalty=?, RPM=0
- External WD HDD: TRIM=?, seekPenalty=?, RPM=?
- External Cavalry HDD: TRIM=?, seekPenalty=Y, RPM=?
Add Comment
Please, Sign In to add comment