static byte[] TryCreateIcon(IBinaryReader reader, ResourceDirectory iconDir) { try { reader.Position = 0; var outStream = new MemoryStream(); var writer = new BinaryWriter(outStream); // Write GRPICONDIR writer.Write(reader.ReadUInt16()); writer.Write(reader.ReadUInt16()); ushort numImages; writer.Write(numImages = reader.ReadUInt16()); var entries = new List<GrpIconDirEntry>(); for (int i = 0; i < numImages; i++) { var e = new GrpIconDirEntry(); entries.Add(e); e.bWidth = reader.ReadByte(); e.bHeight = reader.ReadByte(); e.bColorCount = reader.ReadByte(); e.bReserved = reader.ReadByte(); e.wPlanes = reader.ReadUInt16(); e.wBitCount = reader.ReadUInt16(); e.dwBytesInRes = reader.ReadUInt32(); e.nID = reader.ReadUInt16(); } uint dataOffset = 2 * 3 + (uint)entries.Count * 0x10; foreach (var e in entries) { writer.Write(e.bWidth); writer.Write(e.bHeight); writer.Write(e.bColorCount); writer.Write(e.bReserved); writer.Write(e.wPlanes); writer.Write(e.wBitCount); writer.Write(e.dwBytesInRes); writer.Write(dataOffset); dataOffset += e.dwBytesInRes; } foreach (var e in entries) { var d = iconDir.Directories.FirstOrDefault(a => a.Name == new ResourceName(e.nID)); if (d == null || d.Data.Count == 0) return null; var r = d.Data[0].Data; Debug.Assert(r.Length == e.dwBytesInRes); if (r.Length < e.dwBytesInRes) return null; r.Position = 0; writer.Write(r.ReadBytes((int)e.dwBytesInRes), 0, (int)e.dwBytesInRes); } return outStream.ToArray(); } catch (IOException) { } return null; }
/// <summary> /// Dispose method /// </summary> /// <param name="disposing"><c>true</c> if called by <see cref="Dispose()"/></param> protected virtual void Dispose(bool disposing) { if (!disposing) return; var root = Root; if (root != null) root.Dispose(); Root = null; }
static void GetNamedAndIds(ResourceDirectory dir, out List<ResourceDirectoryEntry> named, out List<ResourceDirectoryEntry> ids) { named = new List<ResourceDirectoryEntry>(); ids = new List<ResourceDirectoryEntry>(); foreach (var d in dir.Directories) { if (d.Name.HasId) ids.Add(d); else named.Add(d); } foreach (var d in dir.Data) { if (d.Name.HasId) ids.Add(d); else named.Add(d); } }
uint WriteTo(BinaryWriter writer, ResourceDirectory dir) { writer.Write(dir.Characteristics); writer.Write(dir.TimeDateStamp); writer.Write(dir.MajorVersion); writer.Write(dir.MinorVersion); List<ResourceDirectoryEntry> named; List<ResourceDirectoryEntry> ids; GetNamedAndIds(dir, out named, out ids); if (named.Count > ushort.MaxValue || ids.Count > ushort.MaxValue) throw new ModuleWriterException("Too many named/id Win32 resource entries"); writer.Write((ushort)named.Count); writer.Write((ushort)ids.Count); // These must be sorted in ascending order. Names are case insensitive. named.Sort((a, b) => a.Name.Name.ToUpperInvariant().CompareTo(b.Name.Name.ToUpperInvariant())); ids.Sort((a, b) => a.Name.Id.CompareTo(b.Name.Id)); foreach (var d in named) { writer.Write(0x80000000 | stringsDict[d.Name.Name]); writer.Write(GetDirectoryEntryOffset(d)); } foreach (var d in ids) { writer.Write(d.Name.Id); writer.Write(GetDirectoryEntryOffset(d)); } return 16 + (uint)(named.Count + ids.Count) * 8; }
void FindDirectoryEntries(ResourceDirectory dir) { if (dirDict.ContainsKey(dir)) return; dirList.Add(dir); dirDict[dir] = 0; foreach (var dir2 in dir.Directories) FindDirectoryEntries(dir2); foreach (var data in dir.Data) { if (dataHeaderDict.ContainsKey(data)) continue; dataHeaderList.Add(data); dataHeaderDict[data] = 0; } }
/// <summary> /// Returns the <see cref="RVA"/> of a <see cref="ResourceDirectory"/>. /// <see cref="SetOffset"/> must have been called. /// </summary> /// <param name="dir">A <see cref="ResourceDirectory"/></param> /// <returns>The RVA or 0 if <paramref name="dir"/> is invalid</returns> public RVA GetRVA(ResourceDirectory dir) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dir, out fileOffset, out rva); return rva; }
/// <summary> /// Returns the <see cref="FileOffset"/> of a <see cref="ResourceDirectory"/>. /// <see cref="SetOffset"/> must have been called. /// </summary> /// <param name="dir">A <see cref="ResourceDirectory"/></param> /// <returns>The file offset or 0 if <paramref name="dir"/> is invalid</returns> public FileOffset GetFileOffset(ResourceDirectory dir) { FileOffset fileOffset; RVA rva; GetFileOffsetAndRvaOf(dir, out fileOffset, out rva); return fileOffset; }
/// <summary> /// Returns the <see cref="FileOffset"/> and <see cref="RVA"/> of a /// <see cref="ResourceDirectory"/>. <see cref="SetOffset"/> must have been called. /// </summary> /// <param name="dir">A <see cref="ResourceDirectory"/></param> /// <param name="fileOffset">Updated with the file offset</param> /// <param name="rva">Updated with the RVA</param> /// <returns><c>true</c> if <paramref name="dir"/> is valid and /// <paramref name="fileOffset"/> and <paramref name="rva"/> have been updated. <c>false</c> /// if <paramref name="dir"/> is not part of the Win32 resources.</returns> public bool GetFileOffsetAndRvaOf(ResourceDirectory dir, out FileOffset fileOffset, out RVA rva) { uint offs; if (dir == null || !dirDict.TryGetValue(dir, out offs)) { fileOffset = 0; rva = 0; return false; } fileOffset = offset + offs; rva = this.rva + offs; return true; }
/// <summary> /// Dispose method /// </summary> /// <param name="disposing"><c>true</c> if called by <see cref="Dispose()"/></param> protected virtual void Dispose(bool disposing) { if (!disposing) return; Root = null; // Property handler will call Dispose() }