📄 dbgport.c
字号:
This routine is called for every parallel port in the system. It
will create a class device upon connecting to the port device
corresponding to it.
****************************************************************************/
VOID ParInitializeDeviceObject(
IN PDRIVER_OBJECT DriverObject,
IN ULONG ParallelPortNumber)
{
UNICODE_STRING portName, className, linkName;
NTSTATUS status;
PDEVICE_OBJECT deviceObject;
PDEVICE_EXTENSION ext;
PFILE_OBJECT fileObject;
// Cobble together the port and class device names.
if (!ParMakeNames(ParallelPortNumber, &portName, &className, &linkName))
return;
// Create the device object.
status = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION),
&className, FILE_DEVICE_PARALLEL_PORT, 0, TRUE,
&deviceObject);
if (!NT_SUCCESS(status)) {
ExFreePool(linkName.Buffer);
goto Cleanup;
}
// Now that the device has been created,
// set up the device extension.
ext = deviceObject->DeviceExtension;
RtlZeroMemory(ext, sizeof(DEVICE_EXTENSION));
ext->DeviceObject = deviceObject;
deviceObject->Flags |= DO_BUFFERED_IO;
status = IoGetDeviceObjectPointer(&portName, FILE_READ_ATTRIBUTES,
&fileObject,
&ext->PortDeviceObject);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(deviceObject);
ExFreePool(linkName.Buffer);
goto Cleanup;
}
ObDereferenceObject(fileObject);
ext->DeviceObject->StackSize = ext->PortDeviceObject->StackSize + 1;
// Get the port information from the port device object.
status = ParGetPortInfoFromPortDevice(ext);
if (!NT_SUCCESS(status)) {
IoDeleteDevice(deviceObject);
ExFreePool(linkName.Buffer);
goto Cleanup;
}
// Set up the symbolic link for windows apps.
status = IoCreateSymbolicLink(&linkName, &className);
if (!NT_SUCCESS(status)) {
ext->CreatedSymbolicLink = FALSE;
ExFreePool(linkName.Buffer);
goto Cleanup;
}
// We were able to create the symbolic link, so record this
// value in the extension for cleanup at unload time.
ext->CreatedSymbolicLink = TRUE;
ext->SymbolicLinkName = linkName;
Cleanup:
ExFreePool(portName.Buffer);
ExFreePool(className.Buffer);
}
/****************************************************************************
REMARKS:
Set the IOPM (I/O permission map) of the calling process so that it
is given full I/O access. Our IOPM_local[] array is all zeros, so
the IOPM will be all zeros. If OnFlag is 1, the process is given I/O
access. If it is 0, access is removed.
****************************************************************************/
VOID SetIOPermissionMap( int OnFlag )
{
if (OnFlag) {
/* Enable I/O for the process */
Ke386QueryIoAccessMap(1,IOPM_saved);
Ke386IoSetAccessProcess(PsGetCurrentProcess(), 1);
Ke386SetIoAccessMap(1, IOPM_local);
} else {
/* Disable I/O for the process, restoring old IOPM table */
Ke386IoSetAccessProcess(PsGetCurrentProcess(), 0);
Ke386SetIoAccessMap(1, IOPM_saved);
}
}
/****************************************************************************
PARAMETERS:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
RETURNS:
STATUS_SUCCESS - Success.
STATUS_NOT_A_DIRECTORY - This device is not a directory.
REMARKS:
This routine is the dispatch for create requests.
****************************************************************************/
NTSTATUS PORTSTDCALL ParCreate(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PDEVICE_EXTENSION ext;
// Give the debugger process full I/O port access. Ideally we should
// restrict this to the actual I/O ports in use, and this can be done
// in the future if desired.
SetIOPermissionMap(1);
// Now create the parallel port extension device
ext = DeviceObject->DeviceExtension;
irpSp = IoGetCurrentIrpStackLocation(Irp);
if (irpSp->Parameters.Create.Options & FILE_DIRECTORY_FILE)
status = STATUS_NOT_A_DIRECTORY;
else if (!ext->TryAllocatePort(ext->AllocFreePortContext))
status = STATUS_DEVICE_BUSY;
else
status = STATUS_SUCCESS;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
/****************************************************************************
PARAMETERS:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
REMARKS:
This is the cancel routine for this driver.
****************************************************************************/
VOID ParCancel(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
}
/****************************************************************************
PARAMETERS:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
REMARKS:
This is the IOCtl routine for this driver.
****************************************************************************/
NTSTATUS PORTSTDCALL ParIOCTL(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PIO_STACK_LOCATION irpSp;
NTSTATUS status;
PDEVICE_EXTENSION ext;
DBGPORT_IO *IOBuffer;
status = STATUS_SUCCESS;
Irp->IoStatus.Information = sizeof( *IOBuffer );
ext = DeviceObject->DeviceExtension;
irpSp = IoGetCurrentIrpStackLocation(Irp);
IOBuffer = (DBGPORT_IO *)Irp->AssociatedIrp.SystemBuffer;
// NT copies inbuf here before entry and copies this to outbuf after
// return, for METHOD_BUFFERED IOCTL's.
switch (irpSp->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_DBG_READ_PORT_U8:
IOBuffer->data.u8 = _inp(IOBuffer->port);
break;
case IOCTL_DBG_READ_PORT_U16:
IOBuffer->data.u16 = READ_PORT_USHORT((PUSHORT)(ext->Controller + IOBuffer->port));
break;
case IOCTL_DBG_READ_PORT_U32:
IOBuffer->data.u32 = READ_PORT_ULONG((PULONG)(ext->Controller + IOBuffer->port));
break;
case IOCTL_DBG_WRITE_PORT_U8:
_outp(IOBuffer->port,IOBuffer->data.u8);
break;
case IOCTL_DBG_WRITE_PORT_U16:
WRITE_PORT_USHORT((PUSHORT)(ext->Controller + IOBuffer->port), IOBuffer->data.u16);
break;
case IOCTL_DBG_WRITE_PORT_U32:
WRITE_PORT_ULONG((PULONG)(ext->Controller + IOBuffer->port), IOBuffer->data.u32);
break;
case IOCTL_DBG_REMOTE_GET:
IOBuffer->status = RemoteGet(ext,IOBuffer->buffer,IOBuffer->len);
break;
case IOCTL_DBG_REMOTE_PUT:
IOBuffer->status = RemotePut(ext,IOBuffer->buffer,IOBuffer->len);
break;
case IOCTL_DBG_REMOTE_CONNECT_SERV:
IOBuffer->status = RemoteConnectServer(ext);
break;
case IOCTL_DBG_REMOTE_CONNECT_CLIENT:
IOBuffer->status = RemoteConnectClient(ext);
break;
case IOCTL_DBG_REMOTE_DISCO:
RemoteDisco(ext);
break;
case IOCTL_DBG_REMOTE_LINK:
RemoteLink(ext);
break;
default:
Irp->IoStatus.Information = 0;
status = STATUS_NOT_IMPLEMENTED;
break;
}
Irp->IoStatus.Status = status;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return status;
}
/****************************************************************************
PARAMETERS:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
REMARKS:
This is the cleanup routine for this driver.
****************************************************************************/
NTSTATUS PORTSTDCALL ParCleanup(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_CANCELLED;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_CANCELLED;
}
/****************************************************************************
PARAMETERS:
DeviceObject - Supplies the device object.
Irp - Supplies the I/O request packet.
REMARKS:
This is the close routine for this driver.
****************************************************************************/
NTSTATUS PORTSTDCALL ParClose(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp)
{
PDEVICE_EXTENSION ext;
// Restore the original I/O port mappings
SetIOPermissionMap(0);
ext = DeviceObject->DeviceExtension;
ext->FreePort(ext->AllocFreePortContext);
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
/****************************************************************************
PARAMETERS:
DriverObject - Supplies the driver object.
REMARKS:
This routine loops through the device list and cleans up after
each of the devices.
****************************************************************************/
VOID PORTSTDCALL ParUnload(
IN PDRIVER_OBJECT DriverObject)
{
PDEVICE_OBJECT currentDevice;
PDEVICE_EXTENSION ext;
while (currentDevice = DriverObject->DeviceObject) {
ext = currentDevice->DeviceExtension;
if (ext->CreatedSymbolicLink) {
IoDeleteSymbolicLink(&ext->SymbolicLinkName);
ExFreePool(ext->SymbolicLinkName.Buffer);
}
IoDeleteDevice(currentDevice);
}
// Free the local IOPM table if allocated
if (IOPM_local)
MmFreeNonCachedMemory(IOPM_local, sizeof(IOPM));
if (IOPM_saved) {
MmFreeNonCachedMemory(IOPM_saved, sizeof(IOPM));
}
}
/****************************************************************************
PARAMETERS:
DriverObject - Supplies the driver object.
RegistryPath - Supplies the registry path for this driver.
REMARKS:
This routine is called at system initialization time to initialize
this driver.
****************************************************************************/
NTSTATUS PORTSTDCALL DriverEntry(
IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
ULONG i;
// TODO: We should be able to re-code this driver to use a call-gate
// to give the calling process full IOPL access, without needing
// the gross IOPM hack we currently use. This would make it
// slightly faster also.
// Allocate a buffer for the local IOPM and zero it.
IOPM_local = MmAllocateNonCachedMemory(sizeof(IOPM));
IOPM_saved = MmAllocateNonCachedMemory(sizeof(IOPM));
if (!IOPM_local || !IOPM_saved)
return STATUS_INSUFFICIENT_RESOURCES;
RtlZeroMemory(IOPM_local, sizeof(IOPM));
Ke386QueryIoAccessMap(1,IOPM_saved);
// Initialise all the device objects
for (i = 0; i < IoGetConfigurationInformation()->ParallelCount; i++)
ParInitializeDeviceObject(DriverObject, i);
if (!DriverObject->DeviceObject)
return STATUS_NO_SUCH_DEVICE;
// Initialize the Driver Object with driver's entry points
DriverObject->MajorFunction[IRP_MJ_CREATE] = ParCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = ParClose;
DriverObject->MajorFunction[IRP_MJ_CLEANUP] = ParCleanup;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = ParIOCTL;
DriverObject->DriverUnload = ParUnload;
return STATUS_SUCCESS;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -