写的键盘驱动都是抄袭网上的,做了一点小修改,只是为了屏蔽特定按键。通过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 );