<?xml version='1.0' encoding="utf-8"?>
      <rss version='2.0'>
      <channel>
      <title>Форум на Исходниках.RU</title>
      <link>https://forum.sources.ru</link>
      <description>Форум на Исходниках.RU</description>
      <generator>Форум на Исходниках.RU</generator>
  	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=415239&amp;view=findpost&amp;p=3808848</guid>
        <pubDate>Fri, 30 Aug 2019 19:04:03 +0000</pubDate>
        <title>Добраться до SMART накопителя.</title>
        <link>https://forum.sources.ru/index.php?showtopic=415239&amp;view=findpost&amp;p=3808848</link>
        <description><![CDATA[Сергей85: Родился в итоге рабочий модуль для разных семейств дисков.<br>
<br>
<div class='tag-code'><span class='pre_code'></span><div class='code  code_collapsed ' title='Подсветка синтаксиса доступна зарегистрированным участникам Форума.' style=''><div><div><ol type="1"><div class="code_line">/*</div><div class="code_line">Модуль тестировался на дисках:</div><div class="code_line">- Seagate: ST380215A, ST500DM002, ST3120213A, ST3320413AS, ST3320418AS, ST3250318AS, ST340014A;</div><div class="code_line">- Western Digital: WD5000AAKX, WD5000AADS;</div><div class="code_line">- Hitachi: HDT725032VLAT80;</div><div class="code_line">- Samsung: SP1203N, SV4012H.</div><div class="code_line">*/</div><div class="code_line">&nbsp;</div><div class="code_line">#include &quot;SMART.h&quot; //Для работы со S.M.A.R.T.</div><div class="code_line">#include &quot;WinInet.h&quot; //Для работы с сетевыми подключениями.</div><div class="code_line">&nbsp;</div><div class="code_line">//Индексы атрибута S.M.A.R.T. Hitachi искажает S.M.A.R.T.: смещение Value с 3 на RAW (+2), смещение WORST с 4 на 9.</div><div class="code_line">#define INDEX_ATTRIBUTE_INDEX &nbsp; &nbsp; &nbsp; 0 //Идентификатор атрибута.</div><div class="code_line">#define INDEX_ATTRIBUTE_STATUSFLAGS 1 //Тип атрибута.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//Второго индекса, реально, нет.</div><div class="code_line">#define INDEX_ATTRIBUTE_VALUE &nbsp; &nbsp; &nbsp; 3 //Текущее значение атрибута.</div><div class="code_line">#define INDEX_ATTRIBUTE_WORST &nbsp; &nbsp; &nbsp; 4 //Наихудшее зафиксированное значение. Погоровое значение - лежит в byteThreshold[1]. Для Hitachi - смещение по Threshold неизвестно.</div><div class="code_line">#define INDEX_ATTRIBUTE_RAW &nbsp; &nbsp; &nbsp; &nbsp; 5 //Абсолютное значение.</div><div class="code_line">&nbsp;</div><div class="code_line">//Типы атрибута S.M.A.R.T.</div><div class="code_line">#define PRE_FAILURE_WARRANTY &nbsp; &nbsp; &nbsp; &nbsp;0x1 //Критический (жизненно важный).</div><div class="code_line">#define ON_LINE_COLLECTION &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0x2 //Коллекция реального времени.</div><div class="code_line">#define PERFORMANCE_ATTRIBUTE &nbsp; &nbsp; &nbsp; 0x4 //Отражает производительность диска.</div><div class="code_line">#define ERROR_RATE_ATTRIBUTE &nbsp; &nbsp; &nbsp; &nbsp;0x8 //Отражает частоту появления ошибок.</div><div class="code_line">#define EVENT_COUNT_ATTRIBUTE &nbsp; &nbsp; &nbsp; 0x10 //Счетчик событий.</div><div class="code_line">#define SELF_PRESERVING_ATTRIBUTE &nbsp; 0x20 //Самосохраняющийся.</div><div class="code_line">&nbsp;</div><div class="code_line">//Ошибки драйвера накопителя.</div><div class="code_line">#define SMART_NO_ERROR &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;0 //No error</div><div class="code_line">#define SMART_IDE_ERROR &nbsp; &nbsp; &nbsp; &nbsp; 1 //Error from IDE controller</div><div class="code_line">#define SMART_INVALID_FLAG &nbsp; &nbsp; &nbsp;2 //Invalid command flag</div><div class="code_line">#define SMART_INVALID_COMMAND &nbsp; 3 //Invalid command byte</div><div class="code_line">#define SMART_INVALID_BUFFER &nbsp; &nbsp;4 //Bad buffer (null, invalid addr..)</div><div class="code_line">#define SMART_INVALID_DRIVE &nbsp; &nbsp; 5 //Drive number not valid</div><div class="code_line">#define SMART_INVALID_IOCTL &nbsp; &nbsp; 6 //Invalid IOCTL</div><div class="code_line">#define SMART_ERROR_NO_MEM &nbsp; &nbsp; &nbsp;7 //Could not lock user&#39;s buffer</div><div class="code_line">#define SMART_INVALID_REGISTER &nbsp;8 //Some IDE Register not valid</div><div class="code_line">#define SMART_NOT_SUPPORTED &nbsp; &nbsp; 9 //Invalid cmd flag set</div><div class="code_line">#define SMART_NO_IDE_DEVICE &nbsp; &nbsp; 10 //Cmd issued to device not present although drive number is valid.</div><div class="code_line">&nbsp;</div><div class="code_line">//Для получения информации о производителе накопителя. Возможно получение и типа.</div><div class="code_line">#define IOCTL_STORAGE_QUERY_PROPERTY &nbsp; CTL_CODE(IOCTL_STORAGE_BASE, 0x0500, METHOD_BUFFERED, FILE_ANY_ACCESS)</div><div class="code_line">&nbsp;</div><div class="code_line">DWORD g_dwBytes_Returned = 0; //Заглушка для выполнения функций.</div><div class="code_line">char g_cErrorText_Title[2] = &quot;32&quot;;</div><div class="code_line">int g_iErrorText_Icons = 32;</div><div class="code_line">&nbsp;</div><div class="code_line">bool bSystem_Test(void)</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp; &nbsp;int iDisk_Number = 0; //Номер накопителя.</div><div class="code_line">&nbsp;&nbsp; &nbsp;bool bNormal = true; //Флаг нормы теста. Лучше сразу сообщить обо всех ошибках, чтобы 100 раз не разбирать системник.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Сбор данных.</div><div class="code_line">&nbsp;&nbsp; &nbsp;AnsiString asDate = DateToStr(Date()); //Критический. Проверка работоспособности батареи BIOS как фактора записи корректной даты съема телеметрии, в т.ч. для печати протоколов.</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fHDA_Temperature = fGet_SMART_Parameter(iDisk_Number, 194); //Температура железа накопителя.</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fMechanical_Shock = fGet_SMART_Parameter(iDisk_Number, 191); //Счетчик механических ударов и внешних нагрузок.</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fDisk_Shift = fGet_SMART_Parameter(iDisk_Number, 220); //Критический. Показатель смещения блока дисков относительно шпинделя.</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fWrite_Error_Rate = fGet_SMART_Parameter(iDisk_Number, 200); //Количество сбойных секторов, вместо которых используется резервная область диска (программами проверки поверхности НЕ показываются.</div><div class="code_line">&nbsp;&nbsp; &nbsp;bool bLAN_Online = InternetGetConnectedState(&amp;g_dwBytes_Returned, 0); //Флаг &quot;хоть одно сетевое подключение подключено&quot;, т.е. передача данных возможна.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Параметры, отсутствующие в S.M.A.R.T. моего HDD WDC WD5000AAKX.</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fAirflow_Temperature = fGet_SMART_Parameter(iDisk_Number, 190);</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fHDD_Temperature = fGet_SMART_Parameter(iDisk_Number, 231);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fReallocated_Sectors_Count = fGet_SMART_Parameter(iDisk_Number, 5);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (asDate.SubString(asDate.Length()-3, 4).ToInt() &#60; 2019)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox(&quot;Дата установлена неправильно. Возможно, разряжена батарея BIOS на системной плате (как правило, CR2032). Программа завершает работу.&quot;, g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;bNormal = false;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (fHDA_Temperature &#62; 40)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Температура накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot; выше 40 градусов (&quot;+ FloatToStr(fHDA_Temperature) + &quot;). Почистите пылевые фильтры и вентиляторы ЭВМ, протрите накопитель от пыли и установите температуру помещения в соответствии с ТУ.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;//bNormal = false;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (fReallocated_Sectors_Count &#62; 200)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Параметр Reallocated Sectors Count накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot; выше 200 (&quot;+ FloatToStr(fReallocated_Sectors_Count) + &quot;). Рекомендуется неспешный поиск нового носителя под замену.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;//bNormal = false;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (fMechanical_Shock &#62; 0)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Параметр Mechanical Shock накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot; выше 0 (&quot;+ FloatToStr(fMechanical_Shock) + &quot;). Проверьте КПА на отсутствие вибраций, не допускайте ударов накопителя и КПА при эксплуатации и перевозке.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;//bNormal = false;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (fDisk_Shift &#62; 0)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Параметр Disk Shift накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot; выше 0 (&quot;+ FloatToStr(fDisk_Shift) + &quot;). Это означает, что произошло смещение блока дисков относительно шпинделя. Немедленно обесточьте КПА и приобретите новый носитель с целью переноса информации. С данной ошибкой диск быстро становится неработоспособным.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;bNormal = false;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (bLAN_Online)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox(&quot;Обнаружено сетевое подключение с состоянием \&quot;подключено\&quot;. С активным сетевым подключением работа с КПА невозможна из-за вероятности ложноотрицательных результатов.&quot;, g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;bNormal = false;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;return bNormal;</div><div class="code_line">}</div><div class="code_line">&nbsp;</div><div class="code_line">float fGet_SMART_Parameter(int iDisk_Number, int iParameter_Number)</div><div class="code_line">{</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Возвращение текущего значения параметра; без порогового значения, т.к. на разных носителях они разные.</div><div class="code_line">&nbsp;&nbsp; &nbsp;//В случае отсутствия параметра в S.M.A.R.T. данная функция вернет -2147483648, а не -2147483647 (что за глюки в разрядах у Builder - не знаю).</div><div class="code_line">&nbsp;&nbsp; &nbsp;float fResult = -2147483647;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;bool bData_Getted = false; //Флаг успешного получения информации S.M.A.R.T.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Для получения производителя диска.</div><div class="code_line">&nbsp;&nbsp; &nbsp;char cQuery[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0, 0};</div><div class="code_line">&nbsp;&nbsp; &nbsp;char cResult[512] = {0}; //Буфер для получения данных от DeviceIoControl.</div><div class="code_line">&nbsp;&nbsp; &nbsp;AnsiString asManufacturer_Disk = &quot;&quot;; //Строка с названием диска и его производителя.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;bool bWestern_Digital = false; //WDC содержит текущую температуру в RAW, а не в VALUE, - но нет флага отличия WDC от других дисков. В итоге температура на WDC отличается на +2.5 градуса, что критично.</div><div class="code_line">&nbsp;&nbsp; &nbsp;bool bHitachi = false; //Hitachi имеет другую структуру S.M.A.R.T. по температуре и расширенный ее съем.</div><div class="code_line">&nbsp;&nbsp; &nbsp;bool bSeagate = false; //Для кучи.</div><div class="code_line">&nbsp;&nbsp; &nbsp;bool bSamsung = false; //Для кучи.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Открытие физического диска.</div><div class="code_line">&nbsp;&nbsp; &nbsp;AnsiString asDrive_Path = &quot;\\.\PhysicalDrive&quot; + IntToStr(iDisk_Number);</div><div class="code_line">&nbsp;&nbsp; &nbsp;HANDLE hDrive_Physical = CreateFile(asDrive_Path.c_str(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (hDrive_Physical == INVALID_HANDLE_VALUE)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Не удалось открыть накопитель HDD №&quot; + IntToStr(iDisk_Number) + &quot; для получения его состояния. Проверьте наличие диска в системе и не занят ли он какой-либо программой (например, Victoria).&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return -1;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Определение производителя диска.</div><div class="code_line">&nbsp;&nbsp; &nbsp;bData_Getted = DeviceIoControl(hDrive_Physical, IOCTL_STORAGE_QUERY_PROPERTY, &amp;cQuery, sizeof(cQuery), &amp;cResult, sizeof(cResult), &amp;g_dwBytes_Returned, NULL);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (!bData_Getted) Application-&#62;MessageBox((&quot;Не удалось получить производителя накопителя №&quot; + IntToStr(iDisk_Number) + &quot;. Показания температуры в S.M.A.R.T. могут быть искажены.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp;else</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for (unsigned int iTemp=0; iTemp&#60;g_dwBytes_Returned; iTemp++)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (cResult[iTemp] != 0) asManufacturer_Disk += cResult[iTemp]; //Исключение терминаторов.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (asManufacturer_Disk.Pos(&quot;ST&quot;) != 0) bSeagate = true; //Лучше первым: вероятность наличия &quot;ST&quot; в других фирмах сохраняется.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (asManufacturer_Disk.Pos(&quot;WDC&quot;) != 0) bWestern_Digital = true;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (asManufacturer_Disk.Pos(&quot;HDT&quot;) != 0) bHitachi = true;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (asManufacturer_Disk.Pos(&quot;SP&quot;)!=0 || asManufacturer_Disk.Pos(&quot;SV&quot;)!=0) bSamsung = true;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;//ShowMessage(asManufacturer_Disk);</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Получение информации из S.M.A.R.T.</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Структура, посылаемая для получения данных в DeviceIoControl.</div><div class="code_line">&nbsp;&nbsp; &nbsp;const int iParams_To_DeviceIoControl_Size_const = sizeof(SENDCMDINPARAMS) - 1; //Количество байт данных при выполнении DeviceIoControl.</div><div class="code_line">&nbsp;&nbsp; &nbsp;SENDCMDINPARAMS Params_To_DeviceIoControl = {0}; //Структура, посылаемая для получения данных в DeviceIoControl.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE; //Размер буфера для получения атрибутов.</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES; //Запрос на чтение атрибутов.</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bSectorCountReg = 1; //Регистр количества секторов.</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bSectorNumberReg = 1; //Регистр номера сектора.</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bCylLowReg = SMART_CYL_LOW; //Младший разряд указателя на № цилиндра.</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bCylHighReg = SMART_CYL_HI; //Старший разряд указателя на № цилиндра.</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bDriveHeadReg = 0xA0|((static_cast&#60;BYTE&#62;(iDisk_Number)&amp;1)&#60;&#60;4); //Регистр диска/головки IDE.</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bCommandReg = SMART_CMD; //Команда IDE.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;const int iParams_From_DeviceIoControl_Size_const = sizeof(SENDCMDOUTPARAMS)-1 + READ_ATTRIBUTE_BUFFER_SIZE; &nbsp;//Количество байт данных при выполнении DeviceIoControl.</div><div class="code_line">&nbsp;&nbsp; &nbsp;SENDCMDOUTPARAMS Params_From_DeviceIoControl[iParams_From_DeviceIoControl_Size_const] = {0}; //Структура, принимающая данные из DeviceIoControl (данные).</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;bData_Getted = DeviceIoControl(hDrive_Physical,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SMART_RCV_DRIVE_DATA,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;Params_To_DeviceIoControl,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iParams_To_DeviceIoControl_Size_const,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;Params_From_DeviceIoControl,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iParams_From_DeviceIoControl_Size_const,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;g_dwBytes_Returned,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (!bData_Getted)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Не удалось получить текущие значения параметров S.M.A.R.T. накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot; для получения его состояния.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;CloseHandle(hDrive_Physical);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return -1;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Получение ошибок драйвера или интерфейса.</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (Params_From_DeviceIoControl-&#62;DriverStatus.bDriverError != 0)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Обнаружена ошибка драйвера накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot;. Данные S.M.A.R.T. могут быть искажены.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;CloseHandle(hDrive_Physical);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return -1;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (Params_From_DeviceIoControl-&#62;DriverStatus.bIDEError != 0)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Обнаружена ошибка интерфейса IDE накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot;. Данные S.M.A.R.T. могут быть искажены.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;CloseHandle(hDrive_Physical);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return -1;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Данные для получения пороговых значений параметров (подготовка).</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.cBufferSize = READ_THRESHOLD_BUFFER_SIZE;</div><div class="code_line">&nbsp;&nbsp; &nbsp;Params_To_DeviceIoControl.irDriveRegs.bFeaturesReg = READ_THRESHOLDS;</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;SENDCMDOUTPARAMS Thresholds_From_DeviceIoControl[iParams_From_DeviceIoControl_Size_const] = {0}; //Структура, принимающая данные из DeviceIoControl (пороговые значения).</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;g_dwBytes_Returned = 0;</div><div class="code_line">&nbsp;&nbsp; &nbsp;bData_Getted = DeviceIoControl(hDrive_Physical,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; SMART_RCV_DRIVE_DATA,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;Params_To_DeviceIoControl,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iParams_To_DeviceIoControl_Size_const,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;Thresholds_From_DeviceIoControl,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iParams_From_DeviceIoControl_Size_const,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &amp;g_dwBytes_Returned,</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;);</div><div class="code_line">&nbsp;&nbsp; &nbsp;if (!bData_Getted)</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Application-&#62;MessageBox((&quot;Не удалось получить пороговые значения параметров S.M.A.R.T. накопителя HDD №&quot; + IntToStr(iDisk_Number) + &quot; для получения его состояния.&quot;).c_str(), g_cErrorText_Title, g_iErrorText_Icons);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;CloseHandle(hDrive_Physical);</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return -1;</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;CloseHandle(hDrive_Physical);</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;//Работа с полученной информацией.</div><div class="code_line">&nbsp;&nbsp; &nbsp;BYTE *byteAttributes = static_cast&#60;BYTE*&#62;(Params_From_DeviceIoControl-&#62;bBuffer); //Обычно 0x0A.</div><div class="code_line">&nbsp;&nbsp; &nbsp;BYTE *byteThresholds = static_cast&#60;BYTE*&#62;(Thresholds_From_DeviceIoControl-&#62;bBuffer); //Обычно 0x01.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;for (int i=0; i&#60;54; ++i) //Кол-во параметров S.M.A.R.T. - 54.</div><div class="code_line">&nbsp;&nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;BYTE *byteAttribute = &amp;byteAttributes[2+i*12];</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;BYTE *byteThreshold = &amp;byteThresholds[2+i*12];</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;unsigned __int64 uiData = 0; //Флаг определения накопителя Hitachi, у которой смещен S.M.A.R.T. И Western Digital, у которых температура записывается не в Value, а в RAW.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (!byteAttribute[INDEX_ATTRIBUTE_INDEX]) continue; //Пропуск пустых атрибутов.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;CopyMemory(static_cast&#60;void*&#62;(&amp;uiData),static_cast&#60;void*&#62;(&amp;byteAttribute[INDEX_ATTRIBUTE_RAW]),sizeof(&amp;byteAttribute[INDEX_ATTRIBUTE_RAW])); //Определение uiData для флага Hitachi.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (byteAttribute[INDEX_ATTRIBUTE_INDEX] == iParameter_Number)</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (iParameter_Number==194 || iParameter_Number==190 || iParameter_Number==231) //Танцы с бубном с температурой. 194-й - самый приближенный к физической реальности: температура железа.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (bHitachi) //Преобразование для Hitachi. uiData показывает на Seagate и WDC просто температуру. Для Hitachi предполагается показ 3 температур как сумма минимальной, текущей и максимальной.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;fResult = byteAttribute[INDEX_ATTRIBUTE_RAW];</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//if (iParameter_Number==194) byteAttribute[INDEX_ATTRIBUTE_RAW+2] - минимальная температура, byteAttribute[INDEX_ATTRIBUTE_RAW+4] - максимальная.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else if (bWestern_Digital) fResult = byteAttribute[INDEX_ATTRIBUTE_RAW];</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else fResult = byteAttribute[INDEX_ATTRIBUTE_VALUE];</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if (fResult &#62; 80) fResult = (fResult-32) * 5/9; //Жесткие диски могут возвращать температуру и в кельвинах, и в цельсиях.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;else fResult = byteAttribute[INDEX_ATTRIBUTE_VALUE]; //Обычный параметр с одним значением.</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//byteAttribute[INDEX_ATTRIBUTE_WORST] - максимальное зафиксированное значение, byteThreshold[1] - пороговое. Пороговому - нет доверия.</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;break;</div><div class="code_line">&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div class="code_line">&nbsp;&nbsp; &nbsp;}</div><div class="code_line">&nbsp;</div><div class="code_line">&nbsp;&nbsp; &nbsp;return fResult;</div><div class="code_line">}</div></ol></div></div></div></div><script>preloadCodeButtons('1');</script>]]></description>
        <author>Сергей85</author>
        <category>Borland C++ Builder/Turbo C++ Explorer</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=415239&amp;view=findpost&amp;p=3807107</guid>
        <pubDate>Wed, 14 Aug 2019 16:59:49 +0000</pubDate>
        <title>Добраться до SMART накопителя.</title>
        <link>https://forum.sources.ru/index.php?showtopic=415239&amp;view=findpost&amp;p=3807107</link>
        <description><![CDATA[Сергей85: Единственный исходный код, который и был найден, и был переделан под билдер - ембаркадеровский последней версии. Был нерабочий и, как выяснилось, логически багнутый. Допилю за неделю - выложу здесь: до целого модуля разросся. Правда, только читать данные умеет.]]></description>
        <author>Сергей85</author>
        <category>Borland C++ Builder/Turbo C++ Explorer</category>
      </item>
	
      <item>
        <guid isPermaLink='true'>https://forum.sources.ru/index.php?showtopic=415239&amp;view=findpost&amp;p=3805304</guid>
        <pubDate>Mon, 29 Jul 2019 15:18:15 +0000</pubDate>
        <title>Добраться до SMART накопителя.</title>
        <link>https://forum.sources.ru/index.php?showtopic=415239&amp;view=findpost&amp;p=3805304</link>
        <description><![CDATA[Сергей85: Возможно ли это на BCB6? Примеры есть? В интернете с этим туго.]]></description>
        <author>Сергей85</author>
        <category>Borland C++ Builder/Turbo C++ Explorer</category>
      </item>
	
      </channel>
      </rss>
	