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

📄 readwrite.c

📁 好东东
💻 C
字号:
/*++

Copyright (c) 2005  Changzhi Zhou All Rights Reserved

Module Name:

    readwrite.c

Abstract:

    This module contains Read/Write routines.

Environment:

    Kernel mode

Revision History:

	Changzhi Zhou Dec 20  2004

--*/
#include <ntddk.h>
#include <initguid.h>
#include "main.h"
#include "..\inc\wdmioctl.h"
NTSTATUS
SampleRead(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
	)
/*++

Routine Description:
	Read I/O request.
	If deviceExtension->SerialStatus.AmountInInQueue, which means there are some data in RxBuffer,
	we call CopyFromRingBuffer to copy data in RxBuffer to Irp->MdlAddress.
	Else mark the Irp pending , return STATUS_PENDING and start a timer. The timeout is set by 
	IOCTL_SERIAL_SET_TIMEOUTS.

Arguments:

  DeviceObject	- pointer to device object
  Irp			- pointer to Read I/O request.

Return Value:

    NT status code.

--*/
{
	PDEVICE_EXTENSION	deviceExtension;
	NTSTATUS			status;
	PIO_STACK_LOCATION IrpStack;
	ULONG				OutputLength;
	ULONG				info;
	KIRQL				oldIrql;

	PAGED_CODE();
	DbgPrint("--- SampleRead routine...\n");
	deviceExtension = DeviceObject->DeviceExtension;
	if ( deviceExtension->DevicePnPState != Working )
		return CompleteRequest ( Irp, STATUS_INVALID_DEVICE_STATE, 0 );
	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	OutputLength = IrpStack->Parameters.Read.Length;
	if( OutputLength == 0 )
		return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
	status	= STATUS_SUCCESS;
	info	= 0;
	KeAcquireSpinLock( &deviceExtension->ThreadSpinLock, &oldIrql );
	if ( deviceExtension->PendingReadIrp == NULL )
	{
		if( deviceExtension->SerialStatus.AmountInInQueue )
		{
			info = CopyFromRingBuffer ( deviceExtension, Irp );
		}else
		{	// set timeout simply.
			LARGE_INTEGER	Timeout;
			ULONG	tmp;
			tmp = ( deviceExtension->Timeouts.ReadIntervalTimeout > READINTERVAL_TIMEOUT )
				? READINTERVAL_TIMEOUT : deviceExtension->Timeouts.ReadIntervalTimeout;
			if ( tmp > 0 )
			{
				Timeout.LowPart = ( -1 ) * tmp;
				Timeout.HighPart = -1;
				DebugPrint(("Irp (%x) Set ReadTimer %d (100 nanosecond )\n", Irp, tmp ));
				SampleIoIncrement( deviceExtension );
				deviceExtension->PendingReadIrp = Irp;
				IoMarkIrpPending ( Irp );
				status = STATUS_PENDING;
				KeSetTimer ( &deviceExtension->ReadTimer, Timeout, &deviceExtension->ReadDpc );
			}
		}
	}else
	{
		status = STATUS_INVALID_DEVICE_REQUEST;
	}
	KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql );
	if ( status != STATUS_PENDING )
		CompleteRequest( Irp, status, info );
	return status;
}
VOID
ReadDpcRoutine(
    IN PKDPC Dpc,
    IN PVOID DeferredContext,
    IN PVOID SystemArgument1,
    IN PVOID SystemArgument2
    )
