阅读:1829回复:1
内核驱动怎么用异步方式调用u盘呢?我的代码在IoCallDriver的时候老是bugcheck 0xa错误。
想在内核驱动的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; } |
|
最新喜欢:![]() |
沙发#
发布于:2007-02-28 17:29
从目前的情况还看基本上确定是IoAllocateMdl调用时,对两个mdl处理在什么地方存在问题,导致运行在DISPATCH_LEVEL的IoCallDriver调用某些东西的时候,页面调不到。但搜遍了整个论坛也没有相关的示例,真是郁闷了:(
还望驱动牛哥们能够指点一下。 |
|