/* (C) 2003-2007 Willem Jan Hengeveld * Web: http://www.xs4all.nl/~itsme/ * http://wiki.xda-developers.com/ * * $Id: tffsreader.cpp 1916 2008-07-30 14:06:20Z itsme $ */ #include #include "storeinfo.h" #include "DiskReader.h" #include "debug.h" #include "ptrutils.h" #include "stringutils.h" #include "FlashDrvReader.h" #include "OnDiskReader.h" #include "TffsDiskReader.h" #include "WinDiskReader.h" #include "cever_deps.h" #ifdef WITHDEBUG #define diskdebug debug #else #define diskdebug while(0) #endif // c:\local\WINCE420\PUBLIC\COMMON\SDK\INC\storemgr.h // #include // for DISK_INFO // todo: move GetDiskInfo from itsutils.cpp to somewhere else. ( like windiskreader.cpp ) int GetDiskInfo(HANDLE hDsk, DISK_INFO &info); #include "cenk.h" #include "kernelmisc.h" bool Disk_GetDiskParams(HANDLE hDisk, DWORD dwBinaryPartitionNr, DWORD &dwBlockSize, DWORD &dwSectorSize); bool Disk_GetDiskSize(HANDLE hDisk, DWORD dwBinaryPartitionNr, ULONGLONG &llDiskSize); bool istffsdisk(DWORD dwBinpart) { return (dwBinpart<0x1000) || (dwBinpart>=BP_OTPSECTOR); } std::string cinfostring(const CINFO *ci) { if (ci) return stringformat("cinfo{%c%c%c%c, n=%d, svr=%08lx}", ci->acName[0], ci->acName[1], ci->acName[2], ci->acName[3], ci->cMethods, ci->pServer); else return "(null)"; } std::string handleinfostring(HANDLE h) { HDATA *hi= cvHandle2HDataPtr(h); return stringformat("hdata{hv=%08lx ci=%hs pvo=%08lx}", hi->hValue, cinfostring(hi->pci).c_str(), hi->pvObj); } HANDLE FindFirstStore(STOREINFO *psi) { return (FindFirstFileW( L"\\StoreMgr", (WIN32_FIND_DATA *)psi)); } bool GetStoreMgrList(std::vector& list) { STOREINFO si; memset(&si, 0, sizeof(STOREINFO)); si.cbSize= sizeof(STOREINFO); int currentStore = 0; HANDLE hEnumStores = FindFirstStore(&si); if (hEnumStores == INVALID_HANDLE_VALUE) { error("FindFirstFile"); return false; } list.push_back(si); while (PSLFindNextStore(hEnumStores, &si)) { list.push_back(si); } if (GetLastError()!=ERROR_NO_MORE_ITEMS) { error("PSLFindNextStore"); return !list.empty(); } if (!PSLFindCloseStore(hEnumStores)) { error("PSLFindCloseStore"); return !list.empty(); } return true; } void cvSTOREINFO2DevStoreinfo(const STOREINFO& si, DevStoreInfo& dsi) { dsi.llStoreSize= si.snNumSectors * si.dwBytesPerSector; wcsncpy(dsi.szDeviceName, si.szDeviceName, DEVICENAMESIZE); diskdebug("STOREINFO dev='%ls' store='%ls'", si.szDeviceName, si.szStoreName); diskdebug(" nsect=%x bpsect=%x free=%x maxpartsize=%x\n", (DWORD)si.snNumSectors, si.dwBytesPerSector, (DWORD)si.snFreeSectors, (DWORD)si.snBiggestPartCreatable); } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetStoreMgrList( DWORD cbInput, void *pbInput, DWORD *pcbOutput, GetStoreMgrListResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; GetStoreMgrListResult *pOut= *ppbOutput= NULL; std::vector list; if (!GetStoreMgrList(list)) { error("GetStoreMgrList"); return GetLastError(); } *pcbOutput= PTR_DIFF(pOut, pOut->storeInfo+list.size()); pOut= *ppbOutput= (GetStoreMgrListResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("LocalAlloc(%d)", *pcbOutput); return GetLastError(); } pOut->nStores = list.size(); for (size_t i=0 ; istoreInfo[i]); } return 0; } bool ReadVirtMemDword(void *pdw, DWORD *pdwVal) { if (!isValidPtr((DWORD)pdw)) return false; *pdwVal= *(DWORD*)pdw; return true; } bool GetSTRGHandleList(std::vector &list) { HDATA *hi= cvHandle2HDataPtr((HANDLE)GetCurrentThreadId()); HDATA *ha; ha=hi; KernelMode _km; do { DWORD dw; if (memcmp(ha->pci->acName, "STRG", 4)==0 && ReadVirtMemDword(MapPtrProc(ha->pvObj, ha->pci->pServer), &dw) && dw == 0x64615900) { list.push_back((DWORD)ha->hValue); } ha= (HDATA*)ha->linkage.fwd; } while (ha!=hi && ha!=NULL); if (ha==NULL) debug("!!! possibly not all handles searched: ha=NULL\n"); return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetSTRGHandleList( DWORD cbInput, void *pbInput, DWORD *pcbOutput, GetSTRGHandleListResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; GetSTRGHandleListResult *pOut= *ppbOutput= NULL; std::vector list; if (!GetSTRGHandleList(list)) { debug("ERROR: GetSTRGHandleList failed\n"); return ERROR_INTERNAL_ERROR; } *pcbOutput= PTR_DIFF(pOut, pOut->handle+list.size()); pOut= *ppbOutput= (GetSTRGHandleListResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("LocalAlloc(%d)", *pcbOutput); return GetLastError(); } pOut->nHandles= list.size(); for (size_t i=0 ; ihandle[i]= list[i]; } return 0; } void cvPARTINFO2DevPartitioninfo(const STOREINFO& si, const PARTINFO& pi, DevPartitionInfo& dpi) { dpi.llPartitionSize= pi.snNumSectors * si.dwBytesPerSector; wcsncpy(dpi.szPartitionName, pi.szPartitionName, PARTITIONNAMESIZE); diskdebug("PARTINFO name='%ls' filesys='%ls' volname='%ls'", pi.szPartitionName, pi.szFileSys, pi.szVolumeName); diskdebug(" end=%x type=%02x\n", (DWORD)pi.snNumSectors, pi.bPartType); } ITSUTILS_API HRESULT STDAPICALLTYPE ITGetPartitionList( DWORD cbInput, GetPartitionListParams *pbInput, DWORD *pcbOutput, GetPartitionListResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; GetPartitionListResult *pOut= *ppbOutput= NULL; std::vector list; HANDLE hStore = pbInput->hStore ? (HANDLE)pbInput->hStore : OpenStore(pbInput->szDeviceName); if (hStore == INVALID_HANDLE_VALUE) { error("GetStorePartitionlist: OpenStore('%ls')", pbInput->szDeviceName); return false; } STOREINFO si; if (!GetStoreInfo(hStore, si)) return GetLastError(); if (!GetStorePartitionlist(hStore, list)) return GetLastError(); if (pbInput->hStore==NULL) CloseHandle(hStore); *pcbOutput= PTR_DIFF(pOut, pOut->partInfo+list.size()); pOut= *ppbOutput= (GetPartitionListResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("LocalAlloc(%d)", *pcbOutput); return GetLastError(); } pOut->nPartitions = list.size(); for (size_t i=0 ; ipartInfo[i]); } return 0; } std::string GuidAsString(GUID& id) { return stringformat("{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", id.Data1, id.Data2, id.Data3, id.Data4[0], id.Data4[1], id.Data4[2], id.Data4[3], id.Data4[4], id.Data4[5], id.Data4[6], id.Data4[7]); } bool ReadDisk_Init(HANDLE hDisk, DWORD dwBinaryPartitionNr, ULONGLONG llOffset, DWORD dwLength, DWORD dwSectorSize) { switch (dwBinaryPartitionNr) { case BP_TFFSSECTOR: return true; case BP_WINCESECTOR: return true; case BP_OTPSECTOR: return true; case BP_FLASHDRV: return true; case BP_ONDISK: return true; default: return TFFS_BDK_InitRead(hDisk, dwBinaryPartitionNr, llOffset, dwLength, dwSectorSize); } } bool ReadDisk(HANDLE hDisk, DWORD dwBinaryPartitionNr, ULONGLONG llOffset, DWORD dwLength, BYTE *buffer, DWORD &dwRead, DWORD dwSectorSize) { diskdebug("readdisk: %d : %I64x %08lx ss=%08lx\n", dwBinaryPartitionNr, llOffset, dwLength, dwSectorSize); switch(dwBinaryPartitionNr) { case BP_TFFSSECTOR: return TFFS_ReadSectors(hDisk, llOffset, dwLength, buffer, dwRead, dwSectorSize); case BP_WINCESECTOR: return Disk_ReadSectors(hDisk, llOffset, dwLength, buffer, dwRead, dwSectorSize); case BP_OTPSECTOR: return TFFS_OTP_Read(hDisk, llOffset, dwLength, buffer, dwRead); #ifndef _ONLY_TFFS case BP_FLASHDRV: return FlashDrv_Read(dwBinaryPartitionNr, llOffset, dwLength, buffer, dwRead); case BP_ONDISK: return OnDisk_Read(dwBinaryPartitionNr, llOffset, dwLength, buffer, dwRead); #endif default: return TFFS_BDK_ReadNextSector(hDisk, dwBinaryPartitionNr, llOffset, dwLength, buffer, dwRead); } } ITSUTILS_API HRESULT STDAPICALLTYPE ITReadDisk( DWORD cbInput, ReadDiskParams *pbInput, DWORD *pcbOutput, ReadDiskResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; ReadDiskResult *pOut= *ppbOutput= NULL; //debugt("ITReadDisk-1 hd=%08lx dn=%ls pn=%ls\n", pbInput->hDisk, pbInput->szDeviceName, pbInput->szPartitionName); HANDLE hStore, hPartition; if (pbInput->hDisk) { hPartition= (HANDLE)pbInput->hDisk; hStore= NULL; } else if (pbInput->szDeviceName[0]==0 && pbInput->szPartitionName[0]==0) { // no handle is ok for some devid's hStore= 0; hPartition= 0; } else if (!OpenTFFSDisk(pbInput->szDeviceName, pbInput->szPartitionName, hStore, hPartition)) return GetLastError(); //debugt("ITReadDisk-2\n"); KernelMode _km; memcpy(BDK_SIGNATURE, pbInput->bdksign, 4); DWORD dwBlockSize, dwSectorSize; if (!Disk_GetDiskParams(hPartition, pbInput->dwBinaryPartitionNr, dwBlockSize, dwSectorSize)) { if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } //debugt("ITReadDisk-3\n"); // allow user override of sectorsize if (pbInput->dwSectorSize) dwSectorSize= pbInput->dwSectorSize; if (pbInput->dwBlockSize) dwBlockSize= pbInput->dwBlockSize; if (pbInput->llOffset % dwSectorSize) { debug("ERROR: ITReadDisk: startoffset not on sector boundary(%04x): sector nr %I64x ofs %04I64x\n", dwSectorSize, pbInput->llOffset / dwSectorSize, pbInput->llOffset % dwSectorSize); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return ERROR_INVALID_PARAMETER; } //debugt("ITReadDisk-4\n"); if ((pbInput->llOffset+pbInput->dwSize) % dwSectorSize) { debug("ERROR: ITReadDisk: endoffset not on sector boundary(%04x): sector nr %I64x ofs %04I64x\n", dwSectorSize, (pbInput->llOffset+pbInput->dwSize)/ dwSectorSize, (pbInput->llOffset+pbInput->dwSize)% dwSectorSize); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return ERROR_INVALID_PARAMETER; } //debugt("ITReadDisk-5\n"); if (!ReadDisk_Init(hPartition, pbInput->dwBinaryPartitionNr, pbInput->llOffset, pbInput->dwSize, dwSectorSize)) { if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } //debugt("ITReadDisk-6\n"); *pcbOutput= PTR_DIFF(pOut, pOut->buffer+pbInput->dwSize); pOut= *ppbOutput= (ReadDiskResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("LocalAlloc(%d)", *pcbOutput); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } DWORD dwRes= 0; diskdebug("outbuf=%08lx .. %08lx\n", pOut, pOut->buffer); diskdebug("reading %I64x : %08lx bytes bs=%08lx ss=%08lx\n", pbInput->llOffset, pbInput->dwSize, dwBlockSize, dwSectorSize); DWORD dwRemainingLength= pbInput->dwSize; DWORD dwBufOffset= 0; ULONGLONG llDiskOffset= pbInput->llOffset; while (dwRemainingLength) { // make sure first wanted makes diskoffset allign to blocksize DWORD dwWanted= dwBlockSize - ((DWORD)llDiskOffset&(dwBlockSize-1)); if (dwWanted > dwRemainingLength) dwWanted= dwRemainingLength; diskdebug("w=%08lx b=%08lx o=%I64x r=%08lx\n", dwWanted, dwBlockSize, llDiskOffset, dwRemainingLength); //debugt("ITReadDisk-7\n"); DWORD dwRead; if (!ReadDisk(hPartition, pbInput->dwBinaryPartitionNr, llDiskOffset, dwWanted, pOut->buffer+dwBufOffset, dwRead, dwSectorSize)) { dwRes= GetLastError(); if (dwRes==0) dwRes= ERROR_INTERNAL_ERROR; break; } if (dwRead==0) break; dwBufOffset += dwRead; llDiskOffset += dwRead; // ?? maybe don't add dwRead for BDK read? dwRemainingLength -= dwRead; } diskdebug("done reading: remaining: %08lx endofs=%08lx\n", dwRemainingLength, llDiskOffset); //debugt("ITReadDisk-8\n"); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); pOut->dwNumberOfBytesRead= dwBufOffset; //debugt("ITReadDisk-9\n"); return dwRes; } bool WriteDisk_Init(HANDLE hDisk, DWORD dwBinaryPartitionNr, ULONGLONG llOffset, DWORD dwLength, DWORD dwSectorSize) { switch (dwBinaryPartitionNr) { case BP_TFFSSECTOR: return true; case BP_WINCESECTOR: return true; case BP_OTPSECTOR: return true; case BP_FLASHDRV: return true; case BP_ONDISK: return true; default: return TFFS_BDK_InitWrite(hDisk, dwBinaryPartitionNr, llOffset, dwLength, dwSectorSize); } } bool WriteDisk(HANDLE hDisk, DWORD dwBinaryPartitionNr, ULONGLONG llStartOffset, ULONGLONG llOffset, DWORD dwLength, const BYTE *buffer, DWORD &dwWritten, DWORD dwSectorSize) { diskdebug("writedisk: %d : %I64x %08lx ss=%08lx\n", dwBinaryPartitionNr, llOffset, dwLength, dwSectorSize); switch(dwBinaryPartitionNr) { case BP_TFFSSECTOR: return TFFS_WriteSectors(hDisk, llOffset, dwLength, buffer, dwWritten, dwSectorSize); case BP_WINCESECTOR: return Disk_WriteSectors(hDisk, llOffset, dwLength, buffer, dwWritten, dwSectorSize); case BP_OTPSECTOR: return TFFS_OTP_Write(hDisk, llOffset, dwLength, buffer, dwWritten); #ifndef _ONLY_TFFS case BP_FLASHDRV: return FlashDrv_Write(dwBinaryPartitionNr, llOffset, dwLength, buffer, dwWritten); case BP_ONDISK: return OnDisk_Write(dwBinaryPartitionNr, llOffset, dwLength, buffer, dwWritten); #endif default: return TFFS_BDK_WriteNextSector(hDisk, dwBinaryPartitionNr, (DWORD)(llStartOffset/dwSectorSize), llOffset, dwLength, buffer, dwWritten); } } ITSUTILS_API HRESULT STDAPICALLTYPE ITWriteDisk( DWORD cbInput, WriteDiskParams *pbInput, DWORD *pcbOutput, WriteDiskResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; WriteDiskResult *pOut= *ppbOutput= NULL; HANDLE hStore, hPartition; if (pbInput->hDisk) { hPartition= (HANDLE)pbInput->hDisk; hStore= NULL; } else if (pbInput->szDeviceName[0]==0 && pbInput->szPartitionName[0]==0) { // no handle is ok for some devid's hStore= 0; hPartition= 0; } else if (!OpenTFFSDisk(pbInput->szDeviceName, pbInput->szPartitionName, hStore, hPartition)) return GetLastError(); KernelMode _km; memcpy(BDK_SIGNATURE, pbInput->bdksign, 4); DWORD dwBlockSize, dwSectorSize; if (!Disk_GetDiskParams(hPartition, pbInput->dwBinaryPartitionNr, dwBlockSize, dwSectorSize)) { if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } // allow user override of sectorsize if (pbInput->dwSectorSize) dwSectorSize= pbInput->dwSectorSize; if (pbInput->dwBlockSize) dwBlockSize= pbInput->dwBlockSize; if (pbInput->llOffset % dwSectorSize) { debug("ERROR: ITWriteDisk: startoffset not on sector boundary(%04x): sector nr %I64x ofs %04I64x\n", dwSectorSize, pbInput->llOffset / dwSectorSize, pbInput->llOffset % dwSectorSize); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return ERROR_INVALID_PARAMETER; } if ((pbInput->llOffset+pbInput->dwSize) % dwSectorSize) { debug("ERROR: ITWriteDisk: endoffset not on sector boundary(%04x): sector nr %I64x ofs %04I64x\n", dwSectorSize, (pbInput->llOffset+pbInput->dwSize)/ dwSectorSize, (pbInput->llOffset+pbInput->dwSize)% dwSectorSize); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return ERROR_INVALID_PARAMETER; } if (!WriteDisk_Init(hPartition, pbInput->dwBinaryPartitionNr, pbInput->llOffset, pbInput->dwSize, dwSectorSize)) { if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } *pcbOutput= sizeof(WriteDiskResult); pOut= *ppbOutput= (WriteDiskResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("LocalAlloc(%d)", *pcbOutput); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } DWORD dwRes= 0; g_pWriteEnableFlag= (DWORD*)pbInput->pWriteEnableFlag; diskdebug("writing %I64x : %08lx bytes bs=%08lx ss=%08lx\n", pbInput->llOffset, pbInput->dwSize, dwBlockSize, dwSectorSize); DWORD dwRemainingLength= pbInput->dwSize; DWORD dwBufOffset= 0; ULONGLONG llDiskOffset= pbInput->llOffset; while (dwRemainingLength) { // make sure first wanted makes diskoffset allign to blocksize DWORD dwWanted= dwBlockSize - ((DWORD)llDiskOffset&(dwBlockSize-1)); if (dwWanted > dwRemainingLength) dwWanted= dwRemainingLength; diskdebug("w=%08lx b=%08lx o=%I64x r=%08lx\n", dwWanted, dwBlockSize, llDiskOffset, dwRemainingLength); DWORD dwWritten; if (!WriteDisk(hPartition, pbInput->dwBinaryPartitionNr, pbInput->llOffset, llDiskOffset, dwWanted, pbInput->buffer+dwBufOffset, dwWritten, dwSectorSize)) { dwRes= GetLastError(); if (dwRes==0) dwRes= ERROR_INTERNAL_ERROR; break; } if (dwWritten==0) break; dwBufOffset += dwWritten; llDiskOffset += dwWritten; // ?? maybe don't add dwWritten for BDK write? dwRemainingLength -= dwWritten; } if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); pOut->dwNumberOfBytesWritten= dwBufOffset; return dwRes; } std::string SI_DeviceClassString(DWORD dw) { switch(dw) { case STORAGE_DEVICE_CLASS_BLOCK : return "BLOCK"; case STORAGE_DEVICE_CLASS_MULTIMEDIA: return "MULTIMEDIA"; default: return stringformat("UNKNOWNDEVCLASS_%08lx", dw); } } std::string SI_DeviceTypeString(DWORD dw) { if (dw==0) return "(none)"; StringList list; if (dw&STORAGE_DEVICE_TYPE_PCIIDE ) list.push_back("PCIIDE"); if (dw&STORAGE_DEVICE_TYPE_FLASH ) list.push_back("FLASH"); if (dw&STORAGE_DEVICE_TYPE_ATA ) list.push_back("ATA"); if (dw&STORAGE_DEVICE_TYPE_ATAPI ) list.push_back("ATAPI"); if (dw&STORAGE_DEVICE_TYPE_PCCARD ) list.push_back("PCCARD"); if (dw&STORAGE_DEVICE_TYPE_CFCARD ) list.push_back("CFCARD"); if (dw&STORAGE_DEVICE_TYPE_SRAM ) list.push_back("SRAM"); if (dw&STORAGE_DEVICE_TYPE_DVD ) list.push_back("DVD"); if (dw&STORAGE_DEVICE_TYPE_CDROM ) list.push_back("CDROM"); if (dw&STORAGE_DEVICE_TYPE_USB ) list.push_back("USB"); if (dw&STORAGE_DEVICE_TYPE_1394 ) list.push_back("1394"); if (dw&STORAGE_DEVICE_TYPE_DOC ) list.push_back("DOC"); if (dw&STORAGE_DEVICE_TYPE_UNKNOWN ) list.push_back("UNKNOWN"); if (dw&STORAGE_DEVICE_TYPE_REMOVABLE_DRIVE) list.push_back("REMOVABLE_DRIVE"); if (dw&STORAGE_DEVICE_TYPE_REMOVABLE_MEDIA) list.push_back("REMOVABLE_MEDIA"); const DWORD knownflags= STORAGE_DEVICE_TYPE_PCIIDE|STORAGE_DEVICE_TYPE_FLASH|STORAGE_DEVICE_TYPE_ATA|STORAGE_DEVICE_TYPE_ATAPI|STORAGE_DEVICE_TYPE_PCCARD|STORAGE_DEVICE_TYPE_CFCARD|STORAGE_DEVICE_TYPE_SRAM|STORAGE_DEVICE_TYPE_DVD|STORAGE_DEVICE_TYPE_CDROM|STORAGE_DEVICE_TYPE_USB|STORAGE_DEVICE_TYPE_1394|STORAGE_DEVICE_TYPE_DOC|STORAGE_DEVICE_TYPE_UNKNOWN|STORAGE_DEVICE_TYPE_REMOVABLE_DRIVE|STORAGE_DEVICE_TYPE_REMOVABLE_MEDIA; if (dw&~knownflags) list.push_back(stringformat("UNKNOWNDEVTYPE_%08lx", dw&~knownflags)); return JoinStringList(list, ","); } std::string SI_DeviceFlagsString(DWORD dw) { if (dw==0) return "(none)"; StringList list; if (dw&STORAGE_DEVICE_FLAG_READWRITE ) list.push_back("READWRITE"); if (dw&STORAGE_DEVICE_FLAG_READONLY ) list.push_back("READONLY"); if (dw&STORAGE_DEVICE_FLAG_TRANSACTED) list.push_back("TRANSACTED"); if (dw&STORAGE_DEVICE_FLAG_MEDIASENSE) list.push_back("MEDIASENSE"); const DWORD knownflags= STORAGE_DEVICE_FLAG_READWRITE|STORAGE_DEVICE_FLAG_READONLY|STORAGE_DEVICE_FLAG_TRANSACTED|STORAGE_DEVICE_FLAG_MEDIASENSE; if (dw&~knownflags) list.push_back(stringformat("UNKNOWNDEVFLAGS_%08lx", dw&~knownflags)); return JoinStringList(list, ","); } std::string GetStorageDeviceInfoString(const STORAGEDEVICEINFO& sdi) { if (sdi.cbSize!=sizeof(STORAGEDEVICEINFO)) debug("WARNING: sdi.cbSize=%d (!= %d)\n", sdi.cbSize, sizeof(STORAGEDEVICEINFO)); return stringformat("profile='%ls' class=%s type=%s flags=%s", sdi.szProfile, SI_DeviceClassString(sdi.dwDeviceClass).c_str(), SI_DeviceTypeString(sdi.dwDeviceType).c_str(), SI_DeviceFlagsString(sdi.dwDeviceFlags).c_str()); } std::string SectorNumString(const SECTORNUM& sn) { return stringformat("%I64x", sn); } std::string FileTimeString(const FILETIME& ft) { if (ft.dwLowDateTime==0 && ft.dwHighDateTime==0) return "(null)"; SYSTEMTIME systime; FILETIME lfiletime; FileTimeToLocalFileTime(&ft, &lfiletime); FileTimeToSystemTime(&lfiletime, &systime); return stringformat("%04d-%02d-%02d %02d:%02d:%02d.%03d", systime.wYear, systime.wMonth, systime.wDay, systime.wHour, systime.wMinute, systime.wSecond,systime.wMilliseconds); } std::string SI_AttributesString(DWORD dw) { if (dw==0) return "(none)"; StringList list; if (dw&STORE_ATTRIBUTE_READONLY ) list.push_back("READONLY"); if (dw&STORE_ATTRIBUTE_REMOVABLE ) list.push_back("REMOVABLE"); if (dw&STORE_ATTRIBUTE_UNFORMATTED) list.push_back("UNFORMATTED"); if (dw&STORE_ATTRIBUTE_AUTOFORMAT ) list.push_back("AUTOFORMAT"); if (dw&STORE_ATTRIBUTE_AUTOPART ) list.push_back("AUTOPART"); if (dw&STORE_ATTRIBUTE_AUTOMOUNT ) list.push_back("AUTOMOUNT"); const DWORD knownflags= STORE_ATTRIBUTE_READONLY|STORE_ATTRIBUTE_REMOVABLE|STORE_ATTRIBUTE_UNFORMATTED|STORE_ATTRIBUTE_AUTOFORMAT|STORE_ATTRIBUTE_AUTOPART|STORE_ATTRIBUTE_AUTOMOUNT; if (dw&~knownflags) list.push_back(stringformat("UNKNOWNSATTRS_%08lx", dw&~knownflags)); return JoinStringList(list, ","); } std::string PI_AttributesString(DWORD dw) { if (dw==0) return "(none)"; StringList list; if (dw&PARTITION_ATTRIBUTE_EXPENDABLE) list.push_back("EXPENDABLE"); if (dw&PARTITION_ATTRIBUTE_READONLY ) list.push_back("READONLY"); if (dw&PARTITION_ATTRIBUTE_AUTOFORMAT) list.push_back("AUTOFORMAT"); if (dw&PARTITION_ATTRIBUTE_ACTIVE ) list.push_back("ACTIVE"); if (dw&PARTITION_ATTRIBUTE_BOOT ) list.push_back("BOOT"); if (dw&PARTITION_ATTRIBUTE_MOUNTED ) list.push_back("MOUNTED"); const DWORD knownflags= PARTITION_ATTRIBUTE_EXPENDABLE|PARTITION_ATTRIBUTE_READONLY|PARTITION_ATTRIBUTE_AUTOFORMAT|PARTITION_ATTRIBUTE_ACTIVE|PARTITION_ATTRIBUTE_BOOT|PARTITION_ATTRIBUTE_MOUNTED; if (dw&~knownflags) list.push_back(stringformat("UNKNOWNPATTRS_%08lx", dw&~knownflags)); return JoinStringList(list, ","); } std::string StoreInfoString(const STOREINFO& si) { std::string str; if (si.cbSize!=sizeof(STOREINFO)) debug("WARNING: si.cbSize=%d (!= %d)\n", si.cbSize, sizeof(STOREINFO)); str += stringformat("dev='%ls' store='%ls' ", si.szDeviceName, si.szStoreName); str += stringformat(" nsect=%s bpsect=%x free=%s maxpartsize=%s", SectorNumString(si.snNumSectors).c_str(), si.dwBytesPerSector, SectorNumString(si.snFreeSectors).c_str(), SectorNumString(si.snBiggestPartCreatable).c_str()); str += stringformat(" created=%s modified=%s", FileTimeString(si.ftCreated).c_str(), FileTimeString(si.ftLastModified).c_str()); str += stringformat(" attribs=%s partitions=%d mounts=%d\n", SI_AttributesString(si.dwAttributes).c_str(), si.dwPartitionCount, si.dwMountCount); str += stringformat(" si=%08lx -> class=%08lx type=%08lx\n", &si, si.dwDeviceClass, si.dwDeviceType); str += stringformat(" class=%s type=%s flags=%s\n", SI_DeviceClassString(si.dwDeviceClass).c_str(), SI_DeviceTypeString(si.dwDeviceType).c_str(), SI_DeviceFlagsString(si.dwDeviceFlags).c_str()); str += stringformat(" sdi: %s\n", GetStorageDeviceInfoString(si.sdi).c_str()); return str; } std::string PartitionInfoString(const PARTINFO& pi) { std::string str; if (pi.cbSize!=sizeof(PARTINFO)) debug("WARNING: pi.cbSize=%d (!= %d)\n", pi.cbSize, sizeof(PARTINFO)); str += stringformat("name='%ls' filesys='%ls' volname='%ls'", pi.szPartitionName, pi.szFileSys, pi.szVolumeName); str += stringformat(" end=%s created=%s modified=%s", SectorNumString(pi.snNumSectors).c_str(), FileTimeString(pi.ftCreated).c_str(), FileTimeString(pi.ftLastModified).c_str()); str += stringformat(" attr=%s type=%02x\n", PI_AttributesString(pi.dwAttributes).c_str(), pi.bPartType); return str; } bool GetStorageDeviceInfo(HANDLE hDisk, STORAGEDEVICEINFO &sdi) { DWORD dwReturned; sdi.cbSize= sizeof(STORAGEDEVICEINFO); if (DeviceIoControl(hDisk, IOCTL_DISK_DEVICE_INFO, &sdi, sizeof(STORAGEDEVICEINFO), NULL, 0, &dwReturned, NULL)) return true; error("IOCTL_DISK_DEVICE_INFO(in)"); sdi.cbSize= sizeof(STORAGEDEVICEINFO); if (DeviceIoControl(hDisk, IOCTL_DISK_DEVICE_INFO, NULL, 0, &sdi, sizeof(STORAGEDEVICEINFO), &dwReturned, NULL)) return true; error("IOCTL_DISK_DEVICE_INFO(out)"); return false; } std::string DiskInfoFlagsString(DWORD dw) { if (dw==0) return "(none)"; StringList list; if (dw&DISK_INFO_FLAG_MBR ) list.push_back("MBR"); if (dw&DISK_INFO_FLAG_CHS_UNCERTAIN ) list.push_back("CHS_UNCERTAIN"); if (dw&DISK_INFO_FLAG_UNFORMATTED ) list.push_back("UNFORMATTED"); if (dw&DISK_INFO_FLAG_PAGEABLE ) list.push_back("PAGEABLE"); const DWORD knownflags= DISK_INFO_FLAG_MBR|DISK_INFO_FLAG_CHS_UNCERTAIN|DISK_INFO_FLAG_UNFORMATTED|DISK_INFO_FLAG_PAGEABLE; if (dw&~knownflags) list.push_back(stringformat("UNKNOWNFLAGS_%08lx", dw&~knownflags)); return JoinStringList(list, ","); } std::string DiskInfoString(const DISK_INFO &di) { return stringformat("tot=0x%08lx bps=0x%x cyls=0x%x hds=0x%x sectpcyl=0x%x flags=%hs", di.di_total_sectors, di.di_bytes_per_sect, di.di_cylinders, di.di_heads, di.di_sectors, DiskInfoFlagsString(di.di_flags).c_str()); } bool GetDiskStorageId(HANDLE hDisk, ByteVector &mfid, ByteVector &serialnr) { ByteVector data; STORAGE_IDENTIFICATION *sid= NULL; data.resize(sizeof(STORAGE_IDENTIFICATION)+256); sid= (STORAGE_IDENTIFICATION*)vectorptr(data); DWORD dwReturned; while (!DeviceIoControl(hDisk, IOCTL_DISK_GET_STORAGEID, NULL, 0, sid, data.size(), &dwReturned, NULL)) { if (GetLastError()!=ERROR_INSUFFICIENT_BUFFER) { error("IOCTL_DISK_GET_STORAGEID(out)"); return false; } data.resize(data.size()*2); sid= (STORAGE_IDENTIFICATION*)vectorptr(data); } if ((sid->dwFlags&MANUFACTUREID_INVALID)==0) { mfid.resize(sid->dwManufactureIDOffset < sid->dwSerialNumOffset ? sid->dwSerialNumOffset-sid->dwManufactureIDOffset : sid->dwSize-sid->dwManufactureIDOffset ); memcpy(vectorptr(mfid), &data[sid->dwManufactureIDOffset], mfid.size()); } if ((sid->dwFlags&SERIALNUM_INVALID)==0) { serialnr.resize(sid->dwSerialNumOffset < sid->dwManufactureIDOffset ? sid->dwManufactureIDOffset-sid->dwSerialNumOffset : sid->dwSize-sid->dwSerialNumOffset); memcpy(vectorptr(serialnr), &data[sid->dwSerialNumOffset], serialnr.size()); } const DWORD dwKnownFlags= MANUFACTUREID_INVALID|SERIALNUM_INVALID; if (sid->dwFlags&~dwKnownFlags) debug("WARNING: STORAGE_IDENTIFICATION: unknown flags: %08lx\n", sid->dwFlags&~dwKnownFlags); return true; } bool GetDiskName(HANDLE hDisk, std::string &name) { WCHAR namebuf[MAX_PATH]; DWORD dwReturned; if (!DeviceIoControl(hDisk, IOCTL_DISK_GETNAME, NULL, 0, namebuf, sizeof(namebuf), &dwReturned, NULL)) { error("IOCTL_DISK_GETNAME(out)"); return false; } name= ToString(namebuf); return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITTFFSGetInfo( DWORD cbInput, TFFSGetInfoParams *pbInput, DWORD *pcbOutput, TFFSGetInfoResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; TFFSGetInfoResult *pOut= *ppbOutput= NULL; //debugt("TFFSGetInfo-1\n"); HANDLE hStore, hPartition; if (pbInput->hDisk) { hPartition= (HANDLE)pbInput->hDisk; hStore= NULL; } else if (pbInput->szDeviceName[0]==0 && pbInput->szPartitionName[0]==0) { // no handle is ok for some devid's hStore= 0; hPartition= 0; } else if (!OpenTFFSDisk(pbInput->szDeviceName, pbInput->szPartitionName, hStore, hPartition)) return GetLastError(); //debugt("TFFSGetInfo-2\n"); KernelMode _km; memcpy(BDK_SIGNATURE, pbInput->bdksign, 4); //debugt("TFFSGetInfo-3\n"); DWORD dwBlockSize, dwSectorSize; if (!Disk_GetDiskParams(hPartition, pbInput->dwBinaryPartitionNr, dwBlockSize, dwSectorSize)) { if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } //debugt("TFFSGetInfo-4\n"); diskdebug("diskparams: bs=%08lx ss=%08lx\n", dwBlockSize, dwSectorSize); ULONGLONG llDiskSize; if (!Disk_GetDiskSize(hPartition, pbInput->dwBinaryPartitionNr, llDiskSize)) { if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } //debugt("TFFSGetInfo-5\n"); diskdebug("disksize: %I64x\n", llDiskSize); DWORD dwNrParts=0; DWORD dwNrBParts=0; DWORD dwBPLength=0; DWORD custid=0; GUID tffsid; memset(&tffsid, 0, sizeof(tffsid)); if (istffsdisk(pbInput->dwBinaryPartitionNr)) { if (TFFS_GetNrOfPartitions(hPartition, dwNrParts)) diskdebug("tffs: %d partitions\n", dwNrParts); if (TFFS_BDK_GetInfo(hPartition, 0, dwBPLength, dwNrBParts)) diskdebug("%d binary partitions, first=%08lx\n", dwNrBParts, dwBPLength); if (TFFS_GetCustomerId(hPartition, custid)) diskdebug("tffs custid: %08lx\n", custid); if (TFFS_GetUniqueId(hPartition, tffsid)) diskdebug("tffs uniqueid: %hs\n", GuidAsString(tffsid).c_str()); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); } *pcbOutput= sizeof(TFFSGetInfoResult); pOut= *ppbOutput= (TFFSGetInfoResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("LocalAlloc(%d)", *pcbOutput); return GetLastError(); } pOut->dwSectorSize= dwSectorSize; pOut->llDiskSize= llDiskSize; pOut->uniqueid= tffsid; pOut->customerid= custid; pOut->dwNrofBinPartitions= dwNrBParts; pOut->dwNrPartitions= dwNrParts; //debugt("TFFSGetInfo-6\n"); return 0; } ITSUTILS_API HRESULT STDAPICALLTYPE ITLogDiskInfo( DWORD cbInput, LogDiskInfoParams *pbInput, DWORD *pcbOutput, BYTE **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; *ppbOutput= NULL; HANDLE hStore, hPartition; if (pbInput->hDisk) { hPartition= (HANDLE)pbInput->hDisk; hStore= NULL; debug("listing diskinfo for existing handle %08lx\n", hPartition); } else if (pbInput->szDeviceName[0]==0 && pbInput->szPartitionName[0]==0) { // no handle is ok for some devid's hStore= 0; hPartition= 0; } else if (!OpenTFFSDisk(pbInput->szDeviceName, pbInput->szPartitionName, hStore, hPartition)) return GetLastError(); else debug("listing diskinfo for %08lx:%08lx %ls/%ls\n", hStore, hPartition, pbInput->szDeviceName, pbInput->szPartitionName); KernelMode _km; memcpy(BDK_SIGNATURE, pbInput->bdksign, 4); TFFS_GetInfo(hPartition); if (istffsdisk(pbInput->dwBinaryPartitionNr)) { DWORD dwNrParts; if (TFFS_GetNrOfPartitions(hPartition, dwNrParts)) debug("tffs: %d partitions\n", dwNrParts); DWORD dwNrBParts=0; DWORD dwLength=0; if (TFFS_BDK_GetInfo(hPartition, 0, dwLength, dwNrBParts)) { debug("tffs: %d binary partitions\n", dwNrBParts); debug("bdk%d: %08lx\n", 0, dwLength); for (DWORD p=1 ; phDisk==NULL) CloseTFFSDisk(hStore, hPartition); return 0; } bool Disk_GetDiskSize(HANDLE hDisk, DWORD dwBinaryPartitionNr, ULONGLONG &llDiskSize) { switch (dwBinaryPartitionNr) { case BP_TFFSSECTOR: case BP_WINCESECTOR: { DISK_INFO di; if (!GetDiskInfo(hDisk, di)) { error("GetDiskInfo"); llDiskSize= 0; return false; } llDiskSize= UInt32x32To64(di.di_total_sectors, di.di_bytes_per_sect); return true; } case BP_OTPSECTOR: { DWORD dwOtpSize, dwMaxOtpSize; if (!TFFS_OTP_GetSize(hDisk, dwOtpSize, dwMaxOtpSize)) { error("TFFS_OTP_GetSize"); llDiskSize= 0; return false; } llDiskSize= dwOtpSize; // returning current size, .. or should i return max size here? return true; } #ifndef _ONLY_TFFS case BP_FLASHDRV: return FlashDrv_GetDiskSize(dwBinaryPartitionNr, llDiskSize); case BP_ONDISK: return OnDisk_GetDiskSize(dwBinaryPartitionNr, llDiskSize); #endif default: { DWORD dwLength, dwNrBParts; if (!TFFS_BDK_GetInfo(hDisk, dwBinaryPartitionNr, dwLength, dwNrBParts)) { error("TFFS_BDK_GetInfo(%d)", dwBinaryPartitionNr); llDiskSize= 0; return false; } llDiskSize= dwLength; return true; } } } bool Disk_GetDiskParams(HANDLE hDisk, DWORD dwBinaryPartitionNr, DWORD &dwBlockSize, DWORD &dwSectorSize) { switch (dwBinaryPartitionNr) { case BP_TFFSSECTOR: dwBlockSize= TFFS_SECTOR_SIZE*16; dwSectorSize= TFFS_SECTOR_SIZE; return true; case BP_WINCESECTOR: // todo: read this from GetStoreInfo. dwBlockSize= TFFS_SECTOR_SIZE*16; dwSectorSize= TFFS_SECTOR_SIZE; return true; case BP_OTPSECTOR: dwBlockSize= TFFS_BLOCK_SIZE; dwSectorSize= TFFS_SECTOR_SIZE; return true; #ifndef _ONLY_TFFS case BP_FLASHDRV: return FlashDrv_GetDiskParams(dwBinaryPartitionNr, dwBlockSize, dwSectorSize); case BP_ONDISK: return OnDisk_GetDiskParams(dwBinaryPartitionNr, dwBlockSize, dwSectorSize); #endif default: // for bdk partitions: dwBlockSize= TFFS_BLOCK_SIZE; dwSectorSize= TFFS_BLOCK_SIZE; return true; } } bool DiskProtect(HANDLE hDisk, DWORD dwBinaryPartitionNr, bool bInsert, BYTE *password) { diskdebug("protect: %d : %d %s\n", dwBinaryPartitionNr, bInsert, password); switch(dwBinaryPartitionNr) { case BP_TFFSSECTOR: if (bInsert) { TFFS_BDK_Protect(hDisk, 0, bInsert, password); TFFS_BDK_ChangeType(hDisk, 0, bInsert, password); TFFS_Protect(hDisk, bInsert, password); TFFS_ChangeType(hDisk, bInsert, password); } else { TFFS_ChangeType(hDisk, bInsert, password); TFFS_Protect(hDisk, bInsert, password); TFFS_BDK_ChangeType(hDisk, 0, bInsert, password); TFFS_BDK_Protect(hDisk, 0, bInsert, password); } return true; case BP_WINCESECTOR: return true; case BP_OTPSECTOR: return true; case BP_FLASHDRV: return FlashDrv_Protection(dwBinaryPartitionNr, !bInsert); case BP_ONDISK: return OnDisk_Protection(!bInsert); default: if (bInsert) { TFFS_BDK_Protect(hDisk, dwBinaryPartitionNr, bInsert, password); TFFS_BDK_ChangeType(hDisk, dwBinaryPartitionNr, bInsert, password); TFFS_Protect(hDisk, bInsert, password); TFFS_ChangeType(hDisk, bInsert, password); } else { TFFS_ChangeType(hDisk, bInsert, password); TFFS_Protect(hDisk, bInsert, password); TFFS_BDK_ChangeType(hDisk, dwBinaryPartitionNr, bInsert, password); TFFS_BDK_Protect(hDisk, dwBinaryPartitionNr, bInsert, password); } } return true; } ITSUTILS_API HRESULT STDAPICALLTYPE ITDiskProtect( DWORD cbInput, DiskProtectParams *pbInput, DWORD *pcbOutput, DiskProtectResult **ppbOutput, IRAPIStream *pStream) { *pcbOutput= 0; DiskProtectResult *pOut= *ppbOutput= NULL; HANDLE hStore, hPartition; if (pbInput->hDisk) { hPartition= (HANDLE)pbInput->hDisk; hStore= NULL; } else if (pbInput->szDeviceName[0]==0 && pbInput->szPartitionName[0]==0) { // no handle is ok for some devid's hStore= 0; hPartition= 0; } else if (!OpenTFFSDisk(pbInput->szDeviceName, pbInput->szPartitionName, hStore, hPartition)) return GetLastError(); KernelMode _km; memcpy(BDK_SIGNATURE, pbInput->bdksign, 4); if (!DiskProtect(hPartition, pbInput->dwBinaryPartitionNr, pbInput->bInsert, pbInput->password)) { if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } *pcbOutput= sizeof(DiskProtectResult); pOut= *ppbOutput= (DiskProtectResult*)LocalAlloc(LPTR, *pcbOutput); if (pOut==NULL) { error("LocalAlloc(%d)", *pcbOutput); if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return GetLastError(); } if (pbInput->hDisk==NULL) CloseTFFSDisk(hStore, hPartition); return 0; }