I’m currently writing a driver that exposes virtual COM ports. In the driver, I send an internal IOCTL from the port FDO down the stack, which is handled from the PDO IO queue. For some reason, the output data is not written to the provided output memory.
I’ve confirmed through windbg that IoCtl_Vcp_GetPortInfo (see below) is being called, and works as intended. The request is completed with STATUS_SUCCESS. At the time that I call WdfRequestComplete, the output buffer has valid data. However, when control returns to GetPortInfo (see below), the provided buffer has not been overwritten. I confirmed this with a hardware breakpoint on access for the receiving buffer. It is not read or written to during the WdfIoTargetSendInteralIoctlSynchronously call.
The code responsible for sending the IOCTL is below:
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;
}
The code that handles the 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;
}
The IOCTL code definition:
#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)
Setting the request completion information with the number of output bytes fixes the issue.