Beispiel #1
0
        public ResourceReader(Stream stream)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (!stream.CanRead)
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable"));
            }

            _table = new Hashtable(FastResourceComparer.Default, FastResourceComparer.Default);
            _store = new BinaryReader(stream, Encoding.UTF8);
            // We have a faster code path for reading resource files from an assembly.
            _ums = stream as __UnmanagedMemoryStream;
            BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(Stream).  UnmanagedMemoryStream: " + (_ums != null));
            ReadResources();
        }
Beispiel #2
0
        // This is the constructor the RuntimeResourceSet calls,
        // passing in the stream to read from and the RuntimeResourceSet's
        // internal hash table (hash table of names with file offsets
        // and values, coupled to this ResourceReader).
        internal ResourceReader(Stream stream, Hashtable table)
        {
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }
            if (table == null)
            {
                throw new ArgumentNullException("table");
            }
            if (!stream.CanRead)
            {
                throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotReadable"));
            }

            _table = table;
            _store = new BinaryReader(stream, Encoding.UTF8);
            _ums   = stream as __UnmanagedMemoryStream;

            BCLDebug.Log("RESMGRFILEFORMAT", "ResourceReader .ctor(Stream, Hashtable).  UnmanagedMemoryStream: " + (_ums != null));
            ReadResources();
        }
Beispiel #3
0
 private void Dispose(bool disposing)
 {
     if (_store != null)
     {
         if (disposing)
         {
             // Close the stream in a thread-safe way.  This fix means
             // that we may call Close n times, but that's safe.
             BinaryReader copyOfStore = _store;
             if (copyOfStore != null)
             {
                 copyOfStore.Close();
             }
         }
         _store            = null;
         _table            = null;
         _namePositions    = null;
         _nameHashes       = null;
         _ums              = null;
         _namePositionsPtr = null;
         _nameHashesPtr    = null;
     }
 }
