Windows DeviceIoControl错误1功能不正确
我已经在内核空间创建了一个设备,并使用Windows DeviceIoControl错误1功能不正确,windows,driver,kmdf,wdf,Windows,Driver,Kmdf,Wdf,我已经在内核空间创建了一个设备,并使用CreateFile在用户空间访问它,我能够将ioctl发送到驱动程序,并且它们被正确执行。不知道如何跟踪WdfRequestComplete之后发生的情况,返回后我以错误1结束(函数无效)。在将其标记为dup之前,请注意,我编写驱动程序ioctl与使用synch io not asynch有区别 在用户空间中: fd = CreateFile(dev_path, (FILE_GENERIC_READ | FILE_GENERIC_WRITE),
CreateFile
在用户空间访问它,我能够将ioctl发送到驱动程序,并且它们被正确执行。不知道如何跟踪WdfRequestComplete
之后发生的情况,返回后我以错误1结束(函数无效)。在将其标记为dup之前,请注意,我编写驱动程序ioctl与使用synch io not asynch有区别
在用户空间中:
fd = CreateFile(dev_path,
(FILE_GENERIC_READ | FILE_GENERIC_WRITE),
(FILE_SHARE_READ | FILE_SHARE_WRITE),
NULL, OPEN_EXISTING, 0, NULL);
// ... error checking code here
DeviceIoControl(fd, // device handler
VIRTQC_CMD_MMAP, // command to send
&inputBuffer,
inputBufferLength,
&outputBuffer,
outputBufferLength,
&returnLength,
(LPOVERLAPPED)NULL); // overlapped structure not needed using sync io
在内核空间中
status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &inputBuffer, NULL);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
return;
}
inputVirtArg = (VirtioQCArg*)inputBuffer;
status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &outputBuffer, NULL);
if (!NT_SUCCESS(status))
{
WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
return;
}
outputVirtArg = (VirtioQCArg*)outputBuffer;
switch (IoControlCode)
{
case VIRTQC_CMD_MMAP:
if (PsGetCurrentThread() == irp->Tail.Overlay.Thread)
{
status = CreateAndMapMemory(device, &(inputVirtArg), &(outputVirtArg));
outputVirtArg->flag = (!NT_SUCCESS(status)) ? 0 : 1;
}
else
status = STATUS_UNSUCCESSFUL;
break;
default:
status = STATUS_INVALID_DEVICE_REQUEST;
break;
}
WdfRequestComplete(Request, status);
更新1:
我尝试了WdfRequestCompleteWithInformation(请求、状态、OutputBufferLength)代码>但结果相同
另外,我注意到inputBuffer和outputBuffer的地址是相同的
更新2:
我试过了
temp = ExAllocatePoolWithTag(
NonPagedPool,
PAGE_SIZE,
MEMORY_TAG
);
// other code to
RtlCopyMemory((VirtioQCArg*)outputBuffer, temp, OutputBufferLength);
仍然出现错误1我在linux驱动程序中将ioctl CMD定义为枚举(工作正常),在windows中实现该驱动程序时使用了相同的枚举定义
enum
{
// Module & Execution control (driver API)
VIRTIQC_SET = 200,
VIRTIQC_UNSET,
// more cmds.....
}
在windows中,定义控制代码需要更多的时间。如前所述,应使用CTL_代码宏定义新的IOCTL控制代码
#定义IOCTL_设备_功能CTL_代码(设备类型、功能、方法、访问)
在我的例子中,我最终定义了这一点:
#define VIRTQC_MAP CTL_CODE(FILE_DEVICE_NETWORK, 0xC8, METHOD_IN_DIRECT, FILE_READ_DATA | FILE_WRITE_DATA)
#define VIRTQC_UNMAP CTL_CODE(FILE_DEVICE_NETWORK, 0xC9, METHOD_OUT_DIRECT, FILE_READ_DATA)
我知道小于0x800的功能代码是为MS保留的,但我主机上的设备需要这些代码,所以我只提供所要求的内容。您需要从一些基本的故障排除开始:自由地使用DbgPrint来查看哪个功能失败以及错误代码。如果没有这些信息,我们不可能帮助您。在使用outputBuffer=irp->AssociatedIrp.SystemBuffer
而不是wdfrequestreeveoutputbuffer
后,我可以在用户空间访问结果,但我不知道为什么。我已经使用DbgPrint并使用windbg进行跟踪,以检查为什么我仍然得到错误1,但所有错误似乎都在EvtIoDeviceControl中正确执行。IOCTL使用什么数据传输类型,请参阅?@HarryJohnston谢谢!就是这样,我使用的代码与我的linux驱动程序相同,并且没有指定CTL_代码宏,因此它默认为METHOD_BUFFEREDYou应该发布详细信息作为答案。作为记录,IOCTL代码不必与硬件代码相对应,因此使用正确的编号可能是安全的。