IOCTL_DISK_GET_DRIVE_GEOMETRY 的 DeviceIoControl() 失败并返回错误代码 87。为什么?
DeviceIoControl() with IOCTL_DISK_GET_DRIVE_GEOMETRY is failing and returning error code 87. Why?
相关代码如下:
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();
此后,controlCheck
为假,check
为ERROR_INVALID_PARAMETER
。 checkF
是ERROR_ALREADY_EXISTS
,这里应该不是问题。
据我所知,我调用 DeviceIoControl()
的方式与 IOCTL_DISK_GET_DRIVE_GEOMETRY
documentation 一致。
,但显然我遗漏了一些东西。非常感谢您的帮助。
编辑:
根据收到的回复,我将内容更改如下:
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);
应该更接近于正确,即使它还不是很正确。 checkF
是 ERROR_FILE_NOT_FOUND
,我觉得很奇怪。我也尝试了 "\.\PhysicalDrive1"
和 "\.\PhysicalDrive2"
,但收到相同的结果。 controlCheck
仍然是 false,但检查现在是 ERROR_INVALID_HANDLE
.
As far as I can tell, I've called DeviceIoControl()
in a way consistent with the IOCTL_DISK_GET_DRIVE_GEOMETRY
documentation
其实你不是,因为你没有注意文档的这个花絮:
hDevice
A handle to the disk device from which the geometry is to be retrieved. To retrieve a device handle, call the CreateFile
function.
您没有将句柄传递给 磁盘设备,而是将句柄传递给 文件系统路径。
当调用 CreateFile2()
获取 磁盘设备的句柄时 ,您需要指定 \.\PhysicalDriveX
格式的物理设备,而不是文件系统路径。
此外,正如 CreateFile2()
文档所说:
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 the OPEN_EXISTING
flag.
- When opening a volume or floppy disk, the
dwShareMode
parameter must have the FILE_SHARE_WRITE
flag.
您正在使用 OPEN_ALWAYS
而不是 OPEN_EXISTING
。
请仔细阅读 CreateFile2()
文档的 "Physical Disks and Volumes" 部分。
尝试更像这样的东西:
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);
}
相关代码如下:
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();
此后,controlCheck
为假,check
为ERROR_INVALID_PARAMETER
。 checkF
是ERROR_ALREADY_EXISTS
,这里应该不是问题。
据我所知,我调用 DeviceIoControl()
的方式与 IOCTL_DISK_GET_DRIVE_GEOMETRY
documentation 一致。
,但显然我遗漏了一些东西。非常感谢您的帮助。
编辑:
根据收到的回复,我将内容更改如下:
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);
应该更接近于正确,即使它还不是很正确。 checkF
是 ERROR_FILE_NOT_FOUND
,我觉得很奇怪。我也尝试了 "\.\PhysicalDrive1"
和 "\.\PhysicalDrive2"
,但收到相同的结果。 controlCheck
仍然是 false,但检查现在是 ERROR_INVALID_HANDLE
.
As far as I can tell, I've called
DeviceIoControl()
in a way consistent with theIOCTL_DISK_GET_DRIVE_GEOMETRY
documentation
其实你不是,因为你没有注意文档的这个花絮:
hDevice
A handle to the disk device from which the geometry is to be retrieved. To retrieve a device handle, call theCreateFile
function.
您没有将句柄传递给 磁盘设备,而是将句柄传递给 文件系统路径。
当调用 CreateFile2()
获取 磁盘设备的句柄时 ,您需要指定 \.\PhysicalDriveX
格式的物理设备,而不是文件系统路径。
此外,正如 CreateFile2()
文档所说:
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.
您正在使用 OPEN_ALWAYS
而不是 OPEN_EXISTING
。
请仔细阅读 CreateFile2()
文档的 "Physical Disks and Volumes" 部分。
尝试更像这样的东西:
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);
}