/// <summary> /// create a BlockAllocationTableReader for an existing filesystem. Side /// effect: when this method finishes, the BAT blocks will have /// been Removed from the raw block list, and any blocks labeled as /// 'unused' in the block allocation table will also have been /// Removed from the raw block list. </summary> /// <param name="bigBlockSizse">the poifs bigBlockSize</param> /// <param name="block_count">the number of BAT blocks making up the block allocation table</param> /// <param name="block_array">the array of BAT block indices from the /// filesystem's header</param> /// <param name="xbat_count">the number of XBAT blocks</param> /// <param name="xbat_index">the index of the first XBAT block</param> /// <param name="raw_block_list">the list of RawDataBlocks</param> public BlockAllocationTableReader(POIFSBigBlockSize bigBlockSizse, int block_count, int[] block_array, int xbat_count, int xbat_index, BlockList raw_block_list) : this(bigBlockSizse) { SanityCheckBlockCount(block_count); RawDataBlock[] blocks = new RawDataBlock[block_count]; int limit = Math.Min(block_count, block_array.Length); int block_index; for (block_index = 0; block_index < limit; block_index++) { int nextOffset = block_array[block_index]; if (nextOffset > raw_block_list.BlockCount()) { throw new IOException("Your file contains " + raw_block_list.BlockCount() + " sectors, but the initial DIFAT array at index " + block_index + " referenced block # " + nextOffset + ". This isn't allowed and " + " your file is corrupt"); } blocks[block_index] = (RawDataBlock)raw_block_list.Remove(nextOffset); } if (block_index < block_count) { // must have extended blocks if (xbat_index < 0) { throw new IOException( "BAT count exceeds limit, yet XBAT index indicates no valid entries"); } int chain_index = xbat_index; int max_entries_per_block = BATBlock.EntriesPerXBATBlock; int chain_index_offset = BATBlock.XBATChainOffset; // Each XBAT block contains either: // (maximum number of sector indexes) + index of next XBAT // some sector indexes + FREE sectors to max # + EndOfChain for (int j = 0; j < xbat_count; j++) { limit = Math.Min(block_count - block_index, max_entries_per_block); byte[] data = raw_block_list.Remove(chain_index).Data; int offset = 0; for (int k = 0; k < limit; k++) { blocks[block_index++] = (RawDataBlock)raw_block_list.Remove(LittleEndian.GetInt(data, offset)); offset += LittleEndianConsts.INT_SIZE; } chain_index = LittleEndian.GetInt(data, chain_index_offset); if (chain_index == POIFSConstants.END_OF_CHAIN) { break; } } } if (block_index != block_count) { throw new IOException("Could not find all blocks"); } // now that we have all of the raw data blocks, go through and // create the indices SetEntries((ListManagedBlock[])blocks, raw_block_list); }