【问题标题】:DeviceIoControl() with IOCTL_DISK_GET_DRIVE_GEOMETRY is failing and returning error code 87. Why?带有 IOCTL_DISK_GET_DRIVE_GEOMETRY 的 DeviceIoControl() 失败并返回错误代码 87。为什么?
【发布时间】:2017-03-21 03:28:05
【问题描述】:

相关代码如下:

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 为 false,checkERROR_INVALID_PARAMETERcheckFERROR_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);

这应该更接近正确,即使它还不是很正确。 checkFERROR_FILE_NOT_FOUND,我觉得很奇怪。我也尝试了"\\.\PhysicalDrive1""\\.\PhysicalDrive2",但得到了相同的结果。 controlCheck 仍然是 false,但检查现在是 ERROR_INVALID_HANDLE

【问题讨论】:

  • AFAIK,IOCTL_DISK_* 仅在您打开磁盘本身时有效,您无法将它们发送到磁盘内卷内文件的打开句柄。

标签: c++ visual-studio deviceiocontrol


【解决方案1】:

据我所知,我调用 DeviceIoControl() 的方式与 IOCTL_DISK_GET_DRIVE_GEOMETRY 文档一致

其实你不是,因为你没有注意文档的这个花絮:

hDevice
要从中检索几何的磁盘设备的句柄。要检索设备句柄,请调用 CreateFile 函数。

您没有将句柄传递给磁盘设备,而是将句柄传递给文件系统路径

当调用CreateFile2() 获取磁盘设备 的句柄时,您需要指定\\.\PhysicalDriveX 格式的物理设备,而不是文件系统路径。

另外,正如CreateFile2() 文档所说:

必须满足以下要求才能使此类调用成功:

  • 调用者必须具有管理权限。有关详细信息,请参阅以特殊权限运行。
  • dwCreationDisposition 参数必须具有OPEN_EXISTING 标志。
  • 打开卷或软盘时,dwShareMode 参数必须具有FILE_SHARE_WRITE 标志。

您使用的是OPEN_ALWAYS 而不是OPEN_EXISTING

请仔细阅读CreateFile2() 文档的“物理磁盘和卷”部分。

试试类似的方法:

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);
}

【讨论】:

  • @MNagy: 那是因为你输入到CreateFile2()的字符串是错误的,所以它失败了,返回INVALID_HANDLE_VALUE并将错误代码设置为ERROR_FILE_NOT_FOUND。您没有检查任何失败,因此您将无效句柄传递给DeviceIoControl(),这就是它报告ERROR_INVALID_HANDLE 错误的原因。您的输入字符串使用 字符串文字,因此您需要通过将斜杠加倍来转义斜杠,例如:L"\\\\.\\PhysicalDrive0".
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 2011-01-18
  • 1970-01-01
  • 1970-01-01
  • 2020-12-20
相关资源
最近更新 更多