bymars
驱动牛犊
驱动牛犊
  • 注册日期2010-06-08
  • 最后登录2010-06-19
  • 粉丝0
  • 关注0
  • 积分2分
  • 威望11点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:2162回复:0

ctrl2cap里卸载驱动导致蓝屏怎么解决(已解决)

楼主#
更多 发布于:2010-06-19 00:29
照抄了一遍ctrl2cap,可以卸载的时候一到IoDeleteDevice就会蓝屏,错误码是IRQL_NOT_LESS_OR_EQUAL
原来是iocreatedevice的时候扩展设备的大小写成了指针的大小

这个论坛很冷清。。。内核方面人真的很少吗
相关代码
__try
    {
        __try
        {
            IoDetachDevice(devExt->pLowerDeviceObject);
            // 把扩展设备数据结构中的指针置空
            devExt->pTargetDeviceObject = NULL;
            // 实质上删除的是过滤设备,见kbfUnload
            if (pDeviceObject!=NULL)
           IoDeleteDevice(pDeviceObject); ----> 一到这里就蓝屏
            devExt->pFilterDeviceObject = NULL;
            KdPrint(("解除成功\n"));
        }
        __except(EXCEPTION_EXECUTE_HANDLER){}
    }
    __finally{}

那位高手能帮我看一下源码哪里有问题吗?代码长了点。。。不好意思
我的源码
//
// @file        kbfilter.c
//
// @author    bymars
//
// @date        2010/6/9

// 抄代码

#include <wdm.h>
#include <ntddkbd.h>
#include "kbfilter.h"

#define KBD_DRIVER_NAME L"\\Driver\\Kbdclass"
#define KEY_UP 1
#define KEY_DOWN 0

#define LCONTROL ((USHORT)0x1D)
#define CAPS_LOCK ((USHORT)0x3A)

typedef struct _KB_DEV_EXT
{
    // 大小
    ULONG NodeSize;

    // 过滤设备对象
    PDEVICE_OBJECT pFilterDeviceObject;

    // 保护锁
    KSPIN_LOCK IoRequestsSpinLock;

    // 进程同步处理
    KEVENT IoInProgressEvent;

    // 绑定的目标设备
    PDEVICE_OBJECT pTargetDeviceObject;

    // 过滤设备下一个设备
    // 因为每次绑定设备最终会帮定这个设备栈的最上面的设备
    PDEVICE_OBJECT pLowerDeviceObject;
} KB_DEV_EXT, *PKB_DEV_EXT;

// 键盘扫描码处理
// 001,010,100
#define    S_SHIFT                1
#define    S_CAPS                2
#define    S_NUM                4
// 默认numlock是打开的
static int kb_status = S_NUM;
void __stdcall print_keystroke(UCHAR sch)
{
    UCHAR    ch = 0;
    int        off = 0;

    // 按下键盘
    if ((sch & 0x80) == 0)    //make
    {
        if ((sch < 0x47) ||
            ((sch >= 0x47 && sch < 0x54) && (kb_status & S_NUM))) // Num Lock
        {
            ch = asciiTbl[off+sch];
        }

        switch (sch)
        {
        case 0x3A:
            kb_status ^= S_CAPS;
            break;

        case 0x2A:
        case 0x36:
            kb_status |= S_SHIFT;
            break;

        case 0x45:
            kb_status ^= S_NUM;
        }
    }
    else        // 按键弹起,只处理左右shift
    {
        if (sch == 0xAA || sch == 0xB6)
            kb_status &= ~S_SHIFT;
    }

    if (ch >= 0x20 && ch < 0x7F)
    {
        DbgPrint("%C \n",ch);
    }

}

// 初始化设备扩展
NTSTATUS
kbfDevExtInit(
    IN PKB_DEV_EXT devExt,
    IN PDEVICE_OBJECT pFilterDeviceObject,
    IN PDEVICE_OBJECT pTargetDeviceObject,
    IN PDEVICE_OBJECT pLowerDeviceObject
    )
{
    memset (devExt, 0, sizeof( KB_DEV_EXT ));

    devExt->NodeSize = sizeof( KB_DEV_EXT );
    devExt->pFilterDeviceObject = pFilterDeviceObject;
    KeInitializeSpinLock(&(devExt->IoRequestsSpinLock));
    KeInitializeEvent(&(devExt->IoInProgressEvent), NotificationEvent, FALSE);
    devExt->pTargetDeviceObject = pTargetDeviceObject;
    devExt->pLowerDeviceObject = pLowerDeviceObject;

    return STATUS_SUCCESS;
}

