c++ - 如何调用 DeviceIoControl 来检索它需要的内存量?

标签 c++ c winapi driver kernel32

我正在尝试调用 DeviceIoControl(IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS) API,作为 shown here ,但我需要它首先“告诉我”它需要多少内存(与我链接到的代码不同。)

所以我这样调用它:

//First determine how much data do we need?
BYTE dummyBuff[1];
DWORD bytesReturned = 0;
if(!::DeviceIoControl(hDevice, dwIoControlCode, lpInBuffer, nInBufferSize, 
    dummyBuff, sizeof(dummyBuff), &bytesReturned, NULL))
{
    //Check last error
    int nError = ::GetLastError();
    if(nOSError == ERROR_INSUFFICIENT_BUFFER ||
        nOSError == ERROR_MORE_DATA)
    {
        //Alloc memory from 'bytesReturned' ...
    }
}

但它总是返回错误代码 87,或 ERROR_INVALID_PARAMETER 而我的 bytesReturned 始终为 0。

那我做错了什么?

最佳答案

获取所有磁盘卷范围的说明记录在 VOLUME_DISK_EXTENTS structure 下:

When the number of extents returned is greater than one (1), the error code ERROR_MORE_DATA is returned. You should call DeviceIoControl again, allocating enough buffer space based on the value of NumberOfDiskExtents after the first DeviceIoControl call.

如果传递小于 sizeof(VOLUME_DISK_EXTENTS) 的输出缓冲区,该行为也记录在 IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS control code 中:

If the output buffer is less than sizeof(VOLUME_DISK_EXTENTS), the call fails, GetLastError returns ERROR_INSUFFICIENT_BUFFER, and lpBytesReturned is 0 (zero).

虽然这解释了 lpBytesReturned 中的返回值,但它没有解释错误代码 87 (ERROR_INVALID_PARAMETER)1)

以下代码将返回所有卷的磁盘范围:

VOLUME_DISK_EXTENTS vde = { 0 };
DWORD bytesReturned = 0;
if ( !::DeviceIoControl( hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, 
                         (void*)&vde, sizeof(vde), &bytesReturned, NULL ) )
{
    // Check last error
    int nError = ::GetLastError();
    if ( nError != ERROR_MORE_DATA )
    {
        // Unexpected error -> error out
        throw std::runtime_error( "DeviceIoControl() failed." );
    }

    size_t size = offsetof( VOLUME_DISK_EXTENTS, Extents[vde.NumberOfDiskExtents] );
    std::vector<BYTE> buffer( size );
    if ( !::DeviceIoControl( hDevice, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0, 
                             (void*)buffer.data(), size, &bytesReturned, NULL ) )
    {
        // Unexpected error -> error out
        throw std::runtime_error( "DeviceIoControl() failed." );
    }
    // At this point we have a fully populated VOLUME_DISK_EXTENTS structure
    const VOLUME_DISK_EXTENTS& result =
        *reinterpret_cast<const VOLUME_DISK_EXTENTS*>( buffer.data() );
}
else
{
    // Call succeeded; vde is populated with single disk extent.
}


附加引用:


1) 我猜测,BYTE[1] 开始于一个内存地址,该地址没有充分对齐 的对齐要求VOLUME_DISK_EXTENTS

关于c++ - 如何调用 DeviceIoControl 来检索它需要的内存量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33327177/

相关文章:

c - 从 C 中的 Windows 内核驱动程序读取注册表

c++ - 用户进程看不到服务创建的全局共享内存

c++ - 退出 PCL 查看器 : wasStopped() not changing value even though window was closed

c++ - 创建重载运算符时出错

c++ - 对于 C++ 中的指针,delete 命令真正对内存有什么作用?

c - printf中lc和c/ls和s的区别

创建相互指向的新节点

c - 用户模式钩子(Hook)的检测

c++ - 创建一个新的 Cocos2d-x 项目超过 200mb!如何创建更简单的模板?

C 寄存器调用约定