TDI Client and MDL [LONG]

Hello,

I’m writting a TDI client driver and have problems using MDL.
Below you can see my source code… First I create a transport address,
then a connection end-point and then I associates them. And I try to
create a MDL for the TdiBuildQueryInformation function but whenever the
IoCallDriver function is called (in my own QueryInformation function) I
get a BSOD with PFN_LIST_CORRUPT.
What is wrong in my code ? Should I use MmMapLockedPages() ?? Or do I
create the transport address and connection end-point incorrectly ??

Thanks for your answers

/*
* EtherBoxDispatchCreate
* IRP_MJ_CREATE Processing
* In -> device object
* -> IRP
* Out <- NT status
*
*/
NTSTATUS EtherBoxDispatchCreate(IN PDEVICE_OBJECT DeviceObject,IN PIRP
Irp)
{
ULONG EASize, // Extended Attributes structure size
ReadBufferSize, // Size of read buffer
WriteBufferSize; // Size of write buffer
NTSTATUS NTStatus; // NT status
PVOID EAAddress, // FILE_FULL_EA_INFORMATION pointer
for address
EAConnection, // FILE_FULL_EA_INFORMATION pointer
for connection
BaseAddress; // Buffer’s base address
PMDL MdlAddress; // MDL pointer
TA_IP_ADDRESS* Address; // IP address description
IO_STATUS_BLOCK IoStatus; // I/O operation status
PIO_STACK_LOCATION IOStack; // I/O stack pointer
OBJECT_ATTRIBUTES ObjectAttributes; // Définition de l’objet fichier
PDEVICE_EXTENSION DevExt; // Internal structure DeviceExtension
pointer
UNICODE_STRING Protocole; // Protocole used name

DevExt = ((PDEVICE_EXTENSION)DeviceObject->DeviceExtension);
DevExt->Address.Handle = NULL;
DevExt->Address.Object = NULL;
DevExt->Connexion.Handle = NULL;
DevExt->Connexion.Object = NULL;

IOStack = IoGetCurrentIrpStackLocation(Irp);
Irp->IoStatus.Information = 0;

// Initialize object file name
RtlInitUnicodeString(&Protocole,L"\Device\Tcp");
InitializeObjectAttributes(&ObjectAttributes,
&Protocole,
OBJ_CASE_INSENSITIVE,
NULL,
NULL);
EASize = sizeof(FILE_FULL_EA_INFORMATION)+
sizeof(TdiTransportAddress)+
sizeof(TA_IP_ADDRESS);
// Memory allocation for ExtendedAttributes structure
EAAddress = ExAllocatePool(NonPagedPool,EASize);
if(EAAddress!=NULL)
{
RtlZeroMemory(EAAddress,EASize);
// Set file extended attributes
((PFILE_FULL_EA_INFORMATION)EAAddress)->EaNameLength =
TDI_TRANSPORT_ADDRESS_LENGTH;
((PFILE_FULL_EA_INFORMATION)EAAddress)->EaValueLength =
sizeof(TA_IP_ADDRESS);
RtlCopyMemory(((PFILE_FULL_EA_INFORMATION)EAAddress)->EaName,
TdiTransportAddress,TDI_TRANSPORT_ADDRESS_LENGTH);
// ID Address description
Address =
(TA_IP_ADDRESS*)(((PFILE_FULL_EA_INFORMATION)EAAddress)->EaName+sizeof(TdiTransportAddress));

Address->TAAddressCount = 1;
Address->Address[0].AddressLength = TDI_ADDRESS_LENGTH_IP;
Address->Address[0].AddressType = TDI_ADDRESS_TYPE_IP;
Address->Address[0].Address[0].sin_port = DevExt->Port;
Address->Address[0].Address[0].in_addr = DevExt->AdresseIp;
// File creation for transport address
NTStatus=ZwCreateFile(&DevExt->Address.Handle,
GENERIC_READ|GENERIC_WRITE,
&ObjectAttributes,
&IoStatus,
0L,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN_IF,
0L,
EAAddress,
EASize);
if(NT_SUCCESS(NTstatus))
{
// Create reference object to address
NTStatus=ObReferenceObjectByHandle(DevExt->Address.Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,
(PVOID*)&DevExt->Address.Object,
NULL);
if(NT_SUCCESS(NTstatus))
{
EASize = sizeof(FILE_FULL_EA_INFORMATION)+
sizeof(TdiConnectionContext)+
sizeof(PVOID);
// Memory allocation for ExtendedAttributes structure
EAConnection = ExAllocatePool(NonPagedPool,EASize);
if(EAConnection!=NULL)
{
RtlZeroMemory(EAConnection,EASize);
// Set file extended attributes
((PFILE_FULL_EA_INFORMATION)EAConnection)->EaNameLength =
TDI_CONNECTION_CONTEXT_LENGTH;
((PFILE_FULL_EA_INFORMATION)EAConnection)->EaValueLength =
sizeof(PVOID);

RtlCopyMemory(((PFILE_FULL_EA_INFORMATION)EAConnection)->EaName,

TdiConnectionContext,TDI_CONNECTION_CONTEXT_LENGTH);
// Open connection end-point
NTStatus=ZwCreateFile(&DevExt->Connexion.Handle,
GENERIC_READ|GENERIC_WRITE|SYNCHRONIZE,
&ObjectAttributes,
&IoStatus,
0L,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN_IF,
0L,
EAConnection,
EASize);
if(NT_SUCCESS(NTstatus))
{
// Create reference object to connection

NTStatus=ObReferenceObjectByHandle(DevExt->Connection.Handle,
FILE_ALL_ACCESS,
NULL,
KernelMode,

(PVOID*)&DevExt->Connection.Object,
NULL);
if(NT_SUCCESS(NTstatus))
{
NTStatus =
AssociateAddress(DevExt->AttachedDevice,DevExt->Connection.Object,
DevExt->Address.Handle);
if(NT_SUCCESS(NTstatus))
{
ReadBufferSize = 0;
WriteBufferSize = 0;
// Get informations about connection
BaseAddress = NULL;
BaseAddress =
ExAllocatePool(NonPagedPool,sizeof(TDI_CONNECTION_INFO));
if(BaseAddress!=NULL)
{
MdlAddress = NULL;
MdlAddress =
IoAllocateMdl(BaseAddress,sizeof(TDI_CONNECTION_INFO),
FALSE,TRUE,NULL);
if(MdlAddress!=NULL)
{
MmBuildMdlForNonPagedPool(MdlAddress);
MmMapLockedPages(MdlAddress,KernelMode);

NTStatus=QueryInformation(DevExt->AttachedDevice,

DevExt->Connexion.Object,

TDI_QUERY_CONNECTION_INFO,MdlAddress);
if(NT_SUCCESS(NTstatus))
{

IoRaiseInformationalHardError(IO_ERR_INTERNAL_ERROR,NULL,NULL);
ReadBufferSize =
((PTDI_CONNECTION_INFO)MmGetSystemAddressForMdl(MdlAddress))->SendBufferSize;

WriteBufferSize =
((PTDI_CONNECTION_INFO)MmGetSystemAddressForMdl(MdlAddress))->ReceiveBufferSize;

}

MmUnmapLockedPages(MmGetMdlVirtualAddress(MdlAddress),MdlAddress);
IoFreeMdl(MdlAddress);
}
ExFreePool(BaseAddress);
}
}
// In case of failure
if(!NT_SUCCESS(NTStatus))
{

DisassociateAddress(DevExt->AttachedDevice,DevExt->Connexion.Object,
DevExt->Address.Handle);
}
// In case of failure
if(!NT_SUCCESS(NTStatus))
ObDereferenceObject(DevExt->Connexion.Object);
}
// In case of failure
if(!NT_SUCCESS(NTStatus))
{
ZwClose(DevExt->Connexion.Handle);
DevExt->Connexion.Handle=NULL;
}
}
else
{
// ZwCreate failure for connection end-point
Irp->IoStatus.Information = IoStatus.Information;
}
// Free memory allocated to connection
ExFreePool(EAConnection);
}
else
{
// ExAllocatePool failure for connection
NTStatus = STATUS_INSUFFICIENT_RESOURCES;
}
// In case of failure
if(!NT_SUCCESS(NTStatus))
{
ObDereferenceObject(DevExt->Address.Object);
DevExt->Address.Object=NULL;
}
}
// In case of failure
if(!NT_SUCCESS(NTStatus))
{
ZwClose(DevExt->Address.Handle);
DevExt->Address.Handle=NULL;
}
}
else
{
// ZwCreate failure for transport address
Irp->IoStatus.Information = IoStatus.Information;
}
// Libère la mémoire allouée pour l’adresse de transport
ExFreePool(EAAddress);
}
else
{
// // Free memory allocated to transport address
NTStatus = STATUS_INSUFFICIENT_RESOURCES;
}

Irp->IoStatus.Status = NTStatus;
IoCompleteRequest(Irp,IO_NO_INCREMENT);

return NTStatus;
}

