zoukankan      html  css  js  c++  java
  • 使用Device IO Control 讀寫 USB Mass Storage

    http://www.ezblog.idv.tw/Download/USBStorage.rar

    這是一個不透過檔案系統,去讀寫USB Mass Storage 任何位置(包含FAT)的方式

    首先需安裝微軟的DDK並include "usbioctl.h" , "usbdi.h" , "ntddscsi.h"

    有幾個資料結構要定義

    typedef struct _SCSI_Device_Info_
    {
      SCSI_PASS_THROUGH Spt;
      BYTE Sense[ 18 ];
      BYTE Data[ 36 ];
    } SCSI_Device_Info, *pSCSI_Device_Info;
    typedef struct _SCSI_PASS_THROUGH_WITH_BUFFERS
    {
      SCSI_PASS_THROUGH Spt;
      ULONG Filler;      // realign buffers to double word boundary
      UCHAR ucSenseBuf[ SPT_SENSE_LENGTH ];
      UCHAR ucDataBuf[ SPTWB_DATA_LENGTH ];
    } SCSI_PASS_THROUGH_WITH_BUFFERS, *pSCSI_PASS_THROUGH_WITH_BUFFERS;
    typedef struct _SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER
    {
      SCSI_PASS_THROUGH_DIRECT sptd;
      ULONG Filler;      // realign buffer to double word boundary
      UCHAR ucSenseBuf[ SPT_SENSE_LENGTH ];
    } SCSI_PASS_THROUGH_DIRECT_WITH_BUFFER, *pSCSI_PASS_THROUGH_DIRECT_WITH_BUFFER;
    
    /*
     * Required UFI Commands
     */
    #define UFI_FORMAT_UNIT             0x04    // output
    #define UFI_INQUIRY                 0x12    // input
    #define UFI_MODE_SELECT             0x55    // output
    #define UFI_MODE_SENSE_6            0x1A    // input
    #define UFI_MODE_SENSE_10           0x5A    // input
    #define UFI_PREVENT_MEDIUM_REMOVAL  0x1E
    #define UFI_READ_10                 0x28    // input
    #define UFI_READ_12                 0xA8    // input
    #define UFI_READ_CAPACITY           0x25    // input
    #define UFI_READ_FORMAT_CAPACITY    0x23    // input
    #define UFI_REQUEST_SENSE           0x03    // input
    #define UFI_REZERO_UNIT             0x01
    #define UFI_SEEK_10                 0x2B
    #define UFI_SEND_DIAGNOSTIC         0x1D
    #define UFI_START_UNIT              0x1B
    #define UFI_TEST_UNIT_READY         0x00
    #define UFI_VERIFY                  0x2F
    #define UFI_WRITE_10                0x2A    // output
    #define UFI_WRITE_12                0xAA    // output
    #define UFI_WRITE_AND_VERIFY        0x2E    // output
    #define UFI_ALLOW_MEDIUM_REMOVAL    UFI_PREVENT_MEDIUM_REMOVAL
    #define UFI_STOP_UNIT               UFI_START_UNIT
    
    bool CUSBStorDrive::m_OpenDrive()
    {
      char DriveStr[100];
    
      m_CloseDrive();
      memset(DriveStr,0x00,100);
    
      sprintf(DriveStr, "\\?\%c:", m_cDrive);
      m_hDrive = CreateFile(
          DriveStr,           // device interface name
          GENERIC_READ | GENERIC_WRITE,// dwDesiredAccess
          FILE_SHARE_READ | FILE_SHARE_WRITE,// dwShareMode
          NULL,// lpSecurityAttributes
          OPEN_EXISTING,// dwCreationDistribution
          0,// dwFlagsAndAttributes
          NULL// hTemplateFile
      );
      if (m_hDrive == INVALID_HANDLE_VALUE)
      {
        m_LastErrCode = GetLastError();
        return false;
      }
      return m_SendInquiry(m_hDrive);
    }
    
    bool CUSBStorDrive::m_CloseDrive()
    {
      if (m_hDrive != NULL)
      {
        CloseHandle(m_hDrive);
      }
      m_hDrive = NULL;
      return true;
    }
    
    bool CUSBStorDrive::m_SendInquiry(HANDLE hDrive)
    {
      SCSI_Device_Info SCSIInfo =
      { 0};
      DWORD ReturnLen;
      BOOL bResult;
    
      if (hDrive == NULL) return false;
    
      SCSIInfo.Spt.Length = sizeof(SCSIInfo.Spt);
      SCSIInfo.Spt.SenseInfoLength = sizeof(SCSIInfo.Sense);
      SCSIInfo.Spt.DataTransferLength = sizeof(SCSIInfo.Data);
      SCSIInfo.Spt.SenseInfoOffset = offsetof(SCSI_Device_Info, Sense);
      SCSIInfo.Spt.DataBufferOffset = offsetof(SCSI_Device_Info, Data);
      SCSIInfo.Spt.TimeOutValue = 30;
      SCSIInfo.Spt.DataIn = SCSI_IOCTL_DATA_IN;
      SCSIInfo.Spt.CdbLength = 6;
      SCSIInfo.Spt.Cdb[0] = UFI_INQUIRY; // inquiry opcode
      SCSIInfo.Spt.Cdb[1] = 0x00;
      SCSIInfo.Spt.Cdb[2] = 0x00;
      SCSIInfo.Spt.Cdb[3] = 0x00;
      SCSIInfo.Spt.Cdb[4] = sizeof(SCSIInfo.Data);
      SCSIInfo.Spt.Cdb[5] = 0x00;
    
      bResult = DeviceIoControl(
          hDrive,
          IOCTL_SCSI_PASS_THROUGH,
          &SCSIInfo,
          sizeof(SCSIInfo),
          &SCSIInfo,
          sizeof(SCSIInfo),
          &ReturnLen,
          FALSE);
      if (bResult)
      {
        return true;
      }
      else
      {
        m_LastErrCode = GetLastError();
        return false;
      }
    }
    
    bool CUSBStorDrive::m_ReadCapacity(HANDLE hDrive)
    {
      SCSI_Device_Info SCSIInfo =
      { 0};
      DWORD ReturnLen;
      BOOL bResult;
      if (hDrive == NULL) return false;
    
      SCSIInfo.Spt.Length = sizeof(SCSIInfo.Spt);
      SCSIInfo.Spt.SenseInfoLength = sizeof(SCSIInfo.Sense);
      SCSIInfo.Spt.DataTransferLength = sizeof(SCSIInfo.Data);
      SCSIInfo.Spt.SenseInfoOffset = offsetof(SCSI_Device_Info, Sense);
      SCSIInfo.Spt.DataBufferOffset = offsetof(SCSI_Device_Info, Data);
      SCSIInfo.Spt.TimeOutValue = 30;
      SCSIInfo.Spt.DataIn = SCSI_IOCTL_DATA_IN;
      SCSIInfo.Spt.CdbLength = 12;
      SCSIInfo.Spt.Cdb[0] = UFI_READ_CAPACITY; // Read Capacity opcode
      SCSIInfo.Spt.Cdb[1] = 0x00;
      SCSIInfo.Spt.Cdb[2] = 0x00;
      SCSIInfo.Spt.Cdb[3] = 0x00;
      SCSIInfo.Spt.Cdb[4] = 0x00;
      SCSIInfo.Spt.Cdb[5] = 0x00;
      SCSIInfo.Spt.Cdb[6] = 0x00;
      SCSIInfo.Spt.Cdb[7] = 0x00;
      SCSIInfo.Spt.Cdb[8] = 0x00;
      SCSIInfo.Spt.Cdb[9] = 0x00;
      SCSIInfo.Spt.Cdb[10] = 0x00;
      SCSIInfo.Spt.Cdb[11] = 0x00;
    
      bResult = DeviceIoControl(
          hDrive,
          IOCTL_SCSI_PASS_THROUGH,
          &SCSIInfo,
          sizeof(SCSIInfo),
          &SCSIInfo,
          sizeof(SCSIInfo),
          &ReturnLen,
          FALSE);
      if (bResult)
      {
        return true;
      }
      else
      {
        m_LastErrCode = GetLastError();
        return false;
      }
    }
    
    bool CUSBStorDrive::m_ReadFormatCapacity(HANDLE hDrive)
    {
      SCSI_Device_Info SCSIInfo =
      { 0};
      DWORD ReturnLen = 0;
      BOOL bResult = false;
      if (hDrive == NULL) return false;
    
      WORD wAllocLeng = 0x0000;
    
      SCSIInfo.Spt.Length = sizeof(SCSIInfo.Spt);
      SCSIInfo.Spt.SenseInfoLength = sizeof(SCSIInfo.Sense);
      SCSIInfo.Spt.DataTransferLength = sizeof(SCSIInfo.Data);
      SCSIInfo.Spt.SenseInfoOffset = offsetof(SCSI_Device_Info, Sense);
      SCSIInfo.Spt.DataBufferOffset = offsetof(SCSI_Device_Info, Data);
      SCSIInfo.Spt.TimeOutValue = 30;
      SCSIInfo.Spt.DataIn = SCSI_IOCTL_DATA_IN;
      SCSIInfo.Spt.CdbLength = 12;
      SCSIInfo.Spt.Cdb[0] = UFI_READ_FORMAT_CAPACITY; // Read format Capacity opcode
      SCSIInfo.Spt.Cdb[1] = 0x00;
      SCSIInfo.Spt.Cdb[2] = 0x00;
      SCSIInfo.Spt.Cdb[3] = 0x00;
      SCSIInfo.Spt.Cdb[4] = 0x00;
      SCSIInfo.Spt.Cdb[5] = 0x00;
      SCSIInfo.Spt.Cdb[6] = 0x00;
      SCSIInfo.Spt.Cdb[7] = wAllocLeng >> 8;//Allocation Length (MSB)
      SCSIInfo.Spt.Cdb[8] = wAllocLeng & 0x00FF;//Allocation Length (LSB)
      SCSIInfo.Spt.Cdb[9] = 0x00;
      SCSIInfo.Spt.Cdb[10] = 0x00;
      SCSIInfo.Spt.Cdb[11] = 0x00;
    
      bResult = DeviceIoControl(
          hDrive,
          IOCTL_SCSI_PASS_THROUGH,
          &SCSIInfo,
          sizeof(SCSIInfo),
          &SCSIInfo,
          sizeof(SCSIInfo),
          &ReturnLen,
          FALSE);
      if (bResult)
      {
        //SCSIInfo.Data[];
        return true;
      }
      else
      {
        m_LastErrCode = GetLastError();
        return false;
      }
    }
    
    bool CUSBStorDrive::m_Read10WithBuffer(HANDLE hDrive,DWORD dwStartBlock,BYTE *pBuf,DWORD dwlength)
    {
      SCSI_PASS_THROUGH_WITH_BUFFERS SCSIDataWithBuf =
      { 0};
      DWORD ReturnLen = 0;
      BOOL bResult = false;
      WORD wBlocks = 0x0001;
      BYTE *ptr = NULL;
      int iCount = 0;
    
      if (hDrive == NULL) return false;
      if (pBuf == NULL) return false;
    
      SCSIDataWithBuf.Spt.Length = sizeof(SCSI_PASS_THROUGH);
      SCSIDataWithBuf.Spt.SenseInfoLength = SPT_SENSE_LENGTH;
      SCSIDataWithBuf.Spt.DataTransferLength = SPTWB_DATA_LENGTH;
      SCSIDataWithBuf.Spt.PathId = 0;
      SCSIDataWithBuf.Spt.TargetId = 1;
      SCSIDataWithBuf.Spt.Lun = 0;
      SCSIDataWithBuf.Spt.TimeOutValue = TIME_OUT;
      SCSIDataWithBuf.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
      SCSIDataWithBuf.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
      SCSIDataWithBuf.Spt.DataIn = SCSI_IOCTL_DATA_IN;
      SCSIDataWithBuf.Spt.CdbLength = 12;
      SCSIDataWithBuf.Spt.Cdb[0] = UFI_READ_10;
      SCSIDataWithBuf.Spt.Cdb[1] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[2] = (dwStartBlock & 0xFF000000) >> 24;
      SCSIDataWithBuf.Spt.Cdb[3] = (dwStartBlock & 0x00FF0000) >> 16;
      SCSIDataWithBuf.Spt.Cdb[4] = (dwStartBlock & 0x0000FF00) >> 8;
      SCSIDataWithBuf.Spt.Cdb[5] = (dwStartBlock & 0x000000FF);
      SCSIDataWithBuf.Spt.Cdb[6] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[7] = (wBlocks & 0xFF00) >> 8;
      SCSIDataWithBuf.Spt.Cdb[8] = (wBlocks & 0x00FF);
      SCSIDataWithBuf.Spt.Cdb[9] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[10] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[11] = 0x00;
    
      ptr = pBuf;
      iCount = dwlength / SPTWB_DATA_LENGTH;
      if ((dwlength % SPTWB_DATA_LENGTH) > 0) iCount++;
      int iPos = 0;
      for (int i=0; i < iCount; i++)
      {
        SCSIDataWithBuf.Spt.Cdb[2] = (dwStartBlock & 0xFF000000) >> 24;
        SCSIDataWithBuf.Spt.Cdb[3] = (dwStartBlock & 0x00FF0000) >> 16;
        SCSIDataWithBuf.Spt.Cdb[4] = (dwStartBlock & 0x0000FF00) >> 8;
        SCSIDataWithBuf.Spt.Cdb[5] = (dwStartBlock & 0x000000FF);
    
        bResult = DeviceIoControl(
            hDrive,
            IOCTL_SCSI_PASS_THROUGH,
            &SCSIDataWithBuf,
            sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS),
            &SCSIDataWithBuf,
            //length,
            sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS),
            &ReturnLen,
            FALSE);
        if (bResult)
        {
          iPos = (i * 100)/iCount;
          if (m_pWaitUISetPosProc != NULL)
          {
            (m_pWaitUISetPosProc)(0,iPos);
          }
          if ((i+1) == iCount)  //last
          {
            memcpy(ptr,SCSIDataWithBuf.ucDataBuf,dwlength);
            dwlength = 0;
          }
          else
          {
            memcpy(ptr,SCSIDataWithBuf.ucDataBuf,SPTWB_DATA_LENGTH);
            dwlength -= SPTWB_DATA_LENGTH;
          }
          ptr += SPTWB_DATA_LENGTH;
          dwStartBlock ++;
        }
        else
        {
          m_LastErrCode = GetLastError();
          break;
        }
      }
      return bResult;
    }
    
    bool CUSBStorDrive::m_Write10WithBuffer(HANDLE hDrive,DWORD dwStartBlock,BYTE *pBuf,DWORD dwlength)
    {
      SCSI_PASS_THROUGH_WITH_BUFFERS SCSIDataWithBuf =
      { 0};
      DWORD ReturnLen = 0;
      WORD wBlocks = 0x0001;
      BYTE *ptr = NULL;
      BOOL bResult = false;
      int iCount = 0;
    
      if (hDrive == NULL) return false;
      if (pBuf == NULL) return false;
    
      SCSIDataWithBuf.Spt.Length = sizeof(SCSI_PASS_THROUGH);
      SCSIDataWithBuf.Spt.SenseInfoLength = SPT_SENSE_LENGTH;
      SCSIDataWithBuf.Spt.DataTransferLength = SPTWB_DATA_LENGTH;
      SCSIDataWithBuf.Spt.PathId = 0;
      SCSIDataWithBuf.Spt.TargetId = 1;
      SCSIDataWithBuf.Spt.Lun = 0;
      SCSIDataWithBuf.Spt.TimeOutValue = TIME_OUT;
      SCSIDataWithBuf.Spt.SenseInfoOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucSenseBuf);
      SCSIDataWithBuf.Spt.DataBufferOffset = offsetof(SCSI_PASS_THROUGH_WITH_BUFFERS,ucDataBuf);
      SCSIDataWithBuf.Spt.DataIn = SCSI_IOCTL_DATA_OUT;
      SCSIDataWithBuf.Spt.CdbLength = 12;
      SCSIDataWithBuf.Spt.Cdb[0] = UFI_WRITE_10;
      SCSIDataWithBuf.Spt.Cdb[1] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[2] = (dwStartBlock & 0xFF000000) >> 24;
      SCSIDataWithBuf.Spt.Cdb[3] = (dwStartBlock & 0x00FF0000) >> 16;
      SCSIDataWithBuf.Spt.Cdb[4] = (dwStartBlock & 0x0000FF00) >> 8;
      SCSIDataWithBuf.Spt.Cdb[5] = (dwStartBlock & 0x000000FF);
      SCSIDataWithBuf.Spt.Cdb[6] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[7] = (wBlocks & 0xFF00) >> 8;
      SCSIDataWithBuf.Spt.Cdb[8] = (wBlocks & 0x00FF);
      SCSIDataWithBuf.Spt.Cdb[9] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[10] = 0x00;
      SCSIDataWithBuf.Spt.Cdb[11] = 0x00;
    
      ptr = pBuf;
      iCount = dwlength / SPTWB_DATA_LENGTH;
      if ((dwlength % SPTWB_DATA_LENGTH) > 0) iCount++;
      int iPos = 0;
    
      for (int i=0; i < iCount; i++)
      {
        SCSIDataWithBuf.Spt.Cdb[2] = (dwStartBlock & 0xFF000000) >> 24;
        SCSIDataWithBuf.Spt.Cdb[3] = (dwStartBlock & 0x00FF0000) >> 16;
        SCSIDataWithBuf.Spt.Cdb[4] = (dwStartBlock & 0x0000FF00) >> 8;
        SCSIDataWithBuf.Spt.Cdb[5] = (dwStartBlock & 0x000000FF);
        memset(SCSIDataWithBuf.ucDataBuf,0x00,SPTWB_DATA_LENGTH);
        if (dwlength >= SPTWB_DATA_LENGTH)
        {
          memcpy(SCSIDataWithBuf.ucDataBuf,ptr,SPTWB_DATA_LENGTH);
        }
        else
        {
          memcpy(SCSIDataWithBuf.ucDataBuf,ptr,dwlength);
        }
        bResult = DeviceIoControl(
            hDrive,
            IOCTL_SCSI_PASS_THROUGH,
            SCSIDataWithBuf,
            sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS),
            SCSIDataWithBuf,
            //length,
            sizeof(SCSI_PASS_THROUGH_WITH_BUFFERS),
            ReturnLen,
            FALSE);
        if (bResult)
        {
          iPos = (i * 100)/iCount;
          if (m_pWaitUISetPosProc != NULL)
          {
            (m_pWaitUISetPosProc)(0,iPos);
          }
          ptr += SPTWB_DATA_LENGTH;
          dwStartBlock ++;
          dwlength -= SPTWB_DATA_LENGTH;
        }
        else
        {
          m_LastErrCode = GetLastError();
          break;
        }
      }
      return bResult;
    }
  • 相关阅读:
    python 的 类属性 与 实例属性
    python 的 append 和 extend
    机器学习的最佳入门学习资源
    各种排序算法探讨与实现
    C++基础:C++中vector使用简介
    C++基础:C++中的explicit关键字
    差分约束(poj 1201
    codeforeces 547C
    2015 7月 做题记录
    set&map
  • 原文地址:https://www.cnblogs.com/shangdawei/p/3164044.html
Copyright © 2011-2022 走看看