Приветствую! Есть \\.\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... С помощью 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).
По поводу вопроса #2, я когда то соотносил их по номерам, т.е. я брал везде номер диска, перечислял и сравнивал. Решение не элегантное, но рабочее. С флэшками вообще проблем много. Часть из них считает себя ЖД, а та часть которая сделана в Китае вообще может удивить. А по 4 вопросу, могу сказать только то, что для открытия именно устройств необходимо чаще всего повышать права, либо до админских, либо до еще каких. Например \\.\C: открывается с правами пользователя, а C:\ только с правами админа или системы (не помню точно).
Код (Text): Const wbemFlagReturnImmediately = &h10 Const wbemFlagForwardOnly = &h20 strComputer = "." set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2") Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_LogicalDiskToPartition", "WQL", wbemFlagReturnImmediately + wbemFlagForwardOnly) For Each objItem In colItems wscript.stdout.write objItem.Antecedent & ";" & objItem.Dependent & vbcrlf Next Код (Text): E:\123>cscript test1.vbs \\HOME\root\cimv2:Win32_DiskPartition.DeviceID="Disk #0, Partition #1";\\HOME\root\cimv2:Win32_LogicalDisk.DeviceID="C:" \\HOME\root\cimv2:Win32_DiskPartition.DeviceID="Disk #1, Partition #0";\\HOME\root\cimv2:Win32_LogicalDisk.DeviceID="D:" \\HOME\root\cimv2:Win32_DiskPartition.DeviceID="Disk #2, Partition #0";\\HOME\root\cimv2:Win32_LogicalDisk.DeviceID="E:" Результаты тупо в виде строчек, их можно пропарсить регулярками.
Что-то я не совсем понял, какой номер диска перечисляли и с чем сравнивали? 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 тома...
Судя по всему использует 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.
Jin X, изначально задача была для этого я пользовался CTL code https://docs.microsoft.com/en-us/wi...l/ni-winioctl-ioctl_storage_get_device_number, но приходится конечно перебирать, что бы полностью соотнести
А к чему вы этот код применяете? К \\.\PhysicalDriveX как-то непонятно, а \\?\Volume{GUID}\ я не могу открыть, CreateFile выдаёт ошибку (даже если убрать последний слэш). --- Сообщение объединено, 31 окт 2018 --- А, я понял, применяем к \\.\X: Спасибо, это работает. А вот \\?\Volume{GUID}, не имеющие буквы, как можно соотнести, интересно? --- Сообщение объединено, 31 окт 2018 --- Навскидку может кто знает, как по букве найти имя тома, т.е. \\?\Volume{GUID} ? --- Сообщение объединено, 31 окт 2018 --- Вот такой вариант сделал пока... --- Сообщение объединено, 31 окт 2018 --- Нет, немного неправильно. GetVolumeInformation'у нужен слэш на конце... Вот так будет лучше --- Сообщение объединено, 31 окт 2018 --- Короче, второй файл который
я находил physical_drive по букве диска или по volume_name через IOCTL_STORAGE_GET_DEVICE_NUMBER и IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS а volume_name по path - через GetVolumePathNameW и GetVolumeNameForVolumeMountPointW работало даже для mountpoints код примерно такой Код (C++): do { hDrive = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(INVALID_HANDLE_VALUE == hDrive) { result = GetLastError(); break; } if(!DeviceIoControl(hDrive, IOCTL_STORAGE_GET_DEVICE_NUMBER, NULL, 0, &Info, sizeof(Info), &dwBytes, NULL)) { result = GetLastError(); if((ERROR_INVALID_FUNCTION == result) || (ERROR_INVALID_PARAMETER == result)) { VOLUME_DISK_EXTENTS extents; result = ERROR_SUCCESS; if(!DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, &extents, sizeof(extents), &dwBytes, NULL)) { result = GetLastError(); if((ERROR_INSUFFICIENT_BUFFER == result) || (ERROR_MORE_DATA == result)) { result = ERROR_INVALID_DRIVE; } break; } Info.DeviceNumber = extents.Extents[0].DiskNumber; } else break; } else { if(FILE_DEVICE_DISK != Info.DeviceType) { result = ERROR_INVALID_DRIVE; break; } } wsprintfA(path, "\\\\.\\PhysicalDrive%u", Info.DeviceNumber); CloseHandle(hDrive); hDrive = CreateFileA(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if(INVALID_HANDLE_VALUE == hDrive) { result = GetLastError(); break; } } while(0); причем в первый CreateFile передается path в виде \\.\disk_letter или \\.\volume_name
z0mailbox, а какой смысл использовать оба кода? IOCTL_STORAGE_GET_DEVICE_NUMBER выдаст номер диска и номер partition'а, а IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS – номер диска, его начало и размер. Разве одного из них недостаточно?