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);
【讨论】:
我记得读过关于WdfRequestCompleted
与 WdfRequestCompletedWithInformation
的冲突/令人困惑的事情。文档建议后者允许您返回某种额外的带外信息。无论如何,我一直在努力弄清楚为什么我的自定义 IOCTL 驱动程序命令没有返回任何数据。 谢谢你以上是关于DeviceIoControl 完全不起作用,返回时 SystemBuffer 为空的主要内容,如果未能解决你的问题,请参考以下文章
SCSI INQUIRY 命令的 DeviceIoControl 返回错误 50
DeviceIoControl 返回 ERROR_ACCESS_DENIED
DeviceIoControl 在 C++ 和 C# 中工作,但在 C++/CLI 中调用时返回 ERROR_INVALID_FUNCTION