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

📄 ioctl.c

📁 windows平台下虚拟串口的driver文件
💻 C
📖 第 1 页 / 共 2 页
字号:
			{
				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 + -