// Gerätetreiber zum direkten Zugriff auf Systemressourcen
// unter Windows NT 4.0, c't 1/97 Matthias Witthopf, Andreas Stiller
extern "C"
{
#include <ntddk.h>
#include <string.h>
#include <stdlib.h>
#include <devioctl.h>
#include <conio.h>
#include "directnt.h"
}
#define DIRECTNT_DEVICE_NAME L"\\Device\\DirectNT"
#define DOS_DEVICE_NAME L"\\DosDevices\\Dev_DirectNT"
#define IOPM_SIZE 0x2000
typedef UCHAR IOPMTYP[IOPM_SIZE];
typedef struct {
ULONG Dummy;
IOPMTYP iopm;
} TLocalDevInfo,* PLocalDevInfo;
extern "C" void Ke386SetIoAccessMap (int,IOPMTYP);
extern "C" void Ke386QueryIoAccessMap (int,IOPMTYP);
extern "C" void Ke386IoSetAccessProcess (PEPROCESS, int);
__declspec(dllimport) BOOLEAN MmIsAddressValid (IN PVOID );
__declspec(dllimport) PVOID MmMapIoSpace (PHYSICAL_ADDRESS,ULONG,BOOLEAN);
__declspec(dllimport) VOID MmUnmapIoSpace (PVOID,ULONG);
NTSTATUS DirectNT_CreateDevice(IN PWSTR PrototypeName,
IN DEVICE_TYPE DeviceType, IN PDRIVER_OBJECT DriverObject,
OUT PDEVICE_OBJECT *ppDevObj)
{
UNICODE_STRING NtDeviceName;
UNICODE_STRING Win32DeviceName;
RtlInitUnicodeString(&NtDeviceName,PrototypeName);
NTSTATUS Status = IoCreateDevice(DriverObject,sizeof(TLocalDevInfo),
&NtDeviceName,DeviceType,0,FALSE,ppDevObj);
if (!NT_SUCCESS(Status)) return Status;
RtlZeroMemory((*ppDevObj)->DeviceExtension,sizeof(TLocalDevInfo));
RtlInitUnicodeString(&Win32DeviceName,DOS_DEVICE_NAME);
Status = IoCreateSymbolicLink(&Win32DeviceName,&NtDeviceName);
if (!NT_SUCCESS(Status))
IoDeleteDevice(*ppDevObj);
return Status;
}
void SetIOPermissionFree(int OnFlag,int pstart,int pend,IOPMTYP iopm)
{
Ke386QueryIoAccessMap(1,iopm);
for (int j=pstart; j<=pend; j++)
iopm[j/8] &= ~(1 << (j%8));
Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag);
Ke386SetIoAccessMap (1,iopm);
}
void SetIOPermissionLock(int OnFlag,int pstart,int pend,IOPMTYP iopm)
{
Ke386QueryIoAccessMap(1,iopm);
for (int j=pstart; j<=pend; j++)
iopm[j/8] |= (1 << (j%8));
Ke386IoSetAccessProcess(PsGetCurrentProcess(), OnFlag);
Ke386SetIoAccessMap (1,iopm);
}
NTSTATUS DirectNT_Control(IN PLocalDevInfo pLDI, IN PIRP pIrp,
IN PIO_STACK_LOCATION IrpStack, IN ULONG IoctlCode)
{
PDirectNTInfo InBuf=(PDirectNTInfo)pIrp->AssociatedIrp.SystemBuffer;
ULONG InBufSize=IrpStack->Parameters.DeviceIoControl.InputBufferLength;
ULONG OpCode=InBuf->OpCode;
void *OutBuf=(void *)pIrp->AssociatedIrp.SystemBuffer;
ULONG OutBufSize=IrpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch(OpCode) {
case OP_Check:
*(PULONG)OutBuf = 0x12345678;
pIrp->IoStatus.Information = sizeof(ULONG);
return STATUS_SUCCESS;
case OP_GiveIO:
SetIOPermissionFree(1,InBuf->Par1,InBuf->Par2,pLDI->iopm);
pIrp->IoStatus.Information = 0;
return STATUS_SUCCESS;
case OP_LoadIOPM:
Ke386QueryIoAccessMap(1,(UCHAR*)OutBuf);
pIrp->IoStatus.Information = IOPM_SIZE;
return STATUS_SUCCESS;
case OP_LockIO:
SetIOPermissionLock(1,InBuf->Par1,InBuf->Par2,pLDI->iopm);
pIrp->IoStatus.Information = 0;
return STATUS_SUCCESS;
case OP_GetCR0:
{
ULONG Result;
__asm MOV EAX,CR0
__asm MOV Result,EAX
*(PULONG)OutBuf = Result;
pIrp->IoStatus.Information = sizeof(ULONG);
return STATUS_SUCCESS;
}
case OP_SetCR0:
{
ULONG Value = InBuf->Par1;
__asm
{ MOV EAX,Value
__emit 0x0F // = wbinvd, Achtung ist in Visual C++ 2.0
__emit 0x09 // vorhanden, aber falsch impementiert!!!
MOV CR0,EAX
}
pIrp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
case OP_GetMR:
{
ULONG Resultlo;
ULONG Resulthi;
ULONG Index = InBuf->Par1;
__asm {
Push ecx
push edx
MOV ECX,Index
__emit 0x0F //RDMSR
__emit 0x32
MOV Resultlo,Eax
MOV Resulthi,Edx
Pop ecx
pop edx
}
*(PULONG)OutBuf = Resultlo;
*((PULONG)(OutBuf)+1) = Resulthi;
pIrp->IoStatus.Information = 2*sizeof(ULONG);
return STATUS_SUCCESS;
}
case OP_SetMR:
{
ULONG Index = InBuf->Par1;
ULONG Valuelo = InBuf->Par2;
ULONG Valuehi = InBuf->Par3;
__asm {
push ecx
push edx
MOV ECX,Index
MOV EAX,Valuelo
MOV EDX,Valuehi
__emit 0x0F // WRMSR
__emit 0x30
pop edx
pop ecx
}
pIrp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
case OP_ReadPortByte:
*(PUCHAR)OutBuf = READ_PORT_UCHAR((PUCHAR)InBuf->Par1);
pIrp->IoStatus.Information = sizeof(UCHAR);
return STATUS_SUCCESS;
case OP_WritePortByte:
WRITE_PORT_UCHAR((PUCHAR)InBuf->Par1,(UCHAR)InBuf->Par2);
pIrp->IoStatus.Information = 0;
return STATUS_SUCCESS;
case OP_WritePCIDword: // Konfigmechanismus 1
{
ULONG cfb=_inp(0xCFB);
ULONG confadd= (1 << 31) | (ULONG)InBuf->Par1 | (ULONG) InBuf->Par2 << 10;
_asm pushf
_asm cli
_outp (0xCFB, cfb | 1);
_outp (0xCFA ,0);
_outpd (0xCF8,confadd);
_outpd (0xCFC,(ULONG)InBuf->Par3);
_outp (0xCFB,cfb);
_asm popf
pIrp->IoStatus.Information = 0;
return STATUS_SUCCESS;
}
case OP_ReadPCIDword: //Konfigmechanismus 1
{
ULONG cfb=_inp(0xCFB);
ULONG confadd= (1 << 31) | (ULONG)InBuf->Par1 | (ULONG) InBuf->Par2 <<10 ;
_asm pushf;
_asm cli;
_outp (0xCFB, cfb | 1);
_outp (0xCFA ,0);
_outpd (0xCF8,confadd);
*(PULONG)OutBuf = _inpd(0xCFC);
_outp (0xCFB,cfb);
_asm popf
pIrp->IoStatus.Information = sizeof(ULONG);
return STATUS_SUCCESS;
}
case OP_ReadFlags:
{
ULONG EFlags;
_asm
{
pushfd
pop eax
mov EFlags,eax
}
pIrp->IoStatus.Information = sizeof(ULONG);
return STATUS_SUCCESS;
}
/* case OP_ReadMemDword:
if (MmIsAddressValid)
{
*(PULONG)OutBuf = *(ULONG*) (InBuf->Par1);
pIrp->IoStatus.Information = sizeof(ULONG);
return STATUS_SUCCESS;
}
else
{
pIrp->IoStatus.Information = 0;
return STATUS_ACCESS_VIOLATION;
}
*/
case OP_ReadPhysMemDword:
PHYSICAL_ADDRESS PADDR;
PADDR.LowPart=(ULONG) (InBuf->Par1);
PADDR.HighPart=0; // Reserve für > 4GByte
PVOID Linadr=MmMapIoSpace (PADDR,4,MmNonCached);
*(PULONG)OutBuf = *(ULONG*) Linadr;
MmUnmapIoSpace (Linadr,4);
pIrp->IoStatus.Information = sizeof(ULONG);
return STATUS_SUCCESS;
}
return STATUS_INVALID_PARAMETER;
}
NTSTATUS DirectNT_Dispatch(IN PDEVICE_OBJECT pDO,IN PIRP pIrp)
{
pIrp->IoStatus.Information = 0; // Anzahl Rückgabe-Bytes
PLocalDevInfo pLDI = (PLocalDevInfo)pDO->DeviceExtension;
PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
switch(pIrpStack->MajorFunction) {
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
Status = STATUS_SUCCESS;
break;
case IRP_MJ_DEVICE_CONTROL:
switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode) {
case IOCTL_DIRECTNT_CONTROL:
Status = DirectNT_Control(pLDI,pIrp,pIrpStack,
pIrpStack->Parameters.DeviceIoControl.IoControlCode);
break;
}
break;
}
pIrp->IoStatus.Status = Status;
IoCompleteRequest(pIrp,IO_NO_INCREMENT);
return Status;
}
VOID DirectNT_Unload(PDRIVER_OBJECT DriverObject)
{ // Symbolischen Link wieder auflösen
UNICODE_STRING Win32DeviceName;
RtlInitUnicodeString(&Win32DeviceName,DOS_DEVICE_NAME);
IoDeleteSymbolicLink(&Win32DeviceName);
IoDeleteDevice(DriverObject->DeviceObject);
}
extern "C" NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{ // Symbolischen Link erzeugen, so daß Win32 darauf zugreifen kann
DriverObject->MajorFunction[IRP_MJ_CREATE] = DirectNT_Dispatch;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DirectNT_Dispatch;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DirectNT_Dispatch;
DriverObject->DriverUnload = DirectNT_Unload;
PDEVICE_OBJECT DeviceObject;
return DirectNT_CreateDevice(DIRECTNT_DEVICE_NAME,DIRECTNT_TYPE,
DriverObject,&DeviceObject);
}
Vorgefundene Kodierung: UTF-8 | 0
|