📄 ioctl.c
字号:
default:
return STATUS_INVALID_PARAMETER;
}
if ( InBufferSize < (sizeof(ULONG) + DataBufferSize) )
{
DebugPrint (("error in InBufferSize\n"));
return STATUS_INVALID_PARAMETER;
}
pde->PortNumber = *pIOBuffer++; // PortNumber in IOBuffer union
if (pde->PortMemoryType == 1)
{
// Address is in I/O space
switch (IoctlCode)
{
case IOCTL_WDT_WRITE_PORT_UCHAR:
WRITE_PORT_UCHAR(
(PUCHAR)((ULONG_PTR)pde->PortNumber),
*(PUCHAR)pIOBuffer );
break;
case IOCTL_WDT_WRITE_PORT_USHORT:
WRITE_PORT_USHORT(
(PUSHORT)((ULONG_PTR)pde->PortNumber),
*(PUSHORT)pIOBuffer );
break;
case IOCTL_WDT_WRITE_PORT_ULONG:
WRITE_PORT_ULONG(
(PULONG)((ULONG_PTR)pde->PortNumber),
*(PULONG)pIOBuffer );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else if (pde->PortMemoryType == 0)
{
// Address is in Memory space
switch (IoctlCode)
{
case IOCTL_WDT_WRITE_PORT_UCHAR:
WRITE_REGISTER_UCHAR(
(PUCHAR)((ULONG_PTR)pde->PortNumber),
*(PUCHAR)pIOBuffer );
break;
case IOCTL_WDT_WRITE_PORT_USHORT:
WRITE_REGISTER_USHORT(
(PUSHORT)((ULONG_PTR)pde->PortNumber),
*(PUSHORT)pIOBuffer );
break;
case IOCTL_WDT_WRITE_PORT_ULONG:
WRITE_REGISTER_ULONG(
(PULONG)((ULONG_PTR)pde->PortNumber),
*(PULONG)pIOBuffer );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else
{
return STATUS_UNSUCCESSFUL;
}
//
// Indicate # of bytes written,set Irp->IoStatus.Information
//
CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);
return STATUS_SUCCESS;
}
NTSTATUS
WDTIoctlGetHardwareID(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
)
{
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG OutBufferSize; // Max data that caller can accept.
ULONG DataBufferSize;
// Size of buffer for data to be sent to application
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DataBufferSize = sizeof(ULONG);
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;
if ( OutBufferSize < DataBufferSize )
{
return STATUS_INVALID_PARAMETER;
}
*pIOBuffer = (ULONG)pde->HardwareID;
// set Irp->IoStatus.Information
CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);
return STATUS_SUCCESS;
}
NTSTATUS
WDTIoctlGetPortIndex(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
)
{
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG OutBufferSize; // Max data that caller can accept.
ULONG DataBufferSize;
// Size of buffer for data to be sent to application
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DataBufferSize = sizeof(ULONG);
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;
if ( OutBufferSize < DataBufferSize )
{
return STATUS_INVALID_PARAMETER;
}
if(pde->HardwareID == 0x97)
{
*pIOBuffer = (ULONG)pde->ShortPortIndex;
}
if((pde->HardwareID == 0x52) || (pde->HardwareID ==0x82) ||
(pde->HardwareID == 0x88) || (pde->HardwareID == 0xA0))
{
*pIOBuffer = (ULONG)pde->PortIndex;
}
// set Irp->IoStatus.Information
CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);
return STATUS_SUCCESS;
}
NTSTATUS
WDTIoctlGetPortData(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
)
{
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG OutBufferSize; // Max data that caller can accept.
ULONG DataBufferSize;
// Size of buffer for data to be sent to application
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DataBufferSize = sizeof(ULONG);
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;
if ( OutBufferSize < DataBufferSize )
{
return STATUS_INVALID_PARAMETER;
}
if(pde->HardwareID == 0x97)
{
*pIOBuffer = (ULONG)pde->ShortPortData;
}
if((pde->HardwareID == 0x52) || (pde->HardwareID ==0x82) ||
(pde->HardwareID == 0x88) || (pde->HardwareID == 0xA0))
{
*pIOBuffer = (ULONG)pde->PortData;
}
// set Irp->IoStatus.Information
CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);
return STATUS_SUCCESS;
}
NTSTATUS
IRQSearchAuto(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
)
{
NTSTATUS status;
PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG OutBufferSize; // Max data that caller can accept.
ULONG DataBufferSize;
ULONG irq=7;
// Size of buffer for data to be sent to application
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DataBufferSize = sizeof(ULONG);
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;
if ( OutBufferSize < DataBufferSize )
{
return STATUS_INVALID_PARAMETER;
}
// Search IRQ automatic.
for(irq=3;irq<16;irq++)
{
if(irq==8 || irq==13)
{
continue;
}
pde->Irq = irq;
pde->Irql = (KIRQL)irq;
// Claim resources
status = ClaimResources(fdo);
if(!NT_SUCCESS(status))
{
DebugPrint(("Could not ClaimResources\n"));
*pIOBuffer = IRQ_SEARCH_AUTO_ERROR;
continue;
}
else
{
break;
}
}
if(irq > 15)
{
*pIOBuffer = IRQ_SEARCH_AUTO_ERROR;
}
else
{
// Resource conflict not found
pde->ResourcesClaimed = TRUE;
// Translate and map resources
status = TranslateAndMapResources(fdo);
if(NT_SUCCESS(status))
{
// Disconnect from interrupt
if( pde->ConnectedToInterrupt)
{
DebugPrint(("Disconnecting from interrupt\n"));
IoDisconnectInterrupt( pde->InterruptObject);
pde->ConnectedToInterrupt = FALSE;
}
DisableInterrupt(pde);
// connect to interrupt again.
status=IoConnectInterrupt(&pde->InterruptObject,(PKSERVICE_ROUTINE)OnInterrupt,
(PVOID)pde,NULL,pde->Vector,pde->Irql,pde->Irql,pde->Mode,FALSE,
pde->Affinity,FALSE);
if(!NT_SUCCESS(status))
{
DebugPrint(("connect interrupt error!\n"));
*pIOBuffer = IRQ_SEARCH_AUTO_ERROR;
pde->ConnectedToInterrupt = FALSE;
}
else
{
DebugPrint(("connect interrupt ok!\n"));
*pIOBuffer = irq;
pde->ConnectedToInterrupt = TRUE;
EnableInterrupt(pde);
}
}
else
{
DebugPrint(("Could not translate resources\n"));
UnclaimResources(fdo);
pde->ResourcesClaimed = FALSE;
}
}
// set Irp->IoStatus.Information
CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);
return STATUS_SUCCESS;
}
NTSTATUS
IRQUserSet(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as an array of longs).
ULONG InBufferSize; // Amount of data avail. from caller.
ULONG OutBufferSize; // Max data that caller can accept.
ULONG DataBufferSize;
// Size of buffer containing data from application
InBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
// Size of buffer for data to be sent to application
OutBufferSize = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
DataBufferSize = sizeof(ULONG);
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;
if ( OutBufferSize < DataBufferSize )
{
return STATUS_INVALID_PARAMETER;
}
pde->Irq = *pIOBuffer;
pde->Irql = (KIRQL)*pIOBuffer;
// Claim resources
status = ClaimResources(fdo);
if(NT_SUCCESS(status))
{
// Resource conflict not found
pde->ResourcesClaimed = TRUE;
// Translate and map resources
status = TranslateAndMapResources(fdo);
if(NT_SUCCESS(status))
{
// Disconnect from interrupt
if( pde->ConnectedToInterrupt)
{
DebugPrint(("Disconnecting from interrupt\n"));
IoDisconnectInterrupt( pde->InterruptObject);
pde->ConnectedToInterrupt = FALSE;
}
DisableInterrupt(pde);
// connect to interrupt again.
status=IoConnectInterrupt(&pde->InterruptObject,(PKSERVICE_ROUTINE)OnInterrupt,
(PVOID)pde,NULL,pde->Vector,pde->Irql,pde->Irql,pde->Mode,FALSE,
pde->Affinity,FALSE);
if(!NT_SUCCESS(status))
{
DebugPrint(("connect interrupt error!\n"));
*pIOBuffer = IRQ_INVALID;
pde->ConnectedToInterrupt = FALSE;
}
else
{
*pIOBuffer = IRQ_VALID;
pde->ConnectedToInterrupt = TRUE;
EnableInterrupt(pde);
}
}
else
{
DebugPrint(("Could not translate resources\n"));
UnclaimResources(fdo);
pde->ResourcesClaimed = FALSE;
}
}
else
{
*pIOBuffer = IRQ_INVALID;
DebugPrint(("Could not ClaimResources\n"));
}
// set Irp->IoStatus.Information
CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);
return STATUS_SUCCESS;
}
// ClaimResources: Ask kernel to give is the resources we want
NTSTATUS ClaimResources( IN PDEVICE_OBJECT fdo)
{
NTSTATUS status = STATUS_SUCCESS;
PDEVICE_EXTENSION pde;
ULONG ListSize;
PCM_RESOURCE_LIST ResourceList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR resource;
PCM_FULL_RESOURCE_DESCRIPTOR FullRD;
BOOLEAN ConflictDetected;
// Get resource count: either 1 (IOport) or 2 (IOport&IRQ)
ULONG PartialResourceCount = 1;
//PartialResourceCount++;
pde = fdo->DeviceExtension;
// Get size of required CM_RESOURCE_LIST
ListSize = FIELD_OFFSET( CM_RESOURCE_LIST, List[0]);
ListSize += sizeof( CM_FULL_RESOURCE_DESCRIPTOR) +
((PartialResourceCount-1) * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR));
// Allocate CM_RESOURCE_LIST
ResourceList = (PCM_RESOURCE_LIST)ExAllocatePool( PagedPool, ListSize);
if( ResourceList==NULL)
{
DebugPrint(("Cannot allocate memory for ResourceList"));
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( ResourceList, ListSize);
// Only one Full Resource Descriptor needed, for ISA
ResourceList->Count = 1;
// Initialise Full Resource Descriptor
FullRD = &ResourceList->List[0];
FullRD->InterfaceType = Isa;
FullRD->BusNumber = 0;
FullRD->PartialResourceList.Count = PartialResourceCount;
// Initialise Partial Resource Descriptor for Interrupt
resource = &FullRD->PartialResourceList.PartialDescriptors[0];
//resource++;
resource->Type = CmResourceTypeInterrupt;
resource->ShareDisposition = CmResourceShareDriverExclusive;
pde->Mode = Latched;
//resource->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
resource->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
resource->u.Interrupt.Level = pde->Irql;
resource->u.Interrupt.Vector = pde->Irql;
resource->u.Interrupt.Affinity = 1;
// Ask for resources for the driver
//DebugPrint(("Allocating %d resources"),PartialResourceCount);
//DebugPrint(("fdo->DriverObject %x"),fdo->DriverObject);
status = IoReportResourceUsage( NULL,
fdo->DriverObject, ResourceList, ListSize, // Driver resources
NULL, NULL, 0, // Device resources
FALSE, &ConflictDetected);
// Cope (or override) if resource conflict found
if( ConflictDetected)
{
DebugPrint(("Conflict Detected\n"));
// NT4 returns STATUS_SUCCESS; W2000 returns !NT_SUCCESS
// Free allocated memory
ExFreePool(ResourceList);
//return STATUS_SUCCESS;
}
return status;
}
// UnclaimResources: Release our resources back to the system
void UnclaimResources( IN PDEVICE_OBJECT fdo)
{
//DebugPrint(("Freeing all allocated resources\n"));
BOOLEAN ConflictDetected;
CM_RESOURCE_LIST ResourceList;
// Release all driver's resources by declaring we have none.
ResourceList.Count = 0;
IoReportResourceUsage( NULL,
fdo->DriverObject, &ResourceList, sizeof(ResourceList), // Driver resources
NULL, NULL, 0, // Device resources
FALSE, &ConflictDetected);
// ignore return result
}
// TranslateAndMapResources: Translate and map our resources
NTSTATUS TranslateAndMapResources( IN PDEVICE_OBJECT fdo)
{
PDEVICE_EXTENSION pde = (PDEVICE_EXTENSION)fdo->DeviceExtension;
// Translate IRQ values
ULONG irq = pde->Irql;
pde->Vector = HalGetInterruptVector( Isa, 0, irq, irq, &pde->Irql, &pde->Affinity);
if( pde->Vector==0)
{
//DebugPrint(("Create filename: Could not get interrupt vector for IRQ %x\n"), irq);
return STATUS_INVALID_PARAMETER;
}
/*DebugPrint(("Interrupt vector %x IRQL %x Affinity %x Mode %x\n"),
pde->Vector, pde->Irql, pde->Affinity, pde->Mode);*/
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -