/// <summary> /// Writes header information into output stream (w/o CRC and table offsets/paddings). /// </summary> /// <param name="writer">Binary writer with correct endianness.</param> /// <param name="isPreAllocationCall">If true no assembly name will be written.</param> public void Write( TinyBinaryWriter writer, Boolean isPreAllocationCall) { writer.WriteString("MSSpot1"); writer.WriteUInt32(0); // header CRC writer.WriteUInt32(0); // assembly CRC writer.WriteUInt32(writer.IsBigEndian ? FLAGS_BIG_ENDIAN : FLAGS_LITTLE_ENDIAN); // This CRC calculated only for BE assemblies!!! writer.WriteUInt32(writer.IsBigEndian ? _context.NativeMethodsCrc.Current : 0x00); writer.WriteUInt32(0xFFFFFFFF); // Native methods offset writer.WriteVersion(_context.AssemblyDefinition.Name.Version); writer.WriteUInt16(isPreAllocationCall ? (UInt16) 0x0000 : _context.StringTable.GetOrCreateStringId(_context.AssemblyDefinition.Name.Name)); writer.WriteUInt16(1); // String table version if (isPreAllocationCall) { _tablesOffset = writer.BaseStream.Position; for (var i = 0; i < 16; ++i) { writer.WriteUInt32(0); } writer.WriteUInt32(0); // Number of patched methods _paddingsOffset = writer.BaseStream.Position; for (var i = 0; i < 16; ++i) { writer.WriteByte(0); } } else { writer.BaseStream.Seek(12, SeekOrigin.Begin); var assemblyCrc32 = ComputeCrc32(writer.BaseStream, _paddingsOffset, writer.BaseStream.Length - _paddingsOffset); writer.WriteUInt32(assemblyCrc32); writer.BaseStream.Seek(8, SeekOrigin.Begin); var headerCrc32 = ComputeCrc32(writer.BaseStream, 0, _paddingsOffset); writer.WriteUInt32(headerCrc32); } }
/// <inheritdoc/> protected override void WriteSingleItem( TinyBinaryWriter writer, MethodReference item) { UInt16 referenceId; _context.TypeReferencesTable.TryGetTypeReferenceId(item.DeclaringType, out referenceId); WriteStringReference(writer, item.Name); writer.WriteUInt16(referenceId); writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(item)); writer.WriteUInt16(0); // padding }
private void WriteAttributes( TinyBinaryWriter writer, UInt16 tableNumber, IEnumerable <Tuple <CustomAttribute, UInt16> > attributes) { foreach (var item in attributes) { var attribute = item.Item1; var targetIdentifier = item.Item2; writer.WriteUInt16(tableNumber); writer.WriteUInt16(targetIdentifier); writer.WriteUInt16(_context.GetMethodReferenceId(attribute.Constructor)); writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(attribute)); } }
private void WriteMethodBodies( Collection <MethodDefinition> methods, Collection <TypeReference> iInterfaces, TinyBinaryWriter writer) { UInt16 firstMethodId = 0xFFFF; var virtualMethodsNumber = 0; foreach (var method in methods.Where(item => item.IsVirtual)) { firstMethodId = Math.Min(firstMethodId, _context.ByteCodeTable.GetMethodId(method)); CreateMethodSignatures(method); ++virtualMethodsNumber; } var instanceMethodsNumber = 0; foreach (var method in methods.Where(item => !(item.IsVirtual || item.IsStatic))) { firstMethodId = Math.Min(firstMethodId, _context.ByteCodeTable.GetMethodId(method)); CreateMethodSignatures(method); ++instanceMethodsNumber; } var staticMethodsNumber = 0; foreach (var method in methods.Where(item => item.IsStatic)) { firstMethodId = Math.Min(firstMethodId, _context.ByteCodeTable.GetMethodId(method)); CreateMethodSignatures(method); ++staticMethodsNumber; } if (virtualMethodsNumber + instanceMethodsNumber + staticMethodsNumber == 0) { firstMethodId = _context.ByteCodeTable.NextMethodId; } writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(iInterfaces)); writer.WriteUInt16(firstMethodId); writer.WriteByte((Byte)virtualMethodsNumber); writer.WriteByte((Byte)instanceMethodsNumber); writer.WriteByte((Byte)staticMethodsNumber); }
private void WriteAttributes( TinyBinaryWriter writer, UInt16 tableNumber, IEnumerable<Tuple<CustomAttribute, UInt16>> attributes) { foreach (var item in attributes) { var attribute = item.Item1; var targetIdentifier = item.Item2; writer.WriteUInt16(tableNumber); writer.WriteUInt16(targetIdentifier); writer.WriteUInt16(_context.GetMethodReferenceId(attribute.Constructor)); writer.WriteUInt16(_context.SignaturesTable.GetOrCreateSignatureId(attribute)); } }
private void WriteClassFields( IList <FieldDefinition> fieldsList, TinyBinaryWriter writer) { var firstStaticFieldId = _context.FieldsTable.MaxFieldId; var staticFieldsNumber = 0; foreach (var field in fieldsList.Where(item => item.IsStatic)) { UInt16 fieldReferenceId; _context.FieldsTable.TryGetFieldReferenceId(field, true, out fieldReferenceId); firstStaticFieldId = Math.Min(firstStaticFieldId, fieldReferenceId); _context.SignaturesTable.GetOrCreateSignatureId(field); _context.StringTable.GetOrCreateStringId(field.Name); ++staticFieldsNumber; } var firstInstanseFieldId = _context.FieldsTable.MaxFieldId; var instanceFieldsNumber = 0; foreach (var field in fieldsList.Where(item => !item.IsStatic)) { UInt16 fieldReferenceId; _context.FieldsTable.TryGetFieldReferenceId(field, true, out fieldReferenceId); firstInstanseFieldId = Math.Min(firstInstanseFieldId, fieldReferenceId); _context.SignaturesTable.GetOrCreateSignatureId(field); _context.StringTable.GetOrCreateStringId(field.Name); ++instanceFieldsNumber; } if (firstStaticFieldId > firstInstanseFieldId) { firstStaticFieldId = firstInstanseFieldId; } writer.WriteUInt16(firstStaticFieldId); writer.WriteUInt16(firstInstanseFieldId); writer.WriteByte((Byte)staticFieldsNumber); writer.WriteByte((Byte)instanceFieldsNumber); }
/// <inheritdoc/> protected override void WriteSingleItem( TinyBinaryWriter writer, AssemblyNameReference item) { WriteStringReference(writer, item.Name); writer.WriteUInt16(0); // padding writer.WriteVersion(item.Version); }
/// <inheritdoc/> public void Write( TinyBinaryWriter writer) { var offset = 0U; foreach (var item in _resouces) { writer.WriteUInt32(0x02); // Version writer.WriteUInt32(0x04); // Size of header writer.WriteUInt32(0x08); // Size of resouce header writer.WriteUInt32(item.Item2); writer.WriteUInt16(item.Item1); writer.WriteUInt16(0x0); // paddding writer.WriteUInt32(offset); offset += 8; // Size of resource table record } }
public void Process( TinyBinaryWriter writer) { writer.WriteUInt32((UInt32)_bitmap.Width); writer.WriteUInt32((UInt32)_bitmap.Height); writer.WriteUInt16(0x00); // flags var tinyImageFormat = GetTinytImageFormat(_bitmap.RawFormat); if (tinyImageFormat != 0) { writer.WriteByte(0x01); // bpp writer.WriteByte(tinyImageFormat); _bitmap.Save(writer.BaseStream, _bitmap.RawFormat); } else { writer.WriteByte(0x10); // bpp writer.WriteByte(tinyImageFormat); var rect = new Rectangle(Point.Empty, _bitmap.Size); using (var convertedBitmap = _bitmap.Clone(new Rectangle(Point.Empty, _bitmap.Size), PixelFormat.Format16bppRgb565)) { var bitmapData = convertedBitmap.LockBits( rect, ImageLockMode.ReadOnly, convertedBitmap.PixelFormat); var buffer = new Int16[bitmapData.Stride * convertedBitmap.Height / sizeof(Int16)]; System.Runtime.InteropServices.Marshal.Copy( bitmapData.Scan0, buffer, 0, buffer.Length); convertedBitmap.UnlockBits(bitmapData); foreach (var item in buffer) { writer.WriteInt16(item); } } } }
/// <summary> /// Processes original data and writes processed data into output writer. /// </summary> /// <param name="writer">Endianness-aware binary writer.</param> public void Process( TinyBinaryWriter writer) { using (var stream = new MemoryStream(_fontResouce, false)) using (var reader = new BinaryReader(stream)) { // CLR_GFX_FontDescription { // CLR_GFX_FontMetrics writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontMetrics.m_height writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_offset writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_ascent writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_descent writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_internalLeading writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_externalLeading writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_aveCharWidth writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontMetrics.m_aveCharWidth } var rangesCount = reader.ReadInt16(); writer.WriteInt16(rangesCount); // CLR_GFX_FontDescription.m_ranges var charactersCount = reader.ReadInt16(); writer.WriteInt16(charactersCount); // CLR_GFX_FontDescription.m_characters var flags = reader.ReadInt16(); writer.WriteInt16(flags); // CLR_GFX_FontDescription.m_flags writer.WriteInt16(reader.ReadInt16()); // CLR_GFX_FontDescription.m_pad // CLR_GFX_BitmapDescription var width = reader.ReadUInt32(); writer.WriteUInt32(width); // CLR_GFX_BitmapDescription.m_width var height = reader.ReadUInt32(); writer.WriteUInt32(height); // CLR_GFX_BitmapDescription.m_height writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_BitmapDescription.m_flags var bitsPerPixel = reader.ReadByte(); writer.WriteByte(bitsPerPixel); // CLR_GFX_BitmapDescription.m_bitsPerPixel writer.WriteByte(reader.ReadByte()); // CLR_GFX_BitmapDescription.m_type for (var i = 0; i <= rangesCount; ++i) // Including sentinel range { // CLR_GFX_FontCharacterRange writer.WriteUInt32(reader.ReadUInt32()); // CLR_GFX_FontCharacterRange.m_indexOfFirstFontCharacter writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontCharacterRange.m_firstChar writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontCharacterRange.m_lastChar writer.WriteUInt32(reader.ReadUInt32()); // CLR_GFX_FontCharacterRange.m_rangeOffset } for (var i = 0; i <= charactersCount; ++i) // Including sentinel character { // CLR_GFX_FontCharacter writer.WriteUInt16(reader.ReadUInt16()); // CLR_GFX_FontCharacter.m_offset writer.WriteByte(reader.ReadByte()); // CLR_GFX_FontCharacter.m_marginLeft writer.WriteByte(reader.ReadByte()); // CLR_GFX_FontCharacter.m_marginRight } if (bitsPerPixel == 0) { bitsPerPixel = 16; // Native value, rest calculations are same } var totalSizeInWords = ((width * bitsPerPixel + 31) / 32) * height; for (var i = 0; i < totalSizeInWords; ++i) { writer.WriteUInt32(reader.ReadUInt32()); } if ((flags & FLAG_FONT_EX) == FLAG_FONT_EX) { // TODO: implement it according original idea if needed } while (stream.Position < stream.Length) { writer.WriteByte(reader.ReadByte()); } } }
private void WriteExceptionsTable() { if (!_body.HasExceptionHandlers) { return; } foreach (var handler in _body.ExceptionHandlers .OrderBy(item => item.HandlerStart.Offset)) { switch (handler.HandlerType) { case ExceptionHandlerType.Catch: _writer.WriteUInt16(0x0000); _writer.WriteUInt16(GetTypeReferenceId(handler.CatchType, 0x8000)); break; case ExceptionHandlerType.Fault: _writer.WriteUInt16(0x0001); _writer.WriteUInt16(0x0000); break; case ExceptionHandlerType.Finally: _writer.WriteUInt16(0x0002); _writer.WriteUInt16(0x0000); break; case ExceptionHandlerType.Filter: _writer.WriteUInt16(0x0003); _writer.WriteUInt16((UInt16)handler.FilterStart.Offset); break; } _writer.WriteUInt16((UInt16)handler.TryStart.Offset); _writer.WriteUInt16((UInt16)handler.TryEnd.Offset); _writer.WriteUInt16((UInt16)handler.HandlerStart.Offset); if (handler.HandlerEnd == null) { _writer.WriteUInt16((UInt16)_body.Instructions.Last().Offset); } else { _writer.WriteUInt16((UInt16)handler.HandlerEnd.Offset); } } _writer.WriteByte((Byte)_body.ExceptionHandlers.Count); }
/// <summary> /// Writes string reference ID related to passed string value into output stream. /// </summary> /// <param name="writer">Target binary writer for writing reference ID.</param> /// <param name="value">String value for obtaining reference and writing.</param> protected void WriteStringReference( TinyBinaryWriter writer, String value) { writer.WriteUInt16(GetOrCreateStringId(value)); }