📄 ioctl.c
字号:
#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 + -