Диски, тома, разделы...

Тема в разделе "WASM.WIN32", создана пользователем Jin X, 6 июл 2018.

  1. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    313
    Адрес:
    Кольца Сатурна
    Приветствую!

    Есть \\.\PhysicalDriveX, его можно открыть через CreateFile и получить GUID (IOCTL_DISK_GET_DRIVE_GEOMETRY_EX... или можно как-то ещё проще получить GUID?).

    Можно получить список (GUID) всех томов через FindFirstVolume/FindNextVolume (в формате \\?\Volume{GUID}).
    0. Можно ли получить GUID типа раздела через IOCTL_DISK_GET_PARTITION_INFO_EX, подставив этот том (\\?\Volume{GUID})?

    1. И есть ли вообще разница между томами и разделами?
    К примеру, в описании IOCTL_DISK_GET_LENGTH_INFO сказано "Retrieves the length of the specified disk, volume, or partition." (типа раздел и том – это не одно и то же).

    2. И главный вопрос: как связать физические диски с разделами?
    Т.е. определить – какие разделы на каком физическом диске находятся?

    3. А как перечислить все физические диски и все разделы на этом диске?
    Можно открывать все подряд PhysicalDrive0, 1, 2... до ошибки типа not found. Но это единственный способ?
    А не может быть такого, что PhysicalDrive1 нет, а PhysicalDrive2 есть?

    4. Ну и ещё вопрос до кучи: какие вообще устройства (диски, разделы) можно задать для CreateFile кроме \\.\PhysycalDriveX, \\.\CdRomX и \\.\X: ? Scsi ещё вроде были (только как их задать – х/з).
    В инете можно найти ещё устройства типа \Device\Harddisk0\Partition1, но у меня открыть (CreateFile) такое устройство не получается (не найден), задаю \\?\Device\Harddisk0\Partition1 – аналогично (\\.\ тоже, без Device\ та же история). Ещё фигурируют какие-то \Device\Harddisk0\DR0 и т.п. – тоже не работает (что это такое вообще?)

    5. Откуда берутся GUID дисков на основе MBR (или вообще с boot-секторами в начале) типа флешек и пр.? Там же нигде эти GUID не зашиты!
     
  2. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    313
    Адрес:
    Кольца Сатурна
    По поводу вопроса №2...

    С помощью DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT_EX) можно получить инфу обо всех разделах и их GUID (как для MBR, так и для GPT разделов). И дальше через GetVolumePathNamesForVolumeName('\\?\Volume{GUID}\') получить инфу о буквах/путях. Через GetVolumeInformation('\\?\Volume{GUID}\') получаем метки, файловую систему и пр. ерунду.
    Есть только один интересный нюанс.
    На хардах всё работает.
    А вот с флешкой глюки: \\?\Volume{GUID}\ не совпадает с тем, что выдаёт утилита mountvol, и GetVolumePathNamesForVolumeName/GetVolumeInformation тоже ничего не выдают.
    Вопрос: как сопоставить GUID диска с GUID, который указан в \\?\Volume{GUID}\. По логике он должен совпадать. Код прикрепляю (тут этот GUID отображается как PartitionId).
     

    Вложения:

  3. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    292
    По поводу вопроса #2, я когда то соотносил их по номерам, т.е. я брал везде номер диска, перечислял и сравнивал. Решение не элегантное, но рабочее. С флэшками вообще проблем много. Часть из них считает себя ЖД, а та часть которая сделана в Китае вообще может удивить.

    А по 4 вопросу, могу сказать только то, что для открытия именно устройств необходимо чаще всего повышать права, либо до админских, либо до еще каких. Например \\.\C: открывается с правами пользователя, а C:\ только с правами админа или системы (не помню точно).
     
  4. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    332
    Код (Text):
    1. Const wbemFlagReturnImmediately = &h10
    2. Const wbemFlagForwardOnly = &h20
    3. strComputer = "."
    4. set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
    5. Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDiskToPartition", "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly)
    6. For Each objItem In colItems
    7.     wscript.stdout.write objItem.Antecedent & ";" & objItem.Dependent & vbcrlf
    8. Next
    Код (Text):
    1. E:\123>cscript test1.vbs
    2. \\HOME\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #1";\\HOME\root\cimv2:Win32_LogicalDisk.DeviceID="C:"
    3. \\HOME\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #0";\\HOME\root\cimv2:Win32_LogicalDisk.DeviceID="D:"
    4. \\HOME\root\cimv2:Win32_DiskPartition.DeviceID="Disk #2, Partition #0";\\HOME\root\cimv2:Win32_LogicalDisk.DeviceID="E:"
    Результаты тупо в виде строчек, их можно пропарсить регулярками.
     
    Jin X нравится это.
  5. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    313
    Адрес:
    Кольца Сатурна
    Что-то я не совсем понял, какой номер диска перечисляли и с чем сравнивали?

    f13nd, спасибо, сохраню в копилку, но хочется чисто на WinAPI всё сделать без WMI.
    Paragon Hard Disk Manager и пр. редакторы дисков, интересно, WMI использует или как? А diskmgmt.msc?

    И я хочу понять, почему PartitionId, выданный DeviceIoControl(IOCTL_DISK_GET_DRIVE_LAYOUT_EX) не совпадает с VolumeName, выданным FindFirst/NextVolume, на флешке? Причём, в таблице GPT (если флеха отформатирована как GPT-диск) указан именно ParitionId. Откуда берётся этот VolumeName?
    Откуда берётся PartitionId для MBR-дисков и почему он снова не совпадает с VolumeName на флешках, отформатированных как MBR-диск?
    --- Сообщение объединено, 30 окт 2018 ---
    По идее, разница между разделом и томом должна быть в том, что раздел может быть "расширенным", т.е. содержать не том, а лишь ссылку на другую таблицу разделов (в MBR-структуре). Ну и ещё раздел может быть неотформатированным или иметь неведомую для ОС структуру (или файловую систему), тогда это тоже не будет томом. А в остальном же вроде всё должно быть одинаково. Пусть не каждый раздел – это том, зато каждый том – это раздел. Может, я неправильно понимаю эту разницу?
    --- Сообщение объединено, 30 окт 2018 ---
    Под виртуалкой XP и 7-ка, кстати, на MBR-харде в PartitionId показали нули, а вот VolumeName – нормальный GUID. Т.е. там эта проблема не только на флешках, но и на хардах (с MBR, ибо с GPT всё ок... в 7-ке, в XP32 они не поддерживаются).
    Только в 10-ке PartitionId имеет даже MBR-раздел (может, ещё и в 8-ке – не знаю, у меня нет её просто).

    Вот и вопрос: как по VolumeName (или его GUID) получить инфу о номере харда и раздела? Ну или имея номер харда/раздела получить GUID тома...
     
  6. f13nd

    f13nd Active Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    332
    Судя по всему использует dmdskmgr.dll, который ком объект "DiskManagement" и в его импорте никаких апи для управления дисками нету. Ком, который использует ком. Если посмотреть rclsid его CoCreateInstance'ов (они там статические), то будет вот такая картина:
    E13B6686-3F39-11D0-96F6-00A0C9191601 DiskManagement.SnapIn
    7086AD76-44BD-11D0-81ED-00A0C90FC491 DiskManagement.UITasks
    9C38ED61-D565-4728-AEEE-C80952F0ECDE Virtual Disk Service Loader
    E13B6688-3F39-11D0-96F6-00A0C9191601 DiskManagement.DataObject
    17D6CCD8-3B7B-11D2-B9E0-00C04FD8DBF7 DsObjectPicker
    9C38ED61-D565-4728-AEEE-C80952F0ECDE Virtual Disk Service Loader
    Я почти уверен, что при запросе через wmi все как раз и упрется в этот же самый ком объект. Давно пора привыкнуть, что для большинства задачек в windows апи-решений не бывает. Ну и как направление поисков интерфейса с апи на ком могу посоветовать SetupDiEnumDeviceInfo из setupapi.dll.
     
  7. drem1lin

    drem1lin Member

    Публикаций:
    0
    Регистрация:
    17 мар 2009
    Сообщения:
    292
    Jin X, изначально задача была
    для этого я пользовался CTL code https://docs.microsoft.com/en-us/wi...l/ni-winioctl-ioctl_storage_get_device_number, но приходится конечно перебирать, что бы полностью соотнести
     
    Jin X нравится это.
  8. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    313
    Адрес:
    Кольца Сатурна
    А к чему вы этот код применяете? К \\.\PhysicalDriveX как-то непонятно, а \\?\Volume{GUID}\ я не могу открыть, CreateFile выдаёт ошибку (даже если убрать последний слэш).
    --- Сообщение объединено, 31 окт 2018 ---
    А, я понял, применяем к \\.\X:
    Спасибо, это работает. А вот \\?\Volume{GUID}, не имеющие буквы, как можно соотнести, интересно?
    --- Сообщение объединено, 31 окт 2018 ---
    Навскидку может кто знает, как по букве найти имя тома, т.е. \\?\Volume{GUID} ?
    --- Сообщение объединено, 31 окт 2018 ---
    Вот такой вариант сделал пока... :)
    --- Сообщение объединено, 31 окт 2018 ---
    Нет, немного неправильно. GetVolumeInformation'у нужен слэш на конце...
    Вот так будет лучше :)
    --- Сообщение объединено, 31 окт 2018 ---
    Короче, второй файл который :)
     

    Вложения:

  9. z0mailbox

    z0mailbox z0

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    634
    Адрес:
    Russia СПБ
    я находил physical_drive по букве диска или по volume_name через IOCTL_STORAGE_GET_DEVICE_NUMBER и IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
    а volume_name по path - через GetVolumePathNameW и GetVolumeNameForVolumeMountPointW
    работало даже для mountpoints
    код примерно такой
    Код (C++):
    1.        
    2. do
    3. {
    4.         hDrive = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    5.         if(INVALID_HANDLE_VALUE == hDrive)
    6.         {
    7.             result = GetLastError();
    8.             break;
    9.         }
    10.  
    11.         if(!DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &Info, sizeof(Info), &dwBytes, NULL))
    12.         {
    13.             result = GetLastError();
    14.  
    15.             if((ERROR_INVALID_FUNCTION == result) || (ERROR_INVALID_PARAMETER == result))
    16.             {
    17.                 VOLUME_DISK_EXTENTS extents;
    18.  
    19.                 result = ERROR_SUCCESS;
    20.  
    21.                 if(!DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwBytes, NULL))
    22.                 {
    23.                     result = GetLastError();
    24.  
    25.                     if((ERROR_INSUFFICIENT_BUFFER == result) || (ERROR_MORE_DATA == result))
    26.                     {
    27.                         result = ERROR_INVALID_DRIVE;
    28.                     }
    29.                     break;
    30.                 }
    31.                 Info.DeviceNumber = extents.Extents[0].DiskNumber;
    32.             } else break;
    33.         } else
    34.         {
    35.             if(FILE_DEVICE_DISK != Info.DeviceType)
    36.             {
    37.                 result = ERROR_INVALID_DRIVE;
    38.                 break;
    39.             }
    40.         }
    41.         wsprintfA(path, "\\\\.\\PhysicalDrive%u", Info.DeviceNumber);
    42.  
    43.         CloseHandle(hDrive);
    44.         hDrive = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    45.         if(INVALID_HANDLE_VALUE == hDrive)
    46.         {
    47.             result = GetLastError();
    48.             break;
    49.         }
    50. } while(0);
    причем в первый CreateFile передается path в виде \\.\disk_letter или \\.\volume_name
     
    Последнее редактирование модератором: 13 ноя 2018
  10. Jin X

    Jin X Active Member

    Публикаций:
    0
    Регистрация:
    15 янв 2009
    Сообщения:
    313
    Адрес:
    Кольца Сатурна
    z0mailbox, а какой смысл использовать оба кода?
    IOCTL_STORAGE_GET_DEVICE_NUMBER выдаст номер диска и номер partition'а, а IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS – номер диска, его начало и размер.
    Разве одного из них недостаточно?
     
  11. z0mailbox

    z0mailbox z0

    Публикаций:
    0
    Регистрация:
    3 фев 2005
    Сообщения:
    634
    Адрес:
    Russia СПБ
    GET_DEVICE_NUMBER не срабатывает в случае если volume расположен на нескольких физических дисках
     
    Jin X нравится это.