// 这个函数存在,但文档中没公开,声明之后可以用
NTSTATUS ObReferenceObjectByName(
    PUNICODE_STRING ObjectName,
    ULONG Attributes,
    PACCESS_STATE AccessState,
    ACCESS_MASK DesiredAccess,
    POBJECT_TYPE ObjectType,
    KPROCESSOR_MODE AccessMode,
    PVOID ParseContext,
    PVOID *Object
    );

// 暂时不知道什么意思
extern POBJECT_TYPE IoDriverObjectType;
ULONG keyCount = 0;
// 全局变量 gDriverObject = DriverObject;
PDRIVER_OBJECT gDriverObject = NULL;

// 绑定kbdclass下面的所有设备
NTSTATUS
kbfAttachDevice(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath)
{
    NTSTATUS status = 0;
    UNICODE_STRING uniNtNameString;
    PKB_DEV_EXT devExt;
    PDEVICE_OBJECT pFilterDeviceObject = NULL;
    PDEVICE_OBJECT pTargetDeviceObject = NULL;
    PDEVICE_OBJECT pLowerDeviceObject = NULL;

    PDRIVER_OBJECT KbdDriverObject = NULL;

    KdPrint(("MyAttach\n"));

    RtlInitUnicodeString(&uniNtNameString, KBD_DRIVER_NAME);

    status = ObReferenceObjectByName(
        &uniNtNameString,
        OBJ_CASE_INSENSITIVE,
        NULL,
        0,
        IoDriverObjectType,
        KernelMode,
        NULL,
        &KbdDriverObject
        );

    if( !NT_SUCCESS(status) )
    {
        KdPrint(("MyAttach: 不能打开设备对象kbdclass"));
        return status;
    } else
    {
        // 调用引用系列函数后都要解除,书上貌似笔误了
        ObDereferenceObject(KbdDriverObject);
    }
    
    // 设备链的第一个设备,第一个目标设备
    pTargetDeviceObject = KbdDriverObject->DeviceObject;

    // 遍历设备链
    while( pTargetDeviceObject )
    {
        // 生成过滤设备,使用扩展设备
        status = IoCreateDevice(
            IN DriverObject,
            IN sizeof(PKB_DEV_EXT),
            IN NULL,
            IN pTargetDeviceObject->DeviceType,
            IN pTargetDeviceObject->Characteristics,
            IN FALSE,
            OUT &pFilterDeviceObject
            );


        if( !NT_SUCCESS(status) )
        {
            KdPrint(("MyAttach: 不能创建过滤设备"));
            return status;
        }

        // 创建成功,绑定目标设备,得到的是目标设备所在设备栈最上面的设备
        // 也就是过滤设备下面那个设备
        pLowerDeviceObject =
            IoAttachDeviceToDeviceStack(pFilterDeviceObject, pTargetDeviceObject);

        if( !pLowerDeviceObject )
        {
            KdPrint(("MyAttach: 绑定失败,删除过滤设备..."));
            IoDeleteDevice(pFilterDeviceObject);
            pFilterDeviceObject = NULL;
            return STATUS_UNSUCCESSFUL;
        }

        // 生成设备扩展,强制转换成PC2P_DEV_EXT类型,实际是确定这个指针的长度
        devExt = (PKB_DEV_EXT)(pFilterDeviceObject->DeviceExtension);
        kbfDevExtInit(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);

        // 取下一个设备
        pTargetDeviceObject = pTargetDeviceObject->NextDevice;
    }
    return status;
}

// 解除绑定
VOID
kbfDetach(IN PDEVICE_OBJECT pDeviceObject)
{
    PKB_DEV_EXT devExt;
    // 没用到啊
    BOOLEAN NoRequestsOutstanding = FALSE;
    devExt = (PKB_DEV_EXT)pDeviceObject->DeviceExtension;
    
    __try
    {
        __try
        {
            IoDetachDevice(devExt->pLowerDeviceObject);
            // 把扩展设备数据结构中的指针置空
            devExt->pTargetDeviceObject = NULL;
            // 实质上删除的是过滤设备,见kbfUnload
            if (pDeviceObject!=NULL)
            IoDeleteDevice(pDeviceObject);
            devExt->pFilterDeviceObject = NULL;
            KdPrint(("解除成功\n"));
        }
        __except(EXCEPTION_EXECUTE_HANDLER){}
    }
    __finally{}

    return;
}

