WDF 内部 IOCTL 不返回输出
WDF Internal IOCTL Not Returning Output
我目前正在编写一个公开虚拟 COM 端口的驱动程序。在驱动程序中,我从 FDO 端口向堆栈发送内部 IOCTL,这是从 PDO IO 队列处理的。由于某种原因,输出数据未写入提供的输出内存。
我已经通过 windbg 确认 IoCtl_Vcp_GetPortInfo(见下文)正在被调用,并且按预期工作。请求以 STATUS_SUCCESS 完成。在我调用 WdfRequestComplete 时,输出缓冲区具有有效数据。但是,当控制 returns 到 GetPortInfo(见下文)时,提供的缓冲区没有被覆盖。我通过接收缓冲区访问的硬件断点确认了这一点。在 WdfIoTargetSendInteralIoctlSynchronously 调用期间不对其进行读取或写入。
负责发送IOCTL的代码如下:
NTSTATUS GetPortInfo(WDFDEVICE device, _Out_ PVCH_PORT_INFO port_info)
{
NTSTATUS status;
WDFIOTARGET io_target;
WDF_MEMORY_DESCRIPTOR output_descriptor;
PVOID buffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(VCH_PORT_INFO), VCH_POOL_TAG);
//WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&output_descriptor, port_info, sizeof(VCH_PORT_INFO));
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&output_descriptor, buffer, sizeof(VCH_PORT_INFO));
io_target = WdfDeviceGetIoTarget(device);
status = WdfIoTargetSendInternalIoctlSynchronously(io_target, NULL, IOCTL_VCP_INTERNAL_GET_PORT_INFO, NULL, &output_descriptor, NULL, NULL);
DbgBreakPoint();
if (!NT_SUCCESS(status))
return status;
memcpy(port_info, buffer, sizeof(VCH_PORT_INFO));
ExFreePoolWithTag(buffer, VCH_POOL_TAG);
return STATUS_SUCCESS;
}
处理IOCTL的代码:
NTSTATUS IoCtl_Vcp_GetPortInfo(WDFDEVICE device, WDFREQUEST request)
{
NTSTATUS status;
PVCH_PORT_INFO buffer;
PPORT_PDO_DESCRIPTOR descriptor = PortPdoGetContext(device);
status = WdfRequestRetrieveOutputBuffer(request, sizeof(VCH_PORT_INFO), (PVOID*)&buffer, NULL);
if (!NT_SUCCESS(status))
return status;
buffer->Address = descriptor->Address;
buffer->ForceComIndex = FALSE; // TODO: Implement
buffer->Writeable = descriptor->Writeable;
DbgBreakPoint();
return STATUS_SUCCESS;
}
IOCTL代码定义:
#define DEVICE_TYPE_VIRTUAL_COM_PORT 0xC51
#define IOCTL_VCP_INTERNAL_GET_PORT_INFO CTL_CODE(DEVICE_TYPE_VIRTUAL_COM_PORT, 0x30, METHOD_BUFFERED, FILE_READ_DATA)
使用输出字节数设置请求完成信息修复了这个问题。
我目前正在编写一个公开虚拟 COM 端口的驱动程序。在驱动程序中,我从 FDO 端口向堆栈发送内部 IOCTL,这是从 PDO IO 队列处理的。由于某种原因,输出数据未写入提供的输出内存。
我已经通过 windbg 确认 IoCtl_Vcp_GetPortInfo(见下文)正在被调用,并且按预期工作。请求以 STATUS_SUCCESS 完成。在我调用 WdfRequestComplete 时,输出缓冲区具有有效数据。但是,当控制 returns 到 GetPortInfo(见下文)时,提供的缓冲区没有被覆盖。我通过接收缓冲区访问的硬件断点确认了这一点。在 WdfIoTargetSendInteralIoctlSynchronously 调用期间不对其进行读取或写入。
负责发送IOCTL的代码如下:
NTSTATUS GetPortInfo(WDFDEVICE device, _Out_ PVCH_PORT_INFO port_info)
{
NTSTATUS status;
WDFIOTARGET io_target;
WDF_MEMORY_DESCRIPTOR output_descriptor;
PVOID buffer = ExAllocatePoolWithTag(NonPagedPool, sizeof(VCH_PORT_INFO), VCH_POOL_TAG);
//WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&output_descriptor, port_info, sizeof(VCH_PORT_INFO));
WDF_MEMORY_DESCRIPTOR_INIT_BUFFER(&output_descriptor, buffer, sizeof(VCH_PORT_INFO));
io_target = WdfDeviceGetIoTarget(device);
status = WdfIoTargetSendInternalIoctlSynchronously(io_target, NULL, IOCTL_VCP_INTERNAL_GET_PORT_INFO, NULL, &output_descriptor, NULL, NULL);
DbgBreakPoint();
if (!NT_SUCCESS(status))
return status;
memcpy(port_info, buffer, sizeof(VCH_PORT_INFO));
ExFreePoolWithTag(buffer, VCH_POOL_TAG);
return STATUS_SUCCESS;
}
处理IOCTL的代码:
NTSTATUS IoCtl_Vcp_GetPortInfo(WDFDEVICE device, WDFREQUEST request)
{
NTSTATUS status;
PVCH_PORT_INFO buffer;
PPORT_PDO_DESCRIPTOR descriptor = PortPdoGetContext(device);
status = WdfRequestRetrieveOutputBuffer(request, sizeof(VCH_PORT_INFO), (PVOID*)&buffer, NULL);
if (!NT_SUCCESS(status))
return status;
buffer->Address = descriptor->Address;
buffer->ForceComIndex = FALSE; // TODO: Implement
buffer->Writeable = descriptor->Writeable;
DbgBreakPoint();
return STATUS_SUCCESS;
}
IOCTL代码定义:
#define DEVICE_TYPE_VIRTUAL_COM_PORT 0xC51
#define IOCTL_VCP_INTERNAL_GET_PORT_INFO CTL_CODE(DEVICE_TYPE_VIRTUAL_COM_PORT, 0x30, METHOD_BUFFERED, FILE_READ_DATA)
使用输出字节数设置请求完成信息修复了这个问题。