Beispiel #4
0
        // Reads in the header information for a .resources file.  Verifies some
        // of the assumptions about this resource set, and builds the class table
        // for the default resource file format.
        private void ReadResources()
        {
            BCLDebug.Assert(_store != null, "ResourceReader is closed!");
            BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence));

            // Do partial binds so we can be tolerant of version number changes.
            bf.AssemblyFormat = FormatterAssemblyStyle.Simple;
            _objFormatter     = bf;

            try {
                // Read ResourceManager header
                // Check for magic number
                int magicNum = _store.ReadInt32();
                if (magicNum != ResourceManager.MagicNumber)
                {
                    throw new ArgumentException(Environment.GetResourceString("Resources_StreamNotValid"));
                }
                // Assuming this is ResourceManager header V1 or greater, hopefully
                // after the version number there is a number of bytes to skip
                // to bypass the rest of the ResMgr header.
                int resMgrHeaderVersion = _store.ReadInt32();
                if (resMgrHeaderVersion > 1)
                {
                    int numBytesToSkip = _store.ReadInt32();
                    BCLDebug.Log("RESMGRFILEFORMAT", LogLevel.Status, "ReadResources: Unexpected ResMgr header version: {0}  Skipping ahead {1} bytes.", resMgrHeaderVersion, numBytesToSkip);
                    BCLDebug.Assert(numBytesToSkip >= 0, "numBytesToSkip in ResMgr header should be positive!");
                    _store.BaseStream.Seek(numBytesToSkip, SeekOrigin.Current);
                }
                else
                {
                    BCLDebug.Log("RESMGRFILEFORMAT", "ReadResources: Parsing ResMgr header v1.");
                    _store.ReadInt32();  // We don't care about numBytesToSkip.

                    // Read in type name for a suitable ResourceReader
                    // Note ResourceWriter & InternalResGen use different Strings.
                    String readerType = _store.ReadString();
                    if (!readerType.Equals(ResourceManager.ResReaderTypeName) &&
                        !readerType.Equals(typeof(ResourceReader).FullName) &&
                        !readerType.Equals(ResourceManager.ResReaderTypeNameInternal))
                    {
                        throw new NotSupportedException("This .resources file shouldn't be used with this reader.  Your resource reader type: " + readerType);
                    }

                    // Skip over type name for a suitable ResourceSet
                    _store.ReadString();
                }

                // Read RuntimeResourceSet header
                // Do file version check
                int version = _store.ReadInt32();
                if (version != RuntimeResourceSet.Version)
                {
                    throw new ArgumentException(String.Format("Version conflict with ResourceManager .resources files!  Expected version: {0} but got: {1}", RuntimeResourceSet.Version, version));
                }

                _numResources = _store.ReadInt32();
                BCLDebug.Log("RESMGRFILEFORMAT", "ReadResources: Expecting " + _numResources + " resources.");
#if _DEBUG
                if (ResourceManager.DEBUG >= 4)
                {
                    Console.WriteLine("ResourceReader::ReadResources - Reading in " + _numResources + " resources");
                }
#endif

                // Read type names into type array.
                int numTypes = _store.ReadInt32();
                _typeTable = new Type[numTypes];
                for (int i = 0; i < numTypes; i++)
                {
                    String typeName = _store.ReadString();
                    // Do partial binds to be tolerant of version number changes.
                    _typeTable[i] = Assembly.LoadTypeWithPartialName(typeName, false);
                    if (_typeTable[i] == null)
                    {
                        throw new TypeLoadException(Environment.GetResourceString("TypeLoad_PartialBindFailed", typeName));
                    }
                }

                // Initialize deserialization permission array
                InitSafeToDeserializeArray();

#if _DEBUG
                if (ResourceManager.DEBUG >= 5)
                {
                    Console.WriteLine("ResourceReader::ReadResources - Reading in " + numTypes + " type table entries");
                }
#endif

                // Prepare to read in the array of name hashes
                //  Note that the name hashes array is aligned to 8 bytes so
                //  we can use pointers into it on 64 bit machines. (4 bytes
                //  may be sufficient, but let's plan for the future)
                //  Skip over alignment stuff, if it's present.
                long pos           = _store.BaseStream.Position;
                int  alignBytes    = ((int)pos) & 7;
                bool fileIsAligned = true;
                if (alignBytes != 0)
                {
                    // For backwards compatibility, don't require the "PAD" stuff
                    // in here, but we should definitely skip it if present.
                    for (int i = 0; i < 8 - alignBytes; i++)
                    {
                        byte b = _store.ReadByte();
                        if (b != "PAD"[i % 3])
                        {
                            fileIsAligned = false;
                            break;
                        }
                    }
                    // If we weren't aligned, we shouldn't have skipped this data!
                    if (!fileIsAligned)
                    {
                        _store.BaseStream.Position = pos;
                    }
                    else
                    {
                        BCLDebug.Assert((_store.BaseStream.Position & 7) == 0, "ResourceReader: Stream should be aligned on an 8 byte boundary now!");
                    }
                }
#if RESOURCE_FILE_FORMAT_DEBUG
                Console.WriteLine("ResourceReader: File alignment: " + fileIsAligned);
#endif
#if !WIN32
                // If the file wasn't aligned, we can't use the _ums code on IA64.
                // However, this should only be a problem for .resources files
                // that weren't rebuilt after ~August 11, 2001 when I introduced
                // the alignment code.  We can rip this check in the next
                // version.        -- Brian Grunkemeyer, 8/8/2001
                if (!fileIsAligned)
                {
                    _ums = null;
                }
#endif

                // Read in the array of name hashes
#if RESOURCE_FILE_FORMAT_DEBUG
                //  Skip over "HASHES->"
                _store.BaseStream.Position += 8;
#endif

                if (_ums == null)
                {
                    _nameHashes = new int[_numResources];
                    for (int i = 0; i < _numResources; i++)
                    {
                        _nameHashes[i] = _store.ReadInt32();
                    }
                }
                else
                {
                    _nameHashesPtr = (int *)_ums.GetBytePtr();
                    // Skip over the array of nameHashes.
                    _ums.Seek(4 * _numResources, SeekOrigin.Current);
                }

                // Read in the array of relative positions for all the names.
#if RESOURCE_FILE_FORMAT_DEBUG
                // Skip over "POS---->"
                _store.BaseStream.Position += 8;
#endif
                if (_ums == null)
                {
                    _namePositions = new int[_numResources];
                    for (int i = 0; i < _numResources; i++)
                    {
                        _namePositions[i] = _store.ReadInt32();
                    }
                }
                else
                {
                    _namePositionsPtr = (int *)_ums.GetBytePtr();
                    // Skip over the array of namePositions.
                    _ums.Seek(4 * _numResources, SeekOrigin.Current);
                }

                // Read location of data section.
                _dataSectionOffset = _store.ReadInt32();

                // Store current location as start of name section
                _nameSectionOffset = _store.BaseStream.Position;
                BCLDebug.Log("RESMGRFILEFORMAT", String.Format("ReadResources: _nameOffset = 0x{0:x}  _dataOffset = 0x{1:x}", _nameSectionOffset, _dataSectionOffset));
            }
            catch (EndOfStreamException eof) {
                throw new ArgumentException("Stream is not a valid .resources file!  It was possibly truncated.", eof);
            }
        }