public void Initialize(FileStream isoStream, long offset, bool isRawDump) { this.VolumeBaseOffset = offset; this.IsRawDump = isRawDump; this.VolumeType = VolumeDataType.Data; this.DirectoryStructureArray = new ArrayList(); this.FormatDescription = MicrosoftExFatFileSystem.FORMAT_DESCRIPTION_STRING; this.JumpBoot = ParseFile.ReadUint24LE(isoStream, this.VolumeBaseOffset + 0); this.MagicBytes = ParseFile.ParseSimpleOffset(isoStream, this.VolumeBaseOffset + 3, 8); this.ZeroChunk = ParseFile.ParseSimpleOffset(isoStream, this.VolumeBaseOffset + 11, 53); this.PartitionOffset = ParseFile.ReadUlongLE(isoStream, this.VolumeBaseOffset + 64); this.VolumeLength = ParseFile.ReadUlongLE(isoStream, this.VolumeBaseOffset + 72); this.FatOffset = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 80); this.FatLength = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 84); this.ClusterHeapOffset = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 88); this.ClusterCount = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 92); this.RootDirectoryFirstCluster = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 96); this.VolumeSerialNumber = ParseFile.ReadUintLE(isoStream, this.VolumeBaseOffset + 100); this.VolumeIdentifier = this.VolumeSerialNumber.ToString("X2"); this.FileSystemRevision = ParseFile.ReadUshortLE(isoStream, this.VolumeBaseOffset + 104); this.VolumeFlags = ParseFile.ReadUshortLE(isoStream, this.VolumeBaseOffset + 106); this.BytesPerSector = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 108); this.SectorsPerCluster = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 109); this.NumberOfFats = ParseFile.ReadByte(isoStream, this.VolumeBaseOffset + 110); // caclulate helper values this.SectorSizeInBytes = (uint)(1 << this.BytesPerSector); this.ClusterSizeInBytes = (uint)(1 << (this.SectorsPerCluster + this.BytesPerSector)); this.VolumeLengthInBytes = this.VolumeLength * this.SectorSizeInBytes; this.FatAbsoluteOffset = (ulong)this.VolumeBaseOffset + (this.FatOffset * this.SectorSizeInBytes); this.FatLengthInBytes = this.FatLength * this.SectorSizeInBytes; this.ClusterHeapAbsoluteOffset = (ulong)this.VolumeBaseOffset + (this.ClusterHeapOffset * this.SectorSizeInBytes); this.RootDirectoryAbsoluteOffset = MicrosoftExFatFileSystem.GetOffsetForClusterId(this.ClusterHeapAbsoluteOffset, this.ClusterSizeInBytes, this.RootDirectoryFirstCluster); // this.ClusterHeapAbsoluteOffset + ((this.RootDirectoryFirstCluster - MicrosoftExFatFileSystem.CLUSTER_CORRECTION_OFFSET) * this.ClusterSizeInBytes); if (this.FileSystemRevision == MicrosoftExFatFileSystem.EXFAT_VERSION_0100) { // initialize FAT this.InitializeAndValidateFat(isoStream); // process root directory entry this.GetVolumeLabel(isoStream); // load directories this.LoadDirectories(isoStream); } else { MessageBox.Show(String.Format("Unsupported exFAT version: {0}", this.FileSystemRevision.ToString("X8"))); } }
private void processDirectory( FileStream isoStream, long directoryOffset, long maxDirectoryLength, string parentDirectory, long volumeBaseOffset, ulong clusterHeapOffset, uint clusterSize) { byte[] primaryEntry; byte[] secondaryRecord; byte entryType = 0xFF; MicrosoftExFatFileStructure newFile; MicrosoftExFatDirectoryStructure newDirectory; ulong objectOffset; MicrosoftExFatRootDirFileDirectoryEntry fileEntry; // = new MicrosoftExFatRootDirFileDirectoryEntry(fileDirectoryEntry); MicrosoftExFatRootDirStreamExtensionEntry streamExtensionEntry; MicrosoftExFatRootDirFileNameExtensionEntry fileNameExtensionEntry; string fileName = String.Empty; DateTime fileDate = new DateTime(); // @todo update to actually parse date long currentOffset = directoryOffset; long maxOffset = directoryOffset + maxDirectoryLength; // @TODO: need to handle when in non-contiguous clusters while ((currentOffset < maxOffset) && (entryType != MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_EMPTY)) { // read primary entry primaryEntry = ParseFile.ParseSimpleOffset(isoStream, currentOffset, MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE); // process primary entry and subentries if needed entryType = primaryEntry[0]; switch (entryType) { case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_FILE_DIRECTORY: fileEntry = new MicrosoftExFatRootDirFileDirectoryEntry(primaryEntry); currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE; // check if in use and process, and skip if not if (fileEntry.IsInUse) { // process Stream Extension Entry secondaryRecord = ParseFile.ParseSimpleOffset(isoStream, currentOffset, MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE); streamExtensionEntry = new MicrosoftExFatRootDirStreamExtensionEntry(secondaryRecord); objectOffset = MicrosoftExFatFileSystem.GetOffsetForClusterId(clusterHeapOffset, clusterSize, streamExtensionEntry.FirstCluster); currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE; // process File Name Extention Entry fileName = String.Empty; for (int i = 0; i < (fileEntry.SecondaryCount - 1); i++) { secondaryRecord = ParseFile.ParseSimpleOffset(isoStream, (currentOffset), MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE); fileNameExtensionEntry = new MicrosoftExFatRootDirFileNameExtensionEntry(secondaryRecord); // build name from chunks fileName += fileNameExtensionEntry.FileNameChunk; // move pointer currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE; } // trim any excess from name fileName = fileName.Substring(0, streamExtensionEntry.NameLength); // create dir or file and add to array list if (fileEntry.IsDirectory) { // get new directory newDirectory = new MicrosoftExFatDirectoryStructure(isoStream, volumeBaseOffset, (long)objectOffset, (long)streamExtensionEntry.DataLength, fileName, parentDirectory, clusterHeapOffset, clusterSize); // add directory to subdirectory array this.SubDirectoryArray.Add(newDirectory); } else // file { newFile = new MicrosoftExFatFileStructure(parentDirectory, isoStream.Name, fileName, (long)objectOffset, volumeBaseOffset, streamExtensionEntry.FirstCluster, (long)streamExtensionEntry.DataLength, fileDate); this.FileArray.Add(newFile); } } else { currentOffset = (uint)(MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE * fileEntry.SecondaryCount); } break; case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_VOLUME_LABEL: case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_ALLOCATION_BITMAP: case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_UPCASE: case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_VOLUME_GUID: case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_TEXFAT_PADDING: case MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_TYPE_WINDOWS_CE_ACL: currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE; break; default: currentOffset += MicrosoftExFatFileSystem.ROOT_DIR_ENTRY_SIZE; break; } // switch (entryType) } }