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

📄 comfilntdevice.cpp

📁 一个2000系统上的虚拟串口驱动程序
💻 CPP
📖 第 1 页 / 共 3 页
字号:
// ComfilntDevice.cpp
// Implementation of ComfilntDevice device class
//
// Generated by DriverWizard version DriverStudio 2.5.0 (Build 240)
// Requires Compuware's DriverWorks classes
//

#include <vdw.h>
//#include "ntddser.h"
#include <kfifo.h>
#include "Comfilnt.h"
#include "ComfilntDevice.h"

#pragma warning(disable:4065) // Allow switch statement with no cases

extern	KTrace	t;			// Global driver trace object	

////////////////////////////////////////////////////////////////////////
// ComfilntDevice::~ComfilntDevice
//
//	Routine Description:
//		This is the destructor for the ComfilntDevice
//
//	Parameters:
//		None
//
//	Return Value:
//		None
//
//	Comments:
//		Disconnect and release resources here.
//
//		Although the use of SAFE_DESTRUCTORS in the class definition cures
//		improper emission of the destructor into the INIT section most of the
//		time, certain rare cases can still cause improper behavior.  To avoid
//		these cases, the destructor	must preceed the INIT section, causing it
//		to be referenced first by the default compiler section.
//

ComfilntDevice::~ComfilntDevice()
{
	delete m_RegPath;
}

#pragma code_seg("INIT")

////////////////////////////////////////////////////////////////////////////////
//  ComfilntDevice::ComfilntDevice
//
//	Routine Description:
//		The device constructor is typically responsible for allocating
//		any physical resources that are associated with the device.
//
//	Parameters:
//		Unit - Unit number. This is a number to append to the device's
//			base device name to distinguish multiple units of this
//			device type.
//
//	Return Value:
//		None
//
//	Comments:
//		The device constructor often reads the registry to setup
//		various configurable parameters.

ComfilntDevice::ComfilntDevice(ULONG Unit,PRW pRW) :
	KDevice()
{
	t << "Enter ComfilntDevice: unit number= " << Unit << "; status= " << (ULONG) m_ConstructorStatus << EOL;
	if ( ! NT_SUCCESS(m_ConstructorStatus) )
	{
		t << "Failed to create device ComfilntDevice unit number " << Unit << " status " << (ULONG) m_ConstructorStatus << EOL;
		return;
	}
	m_Unit = Unit;
	m_IsOpened=0;
	m_pRW=pRW;
//	t << (ULONG) pRW <<EOL;
	m_RegPath = CreateRegistryPath(L"ComfilntDevice", Unit);
	if (m_RegPath == NULL)
	{
		// Error, cannot allocate memory for registry path
		t << "Failed to create registry path\n";
		m_ConstructorStatus = STATUS_INSUFFICIENT_RESOURCES;
		return;
	}

}
#pragma code_seg()

////////////////////////////////////////////////////////////////////////
//  ComfilntDevice::Read
//
//	Routine Description:
//		Handler for IRP_MJ_READ
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//		This routine handles read requests.

