Guest User

Untitled

a guest
Jun 22nd, 2018
115
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.90 KB | None | 0 0
  1. //Open drive as such: "\?PhysicalDriveX" where X is the drive number
  2. //INFO: To get drive number from a logical drive letter, check this method:
  3. // (But keep in mind that a single logical drive, or a volume,
  4. // can span across several physical drives, as a "spanned volume.")
  5. // http://stackoverflow.com/a/11683906/843732
  6.  
  7. #include <WinIoCtl.h>
  8. #include <Ntddscsi.h>
  9.  
  10. DWORD bytesReturned;
  11.  
  12. //As an example, let's test 1st physical drive
  13. HANDLE hDevice = ::CreateFile(L"\\?\PhysicalDrive0",
  14. GENERIC_READ | GENERIC_WRITE, //We need write access to send ATA command to read RPMs
  15. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  16. OPEN_EXISTING, 0, NULL);
  17. if(hDevice != INVALID_HANDLE_VALUE)
  18. {
  19. //Check TRIM -- should be Y for SSD
  20. _tprintf(L"TRIM=");
  21.  
  22. STORAGE_PROPERTY_QUERY spqTrim;
  23. spqTrim.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceTrimProperty;
  24. spqTrim.QueryType = PropertyStandardQuery;
  25.  
  26. bytesReturned = 0;
  27. DEVICE_TRIM_DESCRIPTOR dtd = {0};
  28. if(::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
  29. &spqTrim, sizeof(spqTrim), &dtd, sizeof(dtd), &bytesReturned, NULL) &&
  30. bytesReturned == sizeof(dtd))
  31. {
  32. //Got it
  33. _tprintf(L"%s", dtd.TrimEnabled ? L"Y" : L"N");
  34. }
  35. else
  36. {
  37. //Failed
  38. int err = ::GetLastError();
  39. _tprintf(L"?");
  40. }
  41.  
  42.  
  43. //Check the seek-penalty value -- should be N for SSD
  44. _tprintf(L", seekPenalty=");
  45.  
  46. STORAGE_PROPERTY_QUERY spqSeekP;
  47. spqSeekP.PropertyId = (STORAGE_PROPERTY_ID)StorageDeviceSeekPenaltyProperty;
  48. spqSeekP.QueryType = PropertyStandardQuery;
  49.  
  50. bytesReturned = 0;
  51. DEVICE_SEEK_PENALTY_DESCRIPTOR dspd = {0};
  52. if(::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
  53. &spqSeekP, sizeof(spqSeekP), &dspd, sizeof(dspd), &bytesReturned, NULL) &&
  54. bytesReturned == sizeof(dspd))
  55. {
  56. //Got it
  57. _tprintf(L"%s", dspd.IncursSeekPenalty ? L"Y" : L"N");
  58. }
  59. else
  60. {
  61. //Failed
  62. int err = ::GetLastError();
  63. _tprintf(L"?");
  64. }
  65.  
  66.  
  67. //Get drive's RPMs reading -- should be 1 for SSD
  68. //CODE SOURCE: https://emoacht.wordpress.com/2012/11/06/csharp-ssd/
  69. _tprintf(L", RPM=");
  70.  
  71. ATAIdentifyDeviceQuery id_query;
  72. memset(&id_query, 0, sizeof(id_query));
  73.  
  74. id_query.header.Length = sizeof(id_query.header);
  75. id_query.header.AtaFlags = ATA_FLAGS_DATA_IN;
  76. id_query.header.DataTransferLength = sizeof(id_query.data);
  77. id_query.header.TimeOutValue = 5; //Timeout in seconds
  78. id_query.header.DataBufferOffset = offsetof(ATAIdentifyDeviceQuery, data[0]);
  79. id_query.header.CurrentTaskFile[6] = 0xec; // ATA IDENTIFY DEVICE
  80.  
  81. bytesReturned = 0;
  82. if(::DeviceIoControl(hDevice, IOCTL_ATA_PASS_THROUGH,
  83. &id_query, sizeof(id_query), &id_query, sizeof(id_query), &bytesReturned, NULL) &&
  84. bytesReturned == sizeof(id_query))
  85. {
  86. //Got it
  87.  
  88. //Index of nominal media rotation rate
  89. //SOURCE: http://www.t13.org/documents/UploadedDocuments/docs2009/d2015r1a-ATAATAPI_Command_Set_-_2_ACS-2.pdf
  90. // 7.18.7.81 Word 217
  91. //QUOTE: Word 217 indicates the nominal media rotation rate of the device and is defined in table:
  92. // Value Description
  93. // --------------------------------
  94. // 0000h Rate not reported
  95. // 0001h Non-rotating media (e.g., solid state device)
  96. // 0002h-0400h Reserved
  97. // 0401h-FFFEh Nominal media rotation rate in rotations per minute (rpm)
  98. // (e.g., 7 200 rpm = 1C20h)
  99. // FFFFh Reserved
  100. #define kNominalMediaRotRateWordIndex 217
  101. _tprintf(L"%d", (UINT)id_query.data[kNominalMediaRotRateWordIndex]);
  102. }
  103. else
  104. {
  105. //Failed
  106. int err = ::GetLastError();
  107. _tprintf(L"?");
  108. }
  109.  
  110.  
  111. _tprintf(L"n");
  112. ::CloseHandle(hDevice);
  113. }
  114.  
  115. #ifndef StorageDeviceTrimProperty
  116. #define StorageDeviceTrimProperty 8
  117. #endif
  118.  
  119. #ifndef DEVICE_TRIM_DESCRIPTOR
  120. typedef struct _DEVICE_TRIM_DESCRIPTOR {
  121. DWORD Version;
  122. DWORD Size;
  123. BOOLEAN TrimEnabled;
  124. } DEVICE_TRIM_DESCRIPTOR, *PDEVICE_TRIM_DESCRIPTOR;
  125. #endif
  126.  
  127.  
  128. #ifndef StorageDeviceSeekPenaltyProperty
  129. #define StorageDeviceSeekPenaltyProperty 7
  130. #endif
  131.  
  132. #ifndef DEVICE_SEEK_PENALTY_DESCRIPTOR
  133. typedef struct _DEVICE_SEEK_PENALTY_DESCRIPTOR {
  134. DWORD Version;
  135. DWORD Size;
  136. BOOLEAN IncursSeekPenalty;
  137. } DEVICE_SEEK_PENALTY_DESCRIPTOR, *PDEVICE_SEEK_PENALTY_DESCRIPTOR;
  138. #endif
  139.  
  140.  
  141. struct ATAIdentifyDeviceQuery
  142. {
  143. ATA_PASS_THROUGH_EX header;
  144. WORD data[256];
  145. };
  146.  
  147. Samsung SSD 256GB: TRIM=Y, seekPenalty=N, RPM=1
  148. Samsung SSD 500GB: TRIM=Y, seekPenalty=N, RPM=1
  149. PCIs SSD: TRIM=Y, seekPenalty=?, RPM=0
  150. Internal WD HDD: TRIM=N, seekPenalty=?, RPM=0
  151. External WD HDD: TRIM=?, seekPenalty=?, RPM=?
  152. External Cavalry HDD: TRIM=?, seekPenalty=Y, RPM=?
Add Comment
Please, Sign In to add comment