// 延时
#define  DELAY_ONE_MICROSECOND  (-10)
#define  DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define  DELAY_ONE_SECOND (DELAY_ONE_MILLISECOND*1000)

VOID
kbfUnload(IN PDRIVER_OBJECT DriverObject)
{
    PDEVICE_OBJECT DeviceObject;
    // 没用到
    PDEVICE_OBJECT OldDeviceObject;
    PKB_DEV_EXT devExt;

    LARGE_INTEGER delay;
    PRKTHREAD CurrentThread;
    
    #if DBG
        __asm int 3
    #endif
    // 定义延时
    delay = RtlConvertLongToLargeInteger(100 * DELAY_ONE_MILLISECOND);
    CurrentThread = KeGetCurrentThread();
    // 降低进程优先级
    KeSetPriorityThread(CurrentThread, LOW_REALTIME_PRIORITY);
    
    UNREFERENCED_PARAMETER(DriverObject);

    KdPrint(("正在卸载。。。"));

    // DriverObject->DeviceObject实质上是过滤设备
    // IoCreatDevice(DriverObject, ... , &pFilterDeviceObject)
    // 就是生成DeviceObject下的一个设备
    DeviceObject = DriverObject->DeviceObject;

    // 遍历解绑
    while( DeviceObject )
    {
        kbfDetach(DeviceObject);
        DeviceObject = DeviceObject->NextDevice;
    }

    // 没有完全解绑,错误
    ASSERT(NULL == DriverObject->DeviceObject);

    // 延时直到keyCount为零
    // 每当一个read请求出现时keyCount++,完成之后keyCount--
    // 由于之前过滤设备全部解绑删除,新的irp不会再发给过滤设备
    // 此时只要处理最后一个等待的就可以了
    while( keyCount )
    {
        KeDelayExecutionThread(KernelMode, FALSE, &delay);
    }
    
    KdPrint(("卸载完成^-^"));
    return;
}

// MajorFunction

