summerfruit
驱动牛犊
驱动牛犊
  • 注册日期2004-06-12
  • 最后登录2013-12-07
  • 粉丝0
  • 关注0
  • 积分395分
  • 威望67点
  • 贡献值0点
  • 好评度36点
  • 原创分0分
  • 专家分0分
阅读:1306回复:0

关于modem过滤驱动

楼主#
更多 发布于:2007-03-23 13:57
  小弟正在写一个modem驱动过滤程序。我们的设备包含modem功能,还有一个USB bulk接口,
我就是Windows的modem.sys和USBD之间加入一个过滤驱动程序来跟这个USB bulk接口通信,然后把modem.sys传送下来的数据(包括AT命令,发送到BULK接口(设备会把接收到的数据上传给modem功能块。), 然后自建URB从bulk接口把来自modem的数据传到上层。

小弟碰到了一个关于线程的问题(结束线程后产生了IRQL_NOT_LESS_OR_EQUAL)
小弟建立了一个线程来读取来自modem的数据,这个线程在IRP_MJ_OPEN处理例程里打开。例程代码如下:
VOID ThreadProc(PDEVICE_EXTENSION pdx)
{
    BOOLEAN kill = FALSE;
    NTSTATUS status;
    KTIMER timer;
    LARGE_INTEGER duetime = {0};

    PIRP     pIrp = NULL;
    PURB    pUrb = NULL;
    PIO_STACK_LOCATION  pStack=NULL;
    UCHAR    *pDataBuf=NULL;
    PInternalURBEntry pInterIrp=NULL;
    
    PVOID mainevents[] = {
        (PVOID) &pdx->evThreadKill,
        //(PVOID) &timer,
        (PVOID) &pdx->evInterIrpComplete
        };

    //------prepare internal IRP for reading data from modem.
    
    pUrb = ExAllocatePool(NonPagedPool,sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER));
    if (pUrb==NULL)
    {
        USBD_MODEM_KdPrint(DBGLVL_MEDIUM,("InitializeInternalUSBReadQue:locating NO %d URB memory failed.\n",0));
        //ExFreePool(pIrp);
        return ;
    }

    pDataBuf = ExAllocatePool(NonPagedPool,1024);

    UsbBuildInterruptOrBulkTransferRequest(pUrb,sizeof(struct _URB_BULK_OR_INTERRUPT_TRANSFER),
                                        pdx->hBulkInPipe,
                                        pDataBuf,NULL,1024,
                                        USBD_TRANSFER_DIRECTION_IN|USBD_SHORT_TRANSFER_OK,
                                        NULL);

    pInterIrp = ExAllocatePool(NonPagedPool,sizeof(InternalURBEntry));
    //pInterIrp->Irp = pIrp;
    pInterIrp->Urb = pUrb;
    pInterIrp->pDataBuf = pDataBuf;
    pInterIrp->pvDX = pdx;
    //------end of preparing internal IRP for reading data from modem.
    
    KeInitializeTimerEx(&timer, SynchronizationTimer);
    //KeSetEvent(&pdx->evInterIrpComplete, 0, FALSE);
    //KeClearEvent(&pdx->evInterIrpComplete);

    ASSERT(3 <= THREAD_WAIT_OBJECTS);
    //C_ASSERT(arraysize(pollevents) <= THREAD_WAIT_OBJECTS);

    while (!kill)
    {                        // until told to quit
        if (pIrp!=NULL)
            IoFreeIrp(pIrp);
        
        pIrp = IoAllocateIrp((pdx->LowerDevice->StackSize),FALSE);
        if (pIrp==NULL)
        {
            break ;
        }
        //pStack = IoGetNextIrpStackLocation(pIrp);

        // Now set up the parameters for that driver...
        //pStack->DeviceObject = pdx->DeviceObject;
        //IoSetNextIrpStackLocation(pIrp);
            
        //PIRP Irp = GetCurrentIrp(&pdx->dqReadWrite);
        IoSetCompletionRoutine(pIrp,
                                    (PIO_COMPLETION_ROUTINE) OnInternalIrpComplete,
                                    pInterIrp,
                                    TRUE,        // InvokeOnSuccess
                                    TRUE,        // InvokeOnError
                                    TRUE);       // InvokeOnCancel

        pStack = IoGetNextIrpStackLocation(pIrp);

        // Now set up the parameters for that driver...
        pStack->MajorFunction                            = IRP_MJ_INTERNAL_DEVICE_CONTROL;
        pStack->Parameters.DeviceIoControl.IoControlCode = IOCTL_INTERNAL_USB_SUBMIT_URB;
        pStack->Parameters.Others.Argument1              = pUrb;

        pInterIrp->Irp = pIrp;
        // Starting the timer with a zero due time will cause us to perform the
        // first poll immediately. Thereafter, polls occur at the POLLING_INTERVAL
        // interval (measured in milliseconds).
        KeSetTimerEx(&timer, duetime, POLLING_INTERVAL, NULL);
        KeClearEvent(&pdx->evInterIrpComplete);
        USBD_MODEM_KdPrint(DBGLVL_DEFAULT,("-----Now IoCallDriver Called------------.\n"));
        IoCallDriver(pdx->LowerDevice,pIrp);

        /*status = KeWaitForMultipleObjects(3,
            mainevents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);*/
        status = KeWaitForMultipleObjects(2,
            mainevents, WaitAny, Executive, KernelMode, FALSE, NULL, NULL);

        if (!NT_SUCCESS(status))
        {                    // error in wait
            USBD_MODEM_KdPrint(DBGLVL_HIGH,("POLLING - KeWaitForMultipleObjects failed - %X\n", status));
            break;
        }                    
        if (status == STATUS_WAIT_0)// kill event was set
        {
            USBD_MODEM_KdPrint(DBGLVL_HIGH,("Thread kill event is set.\n"));
            IoCancelIrp(pIrp);
            break;                
        }
        //
        /*if (status == STATUS_WAIT_0+1)
        {
            USBD_MODEM_KdPrint(DBGLVL_HIGH,("timer is out.\n"));
            IoCancelIrp(pIrp);
            KeSetTimerEx(&timer, duetime, POLLING_INTERVAL, NULL);
            continue;
        }*/
        USBD_MODEM_KdPrint(DBGLVL_HIGH,("next read internal URB will be sent.\n"));
    }

    KeWaitForSingleObject(&pdx->evInterIrpComplete,Executive,KernelMode,FALSE,NULL);
    
    //-----------free memory
    if (pInterIrp)
    {
        USBD_MODEM_KdPrint(DBGLVL_DEFAULT,("ThreadProc():pInterIrp will be freed,because thread will be stopped.\n"));
        ExFreePool(pInterIrp);
    }
    if (pUrb)
    {
        USBD_MODEM_KdPrint(DBGLVL_DEFAULT,("ThreadProc():pUrb will be freed, because thread will be stopped.\n"));
        ExFreePool(pUrb);
    }
    if (pIrp)
    {
        USBD_MODEM_KdPrint(DBGLVL_DEFAULT,("ThreadProc():pIrp will be freed, because thread will be stopped.\n"));
        ExFreePool(pIrp);
    }
    //-----------end of freeing memory
    USBD_MODEM_KdPrint(DBGLVL_DEFAULT,("ThreadProc(): internal read thread will be killed.\n"));
    
    PsTerminateSystemThread(STATUS_SUCCESS);
}

然后我通过设置事件pdx->evThreadKill来结束线程,我发现在这个函数执行结束后,出现了IRQL_NOT_LESS_OR_EQUAL错误,请高手赐教啊!谢谢先。
游客

返回顶部