/*++
PhyMem Driver
Ver: 1.2
Author: akui
Date: 2009/5/10
--*/
#include <ntddk.h>
#include "phymem.h"
#include "isr.h"
#include "DebugPrint.h"
//Mapped memory information list
typedef struct tagMAPINFO
{
SINGLE_LIST_ENTRY link;
PMDL pMdl; //allocated mdl
PVOID pvk; //kernel mode virtual address
PVOID pvu; //user mode virtual address
ULONG memSize;//memory size in bytes
} MAPINFO, *PMAPINFO;
//ISR information list
typedef struct tagISRINFO
{
SINGLE_LIST_ENTRY link;
UCHAR intNo; //interrupt number(0-255)
PMDL pIsrMdl; //allocated mdl for isr code
PMDL pContextMdl; //allocated mdl for isr context
INTVECT intVect; //8 bytes IDT table entry
UCHAR isrCode[ISRCODE_LEN];//isr code buffer length
} ISRINFO, *PISRINFO;
SINGLE_LIST_ENTRY lstMapInfo; //mapped memory information
SINGLE_LIST_ENTRY lstIsrInfo; //isr information
PFILE_OBJECT pcifo=NULL; //pci bus filter driver file object
PDEVICE_OBJECT pcifido=NULL; //pci bus filter driver device object
PPCI_BUS_INTERFACE_STANDARD busInterface=NULL; //pci driver interface
//forward function declaration
NTSTATUS PhyMemCreate(IN PDEVICE_OBJECT fdo, IN PIRP irp);
NTSTATUS PhyMemClose(IN PDEVICE_OBJECT fdo, IN PIRP irp);
NTSTATUS PhyMemIoCtl(IN PDEVICE_OBJECT fdo, IN PIRP irp);
VOID PhyMemUnload(IN PDRIVER_OBJECT dro);
NTSTATUS GetBusInterface(IN PDEVICE_OBJECT pcifido,
OUT PPCI_BUS_INTERFACE_STANDARD busInterface);
//local functions
static NTSTATUS PreGetBus();
static NTSTATUS ReadWriteConfig(PIRP irp, PPHYMEM_PCI pPci, BOOLEAN isRead);
static NTSTATUS MapUserToKernel(PVOID pUser, ULONG len, LOCK_OPERATION lo, PMDL *ppMdl, PVOID *ppSysAddr);
static PINTVECT GetStoredIntVector(UCHAR nIntNo);
static VOID RemoveIsrInfo(UCHAR nIntNo);
/*++
DriverEntry routine
--*/
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject,
IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING DeviceNameU;
UNICODE_STRING DeviceLinkU;
NTSTATUS ntStatus;
PDEVICE_OBJECT fdo=NULL;
UNREFERENCED_PARAMETER(RegistryPath);
DebugPrintInit("PhyMem");
DebugPrintMsg("Entering DriverEntry");
lstMapInfo.Next=NULL;
lstIsrInfo.Next=NULL;
//initialize pci bus interface buffer
busInterface=(PPCI_BUS_INTERFACE_STANDARD)ExAllocatePool(NonPagedPool,
sizeof(PCI_BUS_INTERFACE_STANDARD));
if (busInterface==NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory(busInterface, sizeof(PCI_BUS_INTERFACE_STANDARD));
RtlInitUnicodeString(&DeviceNameU, L"\\Device\\PhyMem");
//Create an EXCLUSIVE device object
ntStatus=IoCreateDevice(DriverObject, //IN: Driver Object
0, //IN: Device Extension Size
&DeviceNameU, //IN: Device Name
FILE_DEVICE_PHYMEM, //IN: Device Type
0, //IN: Device Characteristics
TRUE, //IN: Exclusive
&fdo); //OUT:Created Device Object
if (NT_SUCCESS(ntStatus))
{
if (NT_SUCCESS(ntStatus))
{
//Dispatch functions
DriverObject->MajorFunction[IRP_MJ_CREATE]=PhyMemCreate;
DriverObject->MajorFunction[IRP_MJ_CLOSE]=PhyMemClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]=PhyMemIoCtl;
DriverObject->DriverUnload=PhyMemUnload;
//Create a symbolic link
RtlInitUnicodeString(&DeviceLinkU, L"\\DosDevices\\PhyMem");
ntStatus=IoCreateSymbolicLink(&DeviceLinkU, &DeviceNameU);
if (!NT_SUCCESS(ntStatus))
{
DebugPrintMsg("Error: IoCreateSymbolicLink failed");
IoDeleteDevice(fdo);
}
}
else
{
DebugPrintMsg("Error: IoGetDeviceObjectPointer failed");
IoDeleteDevice(fdo);
}
}
else
DebugPrintMsg("Error: IoCreateDevice failed");
DebugPrintMsg("Leaving DriverEntry");
return ntStatus;
}
/*++
IRP_MJ_CREATE dispatch routine
--*/
NTSTATUS PhyMemCreate(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
UNREFERENCED_PARAMETER(fdo);
irp->IoStatus.Status=STATUS_SUCCESS;
irp->IoStatus.Information=0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
DebugPrintMsg("IRP_MJ_CREATE");
return STATUS_SUCCESS;
}
/*++
IRP_MJ_CLOSE dispatch routine
--*/
NTSTATUS PhyMemClose(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
UNREFERENCED_PARAMETER(fdo);
irp->IoStatus.Status=STATUS_SUCCESS;
irp->IoStatus.Information=0;
IoCompleteRequest(irp, IO_NO_INCREMENT);
DebugPrintMsg("IRP_MJ_CLOSE");
return STATUS_SUCCESS;
}
/*++
IRP_MJ_DEVICE_CONTROL dispatch routine
--*/
NTSTATUS PhyMemIoCtl(IN PDEVICE_OBJECT fdo, IN PIRP irp)
{
PIO_STACK_LOCATION irpStack;
ULONG dwInBufLen;
ULONG dwOutBufLen;
ULONG dwIoCtlCode;
NTSTATUS ntStatus;
PVOID pSysBuf;
PPHYMEM_MEM pMem;
PPHYMEM_PORT pPort;
PPHYMEM_PCI pPci;
PPHYMEM_ISR pIsr;
PPHYMEM_SYSCALL pSyscall;
DebugPrintMsg("Entering PhyMemIoCtl");
//Init to default settings
irp->IoStatus.Status=STATUS_SUCCESS;
irp->IoStatus.Information=0;
irpStack=IoGetCurrentIrpStackLocation(irp);
//Get the pointer to the input/output buffer and it's length
pSysBuf=(PVOID)irp->AssociatedIrp.SystemBuffer;
pMem=(PPHYMEM_MEM)pSysBuf;
pPort=(PPHYMEM_PORT)pSysBuf;
pPci=(PPHYMEM_PCI)pSysBuf;
pIsr=(PPHYMEM_ISR)pSysBuf;
pSyscall=(PPHYMEM_SYSCALL)pSysBuf;
dwInBufLen=irpStack->Parameters.DeviceIoControl.InputBufferLength;
dwOutBufLen=irpStack->Parameters.DeviceIoControl.OutputBufferLength;
switch (irpStack->MajorFunction)
{
case IRP_MJ_DEVICE_CONTROL:
dwIoCtlCode=irpStack->Parameters.DeviceIoControl.IoControlCode;
switch (dwIoCtlCode)
{
case IOCTL_PHYMEM_MAP:
if (dwInBufLen==sizeof(PHYMEM_MEM) && dwOutBufLen==sizeof(PVOID))
{
PHYSICAL_ADDRESS phyAddr;
PVOID pvk, pvu;
phyAddr.QuadPart=(ULONGLONG)pMem->pvAddr;
//get mapped kernel address
pvk=MmMapIoSpace(phyAddr, pMem->dwSize, MmNonCached);
if (pvk)
{
//allocate mdl for the mapped kernel address
PMDL pMdl=IoAllocateMdl(pvk, pMem->dwSize, FALSE, FALSE, NULL);
if (pMdl)
{
PMAPINFO pMapInfo;
//build mdl and map to user space
MmBuildMdlForNonPagedPool(pMdl);
pvu=MmMapLockedPages(pMdl, UserMode);
//insert mapped infomation to list
pMapInfo=(PMAPINFO)ExAllocatePool(\
NonPagedPool, sizeof(MAPINFO));
pMapInfo->pMdl=pMdl;
pMapInfo->pvk=pvk;
pMapInfo->pvu=pvu;
pMapInfo->memSize=pMem->dwSize;
PushEntryList(&lstMapInfo, &pMapInfo->link);
DebugPrint("Map physical 0x%x to virtual 0x%x, size %u", \
pMem->pvAddr, pvu, pMem->dwSize);
RtlCopyMemory(pSysBuf, &pvu, sizeof(PVOID));
irp->IoStatus.Information=sizeof(PVOID);
}
else
{
//allocate mdl error, unmap the mapped physical memory
MmUnmapIoSpace(pvk, pMem->dwSize);
irp->IoStatus.Status=STATUS_INSUFFICIENT_RESOURCES;
}
}
else
irp->IoStatus.Status=STATUS_INSUFFICIENT_RESOURCES;
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_UNMAP:
DebugPrintMsg("IOCTL_PHYMEM_UNMAP");
if (dwInBufLen==sizeof(PHYMEM_MEM))
{
PMAPINFO pMapInfo;
PSINGLE_LIST_ENTRY pLink, pPrevLink;
//initialize to head
pPrevLink=pLink=lstMapInfo.Next;
while(pLink)
{
pMapInfo=CONTAINING_RECORD(pLink, MAPINFO, link);
if (pMapInfo->pvu==pMem->pvAddr)
{
if (pMapInfo->memSize==pMem->dwSize)
{
//free mdl, unmap mapped memory
MmUnmapLockedPages(pMapInfo->pvu, pMapInfo->pMdl);
IoFreeMdl(pMapInfo->pMdl);
MmUnmapIoSpace(pMapInfo->pvk, pMapInfo->memSize);
DebugPrint("Unmap virtual address 0x%x, size %u",\
pMapInfo->pvu, pMapInfo->memSize);
//delete matched element from the list
if (pLink==lstMapInfo.Next)
lstMapInfo.Next=pLink->Next; //delete head elememt
else
pPrevLink->Next=pLink->Next;
ExFreePool(pMapInfo);
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
}
pPrevLink=pLink;
pLink=pLink->Next;
}
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_GETPORT:
DebugPrintMsg("IOCTL_PHYMEM_GETPORT");
if (dwInBufLen==sizeof(PHYMEM_PORT) && dwOutBufLen==sizeof(ULONG))
{
irp->IoStatus.Information=sizeof(ULONG);
if (pPort->dwSize==1)
{
*(PULONG)pSysBuf=(ULONG)READ_PORT_UCHAR((PUCHAR)pPort->dwPort);
}
else if (pPort->dwSize==2)
{
*(PULONG)pSysBuf=(ULONG)READ_PORT_USHORT((PUSHORT)pPort->dwPort);
}
else if (pPort->dwSize==4)
{
*(PULONG)pSysBuf=READ_PORT_ULONG((PULONG)pPort->dwPort);
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_SETPORT:
DebugPrintMsg("IOCTL_PHYMEM_SETPORT");
if (dwInBufLen==sizeof(PHYMEM_PORT))
{
if (pPort->dwSize==1)
{
WRITE_PORT_UCHAR((PUCHAR)pPort->dwPort, (UCHAR)pPort->dwValue);
}
else if (pPort->dwSize==2)
{
WRITE_PORT_USHORT((PUSHORT)pPort->dwPort, (USHORT)pPort->dwValue);
}
else if (pPort->dwSize==4)
{
WRITE_PORT_ULONG((PULONG)pPort->dwPort, pPort->dwValue);
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_GETPCI:
DebugPrintMsg("IOCTL_PHYMEM_GETPCI");
//register offset + bytes to read cannnot exceed 256(pci config space limit)
if (dwInBufLen==sizeof(PHYMEM_PCI) &&
((pPci->dwRegOff + pPci->dwBytes)<=256) && (dwOutBufLen>=pPci->dwBytes))
{
irp->IoStatus.Status=ReadWriteConfig(irp, pPci, TRUE);
if (NT_SUCCESS(irp->IoStatus.Status))
{
irp->IoStatus.Information=pPci->dwBytes;
}
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_SETPCI:
DebugPrintMsg("IOCTL_PHYMEM_SETPCI");
//register offset + bytes to write cannnot exceed 256(pci config space limit)
//new values to write are stored in out buffer(strange but it works)
if (dwInBufLen==sizeof(PHYMEM_PCI) &&
((pPci->dwRegOff + pPci->dwBytes)<=256) && (dwOutBufLen>=pPci->dwBytes))
{
irp->IoStatus.Status=ReadWriteConfig(irp, pPci, FALSE);
if (NT_SUCCESS(irp->IoStatus.Status))
{
irp->IoStatus.Information=pPci->dwBytes;
}
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_SETISR:
DebugPrintMsg("IOCTL_PHYMEM_SETISR");
if (dwInBufLen==sizeof(PHYMEM_ISR))
{
//map user mode address to kernel address
PMDL pIsrMdl, pContextMdl;
PVOID isrAddr;
PVOID context;
if (!GetStoredIntVector(pIsr->nIntNo))
{
irp->IoStatus.Status=MapUserToKernel(pIsr->pIsrAddr, pIsr->dwIsrSize,
IoReadAccess, &pIsrMdl, &(PVOID)isrAddr);
if (NT_SUCCESS(irp->IoStatus.Status))
{
DebugPrint("Isr code: User 0x%x --> Kernel 0x%x", pIsr->pIsrAddr, isrAddr);
irp->IoStatus.Status=MapUserToKernel(pIsr->pContext, pIsr->dwContextLen,
IoModifyAccess, &pContextMdl, &context);
if (NT_SUCCESS(irp->IoStatus.Status))
{
PISRINFO pIsrInfo;
PUCHAR c;
DebugPrint("Isr context: User 0x%x --> Kernel 0x%x", pIsr->pContext, context);
//add info to link list
pIsrInfo=(PISRINFO)ExAllocatePool(NonPagedPool, sizeof(ISRINFO));
pIsrInfo->intNo=pIsr->nIntNo;
pIsrInfo->pIsrMdl=pIsrMdl;
pIsrInfo->pContextMdl=pContextMdl;
c=pIsrInfo->isrCode;
RtlZeroMemory(c, ISRCODE_LEN);
PushEntryList(&lstIsrInfo, &pIsrInfo->link);
HookIsr(pIsr->nIntNo, isrAddr, context, &pIsrInfo->intVect, c);
DebugPrint("Interrupt #%d hooked", pIsr->nIntNo);
}
else
{
MmUnlockPages(pIsrMdl);
IoFreeMdl(pIsrMdl);
irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
}
}
else
irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
}
else
irp->IoStatus.Status=STATUS_UNSUCCESSFUL; //isr already installed
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_CLRISR:
DebugPrintMsg("IOCTL_PHYMEM_CLRISR");
if (dwInBufLen==sizeof(UCHAR))
{
UCHAR nIntNo=*(UCHAR*)pSysBuf;
PINTVECT piv=GetStoredIntVector(nIntNo);
if (piv)
{
//restore system default isr
UnhookIsr(nIntNo, piv);
//remove isr info list entry
RemoveIsrInfo(nIntNo);
DebugPrint("Interrupt #%d unhooked", nIntNo);
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
case IOCTL_PHYMEM_PROCADDR:
DebugPrintMsg("IOCTL_PHYMEM_PROCADDR");
if (dwOutBufLen==8)
{
*(FARPROC*)pSysBuf=IoCreateDevice;
*(FARPROC*)(((BYTE*)pSysBuf)+4)=(FARPROC)READ_PORT_UCHAR;
irp->IoStatus.Information=8;
DebugPrint("NTOSKRNL.EXE, IoCreateDevice, 0x%x", IoCreateDevice);
DebugPrint("HAL.DLL, READ_PORT_UCHAR, 0x%x", READ_PORT_UCHAR);
}
break;
case IOCTL_PHYMEM_SYSCALL:
DebugPrintMsg("IOCTL_PHYMEM_SYSCALL");
if (dwInBufLen==sizeof(PHYMEM_SYSCALL))
{
//map user mode address to kernel address
PMDL pCodeMdl, pContextMdl;
PVOID codeAddr;
PVOID context;
//map code
irp->IoStatus.Status=MapUserToKernel(pSyscall->pCodeAddr, pSyscall->dwCodeSize,
IoReadAccess, &pCodeMdl, &(PVOID)codeAddr);
if (NT_SUCCESS(irp->IoStatus.Status))
{
DebugPrint("Syscall code: User 0x%x --> Kernel 0x%x", pSyscall->pCodeAddr, codeAddr);
//map data
irp->IoStatus.Status=MapUserToKernel(pSyscall->pContext, pSyscall->dwContextLen,
IoModifyAccess, &pContextMdl, &context);
if (NT_SUCCESS(irp->IoStatus.Status))
{
DebugPrint("Syscall context: User 0x%x --> Kernel 0x%x", pSyscall->pContext, context);
DebugPrintMsg("Syscall starts");
__asm { PUSH context };
__asm { CALL codeAddr };
DebugPrintMsg("Syscall ended");
//free resources
MmUnlockPages(pCodeMdl);
IoFreeMdl(pCodeMdl);
MmUnlockPages(pContextMdl);
IoFreeMdl(pContextMdl);
}
else
{
MmUnlockPages(pCodeMdl);
IoFreeMdl(pCodeMdl);
irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
}
}
else
irp->IoStatus.Status=STATUS_UNSUCCESSFUL;
}
else
irp->IoStatus.Status=STATUS_INVALID_PARAMETER;
break;
default:
DebugPrintMsg("Error: Unknown IO CONTROL CODE");
break;
}
break;
}
ntStatus=irp->IoStatus.Status;
IoCompleteRequest(irp, IO_NO_INCREMENT);
DebugPrintMsg("Leaving PhyMemIoCtl");
return ntStatus;
}
/*++
Driver Unload routine
--*/
VOID PhyMemUnload(IN PDRIVER_OBJECT dro)
{
UNICODE_STRING DeviceLinkU;
NTSTATUS ntStatus;
PMAPINFO pMapInfo;
PISRINFO pIsrInfo;
PSINGLE_LIST_ENTRY pLink;
DebugPrintMsg("Entering PhyMemUnload");
//free resources
pLink=PopEntryList(&lstMapInfo);
while(pLink)
{
pMapInfo=CONTAINING_RECORD(pLink, MAPINFO, link);
DebugPrint("Unmap virtual address 0x%x, size %u",\
pMapInfo->pvu, pMapInfo->memSize);
MmUnmapLockedPages(pMapInfo->pvu, pMapInfo->pMdl);
IoFreeMdl(pMapInfo->pMdl);
MmUnmapIoSpace(pMapInfo->pvk, pMapInfo->memSize);
ExFreePool(pMapInfo);
pLink=PopEntryList(&lstMapInfo);
}
pLink=PopEntryList(&lstIsrInfo);
while(pLink)
{
pIsrInfo=CONTAINING_RECORD(pLink, ISRINFO, link);
//restore system default isr
UnhookIsr(pIsrInfo->intNo, &pIsrInfo->intVect);
//free mdl
MmUnlockPages(pIsrInfo->pIsrMdl);
IoFreeMdl(pIsrInfo->pIsrMdl);
MmUnlockPages(pIsrInfo->pContextMdl);
IoFreeMdl(pIsrInfo->pContextMdl);
ExFreePool(pIsrInfo);
pLink=PopEntryList(&lstIsrInfo);
}
if (busInterface && busInterface->InterfaceDereference)
{
(*busInterface->InterfaceDereference)(busInterface->Context);
ExFreePool(busInterface);
}
RtlInitUnicodeString(&DeviceLinkU, L"\\DosDevices\\PhyMem");
ntStatus=IoDeleteSymbolicLink(&DeviceLinkU);
if (NT_SUCCESS(ntStatus))
{
IoDeleteDevice(dro->DeviceObject);
}
else
{
DebugPrintMsg("Error: IoDeleteSymbolicLink failed");
}
DebugPrintMsg("Leaving PhyMemUnload");
DebugPrintClose();
}
//prepare to get bus interface
static NTSTATUS PreGetBus()
{
NTSTATUS ntStatus;
UNICODE_STRING pcifidoNameU;
ntStatus=STATUS_SUCCESS;
//get pci filter driver do
if (pcifido==NULL)
{
RtlInitUnicodeString(&pcifidoNameU, L"\\Device\\PhyMemPCIFilter");
ntStatus=IoGetDeviceObjectPointer(&pcifidoNameU,
FILE_READ_DATA|FILE_WRITE_DATA,
&pcifo,
&pcifido);
if (NT_SUCCESS(ntStatus))
{
DebugPrint("Got pci filter device object: 0x%x", pcifido);
}
else
{
DebugPrint("Get pci filter device object failed, code=0x%x", ntStatus);
return STATUS_UNSUCCESSFUL;
}
}
//get bus interface
if (busInterface->ReadConfig==NULL)
{
ntStatus=GetBusInterface(pcifido, busInterface);
if (NT_SUCCESS(ntStatus))
{
DebugPrint("Got pci bus filter driver interface");
}
else
{
DebugPrint("Get pci bus driver interface failed, code=0x%x", ntStatus);
}
}
return ntStatus;
}
//read pci configuration
static NTSTATUS ReadWriteConfig(PIRP irp, PPHYMEM_PCI pPci, BOOLEAN isRead)
{
NTSTATUS ntStatus;
//get pci filter driver interface
ntStatus=PreGetBus();
if (NT_SUCCESS(ntStatus))
{
PVOID pValue;
//get out buffer kernel address
pValue=(PVOID)MmGetSystemAddressForMdlSafe(irp->MdlAddress,
NormalPagePriority);
if (pValue)
{
PCI_SLOT_NUMBER slot;
ULONG ulRet;
slot.u.AsULONG=0;
slot.u.bits.DeviceNumber=pPci->dwDevNum;
slot.u.bits.FunctionNumber=pPci->dwFuncNum;
if (isRead)
ulRet=(*busInterface->ReadConfig)(busInterface->Context, //context
(UCHAR)pPci->dwBusNum, //busoffset
slot.u.AsULONG, //slot
pValue, //buffer
pPci->dwRegOff, //offset
pPci->dwBytes); //length
else
ulRet=(*busInterface->WriteConfig)(busInterface->Context, //context
(UCHAR)pPci->dwBusNum, //busoffset
slot.u.AsULONG, //slot
pValue, //buffer
pPci->dwRegOff, //offset
pPci->dwBytes); //length
if (ulRet==pPci->dwBytes)
{
ntStatus=STATUS_SUCCESS;
if (isRead)
DebugPrint("Read %d bytes from pci config space", ulRet);
else
DebugPrint("Write %d bytes to pci config space", ulRet);
}
else
ntStatus=STATUS_UNSUCCESSFUL;
}
else
ntStatus=STATUS_INVALID_PARAMETER;
}
return ntStatus;
}
//map user mode address to kernel address
static NTSTATUS MapUserToKernel(PVOID pUser, ULONG len, LOCK_OPERATION lo, PMDL *ppMdl, PVOID *ppSysAddr)
{
NTSTATUS ntStatus=STATUS_UNSUCCESSFUL;
PMDL pMdl;
PVOID pSysAddr;
//allocate mdl, probe user mode address
pMdl=IoAllocateMdl(pUser, len, FALSE, FALSE, NULL);
if (pMdl)
{
__try
{
MmProbeAndLockPages(pMdl, UserMode, lo);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
ntStatus=GetExceptionCode();
DebugPrint("Exception while locking isr code 0x%x", ntStatus);
IoFreeMdl(pMdl);
pMdl=NULL;
}
}
else
ntStatus=STATUS_INSUFFICIENT_RESOURCES;
//map isr code to kernel
if (pMdl)
{
pSysAddr=MmGetSystemAddressForMdlSafe(pMdl, NormalPagePriority);
if(pSysAddr)
{
ntStatus=STATUS_SUCCESS;
*ppMdl=pMdl;
*ppSysAddr=pSysAddr;
}
else
{
ntStatus=STATUS_INSUFFICIENT_RESOURCES;
DebugPrintMsg("MmGetSystemAddressForMdlSafe error");
MmUnlockPages(pMdl);
IoFreeMdl(pMdl);
}
}
return ntStatus;
}
//return the stored 8 bytes idt table entry for this interrupt
static PINTVECT GetStoredIntVector(UCHAR nIntNo)
{
PINTVECT pi=NULL;
PISRINFO pIsrInfo;
PSINGLE_LIST_ENTRY pLink;
pLink=lstIsrInfo.Next;
while(pLink)
{
pIsrInfo=CONTAINING_RECORD(pLink, ISRINFO, link);
if (pIsrInfo->intNo==nIntNo)
{
pi=&pIsrInfo->intVect;
break;
}
pLink=pLink->Next;
}
return pi;
}
//remove isr info list entry
static VOID RemoveIsrInfo(UCHAR nIntNo)
{
PISRINFO pIsrInfo;
PSINGLE_LIST_ENTRY pLink, pPrevLink;
//initialize to head
pPrevLink=pLink=lstIsrInfo.Next;
while(pLink)
{
pIsrInfo=CONTAINING_RECORD(pLink, ISRINFO, link);
if (pIsrInfo->intNo==nIntNo)
{
//free mdl
MmUnlockPages(pIsrInfo->pIsrMdl);
IoFreeMdl(pIsrInfo->pIsrMdl);
MmUnlockPages(pIsrInfo->pContextMdl);
IoFreeMdl(pIsrInfo->pContextMdl);
//delete matched element from the list
if (pLink==lstIsrInfo.Next)
lstIsrInfo.Next=pLink->Next; //delete head elememt
else
pPrevLink->Next=pLink->Next;
ExFreePool(pIsrInfo);
break;
}
pPrevLink=pLink;
pLink=pLink->Next;
}
}