Merge branch 'master' of github.com:alcexhim/UniversalEditor

This commit is contained in:
Michael Becker 2014-10-27 08:13:49 -04:00
commit 45f2c344b5
11 changed files with 453 additions and 178 deletions

View File

@ -19,28 +19,9 @@ namespace UniversalEditor.Accessors
set { mvarFileStream.SetLength(value); }
}
public override void Seek(long length, SeekOrigin position)
public override void Seek(long length, SeekOrigin origin)
{
System.IO.SeekOrigin origin = System.IO.SeekOrigin.Begin;
switch (position)
{
case SeekOrigin.Begin:
{
origin = System.IO.SeekOrigin.Begin;
break;
}
case SeekOrigin.Current:
{
origin = System.IO.SeekOrigin.Current;
break;
}
case SeekOrigin.End:
{
origin = System.IO.SeekOrigin.End;
break;
}
}
mvarFileStream.Seek(length, origin);
mvarFileStream.Seek(length, (System.IO.SeekOrigin)origin);
}
internal override int ReadInternal(byte[] buffer, int offset, int count)

View File

@ -7,8 +7,8 @@ namespace UniversalEditor.IO
{
public enum SeekOrigin
{
Begin,
Current,
End
Begin = 0,
Current = 1,
End = 2
}
}

View File

