Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.67/6: Рейтинг темы: голосов - 6, средняя оценка - 4.67
Antinael
0 / 0 / 0
Регистрация: 20.04.2011
Сообщений: 9
1

Запись и чтение данных из внутренней флэш памяти винчестера, или получение ID винта

01.09.2014, 20:54. Просмотров 1153. Ответов 9
Метки нет (Все метки)

Доброго времени суток!
Господа, есть у меня очень интересный вопрос, который очень хотелось бы решить. Суть вопроса в следующем: в каждом винчестере на данный момент есть внутренняя флэш память и мне бы очень хотелось позаимствовать в ней буквально 10 байт места средствами с++ под нужды проекта нашей компании. Может быть кто-то уже задавался подобным вопросом и готов будет поделиться информацией. В принципе, если верить этому источнику, свободное место можно найти и в других сервисных разделах винчестера, что для моих нужд тоже приемлимо. Уповаю на Вашу помощь в этом вопросе, поделитесь опытом и знаниями или ткните мне пальцем на то, что сможет мне помочь в решении этой проблемы.

ЗЫ: Нууу.... или хотя бы подскажите как мне достать ID винчестера. Именно заводской, а не ID, который присваивается при форматировании разделов дисков.

Заранее спасибо.
0
Лучшие ответы (1)
DrOffset
11867 / 6421 / 1545
Регистрация: 30.01.2014
Сообщений: 10,445
02.09.2014, 01:10 2
Цитата Сообщение от Antinael Посмотреть сообщение
Нууу.... или хотя бы подскажите как мне достать ID винчестера.
DeviceIoControl(пример) или через WMI.
1
Antinael
0 / 0 / 0
Регистрация: 20.04.2011
Сообщений: 9
02.09.2014, 11:56  [ТС] 3
Цитата Сообщение от DrOffset Посмотреть сообщение
DeviceIoControl(пример) или через WMI.
Благодарю. Этим обязательно воспользуюсь.

Но вопрос с внутренней памятью винчестера открыт. Хотелось бы узнать побольше о возможностях использования этого нигде неучтённого пространства =)

ЗЫ: не для вредительства, а для плодотворного труда исключительно. Я понимаю, что эти знания можно направить в нехорошее русло, но также их можно направить и на созидание. Если знающие люди не отвечаю исключительно с точки зрения безопасности, то напишите хотя бы в ЛС, мне необходимы эти знания для более жёсткой привязки к железу нашей программы.
0
Antinael
0 / 0 / 0
Регистрация: 20.04.2011
Сообщений: 9
05.09.2014, 12:43  [ТС] 4
Господа, снова доброго времени суток.
Дабы не плодить тем, задам вопрос в этой теме, хоть он и относится к QT (ув. операторы, можете перебросить эту тему в ветку по QT). Суть вопроса в следующем:
В примере приведённом господином DrOffset есть строка
C++ (Qt)
1
strSerialNumber = CString(pOutBuffer + dwSerialNumberOffset);
Я не совсем понимаю, что она делает. pOutBuffer BYTE* переменная, которая на выходе имеет 40 байт информации. dwSerialNumberOffset - DWORD переменная, которая на выходе имеет значение 146. Объясните, пожалуйста, как сей код работает? И ещё вопрос по переносу кода из примера в QT. Переменные CString не идентифицируются. Как я понял, за них отвечает
C++ (Qt)
1
#include <atlstr.h>
но есть трудности с подключением этой библиотеки. Подскажите неопытному как грамотно и красиво перевести в QString данное выражение: CString(pOutBuffer + dwSerialNumberOffset);
Заранее спасибо.
0
Kastaneda
Jesus loves me
Эксперт С++
5061 / 3079 / 351
Регистрация: 12.12.2009
Сообщений: 7,783
Записей в блоге: 2
Завершенные тесты: 1
05.09.2014, 13:23 5
Я пару недель назад именно этот код (по ссылке выше) тоже под QString переписывал. Там ни каких сложностей нет, а atlstr.h не нужен (я так понимаю там CString, не знаю, никогда с ними не работал).
Если будут сложности я вечером могу Qt'шный код скинуть.
1
Antinael
0 / 0 / 0
Регистрация: 20.04.2011
Сообщений: 9
05.09.2014, 16:20  [ТС] 6
Цитата Сообщение от Kastaneda Посмотреть сообщение
Если будут сложности я вечером могу Qt'шный код скинуть.
Буду весьма признателен.
В принципе, программа переделанная под QT как-то работает... "Как-то" потому что я не понимаю что происходит в той строке, но для каждого винчестера на разных машинах выводит разные значения ID. Правда они несколько отличаются от значений, которые выводит прога на С с тем кодом. Буду очень благодарен за возможность посмотреть Ваш код. Заранее спасибо =)
0
Kastaneda
Jesus loves me
Эксперт С++
5061 / 3079 / 351
Регистрация: 12.12.2009
Сообщений: 7,783
Записей в блоге: 2
Завершенные тесты: 1
05.09.2014, 17:16 7
Лучший ответ Сообщение было отмечено Antinael как решение

Решение

