📄 eppflex.c
字号:
#include "ntddk.h"
#include "string.h"
#include "ddk/parallel.h"
#include "eppflex.h"
#define printk DbgPrint
#define kmalloc(size) ExAllocatePool(NonPagedPool,size)
#define kfree ExFreePool
#if 0
#define VLOG(x) do { x; } while (0)
#else
#define VLOG(x) do { } while (0)
#endif
#if 1
#define ELOG(x) do { x; } while (0)
#else
#define ELOG(x) do { } while (0)
#endif
struct eppflex {
unsigned int dummy;
};
struct eppflexfile {
PDEVICE_OBJECT pdo;
PFILE_OBJECT pdfo;
PARALLEL_PORT_INFORMATION info;
PARALLEL_PNP_INFORMATION pnpinfo;
};
static NTSTATUS parcompletion(PDEVICE_OBJECT devobj, PIRP irp, PKEVENT event)
{
KeSetEvent(event, 0, FALSE);
return STATUS_MORE_PROCESSING_REQUIRED;
}
static NTSTATUS callparport(struct eppflexfile *fs, unsigned long ioctlcode,
void *buffer, unsigned int inlen, unsigned int outlen,
LARGE_INTEGER *timeout)
{
NTSTATUS status;
PIRP irp;
PIO_STACK_LOCATION irpsp;
KEVENT event;
irp = IoAllocateIrp((CCHAR)(fs->pdo->StackSize+1), FALSE);
if (!irp)
return STATUS_INSUFFICIENT_RESOURCES;
irpsp = IoGetNextIrpStackLocation(irp);
irpsp->MajorFunction = IRP_MJ_INTERNAL_DEVICE_CONTROL;
irpsp->Parameters.DeviceIoControl.OutputBufferLength = outlen;
irpsp->Parameters.DeviceIoControl.InputBufferLength = inlen;
irpsp->Parameters.DeviceIoControl.IoControlCode = ioctlcode;
irp->AssociatedIrp.SystemBuffer = buffer;
KeInitializeEvent(&event, NotificationEvent, FALSE);
IoSetCompletionRoutine(irp, parcompletion, &event, TRUE, TRUE, TRUE);
status = IoCallDriver(fs->pdo, irp);
if (!NT_SUCCESS(status)) {
IoFreeIrp(irp);
return status;
}
status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, timeout);
if (status == STATUS_TIMEOUT) {
IoCancelIrp(irp);
status = KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
}
status = irp->IoStatus.Status;
IoFreeIrp(irp);
return status;
}
static NTSTATUS read_port(PDEVICE_OBJECT devobj, PIRP irp, PUCHAR port)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpsp;
PFILE_OBJECT fileobj;
struct eppflex *s = devobj->DeviceExtension;
struct eppflexfile *fs;
struct eppflex_rwdata *rw = (struct eppflex_rwdata *)irp->AssociatedIrp.SystemBuffer;
irpsp = IoGetCurrentIrpStackLocation(irp);
fileobj = irpsp->FileObject;
fs = fileobj->FsContext;
irp->IoStatus.Information = 0;
if (irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(struct eppflex_rwdata))
status = STATUS_INVALID_PARAMETER;
else if ((port < fs->info.Controller || port >= fs->info.Controller+fs->info.SpanOfController) &&
(port < fs->pnpinfo.EcpController || port >= fs->pnpinfo.EcpController+fs->pnpinfo.SpanOfEcpController))
status = STATUS_ACCESS_VIOLATION;
else {
rw->data = READ_PORT_UCHAR(port);
irp->IoStatus.Information = sizeof(struct eppflex_rwdata);
}
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
static NTSTATUS write_port(PDEVICE_OBJECT devobj, PIRP irp, PUCHAR port)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpsp;
PFILE_OBJECT fileobj;
struct eppflex *s = devobj->DeviceExtension;
struct eppflexfile *fs;
struct eppflex_rwdata *rw = (struct eppflex_rwdata *)irp->AssociatedIrp.SystemBuffer;
irpsp = IoGetCurrentIrpStackLocation(irp);
fileobj = irpsp->FileObject;
fs = fileobj->FsContext;
irp->IoStatus.Information = 0;
if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct eppflex_rwdata))
status = STATUS_INVALID_PARAMETER;
else if ((port < fs->info.Controller || port >= fs->info.Controller+fs->info.SpanOfController) &&
(port < fs->pnpinfo.EcpController || port >= fs->pnpinfo.EcpController+fs->pnpinfo.SpanOfEcpController))
status = STATUS_ACCESS_VIOLATION;
else {
WRITE_PORT_UCHAR(port, rw->data);
}
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
static NTSTATUS frob_port(PDEVICE_OBJECT devobj, PIRP irp, PUCHAR port)
{
NTSTATUS status = STATUS_SUCCESS;
PIO_STACK_LOCATION irpsp;
PFILE_OBJECT fileobj;
struct eppflex *s = devobj->DeviceExtension;
struct eppflexfile *fs;
struct eppflex_rwdata *rw = (struct eppflex_rwdata *)irp->AssociatedIrp.SystemBuffer;
UCHAR data;
irpsp = IoGetCurrentIrpStackLocation(irp);
fileobj = irpsp->FileObject;
fs = fileobj->FsContext;
irp->IoStatus.Information = 0;
if (irpsp->Parameters.DeviceIoControl.InputBufferLength < sizeof(struct eppflex_rwdata) ||
irpsp->Parameters.DeviceIoControl.OutputBufferLength < sizeof(struct eppflex_rwdata))
status = STATUS_INVALID_PARAMETER;
else if ((port < fs->info.Controller || port >= fs->info.Controller+fs->info.SpanOfController) &&
(port < fs->pnpinfo.EcpController || port >= fs->pnpinfo.EcpController+fs->pnpinfo.SpanOfEcpController))
status = STATUS_ACCESS_VIOLATION;
else {
data = READ_PORT_UCHAR(port);
data = (data & ~rw->mask) ^ rw->data;
WRITE_PORT_UCHAR(port, data);
rw->data = data;
irp->IoStatus.Information = sizeof(struct eppflex_rwdata);
}
irp->IoStatus.Status = status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
static NTSTATUS ioctl(PDEVICE_OBJECT devobj, PIRP irp)
{
NTSTATUS status = STATUS_NOT_IMPLEMENTED;
PIO_STACK_LOCATION irpsp;
PFILE_OBJECT fileobj;
struct eppflex *s = devobj->DeviceExtension;
struct eppflexfile *fs;
irpsp = IoGetCurrentIrpStackLocation(irp);
fileobj = irpsp->FileObject;
fs = fileobj->FsContext;
VLOG(printk("eppflex: ioctl\n"));
if (!fs) {
status = irp->IoStatus.Status = STATUS_NOT_IMPLEMENTED;
IoCompleteRequest(irp, IO_NO_INCREMENT);
return status;
}
switch (irpsp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_EPPFLEX_READ_DATA:
return read_port(devobj, irp, fs->info.Controller);
case IOCTL_EPPFLEX_WRITE_DATA:
return write_port(devobj, irp, fs->info.Controller);
case IOCTL_EPPFLEX_READ_STATUS:
return read_port(devobj, irp, fs->info.Controller + 1);
case IOCTL_EPPFLEX_WRITE_STATUS:
return write_port(devobj, irp, fs->info.Controller + 1);
case IOCTL_EPPFLEX_READ_CONTROL:
return read_port(devobj, irp, fs->info.Controller + 2);
case IOCTL_EPPFLEX_WRITE_CONTROL:
return write_port(devobj, irp, fs->info.Controller + 2);
case IOCTL_EPPFLEX_FROB_CONTROL:
return frob_port(devobj, irp, fs->info.Controller + 2);
case IOCTL_EPPFLEX_READ_ECONTROL:
return read_port(devobj, irp, fs->pnpinfo.EcpController + 2);
case IOCTL_EPPFLEX_WRITE_ECONTROL:
return write_port(devobj, irp, fs->pnpinfo.EcpController + 2);
case IOCTL_EPPFLEX_FROB_ECONTROL:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -