📄 inp.c
字号:
void InpIOAPICConnection(unsigned long ** MappedVirtualVariable)
{
PHYSICAL_ADDRESS IOAPIC_AREA; // i/o apic mapped pointer
//
// Connect physical memory 0xfec00000 to [MappedVirtualVariable]
//
IOAPIC_AREA = RtlConvertLongToLargeInteger(0xFEC00000);
*MappedVirtualVariable = MmMapIoSpace(IOAPIC_AREA, 0x20, MmNonCached);
}
void InpIOAPICDisconnection(unsigned long ** MappedVirtualVariable)
{
MmUnmapIoSpace(*MappedVirtualVariable, 0x20);
}
ULONG InpGetKeyboardInterruptVector(void)
{
ULONG ReturnValue = 0;
// IOREGSEL writing
IOAPICGate[0] = 0x10 + 2 * 1; // 0x10 + 2 * IRQ, Keyboard's irq is 1
// read IOWIN
ReturnValue = IOAPICGate[4] & 0xFF;
//
// Getting Hardware IRQL to corresponding to the IRQ 1
// using i8042prt driver's Interrupt Object
kKeyboardHardwareIrql = (ULONG)GetI8042PrtInterruptObject()->Irql;
if (!kKeyboardHardwareIrql)
kKeyboardHardwareIrql = 0x8; // default on single-processor x86 family
DbgPrint("Keyboard Hardware IRQL :: 0x%x\n", kKeyboardHardwareIrql);
if (!ReturnValue)
ReturnValue = 0x93; // default ps/2 keyboard vector on wintelXP
return ReturnValue;
}
PKINTERRUPT GetI8042PrtInterruptObject(void)
{
PDEVICE_OBJECT pDeviceObject = NULL; // Keyboard DeviceObject
PFILE_OBJECT fileObject;
UNICODE_STRING keyName;
PPORT_KEYBOARD_EXTENSION KeyboardExtension;
PKINTERRUPT ReturnValue = NULL;
RtlInitUnicodeString( &keyName, NT_KEYBOARD_NAME0 );
// Getting the DeviceObject top-of-the-stack of the kbdclass device
IoGetDeviceObjectPointer(&keyName,
FILE_READ_ATTRIBUTES,
&fileObject,
&pDeviceObject);
// if fails
if( !pDeviceObject )
{
DbgPrint("IoGetDeviceObjectPointer Fail.");
return NULL;
}
else
DbgPrint("Top Object : %x\n", pDeviceObject);
DbgPrint("Tracking %x \t/Driver/i8042prt\n", ((PR_DEVOBJ_EXTENSION)pDeviceObject->DeviceObjectExtension)->AttachedTo);
// Tracking the DeviceStack
//
//
// If it is not a i8042prt
while( pDeviceObject->DeviceType != FILE_DEVICE_8042_PORT )
{
// go to the lower level object
if (((PR_DEVOBJ_EXTENSION)pDeviceObject->DeviceObjectExtension)->AttachedTo)
pDeviceObject = ((PR_DEVOBJ_EXTENSION)pDeviceObject->DeviceObjectExtension)->AttachedTo;
else // here is lowest-level and couldn't find i8042prt
return NULL;
}
//
// pDeviceObject == i8042prt's DeviceObject
//
ReturnValue = (PKINTERRUPT)((PPORT_KEYBOARD_EXTENSION)pDeviceObject->DeviceExtension)->InterruptObject;
DbgPrint("i8042prt.sys->Interrupt Object :: 0x%p", ReturnValue);
return ReturnValue;
}
void Initialization(VOID (*FunctionPointer)(IN PKDPC, IN PVOID, IN PVOID, IN PVOID))
{
/*
*
* Multi-Processor Consideration ::
*
* Each processor has it's own IDT.
*
*/
CCHAR i;
long currentProcessor;
PKDPC pkDpc;
KIRQL oldIrql, currentIrql;
currentIrql = KeGetCurrentIrql();
if (currentIrql < DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL, &oldIrql);
InterlockedAnd(&allProcessorDone, 0);
pkDpc = (PKDPC)ExAllocatePoolWithTag(NonPagedPool, KeNumberProcessors * sizeof(KDPC), (ULONG)' pni');
if (!pkDpc)
{
DbgPrint("Insufficient Resource error\n");
return;
}
currentProcessor = KeGetCurrentProcessorNumber();
for (i = 0; i < KeNumberProcessors; i++)
{
KeInitializeDpc(&pkDpc[i],
FunctionPointer,
NULL);
KeSetTargetProcessorDpc(&pkDpc[i], i);
KeInsertQueueDpc(&pkDpc[i], NULL, NULL);
}
// wait for all of the processor's hooking initialization.
while(InterlockedCompareExchange(&allProcessorDone, KeNumberProcessors - 1, KeNumberProcessors - 1) != KeNumberProcessors - 1)
{
_asm pause;
}
if (currentIrql < DISPATCH_LEVEL)
KeLowerIrql(oldIrql);
if (pkDpc)
{
ExFreePool(pkDpc);
pkDpc = NULL;
}
}
void MPInitializationThread(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
unsigned long i = KeGetCurrentProcessorNumber();
unsigned char buffer[6];
unsigned int * IdtrBaseAddress = (unsigned int *)&buffer[2]; // Idtr->Base
unsigned short * IdtrLimit = (unsigned short *)&buffer[0];
PIdtEntry_t IdtEntry;
_asm sidt buffer;
IdtEntry=(PIdtEntry_t)*IdtrBaseAddress; // Get a base address of idt
OldHandler[i] = ((unsigned int)IdtEntry[0xD].OffsetHigh<<16U)|
(IdtEntry[0xD].OffsetLow);
_asm nop;
_asm nop;
_asm nop;
_asm cli;
IdtEntry[0xD].OffsetLow=(unsigned short)NewHandler;
IdtEntry[0xD].OffsetHigh=(unsigned short)((unsigned int)NewHandler>>16);
*IdtrLimit = 0xFF;// 0 to 31 are allowed.
//*IdtrLimit = (8 * n - 1);
_asm lidt buffer;
_asm sti;
InterlockedIncrement(&allProcessorDone);
DbgPrint("Processor [%x] :: Complete.\n", allProcessorDone);
}
void MPDisabledThread(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2)
{
unsigned long i = KeGetCurrentProcessorNumber();
unsigned char buffer[6];
unsigned int * IdtrBaseAddress = (unsigned int *)&buffer[2]; // Idtr->Base
unsigned short * IdtrLimit = (unsigned short *)&buffer[0];
PIdtEntry_t IdtEntry;
_asm sidt buffer;
IdtEntry=(PIdtEntry_t)*IdtrBaseAddress; // Get a base address of idt
_asm cli;
*IdtrLimit = 0xFFFF;
_asm lidt buffer;
IdtEntry[0xD].OffsetLow=(unsigned short)OldHandler[i];
IdtEntry[0xD].OffsetHigh=(unsigned short)((unsigned int)OldHandler[i]>>16);
_asm sti;
InterlockedIncrement(&allProcessorDone);
}
/*
*
* Driver Template
*
*/
VOID DrvUnload(IN PDRIVER_OBJECT pDriverObject)
{
PDEVICE_OBJECT pDeviceObject;
UNICODE_STRING uniWin32NameString;
Initialization(MPDisabledThread);
InpIOAPICDisconnection(&IOAPICGate);
if (OldHandler)
ExFreePool(OldHandler);
if (pEvent)
{
ObDereferenceObject(pEvent); // delete event reference
pEvent = NULL;
}
pDeviceObject = pDriverObject->DeviceObject;
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
IoDeleteSymbolicLink( &uniWin32NameString );
IoDeleteDevice( pDriverObject->DeviceObject );
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING RegistryPath)
{
PDEVICE_OBJECT pDeviceObject = NULL;
NTSTATUS ntStatus;
UNICODE_STRING uniNtNameString, uniWin32NameString;
int i;
KIRQL testIrql;
RtlInitUnicodeString( &uniNtNameString, NT_DEVICE_NAME );
ntStatus = IoCreateDevice (
pDriverObject,
0, // DeviceExtensionSize
&uniNtNameString,
FILE_DEVICE_UNKNOWN, //
0, // No standard device characteristics
FALSE, // not exclusive device
&pDeviceObject
);
if( !NT_SUCCESS(ntStatus) )
{
return ntStatus;
}
// create dispatch points for create/open, close, unload
pDriverObject->DriverUnload = DrvUnload;
RtlInitUnicodeString( &uniWin32NameString, DOS_DEVICE_NAME );
ntStatus = IoCreateSymbolicLink( &uniWin32NameString, &uniNtNameString );
if (!NT_SUCCESS(ntStatus))
{
IoDeleteDevice( pDriverObject->DeviceObject );
}
for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
pDriverObject->MajorFunction[i] = IoDispatch;
pDriverObject->MajorFunction[IRP_MJ_READ] =
pDriverObject->MajorFunction[IRP_MJ_WRITE] = IoReadWrite;
pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IoDeviceControl;
i = KeNumberProcessors * sizeof(PULONG);
OldHandler = (PULONG)ExAllocatePoolWithTag(NonPagedPool, i, (ULONG)' pni');
RtlZeroMemory(OldHandler, i);
///// /////
// //
// Start!!! //
// //
///// /////
InpIOAPICConnection(&IOAPICGate);
KeyboardInterruptVector = InpGetKeyboardInterruptVector();
Initialization(MPInitializationThread);
return STATUS_SUCCESS;
} //DriverEntry
NTSTATUS IoDispatch(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
NTSTATUS iStatus = STATUS_SUCCESS;
pIrp->IoStatus.Status = iStatus;
pIrp->IoStatus.Information = 0;
IoCompleteRequest( pIrp, IO_NO_INCREMENT );
return iStatus;
}
NTSTATUS IoDeviceControl(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
NTSTATUS iStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION pStack;
ULONG iTransfered = 0;
HANDLE hEvent;
pStack = IoGetCurrentIrpStackLocation(pIrp);
switch( pStack->Parameters.DeviceIoControl.IoControlCode)
{
case IOCTL_REGISTER_EVENT:
hEvent = * (PHANDLE) pIrp->AssociatedIrp.SystemBuffer;
iStatus = ObReferenceObjectByHandle(hEvent, EVENT_MODIFY_STATE, *ExEventObjectType, pIrp->RequestorMode, (PVOID *)&pEvent, NULL);
break;
case IOCTL_REQUEST_DATA:
memcpy( (void *)pIrp->AssociatedIrp.SystemBuffer, (const void *)data, sizeof(char [2]));
iTransfered = sizeof(char [2]);
break;
default:
iStatus = STATUS_INVALID_PARAMETER;
break;
}
pIrp->IoStatus.Status = iStatus;
pIrp->IoStatus.Information = iTransfered;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return iStatus;
}
NTSTATUS IoReadWrite(IN PDEVICE_OBJECT pDeviceObject, IN PIRP pIrp)
{
NTSTATUS iStatus = STATUS_SUCCESS;
PIO_STACK_LOCATION pStack;
ULONG iTransfered = 0;
pStack = IoGetCurrentIrpStackLocation(pIrp);
pIrp->IoStatus.Status = iStatus;
pIrp->IoStatus.Information = iTransfered;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
return iStatus;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -