按扇区读取Windows Mobile的数据
http://dev.mmarket.com/cmdn/bbs/redirect.php?tid=114&goto=lastpost
在移动设备程序开发中,许多地方我们可以参考桌面电脑的开发方式,例如,MFC,不仅桌面电脑支持,而且基于Windows Mobile 5移动设备也支持。
/ e: l) M# D5 S6 Y% s0 D ~: s3 l; Y0 h# d
由于移动设备的体系架构与桌面电脑类似,都是由CPU,内存,非易失性存储器组成,因此,对于文件系统管理等方面,将PC上的文件系统引入到移动设备是个非常不错的选择。比如,Windows Mobile 5,(基于windows ce 5.0的内核),就采用了TFAT32的文件格式,相对于FAT32文件系统,TFAT32增强了安全性。中国移动开发者社区; m4 i) M1 F! k! M
7 U! q# ?7 m8 F+ /8 ?/ ^* p
微软的API中提供了CreateFile函数,这个对于从事编程的人员来说应该是非常熟悉不过的了,CreateFile函数不仅能够操作文件,还能操作各种IO设备,比如磁盘,COM口等。由于Windows Mobile 5将整个非易失性存储器(往往是FLASH,下面就将非易失性存储器粗略地当成FLASH,并以此称呼)划分成若干个逻辑分区,往往是3个,操作系统区,数据备份区,用户区。因此就可以使用CreateFile函数对这些逻辑磁盘操作了。& I! g2 P3 n3 s1 W8 z/ |# H
开发者社区论坛: T X; ]6 d0 J6 g: O
首先,可以用FindFirstStore和FindnextStore函数查找存储设备,这些函数需要用到storemgr.h和storeapi.lib文件,这两个文件在Windows Mobile 5的SDK中都有,用上述函数能够得到存数设备的设备名,例如DSK:1等,这些将作为CreateFile的参数。我的设备插上SD卡后得到的设备名有四个,分别是DSK1:到DSK4:,其中DSK1是系统所在分区,文件格式未知,DSK2为备份区,就是恢复出厂设置的时候所用到的区域,DSK3是用户数据区,我们平常存放的短信啊,音乐文件啊都存放在这,也是用户唯一能使用的地方,DSK4就是SD卡。dev.mmarket.com* m2 S" ?! /& w& P
6 B4 p! @7 f- d! G
用CreateFile打开设备后,不能用ReadFile去读取数据,具体原因不清楚,可能是文件系统驱动未提供支持吧。如何读取数据?用DeviceIoControl函数,设置读的标志位DISK_IOCTL_READ,同时需要使用SG_REQ作为该函数的第三个参数,SG_REQ是一个结构体,里面指明了需要读取的磁盘的起始sector和读取sector的数量,该结构体包含在Diskio.h中,不过Diskio.h文件windows mobile 5.0的SDK没有,我是从PB5.0中的目录下拷贝过去的。" i( q0 T" l% j% J" [4 f
7 D" A$ F5 q2 @$ `6 T5 B) T) ? @
由于调用FindFirstStore函数和FindNextStore函数能够获取磁盘的扇区数,所以只要根据获得的扇区数,就能完全读取Windows Mobile各个磁盘的数据。之后将其写入到U盘等设备中,那么打开U盘就像打开Windows Mobile设备一样了。不过其中发现了一个问题,读取用户区的数据之后,必须将头部的512*2的字节数据去掉,然后写入U盘才能打开U盘,不然会提示U盘未格式化。不知道是什么原因,可能是TFAT和FAT之间的区别吧。
摘自:http://blog.163.com/wu_congchao/blog/static/354264720088253476730/
void enumStore()
{
STOREINFO stinfo = {0};
HANDLE hPart = INVALID_HANDLE_VALUE;
HANDLE hstore;
TCHAR szInfo[100] = _T("");
stinfo.cbSize = sizeof(STOREINFO);
hstore = FindFirstStore(&stinfo);
if(hstore!=INVALID_HANDLE_VALUE)
{
do {
RETAILMSG(1,(TEXT("Partion number:%ld /n"),stinfo.dwPartitionCount ));
Size2String(stinfo.snNumSectors * stinfo.dwBytesPerSector,szInfo,100);
RETAILMSG(1,(TEXT("enumPartion:%s szInfo=%s/n"),stinfo.szDeviceName,szInfo));
Size2String(stinfo.dwBytesPerSector, szInfo, 100);
RETAILMSG(1,(TEXT("enumPartion:%s dwBytesPerSector=%s/n"),stinfo.szDeviceName,szInfo));
enumPartion(stinfo.szDeviceName,"//Hard Disk2//");
} while(FindNextStore(hstore, &stinfo));
}
FindCloseStore(hstore);
}
LONGLONG enumPartion(LPCTSTR deviceName,CString szPartionName )
{
PARTINFO partInfo = {0};
STOREINFO stinfo = {0};
HANDLE hPart= INVALID_HANDLE_VALUE;
HANDLE hstore=INVALID_HANDLE_VALUE;
TCHAR szInfo[100] = _T("");
stinfo.cbSize = sizeof(STOREINFO);
partInfo.cbSize = sizeof(PARTINFO);
hstore = OpenStore(deviceName);
if(INVALID_HANDLE_VALUE!=hstore)
{
if(GetStoreInfo(hstore,&stinfo)==FALSE)
return 0;
hPart=FindFirstPartition(hstore, &partInfo);
if(hPart==INVALID_HANDLE_VALUE)
RETAILMSG(1,(TEXT("no find Partion info")));
if(hPart!=INVALID_HANDLE_VALUE)
{
do {
RETAILMSG(1,(TEXT("enumPartion:%s /n"),partInfo.szVolumeName));
if(szPartionName.Right(1).Compare(_T("//"))==0)
szPartionName=szPartionName.Left(szPartionName.GetLength()-1);
if(szPartionName.Compare(partInfo.szVolumeName)==0)
{
CloseHandle(hstore);
FindClosePartition(hPart);
return partInfo.snNumSectors*stinfo.dwBytesPerSector;
}
} while(FindNextPartition(hPart, &partInfo));
}
}
CloseHandle(hstore);
FindClosePartition(hPart);
return 0L;
}
一些相关代码:
#define DEVICE_NAME _T("DSK1:")
#define PARTITION_NAME _T("Part02")
#define DLL_NAME _T("Fatutil.dll")
typedef DWORD (*PFN_FORMAT_VOLUME)(HANDLE hVolume,PDISK_INFO pdi, PFORMAT_OPTIONS pfo, PFN_PROGRESS pfnProgress,PFN_MESSAGE pfnMessage);
CFormatDlg *FormatProgress;
void DiskFomratProgress( DWORD dwNewPercent)
{
RETAILMSG(0, (TEXT("Source Disk Formatted %d /n"),dwNewPercent));
::PostMessage(FormatProgress->GetSafeHwnd(),FORMAT_PERCENT_MESSAGE,NULL,(LPARAM)&(dwNewPercent));
}
BOOL FormatDisk()
{
HANDLE hStore;
hStore=OpenStore(DEVICE_NAME);
if(hStore==INVALID_HANDLE_VALUE)
{
RETAILMSG(1, (TEXT("FormatDisk OpenStore error!!/n")));
return FALSE;
}
HANDLE hPart;
hPart=OpenPartition(hStore,PARTITION_NAME);
if(hPart==INVALID_HANDLE_VALUE)
{
RETAILMSG(1, (TEXT("FormatDisk OpenPartition error!!/n")));
return FALSE;
}
CloseHandle(hStore);
FORMAT_OPTIONS pfo;
//if dwClusSize set to 0 ,the FormatValume() in the dll file will caculate;
//also you could set to 128*512;
pfo.dwClusSize=0;
pfo.dwRootEntries=512;
pfo.dwFatVersion=16;
pfo.dwNumFats=2;
//Careful: Don't set to FATUTIL_FORMAT_TFAT,or it will creat a hidden folder,
//and all of the files, which be copied to harddisk by ActiveSync, are there,
//so you could not lauch the OS!
pfo.dwFlags=FATUTIL_FULL_FORMAT;
CString szDllPath=_T("//Hard Disk//");
szDllPath+=DLL_NAME;
HINSTANCE hUtilDll = NULL;
PFN_FORMAT_VOLUME pfnFormatVolume=NULL;
hUtilDll = LoadLibrary (szDllPath);
if(hUtilDll==NULL)
{
int err=GetLastError();
RETAILMSG(1, (TEXT("FormatDisk LoadLibrary error=%d!/n"),err));
return FALSE;
}
pfnFormatVolume = (PFN_FORMAT_VOLUME)GetProcAddress(hUtilDll, TEXT("FormatVolume"));
if(pfnFormatVolume==NULL)
{
RETAILMSG(1, (TEXT("FormatDisk GetProcAddress error!!/n")));
return FALSE;
}
//must dismount the partition,or the FormatVolumeUI() failed
DismountPartition(hPart);
RETAILMSG(1, (TEXT("start format the disk.....!/n")));
// if(pfnFormatVolume(hPart,NULL,&pfo,NULL,NULL)!=ERROR_SUCCESS)
if(pfnFormatVolume(hPart,NULL,&pfo,(PFN_PROGRESS)DiskFomratProgress,NULL)!=ERROR_SUCCESS)
{
RETAILMSG(1, (TEXT("FormatDisk pfnFormatVolume error!!/n")));
return FALSE;
}
//finished format, mount partition
MountPartition(hPart);
CloseHandle(hPart);
RETAILMSG(1, (TEXT("FormatDisk ok!!/n")));
return TRUE;
}