/// <summary> /// Un-marshal a byte array to PDU struct. /// </summary> /// <param name="binaryReader">BinaryReader</param> internal override void FromBytes(BinaryReader binaryReader) { base.FromBytes(binaryReader); auth_verifier = RpceUtility.AuthVerifierFromBytes( binaryReader, auth_length); alloc_hint = binaryReader.ReadUInt32(); p_cont_id = binaryReader.ReadUInt16(); opnum = binaryReader.ReadUInt16(); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { alloc_hint = EndianUtility.ReverseByteOrder(alloc_hint); p_cont_id = EndianUtility.ReverseByteOrder(p_cont_id); opnum = EndianUtility.ReverseByteOrder(opnum); } if ((pfc_flags & RpceCoPfcFlags.PFC_OBJECT_UUID) != 0) { @object = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE)); } int stubLength = frag_length; stubLength -= GetSize(); if (auth_verifier != null) { stubLength -= auth_verifier.Value.auth_pad_length; stubLength -= RpceUtility.AUTH_VERIFIER_SIZE; stubLength -= auth_length; } stub = binaryReader.ReadBytes(stubLength); }
/// <summary> /// Initializes a new instance of the <see cref="RpxHeader"/> class. /// </summary> /// <param name="rpxFilePath">path to RPX file.</param> public RpxHeader(string rpxFilePath) { this.identity = new byte[ElfSignatureLength]; using (FileStream fs = new FileStream(rpxFilePath, FileMode.Open, FileAccess.Read)) { using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); // Read in the header this.identity = br.ReadBytes(ElfSignatureLength); this.type = EndianUtility.ReadUInt16BE(br); this.machine = EndianUtility.ReadUInt16BE(br); this.version = EndianUtility.ReadUInt32BE(br); this.entryPoint = EndianUtility.ReadUInt32BE(br); this.phOffset = EndianUtility.ReadUInt32BE(br); this.shOffset = EndianUtility.ReadUInt32BE(br); this.flags = EndianUtility.ReadUInt32BE(br); this.ehSize = EndianUtility.ReadUInt16BE(br); this.phEntSize = EndianUtility.ReadUInt16BE(br); this.phNum = EndianUtility.ReadUInt16BE(br); this.shEntSize = EndianUtility.ReadUInt16BE(br); this.shNum = EndianUtility.ReadUInt16BE(br); this.shStrIndex = EndianUtility.ReadUInt16BE(br); } this.sHeaderDataElfOffset = (ulong)(this.shOffset + (this.shNum * this.shEntSize)); }
public RpxHeader(string rpxFilePath) { identity = new byte[ELF_SIGNATURE_LENGTH]; using (FileStream fs = new FileStream(rpxFilePath, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { // Read in the header identity = br.ReadBytes(ELF_SIGNATURE_LENGTH); type = EndianUtility.ReadUInt16BE(br); machine = EndianUtility.ReadUInt16BE(br); version = EndianUtility.ReadUInt32BE(br); entryPoint = EndianUtility.ReadUInt32BE(br); phOffset = EndianUtility.ReadUInt32BE(br); shOffset = EndianUtility.ReadUInt32BE(br); flags = EndianUtility.ReadUInt32BE(br); ehSize = EndianUtility.ReadUInt16BE(br); phEntSize = EndianUtility.ReadUInt16BE(br); phNum = EndianUtility.ReadUInt16BE(br); shEntSize = EndianUtility.ReadUInt16BE(br); shNum = EndianUtility.ReadUInt16BE(br); shStrIndex = EndianUtility.ReadUInt16BE(br); } } sHeaderDataElfOffset = (ulong)(shOffset + (shNum * shEntSize)); }
/// <summary> /// Un-marshal a byte array to PDU struct. /// </summary> /// <param name="binaryReader">BinaryReader</param> internal override void FromBytes(BinaryReader binaryReader) { base.FromBytes(binaryReader); auth_verifier = RpceUtility.AuthVerifierFromBytes( binaryReader, auth_length); alloc_hint = binaryReader.ReadUInt32(); p_cont_id = binaryReader.ReadUInt16(); cancel_count = binaryReader.ReadByte(); reserved = binaryReader.ReadByte(); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { alloc_hint = EndianUtility.ReverseByteOrder(alloc_hint); p_cont_id = EndianUtility.ReverseByteOrder(p_cont_id); } // read stub. int stubLength = frag_length; stubLength -= GetSize(); if (auth_verifier != null) { stubLength -= auth_verifier.Value.auth_pad_length; stubLength -= RpceUtility.AUTH_VERIFIER_SIZE; stubLength -= auth_length; } stub = binaryReader.ReadBytes(stubLength); }
public void ReadUInt24LE_WithValidUInt24_ReadsData() { using MemoryStream ms = new MemoryStream(new byte[] { 0x10, 0x0, 0xB }); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); var result = EndianUtility.ReadUInt24LE(br); Assert.Equal(720912u, result); }
public void ReadUInt32LE_WithValidUInt32_ReadsData() { using MemoryStream ms = new MemoryStream(new byte[] { 0x01, 0xEE, 0xA0, 0x0 }); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); var result = EndianUtility.ReadUInt32LE(br); Assert.Equal(10546689u, result); }
public void ReadInt16BE_WithValidInt16_ReadsData() { using MemoryStream ms = new MemoryStream(new byte[] { 0xA0, 0x0 }); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); var result = EndianUtility.ReadInt16BE(br); Assert.Equal(-24576, result); }
public void ReadUInt32BE_WithValidUint32_ReadsData() { using MemoryStream ms = new MemoryStream(new byte[] { 0x20, 0x00, 0x10, 0x0 }); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); var result = EndianUtility.ReadUInt32BE(br); Assert.Equal(536875008u, result); }
public void ReadNullTerminatedString_WithByteArray_ReadsString() { var byteArray = new byte[] { 0x63, 0x61, 0x74, 0x00, 0x55 }; var result = EndianUtility.ReadNullTerminatedString(byteArray); Assert.Equal("cat", result); }
public void ReadNullTerminatedString_WithStream_ReadsString() { using MemoryStream ms = new MemoryStream(new byte[] { 0x63, 0x61, 0x74, 0x00, 0x55 }); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); var result = EndianUtility.ReadNullTerminatedString(br); Assert.Equal("cat", result); }
public void ReverseLE_OnLESystem_DoesNothing() { EndianUtility.Endianness = Endianness.LittleEndian; var byteArray = new byte[] { 0, 1, 2, 3 }; var result = EndianUtility.ReverseLE(byteArray); Assert.Equal(byteArray, result); }
public void WriteUInt32LE_WithUInt32_WritesData() { using MemoryStream ms = new MemoryStream(new byte[4]); using BinaryWriter bw = new BinaryWriter(ms); EndianUtility.WriteUInt32LE(bw, 12345678u); ms.Seek(0, SeekOrigin.Begin); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); Assert.Equal(12345678u, EndianUtility.ReadUInt32LE(br)); }
private List <uint> ReadChunkTableValues(MemoryStream ms) { List <uint> valueList = new List <uint>(); using (BinaryReader br = new BinaryReader(ms, new ASCIIEncoding(), true)) { // get the offset information byte type = br.ReadByte(); // Get the size of each object in bytes int countByteSize = type - 12; uint count = 0; if (countByteSize == 1) { count = br.ReadByte(); } else if (countByteSize == 2) { count = EndianUtility.ReadUInt16LE(br); } else if (countByteSize == 4) { count = EndianUtility.ReadUInt32LE(br); } byte entrySizeType = br.ReadByte(); int entryByteSize = entrySizeType - 12; uint value = 0; // Read in the values for (int i = 0; i < count; i++) { if (countByteSize == 1) { value = br.ReadByte(); } if (entryByteSize == 2) { value = EndianUtility.ReadUInt16LE(br); } else if (entryByteSize == 4) { value = EndianUtility.ReadUInt32LE(br); } valueList.Add(value); } } return(valueList); }
public void ReverseLE_OnBESystem_ReversesBytes() { EndianUtility.Endianness = Endianness.BigEndian; var byteArray = new byte[] { 0, 1, 2, 3 }; var reversedArray = new byte[] { 3, 2, 1, 0 }; var result = EndianUtility.ReverseLE(byteArray); Assert.Equal(reversedArray, result); }
public void ReadBytesRequired_WithEnoughBytes_ReadsBytes() { var byteArray = new byte[] { 0, 1, 2, 3 }; using MemoryStream ms = new MemoryStream(byteArray); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); var result = EndianUtility.ReadBytesRequired(br, 4); Assert.Equal(byteArray, result); }
/// <summary> /// Initializes a new instance of the <see cref="MdfHeader"/> class. /// </summary> /// <param name="psbPath">path to the PSB file to read.</param> public MdfHeader(string psbPath) { this.signature = new byte[MDFSignatureLength]; using FileStream fs = new FileStream(psbPath, FileMode.Open, FileAccess.Read); using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); // Read in the header this.signature = br.ReadBytes(MDFSignatureLength); this.length = EndianUtility.ReadUInt32LE(br); }
/// <summary> /// Un-marshal a byte array to PDU struct. /// </summary> /// <param name="binaryReader">BinaryReader</param> internal override void FromBytes(BinaryReader binaryReader) { base.FromBytes(binaryReader); auth_verifier = RpceUtility.AuthVerifierFromBytes( binaryReader, auth_length); pad = binaryReader.ReadUInt32(); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { pad = EndianUtility.ReverseByteOrder(pad); } }
public MdfHeader(string psbPath) { signature = new byte[MDF_SIGNATURE_LENGTH]; using (FileStream fs = new FileStream(psbPath, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { // Read in the header signature = br.ReadBytes(MDF_SIGNATURE_LENGTH); length = EndianUtility.ReadUInt32LE(br); } } }
/// <summary> /// Decode CO PDU. /// </summary> /// <param name="context">The context that received data.</param> /// <param name="messageBytes">bytes received</param> /// <param name="consumedLength">num of bytes consumed in processing</param> /// <param name="expectedLength">num of bytes expected if the bytes is not enough</param> /// <returns>pdus</returns> internal static RpceCoPdu[] DecodeCoPdu( RpceContext context, byte[] messageBytes, out int consumedLength, out int expectedLength) { List <RpceCoPdu> pduList = new List <RpceCoPdu>(); consumedLength = 0; expectedLength = 0; while (consumedLength < messageBytes.Length) { if ((messageBytes.Length - consumedLength) < RpceUtility.CO_PDU_HEADER_SIZE) { expectedLength = RpceUtility.CO_PDU_HEADER_SIZE; break; } //#4 byte is drep uint dataRepresentation = BitConverter.ToUInt32( messageBytes, consumedLength + RpceUtility.DREP_FIELD_OFFSET); //#8 byte is frag_length ushort fragmentLength = BitConverter.ToUInt16( messageBytes, consumedLength + RpceUtility.FRAG_LENGTH_FIELD_OFFSET); if ((dataRepresentation & 0x0000FFFFU) != NativeMethods.NDR_LOCAL_DATA_REPRESENTATION) { fragmentLength = EndianUtility.ReverseByteOrder(fragmentLength); } if ((messageBytes.Length - consumedLength) < fragmentLength) { expectedLength = fragmentLength; break; } byte[] pduBytes = new byte[fragmentLength]; Buffer.BlockCopy(messageBytes, consumedLength, pduBytes, 0, fragmentLength); RpceCoPdu pdu = RpceUtility.DecodeCoPdu(context, pduBytes); pduList.Add(pdu); consumedLength += fragmentLength; } return(pduList.ToArray()); }
/// <summary> /// Initializes a new instance of the <see cref="RpxSectionHeader"/> class. /// </summary> /// <param name="sectionBytes">bytes for the section to parse.</param> public RpxSectionHeader(byte[] sectionBytes) { using MemoryStream ms = new MemoryStream(sectionBytes); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); // Read in the header this.name = EndianUtility.ReadUInt32BE(br); this.type = EndianUtility.ReadUInt32BE(br); this.flags = EndianUtility.ReadUInt32BE(br); this.address = EndianUtility.ReadUInt32BE(br); this.offset = EndianUtility.ReadUInt32BE(br); this.size = EndianUtility.ReadUInt32BE(br); this.link = EndianUtility.ReadUInt32BE(br); this.info = EndianUtility.ReadUInt32BE(br); this.addrAlign = EndianUtility.ReadUInt32BE(br); this.entSize = EndianUtility.ReadUInt32BE(br); }
/// <summary> /// Initializes a new instance of the <see cref="PsbHeader"/> class. /// </summary> /// <param name="psbPath">path to the PSB file.</param> public PsbHeader(string psbPath) { this.signature = new byte[PsbSignatureLength]; using FileStream fs = new FileStream(psbPath, FileMode.Open, FileAccess.Read); using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); // Read in the header this.signature = br.ReadBytes(PsbSignatureLength); this.type = EndianUtility.ReadUInt32LE(br); this.unknown = EndianUtility.ReadUInt32LE(br); this.namesOffset = EndianUtility.ReadUInt32LE(br); this.stringsOffset = EndianUtility.ReadUInt32LE(br); this.stringsDataOffset = EndianUtility.ReadUInt32LE(br); this.chunkOffsetsOffset = EndianUtility.ReadUInt32LE(br); this.chunkLengthsOffset = EndianUtility.ReadUInt32LE(br); this.chunkDataOffset = EndianUtility.ReadUInt32LE(br); this.entriesOffset = EndianUtility.ReadUInt32LE(br); }
/// <summary> /// Un-marshal a byte array to PDU struct. /// </summary> /// <param name="binaryReader">BinaryReader</param> internal override void FromBytes(BinaryReader binaryReader) { base.FromBytes(binaryReader); if (packed_drep.dataRepFormat == RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { provider_reject_reason = (p_reject_reason_t)binaryReader.ReadUInt16(); } else { provider_reject_reason = (p_reject_reason_t)EndianUtility.ReverseByteOrder(binaryReader.ReadUInt16()); } versions = new p_rt_versions_supported_t(); versions.n_protocols = binaryReader.ReadByte(); versions.p_protocols = new version_t[versions.n_protocols]; for (int i = 0; i < versions.n_protocols; i++) { versions.p_protocols[i].major = binaryReader.ReadByte(); versions.p_protocols[i].minor = binaryReader.ReadByte(); } //Assume that the client calculates the length of the PDU //until the Signature field as L. //If the frag_length field is greater than or equal to L //plus the size of the Signature field, //the client SHOULD assume that the Signature field is present. //Otherwise, the client SHOULD assume that the Signature field is not present. //TD shows the signature is aligned at 4. int L = RpceUtility.Align((int)binaryReader.BaseStream.Position, 4); if (frag_length >= (L + RpceUtility.GUID_SIZE)) { pad = binaryReader.ReadBytes(L - (int)binaryReader.BaseStream.Position); signature = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE)); extended_error_info = binaryReader.ReadBytes(frag_length - L - RpceUtility.GUID_SIZE); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { signature = EndianUtility.ReverseByteOrder((Guid)signature); } } }
/// <summary> /// Un-marshal a byte array to PDU struct. /// </summary> /// <param name="binaryReader">A binary reader.</param> internal override void FromBytes(BinaryReader binaryReader) { rpc_vers = binaryReader.ReadByte(); rpc_vers_minor = binaryReader.ReadByte(); PTYPE = (RpcePacketType)binaryReader.ReadByte(); pfc_flags = (RpceCoPfcFlags)binaryReader.ReadByte(); packed_drep = new DataRepresentationFormatLabel(); packed_drep.dataRepFormat = (RpceDataRepresentationFormat)binaryReader.ReadUInt16(); packed_drep.reserved = binaryReader.ReadUInt16(); frag_length = binaryReader.ReadUInt16(); auth_length = binaryReader.ReadUInt16(); call_id = binaryReader.ReadUInt32(); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { frag_length = EndianUtility.ReverseByteOrder(frag_length); auth_length = EndianUtility.ReverseByteOrder(auth_length); call_id = EndianUtility.ReverseByteOrder(call_id); } }
public RpxSectionHeader(byte[] sectionBytes) { using (MemoryStream ms = new MemoryStream(sectionBytes)) { using (BinaryReader br = new BinaryReader(ms, new ASCIIEncoding())) { // Read in the header name = EndianUtility.ReadUInt32BE(br); type = EndianUtility.ReadUInt32BE(br); flags = EndianUtility.ReadUInt32BE(br); address = EndianUtility.ReadUInt32BE(br); offset = EndianUtility.ReadUInt32BE(br); size = EndianUtility.ReadUInt32BE(br); link = EndianUtility.ReadUInt32BE(br); info = EndianUtility.ReadUInt32BE(br); addrAlign = EndianUtility.ReadUInt32BE(br); entSize = EndianUtility.ReadUInt32BE(br); } } }
public PsbHeader(string psbPath) { signature = new byte[PSB_SIGNATURE_LENGTH]; using (FileStream fs = new FileStream(psbPath, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { // Read in the header signature = br.ReadBytes(PSB_SIGNATURE_LENGTH); type = EndianUtility.ReadUInt32LE(br); unknown = EndianUtility.ReadUInt32LE(br); namesOffset = EndianUtility.ReadUInt32LE(br); stringsOffset = EndianUtility.ReadUInt32LE(br); stringsDataOffset = EndianUtility.ReadUInt32LE(br); chunkOffsetsOffset = EndianUtility.ReadUInt32LE(br); chunkLengthsOffset = EndianUtility.ReadUInt32LE(br); chunkDataOffset = EndianUtility.ReadUInt32LE(br); entriesOffset = EndianUtility.ReadUInt32LE(br); } } }
public void ReadInt16BE_WithInvalidInt16_ThrowsException() { using MemoryStream ms = new MemoryStream(new byte[] { 0x10 }); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); Assert.Throws <System.IO.EndOfStreamException>(() => EndianUtility.ReadInt16BE(br)); }
/// <summary> /// Un-marshal a byte array to PDU struct. /// </summary> /// <param name="binaryReader">BinaryReader</param> internal override void FromBytes(BinaryReader binaryReader) { base.FromBytes(binaryReader); auth_verifier = RpceUtility.AuthVerifierFromBytes( binaryReader, auth_length); max_xmit_frag = binaryReader.ReadUInt16(); max_recv_frag = binaryReader.ReadUInt16(); assoc_group_id = binaryReader.ReadUInt32(); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { max_xmit_frag = EndianUtility.ReverseByteOrder(max_xmit_frag); max_recv_frag = EndianUtility.ReverseByteOrder(max_recv_frag); assoc_group_id = EndianUtility.ReverseByteOrder(assoc_group_id); } sec_addr = new port_any_t(); sec_addr.length = binaryReader.ReadUInt16(); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { sec_addr.length = EndianUtility.ReverseByteOrder(sec_addr.length); } sec_addr.port_spec = binaryReader.ReadBytes(sec_addr.length); // restore 4-octet alignment int pad2Length = RpceUtility.Align((int)binaryReader.BaseStream.Position, 4) - (int)binaryReader.BaseStream.Position; pad2 = binaryReader.ReadBytes(pad2Length); p_result_list = new p_result_list_t(); p_result_list.n_results = binaryReader.ReadByte(); p_result_list.reserved = binaryReader.ReadByte(); p_result_list.reserved2 = binaryReader.ReadUInt16(); p_result_list.p_results = new p_result_t[p_result_list.n_results]; for (int i = 0; i < p_result_list.n_results; i++) { if (packed_drep.dataRepFormat == RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { p_result_list.p_results[i].result = (p_cont_def_result_t)binaryReader.ReadUInt16(); p_result_list.p_results[i].reason = (p_provider_reason_t)binaryReader.ReadUInt16(); } else { p_result_list.p_results[i].result = (p_cont_def_result_t)EndianUtility.ReverseByteOrder(binaryReader.ReadUInt16()); p_result_list.p_results[i].reason = (p_provider_reason_t)EndianUtility.ReverseByteOrder(binaryReader.ReadUInt16()); } p_result_list.p_results[i].transfer_syntax = new p_syntax_id_t(); p_result_list.p_results[i].transfer_syntax.if_uuid = new Guid(binaryReader.ReadBytes(RpceUtility.GUID_SIZE)); p_result_list.p_results[i].transfer_syntax.if_version = binaryReader.ReadUInt32(); if (packed_drep.dataRepFormat != RpceDataRepresentationFormat.IEEE_LittleEndian_ASCII) { p_result_list.p_results[i].transfer_syntax.if_uuid = EndianUtility.ReverseByteOrder(p_result_list.p_results[i].transfer_syntax.if_uuid); p_result_list.p_results[i].transfer_syntax.if_version = EndianUtility.ReverseByteOrder(p_result_list.p_results[i].transfer_syntax.if_version); } } }
public void ReadBytesRequired_WithoutEnoughBytes_ThrowsException() { using MemoryStream ms = new MemoryStream(new byte[] { 0x10, 0x00, 0xBB }); using BinaryReader br = new BinaryReader(ms, new ASCIIEncoding()); Assert.Throws <System.IO.EndOfStreamException>(() => EndianUtility.ReadBytesRequired(br, 100)); }
public RpxFile(string rpxFilePath) { Console.WriteLine("Decompressing RPX file..."); path = rpxFilePath; decompressedPath = path + ".extract"; // Remove the temp file if it exists if (File.Exists(decompressedPath)) { File.Delete(decompressedPath); } crcDataOffset = 0; header = new RpxHeader(path); using (FileStream fs = new FileStream(decompressedPath, FileMode.OpenOrCreate, FileAccess.Write)) { using (BinaryWriter bw = new BinaryWriter(fs, new ASCIIEncoding())) { bw.Write(header.Identity); EndianUtility.WriteUInt16BE(bw, header.Type); EndianUtility.WriteUInt16BE(bw, header.Machine); EndianUtility.WriteUInt32BE(bw, header.Version); EndianUtility.WriteUInt32BE(bw, header.EntryPoint); EndianUtility.WriteUInt32BE(bw, header.PhOffset); EndianUtility.WriteUInt32BE(bw, header.SectionHeaderOffset); EndianUtility.WriteUInt32BE(bw, header.Flags); EndianUtility.WriteUInt16BE(bw, header.EhSize); EndianUtility.WriteUInt16BE(bw, header.PhEntSize); EndianUtility.WriteUInt16BE(bw, header.PhNum); EndianUtility.WriteUInt16BE(bw, header.ShEntSize); EndianUtility.WriteUInt16BE(bw, header.SectionHeaderCount); EndianUtility.WriteUInt16BE(bw, header.ShStrIndex); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); while ((ulong)bw.BaseStream.Position < header.SectionHeaderDataElfOffset) { bw.Write((byte)0); } while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); header.SectionHeaderDataElfOffset++; } } } sectionHeaderIndices = new List <RpxSectionHeaderSort>(); sectionHeaders = new List <RpxSectionHeader>(header.SectionHeaderCount); crcs = new List <uint>(header.SectionHeaderCount); // TODO: Add debug flag with this output //Console.WriteLine(header.ToString()); using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { // Seek to the Section Header Offset in the file br.BaseStream.Seek(header.SectionHeaderOffset, SeekOrigin.Begin); // Read in all of the section headers for (UInt32 i = 0; i < header.SectionHeaderCount; i++) { crcs.Add(0); // Read in the bytes for the section header byte[] buffer = br.ReadBytes(RpxSectionHeader.SECTION_HEADER_LENGTH); // Create a new section header and add it to the list RpxSectionHeader newSectionHeader = new RpxSectionHeader(buffer); sectionHeaders.Add(newSectionHeader); if (newSectionHeader.Offset != 0) { RpxSectionHeaderSort sectionHeaderIndex = new RpxSectionHeaderSort(); sectionHeaderIndex.index = i; sectionHeaderIndex.offset = newSectionHeader.Offset; sectionHeaderIndices.Add(sectionHeaderIndex); // TODO: Add debug flag with this output //Console.WriteLine(sectionHeaderIndex.ToString()); } // TODO: Add debug flag with this output //Console.WriteLine(newSectionHeader.ToString()); } } } sectionHeaderIndices.Sort(); // Iterate through all of the section header indices for (int i = 0; i < sectionHeaderIndices.Count; i++) { // Seek to the correct part of the file RpxSectionHeader currentSectionHeader = sectionHeaders[(int)sectionHeaderIndices[i].index]; UInt64 position = currentSectionHeader.Offset; using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { br.BaseStream.Seek((long)position, SeekOrigin.Begin); currentSectionHeader.Offset = (uint)br.BaseStream.Position; if ((currentSectionHeader.Flags & RpxSectionHeader.SECTION_HEADER_RPL_ZLIB) == RpxSectionHeader.SECTION_HEADER_RPL_ZLIB) { UInt32 dataSize = currentSectionHeader.Size - 4; currentSectionHeader.Size = EndianUtility.ReadUInt32BE(br); UInt32 blockSize = RpxSectionHeader.CHUNK_SIZE; UInt32 have; byte[] bufferIn = new byte[RpxSectionHeader.CHUNK_SIZE]; byte[] bufferOut = new byte[RpxSectionHeader.CHUNK_SIZE]; ZlibCodec compressor = new ZlibCodec(); compressor.InitializeInflate(true); compressor.AvailableBytesIn = 0; compressor.NextIn = 0; while (dataSize > 0) { blockSize = RpxSectionHeader.CHUNK_SIZE; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; bufferIn = br.ReadBytes((int)blockSize); compressor.NextIn = 0; compressor.InputBuffer = bufferIn; compressor.AvailableBytesIn = bufferIn.Length; compressor.OutputBuffer = bufferOut; do { compressor.AvailableBytesOut = (int)RpxSectionHeader.CHUNK_SIZE; compressor.NextOut = 0; compressor.Inflate(FlushType.None); have = RpxSectionHeader.CHUNK_SIZE - (uint)compressor.AvailableBytesOut; // write the data using (FileStream outFs = new FileStream(decompressedPath, FileMode.Append)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { bw.Write(bufferOut, 0, (int)have); } } crcs[(int)sectionHeaderIndices[i].index] = Crc32Rpx(crcs[(int)sectionHeaderIndices[i].index], bufferOut, have); } while (compressor.AvailableBytesOut == 0); currentSectionHeader.Flags &= ~RpxSectionHeader.SECTION_HEADER_RPL_ZLIB; } } else { UInt32 dataSize = currentSectionHeader.Size; UInt32 blockSize = RpxSectionHeader.CHUNK_SIZE; while (dataSize > 0) { byte[] data = new byte[RpxSectionHeader.CHUNK_SIZE]; blockSize = RpxSectionHeader.CHUNK_SIZE; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; data = br.ReadBytes((int)blockSize); // Write out the section bytes using (FileStream outFs = new FileStream(decompressedPath, FileMode.Append)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { bw.Write(data); } } crcs[(int)sectionHeaderIndices[i].index] = Crc32Rpx(crcs[(int)sectionHeaderIndices[i].index], data, blockSize); } } // Pad out the section on a 0x40 byte boundary using (FileStream outFs = new FileStream(decompressedPath, FileMode.Append)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); } } } if ((currentSectionHeader.Type & RpxSectionHeader.SECTION_HEADER_RPL_CRCS) == RpxSectionHeader.SECTION_HEADER_RPL_CRCS) { crcs[(int)sectionHeaderIndices[i].index] = 0; crcDataOffset = currentSectionHeader.Offset; } } } sectionHeaders[(int)sectionHeaderIndices[i].index] = currentSectionHeader; } // Fix the output headers // TODO: This is not currently accurate vs. wiiurpx tool so may need to investigate using (FileStream outFs = new FileStream(decompressedPath, FileMode.Open, FileAccess.Write)) { using (BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding())) { bw.Seek((int)header.SectionHeaderOffset, SeekOrigin.Begin); for (UInt32 i = 0; i < header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Name); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Type); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Flags); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Address); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Offset); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Size); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Link); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].Info); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].AddrAlign); EndianUtility.WriteUInt32BE(bw, sectionHeaders[(int)i].EntSize); } using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read)) { using (BinaryReader br = new BinaryReader(fs, new ASCIIEncoding())) { // Seek to the Section Header Offset in the file br.BaseStream.Seek((long)crcDataOffset, SeekOrigin.Begin); for (UInt32 i = 0; i < header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, crcs[(int)i]); } } } } } Console.WriteLine("Decompression complete."); }
/// <summary> /// Initializes a new instance of the <see cref="RpxFile"/> class. /// </summary> /// <param name="rpxFilePath">path to the RPX file.</param> /// <param name="verbose">whether to provide verbose output.</param> public RpxFile(string rpxFilePath, bool verbose = false) { Console.WriteLine("Decompressing RPX file..."); this.path = rpxFilePath; this.decompressedPath = this.path + ".extract"; // Remove the temp file if it exists if (File.Exists(this.decompressedPath)) { if (verbose) { Console.WriteLine("Removing file " + System.IO.Path.GetFullPath(this.decompressedPath)); } File.Delete(this.decompressedPath); } this.crcDataOffset = 0; this.header = new RpxHeader(this.path); using (FileStream fs = new FileStream(this.decompressedPath, FileMode.OpenOrCreate, FileAccess.Write)) { using BinaryWriter bw = new BinaryWriter(fs, new ASCIIEncoding()); bw.Write(this.header.Identity); EndianUtility.WriteUInt16BE(bw, this.header.Type); EndianUtility.WriteUInt16BE(bw, this.header.Machine); EndianUtility.WriteUInt32BE(bw, this.header.Version); EndianUtility.WriteUInt32BE(bw, this.header.EntryPoint); EndianUtility.WriteUInt32BE(bw, this.header.PhOffset); EndianUtility.WriteUInt32BE(bw, this.header.SectionHeaderOffset); EndianUtility.WriteUInt32BE(bw, this.header.Flags); EndianUtility.WriteUInt16BE(bw, this.header.EhSize); EndianUtility.WriteUInt16BE(bw, this.header.PhEntSize); EndianUtility.WriteUInt16BE(bw, this.header.PhNum); EndianUtility.WriteUInt16BE(bw, this.header.ShEntSize); EndianUtility.WriteUInt16BE(bw, this.header.SectionHeaderCount); EndianUtility.WriteUInt16BE(bw, this.header.ShStrIndex); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); EndianUtility.WriteUInt32BE(bw, 0x00000000); while ((ulong)bw.BaseStream.Position < this.header.SectionHeaderDataElfOffset) { bw.Write((byte)0); } while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); this.header.SectionHeaderDataElfOffset++; } } this.sectionHeaderIndices = new List <RpxSectionHeaderSort>(); this.sectionHeaders = new List <RpxSectionHeader>(this.header.SectionHeaderCount); this.crcs = new List <uint>(this.header.SectionHeaderCount); if (verbose) { Console.WriteLine(this.header.ToString()); } using (FileStream fs = new FileStream(this.path, FileMode.Open, FileAccess.Read)) { using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); // Seek to the Section Header Offset in the file br.BaseStream.Seek(this.header.SectionHeaderOffset, SeekOrigin.Begin); // Read in all of the section headers for (uint i = 0; i < this.header.SectionHeaderCount; i++) { this.crcs.Add(0); // Read in the bytes for the section header byte[] buffer = br.ReadBytes(RpxSectionHeader.SectionHeaderLength); // Create a new section header and add it to the list RpxSectionHeader newSectionHeader = new RpxSectionHeader(buffer); this.sectionHeaders.Add(newSectionHeader); if (newSectionHeader.Offset != 0) { RpxSectionHeaderSort sectionHeaderIndex = new RpxSectionHeaderSort { Index = i, Offset = newSectionHeader.Offset, }; this.sectionHeaderIndices.Add(sectionHeaderIndex); if (verbose) { Console.WriteLine(sectionHeaderIndex.ToString()); } } if (verbose) { Console.WriteLine(newSectionHeader.ToString()); } } } this.sectionHeaderIndices.Sort(); // Iterate through all of the section header indices for (int i = 0; i < this.sectionHeaderIndices.Count; i++) { if (verbose) { Console.WriteLine(this.sectionHeaderIndices[i].ToString()); } else { Console.Write("."); } // Seek to the correct part of the file RpxSectionHeader currentSectionHeader = this.sectionHeaders[(int)this.sectionHeaderIndices[i].Index]; ulong position = currentSectionHeader.Offset; using (FileStream fs = new FileStream(this.path, FileMode.Open, FileAccess.Read)) { using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); br.BaseStream.Seek((long)position, SeekOrigin.Begin); currentSectionHeader.Offset = (uint)br.BaseStream.Position; if ((currentSectionHeader.Flags & RpxSectionHeader.SectionHeaderRplZlib) == RpxSectionHeader.SectionHeaderRplZlib) { uint dataSize = currentSectionHeader.Size - 4; currentSectionHeader.Size = EndianUtility.ReadUInt32BE(br); uint blockSize = RpxSectionHeader.ChunkSize; uint have; byte[] bufferIn = new byte[RpxSectionHeader.ChunkSize]; byte[] bufferOut = new byte[RpxSectionHeader.ChunkSize]; ZlibCodec compressor = new ZlibCodec(); compressor.InitializeInflate(true); compressor.AvailableBytesIn = 0; compressor.NextIn = 0; while (dataSize > 0) { blockSize = RpxSectionHeader.ChunkSize; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; bufferIn = br.ReadBytes((int)blockSize); compressor.NextIn = 0; compressor.InputBuffer = bufferIn; compressor.AvailableBytesIn = bufferIn.Length; compressor.OutputBuffer = bufferOut; do { compressor.AvailableBytesOut = (int)RpxSectionHeader.ChunkSize; compressor.NextOut = 0; compressor.Inflate(FlushType.None); have = RpxSectionHeader.ChunkSize - (uint)compressor.AvailableBytesOut; // write the data using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Append)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); bw.Write(bufferOut, 0, (int)have); } this.crcs[(int)this.sectionHeaderIndices[i].Index] = this.Crc32Rpx(this.crcs[(int)this.sectionHeaderIndices[i].Index], bufferOut, have); }while (compressor.AvailableBytesOut == 0); currentSectionHeader.Flags &= ~RpxSectionHeader.SectionHeaderRplZlib; } } else { uint dataSize = currentSectionHeader.Size; uint blockSize = RpxSectionHeader.ChunkSize; while (dataSize > 0) { byte[] data = new byte[RpxSectionHeader.ChunkSize]; blockSize = RpxSectionHeader.ChunkSize; if (dataSize < blockSize) { blockSize = dataSize; } dataSize -= blockSize; data = br.ReadBytes((int)blockSize); // Write out the section bytes using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Append)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); bw.Write(data); } this.crcs[(int)this.sectionHeaderIndices[i].Index] = this.Crc32Rpx(this.crcs[(int)this.sectionHeaderIndices[i].Index], data, blockSize); } } // Pad out the section on a 0x40 byte boundary using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Append)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); while (bw.BaseStream.Position % 0x40 != 0) { bw.Write((byte)0); } } if ((currentSectionHeader.Type & RpxSectionHeader.SectionHeaderRplCrcs) == RpxSectionHeader.SectionHeaderRplCrcs) { this.crcs[(int)this.sectionHeaderIndices[i].Index] = 0; this.crcDataOffset = currentSectionHeader.Offset; } } this.sectionHeaders[(int)this.sectionHeaderIndices[i].Index] = currentSectionHeader; } // Fix the output headers // TODO: This is not currently accurate vs. wiiurpx tool so may need to investigate using (FileStream outFs = new FileStream(this.decompressedPath, FileMode.Open, FileAccess.Write)) { using BinaryWriter bw = new BinaryWriter(outFs, new ASCIIEncoding()); bw.Seek((int)this.header.SectionHeaderOffset, SeekOrigin.Begin); for (uint i = 0; i < this.header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Name); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Type); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Flags); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Address); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Offset); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Size); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Link); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].Info); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].AddrAlign); EndianUtility.WriteUInt32BE(bw, this.sectionHeaders[(int)i].EntSize); } using FileStream fs = new FileStream(this.path, FileMode.Open, FileAccess.Read); using BinaryReader br = new BinaryReader(fs, new ASCIIEncoding()); // Seek to the Section Header Offset in the file br.BaseStream.Seek((long)this.crcDataOffset, SeekOrigin.Begin); for (uint i = 0; i < this.header.SectionHeaderCount; i++) { EndianUtility.WriteUInt32BE(bw, this.crcs[(int)i]); } } Console.WriteLine(); Console.WriteLine("Decompression complete."); }