/*++

Routine Description:

  DPC routine.
  It will be called by the trigger of ReadIrp timer. If there are some data, it copies the data
  to Irp->MdlAddress and then complete the Irp. If not, it complete thr Irp directly.
  The deviceExtension->PendingReadIrp is the Read I/O request saved by SampleRead.

Arguments:

	DeferredContext	- pointer to deviceExtension

--*/
{
	KIRQL				oldIrql;
	PDEVICE_EXTENSION	deviceExtension;
	PIRP				Irp;
	ULONG				info;

	deviceExtension = ( PDEVICE_EXTENSION )DeferredContext;
	info			= 0;
	KeAcquireSpinLock( &deviceExtension->ThreadSpinLock, &oldIrql );
	if ( deviceExtension->PendingReadIrp )
	{
		Irp	= deviceExtension->PendingReadIrp;
		DebugPrint(("Irp (%x) DpcRoutine...\n", Irp ));
		if ( deviceExtension->SerialStatus.AmountInInQueue )
		{
			info = CopyFromRingBuffer ( deviceExtension, Irp );
		}
		CompleteRequest( Irp, STATUS_SUCCESS, info );
		SampleIoDecrement ( deviceExtension );
		deviceExtension->PendingReadIrp = NULL;
	}
	KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql );
}
ULONG	CopyFromRingBuffer(
	PDEVICE_EXTENSION	deviceExtension,
	PIRP				Irp )
/*++

Routine Description:

	It copies RingBuffer, that is RxBuffer, to Irp->MdlAddress.
	It must be running at IRQL = DISPATCH_LEVEL within the scope of Spinlock.
Arguments:

	deviceExtension	- pointer to device object extension
	Irp				- Read I/O request packet
Return Value:

    the actual number of data copied from ringbuffer.

--*/
{
	PIO_STACK_LOCATION IrpStack;
	ULONG				OutputLength;
	ULONG				BytesToCopy;
	PUCHAR				buf;
	ULONG				stageSize;

	ASSERT ( deviceExtension->SerialStatus.AmountInInQueue );
	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	OutputLength = IrpStack->Parameters.Read.Length;
	buf = (PUCHAR)MmGetSystemAddressForMdlSafe( Irp->MdlAddress, NormalPagePriority );
	ASSERT ( buf );
	BytesToCopy = ( deviceExtension->SerialStatus.AmountInInQueue > OutputLength ) ? OutputLength : deviceExtension->SerialStatus.AmountInInQueue;
	stageSize = deviceExtension->RxBuffer + RINGBUFFER_SIZE - deviceExtension->lpRead;
	if ( BytesToCopy <= stageSize )
		RtlCopyMemory ( buf, deviceExtension->lpRead, BytesToCopy );
	else
	{
		RtlCopyMemory ( buf, deviceExtension->lpRead, stageSize );
		RtlCopyMemory ( buf + stageSize, deviceExtension->RxBuffer, ( BytesToCopy - stageSize ) );
	}
	deviceExtension->lpRead = deviceExtension->RxBuffer +
		( ( deviceExtension->lpRead + BytesToCopy - deviceExtension->RxBuffer ) % RINGBUFFER_SIZE );
	deviceExtension->SerialStatus.AmountInInQueue -= BytesToCopy;
	return BytesToCopy;
}
NTSTATUS
SampleWrite(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp
	)
/*++

Routine Description:

	It calls TdiSendDatagram to send data to remote peer, which is indicated 
	by deviceExtension->RemoteAddress and deviceExtension->RemotePort.

Arguments:

	DeviceObject	- pointer to device object.
	Irp				- Read I/O request packet
Return Value:

    NT status code.

--*/
{
	PIO_STACK_LOCATION IrpStack;
	PDEVICE_EXTENSION	deviceExtension;
	NTSTATUS			status;

	ULONG				InputLength;
	ULONG				info;
	PAGED_CODE();

	DbgPrint("--- SampleWrite routine...\n");
	deviceExtension = DeviceObject->DeviceExtension;

	if ( deviceExtension->DevicePnPState != Working )
		return CompleteRequest ( Irp, STATUS_INVALID_DEVICE_STATE, 0 );
	IrpStack = IoGetCurrentIrpStackLocation(Irp);
	InputLength = IrpStack->Parameters.Write.Length;
	if( InputLength == 0 )
		return CompleteRequest( Irp, STATUS_SUCCESS, 0 );
	SampleIoIncrement( deviceExtension );
	status	= TDISendDatagram( DeviceObject, Irp );
	info	= Irp->IoStatus.Information;
	status = CompleteRequest( Irp, status, info );
	SampleIoDecrement( deviceExtension );
	return status;
}

⌨️ 快捷键说明

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