// 其他irp直接跳过
NTSTATUS
kbfDispatchGeneral(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
{
    PKB_DEV_EXT devExt;
    devExt = (PKB_DEV_EXT)DeviceObject->DeviceExtension;
    KdPrint(("其他irp"));
    // 此函数的意义在于用IoCallDriver()时,设备栈的下一个设备得到
    // 和当前设备相同的irp
    IoSkipCurrentIrpStackLocation(Irp);

    return IoCallDriver(devExt->pLowerDeviceObject, Irp);
}

// 未完待续
//power irp 稍微有些不同
NTSTATUS
kbfPower(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
{
    PKB_DEV_EXT devExt;
    devExt = (PKB_DEV_EXT)DeviceObject->DeviceExtension;
    PoStartNextPowerIrp(Irp);
    IoSkipCurrentIrpStackLocation(Irp);

    return PoCallDriver(devExt->pLowerDeviceObject, Irp);
}

// pnp 即插即用
NTSTATUS
kbfPnP(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
{
    PKB_DEV_EXT devExt;
    PIO_STACK_LOCATION irpSp;
    NTSTATUS status = STATUS_SUCCESS;
    KIRQL oldIrql;
    KEVENT event;

    devExt = (PKB_DEV_EXT)DeviceObject->DeviceExtension;
    irpSp = IoGetCurrentIrpStackLocation(Irp);

    // 个人理解
    // pnp是major function
    // pnp下还有minor function
    switch( irpSp->MinorFunction )
    {
    case IRP_MN_REMOVE_DEVICE:

        KdPrint(("IRP_MN_REMOVE_DEVICE\n"));

        IoSkipCurrentIrpStackLocation(Irp);
        IoCallDriver(devExt->pLowerDeviceObject, Irp);

        // 180行,解绑的是pTargetDeviceObject, why
        IoDetachDevice(devExt->pLowerDeviceObject);
        IoDeleteDevice(DeviceObject);
        status = STATUS_SUCCESS;

        break;    
    
    default :
    
        IoSkipCurrentIrpStackLocation(Irp);
        status = IoCallDriver(devExt->pLowerDeviceObject, Irp);

        break;
    }

    return status;
}

// 回调函数,read irp 完成后调用此函数
NTSTATUS
kbfReadComplete(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp,
    IN PVOID Context)
{
    PIO_STACK_LOCATION irpSp;
    ULONG buf_len = 0;
    PUCHAR buf = NULL;
    size_t i, numKeys;

    // 按键数据结构
    PKEYBOARD_INPUT_DATA keyData;

    irpSp = IoGetCurrentIrpStackLocation( Irp );

    if( NT_SUCCESS(Irp->IoStatus.Status) )
    {
        buf = Irp->AssociatedIrp.SystemBuffer;
        keyData = (PKEYBOARD_INPUT_DATA)buf;
        // 缓冲区长度一般保存在information中
        buf_len = Irp->IoStatus.Information;
        numKeys = buf_len / sizeof(KEYBOARD_INPUT_DATA);

        // 此处可以处理buf中的扫描码
//        for( i = 0; i < buf_len ; i++ )
//        {
//            KdPrint(("键盘记录: %2x\r\n", buf));
//        }
        // 扫描码处理方法之二
        for( i = 0; i < numKeys ; i++ )
        {
            KdPrint(("\n"));
            KdPrint(("numKeys: %d", numKeys));
            KdPrint(("ScanCode: %x", keyData->MakeCode));
            KdPrint(("%s\n", keyData->Flags?"Up":"Down"));
            print_keystroke((UCHAR)keyData->MakeCode);

//            if( keyData->MakeCode ==  CAPS_LOCK )
//            {
//                keyData->MakeCode = LCONTROL;
//            }
        }
    }

    keyCount--;

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

    return Irp->IoStatus.Status;
}

// read marjor fountion
NTSTATUS
kbfDispatchRead(
    IN PDEVICE_OBJECT DeviceObject,
    IN PIRP Irp)
{
    NTSTATUS status = STATUS_SUCCESS;
    PKB_DEV_EXT devExt;
    PIO_STACK_LOCATION irpSp;
    KEVENT waitEvent;

    // 后面的都不太懂
    // MSDN -- A driver can use an event object to wait while
    // the next-lower driver processes an IRP set up by the waiting driver.
    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);

    // 这是个什么错误
    if( Irp->CurrentLocation == 1 )
    {
        KdPrint(("错误的current location\n"));
        status = STATUS_INVALID_DEVICE_REQUEST;
        Irp->IoStatus.Status = status;
        Irp->IoStatus.Information = 0;
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
    
    // 读请求等待,计数器加一
    keyCount++;

    devExt = (PKB_DEV_EXT)DeviceObject->DeviceExtension;

    // 设置回调函数,等待读请求完成。
    irpSp = IoGetCurrentIrpStackLocation(Irp);
    // IoSkipCurrentIrpStackLocation
    // MSDN -- copies the IRP stack parameters from the current I/O stack
    // location to the stack location of the next-lower driver
    IoCopyCurrentIrpStackLocationToNext(Irp);
    IoSetCompletionRoutine(Irp, kbfReadComplete, DeviceObject, TRUE, TRUE, TRUE);

    return IoCallDriver(devExt->pLowerDeviceObject, Irp);
}

NTSTATUS DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath)
{
    ULONG i;
    NTSTATUS status;
    KdPrint(("进入入口函数\n"));

    //  其他分发函数
    for( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )
    {
        DriverObject->MajorFunction = kbfDispatchGeneral;
    }

    // read irp
    DriverObject->MajorFunction[IRP_MJ_READ] = kbfDispatchRead;

    // power irp
    DriverObject->MajorFunction[IRP_MJ_POWER] = kbfPower;

    // pnp irp
    DriverObject->MajorFunction[IRP_MJ_PNP] = kbfPnP;

    // 卸载函数
    DriverObject->DriverUnload = kbfUnload;
    // 全局变量
    gDriverObject = DriverObject;
    
    // 绑定所有设备
    status = kbfAttachDevice(DriverObject,RegistryPath);

    return status;
}
游客

返回顶部