diff --git a/ICSharpCode.Decompiler/Metadata/Resource.cs b/ICSharpCode.Decompiler/Metadata/Resource.cs index db603f508..dab589928 100644 --- a/ICSharpCode.Decompiler/Metadata/Resource.cs +++ b/ICSharpCode.Decompiler/Metadata/Resource.cs @@ -40,6 +40,7 @@ namespace ICSharpCode.Decompiler.Metadata public virtual ManifestResourceAttributes Attributes => ManifestResourceAttributes.Public; public abstract string Name { get; } public abstract Stream? TryOpenStream(); + public abstract long? TryGetLength(); } public class ByteArrayResource : Resource @@ -57,6 +58,11 @@ namespace ICSharpCode.Decompiler.Metadata { return new MemoryStream(data); } + + public override long? TryGetLength() + { + return data.Length; + } } sealed class MetadataResource : Resource @@ -126,6 +132,29 @@ namespace ICSharpCode.Decompiler.Metadata return null; return new ResourceMemoryStream(Module.Reader, ptr + sizeof(int), length); } + + public unsafe override long? TryGetLength() + { + if (ResourceType != ResourceType.Embedded) + return null; + var headers = Module.Reader.PEHeaders; + if (headers.CorHeader == null) + return null; + var resources = headers.CorHeader.ResourcesDirectory; + if (resources.RelativeVirtualAddress == 0) + return null; + var sectionData = Module.Reader.GetSectionData(resources.RelativeVirtualAddress); + if (sectionData.Length == 0) + return null; + var resource = Module.Metadata.GetManifestResource(Handle); + if (resource.Offset > sectionData.Length) + return null; + byte* ptr = sectionData.Pointer + resource.Offset; + int length = ptr[0] + (ptr[1] << 8) + (ptr[2] << 16) + (ptr[3] << 24); + if (length < 0 || length > sectionData.Length) + return null; + return length; + } } sealed unsafe class ResourceMemoryStream : UnmanagedMemoryStream diff --git a/ICSharpCode.ILSpyX/LoadedPackage.cs b/ICSharpCode.ILSpyX/LoadedPackage.cs index d04504329..f99b78b9b 100644 --- a/ICSharpCode.ILSpyX/LoadedPackage.cs +++ b/ICSharpCode.ILSpyX/LoadedPackage.cs @@ -147,6 +147,7 @@ namespace ICSharpCode.ILSpyX public override string FullName => originalEntry.FullName; public override ResourceType ResourceType => originalEntry.ResourceType; public override Stream? TryOpenStream() => originalEntry.TryOpenStream(); + public override long? TryGetLength() => originalEntry.TryGetLength(); } sealed class ZipFileEntry : PackageEntry @@ -176,6 +177,16 @@ namespace ICSharpCode.ILSpyX memoryStream.Position = 0; return memoryStream; } + + public override long? TryGetLength() + { + Debug.WriteLine("TryGetLength " + Name); + using var archive = ZipFile.OpenRead(zipFile); + var entry = archive.GetEntry(Name); + if (entry == null) + return null; + return entry.Length; + } } sealed class BundleEntry : PackageEntry @@ -217,6 +228,11 @@ namespace ICSharpCode.ILSpyX return decompressedStream; } } + + public override long? TryGetLength() + { + return entry.Size; + } } } diff --git a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs index d09a0de1b..bb306aa9a 100644 --- a/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs +++ b/ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs @@ -67,7 +67,9 @@ namespace ICSharpCode.ILSpy.TreeNodes public override void Decompile(Language language, ITextOutput output, DecompilationOptions options) { - language.WriteCommentLine(output, string.Format("{0} ({1}, {2})", Resource.Name, Resource.ResourceType, Resource.Attributes)); + var sizeInBytes = Resource.TryGetLength(); + var sizeInBytesText = sizeInBytes == null ? "" : ", " + sizeInBytes + " bytes"; + language.WriteCommentLine(output, $"{Resource.Name} ({Resource.ResourceType}, {Resource.Attributes}{sizeInBytesText})"); ISmartTextOutput smartOutput = output as ISmartTextOutput; if (smartOutput != null)