📄 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 <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 + -