NTSTATUS ComfilntDevice::Read(KIrp I)
{
	ULONG Count=0;
	ULONG ReadedBytes=0;
	t << "== Read == " << m_Unit << EOL;
//	t << "Irp=" << I ;
//	t << "COM=" <<m_Unit << EOL;
// TODO:	Check the incoming request.  Replace "FALSE" in the following
//			line with a check that returns TRUE if the request is not valid.
    if (FALSE)
	{
		I.Information() = 0;
		return I.Complete(STATUS_INVALID_PARAMETER);
	}
	CancelSpinLock::Acquire();

	// Always ok to read 0 elements
	if (I.ReadSize() == 0)
	{
		I.Information() = 0;
		return I.Complete(STATUS_SUCCESS);
	}
	NTSTATUS status		= STATUS_SUCCESS;

	KMemory Mem(I.Mdl());						// Declare a memory object
	// Use the memory object to create a pointer to the caller's buffer
	PUCHAR	pBuffer		= (PUCHAR) Mem.VirtualAddress();

	ULONG   dwTotalSize = I.ReadSize(CURRENT);	// Requested read size
	ULONG   dwBytesRead = 0;					// Count of bytes read

// TODO:	If the read can be satisfied immediately, set the Information
//			and Status fields now, then call NextIrp to complete this IRP
//			and start processing the next IRP in the queue.

// TODO:	If the data is not yet available, initiate a request to the
//			physical device here, and defer the Information, Status,
//			and NextIrp handling until the hardware indicates that the
//			read is complete.  Typically, this might be handled in a
//			DPC that is called after the hardware finishes transferring
//			the data.

// TODO:	To satisfy the read now, transfer data from the device to
//			caller's buffer at "pBuffer".  Then, indicate how much data was
//			transferred:
//	RtlCopyMemory( pBuffer, TEXT("1234567890"), 11);
//	pBuffer=(unsigned char*)TEXT("1234567890");
/*	
	int Count=BytePipe.NumberOfItemsAvailableForRead();
	int ReadedBytes=0;
	t <<(ULONG) Count << EOL;
	if(Count==0)
		m_EvenMask=(ULONG)0;

	for(int i=0;i<Count;i++){
		dwBytesRead=BytePipe.Read(pBuffer,dwTotalSize);
		pBuffer+=dwBytesRead;
		ReadedBytes+=dwBytesRead;
	}
*/
	if((m_Unit&1)==0){
		Count=m_pRW->PipeB.NumberOfItemsAvailableForRead();
		//if(Count>dwTotalSize)

		ReadedBytes=0;
		if(Count==0)
			m_pRW->MaskB &=~SERIAL_EV_RXCHAR;

			dwBytesRead=m_pRW->PipeB.Read(pBuffer,dwTotalSize);
			ReadedBytes=dwBytesRead;
		
	}else{
		Count=m_pRW->PipeA.NumberOfItemsAvailableForRead();
		ReadedBytes=0;
		if(Count==0)
			m_pRW->MaskA &=~SERIAL_EV_RXCHAR;

			dwBytesRead=m_pRW->PipeA.Read(pBuffer,dwTotalSize);
			ReadedBytes=dwBytesRead;
		
	}
//	t << "Read Buffer=" << (TCHAR*)pBuffer <<EOL;
//	m_EvenMask=(ULONG)0;
	if((m_Unit&1)==0){
		m_pRW->MaskB &=~SERIAL_EV_RXCHAR;
//		m_pRW->WriteCountB=(ULONG)0;
	}else{
		m_pRW->MaskA &=~SERIAL_EV_RXCHAR;
//		m_pRW->WriteCountA=(ULONG)0;
	}
	if(Count <= ReadedBytes)
	m_WaitMask &= ~EV_RXFLAG;

	I.Information() = ReadedBytes;
	status = STATUS_SUCCESS;
	CancelSpinLock::Release();
	return I.Complete(status);
}


////////////////////////////////////////////////////////////////////////
//  ComfilntDevice::Write
//
//	Routine Description:
//		Handler for IRP_MJ_WRITE
//
//	Parameters:
//		I - Current IRP
//
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//		This routine handles write requests.

