www.pudn.com > VSer.rar > ioctl.c


/*++ 
 
Copyright (c) 2005  Changzhi Zhou All Rights Reserved 
 
Module Name: 
 
    ioctl.c 
 
Abstract: 
 
    This module handles Device I/O control requests. 
 
Environment: 
 
    Kernel mode 
 
Revision History: 
	Changzhi Zhou Dec 20  2004 
 
--*/ 
#include  
#include  
#include "main.h" 
#include "..\inc\wdmioctl.h" 
 
 
NTSTATUS SampleIoControl(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 
/*++ 
 
Routine Description: 
 
    The evice I/O control handle. 
	All handle relevant to Serial Port are deal with here. 
 
Arguments: 
 
   DeviceObject - pointer to a device object. 
 
   Irp - pointer to an I/O Request Packet. 
 
Return Value: 
 
      NT status code 
 
--*/ 
{ 
	PIO_STACK_LOCATION	IrpStack; 
	ULONG				ControlCode; 
	ULONG				InputLength,OutputLength; 
	NTSTATUS			status; 
	ULONG				info; 
	PUCHAR				Buffer; 
	PDEVICE_EXTENSION	deviceExtension; 
 
	KIRQL				oldIrql; 
	 
	PAGED_CODE(); 
 
	deviceExtension = DeviceObject->DeviceExtension; 
	if ( deviceExtension->DevicePnPState != Working) 
	{ 
		status = STATUS_INVALID_DEVICE_STATE; 
		return CompleteRequest(Irp, status, 0); 
    } 
	IrpStack = IoGetCurrentIrpStackLocation(Irp); 
	DebugPrint(("SampleIoControl: IrpStack 0x%08x\n", IrpStack )); 
	 
	ControlCode = IrpStack->Parameters.DeviceIoControl.IoControlCode; 
	InputLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength; 
	OutputLength= IrpStack->Parameters.DeviceIoControl.OutputBufferLength; 
	info = 0; 
	status = STATUS_SUCCESS; 
	SampleIoIncrement ( deviceExtension ); 
	switch(ControlCode) 
	{ 
		case IOCTL_CREATE_DOS_NAME: 
			// create DosName, such as COM5. 
			// 
			status = CreateDosName( DeviceObject, Irp ); 
			break; 
		case IOCTL_DELETE_DOS_NAME: 
			status = SerialUndoExternalNaming( deviceExtension ); 
			break; 
		case IOCTL_SET_REMOTE_INFO: 
			if ( InputLength < ( sizeof ( ULONG ) * 2 ) ) 
			{ 
				status = STATUS_BUFFER_TOO_SMALL; 
				break; 
			} 
			deviceExtension->RemoteAddress	= *((ULONG *)Irp->AssociatedIrp.SystemBuffer); 
			deviceExtension->RemotePort		= (USHORT)*( ((ULONG *)Irp->AssociatedIrp.SystemBuffer) + 1); 
			break; 
		case IOCTL_QUERY_NETWORK_INFORMATION: 
			if ( ( InputLength < sizeof( ULONG ) ) || ( OutputLength < sizeof ( ULONG ) ) ) 
			{ 
				status = STATUS_BUFFER_TOO_SMALL; 
				break; 
			} 
			status = TDIQueryNetworkInformation ( DeviceObject, Irp ); 
			info = Irp->IoStatus.Information; 
			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 )); 
				KeAcquireSpinLock ( &deviceExtension->ThreadSpinLock, &oldIrql ); 
				// 
				// Set wait mask means that we will wait NEW mask. 
				// So we must complete WaitOnMaskIrp and PendingReadIrp 
				// 
				if( deviceExtension->WaitOnMaskIrp ){ 
					// 取消上一次的WAIT_ON_MASK Irp 
					*((ULONG *)deviceExtension->WaitOnMaskIrp->AssociatedIrp.SystemBuffer) = 0; 
					CompleteRequest( deviceExtension->WaitOnMaskIrp, STATUS_SUCCESS, sizeof( ULONG )); 
					SampleIoDecrement( deviceExtension ); 
					deviceExtension->WaitOnMaskIrp = NULL; 
				} 
				deviceExtension->WaitMask = NewMask; 
				KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql ); 
				status = STATUS_SUCCESS; 
				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; 
				} 
				KeAcquireSpinLock ( &deviceExtension->ThreadSpinLock, &oldIrql ); 
				if( deviceExtension->WaitOnMaskIrp ){ 
					DebugPrint(("There is a wait-on-mask request already pending\n")); 
					status = STATUS_INVALID_PARAMETER; 
					KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql ); 
					break; 
				} 
				// Mark the Irp here. Then we check COMMSTATUS at intervals in another thread 
				// to determine whether or not to complete this Irp. 
				// 
				DebugPrint(("MarkIrpPending\n")); 
				IoMarkIrpPending( Irp ); 
				ASSERT( deviceExtension->WaitOnMaskIrp == NULL ); 
				deviceExtension->WaitOnMaskIrp = Irp; 
				KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql ); 
 
				status = STATUS_PENDING; 
				return status; 
			} 
		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)); 
				KeAcquireSpinLock( &deviceExtension->ThreadSpinLock, &oldIrql ); 
				if( ( PurgeMask & SERIAL_PURGE_RXABORT ) || ( PurgeMask & SERIAL_PURGE_RXCLEAR ) ){ 
					// purge Rx buffer and complete PendingReadIrp 
					DebugPrint(( "SERIAL_PURGE_RXABORT\n" )); 
					deviceExtension->SerialStatus.AmountInInQueue = 0; 
					deviceExtension->lpRx	= deviceExtension->RxBuffer; 
					deviceExtension->lpRead	= deviceExtension->RxBuffer; 
				} 
				if ( ( PurgeMask & SERIAL_PURGE_TXABORT ) || ( PurgeMask & SERIAL_PURGE_TXCLEAR ) ){ 
					// purge Tx buffer 
					DebugPrint(( "SERIAL_PURGE_TXABORT\n" )); 
				} 
				KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql ); 
				info = sizeof( ULONG ); 
				status = STATUS_SUCCESS; 
				break; 
			} 
 
		case IOCTL_SERIAL_GET_COMMSTATUS: 
			{ 
				DebugPrint(("--  IOCTL_SERIAL_GET_COMMSTATUS   --\n")); 
				if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( SERIAL_STATUS ) ){ 
					status = STATUS_BUFFER_TOO_SMALL; 
					break; 
				} 
				KeAcquireSpinLock ( &deviceExtension->ThreadSpinLock, &oldIrql ); 
				RtlCopyMemory( Irp->AssociatedIrp.SystemBuffer, &deviceExtension->SerialStatus, sizeof ( SERIAL_STATUS ) ); 
				DebugPrint(("InQueue = %d  OutQueue = %d\n", deviceExtension->SerialStatus.AmountInInQueue, deviceExtension->SerialStatus.AmountInOutQueue )); 
				KeReleaseSpinLock ( &deviceExtension->ThreadSpinLock, oldIrql ); 
				info = sizeof ( SERIAL_STATUS ); 
				status = STATUS_SUCCESS; 
				break; 
			} 
		case IOCTL_SERIAL_GET_WAIT_MASK: 
			{ 
				DebugPrint(("--  IOCTL_SERIAL_GET_WAIT_MASK   --\n")); 
				if( IrpStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof( ULONG ) ){ 
					status = STATUS_BUFFER_TOO_SMALL; 
					break; 
				} 
				*(PULONG)Irp->AssociatedIrp.SystemBuffer = deviceExtension->WaitMask; 
				info = sizeof ( ULONG ); 
				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; 
				} 
				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_SET_BAUD_RATE: 
			DebugPrint(("--  IOCTL_SERIAL_SET_BAUD_RATE  ---\n")); 
			if( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof( SERIAL_BAUD_RATE ) ){ 
				status = STATUS_BUFFER_TOO_SMALL; 
				break; 
			} 
			DebugPrint(("CurrentBaud :  %d     SetBaudRate:   %d\n", deviceExtension->CurrentBaud, ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate)); 
			deviceExtension->CurrentBaud = ((PSERIAL_BAUD_RATE)(Irp->AssociatedIrp.SystemBuffer))->BaudRate; 
			status = STATUS_SUCCESS; 
			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: 
			{ 
				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; 
				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( UCHAR ) * 6 ) ) { 
					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: 
			{ 
				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_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_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; 
			} 
		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_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_IMMEDIATE_CHAR: 
			DebugPrint(("--  IOCTL_SERIAL_IMMEDIATE_CHAR   --\n")); 
			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; 
		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_GET_MODEMSTATUS: 
			DebugPrint(("--  IOCTL_SERIAL_GET_MODEMSTATUS   --\n")); 
			break; 
		case IOCTL_SERIAL_GET_DTRRTS: 
			DebugPrint(("--  IOCTL_SERIAL_GET_DTRRTS   --\n")); 
			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_RESET_DEVICE: 
			DebugPrint(("--  IOCTL_SERIAL_RESET_DEVICE   --\n")); 
			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; 
		default: 
			status=STATUS_INVALID_DEVICE_REQUEST; 
			break; 
	} 
	status = CompleteRequest( Irp, status, info ); 
 
    SampleIoDecrement( deviceExtension ); 
 
	return status; 
} 
NTSTATUS CreateDosName( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) 
/*++ 
 
Routine Description: 
 
	Create Dosname. 
 
Arguments: 
 
   DeviceObject - pointer to a device object. 
 
   Irp - pointer to an I/O Request Packet. 
 
Return Value: 
 
      NT status code 
 
--*/ 
{ 
	LONG ComX; 
	PIO_STACK_LOCATION	IrpStack; 
	NTSTATUS			status; 
	PDEVICE_EXTENSION	deviceExtension; 
	 
	deviceExtension = DeviceObject->DeviceExtension; 
 
	DebugPrint(("-----  IOCTL_INIT_SETTING   ----\n")); 
	IrpStack = IoGetCurrentIrpStackLocation(Irp); 
 
	if( IrpStack->Parameters.DeviceIoControl.InputBufferLength < sizeof( LONG ) ){ 
		status = STATUS_BUFFER_TOO_SMALL; 
		return status; 
	} 
	ComX = *((PLONG)Irp->AssociatedIrp.SystemBuffer); 
	// 此处注意Dos名不要重复 
	if( ( ComX > 255 ) || ( ComX < 1 ) ){ 
		status = STATUS_INVALID_PARAMETER; 
		return status; 
	} 
	if( !deviceExtension->CreatedSymbolicLink ){ 
		status = SerialDoExternalNaming( deviceExtension, ComX); 
	} 
	return status; 
}