wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
阅读:1176回复:4

键盘过滤驱动

楼主#
更多 发布于:2008-04-13 22:57
请问一个键盘过滤驱动的问题
 

我参考Ctrl2cap做了一个键盘过滤驱动,总是出问题,请帮忙看一下。我只列重点的部分,太多不好看
入口代码
NTSTATUS DriverEntry( IN PDRIVER_OBJECT theDriverObject, IN PUNICODE_STRING theRegistryPath )
{
NTSTATUS status = STATUS_SUCCESS;
int i;
__try
{
DbgPrint(" DriverEntry... \n");

g_DriverObject.pDriverObj = theDriverObject;
for (i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++)
{
g_DriverObject.pDriverObj->MajorFunction = DispatchMajorFunction;
}
g_DriverObject.pDriverObj->DriverUnload = DriverUnload;
status = CreateDeviceAndLink(DEVICE_NAME,LINK_NAME);
。。。。。。
}

然后就是创建设备对象的代码,我创建了两个,一个是FILE_DEVICE_UNKNOWN,一个是FILE_DEVICE_KEYBOARD

//创建设备和符号
NTSTATUS CreateDeviceAndLink(PCWSTR DeviceName,PCWSTR LinkName)
{
NTSTATUS status = STATUS_SUCCESS;

CCHAR ntNameBuffer[64];
STRING ntNameString;
UNICODE_STRING ntUnicodeString;
__try
{
DbgPrint(" CreateDeviceAndLink …… \n");
// 创建、初始化设备对象
// 设备名称
RtlInitUnicodeString(&g_DriverObject.ustrDevName, DeviceName);
// 创建设备对象
status = IoCreateDevice(g_DriverObject.pDriverObj,
sizeof(DEVICE_EXTENSION), // 为设备扩展结构申请空间,
&g_DriverObject.ustrDevName,
FILE_DEVICE_UNKNOWN,
0,
FALSE,
&g_DriverObject.pDeviceObj);

if(!NT_SUCCESS(status))
{
DbgPrint(" CreateDevice Failed \n");
return status;
}

// 创建符号连接名称
// 符号连接名称
RtlInitUnicodeString(&g_DriverObject.ustrLinkName, LinkName);
// 创建关联
status = IoCreateSymbolicLink(&g_DriverObject.ustrLinkName, &g_DriverObject.ustrDevName);
if(!NT_SUCCESS(status))
{
DbgPrint(" CreateLink Failed \n");
IoDeleteDevice(g_DriverObject.pDeviceObj);
return status;
}

//创建键盘对象

sprintf( ntNameBuffer, "\\Device\\KeyboardClass0" );
RtlInitAnsiString( &ntNameString, ntNameBuffer );
RtlAnsiStringToUnicodeString( &ntUnicodeString, &ntNameString, TRUE );

status = IoCreateDevice( g_DriverObject.pDriverObj,
0,
NULL,
FILE_DEVICE_KEYBOARD,
0,
FALSE,
&g_DriverObject.pKBDDeviceObj );

if( !NT_SUCCESS(status) ) {

DbgPrint(("Ctrl2cap: Keyboard hook failed to create device!\n"));

RtlFreeUnicodeString( &ntUnicodeString );

return STATUS_SUCCESS;
}

//
// Keyboard uses buffered I/O so we must as well.
//

g_DriverObject.pKBDDeviceObj->Flags |= DO_BUFFERED_IO | DO_POWER_PAGABLE;
g_DriverObject.pKBDDeviceObj->Flags &= ~DO_DEVICE_INITIALIZING;

//
// Attach to the keyboard chain.
//

status = IoAttachDevice( g_DriverObject.pKBDDeviceObj, &ntUnicodeString, &g_DriverObject.pKbdTopOfStack );

if( !NT_SUCCESS(status) ) {

DbgPrint(("Ctrl2cap: Connect with keyboard failed!\n"));

IoDeleteDevice( g_DriverObject.pKBDDeviceObj );

RtlFreeUnicodeString( &ntUnicodeString );
}

RtlFreeUnicodeString( &ntUnicodeString );

DbgPrint(" CreateDeviceAndLink OK \n");
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
DbgPrint("Exception occured, caught in CreateDeviceAndLink(). Unknown error\n");
}
return status;
}
然后就是在这里,IoAttachDevice的时候,前面设置的DispatchMajorFunction函数被调用了,这个函数是这样的:
NTSTATUS DispatchMajorFunction(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
//这里需要对驱动对象进行区分
__try
{
PIO_STACK_LOCATION irpStack = NULL;
PIO_STACK_LOCATION nextIrpStack = NULL;
irpStack = IoGetCurrentIrpStackLocation(pIrp);
//键盘设备对象
if(pDevObj==g_DriverObject.pKBDDeviceObj)
{
pIrp->IoStatus.Status = STATUS_SUCCESS;
switch(irpStack->MajorFunction)
{
case IRP_MJ_READ:
nextIrpStack = IoGetNextIrpStackLocation(pIrp);
*nextIrpStack = *irpStack;

IoSetCompletionRoutine(pIrp, OnKbdReadComplete, pDevObj, TRUE, TRUE, TRUE );

// Return the results of the call to the keyboard class driver.
return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp);
default:
pIrp->CurrentLocation++;
pIrp->Tail.Overlay.CurrentStackLocation++;
// pass this onto whoever we stole it from...
return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp);
}
}
//默认的设备对象
else if(pDevObj==g_DriverObject.pDeviceObj)
{
switch(irpStack->MajorFunction)
{
case IRP_MJ_CREATE:
case IRP_MJ_CLOSE:
return DispatchCreateClose(pDevObj,pIrp);

case IRP_MJ_DEVICE_CONTROL:
return DispatchIoctl(pDevObj,pIrp);
}
}


// 完成请求
pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pIrp, IO_NO_INCREMENT);
}
__finally
{
DbgPrint("Exception occured, caught in DispatchMajorFunction(). Unknown error\n");
}
return STATUS_SUCCESS;
}
第一次调用到这个函数的时候执行了
default:
pIrp->CurrentLocation++;
pIrp->Tail.Overlay.CurrentStackLocation++;
// pass this onto whoever we stole it from...
return IoCallDriver(g_DriverObject.pKbdTopOfStack, pIrp);
这部分代码,然后就在IoCallDriver出错了~
以后每次到这个函数都会在调用IoCallDriver是出错。请问是哪儿的问题啊?
wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-04-14 09:15
用ctrl2cap的代码倒是不会出错,但是
status = IoAttachDevice( HookDeviceObject, &ntUnicodeString, &kbdDevice );
这样连接上以后如何删除呢?

