📄 ioctl.c
字号:
{
DebugPrint(("-- IOCTL_SERIAL_GET_WAIT_MASK --\n"));
break;
}
case IOCTL_SERIAL_SET_WAIT_MASK:
{
ULONG NewMask;
if ( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(ULONG)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}else{
NewMask = *((ULONG *)Irp->AssociatedIrp.SystemBuffer);
}
DebugPrint(("-- IOCTL_SERIAL_SET_WAIT_MASK --\n"));
if (NewMask & ~(SERIAL_EV_RXCHAR |
SERIAL_EV_RXFLAG |
SERIAL_EV_TXEMPTY |
SERIAL_EV_CTS |
SERIAL_EV_DSR |
SERIAL_EV_RLSD |
SERIAL_EV_BREAK |
SERIAL_EV_ERR |
SERIAL_EV_RING |
SERIAL_EV_PERR |
SERIAL_EV_RX80FULL |
SERIAL_EV_EVENT1 |
SERIAL_EV_EVENT2)) {
DebugPrint(("SERIAL: Unknown mask %x\n",NewMask));
status = STATUS_INVALID_PARAMETER;
break;
}
DebugPrint(("Set wait mask: 0x%x\n", NewMask ));
if( deviceExtension->bIsWaitOnMask ){ // 取消上一次的WAIT_ON_MASK Irp
ASSERT( deviceExtension->WaitOnMaskIrp );
*((ULONG *)deviceExtension->WaitOnMaskIrp->AssociatedIrp.SystemBuffer) = 0;
CompleteRequest( deviceExtension->WaitOnMaskIrp, STATUS_SUCCESS, sizeof( ULONG ));
deviceExtension->WaitOnMaskIrp = NULL;
deviceExtension->bIsWaitOnMask = FALSE;
}
deviceExtension->WaitMask = NewMask;
status = STATUS_SUCCESS;
//SerialStartMask();
break;
}
case IOCTL_SERIAL_WAIT_ON_MASK:
{
ULONG RetMask;
DebugPrint(("-- IOCTL_SERIAL_WAIT_ON_MASK --\n"));
if ( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(ULONG)) {
DebugPrint(("SERIAL: Invalid size for the buffer %d\n",
IrpStack->Parameters.DeviceIoControl.OutputBufferLength));
status = STATUS_BUFFER_TOO_SMALL;
break;
}else if( deviceExtension->bIsWaitOnMask ){
DebugPrint(("There is a wait-on-mask request already pending\n"));
status = STATUS_INVALID_PARAMETER;
break;
}
/*
RetMask = SERIAL_EV_TXEMPTY | SERIAL_EV_RXCHAR | SERIAL_EV_RX80FULL;//SERIAL_EV_CTS;
//SerialStartMask();
*((ULONG *)Irp->AssociatedIrp.SystemBuffer) = RetMask;
*/
DebugPrint(("MarkIrpPending\n"));
IoMarkIrpPending( Irp );
IoSetCancelRoutine( Irp, RequestCancelMaskRoutine);
ASSERT( deviceExtension->WaitOnMaskIrp == NULL );
deviceExtension->WaitOnMaskIrp = Irp;
deviceExtension->bIsWaitOnMask = TRUE;
status = STATUS_PENDING;
return status;
}
case IOCTL_SERIAL_IMMEDIATE_CHAR:
DebugPrint(("-- IOCTL_SERIAL_IMMEDIATE_CHAR --\n"));
break;
case IOCTL_SERIAL_PURGE:
{
ULONG PurgeMask;
DebugPrint(("-- IOCTL_SERIAL_PURGE --\n"));
if ( IrpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof( ULONG )) {
DebugPrint(("Serial purge output buffer too small\n"));
status = STATUS_BUFFER_TOO_SMALL;
break;
}
PurgeMask = *(PULONG)Irp->AssociatedIrp.SystemBuffer;
DebugPrint(("IOCTL_SERIAL_PURGE: 0x%x\n", PurgeMask));
if( PurgeMask & SERIAL_PURGE_RXABORT ){
RequestPurgeIrpQueue( DeviceObject, &deviceExtension->ReadIrpQueue );
}
if( PurgeMask & SERIAL_PURGE_TXABORT ){
RequestPurgeIrpQueue( DeviceObject, &deviceExtension->WriteIrpQueue );
}
if( PurgeMask & SERIAL_PURGE_RXCLEAR ){
RequestPurgeDataQueue( DeviceObject, &deviceExtension->ReadDataQueue );
}
if( PurgeMask & SERIAL_PURGE_TXCLEAR ){
DebugPrint(("Purge TxClear\n"));
}
info = sizeof( ULONG );
status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_GET_HANDFLOW:
{
PSERIAL_HANDFLOW HandFlow;
DebugPrint(("-- IOCTL_SERIAL_GET_HANDFLOW --\n"));
if ( IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
sizeof(SERIAL_HANDFLOW)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
HandFlow = (PSERIAL_HANDFLOW)Irp->AssociatedIrp.SystemBuffer;
HandFlow->ControlHandShake = deviceExtension->HandFlow.ControlHandShake;
HandFlow->FlowReplace = deviceExtension->HandFlow.FlowReplace;
HandFlow->XonLimit = deviceExtension->HandFlow.XonLimit;
HandFlow->XoffLimit = deviceExtension->HandFlow.XoffLimit;
DebugPrint(("ControlHandShake: %d FlowReplace: %d XonLimit: %d XoffLimit: %d\n", HandFlow->ControlHandShake, HandFlow->FlowReplace, HandFlow->XonLimit, HandFlow->XoffLimit));
info = sizeof(SERIAL_HANDFLOW);
status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_SET_HANDFLOW:
{
PSERIAL_HANDFLOW HandFlow = Irp->AssociatedIrp.SystemBuffer;
if ( IrpStack->Parameters.DeviceIoControl.InputBufferLength <
sizeof(SERIAL_HANDFLOW)) {
status = STATUS_BUFFER_TOO_SMALL;
break;
}
DebugPrint(("-- IOCTL_SERIAL_SET_HANDFLOW --\n"));
if (HandFlow->ControlHandShake & SERIAL_CONTROL_INVALID) {
status = STATUS_INVALID_PARAMETER;
break;
}
if (HandFlow->FlowReplace & SERIAL_FLOW_INVALID) {
status = STATUS_INVALID_PARAMETER;
break;
}
if ((HandFlow->ControlHandShake & SERIAL_DTR_MASK) ==
SERIAL_DTR_MASK) {
status = STATUS_INVALID_PARAMETER;
break;
}
if ((HandFlow->XonLimit < 0) ||
((ULONG)HandFlow->XonLimit > deviceExtension->BufferSize)) {
DebugPrint(("XonLimit( %d ) > BufferSize\n", ((ULONG)HandFlow->XonLimit )));
status = STATUS_INVALID_PARAMETER;
break;
}
if ((HandFlow->XoffLimit < 0) ||
((ULONG)HandFlow->XoffLimit > deviceExtension->BufferSize)) {
DebugPrint(("XoffLimit( %d ) > BufferSize\n", ((ULONG)HandFlow->XoffLimit )));
status = STATUS_INVALID_PARAMETER;
break;
}
deviceExtension->HandFlow.ControlHandShake = HandFlow->ControlHandShake;
deviceExtension->HandFlow.FlowReplace = HandFlow->FlowReplace;
deviceExtension->HandFlow.XonLimit = HandFlow->XonLimit;
deviceExtension->HandFlow.XoffLimit = HandFlow->XoffLimit;
DebugPrint(("Set_HandFlow OK\n"));
status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_GET_MODEMSTATUS:
DebugPrint(("-- IOCTL_SERIAL_GET_MODEMSTATUS --\n"));
break;
case IOCTL_SERIAL_GET_DTRRTS:
DebugPrint(("-- IOCTL_SERIAL_GET_DTRRTS --\n"));
break;
case IOCTL_SERIAL_GET_COMMSTATUS:
DebugPrint(("-- IOCTL_SERIAL_GET_COMMSTATUS --\n"));
break;
case IOCTL_SERIAL_GET_PROPERTIES:
DebugPrint(("-- IOCTL_SERIAL_GET_PROPERTIES --\n"));
break;
case IOCTL_SERIAL_XOFF_COUNTER:
DebugPrint(("-- IOCTL_SERIAL_XOFF_COUNTER --\n"));
break;
case IOCTL_SERIAL_LSRMST_INSERT:
DebugPrint(("-- IOCTL_SERIAL_LSRMST_INSERT --\n"));
break;
case IOCTL_SERIAL_CONFIG_SIZE:
{
DebugPrint(("-- IOCTL_SERIAL_CONFIG_SIZE --\n"));
if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG ) ){
status = STATUS_BUFFER_TOO_SMALL;
break;
}
info = sizeof( ULONG );
*(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
status = STATUS_SUCCESS;
break;
}
case IOCTL_SERIAL_GET_STATS:
DebugPrint(("-- IOCTL_SERIAL_GET_STATS --\n"));
break;
case IOCTL_SERIAL_CLEAR_STATS:
DebugPrint(("-- IOCTL_SERIAL_CLEAR_STATS --\n"));
break;
default:
break;
}
return CompleteRequest(Irp, status, info);
}
VOID
RequestPurgeIrpQueue(
IN PDEVICE_OBJECT DeviceObject,
IN PLIST_ENTRY QueueToProcess
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to deviceobject
Irp - Pointer to a PnP Irp.
Return Value:
NT Status is returned.
--*/
{
PDEVICE_EXTENSION deviceExtension;
PLIST_ENTRY link;
PIRP pendingIrp;
DebugPrint(("Enter RequestPurgeIrpQueue routine...\n"));
deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
link = ExInterlockedRemoveHeadList( QueueToProcess, &deviceExtension->CancelSpinLock );
while( link ){
pendingIrp = CONTAINING_RECORD( link, IRP, Tail.Overlay.ListEntry );
ASSERT( pendingIrp );
pendingIrp->IoStatus.Status = STATUS_CANCELLED;
pendingIrp->IoStatus.Information = 0;
IoCompleteRequest( pendingIrp, IO_NO_INCREMENT );
link = ExInterlockedRemoveHeadList( QueueToProcess, &deviceExtension->CancelSpinLock );
}
return;
}
VOID
RequestCancelReadRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to deviceobject
Irp - Pointer to a PnP Irp.
Return Value:
NT Status is returned.
--*/
{
BOOLEAN bRet;
PDEVICE_EXTENSION deviceExtension;
DebugPrint(("Enter RequestCancelRead routine...\n"));
deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
bRet = RequestCancelRoutine( &deviceExtension->ReadIrpQueue, &deviceExtension->CancelSpinLock, Irp );
return;
}
VOID
RequestCancelWriteRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to deviceobject
Irp - Pointer to a PnP Irp.
Return Value:
NT Status is returned.
--*/
{
BOOLEAN bRet;
PDEVICE_EXTENSION deviceExtension;
DebugPrint(("Enter RequestCancelRead routine...\n"));
deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
bRet = RequestCancelRoutine( &deviceExtension->WriteIrpQueue, &deviceExtension->CancelSpinLock, Irp );
return;
}
VOID
RequestCancelMaskRoutine(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp
)
/*++
Routine Description:
Arguments:
DeviceObject - Pointer to deviceobject
Irp - Pointer to a PnP Irp.
Return Value:
NT Status is returned.
--*/
{
PDEVICE_EXTENSION deviceExtension;
DebugPrint(("Enter RequestCancelRead routine...\n"));
deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
ASSERT( deviceExtension->bIsWaitOnMask && ( deviceExtension->WaitOnMaskIrp != NULL ) );
CompleteRequest( deviceExtension->WaitOnMaskIrp, STATUS_CANCELLED, 0 );
deviceExtension->WaitOnMaskIrp = NULL;
deviceExtension->bIsWaitOnMask = FALSE;
return;
}
BOOLEAN
RequestCancelRoutine(
IN PLIST_ENTRY QueueToProcess,
IN PKSPIN_LOCK CancelSpinLock,
IN PIRP Irp)
/*++
Routine Description:
A cancel routine for use when cancelling the pending IRP
Arguments:
QueueToProcess - The queue to be processing
CancelSpinLock - Cancel spin lock
Irp - Pointer to a PnP Irp.
Return Value:
NT Status is returned.
If the Irp is in the QueueToProcess, we cancel the irp and return TRUE; else return FALSE.
--*/
{
PLIST_ENTRY link;
PIRP pendingIrp;
PIRP IrpToComplete;
KIRQL oldIrpl;
DebugPrint(("Enter RequestCancel routine...\n"));
IrpToComplete = NULL;
// Find the Irp in the QueueToProcess
KeAcquireSpinLock( CancelSpinLock, &oldIrpl );
for( link = QueueToProcess->Flink; link != QueueToProcess; link = link->Flink )
{
pendingIrp = CONTAINING_RECORD( link, IRP, Tail.Overlay.ListEntry );
ASSERT( pendingIrp );
if( pendingIrp == Irp ){
DebugPrint(("Find out the pending irp, to remove...\n"));
RemoveEntryList( link );
IrpToComplete = pendingIrp;
break;
}
}
KeReleaseSpinLock( CancelSpinLock, oldIrpl );
if( IrpToComplete ){
// If we find out the Irp, cancel the Irp
DebugPrint(("Cancelled Irp\n"));
IrpToComplete->IoStatus.Status = STATUS_CANCELLED;
IrpToComplete->IoStatus.Information = 0;
IoCompleteRequest( IrpToComplete, IO_NO_INCREMENT );
return TRUE;
}else
return FALSE;
}
NTSTATUS Disconnect( IN PDEVICE_EXTENSION deviceExtension )
/*++
Routine Description:
disconnect two virtual devices which are connected before
Arguments:
deviceExtension - Pointer to device extension
Return Value:
NT Status is returned.
--*/
{
PDEVICE_EXTENSION remoteDevExt;
KIRQL OldIrql;
KeAcquireSpinLock( &gSpinLock, &OldIrql );
if( !deviceExtension->bIsConnected ){
KeReleaseSpinLock(&gSpinLock, OldIrql );
return STATUS_INVALID_DEVICE_REQUEST;
}
remoteDevExt = gDeviceArray[ deviceExtension->remoteInstance ].deviceExtension;
deviceExtension->remoteInstance = INVALID_INSTANCE;
deviceExtension->bIsConnected = FALSE;
remoteDevExt->remoteInstance = INVALID_INSTANCE;
remoteDevExt->bIsConnected = FALSE;
KeReleaseSpinLock( &gSpinLock, OldIrql );
return STATUS_SUCCESS;
}
VOID
RequestPurgeDataQueue(
IN PDEVICE_OBJECT DeviceObject,
IN PLIST_ENTRY QueueToProcess
)
{
PDEVICE_EXTENSION deviceExtension;
PLIST_ENTRY link;
PPACKET lpPacket;
DebugPrint(("Enter RequestPurgeDataQueue routine...\n"));
deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;
while( link = ExInterlockedRemoveHeadList( QueueToProcess, &deviceExtension->ReadQueueSpinLock )){
lpPacket = CONTAINING_RECORD( link, PACKET, ListEntry );
RtlZeroMemory( lpPacket, sizeof( PACKET ) );
ExInterlockedInsertTailList( &gIdleQueue, &( lpPacket->ListEntry ), &gPoolSpinLock );
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -