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

Posted

技术标签:

【中文标题】DeviceIoControl 完全不起作用,返回时 SystemBuffer 为空【英文标题】:DeviceIoControl is totally not working, SystemBuffer empty on return 【发布时间】:2017-01-02 15:47:26 【问题描述】:

我有一个带有结构的 IOCTL 被发送到我的驱动程序,该结构被成功传递,然后我的驱动程序发挥了它的魔力,但是当它完成后它应该返回一个简单的 8 字节长的无符号 _int64,我设置IRP 的 iostatus.Information 的大小为 unsigned _int64(8 字节),我将值复制到 AssociatedIrp.SystemBuffer,最后我将 IoStatus.Status 设置为 STATUS_SUCCESS,然后调用 IoCompleteRequest。

现在,我使用 WinDbg 检查 SystemBuffer 包含正确的输出,并且在调用 IoCompleteRequest 时状态和信息字段是正确的,但是当我的用户模式应用程序对 DeviceIoControl 的调用返回时,输出缓冲区不会更改我在 lpOutBuffer 字段中指向的整数。我在创建时将它初始化为一个普通的 0x9,当调用完成时它保持相同的值,当它应该是完全不同的东西时,我有多个 IOCTL,它们都工作并且以完全相同的方式制作,我不知道是什么在这里发生,任何提示将不胜感激,我被引导相信这是一个 Windows 错误现在或类似的东西,因为我已经阅读了我的代码 100 次,却没有弄清楚这个简单而复杂的错误。

很抱歉,由于我不拥有它以及其他原因,我无法发布任何代码。

【问题讨论】:

很抱歉,由于我不拥有它以及其他原因,我无法发布任何代码。 而且.. 我们不要求您发布实际代码。您需要制造 minimal reproducible example,以便1)我们可以重现问题,2)您不发布实际代码。 好吧,没什么,将带有一些数据的结构发送到设备,发送回一个 64 位整数,然后返回,我无法检查缓冲区是什么在用户模式下,我们唯一可以访问的是 DeviceIoControl 调用本身。 好的,IO_STATUS_BLOCK 在用户模式下返回怎么样?它是否填写在您的驱动程序代码中?可能这个 ioctl 没有使用 METHOD_BUFFERED 吗? @RbMm 如果我错了,请纠正我,但用户模式代码无权访问 IO_STATUS_BLOCK 本身,对吗?我认为 IO 管理器只将数据从它复制到 DeviceIoControl 中指定的输出缓冲区?是的,IOCTL 和我的其他 IOCTL 一样是 METHOD_BUFFERED。 你完全错了。用户模式当然总是必须使用IO_STATUS_BLOCK(as 和内核模式)。如果你使用ZwDeviceIoControlFile,你明确IO_STATUS_BLOCK,如果你使用DeviceIoControl - OVERLAPPED(内部,InternalHigh)是IO_STATUS_BLOCK(指向OVERLAPPED的指针作为指向IO_STATUS_BLOCK的指针传递)如果你没有明确传递OVERLAPPED - 系统隐式执行此操作。但在所有情况下都使用IO_STATUS_BLOCK,并且数据从内核复制到用户模式IO_STATUS_BLOCK - 所以看看 - 它是如何填充输出的。在您的情况下,这是 OVERLAPPED(前 2 个成员) 【参考方案1】:

希望您在 3 年前发布此问题后找到了解决方案。我们在调查类似的事情时遇到了这篇文章,解决方案非常简单但没有记录。 如果驱动程序将一些数据复制到输出缓冲区并使用状态为 OK 的 WdfRequestComplete,则不会向调用者返回任何内容!您需要调用 WdfRequestCompleteWithInformation 并传递写入 Information 参数中的字节数。这将告诉框架多少字节返回给调用者。

例如:

WDFMEMORY   reqMemory;
NTSTATUS    status = WdfRequestRetrieveOutputMemory(Request, &reqMemory);
if (!NT_SUCCESS(status))

    break;

WdfMemoryCopyFromBuffer(reqMemory, 0, data, dataLen);

/* this will complete the request but nothing is returned to the caller
WdfRequestComplete(Request, S_OK);
*/
/* this is the correct way of returning the data */
WdfRequestCompleteWithInformation(Request, S_OK, dataLen);

【讨论】:

我记得读过关于 WdfRequestCompletedWdfRequestCompletedWithInformation 的冲突/令人困惑的事情。文档建议后者允许您返回某种额外的带外信息。无论如何,我一直在努力弄清楚为什么我的自定义 IOCTL 驱动程序命令没有返回任何数据。 谢谢你

以上是关于DeviceIoControl 完全不起作用,返回时 SystemBuffer 为空的主要内容,如果未能解决你的问题,请参考以下文章

SCSI INQUIRY 命令的 DeviceIoControl 返回错误 50

DeviceIoControl 返回 ERROR_ACCESS_DENIED

使用 DeviceIoControl 都有哪些好的策略?

DeviceIoControl 在 C++ 和 C# 中工作,但在 C++/CLI 中调用时返回 ERROR_INVALID_FUNCTION

如何使用 DeviceIOControl() 从 CD 中获取“曲目信息”?

为什么我的自动完成功能不起作用?