DeviceIoControl 错误 1 功能不正确
DeviceIoControl error 1 incorrect function
我在内核 space 中创建了一个设备并使用 CreateFile
在用户 space 中访问它 我能够向驱动程序发送 ioctl 并且它们被正确执行。他们不知道如何跟踪 WdfRequestComplete
之后和 return 之后发生的事情,我以错误 1(无效函数)结束。在将其标记为 dup 之前,请注意与 this 的不同之处在于我编写了我的驱动程序 ioctl 并且我使用的是同步 io 而不是异步。
用户 space:
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
在内核中 space
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(Request, status, 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 中定义控制代码需要更多时间。如 here 所述,CTL_CODE 宏应该用于定义新的 IOCTL 控制代码。
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
在我的例子中,我最终定义了这个:
#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 保留的,但我主机上的设备需要此代码,所以我只是提供所要求的内容。
我在内核 space 中创建了一个设备并使用 CreateFile
在用户 space 中访问它 我能够向驱动程序发送 ioctl 并且它们被正确执行。他们不知道如何跟踪 WdfRequestComplete
之后和 return 之后发生的事情,我以错误 1(无效函数)结束。在将其标记为 dup 之前,请注意与 this 的不同之处在于我编写了我的驱动程序 ioctl 并且我使用的是同步 io 而不是异步。
用户 space:
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
在内核中 space
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(Request, status, 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 中定义控制代码需要更多时间。如 here 所述,CTL_CODE 宏应该用于定义新的 IOCTL 控制代码。
#define IOCTL_Device_Function CTL_CODE(DeviceType, Function, Method, Access)
在我的例子中,我最终定义了这个:
#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 保留的,但我主机上的设备需要此代码,所以我只是提供所要求的内容。