#include
//鍵盤過(guò)濾驅(qū)動(dòng)
//IoDriverObjectType 是全局變量,但是頭文件中沒(méi)有,所以在這里聲明
extern POBJECT_TYPE *IoDriverObjectType;
//KbdClass 驅(qū)動(dòng)的名字
#define KBD_DRIVER_NAME L"\\Driver\\Kbdclass"
//ObReferenceObjectByName 未導(dǎo)出文檔,先聲明
NTSTATUS ObReferenceObjectByName(
PUNICODE_STRING ObjectName,
ULONG Attributes,
PACCESS_STATE AccessState,
ACCESS_MASK DesiredAccess,
POBJECT_TYPE ObjectType,
KPROCESSOR_MODE AccessMode,
PVOID ParseContext,
PVOID *Object
);
//全局變量
ULONG gC2pKeyCount = 0;
PDRIVER_OBJECT gDriverObject = NULL;
//設(shè)備擴(kuò)展, 專門定義的一個(gè)結(jié)構(gòu)
typedef struct _C2P_DEV_EXT{
//這個(gè)結(jié)構(gòu)的大小
ULONG NodeSize;
//過(guò)濾設(shè)備對(duì)象
PDEVICE_OBJECT pFilterDeviceObject;
//綁定時(shí)的設(shè)備對(duì)象
PDEVICE_OBJECT TargetDeviceObject;
//綁定前底層設(shè)備對(duì)象
PDEVICE_OBJECT LowerDeviceObject;
}C2P_DEV_EXT, *PC2P_DEV_EXT;
void c2pUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS c2pDispatchGeneral(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS c2pPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS c2pPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp);
NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context);
NTSTATUS c2pAttachDevices(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath);
NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt, IN PDEVICE_OBJECT pFilterDeviceObject, IN PDEVICE_OBJECT pTargetDeviceObject, IN PDEVICE_OBJECT pLowerDeviceObject);
//驅(qū)動(dòng)入口
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){
ULONG i;
NTSTATUS status;
KdPrint(("misaka: entering driverentry\n"));
//填寫所有的分發(fā)函數(shù)指針
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++){
DriverObject->MajorFunction[i] = c2pDispatchGeneral;
DbgPrint("misaka: test %d..\r\n",i);
}
//單獨(dú)填寫一個(gè)讀分發(fā)函數(shù),因?yàn)橹匾氖亲x取按鍵的信息,其他都不重要
DriverObject->MajorFunction[IRP_MJ_READ] = c2pDispatchRead;
//單獨(dú)填寫一個(gè) IRP_MJ_POWER 函數(shù),這是因?yàn)檫@類請(qǐng)求中間要調(diào)用一個(gè) PoCallDriver 和 PoStartNextPowerIrp 比較特殊
DriverObject->MajorFunction[IRP_MJ_POWER] = c2pPower;
//我們想知道什么時(shí)候綁定過(guò)的設(shè)備被卸載了(比如從機(jī)器上拔掉),專門寫一個(gè) PNP(即插即用)分發(fā)函數(shù)
DriverObject->MajorFunction[IRP_MJ_PNP] = c2pPnP;
//卸載函數(shù)
DriverObject->DriverUnload = c2pUnload;
//綁定所有的鍵盤設(shè)備
status = c2pAttachDevices(DriverObject, RegistryPath);
return status;
}
//卸載函數(shù)
#define ?DELAY_ONE_MICROSECOND ?(-10)
#define ?DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define ?DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)
void c2pUnload(IN PDRIVER_OBJECT DriverObject){
PDEVICE_OBJECT DeviceObject;
PDEVICE_OBJECT OldDeviceObject;
PC2P_DEV_EXT devExt;
LARGE_INTEGER lDelay;
PRKTHREAD CurrentThread;
lDelay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND);
CurrentThread = KeGetCurrentThread();
//把當(dāng)前線程設(shè)置為低實(shí)時(shí)模式,以便盡可能少的影響其他程序
KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY);
UNREFERENCED_PARAMETER(DriverObject);
KdPrint(("misaka: driverentry unloading...\n"));
//遍歷所有設(shè)備并一律解除綁定,刪除所有的設(shè)備
DeviceObject = DriverObject->DeviceObject;
while (DeviceObject){
PC2P_DEV_EXT devExt;
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
//只解除綁定
IoDetachDevice(devExt->TargetDeviceObject);
devExt->TargetDeviceObject = NULL;
DbgPrint("misaka: detach finished\r\n");
DeviceObject = DeviceObject->NextDevice;
}
DbgPrint("misaka: ------------------------------------ %d.\r\n", gC2pKeyCount);
//gC2pKeyCount全局變量,等待請(qǐng)求完成才卸載
while (gC2pKeyCount){
KeDelayExecutionThread(KernelMode, FALSE, &lDelay);
}
//刪除過(guò)濾設(shè)備
DeviceObject = DriverObject->DeviceObject;
if (DeviceObject == NULL){
DbgPrint("misaka: DeviceObject and null\r\n");
return;
}
while (DeviceObject){
PC2P_DEV_EXT devExt;
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
IoDeleteDevice(devExt->pFilterDeviceObject);
devExt->pFilterDeviceObject = NULL;
DbgPrint("misaka: unload filter device object success\r\n");
DeviceObject = DeviceObject->NextDevice;
}
//這個(gè)是產(chǎn)出驅(qū)動(dòng)對(duì)象的,但是好像沒(méi)有效果,只要停止驅(qū)動(dòng)之后就不能再次啟動(dòng)了.可能是驅(qū)動(dòng)沒(méi)有卸載干凈
//但是如果照著教程寫的話,如果停止直接藍(lán)屏...
//目前的情況是在win7 64位系統(tǒng)中啟動(dòng)驅(qū)動(dòng)后可以獲取按鍵消息...
//IoDeleteDevice(pDeviceObject);
//devExt->pFilterDeviceObject = NULL;
//DbgPrint("misaka: detach finished\r\n");
//講道理這里應(yīng)該要?jiǎng)h除設(shè)備對(duì)象了
DbgPrint("misaka: bye ,driver unload successfully.\r\n");
return;
}
//鍵盤請(qǐng)求的處理 - 通常處理 - 直接跳過(guò),發(fā)送到真實(shí)設(shè)備對(duì)象上
NTSTATUS c2pDispatchGeneral(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){
KdPrint(("misaka: other diapatch!\n"));
IoSkipCurrentIrpStackLocation(Irp);
return IoCallDriver(((PC2P_DEV_EXT)DeviceObject->DeviceExtension)->LowerDeviceObject, Irp);
}
//鍵盤請(qǐng)求的處理 - 讀請(qǐng)求
NTSTATUS c2pDispatchRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){
NTSTATUS status = STATUS_SUCCESS;
PC2P_DEV_EXT devExt;
PIO_STACK_LOCATION currentIrpStack;
KEVENT waitEvent;
KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);
if (Irp->CurrentLocation == 1){
ULONG ReturnedInformation = 0;
KdPrint(("misaka: dispatch encountered bogus current location\n"));
status = STATUS_INVALID_DEVICE_REQUEST;
Irp->IoStatus.Status = status;
Irp->IoStatus.Information = ReturnedInformation;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return (status);
}
//全局變量計(jì)數(shù)器+1
gC2pKeyCount++;
//得到設(shè)備擴(kuò)展,獲得下一個(gè)設(shè)備的指針
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
//設(shè)置回掉函數(shù)并把IRP傳遞下去,讀處理結(jié)束,等待讀請(qǐng)求完成
currentIrpStack = IoGetCurrentIrpStackLocation(Irp);
IoCopyCurrentIrpStackLocationToNext(Irp);
IoSetCompletionRoutine(Irp, c2pReadComplete, DeviceObject, TRUE, TRUE, TRUE);
DbgPrint("read : number = %d\r\n", gC2pKeyCount);
return IoCallDriver(devExt->LowerDeviceObject, Irp);
}
//鍵盤請(qǐng)求的處理 - 電源相關(guān)請(qǐng)求
NTSTATUS c2pPower(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){
KdPrint(("misaka: Power\n"));
PC2P_DEV_EXT devExt;
devExt = (PC2P_DEV_EXT)DeviceObject->DeviceExtension;
PoStartNextPowerIrp(Irp);
IoSkipCurrentIrpStackLocation(Irp);
return PoCallDriver(devExt->LowerDeviceObject, Irp);
}
//鍵盤請(qǐng)求的處理 - 檔設(shè)備被拔出時(shí),解除綁定,并刪除過(guò)濾設(shè)備
NTSTATUS c2pPnP(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp){
PC2P_DEV_EXT devExt;
PIO_STACK_LOCATION irpStack;
NTSTATUS status = STATUS_SUCCESS;
//獲得真實(shí)設(shè)備
devExt = (PC2P_DEV_EXT)(DeviceObject->DeviceExtension);
irpStack = IoGetCurrentIrpStackLocation(Irp);
switch (irpStack->MinorFunction){
case IRP_MN_REMOVE_DEVICE:
KdPrint(("misaka: IRP_MN_REMOVE_DEVICE\n"));
//先把請(qǐng)求下發(fā)
IoSkipCurrentIrpStackLocation(Irp);
IoCallDriver(devExt->LowerDeviceObject, Irp);
//然后解除綁定
IoDetachDevice(devExt->LowerDeviceObject);
//刪除生成的虛擬設(shè)備
IoDeleteDevice(DeviceObject);
status = STATUS_SUCCESS;
break;
default:
//其他類型的IRP,全部直接下發(fā)
IoSkipCurrentIrpStackLocation(Irp);
status = IoCallDriver(devExt->LowerDeviceObject, Irp);
}
return status;
}
//讀請(qǐng)求完成后的回掉函數(shù)
NTSTATUS c2pReadComplete(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context){
PIO_STACK_LOCATION IrpSp;
ULONG buf_len = 0;
PUCHAR buf = NULL;
size_t i;
IrpSp = IoGetCurrentIrpStackLocation(Irp);
//如果請(qǐng)求成功執(zhí)行(如果失敗則沒(méi)有獲取的意義了)
if (NT_SUCCESS(Irp->IoStatus.Status)){
//獲得讀請(qǐng)求完成后的輸出緩沖區(qū)
buf = Irp->AssociatedIrp.SystemBuffer;
//獲得這個(gè)緩沖區(qū)的長(zhǎng)度,一般來(lái)說(shuō),不管返回值有多長(zhǎng)都保存在 Information 中
buf_len = (ULONG)Irp->IoStatus.Information;
//這里可以進(jìn)一步處理,這里只是簡(jiǎn)單的打印出所有的掃描碼
for (i = 0; i < buf_len; ++i){
DbgPrint("misaka: read %2x\r\n", buf[i]);
}
}
gC2pKeyCount--;
if (Irp->PendingReturned){
IoMarkIrpPending(Irp);
}
DbgPrint("call : number = %d\r\n", gC2pKeyCount);
return Irp->IoStatus.Status;
}
//打開(kāi)驅(qū)動(dòng)對(duì)象 KbdClass,綁定其下的所有設(shè)備
NTSTATUS c2pAttachDevices(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){
NTSTATUS status = 0;
UNICODE_STRING uniNtNameString;
PC2P_DEV_EXT devExt;
PDEVICE_OBJECT pFilterDeviceObject = NULL;
PDEVICE_OBJECT pTargetDeviceObject = NULL;
PDEVICE_OBJECT pLowerDeviceObject = NULL;
PDRIVER_OBJECT KbdDriverObject = NULL;
KdPrint(("misaka:my attach\n"));
//初始化字符串,就是KbdClass驅(qū)動(dòng)的名字
RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);
//打開(kāi)驅(qū)動(dòng)對(duì)象
status = ObReferenceObjectByName(
&uniNtNameString,
OBJ_CASE_INSENSITIVE,
NULL,
0,
*IoDriverObjectType,
KernelMode,
NULL,
(PVOID*)&KbdDriverObject
);
//如果打開(kāi)失敗直接返回
if (!NT_SUCCESS(status)){
KdPrint(("misaka:couldn't get the device object\n"));
return (status);
} else{
//調(diào)用 ObReferenceObjectByName 對(duì)導(dǎo)致對(duì)驅(qū)動(dòng)對(duì)象的引用計(jì)數(shù)增加,這里進(jìn)行解引用
//改: 應(yīng)該是打開(kāi)設(shè)備對(duì)象的指針,而不是驅(qū)動(dòng)對(duì)象
ObDereferenceObject(KbdDriverObject);
DbgPrint("misaka: open filter driver ok\r\n");
}
//設(shè)備鏈中的第一個(gè)設(shè)備
pTargetDeviceObject = KbdDriverObject->DeviceObject;
//遍歷設(shè)備鏈
while (pTargetDeviceObject){
//生成一個(gè)過(guò)濾設(shè)備,也就是對(duì)所有設(shè)備創(chuàng)建過(guò)濾設(shè)備
status = IoCreateDevice(
IN DriverObject,
IN sizeof(PC2P_DEV_EXT),
IN NULL,
IN pTargetDeviceObject->DeviceType,
IN pTargetDeviceObject->Characteristics,
IN FALSE,
OUT &pFilterDeviceObject
);
//如果創(chuàng)建過(guò)濾設(shè)備失敗,直接退出
if (!NT_SUCCESS(status)){
KdPrint(("misaka: couldn't create the filter device object\n"));
return (status);
}
DbgPrint("misaka: create filter driver ok\r\n");
//綁定 pLowerDeviceObject 是綁定之后得到的下一個(gè)設(shè)備(真實(shí)的設(shè)備)
pLowerDeviceObject = IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject);
//如果綁定失敗則放棄之前的操作,退出
if (!pLowerDeviceObject){
KdPrint(("misaka: couldn't attach to device object\n"));
IoDeleteDevice(pFilterDeviceObject);
pFilterDeviceObject = NULL;
return (status);
}
DbgPrint("misaka: attach filter driver ok\r\n");
//過(guò)濾設(shè)備擴(kuò)展 保存著目標(biāo)設(shè)備對(duì)象和真實(shí)設(shè)備對(duì)象的指針
devExt = (PC2P_DEV_EXT)(pFilterDeviceObject->DeviceExtension);
c2pDevExtInit(
devExt,
pFilterDeviceObject,
pTargetDeviceObject,
pLowerDeviceObject
);
//
pFilterDeviceObject->DeviceType = pLowerDeviceObject->DeviceType;
pFilterDeviceObject->Characteristics = pLowerDeviceObject->Characteristics;
pFilterDeviceObject->StackSize = pLowerDeviceObject->StackSize + 1;
pFilterDeviceObject->Flags |= pLowerDeviceObject->Flags & (DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE);
//移動(dòng)到下一個(gè)設(shè)備,繼續(xù)遍歷
pTargetDeviceObject = pTargetDeviceObject->NextDevice;
}
return status;
}
//c2p驅(qū)動(dòng)擴(kuò)展設(shè)置函數(shù)
NTSTATUS c2pDevExtInit(IN PC2P_DEV_EXT devExt, IN PDEVICE_OBJECT pFilterDeviceObject, IN PDEVICE_OBJECT pTargetDeviceObject, IN PDEVICE_OBJECT pLowerDeviceObject){
memset(devExt, 0, sizeof(C2P_DEV_EXT));
devExt->NodeSize = sizeof(C2P_DEV_EXT);
devExt->pFilterDeviceObject = pFilterDeviceObject;
devExt->TargetDeviceObject = pTargetDeviceObject;
devExt->LowerDeviceObject = pLowerDeviceObject;
return (STATUS_SUCCESS);
}