353807973
驱动牛犊
驱动牛犊
  • 注册日期2010-08-26
  • 最后登录2012-05-01
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望181点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1980回复:1

跪求高手,一个关于磁盘读写扇区的问题

楼主#
更多 发布于:2010-12-27 15:26
我做了个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}下面
Pegram
论坛版主
论坛版主
  • 注册日期2005-12-03
  • 最后登录2013-08-23
  • 粉丝13
  • 关注5
  • 积分1333分
  • 威望4717点
  • 贡献值1点
  • 好评度78点
  • 原创分0分
  • 专家分2分
沙发#
发布于:2011-01-15 16:50
IRP_MN_START_DEVICE用来启动设备,不应该读写设备。此后可以。
《寒江独钓》与《竹林蹊径》的合作作者。精通USB开发,设计了CY001 USB驱动套件(http://bbs.driverdevelop.com/read.php?tid-119314.html)。
游客

返回顶部