当前位置: 代码迷 >> 驱动开发 >> 键盘过滤驱动罗致R3假死
  详细解决方案

键盘过滤驱动罗致R3假死

热度:137   发布时间:2016-04-28 10:11:33.0
键盘过滤驱动导致R3假死
写的键盘驱动都是抄袭网上的,做了一点小修改,只是为了屏蔽特定按键。通过IOCTL与R3通信,现在遇到问题是:能够实现屏蔽与开启功能,但是R3一旦调用DeviceIoControl函数成功与驱动同喜 并且返回后,R3不能退出。一直在哪儿,任务管理器等均无法结束此进程。特此求教,谢谢
详细代码如下,谢谢帮忙解决下
由于最多1W字,全部代码贴不下,值能给出关键的地方,全部代码在看雪
http://bbs.pediy.com/showthread.php?p=1281505#post1281505
谢谢大伙儿
void TestKbdFilter( char c )
{
HANDLE hsys = INVALID_HANDLE_VALUE;
DWORD dwRet = 0;
hsys = CreateFile( _T("\\\\.\\KbdFilter"), GENERIC_READ | GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if ( hsys == INVALID_HANDLE_VALUE )
{
cout<<GetLastError()<<endl;
return;
}

if ( c == 'a' )
{
DeviceIoControl( hsys, IOCTL_DISABLE_KBD, nullptr, 0, nullptr, 0, &dwRet, NULL );
cout<<"\t已开启键盘过滤,只能输入 字母 数字 退格键."<<endl;
}
else if ( c== 'b' )
{
DeviceIoControl( hsys, IOCTL_ENABLE_KBD, nullptr, 0, nullptr, 0, &dwRet, NULL );
cout<<"\t键盘过滤已关闭."<<endl;
}
CloseHandle( hsys );
}



NTSTATUS DispatchIoctl(PDEVICE_OBJECT pDevObj, PIRP pIrp)
{
PIO_STACK_LOCATION pIrpStack;
ULONG uIoControlCode;
ULONG uOutSize;

UNREFERENCED_PARAMETER(pDevObj);

pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
uIoControlCode = pIrpStack->Parameters.DeviceIoControl.IoControlCode;

switch(uIoControlCode)
{
case IOCTL_ENABLE_KBD:
{
KdPrint( ("Keyboard enable.\r\n") );
g_bDisableKbd = FALSE;
break;
}
case IOCTL_DISABLE_KBD:
{
KdPrint( ("Keyboard disable.\r\n") );
g_bDisableKbd = TRUE;
break;
}
}
return STATUS_SUCCESS;
}


NTSTATUS KeyReadCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context )
{

PIO_STACK_LOCATION IrpSp;
PKEYBOARD_INPUT_DATA KeyData;
PDEVICE_EXTENSION KeyExtension = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension; 
int numKeys, i;
KIRQL IrqLevel;

IrpSp = IoGetCurrentIrpStackLocation( Irp );

if ( Irp->IoStatus.Status != STATUS_SUCCESS )
{
KdPrint( ( "ntStatus:0x%x", Irp->IoStatus.Status ) );
goto __RoutineEnd;
}

//
// 系统在 SystemBuffer 中保存按键信息
//
KeyData = Irp->AssociatedIrp.SystemBuffer;
if ( KeyData == NULL )
{
KdPrint( ( "KeyData is NULL.\r\n" ) );
goto __RoutineEnd;
}

//
// 得到按键数
//
numKeys = (int)(Irp->IoStatus.Information / sizeof( KEYBOARD_INPUT_DATA ));
if ( numKeys < 0 )
{
KdPrint( ( "numKeys less zero.\r\n" ) );
goto __RoutineEnd;
}

//
// 使用 0 无效扫描码替换,屏蔽预定义的按键
//
for ( i = 0; i < numKeys; i++ )
{
if( g_bDisableKbd )
{
if ( IsFilterKey( KeyData[i].MakeCode ) )
{
KdPrint( ( "This key [0x%02x] is disabled.\r\n", KeyData[i].MakeCode ) );
KeyData[i].MakeCode = 0;
}
else
{
KdPrint( ( "Key - ScanCode[0x%02x].\r\n", KeyData[i].MakeCode ) );
}
}
}
__RoutineEnd : 

if ( Irp->PendingReturned )
{
IoMarkIrpPending( Irp );

//
// 将 IRP 计数器减一,为支持 SMP 使用自旋锁
//
KeAcquireSpinLock( &KeyExtension->SpinLock, &IrqLevel );
InterlockedDecrement( &KeyExtension->IrpsInProgress );
KeReleaseSpinLock( &KeyExtension->SpinLock, IrqLevel );

return Irp->IoStatus.Status ;


NTSTATUS DriverEntry( IN PDRIVER_OBJECT KeyDriverObject, IN PUNICODE_STRING RegistryPath )
{

UNICODE_STRING KeyDeviceName; 
PDRIVER_OBJECT KeyDriver; 
PDEVICE_OBJECT UsbDeviceObject;
PDEVICE_OBJECT pDevObjOut;
NTSTATUS ntStatus; 
//ULONG i; 

UNICODE_STRING ustrLinkName;
UNICODE_STRING ustrDevName;
PDEVICE_OBJECT pDevObj;

PDEVICE_EXTENSION pDevExt = NULL;

//
// 这里没有过滤其他例程,仅处理了按键操作。这样处理会禁止
// 休眠。因在锁定时不允许休眠,所以也就无须处理其他例程
//

//
// 保存设备名,调试使用
//

WCHAR szDeviceName[MAXLEN + MAXLEN] = {0};

//
// 先尝试获得 USB 键盘设备对象,如果成功则挂接 USB 键盘
//
// 注意:因为 USB 键盘设备名不固定,且即使得到名称也无法
// 使用 IoGetDeviceObjectPointer() 函数根据设备名称得到其
// 设备对象,所以这里我们只能自己枚举 USB 设备栈,并得到
// USB 键盘设备来进行挂接
//


ntStatus = GetUsbKeybordDevice( &UsbDeviceObject );
  相关解决方案