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

📄 ioctl.c

📁 好东东
💻 C
📖 第 1 页 / 共 2 页
字号:
/*++

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 <ntddk.h>
#include <initguid.h>
#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;

⌨️ 快捷键说明

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