使用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 ...
随机推荐
- sqlserver中的全局变量总结
@@CONNECTIONS返回自上次启动 Microsoft? SQL Server? 以来连接或试图连接的次数.@@CPU_BUSY返回自上次启动 Microsoft? SQL Server? 以来 ...
- Python获取指定文件夹下的文件名
本文采用os.walk()和os.listdir()两种方法,获取指定文件夹下的文件名. 一.os.walk() 模块os中的walk()函数可以遍历文件夹下所有的文件. os.walk(top, t ...
- HBase 入门笔记-数据落地篇
一.前言 关于数据落地方面,HBase官网也有相关介绍.本文主要介绍一下实际工作中涉及的数据存储方面的一些经验和技巧,主要涉及表rowkey设计.数据落地方案 二.表设计 相对于MySQL等关系型数据 ...
- 中断、轮询、事件驱动、消息驱动、数据流驱动(Flow-Driven)?
轮询.事件驱动.消息驱动.流式驱动 ---数据流驱动 Unidirectional Architecture? 中断.事件.消息这样一种机制来实现更好的在多任务系统里运行... 阻塞,非阻塞同步,异步 ...
- mysql中的包含语句INSTR的使用
1.目前测试百万级数据,效率还是相当可观,感觉比like更精准! 例句 今天项目遇到一个问题,每个用户都有自己的所属渠道,当登录后台操作时,要列出隶属于自己拥有渠道的用户列表,当初想到使用全部遍历出来 ...
- VM ESXI 服务器虚拟化资料积累
编者按: 公司业务需求,公有云平台不能满足部署mac系统环境的需求,故租赁或托管物理机自行虚拟化,使用的工具就是VM ESXI .从部署到应用都没有遇到过什么问题,但是在今天发生VMware vSph ...
- 第一个web程序(ServletRequest , ServletResponse)
一.ServletRequest 1.获取参数的方法(四种) > String getParameter(String name): 根据请求参数的名字, 返回参数值. 若请求参数有多个值(例如 ...
- Ionic Js二十:选项卡栏操作
ion-tabs ion-tabs 是有一组页面选项卡组成的选项卡栏.可以通过点击选项来切换页面. 对于 iOS,它会出现在屏幕的底部,Android会出现在屏幕的顶部(导航栏下面). 用法 < ...
- 21:包含min函数的栈
import java.util.Stack; /** * 面试题21:包含min函数的栈 * 定义栈的数据结构,请在该类型中实现一个能够得到栈最小元素的min函数. */ public class ...
- lnmp 一键安装包
系统需求: CentOS/RHEL/Fedora/Debian/Ubuntu/Raspbian Linux系统 需要5GB以上硬盘剩余空间 需要128MB以上内存(如果为128MB的小内存VPS,Xe ...