📄 comfilntdevice.cpp
字号:
// 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 + -