📄 ioctl.c
字号:
/*++
Copyright (c) 2006 EVOC, All Rights Reserved
Module Name:
Ioctl.c
Abstract: WDT ioctl control code dispatch.
Environment:
Kernel mode
Author: mz.yang may, 2006
Revision History:
--*/
//#include <ntddk.h>
#include "Driver.h"
NTSTATUS
WDTIoctlReadPort(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode );
NTSTATUS
WDTIoctlWritePort(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode
);
NTSTATUS
WDTIoctlGetHardwareID(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
);
NTSTATUS
WDTIoctlGetPortIndex(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
);
NTSTATUS
WDTIoctlGetPortData(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
);
NTSTATUS
IRQSearchAuto(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
);
NTSTATUS
IRQUserSet(
IN PDEVICE_OBJECT fdo,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack
);
NTSTATUS
ClaimResources( IN PDEVICE_OBJECT fdo );
NTSTATUS
TranslateAndMapResources( IN PDEVICE_OBJECT fdo);
NTSTATUS
DRV_Open(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
/*++
Routine Description:
When application called api "CreateFile",system will called this routine.
Arguments:
fdo - pointer to a function device object.
Irp - pointer to an I/O Request Packet.
Return Value:
TRUE :called succeed.
FALSE :called failed.
--*/
{
NTSTATUS status=STATUS_SUCCESS;
PDEVICE_EXTENSION pde=fdo->DeviceExtension;
if(pde->opencount > 0)
{
DebugPrint (("device already opened by other user..\n"));
return STATUS_UNSUCCESSFUL;
}
else
{
pde->opencount++;
status=STATUS_SUCCESS;
DebugPrint (("device opened..\n"));
}
// create kernel mode event,shared with application use the same event name.
if(!pde->EventCreated)
{
RtlInitUnicodeString(&pde->EventName,L"\\BaseNamedObjects\\WDTInterruptEvent");
pde->pEvent = IoCreateNotificationEvent(&pde->EventName,&pde->hEvent);
if(!pde->pEvent)
{
DebugPrint(("creat event error!\n"));
return STATUS_UNSUCCESSFUL;
}
KeClearEvent(pde->pEvent);
pde->EventCreated = TRUE;
DebugPrint(("create event ok!\n"));
}
return CompleteIoReq(Irp,status,0);
}
NTSTATUS
DRV_Close(IN PDEVICE_OBJECT fdo,IN PIRP Irp)
/*++
Routine Description:
When application called api "CloseHandle",system will called this routine.
Arguments:
fdo - pointer to a function device object.
Irp - pointer to an I/O Request Packet.
Return Value:
TRUE :called succeed.
FALSE :called failed.
--*/
{
PIO_STACK_LOCATION stack;
PDEVICE_EXTENSION pde=fdo->DeviceExtension;
if(pde->opencount>0)
pde->opencount--;
if(pde->EventCreated)
{
ZwClose(pde->hEvent);
pde->EventCreated = FALSE;
}
DebugPrint (("device closed..\n"));
return CompleteIoReq(Irp,STATUS_SUCCESS,0);
}
NTSTATUS
DRV_IoCtrl(IN PDEVICE_OBJECT fdo, IN PIRP Irp)
/*++
Routine Description:
This routine is the dispatch handler for the user IOCTL. It is responsible
for processing the IRPs.
Arguments:
fdo - Pointer to device object.
Irp - Pointer to the current IRP.
Return Value:
STATUS_SUCCESS if the IRP was processed successfully, otherwise an error
indicating the reason for failure.
--*/
{
NTSTATUS status;
PIO_STACK_LOCATION IrpStack;
PDEVICE_EXTENSION pde = fdo->DeviceExtension;
ULONG IoctlCode;
DebugPrint(("Enter IOCTRL process\n"));
if(!pde->started)
return CompleteIoReq( Irp, STATUS_DEVICE_NOT_CONNECTED, 0);
status = IoAcquireRemoveLock(&pde->RemoveLock, Irp);
if (!NT_SUCCESS(status))
{
DebugPrint(("Acquire RemoveLock failed\n" ));
CompleteIoReq( Irp, status, 0 );
return status;
}
IrpStack=IoGetCurrentIrpStackLocation(Irp);
IoctlCode=IrpStack->Parameters.DeviceIoControl.IoControlCode;
switch(IoctlCode)
{
case IOCTL_WDT_READ_PORT_UCHAR:
case IOCTL_WDT_READ_PORT_USHORT:
case IOCTL_WDT_READ_PORT_ULONG:
status = WDTIoctlReadPort(
pde,
Irp,
IrpStack,
IoctlCode
);
break;
case IOCTL_WDT_WRITE_PORT_UCHAR:
case IOCTL_WDT_WRITE_PORT_USHORT:
case IOCTL_WDT_WRITE_PORT_ULONG:
status = WDTIoctlWritePort(
pde,
Irp,
IrpStack,
IoctlCode
);
break;
case IOCTL_WDT_GET_HARDWARE_ID:
status = WDTIoctlGetHardwareID(pde,
Irp,
IrpStack);
break;
case IOCTL_WDT_GET_PORT_INDEX:
status = WDTIoctlGetPortIndex(pde,
Irp,
IrpStack);
break;
case IOCTL_WDT_GET_PORT_DATA:
status = WDTIoctlGetPortData(pde,
Irp,
IrpStack);
break;
case IOCTL_WDT_IRQ_SEARCH_AUTO:
status = IRQSearchAuto( fdo,
Irp,
IrpStack
);
break;
case IOCTL_WDT_IRQ_USER_SET:
status = IRQUserSet(fdo,
Irp,
IrpStack
);
break;
default:
status = STATUS_INVALID_PARAMETER;
CompleteIoReq( Irp, status, 0 );
break;
}
IoReleaseRemoveLock(&pde->RemoveLock, Irp);
return STATUS_SUCCESS;
}
NTSTATUS
WDTIoctlReadPort(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode )
/*++
Routine Description:
This routine processes the IOCTLs which read from the ports.
Arguments:
pde - our device extention
Irp - IO request packet
IrpStack - The current stack location
IoctlCode - The ioctl code from the IRP
Return Value:
STATUS_SUCCESS -- OK
STATUS_INVALID_PARAMETER -- The buffer sent to the driver
was too small to contain the
port, or the buffer which
would be sent back to the driver
was not a multiple of the data size.
STATUS_ACCESS_VIOLATION -- An illegal port number was given.
--*/
{
// 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;
PAGED_CODE();
// 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;
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG)Irp->AssociatedIrp.SystemBuffer;
// Check to ensure input buffer is big enough to hold a port number and
// the output buffer is at least as big as the port data width.
//
switch (IoctlCode)
{
case IOCTL_WDT_READ_PORT_UCHAR:
DataBufferSize = sizeof(UCHAR);
break;
case IOCTL_WDT_READ_PORT_USHORT:
DataBufferSize = sizeof(USHORT);
break;
case IOCTL_WDT_READ_PORT_ULONG:
DataBufferSize = sizeof(ULONG);
break;
default:
return STATUS_INVALID_PARAMETER;
}
if ( InBufferSize != sizeof(ULONG) || OutBufferSize < DataBufferSize )
{
return STATUS_INVALID_PARAMETER;
}
// Buffers are big enough.
pde->PortNumber = *pIOBuffer; // Get the I/O port number from the buffer.
if (pde->PortMemoryType == 1)
{
// Address is in I/O space
switch (IoctlCode)
{
case IOCTL_WDT_READ_PORT_UCHAR:
*(PUCHAR)pIOBuffer = READ_PORT_UCHAR(
(PUCHAR)((ULONG_PTR)pde->PortNumber) );
break;
case IOCTL_WDT_READ_PORT_USHORT:
*(PUSHORT)pIOBuffer = READ_PORT_USHORT(
(PUSHORT)((ULONG_PTR)pde->PortNumber) );
break;
case IOCTL_WDT_READ_PORT_ULONG:
*(PULONG)pIOBuffer = READ_PORT_ULONG(
(PULONG)((ULONG_PTR)pde->PortNumber) );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else if (pde->PortMemoryType == 0)
{
// Address is in Memory space
switch (IoctlCode)
{
case IOCTL_WDT_READ_PORT_UCHAR:
*(PUCHAR)pIOBuffer = READ_REGISTER_UCHAR(
(PUCHAR)((ULONG_PTR)pde->PortNumber) );
break;
case IOCTL_WDT_READ_PORT_USHORT:
*(PUSHORT)pIOBuffer = READ_REGISTER_USHORT(
(PUSHORT)((ULONG_PTR)pde->PortNumber) );
break;
case IOCTL_WDT_READ_PORT_ULONG:
*(PULONG)pIOBuffer = READ_REGISTER_ULONG(
(PULONG)((ULONG_PTR)pde->PortNumber) );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else
{
return STATUS_UNSUCCESSFUL;
}
//
// Indicate # of bytes read,set Irp->IoStatus.Information
//
CompleteIoReq(Irp,STATUS_SUCCESS,DataBufferSize);
return STATUS_SUCCESS;
}
NTSTATUS
WDTIoctlWritePort(
IN PDEVICE_EXTENSION pde,
IN PIRP Irp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode
)
/*++
Routine Description:
This routine processes the IOCTLs which write to the ports.
Arguments:
pde - our device extention
Irp - IO request packet
IrpStack - The current stack location
IoctlCode - The ioctl code from the IRP
Return Value:
STATUS_SUCCESS -- OK
STATUS_INVALID_PARAMETER -- The buffer sent to the driver
was too small to contain the
port, or the buffer which
would be sent back to the driver
was not a multiple of the data size.
STATUS_ACCESS_VIOLATION -- An illegal port number was given.
--*/
{
// NOTE: Use METHOD_BUFFERED ioctls.
PULONG pIOBuffer; // Pointer to transfer buffer
// (treated as array of longs).
ULONG InBufferSize; // Amount of data avail. from caller.
ULONG DataBufferSize;
PAGED_CODE();
// Size of buffer containing data from application
InBufferSize = IrpStack->Parameters.DeviceIoControl.InputBufferLength;
// NT copies inbuf here before entry and copies this to outbuf after return,
// for METHOD_BUFFERED IOCTL's.
pIOBuffer = (PULONG) Irp->AssociatedIrp.SystemBuffer;
// Check to ensure input buffer is big enough to hold a port number as well
// as the data to write.
//
// The relative port # is a ULONG, and the data is the type appropriate to
// the IOCTL.
//
DebugPrint (("Entered WdgIoctlWritePort\n"));
switch (IoctlCode)
{
case IOCTL_WDT_WRITE_PORT_UCHAR:
DataBufferSize = sizeof(UCHAR);
break;
case IOCTL_WDT_WRITE_PORT_USHORT:
DataBufferSize = sizeof(USHORT);
break;
case IOCTL_WDT_WRITE_PORT_ULONG:
DataBufferSize = sizeof(ULONG);
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -