I’ve been working on a storage project and TDI is involved to send data to a remote host. I’ve implemented a kernel mode socket using TDI. However, the speed of the data sending is much slower than that of using user-mode socket. I’ve been told that the “KeWaitForSingleObject” after “IoCallDriver” is the cause of it. I’ve tried to drop that waiting section, however, only to get a Blue Screen saying “Access violation”. I thought the cause of it was when the TCPIP.sys tried to access the memory buffer described by the MDL, the buffer had already freed by other parts of my program for the absence of “KeWaitForSingleObject”. Would someone give me some hints on how to improve the sending speed of my TDI client implementation? Thanks in advance.
Here’s the list of the sending function:
NTSTATUS tdi_send_stream(PFILE_OBJECT connectionFileObject, const char *buf, int len, ULONG flags)
{
PDEVICE_OBJECT devObj;
KEVENT event;
PIRP irp;
PMDL mdl;
IO_STATUS_BLOCK iosb;
NTSTATUS status;
devObj = IoGetRelatedDeviceObject(connectionFileObject);
KeInitializeEvent(&event, NotificationEvent, FALSE);
irp = TdiBuildInternalDeviceControlIrp(TDI_SEND, devObj, connectionFileObject, &event, &iosb);
if (irp == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
if (len)
{
mdl = IoAllocateMdl((void*) buf, len, FALSE, FALSE, NULL);
if (mdl == NULL)
{
IoFreeIrp(irp);
return STATUS_INSUFFICIENT_RESOURCES;
}
__try
{
MmProbeAndLockPages(mdl, KernelMode, IoReadAccess);
status = STATUS_SUCCESS;
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
IoFreeMdl(mdl);
IoFreeIrp(irp);
status = STATUS_INVALID_USER_BUFFER;
}
if (!NT_SUCCESS(status))
{
return status;
}
}
TdiBuildSend(irp, devObj, connectionFileObject, NULL, NULL, len ? mdl : 0, flags, len);
status = IoCallDriver(devObj, irp);
if (status == STATUS_PENDING)
{
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
status = iosb.Status;
}
return NT_SUCCESS(status) ? iosb.Information : status;
}