Reputation: 456
It's possible to open a disk volume as a file by using a function call like
HANDLE hDisk = CreateFile("\\\\.\\G:", GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, 0, NULL);
However, that only allows access to the area of the partition occupied by the volume - which may not be all of it.
Is it possible, given the drive letter of the volume, to open a handle to the entire partition? The true size of the partition can be calculated by calling DeviceIoControl(...IOCTL_GET_DRIVE_GEOMETRY...)
on the volume handle, but reads/writes beyond the end of the volume do not work.
Upvotes: 1
Views: 439
Reputation: 456
I found what appears to be a simpler solution for my use case: the FSCTL_ALLOW_EXTENDED_DASD_IO control code removes the restriction on the volume handle, allowing access to sectors on the partition outside the filesystem. So apart from error checking, it's a one-line addition to my code:
DeviceIoControl(hDisk, FSCTL_ALLOW_EXTENDED_DASD_IO, NULL, 0, NULL, 0, &dwBytesRead, NULL);
Upvotes: 0
Reputation: 33744
exist different device objects for whole disk (fdo) and for partitions (pdo) on it. the first created device for whole disk. it have canonical name format
#define FDO_NAME_FORMAT "\\Device\\Harddisk%d\\DR%d"
also well known symbolic links created for it
"\\Device\\Harddisk%d\\Partition0"
"\\DosDevices\\PhysicalDrive%d"
then already, if disk formated and exist partitions on it - created additional volume devices (pdo). the native name of this devices have form
"\\Device\\HarddiskVolume%d"
and well known symbolic links format for partitions -
"\\Device\\HarddiskX\\PartitionY"
where X
the same as for whole disk and Y
always not 0. so disk device is \Device\HarddiskX\DRX
or \Device\HarddiskX\Partition0
or \DosDevices\PhysicalDriveX
and partitions for on this disk have names \Device\HarddiskX\PartitionY
(symbolic link to \Device\HarddiskVolume%d
). when volume is mounted - mount manager can assign letter to device, like \\\?\c:
but this is only symbolic link to some volume device.
Is it possible, given the drive letter of the volume, to open a handle to the entire partition?
yes. more correct say handle to entire disk (or partition 0). we can do by send IOCTL_STORAGE_GET_DEVICE_NUMBER
to volume device and use DeviceNumber
from STORAGE_DEVICE_NUMBER
to construct the name of the disk ("\\\\?\\PhysicalDrive%d"
) on which this partition live. so code can look like
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;
}
here i read the last sector of disk. usual i view here EFI PART
as first 8 in buffer. on some (removable) flash i view ...NTFS
label
Upvotes: 1