(转)驱动开发之五 --- TDI之四 【译文】
http://hi.baidu.com/combojiang/item/623461f6f690a6b031c19932
接上
步骤4:连接
创建一个TCP连接的客户端,我们需要连接。
NTSTATUS TdiFuncs_Connect(PFILE_OBJECT pfoConnection,
UINT uiAddress, USHORT uiPort)
{
NTSTATUS NtStatus = STATUS_INSUFFICIENT_RESOURCES;
PIRP pIrp;
IO_STATUS_BLOCK IoStatusBlock = {0};
PDEVICE_OBJECT pTdiDevice;
TDI_CONNECTION_INFORMATION RequestConnectionInfo = {0};
TDI_CONNECTION_INFORMATION ReturnConnectionInfo = {0};
LARGE_INTEGER TimeOut = {0};
UINT NumberOfSeconds = 60*3;
char cBuffer[256] = {0};
PTRANSPORT_ADDRESS pTransportAddress =(PTRANSPORT_ADDRESS)&cBuffer;
PTDI_ADDRESS_IP pTdiAddressIp;
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);
/*
* 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.
*
* http://msdn.microsoft.com/library/en-us/network/hh/network/
* 34bldmac_f430860a-9ae2-4379-bffc-6b0a81092e7c.xml.asp?frame=true
*/
pIrp = TdiBuildInternalDeviceControlIrp(TDI_CONNECT, pTdiDevice,
pfoConnection, &TdiCompletionContext.kCompleteEvent,
&IoStatusBlock);
if(pIrp)
{
/*
* Step 2: Add the correct parameters into the IRP.
*/
/*
* Time out value
*/
TimeOut.QuadPart = 10000000L;
TimeOut.QuadPart *= NumberOfSeconds;
TimeOut.QuadPart = -(TimeOut.QuadPart);
/*
* Initialize the RequestConnectionInfo which specifies
* the address of the REMOTE computer
*/
RequestConnectionInfo.RemoteAddress = (PVOID)pTransportAddress;
RequestConnectionInfo.RemoteAddressLength =
sizeof(PTRANSPORT_ADDRESS) + sizeof(TDI_ADDRESS_IP);
/*
* The number of transport addresses
*/
pTransportAddress->TAAddressCount = 1;
/*
* This next piece will essentially describe what the
* transport being opened is.
* AddressType = Type of transport
* AddressLength = Length of the address
* Address = A data structure that is essentially
* related to the chosen AddressType.
*/
pTransportAddress->Address[0].AddressType =
TDI_ADDRESS_TYPE_IP;
pTransportAddress->Address[0].AddressLength =
sizeof(TDI_ADDRESS_IP);
pTdiAddressIp =
(TDI_ADDRESS_IP *)&pTransportAddress->Address[0].Address;
/*
* The TDI_ADDRESS_IP data structure is essentially simmilar
* to the usermode sockets data structure.
* sin_port
* sin_zero
* in_addr
*/
/*
* Remember, these must be in NETWORK BYTE ORDER (Big Endian)
*/
/* Example: 1494 = 0x05D6 (Little Endian) or 0xD605 (Big Endian)*/
pTdiAddressIp->sin_port = uiPort;
/* Example: 10.60.2.159 = 0A.3C.02.9F (Little Endian)
or 9F.02.3C.0A (Big Endian)
*/
pTdiAddressIp->in_addr = uiAddress;
TdiBuildConnect(pIrp, pTdiDevice, pfoConnection, NULL, NULL,
&TimeOut, &RequestConnectionInfo,
&ReturnConnectionInfo);
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 thread,
* we are a synchronous call so we want to wait until
* it has completed. The EVENT that we provided will be
* set when the IRP completes.
*/
if(NtStatus == STATUS_PENDING)
{
KeWaitForSingleObject(&TdiCompletionContext.kCompleteEvent,
Executive, KernelMode, FALSE, NULL);
/*
* Find the Status of the completed IRP
*/
NtStatus = IoStatusBlock.Status;
}
}
return NtStatus;
}