使用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 ...
随机推荐
- webpack轻松入门教程
webpack之傻瓜式教程及前端自动化入门 接触webpack也有挺长一段时间了,公司的项目也是一直用着webpack在打包处理,但前几天在教新人的情况下,遇到了一个问题,那就是:尽管网上的webpa ...
- android设备休眠
从上面的连接里面找到了一些资料: 如果一开始就对Android手机的硬件架构有一定的了解,设计出的应用程序通常不会成为待机电池杀手,而要设计出正确的通信机制与通信协议也并不困难.但如果不去了解而盲目设 ...
- 洛谷P3621风铃
传送门啦 分析: 这个题看起来像是个树形dp,嗯,就是看起来像. 所以我们就按树形dp的思路去分析就好了,这个题是一个树形dp的变形题. 和以前建树是一样的,我们用邻接表来进行储存.利用邻接表的特性, ...
- js交互
Js和native交互的方法与问题 实现JS和Native交互有两种方式: 第一种:shouldOverrideUrlLoading(WebView view, String url) 通过给WebV ...
- centos7 vnc 无法systemctl启动
1.centos7 vnc 无法systemctl启动 报错如下:Failed to start Remote desktop service (VNC) 2.解决办法 错误服务脚本名 vncserv ...
- 一行代码实现Okhttp,Retrofit,Glide下载上传进度监听
https://mp.weixin.qq.com/s/bopDUFMB7EiK-MhLc3KDXQ essyan 鸿洋 2017-06-29 本文作者 本文由jessyan投稿. jessyan的博客 ...
- USACO 完结的一些感想
其实日期没有那么近啦……只是我偶尔还点进去造成的,导致我没有每一章刷完的纪念日了 但是全刷完是今天啦 讲真,题很锻炼思维能力,USACO保持着一贯猎奇的题目描述,以及尽量不用高级算法就完成的题解……例 ...
- JS图片滚动代码(无缝、平滑)
非常平滑的JS图片滚动特效代码,无缝循环,速度可自定义,鼠标悬停时停止.它的特点是JS和图片地址分离,这样做你就经易的从数据库动态调用每张图片的地址,方便控制,因此它非常的应用. <!DOCTY ...
- 评分卡模型中的IV和WOE详解
1.IV的用途 IV的全称是Information Value,中文意思是信息价值,或者信息量. 我们在用逻辑回归.决策树等模型方法构建分类模型时,经常需要对自变量进行筛选.比如我们有200个候选 ...
- Java_集合与泛型
Collection 集合,集合是java中提供的一种容器,可以用来存储多个数据.在前面的学习中,我们知道数据多了,可以使用数组存放或者使用ArrayList集合进行存放数据.那么,集合和数组既然都是 ...