阅读:2048回复:1
跪求高手,一个关于磁盘读写扇区的问题
我做了个U盘过滤驱动,现在禁用可以实现了,现在读写U盘扇区的问题上遇到了困难,我是采用构造SRB的方式来读取的,下面附上代码!
NTSTATUS ScsiReadWriteDisk(PDEVICE_OBJECT pDevObj, BOOLEAN bIsRead, ULONG ulSectorPos, PUCHAR lpDataBuff, ULONG ulSecCount) { NTSTATUS ntStatus = STATUS_SUCCESS; PSCSI_REQUEST_BLOCK pSrb = NULL; PSENSE_DATA pSenseData = NULL; PCDB pCdb10 = NULL; KEVENT Event; PIRP pIrp = NULL; PMDL pMdl = NULL; IO_STATUS_BLOCK IoSB; PDEVICE_EXTENSION pdx = (PDEVICE_EXTENSION) pDevObj->DeviceExtension; pSrb = (PSCSI_REQUEST_BLOCK)ExAllocatePoolWithTag(NonPagedPool, sizeof(SCSI_REQUEST_BLOCK),0x12345678); if (pSrb == NULL) goto __end; pSenseData = (PSENSE_DATA)ExAllocatePoolWithTag(NonPagedPool, sizeof(SENSE_DATA),0x12345678); if (pSenseData == NULL) goto __end; RtlZeroMemory(pSrb, sizeof(SCSI_REQUEST_BLOCK)); RtlZeroMemory(pSenseData, sizeof(SENSE_DATA)); pSrb->Length = sizeof (SCSI_REQUEST_BLOCK); pSrb->Function = SRB_FUNCTION_EXECUTE_SCSI; // // // pSrb->PathId = 0; pSrb->TargetId = 1; pSrb->Lun = 0; pSrb->NextSrb = NULL; pSrb->LinkTimeoutValue = -1; pSrb->SrbStatus = SRB_STATUS_PENDING; pSrb->ScsiStatus = SRB_STATUS_PENDING; pSrb->QueueAction = SRB_SIMPLE_TAG_REQUEST; pSrb->SenseInfoBuffer = pSenseData; pSrb->SenseInfoBufferLength = sizeof(SENSE_DATA); pSrb->DataBuffer = (PVOID)lpDataBuff; pSrb->DataTransferLength = ulSecCount; pSrb->QueueSortKey = ulSectorPos; if (bIsRead) { // // READ // pSrb->SrbFlags |= SRB_FLAGS_DATA_IN; // pSrb->SrbFlags |= SRB_FLAGS_ADAPTER_CACHE_ENABLE; pSrb->SrbFlags |=SRB_FLAGS_DISABLE_SYNCH_TRANSFER; pSrb->SrbFlags |=SRB_FLAGS_NO_QUEUE_FREEZE ; } else { // // WRITE // pSrb->SrbFlags |= SRB_FLAGS_DATA_OUT; } pSrb->SrbFlags |= SRB_FLAGS_DISABLE_AUTOSENSE; // // 填写CDB // pSrb->CdbLength = 0x0A; //CDB10 pCdb10 = (PCDB)pSrb->Cdb; if (bIsRead) { pCdb10->CDB10.OperationCode = SCSIOP_READ; } else { pCdb10->CDB10.OperationCode = SCSIOP_WRITE; } pCdb10->CDB10.LogicalBlockByte0 = ((PFOUR_BYTE)&ulSectorPos)->Byte3; pCdb10->CDB10.LogicalBlockByte1 = ((PFOUR_BYTE)&ulSectorPos)->Byte2; pCdb10->CDB10.LogicalBlockByte2 = ((PFOUR_BYTE)&ulSectorPos)->Byte1; pCdb10->CDB10.LogicalBlockByte3 = ((PFOUR_BYTE)&ulSectorPos)->Byte0; pCdb10->CDB10.TransferBlocksLsb = 1; pCdb10->CDB10.TransferBlocksMsb = 0; pCdb10->CDB10.ForceUnitAccess = TRUE; // // 构造IRP来SRB请求 // KeInitializeEvent(&Event, NotificationEvent, FALSE); pIrp = IoAllocateIrp(pDevObj->StackSize, FALSE); if (pIrp == NULL) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto __end; } pMdl = IoAllocateMdl((PVOID)lpDataBuff, ulSecCount * g_ulBytesPerSector, FALSE, FALSE, pIrp); if (pMdl == NULL) { IoFreeIrp(pIrp); pIrp = NULL; ntStatus = STATUS_INSUFFICIENT_RESOURCES; goto __end; } MmProbeAndLockPages(pMdl, KernelMode, bIsRead ? IoReadAccess : IoWriteAccess); pIrp->UserIosb = &IoSB; RtlZeroMemory(&pIrp->IoStatus, sizeof(IO_STATUS_BLOCK)); pIrp->UserEvent = &Event; pIrp->Cancel = FALSE; pIrp->CancelRoutine = NULL; pIrp->MdlAddress = pMdl; pIrp->AssociatedIrp.SystemBuffer = NULL; pIrp->Flags = IRP_NOCACHE | IRP_SYNCHRONOUS_API; pIrp->RequestorMode = KernelMode; pIrp->Tail.Overlay.Thread = PsGetCurrentThread(); pSrb->OriginalRequest = pIrp; // // 填写IO_STACK_LOCATION // PIO_STACK_LOCATION pIrpSp = IoGetNextIrpStackLocation(pIrp); pIrpSp->DeviceObject = pDevObj; pIrpSp->MajorFunction = IRP_MJ_SCSI; pIrpSp->Parameters.Scsi.Srb = pSrb; IoSetCompletionRoutine(pIrp, ScsiReadWriteDiskCompletion, pSrb, TRUE, TRUE, TRUE); ntStatus = IoCallDriver(pdx->LowerDeviceObject, pIrp); if (ntStatus == STATUS_PENDING) { KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); ntStatus = STATUS_SUCCESS; } if (NT_SUCCESS(ntStatus) && pSrb->SrbStatus == SRB_STATUS_SUCCESS && pSrb->ScsiStatus == SCSISTAT_GOOD) { ntStatus = STATUS_SUCCESS; } else { ntStatus = STATUS_UNSUCCESSFUL; } __end: if (pSrb->SenseInfoBuffer && pSrb->SenseInfoBuffer != pSenseData) { ExFreePool(pSrb->SenseInfoBuffer); } if (pSrb != NULL) { ExFreePool(pSrb); } if (pSenseData != NULL) { ExFreePool(pSenseData); } return ntStatus; } 在IRP_MN_START_DEVICE中调用,但是每次返回的都值都是错误的,实在找不出问题出在哪里的,有没高手做过类似的啊,给点意见吧,我都愁死了! 驱动挂载在磁盘类HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Class\{4D36E967-E325-11CE-BFC1-08002BE10318}下面 |
|
沙发#
发布于:2011-01-15 16:50
IRP_MN_START_DEVICE用来启动设备,不应该读写设备。此后可以。
|
|
|