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

📄 ioctl.c

📁 windows平台下虚拟串口的driver文件
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <ntddk.h>
#include <ntddser.h>

#include "main.h"
#include "..\inc\wdmioctl.h"


#ifdef ALLOC_PRAGMA

#endif

extern DEVICE_ARRAY	gDeviceArray[ MAX_NUM_DEV ];
extern KSPIN_LOCK		gSpinLock;
extern KSPIN_LOCK		gPoolSpinLock;
extern LIST_ENTRY		gIdleQueue;

NTSTATUS RequestControl(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.
--*/
{
	PIO_STACK_LOCATION IrpStack;
	ULONG				ControlCode;
	ULONG				InputLength,OutputLength;
	NTSTATUS			status;
	PDEVICE_EXTENSION	deviceExtension;
	ULONG				info;

	DebugPrint(("Enter IoControl routine\n"));
	deviceExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;

	if( !deviceExtension->bIsOpen ){
		status = STATUS_INVALID_DEVICE_REQUEST;
		return CompleteRequest( Irp, status, 0 );
	}


	IrpStack=IoGetCurrentIrpStackLocation(Irp);
	
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode;
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
	DbgPrint("InputBufferLength:  %d     OutputBufferLength:   %d\n", InputLength, OutputLength );
	
	status = STATUS_INVALID_DEVICE_REQUEST;
	info = 0;
	switch(ControlCode)
	{
		case IOCTL_GET_IDENTITIER:
			// 得到本驱动的ID,用来指明该设备是本驱动生成的虚拟串口设备
			DebugPrint(("-----  IOCTL_GET_IDENTITIER   ----\n"));
			if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG ) ){
				status = STATUS_BUFFER_TOO_SMALL;
				break;
			}
			*( (PULONG)Irp->AssociatedIrp.SystemBuffer ) = VIRTUAL_SERIAL_DEVICE_ID;
			status=STATUS_SUCCESS;
			info = sizeof( ULONG );
			break;
		case IOCTL_GET_CURRENT_COMX:
			DebugPrint(("-----  IOCTL_GET_CURRENT_COMX   ----\n"));
			if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG ) ){
				status = STATUS_BUFFER_TOO_SMALL;
				break;
			}
			if( deviceExtension->CreatedSymbolicLink ){
				*( (PULONG)Irp->AssociatedIrp.SystemBuffer ) = deviceExtension->ComX;
				info = sizeof( ULONG );
				status = STATUS_SUCCESS;
			}
			break;
		case IOCTL_CREATE_DOS_NAME:
			{
				LONG ComX;
				DebugPrint(("-----  IOCTL_INIT_SETTING   ----\n"));
				if( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof( LONG ) ){
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				ComX = *((PLONG)Irp->AssociatedIrp.SystemBuffer);
				// 此处注意Dos名不要重复
				if( ( ComX > 255 ) || ( ComX < 1 ) ){
					status = STATUS_INVALID_PARAMETER;
					break;
				}
				if( !deviceExtension->CreatedSymbolicLink ){
					status = SerialDoExternalNaming( deviceExtension, ComX);
				}
				break;
			}
		case IOCTL_DEL_DOS_NAME:
			DebugPrint(("-----  IOCTL_FINISH_SETTING   ----\n"));
			if( deviceExtension->CreatedSymbolicLink ){
				status = SerialUndoExternalNaming( deviceExtension );
			}
			break;
		case IOCTL_GET_CURRENT_INSTANCE:
			{
				DebugPrint(("--  IOCTL_GET_CURRENT_INSTANCE  ---\n"));
				if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG ) ){
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				DebugPrint(("localInstance:  %d\n", deviceExtension->localInstance ));
				*( (PULONG)Irp->AssociatedIrp.SystemBuffer ) = deviceExtension->localInstance;
				status = STATUS_SUCCESS;
				info = sizeof( ULONG );
				break;
			}
		case IOCTL_SET_REMOTE_INSTANCE:
			{
				LONG	remoteInstance;
				KIRQL				OldIrql;
				DebugPrint(("--  IOCTL_SET_REMOTE_INSTANCE  ---\n"));
				if( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof( ULONG ) ){
					DebugPrint(("buffer is too small\n"));
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				// 若已经Connected,则返回错误。此时win32app 需要调用disconnect首先断开连接
				if( deviceExtension->remoteInstance != INVALID_INSTANCE ){
					break;
				}
				remoteInstance = *( (PULONG)Irp->AssociatedIrp.SystemBuffer );
				if( ( remoteInstance < 0 ) || ( remoteInstance > 255 ) ||
					( gDeviceArray[ remoteInstance ].deviceExtension == NULL ) ){
					DebugPrint(("remoteInstance error remoteInstance: %d\n", remoteInstance));
					status = STATUS_INVALID_PARAMETER;
					break;
				}
				//Disconnect( deviceExtension );
				DebugPrint(("Connect remote ports..."));
				KeAcquireSpinLock( &gSpinLock, &OldIrql );
				if( gDeviceArray[ remoteInstance ].deviceExtension->bIsConnected ){
					KeReleaseSpinLock( &gSpinLock, OldIrql );
					status = STATUS_INVALID_PARAMETER;
					break;
				}
				deviceExtension->remoteInstance = remoteInstance;
				deviceExtension->bIsConnected = TRUE;
				gDeviceArray[ remoteInstance ].deviceExtension->remoteInstance = deviceExtension->localInstance;
				gDeviceArray[ remoteInstance ].deviceExtension->bIsConnected = TRUE;
				KeReleaseSpinLock( &gSpinLock, OldIrql );
				status = STATUS_SUCCESS;
				info = sizeof( ULONG );
				break;
			}
		case IOCTL_GET_REMOTE_INSTANCE:
			{
				DebugPrint(("--  IOCTL_GET_REMOTE_INSTANCE  ---\n"));
				if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG ) ){
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				if( !deviceExtension->bIsConnected ){
					DebugPrint(("remoteInstance:  %d\n", deviceExtension->remoteInstance ));
					status = STATUS_INVALID_DEVICE_REQUEST;
					break;
				}
				*( (PULONG)Irp->AssociatedIrp.SystemBuffer ) = deviceExtension->remoteInstance;
				status = STATUS_SUCCESS;
				info = sizeof( ULONG );
				break;
			}
		case IOCTL_DISCONNECT:
			DebugPrint(("---  IOCTL_DISCONNECT   ----\n"));
			status = Disconnect( deviceExtension );
			break;
		case IOCTL_SERIAL_SET_BAUD_RATE:
			{// to be continued
				// e.g
				DebugPrint(("--  IOCTL_SERIAL_SET_BAUD_RATE  ---\n"));
				if( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof( SERIAL_BAUD_RATE ) ){
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				deviceExtension->CurrentBaud = ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate;
				DebugPrint(("CurrentBaud :  %d     SetBaudRate:   %d\n", deviceExtension->CurrentBaud, ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate));
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_GET_BAUD_RATE:
			{
				PSERIAL_BAUD_RATE	Br = ( PSERIAL_BAUD_RATE )Irp->AssociatedIrp.SystemBuffer;
				DebugPrint(("--  IOCTL_SERIAL_GET_BAUD_RATE  ---\n"));
				if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( SERIAL_BAUD_RATE ) ){
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				DebugPrint(("Br->BaudRate :  %d\n", Br->BaudRate ));
				Br->BaudRate = deviceExtension->CurrentBaud;
				DebugPrint(("CurrentBaud:  %d    Br->BaudRate   %d\n", deviceExtension->CurrentBaud, Br->BaudRate ));
				info = sizeof( SERIAL_BAUD_RATE );
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_GET_MODEM_CONTROL:
			DebugPrint(("--  IOCTL_SERIAL_GET_MODEM_CONTROL   --\n"));
			break;
		case IOCTL_SERIAL_SET_MODEM_CONTROL:
			DebugPrint(("--  IOCTL_SERIAL_SET_MODEM_CONTROL   --\n"));
			break;
		case IOCTL_SERIAL_SET_FIFO_CONTROL:
			DebugPrint(("--  IOCTL_SERIAL_SET_FIFO_CONTROL   --\n"));
			break;
		case IOCTL_SERIAL_SET_LINE_CONTROL:
			{
				PSERIAL_LINE_CONTROL Lc;
				UCHAR LData;
				UCHAR LStop;
				UCHAR LParity;
				UCHAR Mask = 0xff;
				DebugPrint(("--  IOCTL_SERIAL_SET_LINE_CONTROL   --\n"));
				if( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_LINE_CONTROL)) {
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				Lc = ((PSERIAL_LINE_CONTROL)(Irp->AssociatedIrp.SystemBuffer));
				deviceExtension->LineControl.WordLength = Lc->WordLength;
				deviceExtension->LineControl.Parity		= Lc->Parity;
				deviceExtension->LineControl.StopBits	= Lc->StopBits;
				DebugPrint(("IOCTL_SERIAL_SET_LINE_CONTROL:  WordLength:  %d  Parity:  %d  StopBits  %d\n", Lc->WordLength, Lc->Parity, Lc->StopBits ));
				status = STATUS_SUCCESS;
				break;

			}
		case IOCTL_SERIAL_GET_LINE_CONTROL:
			{	//	need ControlLock
				PSERIAL_LINE_CONTROL Lc = (PSERIAL_LINE_CONTROL)Irp->AssociatedIrp.SystemBuffer;
				DebugPrint(("--  IOCTL_SERIAL_GET_LINE_CONTROL   --\n"));
				
				if (IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(SERIAL_LINE_CONTROL)) {
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				Lc->WordLength	= deviceExtension->LineControl.WordLength;
				Lc->Parity		= deviceExtension->LineControl.Parity;
				Lc->StopBits	= deviceExtension->LineControl.StopBits;

				DebugPrint(("IOCTL_SERIAL_GET_LINE_CONTROL:  WordLength:  %d  Parity:  %d  StopBits  %d\n", Lc->WordLength, Lc->Parity, Lc->StopBits ));
				info = sizeof(SERIAL_LINE_CONTROL);
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_SET_TIMEOUTS:
			{
				PSERIAL_TIMEOUTS NewTimeouts =
					((PSERIAL_TIMEOUTS)(Irp->AssociatedIrp.SystemBuffer));
				DebugPrint(("--  IOCTL_SERIAL_SET_TIMEOUTS   --\n"));
				if ( IrpStack->Parameters.DeviceIoControl.InputBufferLength <
					sizeof(SERIAL_TIMEOUTS)) {
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				if ((NewTimeouts->ReadIntervalTimeout == MAXULONG) &&
					(NewTimeouts->ReadTotalTimeoutMultiplier == MAXULONG) &&
					(NewTimeouts->ReadTotalTimeoutConstant == MAXULONG)) {
					status = STATUS_INVALID_PARAMETER;
					break;
				}
				deviceExtension->Timeouts.ReadIntervalTimeout = NewTimeouts->ReadIntervalTimeout;
				deviceExtension->Timeouts.ReadTotalTimeoutMultiplier =NewTimeouts->ReadTotalTimeoutMultiplier;
				deviceExtension->Timeouts.ReadTotalTimeoutConstant = NewTimeouts->ReadTotalTimeoutConstant;
				deviceExtension->Timeouts.WriteTotalTimeoutMultiplier =	NewTimeouts->WriteTotalTimeoutMultiplier;
				deviceExtension->Timeouts.WriteTotalTimeoutConstant = NewTimeouts->WriteTotalTimeoutConstant;
				DebugPrint(("Set_Timeouts\n"));
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_GET_TIMEOUTS:
			{
				if ( IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
					sizeof(SERIAL_TIMEOUTS)) {
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				DebugPrint(("--  IOCTL_SERIAL_GET_TIMEOUTS   --\n"));
				*((PSERIAL_TIMEOUTS)Irp->AssociatedIrp.SystemBuffer) = deviceExtension->Timeouts;
				//Irp->IoStatus.Information = sizeof(SERIAL_TIMEOUTS);	// modified by zcz dec 25, 2003
				info = sizeof( SERIAL_TIMEOUTS );
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_SET_CHARS:
			{
				PSERIAL_CHARS NewChars =
					((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
				DebugPrint(("--  IOCTL_SERIAL_SET_CHARS   --\n"));
				if ( IrpStack->Parameters.DeviceIoControl.InputBufferLength <
					sizeof(SERIAL_CHARS)) {
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}else if( NewChars->XonChar == NewChars->XoffChar ){
					status = STATUS_INVALID_PARAMETER;
					break;
				}else{
					deviceExtension->SpecialChars.EofChar	= NewChars->EofChar;
					deviceExtension->SpecialChars.ErrorChar	= NewChars->ErrorChar;
					deviceExtension->SpecialChars.BreakChar	= NewChars->BreakChar;
					deviceExtension->SpecialChars.EventChar	= NewChars->EventChar;
					deviceExtension->SpecialChars.XonChar	= NewChars->XonChar;
					deviceExtension->SpecialChars.XoffChar	= NewChars->XoffChar;
					DebugPrint(("SetChars:  %2x %2x %2x %2x %2x %2x\n", NewChars->EofChar, NewChars->ErrorChar, NewChars->BreakChar, NewChars->EventChar, NewChars->XonChar, NewChars->XoffChar ));
					status = STATUS_SUCCESS;
				}
				break;
			}
		case IOCTL_SERIAL_GET_CHARS:
			{	//	need ControlLock
				PSERIAL_CHARS NewChars = ((PSERIAL_CHARS)(Irp->AssociatedIrp.SystemBuffer));
				DebugPrint(("--  IOCTL_SERIAL_GET_CHARS   --\n"));

				if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength <
					sizeof(SERIAL_CHARS)) {
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer)->XonChar	= deviceExtension->SpecialChars.XonChar;
				((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer)->XoffChar	= deviceExtension->SpecialChars.XoffChar;
				((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer)->EofChar	= deviceExtension->SpecialChars.EofChar;
				((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer)->ErrorChar	= deviceExtension->SpecialChars.ErrorChar;
				((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer)->BreakChar	= deviceExtension->SpecialChars.BreakChar;
				((PSERIAL_CHARS)Irp->AssociatedIrp.SystemBuffer)->EventChar	= deviceExtension->SpecialChars.EventChar;
				DebugPrint(("GetChars:  %2x %2x %2x %2x %2x %2x\n", NewChars->EofChar, NewChars->ErrorChar, NewChars->BreakChar, NewChars->EventChar, NewChars->XonChar, NewChars->XoffChar ));
				info = sizeof( SERIAL_CHARS );
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_SET_DTR:
			{
				DebugPrint(("--  IOCTL_SERIAL_SET_DTR   --\n"));
				if (( deviceExtension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_HANDSHAKE){
					DebugPrint(("IOCTL_SERIAL_SET_DTR error: Current ControlHandShake 0x%x\n", deviceExtension->HandFlow.ControlHandShake ));
					status = STATUS_INVALID_PARAMETER;
				}
				info = 0;
				//*(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
				status = STATUS_SUCCESS;

				break;
			}
        case IOCTL_SERIAL_CLR_DTR:
			{
				DebugPrint(("--  IOCTL_SERIAL_CLR_DTR   --\n"));
				if (( deviceExtension->HandFlow.ControlHandShake & SERIAL_DTR_MASK) == SERIAL_DTR_HANDSHAKE){
					DebugPrint(("IOCTL_SERIAL_CLR_DTR error\n"));
					status = STATUS_INVALID_PARAMETER;
				}
				//*(PULONG)Irp->AssociatedIrp.SystemBuffer = 0;
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_RESET_DEVICE:
			DebugPrint(("--  IOCTL_SERIAL_RESET_DEVICE   --\n"));
			break;
		case IOCTL_SERIAL_SET_RTS:
			{
				DebugPrint(("--  IOCTL_SERIAL_SET_RTS   --\n"));
				if (( deviceExtension->HandFlow.FlowReplace & SERIAL_RTS_MASK) == SERIAL_RTS_HANDSHAKE ){
					DebugPrint(("IOCTL_SERIAL_SET_RTS error\n"));
					status = STATUS_INVALID_PARAMETER;
				}
				
				status = STATUS_SUCCESS;
				break;
			}
		case IOCTL_SERIAL_CLR_RTS:
			DebugPrint(("--  IOCTL_SERIAL_CLR_RTS   --\n"));
			break;
		case IOCTL_SERIAL_SET_XOFF:
			DebugPrint(("--  IOCTL_SERIAL_SET_XOFF   --\n"));
			break;
		case IOCTL_SERIAL_SET_XON:
			DebugPrint(("--  IOCTL_SERIAL_SET_XON   --\n"));
			break;
		case IOCTL_SERIAL_SET_BREAK_ON:
			DebugPrint(("--  IOCTL_SERIAL_SET_BREAK_ON   --\n"));
			break;
		case IOCTL_SERIAL_SET_BREAK_OFF:
			DebugPrint(("--  IOCTL_SERIAL_SET_BREAK_OFF   --\n"));
			break;
		case IOCTL_SERIAL_SET_QUEUE_SIZE:
			{
				PSERIAL_QUEUE_SIZE	Rs = ( PSERIAL_QUEUE_SIZE )Irp->AssociatedIrp.SystemBuffer;
				DebugPrint(("--  IOCTL_SERIAL_SET_QUEUE_SIZE   --\n"));
				if( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof(SERIAL_QUEUE_SIZE)) {
					status = STATUS_BUFFER_TOO_SMALL;
					break;
				}
				if( Rs->InSize > deviceExtension->BufferSize ){
					deviceExtension->BufferSize = Rs->InSize;
				}
				DebugPrint(("Buffersize :  %d\n", deviceExtension->BufferSize ));
				status = STATUS_SUCCESS;
				break;
#if 0
				try{
					IrpStack->Parameters.DeviceIoControl.Type3InputBuffer =
						ExAllocatePoolWithQuota( NonPagedPool, Rs->InSize );
				}except( EXCEPTION_EXECUTE_HANDLER ){
					IrpStack->Parameters.DeviceIoControl.Type3InputBuffer = NULL;
					status = GetExceptionCode();
				}
				if (!IrpStack->Parameters.DeviceIoControl.Type3InputBuffer) {
					break;
				}
				if( ( deviceExtension->BufferSize != 0 ) || ( deviceExtension->ReadBufferBase != NULL ) ){
					ExFreePool( deviceExtension->ReadBufferBase );
					deviceExtension->BufferSize = 0;
				}
				deviceExtension->ReadBufferBase = IrpStack->Parameters.DeviceIoControl.Type3InputBuffer;
#endif

			}
		case IOCTL_SERIAL_GET_WAIT_MASK:

⌨️ 快捷键说明

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