NTSTATUS ComfilntDevice::Write(KIrp I)
{
	t << "--- Write " <<m_Unit << EOL;
//	t << "Irp=" << I ;
//	t << "COM=" <<m_Unit << EOL;
// TODO:	Check the incoming request.  Replace "FALSE" in the following
//			line with a check that returns TRUE if the request is not valid.
    if (FALSE)
	{
		I.Information() = 0;
		return I.Complete(STATUS_INVALID_PARAMETER);
	}
	CancelSpinLock::Acquire();

	// Always ok to write 0 elements
	if (I.WriteSize() == 0)
	{
		I.Information() = 0;
		return I.Complete(STATUS_SUCCESS);
	}
	NTSTATUS status		= STATUS_SUCCESS;

	KMemory Mem(I.Mdl());						// Declare a memory object
	// Use the memory object to create a pointer to the caller's buffer
	PUCHAR	pBuffer		= (PUCHAR) Mem.VirtualAddress();

	ULONG   dwTotalSize = I.WriteSize(CURRENT);
	ULONG   dwBytesSent = 0;
	if(dwTotalSize>0x100)
		dwTotalSize=0x100;
	
	if((m_Unit&1)==0){
		if(m_pRW->PipeA.IsFull()==FALSE){
			dwBytesSent=m_pRW->PipeA.Write(pBuffer,dwTotalSize);
			m_pRW->WriteCountA=dwBytesSent;
//			t<<"Write PipeA,CountA="<<(ULONG)m_pRW->WriteCountA<<EOL;
			m_pRW->MaskA=SERIAL_EV_RXCHAR;
//			t <<"MaskA"<<(ULONG)m_pRW->MaskA<< EOL;
		}else{
//			t <<"Pending(A),COM="<<(ULONG)m_Unit<< EOL;
			dwBytesSent=0;
			status	= STATUS_PENDING;
		}
	}else{
		if(m_pRW->PipeB.IsFull()==FALSE){
			dwBytesSent=m_pRW->PipeB.Write(pBuffer,dwTotalSize);
			m_pRW->WriteCountB=dwBytesSent;
			t<<"Write PipeB,CountB="<<(ULONG)m_pRW->PipeB.NumberOfItemsAvailableForRead()<<EOL;
//			t <<"MaskB"<<(ULONG)m_pRW->MaskB<< EOL;
			m_pRW->MaskB=SERIAL_EV_RXCHAR;
		}else{
//			t <<"Pending (B),COM="<<(ULONG)m_Unit<< EOL;
			dwBytesSent = 0;
			status	= STATUS_PENDING;
		}
	}

//	t << "****Write Buffer=" <<(char*)wkBuffer <<EOL;
//	t << "****Write Bytes=" <<dwBytesSent <<EOL;
	I.Information() = dwBytesSent;
	m_WaitMask|=EV_RXFLAG;
//	status		= STATUS_SUCCESS;
//	if((m_Unit&1)==0){
//
//		m_pRW->MaskA|=SERIAL_EV_RXCHAR;
//		t <<"MaskA"<<(ULONG)m_pRW->MaskA<< EOL;
//	}else{
//		t <<"MaskB"<<(ULONG)m_pRW->MaskB<< EOL;
//		m_pRW->MaskB|=SERIAL_EV_RXCHAR;
//	}
	CancelSpinLock::Release();
	return I.Complete(status);
}

////////////////////////////////////////////////////////////////////////
//  ComfilntDevice::DeviceControl
//
//	Routine Description:
//		Handler for IRP_MJ_DEVICE_CONTROL
//
//	Parameters:
//		I - Current IRP
// 
//	Return Value:
//		NTSTATUS - Result code
//
//	Comments:
//		This routine is the first handler for Device Control requests.

NTSTATUS ComfilntDevice::DeviceControl(KIrp I) 
{
	NTSTATUS status;
	ULONG Mask;
//	t << "<<Device Control>>" <<EOL;
//t << (ULONG)m_pRW <<EOL;
//	t << "Irp=" << I ;
	CancelSpinLock::Acquire();
	ULONG code=I.IoctlCode();
//	t << "COM=" <<m_Unit << " Code=" << (unsigned long) code << EOL;

	I.Information() = 0;

	switch (I.IoctlCode())
	{
	///////////////////////////////////////////////////////////////////
	// Set Baud Rate
	//(4h--1)
	case IOCTL_SERIAL_SET_BAUD_RATE:
	{
		PSERIAL_BAUD_RATE pBR;

		pBR = PSERIAL_BAUD_RATE(I.IoctlBuffer());

//		GTRACE( (TLEVEL,"--IOCTL_SERIAL_SET_BAUD_RATE, rate=%d\n", pBR->BaudRate) ); 
			
		if (I.IoctlInputBufferSize() < sizeof(SERIAL_BAUD_RATE) )
			status = STATUS_BUFFER_TOO_SMALL;
		else
		{
			IoctlSetBaudRate( *pBR );
			I.Information() = 0;
			status = STATUS_SUCCESS;
		}
		break;
	}
	///////////////////////////////////////////////////////////////////
	// Get Baud Rate
	//(50h--20)
	case IOCTL_SERIAL_GET_BAUD_RATE:

//		GTRACE((TLEVEL,"--IOCTL_SERIAL_GET_BAUD_RATE\n")); 

		if (I.IoctlOutputBufferSize() < sizeof(SERIAL_BAUD_RATE) )
			status = STATUS_BUFFER_TOO_SMALL;
		else
		{
			IoctlGetBaudRate(*(SERIAL_BAUD_RATE*)I.IoctlBuffer());
			I.Information() = sizeof(SERIAL_BAUD_RATE);
			status = STATUS_SUCCESS;
		}			
		break;

	///////////////////////////////////////////////////////////////////
	// Set Line Control (parity, data bits, stop bits)
	//(0ch--3)
	case IOCTL_SERIAL_SET_LINE_CONTROL:
		t <<"SetLineControl" << EOL;
//		GTRACE((TLEVEL,"--IOCTL_SERIAL_SET_LINE_CONTROL: %x\n", *(UCHAR*)I.IoctlBuffer())); 
		if (I.IoctlInputBufferSize() < sizeof(SERIAL_LINE_CONTROL) )
			status = STATUS_BUFFER_TOO_SMALL;
		else
			status = IoctlSetLineControl(*(SERIAL_LINE_CONTROL*)I.IoctlBuffer());
			I.Information() = 0;
			status = STATUS_SUCCESS;

		break;		

	///////////////////////////////////////////////////////////////////
	// Get Line Control (parity, data bits, stop bits)
	//(54h--21)
	case IOCTL_SERIAL_GET_LINE_CONTROL:
		t <<"GetLineControl" << EOL;

//		GTRACE((TLEVEL,"--IOCTL_SERIAL_GET_LINE_CONTROL\n")); 

		if (I.IoctlOutputBufferSize() < sizeof(SERIAL_LINE_CONTROL) )
			status = STATUS_INVALID_PARAMETER;
		else
		{
			IoctlGetLineControl(*(SERIAL_LINE_CONTROL*)I.IoctlBuffer());
			I.Information() = sizeof (SERIAL_LINE_CONTROL);
			status = STATUS_SUCCESS;
		}
		break;

	///////////////////////////////////////////////////////////////////
	// Reset device
	//(2ch--11)
	case IOCTL_SERIAL_RESET_DEVICE:
		t <<"ReSetDevice" << EOL;
//		IoctlReset();
		I.Information() = 0;
		status = STATUS_SUCCESS;
		break;

	///////////////////////////////////////////////////////////////////
	// Set Handshake / Flow control
	//(60h--24)
	case IOCTL_SERIAL_GET_HANDFLOW:
		t <<"GetHandFlow" << EOL;

//		GTRACE((TLEVEL,"--IOCTL_SERIAL_GET_HANDFLOW\n"));

		if (I.IoctlOutputBufferSize() < sizeof SERIAL_HANDFLOW)
			status = STATUS_BUFFER_TOO_SMALL;
		else
		{			
			IoctlGetHandFlow(*(SERIAL_HANDFLOW*)I.IoctlBuffer());
			I.Information() = sizeof(SERIAL_HANDFLOW);
			status = STATUS_SUCCESS;
		}

⌨️ 快捷键说明

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