⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tdiclient.c

📁 好东东
💻 C
📖 第 1 页 / 共 3 页
字号:
    IN PVOID  Options,
    IN ULONG  ReceiveDatagramFlags,
    IN ULONG  BytesIndicated,
    IN ULONG  BytesAvailable,
    OUT ULONG  *BytesTaken,
    IN PVOID  Tsdu,
    OUT PIRP  *IoRequestPacket
    )
/*++

Routine Description:

  TDI_EVENT_RECEIVE_DATAGRAM handle.
  When a UDP packet from particular address and port arrive, this callback function will be called.
  Usually BytesIndicated is less than or equal to BytesAvailable. If less, a Irp should be buildt
  for the remainder data. This irp has be pre-allocated by TDIBuildRecvContext.

Note:
	Don't forget to call IoSetNextIrpStackLocation to handle the IoRequestPacket.
	Because the stack locations of this irp between this function and underlying transport are identical.

  Pls refer to Windows DDK documentation chapter relevant to this handle.

--*/
{
	LONG	i;
	PUCHAR	p;
	PIRP	pIrp;

	NTSTATUS	status;
	ULONG	BytesToCopy;
	ULONG	stageSize;
	PDEVICE_EXTENSION	deviceExtension;

	deviceExtension = (PDEVICE_EXTENSION)TdiEventContext;
	DebugPrint(("SourceAddress: "));
	p = (PUCHAR)SourceAddress;
	for( i = 0; i < SourceAddressLength; i++)
	{
		DbgPrint("%2x ", p[ i ] );
	}
	DbgPrint(("\n"));
	DebugPrint(("ReceiveDatagramFlags: %x\n", ReceiveDatagramFlags ));
	DebugPrint(("BytesIndicated: %d\n", BytesIndicated ));
	DebugPrint(("BytesAvailable: %d\n", BytesAvailable ));
	*BytesTaken = BytesIndicated;
	CopyToRingBuffer( deviceExtension, (PUCHAR)Tsdu, BytesIndicated );

	*IoRequestPacket = NULL;
	status = STATUS_SUCCESS;
	if ( BytesIndicated < BytesAvailable )
	{
		if ( deviceExtension->recvContext.pIrp )
		{
			pIrp = deviceExtension->recvContext.pIrp;
			DebugPrint(("EventRecvDatagram: pIrp = %x\n", deviceExtension->recvContext.pIrp ));
			TdiBuildReceiveDatagram( pIrp,
				deviceExtension->TDILowerDeviceObject,
				deviceExtension->lpTransAddrFileObject,
				TDIRecvRemainderCompRoutine,
				deviceExtension,
				deviceExtension->recvContext.pMdl,
				0,
				&(deviceExtension->recvContext.ReceiveDatagramInfo),
				&(deviceExtension->recvContext.ReturnInfo),
				TDI_RECEIVE_NORMAL);
			IoSetNextIrpStackLocation ( pIrp );
			*IoRequestPacket = pIrp;
			status = STATUS_MORE_PROCESSING_REQUIRED;
		}
	}
	return status;
}
VOID CopyToRingBuffer(
	PDEVICE_EXTENSION deviceExtension,
	PUCHAR	LinearBuffer,
	ULONG	BytesIndicated )
