(转)驱动开发之五 --- TDI之五【译文】
http://hi.baidu.com/combojiang/item/07a100ef4662a0225a2d640e
步骤5:发送和接收数据
为了发送数据,你只需创建一个TDI_SEND IOCTL,然后把它传送给传输设备。下面的代码实现了数据发送。
NTSTATUS TdiFuncs_Send(PFILE_OBJECT pfoConnection, PVOID pData,
UINT uiSendLength, UINT *pDataSent)
{
NTSTATUS NtStatus = STATUS_INSUFFICIENT_RESOURCES;
PIRP pIrp;
IO_STATUS_BLOCK IoStatusBlock = {0};
PDEVICE_OBJECT pTdiDevice;
PMDL pSendMdl;
TDI_COMPLETION_CONTEXT TdiCompletionContext;
KeInitializeEvent(&TdiCompletionContext.kCompleteEvent,
NotificationEvent, FALSE);
/*
* The TDI Device Object is required to
* send these requests to the TDI Driver.
*/
pTdiDevice = IoGetRelatedDeviceObject(pfoConnection);
*pDataSent = 0;
/*
* The send requires an MDL which is what you may remember from DIRECT_IO.
* However, instead of using an MDL we need to create one.
*/
pSendMdl = IoAllocateMdl((PCHAR )pData, uiSendLength, FALSE, FALSE, NULL);
if(pSendMdl)
{
__try {
MmProbeAndLockPages(pSendMdl, KernelMode, IoModifyAccess);
} __except (EXCEPTION_EXECUTE_HANDLER) {
IoFreeMdl(pSendMdl);
pSendMdl = NULL;
};
if(pSendMdl)
{
/*
* Step 1: Build the IRP. TDI defines several macros and functions
* that can quickly create IRP's, etc. for variuos purposes.
* While this can be done manually it's easiest to use
* the macros.
*/
pIrp = TdiBuildInternalDeviceControlIrp(TDI_SEND,
pTdiDevice, pfoConnection,
&TdiCompletionContext.kCompleteEvent,
&IoStatusBlock);
if(pIrp)
{
/*
* Step 2: Add the correct parameters into the IRP.
*/
TdiBuildSend(pIrp, pTdiDevice, pfoConnection, NULL,
NULL, pSendMdl, 0, uiSendLength);
NtStatus = IoCallDriver(pTdiDevice, pIrp);
/*
* If the status returned is STATUS_PENDING this means that the
* IRP will not be completed synchronously and the driver has
* queued the IRP for later processing. This is fine but we do
* not want to return this not want to return this not want to
* return this to wait until it has completed. The EVENT
* that we providedwill be set when the IRP completes.
*/
if(NtStatus == STATUS_PENDING)
{
KeWaitForSingleObject(&TdiCompletionContext.kCompleteEvent,
Executive, KernelMode, FALSE, NULL);
}
NtStatus = IoStatusBlock.Status;
*pDataSent = (UINT)IoStatusBlock.Information;
/*
* I/O Manager will free the MDL
*
if(pSendMdl)
{
MmUnlockPages(pSendMdl);
IoFreeMdl(pSendMdl);
} */
}
}
}
return NtStatus;
}