Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/http/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows DeviceIoControl错误1功能不正确_Windows_Driver_Kmdf_Wdf - Fatal编程技术网

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代码不必与硬件代码相对应,因此使用正确的编号可能是安全的。