/*
* AssociateAddress
*/
NTSTATUS AssociateAddress(IN PDEVICE_OBJECT TargetDevice,
IN PFILE_OBJECT FileObject,
IN HANDLE AddressHandle)
{
PIRP Irp;
KEVENT Event;
NTSTATUS StatusNT;
LARGE_INTEGER Zero;
IO_STATUS_BLOCK IoStatus;

KeInitializeEvent(&Event,NotificationEvent,FALSE);
Irp =
TdiBuildInternalDeviceControlIrp(TDI_ASSOCIATE_ADDRESS,TargetDevice,FileObject,&Event,

&IoStatus);
if(Irp!=NULL)
{

TdiBuildAssociateAddress(Irp,TargetDevice,FileObject,NULL,NULL,AddressHandle);

StatusNT = IoCallDriver(TargetDevice,Irp);
if(StatusNT == STATUS_PENDING)
{
Zero.QuadPart=0;
StatusNT =
KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,&Zero);
}
}
else
StatusNT = IoStatus.Status;

return StatusNT;
}

/*
* QueryInformation
*/
NTSTATUS QueryInformation(IN PDEVICE_OBJECT TargetDevice,
IN PFILE_OBJECT FileObject,
IN ULONG QueryType,
IN PMDL MdlAddress)
{
PIRP Irp;
KEVENT Event;
NTSTATUS StatusNT;
LARGE_INTEGER Zero;
IO_STATUS_BLOCK IoStatus;

KeInitializeEvent(&Event,NotificationEvent,FALSE);
Irp=TdiBuildInternalDeviceControlIrp(TDI_QUERY_INFORMATION,TargetDevice,FileObject,&Event,

&IoStatus);
if(Irp!=NULL)
{

TdiBuildQueryInformation(Irp,TargetDevice,FileObject,NULL,NULL,QueryType,MdlAddress);

StatusNT=IoCallDriver(TargetDevice,Irp);
if(StatusNT==STATUS_PENDING)
{
Zero.QuadPart=0;

StatusNT=KeWaitForSingleObject(&Event,Executive,KernelMode,FALSE,&Zero);
}
}
else
StatusNT=IoStatus.Status;

return StatusNT;
}