На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
  
> Имя устройства физического диска
    Всем привет!
    Мне нужно получить имя (прошитый в устройстве идентификатор) физического диска.
    Не метку логического диска, не GUID, не "\Device\HarddiskVolume1" или т.п.
    А то, что выдаёт wmic diskdrive list brief в столбцах Caption и Model, например:
    ExpandedWrap disabled
      Generic STORAGE DEVICE USB Device
      JetFlash Transcend 16GB USB Device
      ST2000DM006-2DM164
      ST31000528AS
      ST2000DM001-1CH164
      PLEXTOR PX-128M6Pro
      USB DISK 2.0 USB Device
    К примеру, у меня открыто устройство "\\.\PhysicalDrive0" (пишу без экранирования), наверняка же есть какой-то DeviceIoControl, через который можно это получить.
    PowerShell и т.п. вещи не интересуют, нужно получить программно. Вроде есть вариант через WMI. Но хочется на чистом WinAPI.
    p.s. Есть ещё вариант через SMART, но это не прокатит с флешками (только харды) + нужны права админа.
        JoeUser, спасибо :victory:
        Я, правда, сам тоже нашёл: IOCTL_STORAGE_QUERY_PROPERTY. Запрос StorageDeviceProperty, поле ProductIdOffset.
        Навороченный какой код (второй). Надо посмотреть, что там. Но там, я вижу, тоже есть этот IOCTL_STORAGE_QUERY_PROPERTY.
          Да, автор второго кода - мастер по жести! :lol:
          ExpandedWrap disabled
            switch (*cP)
                     {
                        case '0': i64Id += 0; break;
                        case '1': i64Id += 1; break;
                        case '2': i64Id += 2; break;
                        case '3': i64Id += 3; break;
                        case '4': i64Id += 4; break;
                        case '5': i64Id += 5; break;
                        case '6': i64Id += 6; break;
                        case '7': i64Id += 7; break;
                        case '8': i64Id += 8; break;
                        case '9': i64Id += 9; break;
                        case 'a': case 'A': i64Id += 10; break;
                        case 'b': case 'B': i64Id += 11; break;
                        case 'c': case 'C': i64Id += 12; break;
                        case 'd': case 'D': i64Id += 13; break;
                        case 'e': case 'E': i64Id += 14; break;
                        case 'f': case 'F': i64Id += 15; break;
                        case 'g': case 'G': i64Id += 16; break;
                        case 'h': case 'H': i64Id += 17; break;
                        case 'i': case 'I': i64Id += 18; break;
                        case 'j': case 'J': i64Id += 19; break;
                        case 'k': case 'K': i64Id += 20; break;
                        case 'l': case 'L': i64Id += 21; break;
                        case 'm': case 'M': i64Id += 22; break;
                        case 'n': case 'N': i64Id += 23; break;
                        case 'o': case 'O': i64Id += 24; break;
                        case 'p': case 'P': i64Id += 25; break;
                        case 'q': case 'Q': i64Id += 26; break;
                        case 'r': case 'R': i64Id += 27; break;
                        case 's': case 'S': i64Id += 28; break;
                        case 't': case 'T': i64Id += 29; break;
                        case 'u': case 'U': i64Id += 30; break;
                        case 'v': case 'V': i64Id += 31; break;
                        case 'w': case 'W': i64Id += 32; break;
                        case 'x': case 'X': i64Id += 33; break;
                        case 'y': case 'Y': i64Id += 34; break;
                        case 'z': case 'Z': i64Id += 35; break;
                     }                            
                  }
            Цитата JoeUser @
            Да, автор второго кода - мастер по жести!

            Начитаются бородатых анекдотов, а потом код пишут... https://www.anekdot.ru/id/-9934695/
              Давай я облегчу жизъть
              ExpandedWrap disabled
                #include <windows.h>
                #include <iostream>
                #include <iomanip>
                #include <vector>
                #include <string>
                 
                void getDevInfo(HANDLE hDev)
                {
                  STORAGE_PROPERTY_QUERY     inBuf;
                  std::vector<unsigned char> buf;
                  DWORD                      retSize;   // unused
                 
                  inBuf.PropertyId = StorageDeviceProperty;
                  inBuf.QueryType  = PropertyStandardQuery;
                  buf.resize(sizeof(STORAGE_DEVICE_DESCRIPTOR));
                 
                  STORAGE_DEVICE_DESCRIPTOR *outBuf = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(&buf.front());
                 
                  outBuf->Version = sizeof(*outBuf);
                  if (DeviceIoControl(hDev, IOCTL_STORAGE_QUERY_PROPERTY, &inBuf, sizeof(inBuf), outBuf, buf.size(),
                                      &retSize, NULL) == FALSE)
                  {
                    std::cerr << "DeviceIoControl (1st) failed. Code error is " << GetLastError() << std::endl;
                    return;
                  }
                 
                  buf.resize(outBuf->Size);
                  outBuf = reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(&buf.front());
                  if (DeviceIoControl(hDev, IOCTL_STORAGE_QUERY_PROPERTY, &inBuf, sizeof(inBuf), outBuf, buf.size(),
                                      &retSize, NULL) == FALSE)
                  {
                    std::cerr << "DeviceIoControl (2nd) failed. Code error is " << GetLastError() << std::endl;
                    return;
                  }
                  if (outBuf->VendorIdOffset        != 0)
                    std::cout << "Vendor   is " << &buf[outBuf->VendorIdOffset]        << '\n';
                  if (outBuf->ProductIdOffset       != 0)
                    std::cout << "Product  is " << &buf[outBuf->ProductIdOffset]       << '\n';
                  if (outBuf->ProductRevisionOffset != 0)
                    std::cout << "Revision is " << &buf[outBuf->ProductRevisionOffset] << '\n';
                  if (outBuf->SerialNumberOffset    != 0)
                    std::cout << "S/N      is " << &buf[outBuf->SerialNumberOffset]    << '\n';
                 
                  std::cout << "\nRawData  is:" << '\n';
                  for (int i = 0; i < outBuf->RawPropertiesLength; ++i)
                  {
                    unsigned byte = static_cast<unsigned>(outBuf->RawDeviceProperties[i]) & 0xFF;
                 
                    std::cout << '[' << i << "]\t"
                              << std::setfill('0') << " (0x" << std::setw(2) << std::hex << std::uppercase << byte
                              << std::setfill(' ') << ") "   << std::setw(3) << std::dec                   << byte
                              << ' ' << outBuf->RawDeviceProperties[i] << '\n';
                  }
                  std::cout << std::endl;
                }
                 
                int main()
                {
                  for (int i = 0; ; ++i)
                  {
                    std::string nameDev = "\\\\.\\PhysicalDrive" + std::to_string(i);
                 
                    HANDLE hDev = CreateFile(nameDev.c_str(), GENERIC_READ,
                                             FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                 
                    if (hDev == INVALID_HANDLE_VALUE) break;
                 
                    std::cout << nameDev << " info\n" << std::string(nameDev.length() + 5, '=') << '\n';
                    getDevInfo(hDev);
                    CloseHandle(hDev);
                  }
                }


              Добавлено
              Но вообще как-то мало инфы. Подозреваю, что сюда ещё SMART можно затесать.
                Цитата Qraizer @
                if (hDev == INVALID_HANDLE_VALUE) break;
                Кстати, номера могут иметь дыры.
                Т.е. запросто могут быть диски 0, 1, 3, 6, допустим.
                  Я знаю, ну так это ж пример использования. Основное в getDevInfo(), ибо в ваших примерах как-то многословно всё. И на Сях, что не добавляет ясности.
                  Я вот не в курсе, как нормально дыры обходить. Только через SetupAPI получить все железки с нужным классом и переэнумить руками. Где-то был похожий код, но другой, там RSы ищутся. Если найду, приложу, там тоже не всё так гладко.
                  Сообщение отредактировано: Qraizer -
                    Цитата Qraizer @
                    Только через SetupAPI получить все железки с нужным классом и переэнумить руками. Где-то был похожий код, но другой, там RSы ищутся. Если найду, приложу, там тоже не всё так гладко.
                    Да, я тоже через SetupAPI только видел. Сегодня ковырял rufus, там так же. Что такое RS'ы?
                    Я обычно тупо делаю перебор номеров от 0 до 15. Кстати, какое кол-во дисков может быть максимум?
                      Цитата Jin X @
                      Что такое RS'ы?
                      COM-порты. Но там и задача была сложнее: нужно было найти конкретный девайс по его COMномеру:, отыскать его родительное устройство, проверить, что оно конкретная USB-шелезяка и выторкнуть/перевоткнуть. Шелезяку, не COM.
                      Цитата Jin X @
                      Я обычно тупо делаю перебор номеров от 0 до 15. Кстати, какое кол-во дисков может быть максимум?
                      Теоретически олимпиллиард. Вот тут можно посмотреть на дикую смесь C и Плюсов, но он не даст полной инфы. Впрочем, это зависит от того, какие устройства вообще интересуют.
                        Цитата Qraizer @
                        Вот тут можно посмотреть на дикую смесь C и Плюсов, но он не даст полной инфы.
                        Там тоже ж SetupAPI.
                        Почему не даст?
                          Ну а как быть, например, с floppy или cdrom? Разве они не физические? Но я ж написал:
                          Цитата Qraizer @
                          Впрочем, это зависит от того, какие устройства вообще интересуют.
                            Цитата Qraizer @
                            Ну а как быть, например, с floppy или cdrom?
                            CD вообще перечисляются через \\.\CdRomX.
                            А floppy есть в списках \\.\PsysicalDriveX ?
                              Флешки должны быть. А их дофига воткнуть можно.
                                Jin X, посмотри тут (запусти), может тебе это даст какую-то полезную инфу перед непосредственным опросом устройств.
                                  Цитата JoeUser @
                                  Jin X, посмотри тут (запусти), может тебе это даст какую-то полезную инфу перед непосредственным опросом устройств.
                                  Ух ты! Вот уж не думал. Спасибо! Да, там все "Physical Drives" присутствуют :)
                                    Цитата Jin X @
                                    Запрос StorageDeviceProperty, поле ProductIdOffset.

                                    У меня запрос "IOCTL_STORAGE_QUERY_PROPERTY" возвращает только модель и версию ProductId, а вот чтение смарта через "IOCTL_SMART_RCV_DRIVE_DATA" уже намного больше инфы, и среди прочего в буфере получаю валидный S/N. Правда байты в словах расположены наоборот, но это поправимо - вот логи (диск ST380011A, версия 3.06, серийник 5JV4L976):

                                    ExpandedWrap disabled
                                      ;//====== IOCTL_STORAGE_QUERY_PROPERTY =====================================
                                      ;//=========================================================================
                                      00401040  28 00 00 00 A7 00 00 00  00 00 00 00 00 00 00 00  (...§...........
                                      00401050  4C 00 00 00 75 00 00 00  7E 00 00 00 03 00 00 00  L...u...~... ...
                                      00401060  24 00 00 00 00 00 00 00  00 00 00 02 20 00 00 00  $..........  ...
                                      00401070  53 54 33 38 30 30 31 31  41 00 20 20 20 20 20 20  ST380011A.
                                      00401080  20 20 20 20 20 20 20 20  33 2E 30 36 53 54 33 38          3.06ST38
                                      00401090  30 30 31 31 41 00 20 20  20 20 20 20 20 20 20 20  0011A.
                                      004010A0  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20
                                      004010B0  20 20 20 20 00 33 2E 30  36 00 20 20 20 00 34 61      .3.06.   .4a
                                      004010C0  33 35 33 34 35 36 33 39  34 63 33 36 33 37 32 30  353456394c363720
                                      004010D0  32 30 32 30 32 30 32 30  32 30 32 30 32 30 32 30  2020202020202020
                                      004010E0  32 30 32 30 32 30 00 00  00 00 00 00 00 00 00 00  202020..........
                                      004010F0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
                                       
                                      ;//====== IOCTL_SMART_RCV_DRIVE_DATA =======================================
                                      ;//=========================================================================
                                      00401040  18 00 00 00 D0 01 01 4F  C2 A0 EC 00 00 00 00 00   ...Р  OВ м.....
                                      00401050  00 00 00 00 00 00 00 00  00 18 00 00 00 00 00 01  ......... .....
                                      00401060  4F C2 A0 EC 00 00 00 00  00 5A 0C FF 3F 37 C8 10  OВ м.....Z.я?7И
                                      00401070  00 00 00 00 00 3F 00 00  00 00 00 00 00 4A 35 34  .....?.......J54   <---- 5JV4L976
                                      00401080  56 39 4C 36 37 20 20 20  20 20 20 20 20 20 20 20  V9L67
                                      00401090  20 00 00 00 10 04 00 2E  33 36 30 20 20 20 20 54   ...  ..360    T
                                      004010A0  53 38 33 30 30 31 31 20  41 20 20 20 20 20 20 20  S830011 A
                                      004010B0  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20
                                      004010C0  20 20 20 20 20 20 20 10  80 00 00 00 2F 00 00 00          Ђ.../...
                                      004010D0  02 00 02 07 00 FF 3F 10  00 3F 00 10 FC FB 00 10   .  .я? .?. ьы.
                                      004010E0  01 B0 F8 50 09 00 00 07  00 03 00 78 00 78 00 F0   °шP... . .x.x.р
                                      004010F0  00 78 00 00 00 00 00 00  00 00 00 00 00 00 00 00  .x..............
                                      00401100  00 00 00 00 00 00 00 00  00 7E 00 1B 00 6B 34 01  .........~. .k4
                                      00401110  7D 03 40 69 34 01 3C 03  40 3F 04 00 00 00 00 FE  } @i4 < @? ....ю
                                      00401120  FE 00 00 4B 40 00 80 00  00 00 00 00 00 00 00 00  ю..K@.Ђ.........
                                      00401130  00 B0 F8 50 09 00 00 00  00 00 00 00 00 00 00 00  .°шP............
                                      00401140  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
                                      00401150  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
                                      00401160  00 00 00 00 00 00 00 00  00 09 00 B0 F8 50 09 B0  ...........°шP.°
                                      00401170  F8 50 09 20 20 02 00 B6  42 00 00 00 8A 06 3C 0A  шP.   .¶B...Љ <.
                                      00401180  3C FF FF C6 07 00 01 00  08 D0 09 00 04 02 00 30  <яяЖ . . Р..  .0
                                      00401190  00 00 00 00 00 00 00 06  FE 00 00 02 00 00 00 00  ....... ю.. ....
                                      004011A0  00 00 00 00 00 21 00 0B  00 00 00 00 00 00 00 00  .....!. ........
                                      004011B0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
                                      004011C0  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  ................
                                      Цитата core-i7 @
                                      ProductId
                                      Так, это и нужно.

                                      Цитата core-i7 @
                                      а вот чтение смарта через "IOCTL_SMART_RCV_DRIVE_DATA" уже намного больше инфы
                                      Проблема со SMART'ом в том, что его нет на флешках - раз, нужны права админа - два.

                                      Вот эта прога что выдаёт у тебя?
                                      Скрытый текст
                                      ExpandedWrap disabled
                                        #include <windows.h>
                                        #include <memory>
                                        #include <string>
                                         
                                        //returns the serial number of the first physical drive in a std::string or an empty std::string in case of failure
                                        //based on http://codexpert.ro/blog/2013/10/26/get-physical-drive-serial-number-part-1/
                                        std::string getFirstHddSerialNumber() {
                                            //get a handle to the first physical drive
                                            HANDLE h = CreateFileW(L"\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
                                            if(h == INVALID_HANDLE_VALUE) return {};
                                            //an std::unique_ptr is used to perform cleanup automatically when returning (i.e. to avoid code duplication)
                                            std::unique_ptr<std::remove_pointer<HANDLE>::type, void(*)(HANDLE)> hDevice{h, [](HANDLE handle){CloseHandle(handle);}};
                                            //initialize a STORAGE_PROPERTY_QUERY data structure (to be used as input to DeviceIoControl)
                                            STORAGE_PROPERTY_QUERY storagePropertyQuery{};
                                            storagePropertyQuery.PropertyId= StorageDeviceProperty;
                                            storagePropertyQuery.QueryType= PropertyStandardQuery;
                                            //initialize a STORAGE_DESCRIPTOR_HEADER data structure (to be used as output from DeviceIoControl)
                                            STORAGE_DESCRIPTOR_HEADER storageDescriptorHeader{};
                                            //the next call to DeviceIoControl retrieves necessary size (in order to allocate a suitable buffer)
                                            //call DeviceIoControl and return an empty std::string on failure
                                            DWORD dwBytesReturned= 0;
                                            if(!DeviceIoControl(hDevice.get(), IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
                                                                &storageDescriptorHeader, sizeof(STORAGE_DESCRIPTOR_HEADER), &dwBytesReturned, NULL))
                                                return {};
                                            //allocate a suitable buffer
                                            const DWORD dwOutBufferSize= storageDescriptorHeader.Size;
                                            std::unique_ptr<BYTE[]> pOutBuffer{new BYTE[dwOutBufferSize]{}};
                                            //call DeviceIoControl with the allocated buffer
                                            if(!DeviceIoControl(hDevice.get(), IOCTL_STORAGE_QUERY_PROPERTY, &storagePropertyQuery, sizeof(STORAGE_PROPERTY_QUERY),
                                                                pOutBuffer.get(), dwOutBufferSize, &dwBytesReturned, NULL))
                                                return {};
                                            //read and return the serial number out of the output buffer
                                            STORAGE_DEVICE_DESCRIPTOR* pDeviceDescriptor= reinterpret_cast<STORAGE_DEVICE_DESCRIPTOR*>(pOutBuffer.get());
                                            const DWORD dwSerialNumberOffset= pDeviceDescriptor->SerialNumberOffset;
                                            if(dwSerialNumberOffset==0) return {};
                                            const char* serialNumber= reinterpret_cast<const char*>(pOutBuffer.get() + dwSerialNumberOffset);
                                            return serialNumber;
                                        }
                                         
                                        #include <iostream>
                                        int main() {
                                            std::string serialNumber = getFirstHddSerialNumber();
                                            if(serialNumber.empty())
                                                std::cout << "failed to retrieve serial number\n";
                                            else
                                                std::cout << "serial number: " << serialNumber << "\n";
                                            return 0;
                                        }
                                        Цитата Jin X @
                                        Вот эта прога что выдаёт у тебя?

                                        у меня плюсы не установлены, я на фасм переписывал и в буфере получал логи выше.
                                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                        0 пользователей:


                                        Рейтинг@Mail.ru
                                        [ Script execution time: 0,0576 ]   [ 17 queries used ]   [ Generated: 16.04.24, 10:03 GMT ]