Example #1
0
		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;
		}
Example #9
0
		/// <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()
		}