Relevant code is as follows:
std::wstring path = ApplicationData::Current->LocalFolder->Path->Data();
std::wstring testFileName = path + std::wstring(L"\\TestVariablySized");
this->hMappedFile = CreateFile2(
testFileName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
OPEN_ALWAYS,
NULL);
uint32_t checkF = GetLastError();
DISK_GEOMETRY geo = { 0 };
DWORD bReturned = 0;
bool controlCheck = DeviceIoControl(
(HANDLE)hMappedFile, // handle to device
IOCTL_DISK_GET_DRIVE_GEOMETRY, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
(LPVOID)&geo, // output buffer
(DWORD)sizeof(geo), // size of output buffer
(LPDWORD)&bReturned, // number of bytes returned
NULL);
uint32_t check = GetLastError();
After this, controlCheck
is false and check
is ERROR_INVALID_PARAMETER
. checkF
is ERROR_ALREADY_EXISTS
, which shouldn't be a problem here.
As far as I can tell, I've called DeviceIoControl()
in a way consistent with the IOCTL_DISK_GET_DRIVE_GEOMETRY
documentation.
, but clearly I'm missing something. Your help is most appreciated.
Edit:
Per responses received, I altered things to be as follows:
HANDLE hDevice = CreateFile2(
L"\\.\PhysicalDrive0",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
OPEN_EXISTING,
NULL);
uint32_t checkF = GetLastError();
DISK_GEOMETRY geo = { 0 };
DWORD bReturned = 0;
bool controlCheck = DeviceIoControl(
hDevice, // handle to device
IOCTL_DISK_GET_DRIVE_GEOMETRY, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
(LPVOID)&geo, // output buffer
(DWORD)sizeof(geo), // size of output buffer
(LPDWORD)&bReturned, // number of bytes returned
NULL);
uint32_t check = GetLastError();
CloseHandle(hDevice);
Which should be closer to being correct, even if it's not quite correct yet. checkF
is ERROR_FILE_NOT_FOUND
, which I found strange. I tried "\\.\PhysicalDrive1"
and "\\.\PhysicalDrive2"
as well, but receive the same result. controlCheck
is still false, but check is now ERROR_INVALID_HANDLE
.
As far as I can tell, I've called
DeviceIoControl()
in a way consistent with theIOCTL_DISK_GET_DRIVE_GEOMETRY
documentation
Actually, you are not, because you did not pay attention to this tidbit of the documentation:
hDevice
A handle to the disk device from which the geometry is to be retrieved. To retrieve a device handle, call theCreateFile
function.
You are not passing a handle to a disk device, you are passing a handle to a filesystem path instead.
When calling CreateFile2()
to get a handle to a disk device, you need to specify a physical device in \\.\PhysicalDriveX
format instead, not a filesystem path.
Also, as the CreateFile2()
documentation says:
The following requirements must be met for such a call to succeed:
- The caller must have administrative privileges. For more information, see Running with Special Privileges.
- The
dwCreationDisposition
parameter must have theOPEN_EXISTING
flag.- When opening a volume or floppy disk, the
dwShareMode
parameter must have theFILE_SHARE_WRITE
flag.
You are using OPEN_ALWAYS
instead of OPEN_EXISTING
.
Please read the "Physical Disks and Volumes" section of the CreateFile2()
documentation more carefully.
Try something more like this instead:
std::wstring path = L"\\\\.\\PhysicalDrive0";
DWORD errCode;
hMappedFile = CreateFile2(
path.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
OPEN_EXISTING,
NULL);
if (this->hMappedFile == INVALID_HANDLE_VALUE)
{
errCode = GetLastError();
// handle error as needed...
}
else
{
DISK_GEOMETRY geo = { 0 };
DWORD dwReturned = 0;
bool controlCheck = DeviceIoControl(
hMappedFile, // handle to device
IOCTL_DISK_GET_DRIVE_GEOMETRY, // dwIoControlCode
NULL, // lpInBuffer
0, // nInBufferSize
&geo, // output buffer
sizeof(geo), // size of output buffer
&dwReturned, // number of bytes returned
NULL);
if (!controlCheck)
{
errCode = GetLastError();
// handle error as needed...
}
else
{
// use drive as needed...
}
CloseHandle(hMappedFile);
}