Вот, работает с std::string, в QString я потом уже переделываю
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
DWORD GetPhysicalDriveSerialNumber(const std::string &nDriveNumber, std::string &strSerialNumber)
{
    DWORD dwResult = NO_ERROR;
 
    // Format physical drive path (may be '\\.\PhysicalDrive0', '\\.\PhysicalDrive1' and so on).
    std::string strDrivePath("\\\\.\\PhysicalDrive");
    strDrivePath += nDriveNumber;
 
    // call CreateFile to get a handle to physical drive
    HANDLE hDevice = ::CreateFileA(strDrivePath.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL, OPEN_EXISTING, 0, NULL);
 
    if(INVALID_HANDLE_VALUE == hDevice)
        return ::GetLastError();
 
    // set the input STORAGE_PROPERTY_QUERY data structure
    STORAGE_PROPERTY_QUERY storagePropertyQuery;
    ZeroMemory(&storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY));
    storagePropertyQuery.PropertyId = StorageDeviceProperty;
    storagePropertyQuery.QueryType = PropertyStandardQuery;
 
    // get the necessary output buffer size
    STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader = { 0 };
    DWORD dwBytesReturned = 0;
    if(!::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
        &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
        &storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER),
        &dwBytesReturned, NULL))
    {
        dwResult = ::GetLastError();
        ::CloseHandle(hDevice);
        return dwResult;
    }
 
    // allocate the necessary memory for the output buffer
    const DWORD dwOutBufferSize = storageDescriptorHeader.Size;
    BYTE* pOutBuffer = new BYTE[dwOutBufferSize];
    ZeroMemory(pOutBuffer, dwOutBufferSize);
 
    // get the storage device descriptor
    if (!::DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY,
        &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
        pOutBuffer, dwOutBufferSize,
        &dwBytesReturned, NULL))
    {
        dwResult = ::GetLastError();
        delete[]pOutBuffer;
        ::CloseHandle(hDevice);
        return dwResult;
    }
 
    // Now, the output buffer points to a STORAGE_DEVICE_DESCRIPTOR structure
    // followed by additional info like vendor ID, product ID, serial number, and so on.
    STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor = (STORAGE_DEVICE_DESCRIPTOR*)pOutBuffer;
    const DWORD dwSerialNumberOffset = pDeviceDescriptor->SerialNumberOffset;
    if (dwSerialNumberOffset != 0)
    {
        // finally, get the serial number
        strSerialNumber = std::string((const char*)pOutBuffer + dwSerialNumberOffset);
    }
 
    // perform cleanup and return
    delete[]pOutBuffer;
    ::CloseHandle(hDevice);
    return dwResult;
}
C++
1
2
    QString qSerialNumber(serialNumber.c_str());
    qSerialNumber = qSerialNumber.trimmed(); // бывают лишние пробелы слева
Результат я проверял сравнивая с реальным серийным номером винта (в винде через консоль можно получить эту информацию, не помню как, я гуглил)
1
Antinael
0 / 0 / 0
Регистрация: 20.04.2011
Сообщений: 9
08.09.2014, 11:55  [ТС] 8
Цитата Сообщение от Kastaneda Посмотреть сообщение
Вот, работает с std::string, в QString я потом уже переделываю
Большое спасибо. мой вариант был немного другим, давал уникальный номер, но... но я так и не понял, что он считал.
Ещё один вопрос... я не совсем понимаю, что делает эта строка:
C++ (Qt)
1
strSerialNumber = std::string((const char*)pOutBuffer + dwSerialNumberOffset);
pOutBuffer - это, как я понял, массив информации о серийном номере, смотрел по дебагу - он принимает значение 40... dwSerialNumberOffset - смещение; как я понимаю от начала массива... но оно принимает значение 147 по дебагу. Объясните, пожалуйста, как сие работает. Заранее спасибо.
0
Kastaneda
Jesus loves me
Эксперт С++
5061 / 3079 / 351
Регистрация: 12.12.2009
Сообщений: 7,783
Записей в блоге: 2
Завершенные тесты: 1
08.09.2014, 12:11 9
Цитата Сообщение от Antinael Посмотреть сообщение
я не совсем понимаю, что делает эта строка:
Создает std::string, в качестве аргумента указатель на начало серийника.
Цитата Сообщение от Antinael Посмотреть сообщение
он принимает значение 40
Это имеется ввиду, что дебагер показывает, что длина строки 40? Я честно говоря не вникал в работу этого кода, просто проверил, что результат корректный и глазами посмотрел, что утечки памяти нет. Могу предположить, что там в буфере лежат несколько строк, заканчивающихся null-terminator'ом, поэтому отладчик не может показать длину всего буфера. По смещению dwSerialNumberOffset мы имеем начало строки, в которой записан серийник.
1
Antinael
0 / 0 / 0
Регистрация: 20.04.2011
Сообщений: 9
08.09.2014, 16:16  [ТС] 10
Цитата Сообщение от Kastaneda Посмотреть сообщение
Создает std::string, в качестве аргумента указатель на начало серийника.
Это я понимал =)
Но благодарю ещё раз. Теперь я понял, почему полученные мной результаты не совпадали с нужными. Действительно всё так, как вы описали. Ещё раз спасибо
0
08.09.2014, 16:16
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2020, vBulletin Solutions, Inc.