使用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[ ];
BYTE Data[ ];
} 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[]; m_CloseDrive();
memset(DriveStr,0x00,); 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
,// 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 =
{ };
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 = ;
SCSIInfo.Spt.DataIn = SCSI_IOCTL_DATA_IN;
SCSIInfo.Spt.CdbLength = ;
SCSIInfo.Spt.Cdb[] = UFI_INQUIRY; // inquiry opcode
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = sizeof(SCSIInfo.Data);
SCSIInfo.Spt.Cdb[] = 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 =
{ };
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 = ;
SCSIInfo.Spt.DataIn = SCSI_IOCTL_DATA_IN;
SCSIInfo.Spt.CdbLength = ;
SCSIInfo.Spt.Cdb[] = UFI_READ_CAPACITY; // Read Capacity opcode
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 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 =
{ };
DWORD ReturnLen = ;
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 = ;
SCSIInfo.Spt.DataIn = SCSI_IOCTL_DATA_IN;
SCSIInfo.Spt.CdbLength = ;
SCSIInfo.Spt.Cdb[] = UFI_READ_FORMAT_CAPACITY; // Read format Capacity opcode
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = wAllocLeng >> ;//Allocation Length (MSB)
SCSIInfo.Spt.Cdb[] = wAllocLeng & 0x00FF;//Allocation Length (LSB)
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 0x00;
SCSIInfo.Spt.Cdb[] = 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 =
{ };
DWORD ReturnLen = ;
BOOL bResult = false;
WORD wBlocks = 0x0001;
BYTE *ptr = NULL;
int iCount = ; 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 = ;
SCSIDataWithBuf.Spt.TargetId = ;
SCSIDataWithBuf.Spt.Lun = ;
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 = ;
SCSIDataWithBuf.Spt.Cdb[] = UFI_READ_10;
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0xFF000000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x00FF0000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x0000FF00) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x000000FF);
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = (wBlocks & 0xFF00) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (wBlocks & 0x00FF);
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = 0x00; ptr = pBuf;
iCount = dwlength / SPTWB_DATA_LENGTH;
if ((dwlength % SPTWB_DATA_LENGTH) > ) iCount++;
int iPos = ;
for (int i=; i < iCount; i++)
{
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0xFF000000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x00FF0000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x0000FF00) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (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 * )/iCount;
if (m_pWaitUISetPosProc != NULL)
{
(m_pWaitUISetPosProc)(,iPos);
}
if ((i+) == iCount) //last
{
memcpy(ptr,SCSIDataWithBuf.ucDataBuf,dwlength);
dwlength = ;
}
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 =
{ };
DWORD ReturnLen = ;
WORD wBlocks = 0x0001;
BYTE *ptr = NULL;
BOOL bResult = false;
int iCount = ; 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 = ;
SCSIDataWithBuf.Spt.TargetId = ;
SCSIDataWithBuf.Spt.Lun = ;
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 = ;
SCSIDataWithBuf.Spt.Cdb[] = UFI_WRITE_10;
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0xFF000000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x00FF0000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x0000FF00) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x000000FF);
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = (wBlocks & 0xFF00) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (wBlocks & 0x00FF);
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = 0x00;
SCSIDataWithBuf.Spt.Cdb[] = 0x00; ptr = pBuf;
iCount = dwlength / SPTWB_DATA_LENGTH;
if ((dwlength % SPTWB_DATA_LENGTH) > ) iCount++;
int iPos = ; for (int i=; i < iCount; i++)
{
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0xFF000000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x00FF0000) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (dwStartBlock & 0x0000FF00) >> ;
SCSIDataWithBuf.Spt.Cdb[] = (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 * )/iCount;
if (m_pWaitUISetPosProc != NULL)
{
(m_pWaitUISetPosProc)(,iPos);
}
ptr += SPTWB_DATA_LENGTH;
dwStartBlock ++;
dwlength -= SPTWB_DATA_LENGTH;
}
else
{
m_LastErrCode = GetLastError();
break;
}
}
return bResult;
}
使用Device IO Control 讀寫 USB Mass Storage的更多相关文章
- usb mass storage device
Problem adding USB host device to KVM Windows guest machine. Status: CLOSED CURRENTRELEASE Aliases ...
- USB Mass Storage协议分析
目录 简介 指令数据和状态协议 CBW指令格式 CSWCommand Status Wrapper状态格式 SCSI命令集 Format Unit Inquiry MODE SELECT 简介 USB ...
- USB Mass Storage大容量存储的基本知识
http://www.crifan.com/files/doc/docbook/usb_disk_driver/release/htmls/ch02_msc_basic.html 目录 2.1. US ...
- USB Mass Storage communication with PassThrough / more than 64K data length
http://social.msdn.microsoft.com/Forums/windowsdesktop/zh-CN/35620a05-43be-46a8-8cbe-846bc8295d85/us ...
- Android USB Connections Explained: MTP, PTP, and USB Mass Storage
Android USB Connections Explained: MTP, PTP, and USB Mass Storage Older Android devices support USB ...
- USB Mass Storage学习笔记-STM32+FLASH实现U盘
一.内容概述 采用STM32内部自带USB控制器外加大页NAND FLASH K9F1G08U0A实现一个128M的U盘. 1.STM32的USB控制器 STM32F103的MCU自带USB从控制器 ...
- usb mass storage之旅
前面总结了usb hid keyboard,现在总结usb mass storage,在枚举阶段没什么好总结的,hid和mass storage差不多,都是同样的枚举过程,但是在他们的配置描述符.接口 ...
- USB mass storage协议
这一节主要把在实现“linux模拟U盘功能”过程中的一些调试过程记录下来,并加以解析. 一.背景知识 1.USB Mass Storage类规范概述 USB 组织在univers ...
- 实现Linux下的U盘(USB Mass Storage)驱动
如何实现Linux下的U盘(USB Mass Storage)驱动 版本:v0.7 How to Write Linux USB MSC (Mass Storage Class) Driver Cri ...
随机推荐
- MySQL基础 - 视图
创建视图: 假设要将posts表的前十条数据作为视图 mysql> CREATE VIEW view_test AS SELECT * FROM POSTS LIMIT 10; 使用: 可以把视 ...
- [android]解析XML文件的方法有三种:PULL,DOM,SAM
PULL 的工作原理: XML pull提供了开始元素和结束元素.当某个元素开始时,可以调用parser.nextText从XML文档中提取所有字符数据.当解析到一个文档结束时,自动生成EndDocu ...
- eclipse中Maven项目jar问题
eclipse中Maven项目jar包下载下来了,不然我们import是时候根本导入不进来,网上的方法都试过了,Maven仓库也清空过后重新下载过了,都解决不了. 后来发现虽然jar包是下载下来了,可 ...
- 从一道简单的dp题中学到的...
今天想学点动态规划的知识,于是就看了杭电的课件,数塔问题啊,LCS啊都是比较经典的动规了,然后随便看了看就开始做课后练习题... HDOJ 1421 搬寝室 http://acm.hdu.edu.cn ...
- iOS网络加载图片缓存与SDWebImage
加载网络图片可以说是网络应用中必备的.如果单纯的去下载图片,而不去做多线程.缓存等技术去优化,加载图片时的效果与用户体验就会很差. 一.自己实现加载图片的方法 tips: *iOS中所有网络访问都是异 ...
- switch case语句
五.switch case语句 1.格式 Switch(表达式) { case 表达式:语句块 break: … default break: } 2.例题 输入年份.月份.日期,判断是否是闰年,并且 ...
- asp.net 微信公众号源码
需要源码,请加QQ:858-048-581 功能菜单 该源码功能十分的全面,具体介绍如下:1.菜单回复:微信自定义回复.关注时回复.默认回复.文本回复.图文回复.语音回复. 请求回复记录.LBS位置回 ...
- mycat性能调优
http://blog.csdn.net/wangshuang1631/article/details/69056070
- babel使用中不想使用 严格模式 如何去除?
使用babel进行es6转es5时,默认转化之后是严格模式,有些时候我们想去除严格模式. 解决方法如下 安装 babel-plugin-transform-remove-strict-mode 依赖 ...
- bzoj 1820 dp
最普通dp要4维,因为肯定有一个在上一个的位置,所以可以变为3维,然后滚动数组优化一下. #include<bits/stdc++.h> #define LL long long #def ...