mouse.mouth
驱动牛犊
驱动牛犊
  • 注册日期2007-01-23
  • 最后登录2007-03-08
  • 粉丝0
  • 关注0
  • 积分120分
  • 威望13点
  • 贡献值0点
  • 好评度12点
  • 原创分0分
  • 专家分0分
阅读:1829回复:1

内核驱动怎么用异步方式调用u盘呢?我的代码在IoCallDriver的时候老是bugcheck 0xa错误。

楼主#
更多 发布于:2007-02-28 11:54
  想在内核驱动的DISPATCH_LEVEL层次调用U盘读写特定数据,向U盘传输数据用的是spti的例子。程序运行到IoCallDriver的时候就蓝屏报0xa错误。如果不用spti的数据结构,直接将buffer映射的MDL传给u盘,则在IoCallDriver时没有问题,但这不能满足需求也得不到正确的结果。不知道诸位能否指点迷津。谢谢了。
                ndis_status = NdisAllocateMemoryWithTag( &buffer, totallen, TAG );
    if( ndis_status != NDIS_STATUS_SUCCESS )
    {
        DBGPRINT( ( "cannot allocate memory for data to transfer\n" ) );
        return FALSE;
    }
    NdisZeroMemory( buffer, totallen );

    NdisMoveMemory( buffer, &keyprefix, sizeof(KEY_CMD_PREFIX) );
    NdisMoveMemory( buffer + sizeof(KEY_CMD_PREFIX), pinput, inputlen );

    ndis_status = NdisAllocateMemoryWithTag( &psptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER), TAG );
    if( ndis_status != NDIS_STATUS_SUCCESS )
    {
        DBGPRINT( ( "cannot allocate passthru direct with buffer memory\n" ) );
        NdisFreeMemory( buffer, totallen, 0 );
        return FALSE;
    }
    NdisZeroMemory( (u_char*)psptdwb, sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER) );
    
    psptdwb->sptd.Length = sizeof(SCSI_PASS_THROUGH_DIRECT);
    psptdwb->sptd.PathId = 0;
    psptdwb->sptd.TargetId = 1;
    psptdwb->sptd.Lun = 0;
    psptdwb->sptd.CdbLength = CDB10GENERIC_LENGTH;
    psptdwb->sptd.SenseInfoLength = 24;
    psptdwb->sptd.DataIn = SCSI_IOCTL_DATA_OUT;
    psptdwb->sptd.DataTransferLength = totallen;
    psptdwb->sptd.TimeOutValue = 10;
    psptdwb->sptd.DataBuffer = buffer;
    psptdwb->sptd.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER,ucSenseBuf);
    psptdwb->sptd.Cdb[0] = 0xfd;//out
    NdisMoveMemory( psptdwb->sptd.Cdb + 1, "WATCH", 5 );
    ulength = sizeof(SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER);

    KeInitializeEvent( &event, NotificationEvent, FALSE );

    pIrp = IoAllocateIrp( pDeviceObject->StackSize, FALSE );

    if( ! pIrp )
    {
        NdisFreeMemory( buffer, totallen, 0 );
        NdisFreeMemory( psptdwb, ulength, 0 );
        return FALSE;
    }
    pIoStackLocation = IoGetNextIrpStackLocation( pIrp );
    pIoStackLocation->MajorFunction = IRP_MJ_DEVICE_CONTROL;
    pIoStackLocation->Parameters.DeviceIoControl.InputBufferLength = ulength;
    pIoStackLocation->Parameters.DeviceIoControl.IoControlCode = IOCTL_SCSI_PASS_THROUGH_DIRECT;

    if( pDeviceObject->Flags & DO_BUFFERED_IO )
    {
        pIrp->AssociatedIrp.SystemBuffer = psptdwb;
        pIrp->MdlAddress = NULL;
    }
    else
    {
        pbufmdl = IoAllocateMdl( buffer, totallen, FALSE, FALSE, NULL );
        if( pbufmdl == NULL )
        {
                                                IoFreeIrp( pIrp );
            NdisFreeMemory( buffer, totallen, 0 );
            NdisFreeMemory( psptdwb, ulength, 0 );
                                                return FALSE;
        }

        pIrp->MdlAddress = IoAllocateMdl( psptdwb, ulength, FALSE, FALSE, NULL );
        if( pIrp->MdlAddress == NULL )
        {
            if( pbufmdl != NULL )
            {
                IoFreeMdl( pbufmdl );
            }
            
            IoFreeIrp( pIrp );
            NdisFreeMemory( buffer, totallen, 0 );
            NdisFreeMemory( psptdwb, ulength, 0 );
            return FALSE;
        }

        pIrp->MdlAddress->Next = pbufmdl;

        try
        {
            MmProbeAndLockPages( pIrp->MdlAddress, KernelMode, IoModifyAccess );
        }
        except( EXCEPTION_EXECUTE_HANDLER )
        {            
            if( pIrp->MdlAddress != NULL )
            {
                IoFreeMdl( pIrp->MdlAddress );
            }

            if( pbufmdl != NULL )
            {
                IoFreeMdl( pbufmdl );
            }
            IoFreeIrp( pIrp );

            NdisFreeMemory( buffer, totallen, 0 );
            NdisFreeMemory( psptdwb, ulength, 0 );
            return FALSE;
        }
    }

    IoSetCompletionRoutine( pIrp, RequestCompletion, (PVOID)&event, TRUE, TRUE, TRUE );

    status = IoCallDriver( pDeviceObject, pIrp );

    if( status == STATUS_PENDING )
    {
        KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
        status = pIrp->IoStatus.Status;
    }

最新喜欢:

LeopardLeopar...
mouse.mouth
驱动牛犊
驱动牛犊
  • 注册日期2007-01-23
  • 最后登录2007-03-08
  • 粉丝0
  • 关注0
  • 积分120分
  • 威望13点
  • 贡献值0点
  • 好评度12点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2007-02-28 17:29
从目前的情况还看基本上确定是IoAllocateMdl调用时,对两个mdl处理在什么地方存在问题,导致运行在DISPATCH_LEVEL的IoCallDriver调用某些东西的时候,页面调不到。但搜遍了整个论坛也没有相关的示例,真是郁闷了:(
还望驱动牛哥们能够指点一下。
游客

返回顶部