/*++

Routine Description:

  This function is called by TDIEventRecvDatagram and TDIRecvRemainderCompRoutine.

  It copies linear buffer containing network packet to ring buffer. If source buffer length
  is more than the length of ReceiveBuffer, the last part of LinearBuffer will be copied
  to destination buffer.

  If there is WaitOnMaskIrp in deviceExtension and the WaitMask meets SERIAL_EV_RXCHAR || SERIAL_EV_RLSD,
  it will complete the WaitOnMaskIrp to indicate the application that there are some data arrive.

  The destination ringbuffer, deviceExtension->RxBuffer, is shared with IRP_MJ_READ.
  So the access to the ringbuffer must be synchronous.
	
Arguments:

  deviceExtension	- pointer to device object extension
  LinearBuffer		- Tsdu containing network packets.
  BytesIndicated	- the length of LinearBuffer

Return Value:

    NT status code.

--*/
{
	ULONG	stageSize;
	KIRQL	oldIrql;
	ULONG	BytesToCopy;
	PUCHAR	lpSrc;

	BytesToCopy = BytesIndicated;
	lpSrc		= LinearBuffer;
	if ( BytesIndicated > RINGBUFFER_SIZE )
	{
		lpSrc		= (PUCHAR)LinearBuffer + BytesIndicated - RINGBUFFER_SIZE;
		BytesToCopy = RINGBUFFER_SIZE;
	}
	KeAcquireSpinLock(&deviceExtension->ThreadSpinLock, &oldIrql);
	stageSize = deviceExtension->RxBuffer + RINGBUFFER_SIZE - deviceExtension->lpRx;
	if( BytesToCopy <= stageSize )
		RtlCopyMemory ( deviceExtension->lpRx, lpSrc, BytesToCopy );
	else
	{
		RtlCopyMemory ( deviceExtension->lpRx, lpSrc, stageSize );
		RtlCopyMemory ( deviceExtension->RxBuffer, lpSrc + stageSize, ( BytesToCopy - stageSize ) );
	}
	deviceExtension->lpRx = deviceExtension->RxBuffer + ( ( RINGBUFFER_SIZE - stageSize + BytesToCopy ) % RINGBUFFER_SIZE );
	deviceExtension->SerialStatus.AmountInInQueue += BytesToCopy;
	if ( deviceExtension->SerialStatus.AmountInInQueue > RINGBUFFER_SIZE )
	{
		deviceExtension->lpRead = deviceExtension->lpRx;
		deviceExtension->SerialStatus.AmountInInQueue = RINGBUFFER_SIZE;
	}
	if( ( deviceExtension->WaitOnMaskIrp ) &&
		( ( deviceExtension->WaitMask & SERIAL_EV_RXCHAR ) || ( deviceExtension->WaitMask & SERIAL_EV_RLSD ) ) )
	{
		DebugPrint(("ClientEventRecv: Complete WaitOnMaskIrp\n"));
		deviceExtension->SerialStatus.EofReceived = TRUE;
		*(PULONG)deviceExtension->WaitOnMaskIrp->AssociatedIrp.SystemBuffer = ( SERIAL_EV_RXCHAR | SERIAL_EV_RLSD );
		CompleteRequest( deviceExtension->WaitOnMaskIrp, STATUS_SUCCESS, sizeof( ULONG ) );
		deviceExtension->WaitOnMaskIrp = NULL;
		SampleIoDecrement( deviceExtension );
	}
	KeReleaseSpinLock( &deviceExtension->ThreadSpinLock, oldIrql );	
}
NTSTATUS TDIBuildRecvContext( PRECV_CONTEXT lpContext)
/*++

Routine Description:

  This function is called by InitializeConnection.
  It builds RecvContext, including pIrp, pMdl, and locks the Mdl.
	
Arguments:

  lpContext	- pointer to deviceExtension->recvContext

Return Value:

    NT status code.

--*/
{
	PIRP				pIrp;
	PMDL				pMdl;
	PDEVICE_EXTENSION		deviceExtension;
	EXCEPTION_POINTERS        * pExceptionInfo;
	ULONG                       lclExceptionCode;
	PVOID                       lclExceptionAddr;
	PIO_STACK_LOCATION	ioStack;

	if( lpContext->pIrp || lpContext->pMdl || ( lpContext->RemainderBuffer == NULL ) )
		return STATUS_UNSUCCESSFUL;
	deviceExtension = CONTAINING_RECORD( lpContext, DEVICE_EXTENSION, recvContext );
	pIrp = IoAllocateIrp ( deviceExtension->TDILowerDeviceObject->StackSize + 2, FALSE );
	/*
	Because the irp will be used for many times, TdiBuildInternalDeviceControlIrp is not best.
	*/
/*	pIrp = TdiBuildInternalDeviceControlIrp(
		TDI_RECEIVE_DATAGRAM,
		deviceExtension->TDILowerDeviceObject,
		deviceExtension->lpTransAddrFileObject,
		&lpContext->Event,
		&lpContext->IoStatus
		);
*/
	if (NULL == pIrp)
	{
		DebugPrint(("TdiBuildInternalIrp failed\n"));
		return STATUS_INSUFFICIENT_RESOURCES;
	}else
	{
		DebugPrint(("TDIBuildRecvContext: pIrp = %x\n", pIrp ));
	}
	pMdl = IoAllocateMdl ( lpContext->RemainderBuffer,
		RECVREMAINDER_BUFFER_SIZE, FALSE, FALSE, NULL );
	if (NULL==pMdl)
	{
		goto Error_Exit;
	}
	_try
	{
		// lockpage the Mdl, even though it is allocated based on NonPagesPool
		MmProbeAndLockPages(pMdl,                     // (Try to) fix buffer.
			KernelMode,
			IoModifyAccess
			);
		lpContext->bLocked = TRUE;
		DebugPrint(("RemainderBuffer: 0x%x,  pMdl: 0x%x\n", lpContext->RemainderBuffer, pMdl ));
	}
	_except(
		pExceptionInfo = GetExceptionInformation(),                                                                                                                                                                                                    
		lclExceptionCode = pExceptionInfo->ExceptionRecord->ExceptionCode,                                                                                                                                                                             
		lclExceptionAddr = pExceptionInfo->ExceptionRecord->ExceptionAddress,                                                                                                                                                                          
		EXCEPTION_EXECUTE_HANDLER                                                                                                                                                                                                                      
		)                                                                                                                                                                                                                                               
	{                                                                                                                                                                                                                                                    
		DebugPrint((".TDIClnRecv:  MmProbeAndLockPages() failed.  Error = 0x%08x at 0x%08x\n",
			lclExceptionCode, lclExceptionAddr));
		goto Error_Exit;
	}
	lpContext->pIrp = pIrp;
	lpContext->pMdl = pMdl;
	return STATUS_SUCCESS;
Error_Exit:
	if ( pMdl )
		IoFreeMdl ( pMdl );
	if ( pIrp )
		IoFreeIrp ( pIrp );
	return STATUS_UNSUCCESSFUL;
}
NTSTATUS                                          
TDIRecvRemainderCompRoutine(
	PDEVICE_OBJECT      DeviceObject, // TDI driver's device object.
	PIRP                pIrp,    // Address of completed Irp.
	PVOID               pCtx     // Pointer to context.
	)
/*++

Routine Description:

  Completion routine of IoRequestPacket in TDIEventRecvDatagram.
  It copies receiving data in recvContext.RemainderBuffer to RxBuffer.
  The length of receining data is indicated by pIrp->IoStatus.Information.

Arguments:

    DeviceObject - pointer to the device object
	pIrp		- pointer to completed Irp, which is recvContext->pIrp
	pCtx		- pointer to context, which is deviceExtension

Return Value:

    NT status code.

--*/
{
	PDEVICE_EXTENSION	deviceExtension;
	PRECV_CONTEXT lpContext;
	ULONG			RecvDataLength;
	PUCHAR			lpSrc;

	DebugPrint(("TDIRecvRemainderCompRoutine...\n"));
	RecvDataLength = pIrp->IoStatus.Information;
	deviceExtension = (PDEVICE_EXTENSION)pCtx;
	DebugPrint(("Remainder length: %d\n", RecvDataLength ));
	CopyToRingBuffer ( deviceExtension,
		(PUCHAR)deviceExtension->recvContext.RemainderBuffer,
		RecvDataLength );
	return STATUS_MORE_PROCESSING_REQUIRED;
}
NTSTATUS TDIFreeRecvContext( PRECV_CONTEXT lpContext )
/*++

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -