private void ReadResources()
{
BCLDebug.Assert(_store != null, "ResourceReader is closed!");
BinaryFormatter bf = new BinaryFormatter(null, new StreamingContext(StreamingContextStates.File | StreamingContextStates.Persistence));
_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.");
SkipInt32(); // We don't care about numBytesToSkip.
// Read in type name for a suitable ResourceReader
// Note ResourceWriter & InternalResGen use different Strings.
String readerType = _store.ReadString();
AssemblyName mscorlib = new AssemblyName(ResourceManager.MscorlibName);
if (!ResourceManager.CompareNames(readerType, ResourceManager.ResReaderTypeName, mscorlib))
throw new NotSupportedException(Environment.GetResourceString("NotSupported_WrongResourceReader_Type", readerType));
// Skip over type name for a suitable ResourceSet
SkipString();
}
// Read RuntimeResourceSet header
// Do file version check
int version = _store.ReadInt32();
if (version != RuntimeResourceSet.Version && version != 1)
throw new ArgumentException(Environment.GetResourceString("Arg_ResourceFileUnsupportedVersion", RuntimeResourceSet.Version, version));
_version = version;
#if RESOURCE_FILE_FORMAT_DEBUG
// Look for ***DEBUG*** to see if this is a debuggable file.
long oldPos = _store.BaseStream.Position;
_debug = false;
try {
String debugString = _store.ReadString();
_debug = String.Equals("***DEBUG***", debugString);
}
catch(IOException) {
}
catch(OutOfMemoryException) {
}
if (_debug) {
Console.WriteLine("ResourceReader is looking at a debuggable .resources file, version {0}", _version);
}
else {
_store.BaseStream.Position = oldPos;
}
#endif
_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 positions into type positions array.
// But delay initialize the type table.
int numTypes = _store.ReadInt32();
_typeTable = new Type[numTypes];
_typeNamePositions = new int[numTypes];
for(int i=0; i<numTypes; i++) {
_typeNamePositions[i] = (int) _store.BaseStream.Position;
// Skip over the Strings in the file. Don't create types.
SkipString();
}
#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. All public .resources files
// should be aligned No need to verify the byte values.
long pos = _store.BaseStream.Position;
int alignBytes = ((int)pos) & 7;
if (alignBytes != 0) {
for(int i=0; i<8 - alignBytes; i++) {
_store.ReadByte();
}
}
// Read in the array of name hashes
#if RESOURCE_FILE_FORMAT_DEBUG
// Skip over "HASHES->"
if (_debug) {
_store.BaseStream.Position += 8;
}
#endif
if (_ums == null) {
_nameHashes = new int[_numResources];
for(int i=0; i<_numResources; i++)
_nameHashes[i] = _store.ReadInt32();
}
else {
unsafe {
_nameHashesPtr = (int*) _ums.PositionPointer;
// Skip over the array of nameHashes.
_ums.Seek(4 * _numResources, SeekOrigin.Current);
// get the position pointer once more to check that the whole table is within the stream
byte* junk = _ums.PositionPointer;
}
}
// Read in the array of relative positions for all the names.
#if RESOURCE_FILE_FORMAT_DEBUG
// Skip over "POS---->"
if (_debug) {
_store.BaseStream.Position += 8;
}
#endif
if (_ums == null) {
_namePositions = new int[_numResources];
for(int i=0; i<_numResources; i++)
_namePositions[i] = _store.ReadInt32();
}
else {
unsafe {
_namePositionsPtr = (int*) _ums.PositionPointer;
// Skip over the array of namePositions.
_ums.Seek(4 * _numResources, SeekOrigin.Current);
// get the position pointer once more to check that the whole table is within the stream
byte* junk = _ums.PositionPointer;
}
}
// 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(CultureInfo.InvariantCulture, "ReadResources: _nameOffset = 0x{0:x} _dataOffset = 0x{1:x}", _nameSectionOffset, _dataSectionOffset));
}
catch (EndOfStreamException eof) {
throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"), eof);
}
catch (IndexOutOfRangeException e) {
throw new BadImageFormatException(Environment.GetResourceString("BadImageFormat_ResourcesHeaderCorrupted"), e);
}
}