VOID DriverUnload(PDRIVER_OBJECT pDriverObj)
{    
        IoDetachDevice(kbdDevice);
        IoDeleteDevice(HookDeviceObject);
}
这样的方式会出错
wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-04-14 17:33
没有人啊没有人
wowocock
VIP专家组
VIP专家组
  • 注册日期2002-04-08
  • 最后登录2016-01-09
  • 粉丝16
  • 关注2
  • 积分601分
  • 威望1651点
  • 贡献值1点
  • 好评度1227点
  • 原创分1分
  • 专家分0分
地板#
发布于:2008-04-14 17:34
参考SINISTER的文章.
花开了,然后又会凋零,星星是璀璨的,可那光芒也会消失。在这样 一瞬间,人降生了,笑者,哭着,战斗,伤害,喜悦,悲伤憎恶,爱。一切都只是刹那间的邂逅,而最后都要归入死亡的永眠
wildcatstar
驱动牛犊
驱动牛犊
  • 注册日期2006-06-23
  • 最后登录2010-05-20
  • 粉丝0
  • 关注0
  • 积分191分
  • 威望31点
  • 贡献值0点
  • 好评度20点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-04-16 00:05
谢谢指点~
看了SINISTER的文章和KLOG的代码,大致明白了~
需要把最后一次读键盘的回调执行完
游客

返回顶部