/// <inheritdoc/> protected override void WriteSingleItem( TinyBinaryWriter writer, MethodDefinition item) { WriteStringReference(writer, item.Name); writer.WriteUInt16(_context.ByteCodeTable.GetMethodRva(item)); writer.WriteUInt32(GetFlags(item)); var parametersCount = (Byte)item.Parameters.Count; if (!item.IsStatic) { ++parametersCount; // add implicit 'this' pointer into non-static methods } _context.SignaturesTable.WriteDataType(item.ReturnType, writer, false, false); if (item.ReturnType is TypeSpecification) { _context.TypeSpecificationsTable .GetOrCreateTypeSpecificationId(item.ReturnType); } writer.WriteByte(parametersCount); writer.WriteByte((Byte)(item.HasBody ? item.Body.Variables.Count : 0)); writer.WriteByte(CodeWriter.CalculateStackSize(item.Body)); var methodSignature = _context.SignaturesTable.GetOrCreateSignatureId(item); writer.WriteUInt16(item.HasBody ? _context.SignaturesTable.GetOrCreateSignatureId(item.Body.Variables) : (item.IsAbstract || item.IsRuntime ? (UInt16)0x0000 : (UInt16)0xFFFF)); writer.WriteUInt16(methodSignature); }
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 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); }
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); } } } }
private void WriteTypeInfo( TypeReference typeReference, TinyBinaryWriter writer) { if (typeReference.IsOptionalModifier) { writer.WriteByte(0); // OpTypeModifier ??? } var byReference = typeReference as ByReferenceType; if (byReference != null) { writer.WriteByte((Byte)TinyDataType.DATATYPE_BYREF); WriteDataType(byReference.ElementType, writer, true, false); } else { WriteDataType(typeReference, writer, true, false); } }
/// <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); } }
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> /// Updates tables offest value and padding value for current table and /// advance writing position for next method call (filling tables info). /// </summary> /// <param name="writer">Binary writer with correct endianness.</param> /// <param name="tableBegin">Table beginning address (offset).</param> /// <param name="padding">Table padding value.</param> public void UpdateTableOffset( TinyBinaryWriter writer, Int64 tableBegin, Int64 padding) { writer.BaseStream.Seek(_tablesOffset, SeekOrigin.Begin); writer.WriteUInt32((UInt32)tableBegin); _tablesOffset += sizeof(Int32); writer.BaseStream.Seek(_paddingsOffset, SeekOrigin.Begin); writer.WriteByte((Byte)padding); _paddingsOffset += sizeof(Byte); writer.BaseStream.Seek(0, SeekOrigin.End); }
/// <inheritdoc/> public void Write( TinyBinaryWriter writer) { var orderedResources = new SortedDictionary <Int16, Tuple <ResourceKind, Byte[]> >(); foreach (var item in _resources.OfType <EmbeddedResource>()) { var count = 0U; using (var reader = new ResourceReader(item.GetResourceStream())) { foreach (DictionaryEntry resource in reader) { String resourceType; Byte[] resourceData; var resourceName = resource.Key.ToString(); reader.GetResourceData(resourceName, out resourceType, out resourceData); var kind = GetResourceKind(resourceType, resourceData); if (kind == ResourceKind.Bitmap) { using (var stream = new MemoryStream(resourceData.Length)) { var bitmapProcessor = new TinyBitmapProcessor((Bitmap)resource.Value); bitmapProcessor.Process(writer.GetMemoryBasedClone(stream)); resourceData = stream.ToArray(); } } orderedResources.Add(GenerateIdFromResourceName(resourceName), new Tuple <ResourceKind, Byte[]>(kind, resourceData)); ++count; } } _context.ResourceFileTable.AddResourceFile(item, count); } foreach (var item in orderedResources) { var kind = item.Value.Item1; var bytes = item.Value.Item2; var padding = 0; switch (kind) { case ResourceKind.String: var stringLength = (Int32)bytes[0]; if (stringLength < 0x7F) { bytes = bytes.Skip(1).Concat(Enumerable.Repeat((Byte)0, 1)).ToArray(); } else { bytes = bytes.Skip(2).Concat(Enumerable.Repeat((Byte)0, 1)).ToArray(); } break; case ResourceKind.Bitmap: padding = _context.ResourceDataTable.AlignToWord(); break; case ResourceKind.Binary: bytes = bytes.Skip(4).ToArray(); break; case ResourceKind.Font: padding = _context.ResourceDataTable.AlignToWord(); bytes = bytes.Skip(32).ToArray(); // File size + resource header size break; } // Pre-process font data (swap endiannes if needed). if (kind == ResourceKind.Font) { using (var stream = new MemoryStream(bytes.Length)) { var fontProcessor = new TinyFontProcessor(bytes); fontProcessor.Process(writer.GetMemoryBasedClone(stream)); bytes = stream.ToArray(); } } writer.WriteInt16(item.Key); writer.WriteByte((Byte)kind); writer.WriteByte((Byte)padding); writer.WriteInt32(_context.ResourceDataTable.CurrentOffset); _context.ResourceDataTable.AddResourceData(bytes); } if (orderedResources.Count != 0) { writer.WriteInt16(0x7FFF); writer.WriteByte((Byte)ResourceKind.None); writer.WriteByte(0x00); writer.WriteInt32(_context.ResourceDataTable.CurrentOffset); } }
/// <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()); } } }
/// <summary> /// Writes data tzpe signature into ouput stream. /// </summary> /// <param name="typeDefinition">Tzpe reference or definition in Mono.Cecil format.</param> /// <param name="writer">Target binary writer for writing signature information.</param> /// <param name="alsoWriteSubType">If set to <c>true</c> also sub-type will be written.</param> /// <param name="expandEnumType">If set to <c>true</c> expand enum with base type.</param> public void WriteDataType( TypeReference typeDefinition, TinyBinaryWriter writer, Boolean alsoWriteSubType, Boolean expandEnumType) { TinyDataType dataType; if (_primitiveTypes.TryGetValue(typeDefinition.FullName, out dataType)) { writer.WriteByte((Byte)dataType); return; } if (typeDefinition is TypeSpecification) { //Debug.Fail("Gotcha!"); } if (typeDefinition.MetadataType == MetadataType.Class) { writer.WriteByte((Byte)TinyDataType.DATATYPE_CLASS); if (alsoWriteSubType) { WriteSubTypeInfo(typeDefinition, writer); } return; } if (typeDefinition.MetadataType == MetadataType.ValueType) { var resolvedType = typeDefinition.Resolve(); if (resolvedType != null && resolvedType.IsEnum && expandEnumType) { var baseTypeValue = resolvedType.Fields.FirstOrDefault(item => item.IsSpecialName); if (baseTypeValue != null) { WriteTypeInfo(baseTypeValue.FieldType, writer); return; } } writer.WriteByte((Byte)TinyDataType.DATATYPE_VALUETYPE); if (alsoWriteSubType) { WriteSubTypeInfo(typeDefinition, writer); } return; } if (typeDefinition.IsArray) { writer.WriteByte((Byte)TinyDataType.DATATYPE_SZARRAY); if (alsoWriteSubType) { var array = (ArrayType)typeDefinition; WriteDataType(array.ElementType, writer, true, expandEnumType); } return; } writer.WriteByte(0x00); }
/// <inheritdoc/> public void Write( TinyBinaryWriter writer) { var orderedResources = new SortedDictionary<Int16, Tuple<ResourceKind, Byte[]>>(); foreach (var item in _resources.OfType<EmbeddedResource>()) { var count = 0U; using (var reader = new ResourceReader(item.GetResourceStream())) { foreach (DictionaryEntry resource in reader) { String resourceType; Byte[] resourceData; var resourceName = resource.Key.ToString(); reader.GetResourceData(resourceName, out resourceType, out resourceData); var kind = GetResourceKind(resourceType, resourceData); if (kind == ResourceKind.Bitmap) { using (var stream = new MemoryStream(resourceData.Length)) { var bitmapProcessor = new TinyBitmapProcessor((Bitmap)resource.Value); bitmapProcessor.Process(writer.GetMemoryBasedClone(stream)); resourceData = stream.ToArray(); } } orderedResources.Add(GenerateIdFromResourceName(resourceName), new Tuple<ResourceKind, Byte[]>(kind, resourceData)); ++count; } } _context.ResourceFileTable.AddResourceFile(item, count); } foreach (var item in orderedResources) { var kind = item.Value.Item1; var bytes = item.Value.Item2; var padding = 0; switch (kind) { case ResourceKind.String: var stringLength = (Int32)bytes[0]; if (stringLength < 0x7F) { bytes = bytes.Skip(1).Concat(Enumerable.Repeat((Byte)0, 1)).ToArray(); } else { bytes = bytes.Skip(2).Concat(Enumerable.Repeat((Byte)0, 1)).ToArray(); } break; case ResourceKind.Bitmap: padding = _context.ResourceDataTable.AlignToWord(); break; case ResourceKind.Binary: bytes = bytes.Skip(4).ToArray(); break; case ResourceKind.Font: padding = _context.ResourceDataTable.AlignToWord(); bytes = bytes.Skip(32).ToArray(); // File size + resource header size break; } // Pre-process font data (swap endiannes if needed). if (kind == ResourceKind.Font) { using (var stream = new MemoryStream(bytes.Length)) { var fontProcessor = new TinyFontProcessor(bytes); fontProcessor.Process(writer.GetMemoryBasedClone(stream)); bytes = stream.ToArray(); } } writer.WriteInt16(item.Key); writer.WriteByte((Byte)kind); writer.WriteByte((Byte)padding); writer.WriteInt32(_context.ResourceDataTable.CurrentOffset); _context.ResourceDataTable.AddResourceData(bytes); } if (orderedResources.Count != 0) { writer.WriteInt16(0x7FFF); writer.WriteByte((Byte)ResourceKind.None); writer.WriteByte(0x00); writer.WriteInt32(_context.ResourceDataTable.CurrentOffset); } }
/// <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); } }