Add giveio device driver source. Requires MS DDK to build.
git-svn-id: svn://svn.savannah.nongnu.org/avrdude/trunk@228 81a1dc3b-b13d-400b-aceb-764788c761c2
This commit is contained in:
parent
e5c227d049
commit
c39f81bb1b
|
@ -0,0 +1,168 @@
|
|||
/*********************************************************************
|
||||
|
||||
Author: Dale Roberts
|
||||
Date: 8/30/95
|
||||
Program: GIVEIO.SYS
|
||||
Compile: Use DDK BUILD facility
|
||||
|
||||
Purpose: Give direct port I/O access to a user mode process.
|
||||
|
||||
*********************************************************************/
|
||||
#include <ntddk.h>
|
||||
|
||||
/*
|
||||
* The name of our device driver.
|
||||
*/
|
||||
#define DEVICE_NAME_STRING L"giveio"
|
||||
|
||||
/*
|
||||
* This is the "structure" of the IOPM. It is just a simple
|
||||
* character array of length 0x2000.
|
||||
*
|
||||
* This holds 8K * 8 bits -> 64K bits of the IOPM, which maps the
|
||||
* entire 64K I/O space of the x86 processor. Any 0 bits will give
|
||||
* access to the corresponding port for user mode processes. Any 1
|
||||
* bits will disallow I/O access to the corresponding port.
|
||||
*/
|
||||
#define IOPM_SIZE 0x2000
|
||||
typedef UCHAR IOPM[IOPM_SIZE];
|
||||
|
||||
/*
|
||||
* This will hold simply an array of 0's which will be copied
|
||||
* into our actual IOPM in the TSS by Ke386SetIoAccessMap().
|
||||
* The memory is allocated at driver load time.
|
||||
*/
|
||||
IOPM *IOPM_local = 0;
|
||||
|
||||
/*
|
||||
* These are the two undocumented calls that we will use to give
|
||||
* the calling process I/O access.
|
||||
*
|
||||
* Ke386IoSetAccessMap() copies the passed map to the TSS.
|
||||
*
|
||||
* Ke386IoSetAccessProcess() adjusts the IOPM offset pointer so that
|
||||
* the newly copied map is actually used. Otherwise, the IOPM offset
|
||||
* points beyond the end of the TSS segment limit, causing any I/O
|
||||
* access by the user mode process to generate an exception.
|
||||
*/
|
||||
void Ke386SetIoAccessMap(int, IOPM *);
|
||||
void Ke386QueryIoAccessMap(int, IOPM *);
|
||||
void Ke386IoSetAccessProcess(PEPROCESS, int);
|
||||
|
||||
/*********************************************************************
|
||||
Release any allocated objects.
|
||||
*********************************************************************/
|
||||
VOID GiveioUnload(IN PDRIVER_OBJECT DriverObject)
|
||||
{
|
||||
WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING;
|
||||
UNICODE_STRING uniDOSString;
|
||||
|
||||
if(IOPM_local)
|
||||
MmFreeNonCachedMemory(IOPM_local, sizeof(IOPM));
|
||||
|
||||
RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);
|
||||
IoDeleteSymbolicLink (&uniDOSString);
|
||||
IoDeleteDevice(DriverObject->DeviceObject);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
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)
|
||||
{
|
||||
Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag);
|
||||
Ke386SetIoAccessMap(1, IOPM_local);
|
||||
}
|
||||
|
||||
void GiveIO(void)
|
||||
{
|
||||
SetIOPermissionMap(1);
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Service handler for a CreateFile() user mode call.
|
||||
|
||||
This routine is entered in the driver object function call table by
|
||||
the DriverEntry() routine. When the user mode application calls
|
||||
CreateFile(), this routine gets called while still in the context of
|
||||
the user mode application, but with the CPL (the processor's Current
|
||||
Privelege Level) set to 0. This allows us to do kernel mode
|
||||
operations. GiveIO() is called to give the calling process I/O
|
||||
access. All the user mode application needs do to obtain I/O access
|
||||
is open this device with CreateFile(). No other operations are
|
||||
required.
|
||||
*********************************************************************/
|
||||
NTSTATUS GiveioCreateDispatch(
|
||||
IN PDEVICE_OBJECT DeviceObject,
|
||||
IN PIRP Irp
|
||||
)
|
||||
{
|
||||
GiveIO(); // give the calling process I/O access
|
||||
|
||||
Irp->IoStatus.Information = 0;
|
||||
Irp->IoStatus.Status = STATUS_SUCCESS;
|
||||
IoCompleteRequest(Irp, IO_NO_INCREMENT);
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/*********************************************************************
|
||||
Driver Entry routine.
|
||||
|
||||
This routine is called only once after the driver is initially
|
||||
loaded into memory. It allocates everything necessary for the
|
||||
driver's operation. In our case, it allocates memory for our IOPM
|
||||
array, and creates a device which user mode applications can open.
|
||||
It also creates a symbolic link to the device driver. This allows
|
||||
a user mode application to access our driver using the \\.\giveio
|
||||
notation.
|
||||
*********************************************************************/
|
||||
NTSTATUS DriverEntry(
|
||||
IN PDRIVER_OBJECT DriverObject,
|
||||
IN PUNICODE_STRING RegistryPath
|
||||
)
|
||||
{
|
||||
PDEVICE_OBJECT deviceObject;
|
||||
NTSTATUS status;
|
||||
WCHAR NameBuffer[] = L"\\Device\\" DEVICE_NAME_STRING;
|
||||
WCHAR DOSNameBuffer[] = L"\\DosDevices\\" DEVICE_NAME_STRING;
|
||||
UNICODE_STRING uniNameString, uniDOSString;
|
||||
|
||||
//
|
||||
// Allocate a buffer for the local IOPM and zero it.
|
||||
//
|
||||
IOPM_local = MmAllocateNonCachedMemory(sizeof(IOPM));
|
||||
if(IOPM_local == 0)
|
||||
return STATUS_INSUFFICIENT_RESOURCES;
|
||||
RtlZeroMemory(IOPM_local, sizeof(IOPM));
|
||||
|
||||
//
|
||||
// Set up device driver name and device object.
|
||||
//
|
||||
RtlInitUnicodeString(&uniNameString, NameBuffer);
|
||||
RtlInitUnicodeString(&uniDOSString, DOSNameBuffer);
|
||||
|
||||
status = IoCreateDevice(DriverObject, 0,
|
||||
&uniNameString,
|
||||
FILE_DEVICE_UNKNOWN,
|
||||
0, FALSE, &deviceObject);
|
||||
|
||||
if(!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
status = IoCreateSymbolicLink (&uniDOSString, &uniNameString);
|
||||
|
||||
if (!NT_SUCCESS(status))
|
||||
return status;
|
||||
|
||||
//
|
||||
// Initialize the Driver Object with driver's entry points.
|
||||
// All we require are the Create and Unload operations.
|
||||
//
|
||||
DriverObject->MajorFunction[IRP_MJ_CREATE] = GiveioCreateDispatch;
|
||||
DriverObject->DriverUnload = GiveioUnload;
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
Loading…
Reference in New Issue