@ -0,0 +1,43 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.IO;
using UniversalEditor.ObjectModels.AbstractSyntax;
namespace UniversalEditor.DataFormats.AbstractSyntax.DER
{
public class DERDataFormat : DataFormat
{
private static DataFormatReference _dfr = null;
public override DataFormatReference MakeReference()
{
if (_dfr == null)
{
_dfr = base.MakeReference();
_dfr.Capabilities.Add(typeof(AbstractSyntaxObjectModel), DataFormatCapabilities.All);
}
return _dfr;
}
protected override void LoadInternal(ref ObjectModel objectModel)
{
AbstractSyntaxObjectModel asn = (objectModel as AbstractSyntaxObjectModel);
if (asn == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
while (!reader.EndOfStream)
{
byte identifier = reader.ReadByte();
byte tagClass = (byte)identifier.GetBits(7, 2);
byte primitiveOrConstructed = (byte)identifier.GetBits(6, 1);
byte tagNumber = (byte)identifier.GetBits(0, 5);
}
}
protected override void SaveInternal(ObjectModel objectModel)
{
throw new NotImplementedException();
}
}
}

View File

@ -45,8 +45,8 @@ namespace UniversalEditor.DataFormats.Markup.EBML
private MarkupElement ReadEBMLElement(Reader reader)
{
long elementID = ReadEBMLElementID(reader);
long dataSize = ReadEBMLElementID(reader);
long elementID = ReadEBMLCompressedInteger(reader);
long dataSize = ReadEBMLCompressedInteger(reader);
byte[] data = reader.ReadBytes(dataSize);
MarkupTagElement tag = new MarkupTagElement();
@ -85,7 +85,7 @@ namespace UniversalEditor.DataFormats.Markup.EBML
return tag;
}
private long ReadEBMLElementID(Reader reader)
private long ReadEBMLCompressedInteger(Reader reader)
{
byte[] buffer = reader.ReadBytes(8);
reader.Seek(-8, SeekOrigin.Current);
@ -209,6 +209,111 @@ namespace UniversalEditor.DataFormats.Markup.EBML
// which will be sufficient for the time being.
throw new NotImplementedException("Unknown Element Size coding: 0x" + buffer[0].ToString("X"));
}
private void WriteEBMLCompressedInteger(Writer writer, long value)
{
if (value <= 0x7F)
{
writer.WriteByte((byte)(value & 0x80));
return;
}
else if (value <= 0x7FFF)
{
// two bytes
byte[] _buffer = new byte[2];
byte[] buffer = BitConverter.GetBytes(value);
_buffer[0] = (byte)(buffer[1] | 0x40);
_buffer[1] = buffer[0];
writer.WriteBytes(_buffer);
return;
}
else if (value <= 0x7FFFFF)
{
// three bytes
byte[] _buffer = new byte[3];
byte[] buffer = BitConverter.GetBytes(value);
_buffer[0] = (byte)(buffer[2] | 0x20);
_buffer[1] = buffer[1];
_buffer[2] = buffer[0];
writer.WriteBytes(_buffer);
return;
}
else if (value <= 0x7FFFFFFF)
{
// four bytes
byte[] _buffer = new byte[4];
byte[] buffer = BitConverter.GetBytes(value);
_buffer[0] = (byte)(buffer[3] | 0x10);
_buffer[1] = buffer[2];
_buffer[2] = buffer[1];
_buffer[3] = buffer[0];
writer.WriteBytes(_buffer);
return;
}
else if (value <= 0x7FFFFFFFFF)
{
// five bytes
byte[] _buffer = new byte[5];
byte[] buffer = BitConverter.GetBytes(value);
_buffer[0] = (byte)(buffer[4] | 0x08);
_buffer[1] = buffer[3];
_buffer[2] = buffer[2];
_buffer[3] = buffer[1];
_buffer[4] = buffer[0];
writer.WriteBytes(_buffer);
return;
}
else if (value <= 0x7FFFFFFFFFFF)
{
// six bytes
byte[] _buffer = new byte[6];
byte[] buffer = BitConverter.GetBytes(value);
_buffer[0] = (byte)(buffer[5] | 0x04);
_buffer[1] = buffer[4];
_buffer[2] = buffer[3];
_buffer[3] = buffer[2];
_buffer[4] = buffer[1];
_buffer[5] = buffer[0];
writer.WriteBytes(_buffer);
return;
}
else if (value <= 0x7FFFFFFFFFFFFF)
{
// seven bytes
byte[] _buffer = new byte[7];
byte[] buffer = BitConverter.GetBytes(value);
_buffer[0] = (byte)(buffer[6] | 0x02);
_buffer[1] = buffer[5];
_buffer[2] = buffer[4];
_buffer[3] = buffer[3];
_buffer[4] = buffer[2];
_buffer[5] = buffer[1];
_buffer[6] = buffer[0];
writer.WriteBytes(_buffer);
return;
}
else if (value <= 0x7FFFFFFFFFFFFFFF)
{
// eight bytes
byte[] _buffer = new byte[8];
byte[] buffer = BitConverter.GetBytes(value);
_buffer[0] = (byte)(buffer[7] | 0x01);
_buffer[1] = buffer[6];
_buffer[2] = buffer[5];
_buffer[3] = buffer[4];
_buffer[4] = buffer[3];
_buffer[5] = buffer[2];
_buffer[6] = buffer[1];
_buffer[7] = buffer[0];
writer.WriteBytes(_buffer);
return;
}
// Since modern computers do not easily deal with data coded in sizes greater than 64 bits,
// any larger Element Sizes are left undefined at the moment. Currently, the Element Size
// coding allows for an Element to grow to 72000 To, i.e. 7x10^16 octets or 72000 terabytes,
// which will be sufficient for the time being.
throw new NotImplementedException("Value cannot be represented as an EBML compressed integer: " + value.ToString());
}
protected override void SaveInternal(ObjectModel objectModel)
{

View File

@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UniversalEditor.ObjectModels.AbstractSyntax;
using UniversalEditor.DataFormats.AbstractSyntax.DER;
using UniversalEditor.IO;
using UniversalEditor.ObjectModels.SecurityCertificate;
namespace UniversalEditor.DataFormats.SecurityCertificate.DER
{
public class DERCertificateDataFormat : DERDataFormat
{
private static DataFormatReference _dfr = null;
public override DataFormatReference MakeReference()
{
if (_dfr == null)
{
_dfr = new DataFormatReference(GetType());
_dfr.Capabilities.Add(typeof(SecurityCertificateObjectModel), DataFormatCapabilities.All);
_dfr.Filters.Add("Security certificate (Binary-encoded DER)", new byte?[][] { new byte?[] { (byte)0x30, (byte)0x82 } }, new string[] { "*.cer", "*.der", "*.p7b" });
_dfr.Filters.Add("Security certificate (Base64-encoded DER)", new byte?[][] { new byte?[] { (byte)'-', (byte)'-', (byte)'-', (byte)'-', (byte)'-', (byte)'B', (byte)'E', (byte)'G', (byte)'I', (byte)'N', (byte)' ', (byte)'C', (byte)'E', (byte)'R', (byte)'T', (byte)'I', (byte)'F', (byte)'I', (byte)'C', (byte)'A', (byte)'T', (byte)'E', (byte)'-', (byte)'-', (byte)'-', (byte)'-', (byte)'-', (byte)'\r', (byte)'\n' } }, new string[] { "*.cer", "*.der", "*.p7b" });
}
return _dfr;
}
protected override void BeforeLoadInternal(Stack<ObjectModel> objectModels)
{
base.BeforeLoadInternal(objectModels);
objectModels.Push(new AbstractSyntaxObjectModel());
}
protected override void AfterLoadInternal(Stack<ObjectModel> objectModels)
{
base.AfterLoadInternal(objectModels);
AbstractSyntaxObjectModel asn = (objectModels.Pop() as AbstractSyntaxObjectModel);
SecurityCertificateObjectModel cer = (objectModels.Pop() as SecurityCertificateObjectModel);
}
protected override void BeforeSaveInternal(Stack<ObjectModel> objectModels)
{
base.BeforeSaveInternal(objectModels);
SecurityCertificateObjectModel cer = (objectModels.Pop() as SecurityCertificateObjectModel);
AbstractSyntaxObjectModel asn = new AbstractSyntaxObjectModel();
objectModels.Push(asn);
}
}
}

View File

@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.ObjectModels.AbstractSyntax
{
public class AbstractSyntaxObjectModel : ObjectModel
{
public override void Clear()
{
throw new NotImplementedException();
}
public override void CopyTo(ObjectModel where)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace UniversalEditor.ObjectModels.SecurityCertificate
{
public class SecurityCertificateObjectModel : ObjectModel
{
private static ObjectModelReference _omr = null;
public override ObjectModelReference MakeReference()
{
if (_omr == null)
{
_omr = base.MakeReference();
_omr.Title = "Security certificate";
_omr.Path = new string[] { "Security", "Certificate" };
}
return _omr;
}
public override void Clear()
{
}
public override void CopyTo(ObjectModel where)
{
}
}
}

View File

@ -44,6 +44,7 @@
<Compile Include="Common\Reflection.cs" />
<Compile Include="Condition.cs" />
<Compile Include="Converter.cs" />
<Compile Include="DataFormats\AbstractSyntax\DER\DERDataFormat.cs" />
<Compile Include="DataFormats\Chunked\REV\REVDataFormat.cs" />
<Compile Include="DataFormats\Chunked\RIFF\RIFFDataFormat.cs" />
<Compile Include="DataFormats\FileSystem\UXT\Internal\FileInfo.cs" />
@ -60,10 +61,12 @@
<Compile Include="DataFormats\PropertyList\UniversalPropertyList\VariantType.cs" />
<Compile Include="DataFormats\PropertyList\WindowsConfigurationDataFormat.cs" />
<Compile Include="DataFormats\PropertyList\XML\XMLPropertyListDataFormat.cs" />
<Compile Include="DataFormats\SecurityCertificate\DER\DERCertificateDataFormat.cs" />
<Compile Include="DataFormats\Shortcut\FreeDesktop\DesktopShortcutAction.cs" />
<Compile Include="DataFormats\Shortcut\FreeDesktop\DesktopShortcutDataFormat.cs" />
<Compile Include="DataFormats\Shortcut\FreeDesktop\DesktopShortcutStartupNotifyBehavior.cs" />
<Compile Include="DataFormats\Shortcut\FreeDesktop\DesktopShortcutType.cs" />
<Compile Include="ObjectModels\AbstractSyntax\AbstractSyntaxObjectModel.cs" />
<Compile Include="ObjectModels\Chunked\ChunkedObjectModel.cs" />
<Compile Include="ObjectModels\Chunked\RIFFChunk.cs" />
<Compile Include="ObjectModels\Chunked\RIFFDataChunk.cs" />
@ -95,6 +98,7 @@
<Compile Include="ObjectModels\Project\ProjectFileSystem.cs" />
<Compile Include="ObjectModels\Project\ProjectFolder.cs" />
<Compile Include="ObjectModels\Project\Reference.cs" />
<Compile Include="ObjectModels\SecurityCertificate\SecurityCertificateObjectModel.cs" />
<Compile Include="ObjectModels\Shortcut\ShortcutObjectModel.cs" />
<Compile Include="ObjectModels\Solution\SolutionObjectModel.cs" />
<Compile Include="ObjectModels\Text\Formatted\FormattedTextObjectModel.cs" />

View File

@ -26,12 +26,12 @@ namespace UniversalEditor.DataFormats.Multimedia.Picture.TBODY
protected override void LoadInternal(ref ObjectModel objectModel)
{
// A TBODY file is just a DDS file without a header
// A TBODY file is just a DDS file without a header
IO.Reader br = base.Accessor.Reader;
byte[] data = br.ReadToEnd();
// We have to add the DDS header
MemoryAccessor ma = new MemoryAccessor();
// We have to add the DDS header
MemoryAccessor ma = new MemoryAccessor();
IO.Writer bw = new IO.Writer(ma);
bw.WriteUInt32(DirectDrawSurfaceDataFormat.DDS_MAGIC);
bw.WriteUInt32((uint)124); // data size
@ -71,10 +71,10 @@ namespace UniversalEditor.DataFormats.Multimedia.Picture.TBODY
ma = new MemoryAccessor(data1);
DirectDrawSurfaceDataFormat dds = new DirectDrawSurfaceDataFormat();
Document doc = new Document(objectModel, new DirectDrawSurfaceDataFormat(), ma);
doc.InputAccessor.Open();
doc.Load();
doc.InputAccessor.Close();
Document doc = new Document(objectModel, new DirectDrawSurfaceDataFormat(), ma);
doc.InputAccessor.Open();
doc.Load();
doc.InputAccessor.Close();
}
protected override void SaveInternal(ObjectModel objectModel)

View File

@ -21,9 +21,9 @@ namespace UniversalEditor.DataFormats.Multimedia3D.Model.Avalanche
}
return _dfr;
}
protected override void LoadInternal(ref ObjectModel objectModel)
{
protected override void LoadInternal(ref ObjectModel objectModel)
{
ModelObjectModel model = (objectModel as ModelObjectModel);
if (model == null) throw new ObjectModelNotSupportedException();
@ -39,41 +39,41 @@ namespace UniversalEditor.DataFormats.Multimedia3D.Model.Avalanche
//br.BaseStream.Seek(0, System.IO.SeekOrigin.Begin);
ModelSurface surf = new ModelSurface();
int count = (int)(brIBUF.Accessor.Length / 2);
int count = (int)(brIBUF.Accessor.Length / 2);
for (int i = 0; i < count; i++)
{
float vx = br.ReadSingle();
float vz = br.ReadSingle();
float vy = br.ReadSingle();
vx *= 100;
vy *= 100;
vz *= 100;
vz *= -1;
vx *= 100;
vy *= 100;
vz *= 100;
vz *= -1;
float tu = br.ReadHalf();
float tv = br.ReadHalf();
tv = 1 - tv;
float tv = br.ReadHalf();
tv = 1 - tv;
uint unknown1 = br.ReadUInt32();
uint vertexColor = br.ReadUInt32();
uint unknown1 = br.ReadUInt32();
uint vertexColor = br.ReadUInt32();
ModelVertex vtx = new ModelVertex(vx, vy, vz, tu, tv); // vx, vz, vy in original script??
surf.Vertices.Add(vtx);
}
/*
/*
for (int x = 0; x < surf.Vertices.Count; x++)
{
float nx = br.ReadSingle();
float ny = br.ReadSingle();
float nz = br.ReadSingle();
nz *= -1;
nz *= -1;
float un = br.ReadSingle();
surf.Vertices[x].Normal = new PositionVector3(nx, ny, nz);
surf.Vertices[x].OriginalNormal = new PositionVector3(nx, ny, nz);
surf.Vertices[x].Normal = new PositionVector3(nx, ny, nz);
surf.Vertices[x].OriginalNormal = new PositionVector3(nx, ny, nz);
// not sure why this needs to be here...
br.BaseStream.Seek(10, System.IO.SeekOrigin.Current);
// not sure why this needs to be here...
br.BaseStream.Seek(10, System.IO.SeekOrigin.Current);
}
while (!brIBUF.EndOfStream)
{
@ -82,21 +82,21 @@ namespace UniversalEditor.DataFormats.Multimedia3D.Model.Avalanche
ushort fc = (ushort)(brIBUF.ReadUInt16() + 1);
surf.Triangles.Add(surf.Vertices[fa], surf.Vertices[fb], surf.Vertices[fc]);
}
*/
*/
for (int i = 0; i < surf.Vertices.Count - 3; i += 3)
{
surf.Triangles.Add(surf.Vertices[i], surf.Vertices[i + 1], surf.Vertices[i + 2]);
}
for (int i = 0; i < surf.Vertices.Count - 3; i += 3)
{
surf.Triangles.Add(surf.Vertices[i], surf.Vertices[i + 1], surf.Vertices[i + 2]);
}
ModelMaterial matDefault = new ModelMaterial();
matDefault.Name = "default";
matDefault.EmissiveColor = Color.FromRGBA(255, 255, 255, 255);
foreach (ModelTriangle tri in surf.Triangles)
{
matDefault.Triangles.Add(tri);
}
model.Materials.Add(matDefault);
ModelMaterial matDefault = new ModelMaterial();
matDefault.Name = "default";
matDefault.EmissiveColor = Color.FromRGBA(255, 255, 255, 255);
foreach (ModelTriangle tri in surf.Triangles)
{
matDefault.Triangles.Add(tri);
}
model.Materials.Add(matDefault);
model.Surfaces.Add(surf);
/*
@ -116,7 +116,7 @@ namespace UniversalEditor.DataFormats.Multimedia3D.Model.Avalanche
)))) else (Print "Aborted.")
}
*/
brIBUF.Close();
brIBUF.Close();
}
protected override void SaveInternal(ObjectModel objectModel)

View File

@ -78,8 +78,31 @@ namespace UniversalEditor.DataFormats.FileSystem.Microsoft.CompoundDocument
/// </summary>
private int mvarMasterSectorAllocationTableSize = 0;
private void ReadHeader(Reader reader)
private int mvarShortSectorFirstSectorID = 0;
private int GetSectorPositionFromSectorID(int sectorID)
{
if (sectorID < 0) return 0;
return (int)(512 + (sectorID * mvarSectorSize));
}
private int GetShortSectorPositionFromSectorID(int sectorID)
{
if (sectorID < 0) return 0;
return (int)(sectorID * mvarShortSectorSize);
}
private byte[] mvarShortSectorContainerStreamData = null;
protected override void LoadInternal(ref ObjectModel objectModel)
{
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
if (fsom == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
// The header is always located at the beginning of the file, and its size is
// exactly 512 bytes. This implies that the first sector (0) always starts at
// file offset 512.
byte[] validSignature = new byte[] { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 };
byte[] signature = reader.ReadBytes(8);
if (!signature.Match(validSignature))
@ -87,7 +110,7 @@ namespace UniversalEditor.DataFormats.FileSystem.Microsoft.CompoundDocument
throw new InvalidDataFormatException("File does not begin with { 0xD0, 0xCF, 0x11, 0xE0, 0xA1, 0xB1, 0x1A, 0xE1 }");
}
mvarUniqueIdentifier = reader.ReadGuid();
ushort MinorVersion = reader.ReadUInt16();
ushort MajorVersion = reader.ReadUInt16();
mvarFormatVersion = new Version(MajorVersion, MinorVersion);
@ -129,7 +152,7 @@ namespace UniversalEditor.DataFormats.FileSystem.Microsoft.CompoundDocument
#region Read Master Sector Allocation Table
// First part of the master sector allocation table, containing 109 SecIDs
int[] masterSectorAllocationTable = reader.ReadInt32Array(109);
// TODO: test this! when MSAT contains more than 109 SecIDs
int countForMSAT = (int)((double)mvarSectorSize / 4);
int nextSectorForMSAT = mvarMasterSectorAllocationTableFirstSectorID;
@ -139,7 +162,7 @@ namespace UniversalEditor.DataFormats.FileSystem.Microsoft.CompoundDocument
Array.Resize(ref masterSectorAllocationTable, masterSectorAllocationTable.Length + countForMSAT);
int[] masterSectorAllocationTablePart = reader.ReadInt32Array(countForMSAT);
Array.Copy(masterSectorAllocationTablePart, 0, masterSectorAllocationTable, nextPositionForMSAT, masterSectorAllocationTablePart.Length);
nextSectorForMSAT = masterSectorAllocationTablePart[masterSectorAllocationTablePart.Length - 1];
}
#endregion
@ -165,150 +188,171 @@ namespace UniversalEditor.DataFormats.FileSystem.Microsoft.CompoundDocument
Array.Copy(sectorData, 0, data, (i * mvarSectorSize), mvarSectorSize);
}
#endregion
#region Read Short Sector Allocation Table
List<int> shortSectorAllocationTable = new List<int>();
List<int> shortSectorAllocationTableSectors = new List<int>();
if (mvarShortSectorAllocationTableFirstSectorID >= 0)
{
int sector = mvarShortSectorAllocationTableFirstSectorID;
while (sector >= 0)
{
shortSectorAllocationTableSectors.Add(sector);
sector = sectorAllocationTable[sector];
}
}
byte[] shortSectorAllocationTableData = new byte[mvarSectorSize * shortSectorAllocationTableSectors.Count];
for (int i = 0; i < shortSectorAllocationTableSectors.Count; i++)
{
pos = GetSectorPositionFromSectorID(shortSectorAllocationTableSectors[i]);
reader.Accessor.Seek(pos, SeekOrigin.Begin);
byte[] sectorData = reader.ReadBytes(mvarSectorSize);
Array.Copy(sectorData, 0, shortSectorAllocationTableData, (i * mvarSectorSize), mvarSectorSize);
}
Accessors.MemoryAccessor ma1 = new Accessors.MemoryAccessor(shortSectorAllocationTableData);
Reader shortSectorAllocationTableReader = new Reader(ma1);
while (!shortSectorAllocationTableReader.EndOfStream)
{
int sectorID = shortSectorAllocationTableReader.ReadInt32();
shortSectorAllocationTable.Add(sectorID);
}
#endregion
#region Read Sector Directory Entries
Accessors.MemoryAccessor ma = new Accessors.MemoryAccessor(data);
reader = new Reader(ma);
List<File> files = new List<File>();
Reader sectorReader = new Reader(ma);
while (!reader.EndOfStream)
{
// The first directory entry always represents the root storage entry
string storageName = reader.ReadFixedLengthString(64, IO.Encoding.UTF16LittleEndian).TrimNull();
ushort storageNameLength = reader.ReadUInt16();
string storageName = sectorReader.ReadFixedLengthString(64, IO.Encoding.UTF16LittleEndian).TrimNull();
if (String.IsNullOrEmpty(storageName)) break;
ushort storageNameLength = sectorReader.ReadUInt16();
storageNameLength /= 2;
if (storageNameLength > 0) storageNameLength -= 1;
if (storageName.Length != storageNameLength) throw new InvalidDataFormatException("Sanity check: storage name length is not actual length of storage name");
byte storageType = reader.ReadByte();
byte storageNodeColor = reader.ReadByte();
byte storageType = sectorReader.ReadByte();
byte storageNodeColor = sectorReader.ReadByte();
int leftChildNodeDirectoryID = reader.ReadInt32();
int rightChildNodeDirectoryID = reader.ReadInt32();
int leftChildNodeDirectoryID = sectorReader.ReadInt32();
int rightChildNodeDirectoryID = sectorReader.ReadInt32();
// directory ID of the root node entry of the red-black tree of all members of the root storage
int rootNodeEntryDirectoryID = reader.ReadInt32();
int rootNodeEntryDirectoryID = sectorReader.ReadInt32();
Guid uniqueIdentifier = reader.ReadGuid();
uint flags = reader.ReadUInt32();
long creationTimestamp = reader.ReadInt64();
long lastModificationTimestamp = reader.ReadInt64();
Guid uniqueIdentifier = sectorReader.ReadGuid();
uint flags = sectorReader.ReadUInt32();
long creationTimestamp = sectorReader.ReadInt64();
long lastModificationTimestamp = sectorReader.ReadInt64();
int firstSectorOfStream = reader.ReadInt32();
int streamOffset = GetSectorPositionFromSectorID(firstSectorOfStream);
int streamLength = reader.ReadInt32();
int unused3 = reader.ReadInt32();
if (streamLength < mvarMinimumStandardStreamSize)
int firstSectorOfStream = sectorReader.ReadInt32();
if (storageType == 0x05)
{
// stored as a short-sector container stream
streamOffset = (int)(512 + (firstSectorOfStream * mvarShortSectorSize));
// this is the root storage entry
mvarShortSectorFirstSectorID = firstSectorOfStream;
#region Read Short Stream Container Stream
List<int> shortStreamContainerStreamSectors = new List<int>();
{
int shortSectorDataSector = mvarShortSectorFirstSectorID;
while (shortSectorDataSector >= 0)
{
shortStreamContainerStreamSectors.Add(shortSectorDataSector);
shortSectorDataSector = sectorAllocationTable[shortSectorDataSector];
}
}
byte[] shortStreamContainerStreamData = new byte[shortStreamContainerStreamSectors.Count * mvarSectorSize];
int i = 0;
foreach (int sector in shortStreamContainerStreamSectors)
{
int wpos = GetSectorPositionFromSectorID(sector);
reader.Seek(wpos, SeekOrigin.Begin);
byte[] sectorData = reader.ReadBytes(mvarSectorSize);
Array.Copy(sectorData, 0, shortStreamContainerStreamData, i, sectorData.Length);
i += sectorData.Length;
}
mvarShortSectorContainerStreamData = shortStreamContainerStreamData;
#endregion
}
File file = new File();
file.Name = storageName;
file.Properties.Add("reader", reader);
file.Properties.Add("offset", streamOffset);
file.Properties.Add("length", streamLength);
file.DataRequest += file_DataRequest;
files.Add(file);
}
#endregion
}
int streamLength = sectorReader.ReadInt32();
int unused3 = sectorReader.ReadInt32();
private int GetSectorPositionFromSectorID(int sectorID)
{
if (sectorID < 0) return 0;
return (int)(512 + (sectorID * mvarSectorSize));
}
protected override void LoadInternal(ref ObjectModel objectModel)
{
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
if (fsom == null) throw new ObjectModelNotSupportedException();
Reader reader = base.Accessor.Reader;
// The header is always located at the beginning of the file, and its size is
// exactly 512 bytes. This implies that the first sector (0) always starts at
// file offset 512.
ReadHeader(reader);
// TODO: read extra sectors if necessary
int directoryEntryLength = 128;
int directoryEntryCount = (int)((mvarSectorAllocationTableSize * mvarSectorSize) / directoryEntryLength);
for (int i = 0; i < directoryEntryCount; i++)
{
// The first directory entry always represents the root storage entry
string storageName = reader.ReadFixedLengthString(64, IO.Encoding.UTF16LittleEndian).TrimNull();
ushort storageNameLength = reader.ReadUInt16();
storageNameLength /= 2;
storageNameLength -= 1;
if (storageName.Length != storageNameLength) throw new InvalidDataFormatException("Sanity check: storage name length is not actual length of storage name");
byte storageType = reader.ReadByte();
byte storageNodeColor = reader.ReadByte();
int leftChildNodeDirectoryID = reader.ReadInt32();
int rightChildNodeDirectoryID = reader.ReadInt32();
// directory ID of the root node entry of the red-black tree of all members of the root storage
int rootNodeEntryDirectoryID = reader.ReadInt32();
Guid uniqueIdentifier = reader.ReadGuid();
uint flags = reader.ReadUInt32();
long creationTimestamp = reader.ReadInt64();
long lastModificationTimestamp = reader.ReadInt64();
int firstSectorOfStream = reader.ReadInt32();
int streamOffset = GetSectorPositionFromSectorID(firstSectorOfStream);
int streamLength = reader.ReadInt32();
int unused3 = reader.ReadInt32();
/*
The directory entry of a stream contains the SecID of the first sector or
short-sector containing the stream data. All streams that are shorter than a
specific size given in the header are stored as a short-stream, thus inserted
into the short-stream container stream. In this case the SecID specifies the
first short-sector inside the short-stream container stream, and the
short-sector allocation table is used to build up the SecID chain of the
stream.
*/
if (i == 0)
List<int> sectors = new List<int>();
if (streamLength < mvarMinimumStandardStreamSize)
{
// in the case of the Root Entry, the firstSectorOfStream is the SecID of
// the first sector and the streamLength is the size of the short-stream
// container stream
continue;
// use the short-sector allocation table
int sector = firstSectorOfStream;
while (sector >= 0)
{
sectors.Add(sector);
sector = shortSectorAllocationTable[sector];
}
}
else
{
}
if (streamLength < mvarMinimumStandardStreamSize)
{
// stored as a short-sector container stream
streamOffset = (int)(512 + (firstSectorOfStream * mvarShortSectorSize));
// use the standard sector allocation table
int sector = firstSectorOfStream;
while (sector >= 0)
{
sectors.Add(sector);
sector = sectorAllocationTable[sector];
}
}
File file = new File();
file.Name = storageName;
file.Properties.Add("reader", reader);
file.Properties.Add("offset", streamOffset);
file.Properties.Add("sectors", sectors);
file.Properties.Add("length", streamLength);
file.DataRequest += file_DataRequest;
fsom.Files.Add(file);
}
#endregion
}
private Reader shortSectorReader = null;
private void file_DataRequest(object sender, DataRequestEventArgs e)
{
File file = (sender as File);
Reader reader = (Reader)file.Properties["reader"];
int offset = (int)file.Properties["offset"];
if (shortSectorReader == null) shortSectorReader = new Reader(new Accessors.MemoryAccessor(mvarShortSectorContainerStreamData));
List<int> sectors = (List<int>)file.Properties["sectors"];
int length = (int)file.Properties["length"];
reader.Accessor.Seek(offset, SeekOrigin.Begin);
e.Data = reader.ReadBytes(length);
byte[] realdata = new byte[length];
if (length < mvarMinimumStandardStreamSize)
{
// use the short-sector allocation table and short stream container stream
byte[] data = new byte[sectors.Count * mvarShortSectorSize];
int start = 0;
foreach (int sector in sectors)
{
int pos = GetShortSectorPositionFromSectorID(sector);
shortSectorReader.Accessor.Seek(pos, SeekOrigin.Begin);
byte[] sectorData = shortSectorReader.ReadBytes(mvarShortSectorSize);
Array.Copy(sectorData, 0, data, start, sectorData.Length);
start += (int)mvarShortSectorSize;
}
Array.Copy(data, 0, realdata, 0, realdata.Length);
}
else
{
byte[] data = new byte[sectors.Count * mvarSectorSize];
int start = 0;
foreach (int sector in sectors)
{
int pos = GetSectorPositionFromSectorID(sector);
reader.Accessor.Seek(pos, SeekOrigin.Begin);
byte[] sectorData = reader.ReadBytes(mvarSectorSize);
Array.Copy(sectorData, 0, data, start, sectorData.Length);
start += (int)mvarSectorSize;
}
Array.Copy(data, 0, realdata, 0, realdata.Length);
}
e.Data = realdata;
}
protected override void SaveInternal(ObjectModel objectModel)