using System; using System.Collections; using System.IO; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters.Binary; using System.Text; namespace System.Resources { /// Enumerates .resources files and streams, reading sequential resource name and value pairs. // Token: 0x02000279 RID: 633 [ComVisible(true)] public sealed class ResourceReader : IEnumerable, IDisposable, IResourceReader { /// Initializes a new instance of the class for the specified stream. /// The input stream for reading resources. /// The is not readable. /// The parameter is null. /// An I/O error has occurred while accessing . // Token: 0x06002057 RID: 8279 RVA: 0x00075980 File Offset: 0x00073B80 public ResourceReader(Stream stream) { if (stream == null) { throw new ArgumentNullException("stream"); } if (!stream.CanRead) { throw new ArgumentException("Stream was not readable."); } this.reader = new BinaryReader(stream, Encoding.UTF8); this.formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence)); this.ReadHeaders(); } /// Initializes a new instance of the class for the specified resource file. /// The path of the resource file to be read. /// The parameter is null. /// The file cannot be found. /// An I/O error has occurred. /// The resource file has an invalid format. For example, the length of the file is zero. // Token: 0x06002058 RID: 8280 RVA: 0x000759FC File Offset: 0x00073BFC public ResourceReader(string fileName) { this.reader = new BinaryReader(new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)); this.formatter = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence)); this.ReadHeaders(); } /// Returns an enumerator for this . /// An for this . /// The reader has already been closed, and thus cannot be accessed. // Token: 0x06002059 RID: 8281 RVA: 0x00075A54 File Offset: 0x00073C54 IEnumerator IEnumerable.GetEnumerator() { return ((IResourceReader)this).GetEnumerator(); } /// Releases the resources used by the . // Token: 0x0600205A RID: 8282 RVA: 0x00075A5C File Offset: 0x00073C5C void IDisposable.Dispose() { this.Dispose(true); } // Token: 0x0600205B RID: 8283 RVA: 0x00075A68 File Offset: 0x00073C68 private void ReadHeaders() { try { int num = this.reader.ReadInt32(); if (num != ResourceManager.MagicNumber) { throw new ArgumentException(string.Format("Stream is not a valid .resources file, magic=0x{0:x}", num)); } int num2 = this.reader.ReadInt32(); int num3 = this.reader.ReadInt32(); if (num2 > ResourceManager.HeaderVersionNumber) { this.reader.BaseStream.Seek((long)num3, SeekOrigin.Current); } else { string text = this.reader.ReadString(); if (!text.StartsWith("System.Resources.ResourceReader")) { throw new NotSupportedException("This .resources file requires reader class " + text); } string text2 = this.reader.ReadString(); if (!text2.StartsWith(typeof(ResourceSet).FullName) && !text2.StartsWith("System.Resources.RuntimeResourceSet")) { throw new NotSupportedException("This .resources file requires set class " + text2); } } this.resource_ver = this.reader.ReadInt32(); if (this.resource_ver != 1 && this.resource_ver != 2) { throw new NotSupportedException("This .resources file requires unsupported set class version: " + this.resource_ver.ToString()); } this.resourceCount = this.reader.ReadInt32(); this.typeCount = this.reader.ReadInt32(); this.typeNames = new string[this.typeCount]; for (int i = 0; i < this.typeCount; i++) { this.typeNames[i] = this.reader.ReadString(); } int num4 = (int)(this.reader.BaseStream.Position & 7L); int num5 = 0; if (num4 != 0) { num5 = 8 - num4; } for (int j = 0; j < num5; j++) { byte b = this.reader.ReadByte(); if ((char)b != "PAD"[j % 3]) { throw new ArgumentException("Malformed .resources file (padding values incorrect)"); } } this.hashes = new int[this.resourceCount]; for (int k = 0; k < this.resourceCount; k++) { this.hashes[k] = this.reader.ReadInt32(); } long[] array = new long[this.resourceCount]; for (int l = 0; l < this.resourceCount; l++) { array[l] = (long)this.reader.ReadInt32(); } this.dataSectionOffset = this.reader.ReadInt32(); this.nameSectionOffset = this.reader.BaseStream.Position; long position = this.reader.BaseStream.Position; this.infos = new ResourceReader.ResourceInfo[this.resourceCount]; for (int m = 0; m < this.resourceCount; m++) { this.CreateResourceInfo(array[m], ref this.infos[m]); } this.reader.BaseStream.Seek(position, SeekOrigin.Begin); } catch (EndOfStreamException ex) { throw new ArgumentException("Stream is not a valid .resources file! It was possibly truncated.", ex); } } // Token: 0x0600205C RID: 8284 RVA: 0x00075DA8 File Offset: 0x00073FA8 private void CreateResourceInfo(long position, ref ResourceReader.ResourceInfo info) { long num = position + this.nameSectionOffset; this.reader.BaseStream.Seek(num, SeekOrigin.Begin); int num2 = this.Read7BitEncodedInt(); byte[] array = new byte[num2]; this.reader.Read(array, 0, num2); string @string = Encoding.Unicode.GetString(array); long num3 = (long)(this.reader.ReadInt32() + this.dataSectionOffset); this.reader.BaseStream.Seek(num3, SeekOrigin.Begin); int num4 = this.Read7BitEncodedInt(); info = new ResourceReader.ResourceInfo(@string, this.reader.BaseStream.Position, num4); } // Token: 0x0600205D RID: 8285 RVA: 0x00075E44 File Offset: 0x00074044 private int Read7BitEncodedInt() { int num = 0; int num2 = 0; byte b; do { b = this.reader.ReadByte(); num |= (int)(b & 127) << num2; num2 += 7; } while ((b & 128) == 128); return num; } // Token: 0x0600205E RID: 8286 RVA: 0x00075E84 File Offset: 0x00074084 private object ReadValueVer2(int type_index) { switch (type_index) { case 0: return null; case 1: return this.reader.ReadString(); case 2: return this.reader.ReadBoolean(); case 3: return (char)this.reader.ReadUInt16(); case 4: return this.reader.ReadByte(); case 5: return this.reader.ReadSByte(); case 6: return this.reader.ReadInt16(); case 7: return this.reader.ReadUInt16(); case 8: return this.reader.ReadInt32(); case 9: return this.reader.ReadUInt32(); case 10: return this.reader.ReadInt64(); case 11: return this.reader.ReadUInt64(); case 12: return this.reader.ReadSingle(); case 13: return this.reader.ReadDouble(); case 14: return this.reader.ReadDecimal(); case 15: return new DateTime(this.reader.ReadInt64()); case 16: return new TimeSpan(this.reader.ReadInt64()); case 32: return this.reader.ReadBytes(this.reader.ReadInt32()); case 33: { byte[] array = new byte[this.reader.ReadUInt32()]; this.reader.Read(array, 0, array.Length); return new MemoryStream(array); } } type_index -= 64; return this.ReadNonPredefinedValue(Type.GetType(this.typeNames[type_index], true)); } // Token: 0x0600205F RID: 8287 RVA: 0x00076098 File Offset: 0x00074298 private object ReadValueVer1(Type type) { if (type == typeof(string)) { return this.reader.ReadString(); } if (type == typeof(int)) { return this.reader.ReadInt32(); } if (type == typeof(byte)) { return this.reader.ReadByte(); } if (type == typeof(double)) { return this.reader.ReadDouble(); } if (type == typeof(short)) { return this.reader.ReadInt16(); } if (type == typeof(long)) { return this.reader.ReadInt64(); } if (type == typeof(sbyte)) { return this.reader.ReadSByte(); } if (type == typeof(float)) { return this.reader.ReadSingle(); } if (type == typeof(TimeSpan)) { return new TimeSpan(this.reader.ReadInt64()); } if (type == typeof(ushort)) { return this.reader.ReadUInt16(); } if (type == typeof(uint)) { return this.reader.ReadUInt32(); } if (type == typeof(ulong)) { return this.reader.ReadUInt64(); } if (type == typeof(decimal)) { return this.reader.ReadDecimal(); } if (type == typeof(DateTime)) { return new DateTime(this.reader.ReadInt64()); } return this.ReadNonPredefinedValue(type); } // Token: 0x06002060 RID: 8288 RVA: 0x00076280 File Offset: 0x00074480 private object ReadNonPredefinedValue(Type exp_type) { object obj = this.formatter.Deserialize(this.reader.BaseStream); if (obj.GetType() != exp_type) { throw new InvalidOperationException("Deserialized object is wrong type"); } return obj; } // Token: 0x06002061 RID: 8289 RVA: 0x000762BC File Offset: 0x000744BC private void LoadResourceValues(ResourceReader.ResourceCacheItem[] store) { object obj = this.readerLock; lock (obj) { for (int i = 0; i < this.resourceCount; i++) { ResourceReader.ResourceInfo resourceInfo = this.infos[i]; if (resourceInfo.TypeIndex == -1) { store[i] = new ResourceReader.ResourceCacheItem(resourceInfo.ResourceName, null); } else { this.reader.BaseStream.Seek(resourceInfo.ValuePosition, SeekOrigin.Begin); object obj2; if (this.resource_ver == 2) { obj2 = this.ReadValueVer2(resourceInfo.TypeIndex); } else { obj2 = this.ReadValueVer1(Type.GetType(this.typeNames[resourceInfo.TypeIndex], true)); } store[i] = new ResourceReader.ResourceCacheItem(resourceInfo.ResourceName, obj2); } } } } // Token: 0x06002062 RID: 8290 RVA: 0x000763C0 File Offset: 0x000745C0 internal unsafe UnmanagedMemoryStream ResourceValueAsStream(string name, int index) { ResourceReader.ResourceInfo resourceInfo = this.infos[index]; if (resourceInfo.TypeIndex != 33) { throw new InvalidOperationException(string.Format("Resource '{0}' was not a Stream. Use GetObject() instead.", name)); } object obj = this.readerLock; UnmanagedMemoryStream unmanagedMemoryStream2; lock (obj) { this.reader.BaseStream.Seek(resourceInfo.ValuePosition, SeekOrigin.Begin); long num = (long)this.reader.ReadInt32(); UnmanagedMemoryStream unmanagedMemoryStream = this.reader.BaseStream as UnmanagedMemoryStream; if (unmanagedMemoryStream != null) { unmanagedMemoryStream2 = new UnmanagedMemoryStream(unmanagedMemoryStream.PositionPointer, num); } else { IntPtr ptr = Marshal.AllocHGlobal((int)num); byte* ptr2 = (byte*)ptr.ToPointer(); UnmanagedMemoryStream unmanagedMemoryStream3 = new UnmanagedMemoryStream(ptr2, num, num, FileAccess.ReadWrite); unmanagedMemoryStream3.Closed += delegate(object o, EventArgs e) { Marshal.FreeHGlobal(ptr); }; byte[] array = new byte[(num >= 1024L) ? 1024L : num]; while (num > 0L) { int num2 = this.reader.Read(array, 0, (int)Math.Min((long)array.Length, num)); if (num2 == 0) { throw new FormatException("The resource data is corrupt. Resource stream ended"); } unmanagedMemoryStream3.Write(array, 0, num2); num -= (long)num2; } unmanagedMemoryStream3.Seek(0L, SeekOrigin.Begin); unmanagedMemoryStream2 = unmanagedMemoryStream3; } } return unmanagedMemoryStream2; } /// Releases all operating system resources associated with this . // Token: 0x06002063 RID: 8291 RVA: 0x0007654C File Offset: 0x0007474C public void Close() { this.Dispose(true); } /// Returns an enumerator for this . /// An for this . /// The reader has been closed or disposed, and cannot be accessed. // Token: 0x06002064 RID: 8292 RVA: 0x00076558 File Offset: 0x00074758 public IDictionaryEnumerator GetEnumerator() { if (this.reader == null) { throw new InvalidOperationException("ResourceReader is closed."); } return new ResourceReader.ResourceEnumerator(this); } /// Retrieves the type name and data content of a named resource from an open resource file or stream. /// The name of a resource. /// When this method returns, contains a string that is the type name of the retrieved type. This parameter is passed uninitialized. /// When this method returns, contains a byte array that is the binary representation of the retrieved type. This parameter is passed uninitialized. /// /// is null. /// /// does not exist. /// The retrieved resource data is corrupted. /// The current object is not initialized. The probable cause is that the object is closed. // Token: 0x06002065 RID: 8293 RVA: 0x00076578 File Offset: 0x00074778 public void GetResourceData(string resourceName, out string resourceType, out byte[] resourceData) { if (resourceName == null) { throw new ArgumentNullException("resourceName"); } ResourceReader.ResourceEnumerator resourceEnumerator = new ResourceReader.ResourceEnumerator(this); while (resourceEnumerator.MoveNext()) { if ((string)resourceEnumerator.Key == resourceName) { this.GetResourceDataAt(resourceEnumerator.Index, out resourceType, out resourceData); return; } } throw new ArgumentException(string.Format("Specified resource not found: {0}", resourceName)); } // Token: 0x06002066 RID: 8294 RVA: 0x000765E4 File Offset: 0x000747E4 private void GetResourceDataAt(int index, out string resourceType, out byte[] data) { ResourceReader.ResourceInfo resourceInfo = this.infos[index]; int typeIndex = resourceInfo.TypeIndex; if (typeIndex == -1) { throw new FormatException("The resource data is corrupt"); } object obj = this.readerLock; lock (obj) { this.reader.BaseStream.Seek(resourceInfo.ValuePosition, SeekOrigin.Begin); long position = this.reader.BaseStream.Position; if (this.resource_ver == 2) { if (typeIndex >= 64) { int num = typeIndex - 64; if (num >= this.typeNames.Length) { throw new FormatException("The resource data is corrupt. Invalid index to types"); } resourceType = this.typeNames[num]; } else { resourceType = "ResourceTypeCode." + (PredefinedResourceType)typeIndex; } this.ReadValueVer2(typeIndex); } else { resourceType = "ResourceTypeCode.Null"; this.ReadValueVer1(Type.GetType(this.typeNames[typeIndex], true)); } int num2 = (int)(this.reader.BaseStream.Position - position); this.reader.BaseStream.Seek((long)(-(long)num2), SeekOrigin.Current); data = new byte[num2]; this.reader.BaseStream.Read(data, 0, num2); } } // Token: 0x06002067 RID: 8295 RVA: 0x00076748 File Offset: 0x00074948 private void Dispose(bool disposing) { if (disposing && this.reader != null) { this.reader.Close(); } this.reader = null; this.hashes = null; this.infos = null; this.typeNames = null; this.cache = null; } // Token: 0x04000B6A RID: 2922 private BinaryReader reader; // Token: 0x04000B6B RID: 2923 private object readerLock = new object(); // Token: 0x04000B6C RID: 2924 private IFormatter formatter; // Token: 0x04000B6D RID: 2925 internal int resourceCount; // Token: 0x04000B6E RID: 2926 private int typeCount; // Token: 0x04000B6F RID: 2927 private string[] typeNames; // Token: 0x04000B70 RID: 2928 private int[] hashes; // Token: 0x04000B71 RID: 2929 private ResourceReader.ResourceInfo[] infos; // Token: 0x04000B72 RID: 2930 private int dataSectionOffset; // Token: 0x04000B73 RID: 2931 private long nameSectionOffset; // Token: 0x04000B74 RID: 2932 private int resource_ver; // Token: 0x04000B75 RID: 2933 private ResourceReader.ResourceCacheItem[] cache; // Token: 0x04000B76 RID: 2934 private object cache_lock = new object(); // Token: 0x0200027A RID: 634 private struct ResourceInfo { // Token: 0x06002068 RID: 8296 RVA: 0x00076794 File Offset: 0x00074994 public ResourceInfo(string resourceName, long valuePosition, int type_index) { this.ValuePosition = valuePosition; this.ResourceName = resourceName; this.TypeIndex = type_index; } // Token: 0x04000B77 RID: 2935 public readonly long ValuePosition; // Token: 0x04000B78 RID: 2936 public readonly string ResourceName; // Token: 0x04000B79 RID: 2937 public readonly int TypeIndex; } // Token: 0x0200027B RID: 635 private struct ResourceCacheItem { // Token: 0x06002069 RID: 8297 RVA: 0x000767AC File Offset: 0x000749AC public ResourceCacheItem(string name, object value) { this.ResourceName = name; this.ResourceValue = value; } // Token: 0x04000B7A RID: 2938 public readonly string ResourceName; // Token: 0x04000B7B RID: 2939 public readonly object ResourceValue; } // Token: 0x0200027C RID: 636 internal sealed class ResourceEnumerator : IEnumerator, IDictionaryEnumerator { // Token: 0x0600206A RID: 8298 RVA: 0x000767BC File Offset: 0x000749BC internal ResourceEnumerator(ResourceReader readerToEnumerate) { this.reader = readerToEnumerate; this.FillCache(); } // Token: 0x1700060B RID: 1547 // (get) Token: 0x0600206B RID: 8299 RVA: 0x000767D8 File Offset: 0x000749D8 public int Index { get { return this.index; } } // Token: 0x1700060C RID: 1548 // (get) Token: 0x0600206C RID: 8300 RVA: 0x000767E0 File Offset: 0x000749E0 public DictionaryEntry Entry { get { if (this.reader.reader == null) { throw new InvalidOperationException("ResourceReader is closed."); } if (this.index < 0) { throw new InvalidOperationException("Enumeration has not started. Call MoveNext."); } return new DictionaryEntry(this.Key, this.Value); } } // Token: 0x1700060D RID: 1549 // (get) Token: 0x0600206D RID: 8301 RVA: 0x00076830 File Offset: 0x00074A30 public object Key { get { if (this.reader.reader == null) { throw new InvalidOperationException("ResourceReader is closed."); } if (this.index < 0) { throw new InvalidOperationException("Enumeration has not started. Call MoveNext."); } return this.reader.cache[this.index].ResourceName; } } // Token: 0x1700060E RID: 1550 // (get) Token: 0x0600206E RID: 8302 RVA: 0x0007688C File Offset: 0x00074A8C public object Value { get { if (this.reader.reader == null) { throw new InvalidOperationException("ResourceReader is closed."); } if (this.index < 0) { throw new InvalidOperationException("Enumeration has not started. Call MoveNext."); } return this.reader.cache[this.index].ResourceValue; } } // Token: 0x1700060F RID: 1551 // (get) Token: 0x0600206F RID: 8303 RVA: 0x000768E8 File Offset: 0x00074AE8 public UnmanagedMemoryStream ValueAsStream { get { if (this.reader.reader == null) { throw new InvalidOperationException("ResourceReader is closed."); } if (this.index < 0) { throw new InvalidOperationException("Enumeration has not started. Call MoveNext."); } return this.reader.ResourceValueAsStream((string)this.Key, this.index); } } // Token: 0x17000610 RID: 1552 // (get) Token: 0x06002070 RID: 8304 RVA: 0x00076944 File Offset: 0x00074B44 public object Current { get { return this.Entry; } } // Token: 0x06002071 RID: 8305 RVA: 0x00076954 File Offset: 0x00074B54 public bool MoveNext() { if (this.reader.reader == null) { throw new InvalidOperationException("ResourceReader is closed."); } if (this.finished) { return false; } if (++this.index < this.reader.resourceCount) { return true; } this.finished = true; return false; } // Token: 0x06002072 RID: 8306 RVA: 0x000769B4 File Offset: 0x00074BB4 public void Reset() { if (this.reader.reader == null) { throw new InvalidOperationException("ResourceReader is closed."); } this.index = -1; this.finished = false; } // Token: 0x06002073 RID: 8307 RVA: 0x000769E0 File Offset: 0x00074BE0 private void FillCache() { if (this.reader.cache != null) { return; } object cache_lock = this.reader.cache_lock; lock (cache_lock) { if (this.reader.cache == null) { ResourceReader.ResourceCacheItem[] array = new ResourceReader.ResourceCacheItem[this.reader.resourceCount]; this.reader.LoadResourceValues(array); this.reader.cache = array; } } } // Token: 0x04000B7C RID: 2940 private ResourceReader reader; // Token: 0x04000B7D RID: 2941 private int index = -1; // Token: 0x04000B7E RID: 2942 private bool finished; } } }