существуют различные объекты устройства для всего диска (fdo) и для разделов (pdo) на нем. первое созданное устройство для всего диска. имеет канонический формат имени
#define FDO_NAME_FORMAT "\\Device\\Harddisk%d\\DR%d"
для него созданы также известные символические ссылки
"\\Device\\Harddisk%d\\Partition0"
"\\DosDevices\\PhysicalDrive%d"
тогда уже, если диск отформатирован и на нем существуют разделы - создаются дополнительные тома устройства (pdo). родное название этого устройства имеет вид
"\\Device\\HarddiskVolume%d"
и хорошо известный формат символических ссылок для разделов -
"\\Device\\HarddiskX\\PartitionY"
, где X
то же самое, что и для всего диска, и Y
всегда не 0. Таким образом, дисковое устройство имеет \Device\HarddiskX\DRX
или \Device\HarddiskX\Partition0
или \DosDevices\PhysicalDriveX
, а разделы для этого диска имеют имена \Device\HarddiskX\PartitionY
(символическая ссылка до \Device\HarddiskVolume%d
). когда том смонтирован - менеджер монтирования может назначить букву устройству, например \\\?\c:
, но это только символическая ссылка на некоторое устройство тома.
Можно ли, учитывая букву диска тома, открыть ручку
на весь раздел?
да. правильнее сказать дескриптор всего диска (или раздела 0). мы можем отправить IOCTL_STORAGE_GET_DEVICE_NUMBER
на том устройства и использовать DeviceNumber
из STORAGE_DEVICE_NUMBER
, чтобы создать имя диска ("\\\\?\\PhysicalDrive%d"
), на котором этот раздел находится. поэтому код может выглядеть как
ULONG dv(PCWSTR VolumeName)
{
HANDLE hFile = CreateFile(VolumeName, 0, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
union {
STORAGE_DEVICE_NUMBER sdn;
DISK_GEOMETRY_EX dg;
};
OVERLAPPED ov = {};
ULONG dwError = DeviceIoControl(hFile, IOCTL_STORAGE_GET_DEVICE_NUMBER, 0, 0, &sdn, sizeof(sdn), 0, &ov)
? NOERROR : GetLastError();
CloseHandle(hFile);
if (dwError == NOERROR)
{
WCHAR name[32];
swprintf(name, L"\\\\?\\PhysicalDrive%d", sdn.DeviceNumber);
hFile = CreateFile(name, FILE_GENERIC_READ,
FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
if (hFile != INVALID_HANDLE_VALUE)
{
if (DeviceIoControl(hFile, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, 0, 0, &dg, sizeof(dg), 0, &ov))
{
FILE_ALIGNMENT_INFO fai;
if (GetFileInformationByHandleEx(hFile, FileAlignmentInfo, &fai, sizeof(fai)))
{
if (fai.AlignmentRequirement < 2*sizeof(void*))
{
fai.AlignmentRequirement = 0;
}
ULONG_PTR a = fai.AlignmentRequirement;
if (PVOID buf = _malloca(dg.Geometry.BytesPerSector + a))
{
PVOID pv = (PVOID)(((ULONG_PTR)buf + a) & ~a);
LARGE_INTEGER ByteOffset;
ByteOffset.QuadPart = dg.DiskSize.QuadPart - dg.Geometry.BytesPerSector;
ov.Offset = ByteOffset.LowPart;
ov.OffsetHigh = ByteOffset.HighPart;
ReadFile(hFile, pv, dg.Geometry.BytesPerSector, 0, &ov);
_freea(buf);
}
}
}
CloseHandle(hFile);
}
}
return dwError;
}
здесь я прочитал последний сектор диска. обычно я рассматриваю здесь EFI PART
как первые 8 в буфере. на некоторых (съемных) вспышках я вижу ...NTFS
метку