为啥 DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX 失败?

Posted

技术标签:

【中文标题】为啥 DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX 失败?【英文标题】:Why DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX failed?为什么 DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX 失败? 【发布时间】:2020-07-30 01:42:30 【问题描述】:

我在使用 DeviceIoControl 查询 PartitionCount 时遇到问题。

#include <tchar.h>
#include <iostream>
#include <windows.h>

int wmain(int argc, wchar_t *argv[])

    HANDLE hDevice = CreateFileA("\\\\.\\PhysicalDrive0", 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
    if (hDevice == INVALID_HANDLE_VALUE) 
        return 0;
    
    else 
            DWORD dwInfoSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX)+sizeof(PARTITION_INFORMATION_EX)* 3;
            DRIVE_LAYOUT_INFORMATION_EX* tpDriveLayoutInformationEx = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(dwInfoSize);
            if (NULL == tpDriveLayoutInformationEx) 
                CloseHandle(hDevice);
                return(-1);
            
            DWORD dwResult = 0;
            BOOL bResult = DeviceIoControl(hDevice,                            // handle to device
                IOCTL_DISK_GET_DRIVE_LAYOUT_EX,          // dwIoControlCode
                NULL,                                        // lpInBuffer
                0,                                           // nInBufferSize
                tpDriveLayoutInformationEx,          // output buffer
                dwInfoSize,                           // size of output buffer
                &dwResult,                          // number of bytes returned
                NULL                          // OVERLAPPED structure
                );
            if (0 == bResult) 
                printf("DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX FAILED", "");
                CloseHandle(hDevice);
                return 0;
            
            printf("PartitionCount: %s", tpDriveLayoutInformationEx->PartitionCount);

    system("pause");
    return 0;

为什么 DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX 失败了? 请帮我。 谢谢。

【问题讨论】:

如果操作失败或挂起,返回值为零。要获取扩展错误信息,请调用 GetLastError。 我可以正常运行代码,但是将%s更改为%d,因为PartitionCountDWORD。希望您可以使用GetLastError查看错误码,以便我们为您提供更多帮助。 GetLastError() = 122. 【参考方案1】:

可以参考How to call DeviceIoControl to retrieve the amount of memory it needs?

并根据VOLUME_DISK_EXTENTS

扩展区是一个磁盘上连续运行的扇区。当返回的范围数大于一 (1) 时,将返回错误代码 ERROR_MORE_DATA。您应该再次调用 DeviceIoControl,在第一次 DeviceIoControl 调用后根据 NumberOfDiskExtents 的值分配足够的缓冲区空间。

如果您传递一个小于 sizeof(VOLUME_DISK_EXTENTS) 的输出缓冲区,则在 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 控制代码中也有记录:

如果输出缓冲区小于sizeof(VOLUME_DISK_EXTENTS),则调用失败,GetLastError 返回ERROR_INSUFFICIENT_BUFFERlpBytesReturned 为 0(零)。

【讨论】:

以上是关于为啥 DeviceIoControl IOCTL_DISK_GET_DRIVE_LAYOUT_EX 失败?的主要内容,如果未能解决你的问题,请参考以下文章

Delphi - 使用 DeviceIoControl 传递 IOCTL_DISK_GET_LENGTH_INFO 来获取闪存介质物理大小(非分区)

SCSI INQUIRY 命令的 DeviceIoControl 返回错误 50

DeviceIoControl 完全不起作用,返回时 SystemBuffer 为空

释放 DeviceIoControl 分配的内存

使用 DeviceIoControl 从应用程序向驱动程序发送数据

为啥在 VB.NET 中使用 DeviceIoControl 进行文件枚举比在 C++ 中更快?