首页
社区
课程
招聘
[原创]鼠标经常在单击时变成双击,所以打算写一个鼠标过滤驱动来修复硬件的BUG
发表于: 2012-9-12 11:46 7745

[原创]鼠标经常在单击时变成双击,所以打算写一个鼠标过滤驱动来修复硬件的BUG

2012-9-12 11:46
7745
本来想自己从头写个鼠标过滤驱动,来实现这个功能,不过用了一下搜索引擎,发现riusksk已经在09年就已经实现了这个功能,果然惰性是人最大的天敌,既然有现成可用的代码,就不想从头再写了。

鼠标过滤驱动能修复这个Bug的原理是:
鼠标在点击时,会触发一个硬件中断,然后发消息给过滤驱动,这时我在驱动中判断两次点击的时间间隔,如果小于100ms则认为是硬件故障,屏蔽掉该此操作

关于鼠标过滤,riusksk的帖子已经写的很详细了,这里我就不多说了,这里主要说一下IRP的取消。取消IRP还真是花费了我很多时间,原因是IoCancelIrp这个函数会直接回调完成例程,然后破坏了链表的结构,导致了蓝屏。(我在MyRead例程里面把IRP插入到一个链表里面,然后在MyReadComplete里面,从链表里面移除该IRP)

这样只好,在取消IRP时,复制一个新的链表,在新的链表里面对IRP进行取消,这样总算是OK了

好了,废话说完了,大家看代码吧:

// 取消等待的IRP
VOID CancelPendingIrp()
{
    PPENDING_IRP_LIST PendingList = NULL, CancelList = NULL;
    PSINGLE_LIST_ENTRY pSingleListEntry = NULL;

    // 获取互斥体,保护链表gFilterData.ListHead
    KeWaitForMutexObject(&gFilterData.ReadMutex, Executive, KernelMode, FALSE, NULL);
    
    pSingleListEntry = gFilterData.ListHead.Next;
    while(pSingleListEntry)
    {       
        PendingList = CONTAINING_RECORD(pSingleListEntry, PENDING_IRP_LIST, SingleListEntry);
        KdPrint(("Copy Single List = 0x%x", PendingList));

        // 复制链表,然后将取消IRP的操作放到新的链表中处理
        CancelList = (PPENDING_IRP_LIST)ExAllocatePoolWithTag(NonPagedPool, sizeof(PENDING_IRP_LIST), POOL_TAG);
        if(CancelList)
        {
            RtlCopyMemory(CancelList, PendingList, sizeof(PENDING_IRP_LIST));
            PushEntryList(&gFilterData.CancelHead, &CancelList->SingleListEntry);
        }           
        
        pSingleListEntry = pSingleListEntry->Next;
    }   
    // 释放互斥体
    KeReleaseMutex(&gFilterData.ReadMutex, FALSE);
    

    // 之所以要复制一个新的链表来取消IRP (通过调用IoCancelIrp),
    // 是因为IoCancelIrp 会调用MyReadComplete 这个完成例程回调,
    // 而MyReadComplete里面又对链表进行操作,这样会破坏链表的结构
    pSingleListEntry = PopEntryList(&gFilterData.CancelHead);
    while(pSingleListEntry)
    {
        CancelList = CONTAINING_RECORD(pSingleListEntry, PENDING_IRP_LIST, SingleListEntry);
        if(CancelList)
        {
            KdPrint(("CancelPendingIrp = 0x%x", CancelList->PendingIrp));

            if(!CancelList->PendingIrp->Cancel)
            {// 在这里,取出复制链表中的IRP,然后进行取消
                IoCancelIrp(CancelList->PendingIrp);
            }
            ExFreePoolWithTag(CancelList, POOL_TAG);        
            pSingleListEntry = PopEntryList(&gFilterData.CancelHead);
        }
    }
}


参考资料:
http://www.cnblogs.com/evlon/articles/825597.html

http://bbs.pediy.com/showthread.php?t=96245&page=3

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 1
支持
分享
最新回复 (4)
雪    币: 382
活跃值: (352)
能力值: ( LV2,RANK:140 )
在线值:
发帖
回帖
粉丝
2
这个霸道..哥还在用DoubleClickFix呢.
家里的鼠标拆开刮一下触点就行了.公司的这个不好意思拆.
ps:
你链接的那个不是Fypher的嘛
2012-9-12 13:28
0
雪    币: 558
活跃值: (73)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
嗯,的确是,不过改动有两点,“鼠标修复专家 2.0”那个好像不支持Win7,重新编译也没有效果,

第二点,上面那个在卸载驱动时,会一直等待完成例程结束,也就是说需要用户手动“点一下鼠标”

我主要在UnLoad里面,对IRP进行了取消,省去一次鼠标操作
2012-9-12 14:05
0
雪    币: 285
活跃值: (16)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
啥时候楼主写个更好的程序,直接让鼠标变成脑电波控制的。
2012-9-12 14:39
0
雪    币: 190
活跃值: (40)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
顶个,牛人!
2012-9-13 19:33
0
游客
登录 | 注册 方可回帖
返回
//