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

📄 readwrite.c

📁 windows平台下虚拟串口的driver文件
💻 C
字号:
#include <ntddk.h>
#include <ntddser.h>
#include "main.h"

extern DEVICE_ARRAY	gDeviceArray[ MAX_NUM_DEV ];
extern KSPIN_LOCK		gSpinLock;
extern KSPIN_LOCK		gPoolSpinLock;
extern LIST_ENTRY		gIdleQueue;

NTSTATUS
DispatchRead(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
{
	NTSTATUS			status;
	PDEVICE_EXTENSION	deviceExtension;
	KIRQL				OldIrql;
	BOOLEAN				bIsEmpty;

	status = STATUS_SUCCESS;
	DebugPrint(("Enter Read routine\n"));
	deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;


/*
	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DbgPrint("InputBufferLength:  %d     OutputBufferLength:   %d\n", InputLength, OutputLength );

	pOutBuf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
	*/
	/*
	DebugPrint(("pOutBuf:   0x%x\n", pOutBuf ));
	*pOutBuf = 0x32;

	DebugPrint(("Exit read routine\n"));

  return CompleteRequest(Irp, status, info);
	*/
	// 创建两个队列,一个是Irp队列,一个是Packet队列。
	// 当packet队列为空时,将Irp放入队列
	// 否则从packet队列里边取出数据,返回ReadIrp
	KeAcquireSpinLock( &deviceExtension->ReadQueueSpinLock, &OldIrql );
	bIsEmpty = IsListEmpty( &deviceExtension->ReadDataQueue );
	KeReleaseSpinLock( &deviceExtension->ReadQueueSpinLock, OldIrql );
	if( bIsEmpty ){
		IoMarkIrpPending( Irp );
		IoSetCancelRoutine( Irp, RequestCancelReadRoutine);
		ExInterlockedInsertTailList( &deviceExtension->ReadIrpQueue, &Irp->Tail.Overlay.ListEntry, &deviceExtension->CancelSpinLock );
		status = STATUS_PENDING;
		return status;
	}else{
		return CompleteReadIrp( deviceExtension, Irp );
	}
	
}
/*

*/
NTSTATUS
DispatchWrite(
	IN PDEVICE_OBJECT DeviceObject,
	IN PIRP Irp
	)
{
	PIO_STACK_LOCATION IrpStack;
	ULONG				ControlCode;
	ULONG				InputLength,OutputLength;
	NTSTATUS			status;
	PDEVICE_EXTENSION	deviceExtension;
	ULONG				info;
	PUCHAR				pInBuf;
	PLIST_ENTRY			link;
	ULONG				nTx;
	PPACKET				lpPacket;

	KIRQL				OldIrql;
	KIRQL				remoteOldIrql;
	PDEVICE_EXTENSION	remoteDev;
	PIRP				pendingMaskIrp;
	
	ULONG				i;
	PLIST_ENTRY			linkIrp;

	status = STATUS_SUCCESS;
	info = 0;
	DebugPrint(("---------      Enter Write routine    -------\n"));
	deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;

	IrpStack=IoGetCurrentIrpStackLocation(Irp);
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DbgPrint("InputBufferLength:  %d     OutputBufferLength:   %d\n", InputLength, OutputLength );

	pInBuf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;
	DebugPrint(("Data to write: \n"));
	for( i = 0; i < OutputLength; i++)
	{
		//*( pInBuf++ ) = i % 256;
		DbgPrint("%2x ", pInBuf[ i ] );
	}
	DbgPrint("\n");
	KeAcquireSpinLock( &gSpinLock, &OldIrql );
	if( deviceExtension->bIsConnected ){
		// 将数据打包成packet,
		// 检查接收端有无ReadIrp在队列中
		// 若有,完成该ReadIrp
		// 若无,则直接放入接收端的接收packet队列中
		nTx = 0;
		remoteDev = gDeviceArray[ deviceExtension->remoteInstance ].deviceExtension;
		while( nTx < OutputLength ){
			if( link = ExInterlockedRemoveHeadList( &gIdleQueue, &gPoolSpinLock ) ){
				lpPacket = CONTAINING_RECORD( link, PACKET, ListEntry );
				DebugPrint(("lpPacket: %x\n", lpPacket ));
				lpPacket->nTotalNum = ( ( OutputLength - nTx ) > PACKET_SIZE  ) ? PACKET_SIZE : ( OutputLength - nTx );
				lpPacket->nReadBytes = 0;
				RtlCopyMemory( lpPacket->Buffer, &pInBuf[ nTx ], lpPacket->nTotalNum );
				ExInterlockedInsertTailList( &( remoteDev->ReadDataQueue ), link, &remoteDev->ReadQueueSpinLock );
				nTx += lpPacket->nTotalNum;

				// 察看remoteInstance是否有ReadIrp
				linkIrp = ExInterlockedRemoveHeadList( &remoteDev->ReadIrpQueue, &remoteDev->CancelSpinLock );
				if( linkIrp ){
					// 若远方端口已经有ReadIrp在pending,则完成该ReadIrp
					pendingMaskIrp = CONTAINING_RECORD( linkIrp, IRP, Tail.Overlay.ListEntry );
					ASSERT( pendingMaskIrp );
					CompleteReadIrp( remoteDev, pendingMaskIrp );
				}
			}else{
				DebugPrint(("IdleQueue is empty!!!!\n"));
				break;
			}
		}
		info = nTx;
	}else{
		info = OutputLength;
	}
	KeReleaseSpinLock( &gSpinLock, OldIrql );
	DebugPrint(("Totally wrote %d\n---------      Exit Write routine    -------\n", info ));

	return CompleteRequest(Irp, status, info);
}

NTSTATUS
CompleteReadIrp(
	IN PDEVICE_EXTENSION	deviceExtension,
	IN PIRP					Irp
	)
{
	PIO_STACK_LOCATION	IrpStack;
	NTSTATUS			status;
	ULONG				ControlCode;
	ULONG				InputLength,OutputLength;
	PUCHAR				pOutBuf;
	ULONG				info;
	ULONG				nToReadBytes;
	PLIST_ENTRY			link;
	PPACKET				lpPacket;


	DebugPrint(("------  Enter CompleteReadIrp routine ( 0x%x )  --------\n", Irp));
	IrpStack = IoGetCurrentIrpStackLocation(Irp);

	DebugPrint(("GetCurrentIrpStackLocation OK\n"));
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DbgPrint("InputBufferLength:  %d     OutputBufferLength:   %d\n", InputLength, OutputLength );

	pOutBuf = (PUCHAR)Irp->AssociatedIrp.SystemBuffer;

	link = ExInterlockedRemoveHeadList( &deviceExtension->ReadDataQueue, &deviceExtension->ReadQueueSpinLock );
	ASSERT( link );
	lpPacket = CONTAINING_RECORD( link, PACKET, ListEntry );
	DebugPrint(("lpPacket: %x!\n", lpPacket ));
	nToReadBytes = ( lpPacket->nTotalNum - lpPacket->nReadBytes );
	ASSERT( nToReadBytes > 0);
	nToReadBytes = ( nToReadBytes > OutputLength ) ? OutputLength : nToReadBytes;
	RtlCopyMemory( pOutBuf, &( lpPacket->Buffer[ lpPacket->nReadBytes ] ), nToReadBytes );
	lpPacket->nReadBytes += nToReadBytes;
	if( lpPacket->nReadBytes == lpPacket->nTotalNum ){
		RtlZeroMemory( lpPacket, sizeof( PACKET ) );
		DebugPrint(("ZeroMemory lpPacket!\n"));
		ExInterlockedInsertTailList( &gIdleQueue, &( lpPacket->ListEntry ), &gPoolSpinLock );
	}else{
		ExInterlockedInsertHeadList( &deviceExtension->ReadDataQueue, link, &deviceExtension->ReadQueueSpinLock );
	}
	status = STATUS_SUCCESS;
	DebugPrint(("--------      Exit ReadIrp routine   -----------\n"));
	return CompleteRequest( Irp, status, nToReadBytes );
}

⌨️ 快捷键说明

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