Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.86/43: Рейтинг темы: голосов - 43, средняя оценка - 4.86
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128

Получение HDD S.M.A.R.T

04.06.2014, 21:10. Показов 8648. Ответов 1
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Помогите понять почему программа получает не все атрибуты SMART жесткого диска, да еще и со значениями отличными от AIDA (Everest).

Как источник использовал статью и msdn.

Код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
struct attribute {
    int id;
    __int64 value;
    __int64 worst;
    __int64 threshold;
    __int64 statusFlags;
    __int64 raw;
    AnsiString hexRaw;
} attribute;
 
typedef struct _DRIVEATTRIBUTESHEADER {                                         // Заголовок атрибутов
    WORD wRevision;                                                             // Номер версии
    BYTE bData[1];                                                              // Данные
} DRIVEATTRIBUTESHEADER, *LPDRIVEATTRIBUTESHEADER;
 
typedef struct _DRIVEATTRIBUTES {                                               // Атрибуты
    BYTE bAttrID;                                                               // Идентификатор атрибута
    WORD wStatusFlags;                                                          // Тип атрибута (критический, счетчик ошибок и т.д.)
    BYTE bAttrValue;                                                            // Значение
    BYTE bWorstValue;                                                           // Худшее зафиксированное значение
    BYTE bRawValue[6];                                                          // Ненормализованное значение
    BYTE bReserved;
} DRIVEATTRIBUTES, *LPDRIVEATTRIBUTES;
 
typedef struct _DRIVETHRESHOLDS {                                               // Пороговое значение атрибутов
    BYTE bAttrID;                                                               // Идентификатор атрибута
    BYTE bWarrantyThreshold;                                                    // Значение
    BYTE bReserved[10];
} DRIVETHRESHOLDS, *LPDRIVETHRESHOLDS;
 
void GetSMART()
{
// Открытие физического диска
    int driveNumber = 0;
    String drivePath = "\\\\.\\PhysicalDrive" + IntToStr(driveNumber);
    HANDLE hPhysicalDrive = CreateFile(drivePath.c_str(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
    if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
        ShowMessage(SysErrorMessage(GetLastError()) + "Can't open physDrive!"); ///Error
        return;
    }
// Получение S.M.A.R.T.
    bool isGetData;
    DWORD bytesReturned;
    const int inParamsSize = sizeof(SENDCMDINPARAMS)-1;
    SENDCMDINPARAMS inParams = {0};
    inParams.cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE;                          // Размер буфера для получения атрибутов
    inParams.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES;                        // Запрос на чтение атрибутов
    inParams.irDriveRegs.bSectorCountReg = 1;                                   // Регистр количества секторов
    inParams.irDriveRegs.bSectorNumberReg = 1;                                  // Регистр номера сектора
    inParams.irDriveRegs.bCylLowReg = SMART_CYL_LOW;                            // Младший разряд, указывающий на номер цилиндра
    inParams.irDriveRegs.bCylHighReg = SMART_CYL_HI;                            // Старший разряд, указывающий на номер цилиндра
    inParams.irDriveRegs.bDriveHeadReg = 0xA0|(((BYTE)driveNumber & 1)<<4);     // Регистр диска/головки IDE
    inParams.irDriveRegs.bCommandReg = SMART_CMD;                               // Команда IDE
    const int outParamsSize = sizeof(SENDCMDOUTPARAMS)-1 + READ_ATTRIBUTE_BUFFER_SIZE;
    SENDCMDOUTPARAMS outParamsAttributes[outParamsSize] = {0};
    isGetData = DeviceIoControl(hPhysicalDrive,SMART_RCV_DRIVE_DATA,
        &inParams,inParamsSize,&outParamsAttributes,outParamsSize,&bytesReturned,NULL);
    if (!isGetData) {
            ShowMessage(SysErrorMessage(GetLastError()) + " Can't get S.M.A.R.T. attributes!"); ///Error
            CloseHandle(hPhysicalDrive);
            return;
    }
    inParams.cBufferSize = READ_THRESHOLD_BUFFER_SIZE;
    inParams.irDriveRegs.bFeaturesReg = READ_THRESHOLDS;
    SENDCMDOUTPARAMS outParamsThresholds[outParamsSize] = {0};
    isGetData = DeviceIoControl(hPhysicalDrive,SMART_RCV_DRIVE_DATA,
        &inParams,inParamsSize,&outParamsThresholds,outParamsSize,&bytesReturned,NULL);
    if (!isGetData) {
            ShowMessage(SysErrorMessage(GetLastError()) + " Can't get S.M.A.R.T. thresholds!"); ///Error
            CloseHandle(hPhysicalDrive);
            return;
    }
    CloseHandle(hPhysicalDrive);
    LPDRIVEATTRIBUTESHEADER lpAttributesHeader = (LPDRIVEATTRIBUTESHEADER)(outParamsAttributes->bBuffer);
    LPDRIVEATTRIBUTES lpAttributes = (LPDRIVEATTRIBUTES)(lpAttributesHeader->bData);
    LPDRIVEATTRIBUTESHEADER lpThresholdsHeader = (LPDRIVEATTRIBUTESHEADER)(outParamsThresholds->bBuffer);
    LPDRIVETHRESHOLDS lpThresholds = (LPDRIVETHRESHOLDS)(lpThresholdsHeader->bData);
 
    const int maxAttributes = 256;
    for (int i=0; i < maxAttributes; i++) {
        if(lpAttributes[i].bAttrID == 0)                                        // Пропуск пустых атрибутов
            continue;
        struct attribute attr;
 
 
        attr.id         = lpAttributes[i].bAttrID;
        attr.value          = lpAttributes[i].bAttrValue;
        attr.worst          = lpAttributes[i].bWorstValue;
        attr.statusFlags    = lpAttributes[i].wStatusFlags;
        attr.threshold      = lpThresholds[i].bWarrantyThreshold;
        attr.raw            = (__int64)lpAttributes[i].bRawValue;
        attr.hexRaw.printf("%X",lpAttributes[i].bRawValue);
 
        ShowMessage("id:"+IntToStr(attr.id)+" val:"+IntToStr(attr.value)+" worst:"+IntToStr(attr.worst)+" statFlag:"+IntToStr(attr.statusFlags)+" Thres:"+IntToStr(attr.threshold)+" hexRaw:"+attr.hexRaw+" raw:"+attr.raw);
        ///attributes.push_back(attr);
    }
}
1
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
04.06.2014, 21:10
Ответы с готовыми решениями:

получение id hdd
добрый день . для моей идеи мне нужно было вытягивать id hdd ..но не простой а заскриптованный.....(тоесть приложение вытягивает ID...

Получение serial number CPU/HDD asm
Можно ли получить серийный номер процессора или жесткого диска с помощью WinApi? Или же путем вызова asm кода? Отдельные библиотеки не...

Достать инфу с мёртвого HDD. Не запускается винда с подключённым (дохлым) HDD
Добрый день. Не нашёл тут аналогичной проблемы. В общем есть старый HDD. Хочу вытащить с него очень важную инфу. Проблема в том, что я даже...

1
 Аватар для ExeiLj
13 / 13 / 3
Регистрация: 02.08.2012
Сообщений: 128
06.06.2014, 22:20  [ТС]
Блин, капец, уже 500 вариантов испробовал. Данные хард выдает правильно, проблема в их интерпритации...
Программа в статье работает как надо, но когда переписал все в Эмбаркадеро ХЕ2 строка в строку (за исключением очевидных правок из-за среды) то выводит уже неправильно! Неужели Эмбаркадеро косячная? ((

Добавлено через 7 часов 25 минут
В общем, спасибо некому Jory Stone за его плагин к неизвестной мне программе Munin Node. Его исходники содержали столь заветный рабочий алгоритм для C++ Builder'а.

Теперь программа получает СМАРТ не хуже АИДЫ-Эвереста! Кроме одного - на ЖД от Хитачи не показывает максимальную(худшую зафиксированную) температуру. Т.к. я даже не знаю откуда АИДА ее берет, в СМАРТе таких данных нет :-(

В общем, вот код рабочей читалки СМАРТа для Эмбаркадеро C++:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
String BitmapToStr(int bitmap)
{
    String bitLine = "";
    for (int i=0; i<8; i++)
        if (bitmap & (1<<i))
            bitLine += "1";
        else
            bitLine += "0";
    return bitLine;
}
 
struct VERSION {
    int version;
    int revision;
    int IDEDeviceMap;
    int capabilities;
} VERSION;
 
struct ATTRIBUTE {
    int id;                                                                     // Идентификатор атрибута
    int value;                                                                  // Значение
    int worst;                                                                  // Худшее зафиксированное значение
    int threshold;                                                              // Пороговое значение
    unsigned __int64 data;                                                      // Данные
    int statusFlags;                                                            // Тип атрибута
} ATTRIBUTE;
 
struct TEMPERATURE {
    int current;                                                                // Текущая температура, только для атрибута 194
    int min;                                                                    // Минимальная температура, только для атрибута 194
    int max;                                                                    // Максимальная температура, только для атрибута 194
} TEMPERATURE;
 
void GetSMART()
{
// Открытие физического диска
    int driveNumber = 0; // № диска
    String drivePath = "\\\\.\\PhysicalDrive" + IntToStr(driveNumber);
    HANDLE hPhysicalDrive = CreateFile(drivePath.c_str(),GENERIC_READ|GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
    if (hPhysicalDrive == INVALID_HANDLE_VALUE) {
        ShowMessage(SysErrorMessage(GetLastError()) + "Can't open physDrive!"); ///Error
        return;
    }
// Получение S.M.A.R.T.
    bool isGetData;
    DWORD bytesReturned;
/* // SMART_GET_VERSION
    GETVERSIONINPARAMS verInParams = {0};
    isGetData = DeviceIoControl(hPhysicalDrive,SMART_GET_VERSION,
        NULL,0,&verInParams,sizeof(verInParams),&bytesReturned,NULL);
    if (!isGetData) {
            ShowMessage(SysErrorMessage(GetLastError()) + " Can't get S.M.A.R.T. ver!"); ///Error
            CloseHandle(hPhysicalDrive);
            return;
    }
    struct VERSION ver;
    ver.version = verInParams.bVersion;
    ver.revision = verInParams.bRevision;
    ver.IDEDeviceMap = verInParams.bIDEDeviceMap;
    ver.capabilities = verInParams.fCapabilities;
    Form1->Memo1->Lines->Add("ver: "+IntToStr(ver.version)+
        "   rev: "+IntToStr(ver.revision)+"   devMap: "+BitmapToStr(ver.IDEDeviceMap)+
        "   cap: "+BitmapToStr(ver.capabilities));
*/
    const int inParamsSize = sizeof(SENDCMDINPARAMS)-1;
    SENDCMDINPARAMS inParams = {0};
    inParams.cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE;                                      // Размер буфера для получения атрибутов
    inParams.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES;                                    // Запрос на чтение атрибутов
    inParams.irDriveRegs.bSectorCountReg = 1;                                               // Регистр количества секторов
    inParams.irDriveRegs.bSectorNumberReg = 1;                                              // Регистр номера сектора
    inParams.irDriveRegs.bCylLowReg = SMART_CYL_LOW;                                        // Младший разряд, указывающий на номер цилиндра
    inParams.irDriveRegs.bCylHighReg = SMART_CYL_HI;                                        // Старший разряд, указывающий на номер цилиндра
    inParams.irDriveRegs.bDriveHeadReg = 0xA0|((static_cast<BYTE>(driveNumber)&1)<<4);      // Регистр диска/головки IDE
    inParams.irDriveRegs.bCommandReg = SMART_CMD;                                           // Команда IDE
    const int outParamsSize = sizeof(SENDCMDOUTPARAMS)-1 + READ_ATTRIBUTE_BUFFER_SIZE;
    SENDCMDOUTPARAMS outParamsAttributes[outParamsSize] = {0};
    isGetData = DeviceIoControl(hPhysicalDrive,SMART_RCV_DRIVE_DATA,
        &inParams,inParamsSize,&outParamsAttributes,outParamsSize,&bytesReturned,NULL);
    if (!isGetData) {
            ShowMessage(SysErrorMessage(GetLastError()) + " Can't get S.M.A.R.T. attributes!"); ///Error
            CloseHandle(hPhysicalDrive);
            return;
    }
    inParams.cBufferSize = READ_THRESHOLD_BUFFER_SIZE;
    inParams.irDriveRegs.bFeaturesReg = READ_THRESHOLDS;
    SENDCMDOUTPARAMS outParamsThresholds[outParamsSize] = {0};
    isGetData = DeviceIoControl(hPhysicalDrive,SMART_RCV_DRIVE_DATA,
        &inParams,inParamsSize,&outParamsThresholds,outParamsSize,&bytesReturned,NULL);
    if (!isGetData) {
            ShowMessage(SysErrorMessage(GetLastError()) + " Can't get S.M.A.R.T. thresholds!"); ///Error
            CloseHandle(hPhysicalDrive);
            return;
    }
    CloseHandle(hPhysicalDrive);
 
// Индексы атрибута S.M.A.R.T.
#define INDEX_ATTRIBUTE_INDEX       0
#define INDEX_ATTRIBUTE_STATUSFLAGS 1
#define INDEX_ATTRIBUTE_VALUE       3
#define INDEX_ATTRIBUTE_WORST       4
#define INDEX_ATTRIBUTE_RAW         5
 
// Типы атрибута S.M.A.R.T.
#define PRE_FAILURE_WARRANTY        0x1                                         // Жизненно важный (критический)
#define ON_LINE_COLLECTION          0x2                                         // Коллекция реального времени
#define PERFORMANCE_ATTRIBUTE       0x4                                         // Атрибут, отражающий производительность диска
#define ERROR_RATE_ATTRIBUTE        0x8                                         // Атрибут, отражающий частоту появления ошибок
#define EVENT_COUNT_ATTRIBUTE       0x10                                        // Счётчик событий
#define SELF_PRESERVING_ATTRIBUTE   0x20                                        // Самосохраняющийся атрибут
 
    BYTE *attributes = static_cast<BYTE*>(outParamsAttributes->bBuffer);
    BYTE *thresholds = static_cast<BYTE*>(outParamsThresholds->bBuffer);
    const int maxAttributes = 30;
    for (int i=0; i < maxAttributes; ++i) {
        BYTE *attribute = &attributes[2+i*12];
        if (!attribute[INDEX_ATTRIBUTE_INDEX])                                  // Пропуск пустых атрибутов
            continue;
        int *thres = static_cast<int*>(static_cast<void*>(&thresholds[2+i*12+1]));
        BYTE *threshold = &thresholds[2+i*12];
        struct ATTRIBUTE attr;
        struct TEMPERATURE temp;
        CopyMemory(static_cast<void*>(&attr.data),static_cast<void*>(&attribute[INDEX_ATTRIBUTE_RAW]),sizeof(&attribute[INDEX_ATTRIBUTE_RAW]));
        if (attribute[INDEX_ATTRIBUTE_INDEX] == 194)
            if (attr.data > 200) {
                // преобразования для Hitachi
                temp.current = attribute[INDEX_ATTRIBUTE_RAW];
                temp.min = attribute[INDEX_ATTRIBUTE_RAW+2];
                temp.max = attribute[INDEX_ATTRIBUTE_RAW+4];
            } else {
                temp.current = attribute[INDEX_ATTRIBUTE_VALUE];
                temp.min = 404;                                                 // 404 - код ошибки, т.к. температура может быть равна 0
                temp.max = attribute[INDEX_ATTRIBUTE_WORST];
            }
        attribute[INDEX_ATTRIBUTE_RAW+2] = attribute[INDEX_ATTRIBUTE_RAW+3] = attribute[INDEX_ATTRIBUTE_RAW+4] =
            attribute[INDEX_ATTRIBUTE_RAW+5] = attribute[INDEX_ATTRIBUTE_RAW+6] = 0;
        threshold[INDEX_ATTRIBUTE_RAW+2] = threshold[INDEX_ATTRIBUTE_RAW+3] = threshold[INDEX_ATTRIBUTE_RAW+4] =
            threshold[INDEX_ATTRIBUTE_RAW+5] = threshold[INDEX_ATTRIBUTE_RAW+6] = 0;
        attr.id = attribute[INDEX_ATTRIBUTE_INDEX];
        attr.value = attribute[INDEX_ATTRIBUTE_VALUE];
        attr.worst = attribute[INDEX_ATTRIBUTE_WORST];
        attr.threshold = thres[0];
        attr.statusFlags = attribute[INDEX_ATTRIBUTE_STATUSFLAGS];
 
        String status = "";
        if (attr.statusFlags&PRE_FAILURE_WARRANTY)
            status += "Критич.; ";
        if (attr.statusFlags&PERFORMANCE_ATTRIBUTE)
            status += "Производ.; ";
 
        Form1->Memo1->Lines->Add("id: "+IntToStr(attr.id)+"\t val: "+IntToStr(attr.value)+
            "\t worst: "+IntToStr(attr.worst)+"\t thres: "+IntToStr(attr.threshold)+
            "\t data: "+static_cast<String>(attr.data)+"\t\t "+status);
        if (attr.id == 194) {
            String minTemp = "";
            if (temp.min != 404)
                minTemp = IntToStr(temp.min)+", ";
            Form1->Memo1->Lines->Add("t: "+IntToStr(temp.max)+", "+minTemp+IntToStr(temp.current));
        }
    }
    //int driverError = outParamsAttributes->DriverStatus.bDriverError;
/* //bDriverError values
#define SMART_NO_ERROR          0       // No error
#define SMART_IDE_ERROR         1       // Error from IDE controller
#define SMART_INVALID_FLAG      2       // Invalid command flag
#define SMART_INVALID_COMMAND   3       // Invalid command byte
#define SMART_INVALID_BUFFER    4       // Bad buffer (null, invalid addr..)
#define SMART_INVALID_DRIVE     5       // Drive number not valid
#define SMART_INVALID_IOCTL     6       // Invalid IOCTL
#define SMART_ERROR_NO_MEM      7       // Could not lock user's buffer
#define SMART_INVALID_REGISTER  8       // Some IDE Register not valid
#define SMART_NOT_SUPPORTED     9       // Invalid cmd flag set
#define SMART_NO_IDE_DEVICE     10      // Cmd issued to device not present
                                        // although drive number is valid*/
    //Form1->Memo1->Lines->Add("driverError: "+IntToStr(driverError));*/
    Form1->Memo1->Lines->Add("Done!");
}
UPD: Теперь показывает все виды температур у Хитачи.
4
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.06.2014, 22:20
Помогаю со студенческими работами здесь

При подключении hdd c mbr перестает грузиться с gpt hdd
Всем доброго времени суток. Появилась проблемка. Есть системник с установленой на нем Win7 на GPT раздел. После подключения к нему еще...

Перенос CentOS 6 со старого IDE HDD на новый SATA HDD
Здравствуйте. Сейчас в компьютере стоит CentOS 6 на IDE HDD. Нужно её перенести на новый HDD SATA. Т.е. клонировать диск. Как проще...

Стоит ли переносить систему c hdd с буфером 32мб на hdd 128мб
Имею win 7 home x64 лиц. Стоит на старом hdd - вот его характеристики: Описание драйвера WDC WD5000AADS-00M2B0 ATA Device Дата...

Ошибка при замене HDD с нового компа на HDD со старого
Здравствуйте! Купили новый компьютер. Для того, чтобы всё не переустанавливать, решил просто заменить винт с нового компа на винт со...

При установке Win 7 не видит hdd и флешки тоже, Asrock g41c-vs, hdd wd 3200av js
При выборе раздела для форматирования и установки win 7 не видит жесткого диска. Диск с драйверами материнской платы потеряны, что делать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
2
Ответ Создать тему
Новые блоги и статьи
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
Реалии
Hrethgir 01.03.2026
Нет, я не закончил до сих пор симулятор. Эта задача сложнее. Не получилось уйти в плавсостав, но оно и к лучшему, возможно. Точнее получалось - но сварщиком в палубную команду, а это значит, в моём. . .
Ритм жизни
kumehtar 27.02.2026
Иногда приходится жить в ритме, где дел становится всё больше, а вовлечения в происходящее — всё меньше. Плотный график не даёт вниманию закрепиться ни на одном событии. Утро начинается с быстрых,. . .
SDL3 для Web (WebAssembly): Сборка библиотек: SDL3, Box2D, FreeType, SDL3_ttf, SDL3_mixer и SDL3_image из исходников с помощью CMake и Emscripten
8Observer8 27.02.2026
Недавно вышла версия 3. 4. 2 библиотеки SDL3. На странице официальной релиза доступны исходники, готовые DLL (для x86, x64, arm64), а также библиотеки для разработки под Android, MinGW и Visual Studio. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru