c++ - 带有 IOCTL_DISK_GET_DRIVE_GEOMETRY 的 DeviceIoControl() 失败并返回错误代码 87。为什么?

标签 c++ visual-studio deviceiocontrol

相关代码如下:

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,这在这里应该不是问题。

据我所知,我以与 IOCTL_DISK_GET_DRIVE_GEOMETRY documentation 一致的方式调用了 DeviceIoControl() . ,但显然我遗漏了一些东西。非常感谢您的帮助。

编辑:

根据收到的回复,我将内容更改如下:

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

最佳答案

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() 的“物理磁盘和卷”部分更仔细地记录。

尝试更像这样的东西:

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

关于c++ - 带有 IOCTL_DISK_GET_DRIVE_GEOMETRY 的 DeviceIoControl() 失败并返回错误代码 87。为什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40471074/

相关文章:

c++ - 如何使用 vn_rdwr() API 组合 osx 内核扩展中的两个文件

C++:在 DLL 中绑定(bind)类函数

c++ - 在 Visual Studio 中使用/MT 标志编译 SFML

c# - Nuget 返回意外状态代码 '404 Not Found' - 本地驱动器上的包

c++ - 获取文件的完整路径给定其 "Reference Number"

c++ - 将对象传递给函数和构造函数中的动态内存分配

c++ - 如何将 SDL_renderer 转换为 SDL_window?

.net - 是否有一个属性来确定是否加载了表单(及其控件)?

c++ - DeviceIoControl 对内存位置的访问无效