📄 genport.c.bak
字号:
//
pIrp->IoStatus.Status = Status = STATUS_DEVICE_NOT_READY;
IoCompleteRequest(pIrp, IO_NO_INCREMENT );
IoReleaseRemoveLock(&pLDI->RemoveLock, NULL);
return Status;
}
pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
// Dispatch based on major fcn code.
switch (pIrpStack->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
// We don't need any special processing on open/close so we'll
// just return success.
Status = STATUS_SUCCESS;
break;
case IRP_MJ_DEVICE_CONTROL:
// Dispatch on IOCTL
switch (pIrpStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_GPD_READ_PORT_UCHAR:
case IOCTL_GPD_READ_PORT_USHORT:
case IOCTL_GPD_READ_PORT_ULONG:
Status = GpdIoctlReadPort(
pLDI,
pIrp,
pIrpStack,
pIrpStack->Parameters.DeviceIoControl.IoControlCode
);
break;
case IOCTL_GPD_WRITE_PORT_UCHAR:
case IOCTL_GPD_WRITE_PORT_USHORT:
case IOCTL_GPD_WRITE_PORT_ULONG:
Status = GpdIoctlWritePort(
pLDI,
pIrp,
pIrpStack,
pIrpStack->Parameters.DeviceIoControl.IoControlCode
);
break;
default:
Status = STATUS_INVALID_PARAMETER;
}
break;
default:
Status = STATUS_NOT_IMPLEMENTED;
break;
}
// We're done with I/O request. Record the status of the I/O action.
pIrp->IoStatus.Status = Status;
// Don't boost priority when returning since this took little time.
IoCompleteRequest(pIrp, IO_NO_INCREMENT );
IoReleaseRemoveLock(&pLDI->RemoveLock, NULL);
return Status;
}
NTSTATUS
GpdIoctlReadPort(
IN PLOCAL_DEVICE_INFO pLDI,
IN PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode )
/*++
Routine Description:
This routine processes the IOCTLs which read from the ports.
Arguments:
pLDI - our local device data
pIrp - 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 nPort; // Port number to read
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)pIrp->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_GPD_READ_PORT_UCHAR:
DataBufferSize = sizeof(UCHAR);
break;
case IOCTL_GPD_READ_PORT_USHORT:
DataBufferSize = sizeof(USHORT);
break;
case IOCTL_GPD_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.
nPort = *pIOBuffer; // Get the I/O port number from the buffer.
if (nPort >= pLDI->PortCount ||
(nPort + DataBufferSize) > pLDI->PortCount ||
(((ULONG_PTR)pLDI->PortBase + nPort) & (DataBufferSize - 1)) != 0)
{
return STATUS_ACCESS_VIOLATION; // It was not legal.
}
if (pLDI->PortMemoryType == 1)
{
// Address is in I/O space
switch (IoctlCode)
{
case IOCTL_GPD_READ_PORT_UCHAR:
*(PUCHAR)pIOBuffer = READ_PORT_UCHAR(
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
case IOCTL_GPD_READ_PORT_USHORT:
*(PUSHORT)pIOBuffer = READ_PORT_USHORT(
(PUSHORT)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
case IOCTL_GPD_READ_PORT_ULONG:
*(PULONG)pIOBuffer = READ_PORT_ULONG(
(PULONG)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else if (pLDI->PortMemoryType == 0)
{
// Address is in Memory space
switch (IoctlCode)
{
case IOCTL_GPD_READ_PORT_UCHAR:
*(PUCHAR)pIOBuffer = READ_REGISTER_UCHAR(
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
case IOCTL_GPD_READ_PORT_USHORT:
*(PUSHORT)pIOBuffer = READ_REGISTER_USHORT(
(PUSHORT)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
case IOCTL_GPD_READ_PORT_ULONG:
*(PULONG)pIOBuffer = READ_REGISTER_ULONG(
(PULONG)((ULONG_PTR)pLDI->PortBase + nPort) );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else
{
return STATUS_UNSUCCESSFUL;
}
//
// Indicate # of bytes read
//
pIrp->IoStatus.Information = DataBufferSize;
return STATUS_SUCCESS;
}
NTSTATUS
GpdIoctlWritePort(
IN PLOCAL_DEVICE_INFO pLDI,
IN PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack,
IN ULONG IoctlCode
)
/*++
Routine Description:
This routine processes the IOCTLs which write to the ports.
Arguments:
pLDI - our local device data
pIrp - 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 nPort; // Port number to read or write.
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) pIrp->AssociatedIrp.SystemBuffer;
pIrp->IoStatus.Information = 0;
// 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.
//
switch (IoctlCode)
{
case IOCTL_GPD_WRITE_PORT_UCHAR:
DataBufferSize = sizeof(UCHAR);
break;
case IOCTL_GPD_WRITE_PORT_USHORT:
DataBufferSize = sizeof(USHORT);
break;
case IOCTL_GPD_WRITE_PORT_ULONG:
DataBufferSize = sizeof(ULONG);
break;
default:
return STATUS_INVALID_PARAMETER;
}
if ( InBufferSize < (sizeof(ULONG) + DataBufferSize) )
{
return STATUS_INVALID_PARAMETER;
}
nPort = *pIOBuffer++;
if (nPort >= pLDI->PortCount ||
(nPort + DataBufferSize) > pLDI->PortCount ||
(((ULONG_PTR)pLDI->PortBase + nPort) & (DataBufferSize - 1)) != 0)
{
return STATUS_ACCESS_VIOLATION; // Illegal port number
}
if (pLDI->PortMemoryType == 1)
{
// Address is in I/O space
switch (IoctlCode)
{
case IOCTL_GPD_WRITE_PORT_UCHAR:
WRITE_PORT_UCHAR(
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort),
*(PUCHAR)pIOBuffer );
break;
case IOCTL_GPD_WRITE_PORT_USHORT:
WRITE_PORT_USHORT(
(PUSHORT)((ULONG_PTR)pLDI->PortBase + nPort),
*(PUSHORT)pIOBuffer );
break;
case IOCTL_GPD_WRITE_PORT_ULONG:
WRITE_PORT_ULONG(
(PULONG)((ULONG_PTR)pLDI->PortBase + nPort),
*(PULONG)pIOBuffer );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else if (pLDI->PortMemoryType == 0)
{
// Address is in Memory space
switch (IoctlCode)
{
case IOCTL_GPD_WRITE_PORT_UCHAR:
WRITE_REGISTER_UCHAR(
(PUCHAR)((ULONG_PTR)pLDI->PortBase + nPort),
*(PUCHAR)pIOBuffer );
break;
case IOCTL_GPD_WRITE_PORT_USHORT:
WRITE_REGISTER_USHORT(
(PUSHORT)((ULONG_PTR)pLDI->PortBase + nPort),
*(PUSHORT)pIOBuffer );
break;
case IOCTL_GPD_WRITE_PORT_ULONG:
WRITE_REGISTER_ULONG(
(PULONG)((ULONG_PTR)pLDI->PortBase + nPort),
*(PULONG)pIOBuffer );
break;
default:
return STATUS_INVALID_PARAMETER;
}
}
else
{
return STATUS_UNSUCCESSFUL;
}
//
// Indicate # of bytes written
//
pIrp->IoStatus.Information = DataBufferSize;
return STATUS_SUCCESS;
}
#if DBG
PCHAR
PnPMinorFunctionString (
UCHAR MinorFunction
)
{
switch (MinorFunction)
{
case IRP_MN_START_DEVICE:
return "IRP_MN_START_DEVICE";
case IRP_MN_QUERY_REMOVE_DEVICE:
return "IRP_MN_QUERY_REMOVE_DEVICE";
case IRP_MN_REMOVE_DEVICE:
return "IRP_MN_REMOVE_DEVICE";
case IRP_MN_CANCEL_REMOVE_DEVICE:
return "IRP_MN_CANCEL_REMOVE_DEVICE";
case IRP_MN_STOP_DEVICE:
return "IRP_MN_STOP_DEVICE";
case IRP_MN_QUERY_STOP_DEVICE:
return "IRP_MN_QUERY_STOP_DEVICE";
case IRP_MN_CANCEL_STOP_DEVICE:
return "IRP_MN_CANCEL_STOP_DEVICE";
case IRP_MN_QUERY_DEVICE_RELATIONS:
return "IRP_MN_QUERY_DEVICE_RELATIONS";
case IRP_MN_QUERY_INTERFACE:
return "IRP_MN_QUERY_INTERFACE";
case IRP_MN_QUERY_CAPABILITIES:
return "IRP_MN_QUERY_CAPABILITIES";
case IRP_MN_QUERY_RESOURCES:
return "IRP_MN_QUERY_RESOURCES";
case IRP_MN_QUERY_RESOURCE_REQUIREMENTS:
return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS";
case IRP_MN_QUERY_DEVICE_TEXT:
return "IRP_MN_QUERY_DEVICE_TEXT";
case IRP_MN_FILTER_RESOURCE_REQUIREMENTS:
return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS";
case IRP_MN_READ_CONFIG:
return "IRP_MN_READ_CONFIG";
case IRP_MN_WRITE_CONFIG:
return "IRP_MN_WRITE_CONFIG";
case IRP_MN_EJECT:
return "IRP_MN_EJECT";
case IRP_MN_SET_LOCK:
return "IRP_MN_SET_LOCK";
case IRP_MN_QUERY_ID:
return "IRP_MN_QUERY_ID";
case IRP_MN_QUERY_PNP_DEVICE_STATE:
return "IRP_MN_QUERY_PNP_DEVICE_STATE";
case IRP_MN_QUERY_BUS_INFORMATION:
return "IRP_MN_QUERY_BUS_INFORMATION";
case IRP_MN_DEVICE_USAGE_NOTIFICATION:
return "IRP_MN_DEVICE_USAGE_NOTIFICATION";
case IRP_MN_SURPRISE_REMOVAL:
return "IRP_MN_SURPRISE_REMOVAL";
default:
return "IRP_MN_?????";
}
}
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -