//=====================================================================
//TITLE:
// WinCE获取SD卡序列号
//AUTHOR:
// norains
//DATE:
// Thursday 25-February-2011
//Environment:
// Visual Studio 2005
// Windows CE 6.0
// Telechips TCC89x
//=====================================================================
WinCE的设备,估计会和SD卡打交道的应该不在少数。特别是一些软件,比方导航地图之类,加密数据用的便是SD卡的序列号。不过,严格来说,在WinCE下面并没有专门针关于SD卡序列号的获取函数,而是针对Storage的。只不过SD卡也是Storage的一种,所以天然也能够被获取。
SD卡序列号的获取,是需求经过驱动的的。这么一说的话,了解的朋友或许就了解流程了:首要调用CreateFile翻开驱动,接着运用DeviceIoControl来获取序列号,最终则是调用CloseHandle进行封闭。
一步一步来,先看看CreateFile的调用,如:
[cpp] view plaincopyHANDLE hDisk = CreateFile(TEXT(DSK2:),
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
这段代码没什么问题,或许咱们比较关心的是DSK2:这个参数的来历。或是说,我怎么承认这个参数。许多朋友或许会错以为,当咱们SD卡刺进到设备中,在我的设备会呈现Storage Card分区,那么CreateFile的第一个形参就应该是它。但实际上这样是过错的,传入的形参并不是分区名,而应该是驱动名。而这个驱动名的承认,能够经过控制面板的存储器承认,如图:
图中的DSK1:是设备中NAND FLASH的驱动,而DSK2:则是SD卡的。或许有朋友问了,我怎么判别哪个是SD卡的呢?其实这是一个很简略的工作:没刺进SD卡的时分检查一次,刺进SD卡的时分再检查一次,多出的那个便是SD卡了。~
接着咱们就有必要调用DeviceIoControl函数了,如下代码所示:
[cpp] view plaincopyPSTORAGE_IDENTIFICATION pStoreInfo = (PSTORAGE_IDENTIFICATION) new BYTE[300];
DeviceIoControl(hDisk,
IOCTL_DISK_GET_STORAGEID,
NULL,
0,
pStoreInfo,
BUFFER_SIZE,
dwBytesRet,
NULL);
IOCTL_DISK_GET_STORAGEID是设备恳求标识符,这个应该也好了解。假如你的代码编译时该标识符没有界说,那么你应该是没有包括Diskio.h文件。或许比较隐晦的是pStoreInfo,为什么要new个300byte的空间,然后又转换为PSTORAGE_IDENTIFICATION指针呢?这个咱们有必要要从STORAGE_IDENTIFICATION结构说起。
STORAGE_IDENTIFICATION结构界说如下:
[cpp] view plaincopytypedef struct _STORAGE_IDENTIFICATION {
DWORD dwSize;
DWORD dwFlags;
DWORD dwManufactureIDOffset;
DWORD dwSerialNumOffset;
} STORAGE_IDENTIFICATION, *PSTORAGE_IDENTIFICATION;
dwSize是结构体和标识符的巨细,dwFlags标志着标识符是否可用,dwManufactureIDOffset是标识符的中的厂家ID偏移方位,最终的dwSerialNumOffset则是标识符中的序列号偏移方位。完了?是的,完了,便是这几样东西。那么,疑问来了,那标识符在哪里?别急,咱们来看看回来回来数据的存储方法,如图:
图中的灰色部分为STORAGE_IDENTIFICATION的成员,其巨细为sizeof(STORAGE_IDENTIFICATION),是固定值;而蓝色的部分,则是咱们分配的内存减去结构体后的巨细,容量跟着咱们分配的内存而改动。在这里略微回来来看一下代码,为什么咱们代码平分配了个300Byte的空间呢?其实300这个数值是随意的,假如你设备的标识符大于这个数值,能够进行修正。但关于SD卡来说,标识符也便是10位,加上STORAGE_IDENTIF%&&&&&%ATION的巨细,300的空间彻底足够了。
接着从图中能够知道,在紧跟着结构体之后的是ManufactureID和SerialNumber的数值。那么这两个数值的方位应该怎么承认呢?那便是经过dwManufactureIDOffset和dwSerialNumOffset的数值来承认,这也便是为什么图中dwManufactureIDOffset方块延伸出来的箭头会指向ManufactureID前端的原因。
关于ManufactureID和SerialNumber还有一些当地需求留意的。这两个号码合起来的长度是不固定的,但咱们能经过结束是否为’/0’来判别标识符是否结束。别的还有一点,ManufactureID和SerialNumber之间是没有分隔符的,咱们只能经过(dwSerialNumOffset – dwManufactureIDOffset)来承认。但这个仍是需求有前提条件的,便是dwSerialNumOffset和dwManufactureIDOffset都不能为0,由于为0时,就意味着该标识符无效。简略点来说,假如dwSerialNumOffset这个偏移量的数值为0,那么意味着回来的数值中并没有ManufactureID。
结构了解之后,咱们就很简单获取这两个标志的开始地址了:
[cpp] view plaincopychar *pManufactureID = reinterpret_cast
char *pSerialNum = reinterpret_cast
接下来的工作或许就不必细说了,无非便是依据开始地址来仿制字符串。最终,便是调用CloseHandle来封闭驱动句柄了。
流程介绍结束,但还不是文章的结束。本文的最终,让咱们来看看一个完好的获取标识符的函数,代码如下所示:
[cpp] view plaincopyBOOL GetStorageIdentification(std::wstring strDiskName,std::string strManufactureID,std::string strSerialNum)