preliminary work on NTFS filesystem and OLE1 data formats
This commit is contained in:
parent
eed27053c2
commit
d29b197f72
@ -0,0 +1,28 @@
|
||||
//
|
||||
// NTFSDataAttribute.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS.Attributes
|
||||
{
|
||||
public class NTFSDataAttribute : NTFSAttribute
|
||||
{
|
||||
public byte[] Data { get; set; } = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
//
|
||||
// NTFSFileNameAttribute.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS.Attributes
|
||||
{
|
||||
public class NTFSFileNameAttribute : NTFSAttribute
|
||||
{
|
||||
public DateTime CreationDateTime { get; set; }
|
||||
public DateTime ModificationDateTime { get; set; }
|
||||
public DateTime AccessDateTime { get; set; }
|
||||
|
||||
public long AllocatedSize { get; set; }
|
||||
public long ActualSize { get; set; }
|
||||
|
||||
public string FileName { get; set; } = null;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
//
|
||||
// NTFSStandardInformationAttribute.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS.Attributes
|
||||
{
|
||||
public class NTFSStandardInformationAttribute : NTFSAttribute
|
||||
{
|
||||
public NTFSStandardInformationAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,30 @@
|
||||
//
|
||||
// NTFSAttribute.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS
|
||||
{
|
||||
public abstract class NTFSAttribute
|
||||
{
|
||||
public NTFSAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,344 @@
|
||||
//
|
||||
// NTFSDataFormat.cs - provides a DataFormat for manipulating NTFS file systems
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS.Attributes;
|
||||
using UniversalEditor.IO;
|
||||
using UniversalEditor.ObjectModels.FileSystem;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a <see cref="DataFormat" /> for manipulating NTFS file systems.
|
||||
/// </summary>
|
||||
public class NTFSDataFormat : DataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
protected override DataFormatReference MakeReferenceInternal()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReferenceInternal();
|
||||
_dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
protected override void LoadInternal(ref ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
Reader reader = Accessor.Reader;
|
||||
byte[] jump = reader.ReadBytes(3);
|
||||
|
||||
string id = reader.ReadFixedLengthString(8); // 'NTFS '
|
||||
if (id != "NTFS ") throw new InvalidDataFormatException("file does not begin with 'NTFS '");
|
||||
|
||||
BytesPerSector = reader.ReadInt16();
|
||||
SectorsPerCluster = reader.ReadByte();
|
||||
|
||||
short reservedSectors = reader.ReadInt16(); // 0x0000
|
||||
byte[] reserved2 = reader.ReadBytes(3); // 00 00 00
|
||||
short reserved3 = reader.ReadInt16(); // 0x0000
|
||||
MediaDescriptor = (NTFSMediaDescriptor)reader.ReadByte();
|
||||
short reserved4 = reader.ReadInt16(); // 0x0000
|
||||
SectorsPerTrack = reader.ReadInt16();
|
||||
NumberOfHeads = reader.ReadInt16();
|
||||
HiddenSectors = reader.ReadInt32();
|
||||
int reserved5 = reader.ReadInt32(); // 0x00000000
|
||||
int reserved6 = reader.ReadInt32(); // 0x00800080
|
||||
long totalSectors = reader.ReadInt64(); // 0x00000000007FF54A
|
||||
long masterFileTableClusterNumber = reader.ReadInt64(); // 0x0000000000000004
|
||||
long masterFileTableMirrorClusterNumber = reader.ReadInt64(); // 0x000000000007FF54
|
||||
|
||||
// A positive value denotes the number of clusters in a File Record Segment. A negative value denotes the amount of bytes in a File Record Segment, in which case the
|
||||
// size is 2 to the power of the absolute value. (0xF6 = -10 → 210 = 1024).
|
||||
sbyte bytesOrClustersPerFileRecordSegment = reader.ReadSByte();
|
||||
|
||||
byte[] reserved7 = reader.ReadBytes(3);
|
||||
|
||||
// A positive value denotes the number of clusters in an Index Buffer. A negative value denotes the amount of bytes and it uses the same algorithm for negative
|
||||
// numbers as the "Bytes or Clusters Per File Record Segment."
|
||||
byte bytesOrClustersPerIndexBuffer = reader.ReadByte();
|
||||
|
||||
byte[] reserved8 = reader.ReadBytes(3);
|
||||
long volumeSerialNumber = reader.ReadInt64(); // A unique random number assigned to this partition, to keep things organized.
|
||||
|
||||
int checksum = reader.ReadInt32(); // checksum
|
||||
|
||||
byte[] bootstrapCodeBlock = reader.ReadBytes(426);
|
||||
|
||||
ushort endOfSectorMarker = reader.ReadUInt16();
|
||||
if (endOfSectorMarker != 0xAA55)
|
||||
{
|
||||
throw new InvalidDataFormatException("file does not contain end of sector marker");
|
||||
}
|
||||
|
||||
SeekToCluster(masterFileTableClusterNumber);
|
||||
|
||||
while (true)
|
||||
{
|
||||
bool retval = ReadFile(reader, out File file);
|
||||
if (!retval)
|
||||
break;
|
||||
|
||||
if (file != null)
|
||||
{
|
||||
fsom.Files.Add(file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool ReadFile(Reader reader, out File file)
|
||||
{
|
||||
long thisoffset = reader.Accessor.Position;
|
||||
|
||||
string signature = reader.ReadFixedLengthString(4);
|
||||
if (signature != "FILE")
|
||||
{
|
||||
file = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
file = new File();
|
||||
|
||||
ushort offsetToUpdateSequence = reader.ReadUInt16();
|
||||
ushort fixupEntryCount = reader.ReadUInt16();
|
||||
long logFileSequenceNumber = reader.ReadInt64();
|
||||
ushort sequenceNumber = reader.ReadUInt16();
|
||||
ushort hardLinkCount = reader.ReadUInt16();
|
||||
ushort firstAttributeOffset = reader.ReadUInt16();
|
||||
NTFSMftEntryFlags flags = (NTFSMftEntryFlags)reader.ReadUInt16();
|
||||
|
||||
uint mftEntryUsedSize = reader.ReadUInt32();
|
||||
uint mftEntryAllocatedSize = reader.ReadUInt32();
|
||||
long baseFILErecordRef = reader.ReadInt64();
|
||||
ushort nextAttributeID = reader.ReadUInt16();
|
||||
ushort align = reader.ReadUInt16();
|
||||
uint mftRecordNumber = reader.ReadUInt32();
|
||||
|
||||
reader.Accessor.Seek(thisoffset + firstAttributeOffset, SeekOrigin.Begin);
|
||||
|
||||
// read the attributes
|
||||
while (true)
|
||||
{
|
||||
bool keepgoing = ReadAttribute(reader, out NTFSMftKnownAttribute type, out NTFSAttribute attr);
|
||||
if (attr == null && type != NTFSMftKnownAttribute.End)
|
||||
{
|
||||
Console.WriteLine("ue: ntfs: WARNING: skipping unknown attribute {0}", type);
|
||||
}
|
||||
|
||||
if (type == NTFSMftKnownAttribute.Invalid)
|
||||
{
|
||||
Console.WriteLine("ue: ntfs: WARNING: caught 'invalid' attribute 0, panicking");
|
||||
break;
|
||||
}
|
||||
|
||||
if (attr is NTFSFileNameAttribute)
|
||||
{
|
||||
NTFSFileNameAttribute att = (attr as NTFSFileNameAttribute);
|
||||
file.Name = att.FileName;
|
||||
file.Size = att.AllocatedSize;
|
||||
}
|
||||
|
||||
if (!keepgoing)
|
||||
break;
|
||||
}
|
||||
|
||||
// skip empty space
|
||||
reader.Accessor.Seek(thisoffset + mftEntryAllocatedSize, SeekOrigin.Begin);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ReadAttribute(Reader reader, out NTFSMftKnownAttribute type, out NTFSAttribute attr)
|
||||
{
|
||||
long thisoffset = reader.Accessor.Position;
|
||||
|
||||
NTFSMftKnownAttribute attributeId = (NTFSMftKnownAttribute)reader.ReadInt32();
|
||||
type = attributeId;
|
||||
if (attributeId == NTFSMftKnownAttribute.End)
|
||||
{
|
||||
attr = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint attributeLength = reader.ReadUInt32();
|
||||
byte nonResidentFlag = reader.ReadByte();
|
||||
byte nameLength = reader.ReadByte();
|
||||
ushort nameOffset = reader.ReadUInt16();
|
||||
ushort flags = reader.ReadUInt16();
|
||||
|
||||
ushort attributeIdentifier = reader.ReadUInt16();
|
||||
if (nonResidentFlag == 0)
|
||||
{
|
||||
uint contentSize = reader.ReadUInt32();
|
||||
ushort contentOffset = reader.ReadUInt16();
|
||||
|
||||
reader.Seek(thisoffset + contentOffset, SeekOrigin.Begin);
|
||||
switch (attributeId)
|
||||
{
|
||||
case NTFSMftKnownAttribute.StandardInformation:
|
||||
{
|
||||
NTFSStandardInformationAttribute att = new NTFSStandardInformationAttribute();
|
||||
long creationDateTime = reader.ReadInt64();
|
||||
long modificationDateTime = reader.ReadInt64();
|
||||
long mftModificationDateTime = reader.ReadInt64();
|
||||
long readDateTime = reader.ReadInt64();
|
||||
int dosFilePermissions = reader.ReadInt32();
|
||||
int maxVersionCount = reader.ReadInt32();
|
||||
int versionNumber = reader.ReadInt32();
|
||||
int classId = reader.ReadInt32();
|
||||
int ownerId = reader.ReadInt32();
|
||||
int securityId = reader.ReadInt32();
|
||||
long quotaCharged = reader.ReadInt64();
|
||||
long updateSequenceNumber = reader.ReadInt64();
|
||||
attr = att;
|
||||
break;
|
||||
}
|
||||
case NTFSMftKnownAttribute.FileName:
|
||||
{
|
||||
NTFSFileNameAttribute att = new NTFSFileNameAttribute();
|
||||
long parentDirectoryFileref = reader.ReadInt64();
|
||||
long creationDateTime = reader.ReadInt64();
|
||||
att.CreationDateTime = new DateTime(creationDateTime);
|
||||
long modificationDateTime = reader.ReadInt64();
|
||||
att.ModificationDateTime = new DateTime(modificationDateTime);
|
||||
long mftModificationDateTime = reader.ReadInt64();
|
||||
long readDateTime = reader.ReadInt64();
|
||||
att.AccessDateTime = new DateTime(readDateTime);
|
||||
att.AllocatedSize = reader.ReadInt64();
|
||||
att.ActualSize = reader.ReadInt64();
|
||||
int fileNameFlags = reader.ReadInt32();
|
||||
int reparse = reader.ReadInt32();
|
||||
// int securityId = reader.ReadInt32();
|
||||
byte fileNameLength = reader.ReadByte();
|
||||
byte fileNameNamespace = reader.ReadByte();
|
||||
string fileNameUnicode = reader.ReadFixedLengthString(fileNameLength * 2, Encoding.UTF16LittleEndian);
|
||||
att.FileName = fileNameUnicode;
|
||||
|
||||
attr = att;
|
||||
break;
|
||||
}
|
||||
case NTFSMftKnownAttribute.Data:
|
||||
{
|
||||
NTFSDataAttribute att = new NTFSDataAttribute();
|
||||
att.Data = reader.ReadBytes(attributeLength);
|
||||
attr = att;
|
||||
break;
|
||||
}
|
||||
case NTFSMftKnownAttribute.UnknownB0:
|
||||
{
|
||||
attr = null;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
attr = null;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long runlistStartingVirtualClusterNumber = reader.ReadInt64();
|
||||
long runlistEndingVirtualClusterNumber = reader.ReadInt64();
|
||||
ushort runlistOffset = reader.ReadUInt16();
|
||||
ushort compressionUnitSize = reader.ReadUInt16();
|
||||
uint unused = reader.ReadUInt32();
|
||||
ulong attributeContentAllocatedSize = reader.ReadUInt64();
|
||||
ulong attributeContentActualSize = reader.ReadUInt64();
|
||||
ulong attributeContentInitializedSize = reader.ReadUInt64();
|
||||
|
||||
SeekToCluster(runlistStartingVirtualClusterNumber);
|
||||
|
||||
attr = null;
|
||||
}
|
||||
|
||||
long remaining = (thisoffset + attributeLength) - reader.Accessor.Position;
|
||||
if (remaining > 0)
|
||||
{
|
||||
reader.Seek(remaining, SeekOrigin.Current);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private void SeekToCluster(long clusterNumber)
|
||||
{
|
||||
Accessor.Seek(clusterNumber * BytesPerSector * SectorsPerCluster, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
public short BytesPerSector { get; set; } = 0x0200;
|
||||
public byte SectorsPerCluster { get; set; } = 0x08;
|
||||
public NTFSMediaDescriptor MediaDescriptor { get; set; } = NTFSMediaDescriptor.HardDisk;
|
||||
public short SectorsPerTrack { get; set; } = 0x003F;
|
||||
public short NumberOfHeads { get; set; } = 0x00FF;
|
||||
public int HiddenSectors { get; set; } = 0x0000003F;
|
||||
|
||||
protected override void SaveInternal(ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
Writer writer = Accessor.Writer;
|
||||
writer.WriteBytes(new byte[] { 0xEB, 0x52, 0x90 });
|
||||
writer.WriteFixedLengthString("NTFS ");
|
||||
|
||||
writer.WriteInt16(BytesPerSector);
|
||||
writer.WriteByte(SectorsPerCluster);
|
||||
writer.WriteInt16(0x0000); // reservedSectors
|
||||
writer.WriteBytes(new byte[] { 0, 0, 0 });
|
||||
writer.WriteInt16(0x0000);
|
||||
writer.WriteByte((byte)MediaDescriptor);
|
||||
writer.WriteInt16(0x0000);
|
||||
writer.WriteInt16(SectorsPerTrack);
|
||||
writer.WriteInt16(NumberOfHeads);
|
||||
writer.WriteInt32(HiddenSectors);
|
||||
writer.WriteInt32(0x00000000);
|
||||
writer.WriteInt32(0x00800080); // reserved6
|
||||
writer.WriteInt64(0x00000000007FF54A); // totalSectors
|
||||
writer.WriteInt64(0x0000000000000004); // $MFT cluster number
|
||||
writer.WriteInt64(0x000000000007FF54); // $MFTMirr cluster number
|
||||
|
||||
// A positive value denotes the number of clusters in a File Record Segment. A negative value denotes the amount of bytes in a File Record Segment, in which case the
|
||||
// size is 2 to the power of the absolute value. (0xF6 = -10 → 2^10 = 1024).
|
||||
writer.WriteByte(0xF6); // bytesOrClustersPerFileRecordSegment
|
||||
|
||||
writer.WriteBytes(new byte[] { 0x00, 0x00, 0x00 });
|
||||
|
||||
// A positive value denotes the number of clusters in an Index Buffer. A negative value denotes the amount of bytes and it uses the same algorithm for negative
|
||||
// numbers as the "Bytes or Clusters Per File Record Segment."
|
||||
writer.WriteByte(0x01);
|
||||
|
||||
writer.WriteBytes(new byte[] { 0x00, 0x00, 0x00 });
|
||||
writer.WriteInt64(0x1C741BC9741BA514); // volumeSerialNumber
|
||||
|
||||
writer.WriteInt32(0); // Checksum, unused
|
||||
|
||||
byte[] bootstrapCodeBlock = new byte[426]; // The code that loads the rest of the operating system. This is pointed to by the first 3 bytes of this sector.
|
||||
writer.WriteBytes(bootstrapCodeBlock);
|
||||
|
||||
writer.WriteUInt16(0xAA55); // end-of-sector marker
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
//
|
||||
// NTFSMediaDescriptor.cs - indicates the type of drive hosting an NTFS file system
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the type of drive hosting an NTFS file system.
|
||||
/// </summary>
|
||||
public enum NTFSMediaDescriptor
|
||||
{
|
||||
/// <summary>
|
||||
/// Used to denote a hard drive (in contrast to the several sizes of floppy).
|
||||
/// </summary>
|
||||
HardDisk = 0xF8
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
//
|
||||
// NTFSMftEntryFlags.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS
|
||||
{
|
||||
[Flags()]
|
||||
public enum NTFSMftEntryFlags
|
||||
{
|
||||
Deleted = 0x0000,
|
||||
Allocated = 0x0001,
|
||||
Directory = 0x0002
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,33 @@
|
||||
//
|
||||
// NTFSMftKnownAttribute.cs
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
using System;
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.NTFS
|
||||
{
|
||||
public enum NTFSMftKnownAttribute
|
||||
{
|
||||
Invalid = 0x00,
|
||||
StandardInformation = 0x10,
|
||||
FileName = 0x30,
|
||||
Data = 0x80,
|
||||
UnknownB0 = 0xB0,
|
||||
End = -1
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,38 @@
|
||||
//
|
||||
// OLE1ChunkType.cs - indicates the type of chunk in an Object Linking and Embedding (OLE) version 1.0 file
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UniversalEditor.IO;
|
||||
using UniversalEditor.ObjectModels.FileSystem;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.OLE.OLE1
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates the type of chunk in an Object Linking and Embedding (OLE) version 1.0 file.
|
||||
/// </summary>
|
||||
public enum OLE1ChunkType
|
||||
{
|
||||
LinkedObject = 0x00000001,
|
||||
EmbeddedObject = 0x00000002
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,187 @@
|
||||
//
|
||||
// OLE1DataFormat.cs - provides a DataFormat for manipulating Microsoft Object Linking and Embedding (OLE) version 1 files
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using UniversalEditor.IO;
|
||||
using UniversalEditor.ObjectModels.FileSystem;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.OLE.OLE1
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides a <see cref="DataFormat" /> for manipulating Microsoft Object Linking and Embedding (OLE) version 1 files.
|
||||
/// </summary>
|
||||
public class OLE1DataFormat : DataFormat
|
||||
{
|
||||
private static DataFormatReference _dfr = null;
|
||||
protected override DataFormatReference MakeReferenceInternal()
|
||||
{
|
||||
if (_dfr == null)
|
||||
{
|
||||
_dfr = base.MakeReferenceInternal();
|
||||
_dfr.Capabilities.Add(typeof(FileSystemObjectModel), DataFormatCapabilities.All);
|
||||
_dfr.ExportOptions.Add(new CustomOptionText(nameof(ProgramName), "_Program name"));
|
||||
_dfr.ExportOptions.Add(new CustomOptionNumber(nameof(OriginalFileName), "Original file _name"));
|
||||
}
|
||||
return _dfr;
|
||||
}
|
||||
|
||||
public string ProgramName { get; set; }
|
||||
public string OriginalFileName { get; set; }
|
||||
|
||||
protected override void LoadInternal(ref ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
Reader reader = base.Accessor.Reader;
|
||||
|
||||
OLE1ObjectHeader chunk = ReadOLE1ObjectHeader(reader);
|
||||
switch (chunk.Type)
|
||||
{
|
||||
case OLE1ChunkType.EmbeddedObject:
|
||||
{
|
||||
uint nativeDataSize = reader.ReadUInt32();
|
||||
|
||||
// blah?
|
||||
ushort x0200 = reader.ReadUInt16();
|
||||
byte nul = reader.ReadByte();
|
||||
string w = reader.ReadNullTerminatedString();
|
||||
uint unkn2 = reader.ReadUInt32();
|
||||
uint originalFileNameLen = reader.ReadUInt32();
|
||||
string originalFileName = reader.ReadFixedLengthString(originalFileNameLen);
|
||||
|
||||
uint nativeDataLen = reader.ReadUInt32();
|
||||
byte[] nativeData = reader.ReadBytes(nativeDataLen);
|
||||
|
||||
reader.Seek(nativeDataSize + 40, SeekOrigin.Begin);
|
||||
fsom.Files.Add("NATIVEDATA", nativeData);
|
||||
break;
|
||||
}
|
||||
case OLE1ChunkType.LinkedObject:
|
||||
{
|
||||
// networkname
|
||||
uint unknown4 = reader.ReadUInt32(); // 0
|
||||
|
||||
// reserved
|
||||
uint unknown5 = reader.ReadUInt32(); // 0
|
||||
|
||||
// linkupdateoption
|
||||
uint unknown6 = reader.ReadUInt32(); // 0
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
OLE1PresentationObject chunk2 = ReadOLE1PresentationObject(reader);
|
||||
fsom.Files.Add(System.IO.Path.GetFileName(chunk.TopicName.Replace('\\', System.IO.Path.DirectorySeparatorChar)), chunk2.Data);
|
||||
}
|
||||
|
||||
private OLE1ObjectHeader ReadOLE1ObjectHeader(Reader reader)
|
||||
{
|
||||
OLE1ObjectHeader header = new OLE1ObjectHeader();
|
||||
uint oleversion = reader.ReadUInt32(); // 1281
|
||||
header.Type = (OLE1ChunkType)reader.ReadUInt32(); // 01, 02, 05
|
||||
|
||||
uint classNameLength = reader.ReadUInt32(); // length of program name + null terminator
|
||||
string className = reader.ReadFixedLengthString(classNameLength);
|
||||
header.ClassName = className.TrimNull();
|
||||
|
||||
uint topicNameLength = reader.ReadUInt32(); // incl. null terminator
|
||||
string topicName = reader.ReadFixedLengthString(topicNameLength);
|
||||
header.TopicName = topicName.TrimNull();
|
||||
|
||||
uint itemNameLength = reader.ReadUInt32(); // 0
|
||||
string itemName = reader.ReadFixedLengthString(itemNameLength);
|
||||
header.ItemName = itemName.TrimNull();
|
||||
return header;
|
||||
}
|
||||
private OLE1PresentationObject ReadOLE1PresentationObject(Reader reader)
|
||||
{
|
||||
OLE1PresentationObject header = new OLE1PresentationObject();
|
||||
uint oleversion = reader.ReadUInt32(); // 1281
|
||||
uint flags = reader.ReadUInt32();
|
||||
if (flags == 0x00000005)
|
||||
{
|
||||
uint classNameLength = reader.ReadUInt32();
|
||||
header.ClassName = reader.ReadFixedLengthString(classNameLength).TrimNull();
|
||||
}
|
||||
else
|
||||
{
|
||||
header.ClassName = null;
|
||||
}
|
||||
|
||||
header.Width = reader.ReadUInt32();
|
||||
header.Height = (uint)(reader.ReadInt32() * -1); // the fuck?
|
||||
|
||||
uint datasize = reader.ReadUInt32();
|
||||
if (header.ClassName == "METAFILEPICT")
|
||||
{
|
||||
datasize -= 8;
|
||||
ushort reserved1 = reader.ReadUInt16();
|
||||
ushort reserved2 = reader.ReadUInt16();
|
||||
ushort reserved3 = reader.ReadUInt16();
|
||||
ushort reserved4 = reader.ReadUInt16();
|
||||
}
|
||||
|
||||
header.Data = reader.ReadBytes(datasize);
|
||||
return header;
|
||||
}
|
||||
|
||||
private void WriteOLE1ObjectHeader(Writer writer, OLE1ObjectHeader value)
|
||||
{
|
||||
writer.WriteUInt32(1281); // ole version
|
||||
writer.WriteUInt32((uint)value.Type);
|
||||
|
||||
writer.WriteUInt32((uint)(value.ClassName.Length + 1));
|
||||
writer.WriteNullTerminatedString(value.ClassName);
|
||||
writer.WriteUInt32((uint)(value.TopicName.Length + 1));
|
||||
writer.WriteNullTerminatedString(value.TopicName);
|
||||
writer.WriteUInt32((uint)(value.ItemName.Length + 1));
|
||||
writer.WriteNullTerminatedString(value.ItemName);
|
||||
}
|
||||
|
||||
protected override void SaveInternal(ObjectModel objectModel)
|
||||
{
|
||||
FileSystemObjectModel fsom = (objectModel as FileSystemObjectModel);
|
||||
if (fsom == null) throw new ObjectModelNotSupportedException();
|
||||
|
||||
Writer writer = base.Accessor.Writer;
|
||||
|
||||
OLE1ObjectHeader header = new OLE1ObjectHeader();
|
||||
WriteOLE1ObjectHeader(writer, header);
|
||||
|
||||
switch (header.Type)
|
||||
{
|
||||
case OLE1ChunkType.LinkedObject:
|
||||
{
|
||||
// networkname
|
||||
writer.WriteUInt32(0);
|
||||
// reserved
|
||||
writer.WriteUInt32(0);
|
||||
// linkupdateoption
|
||||
writer.WriteUInt32(0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
//
|
||||
// OLE1Chunk.cs -
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
using UniversalEditor.IO;
|
||||
using UniversalEditor.ObjectModels.FileSystem;
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.OLE.OLE1
|
||||
{
|
||||
public class OLE1ObjectHeader
|
||||
{
|
||||
public OLE1ChunkType Type { get; set; }
|
||||
public string ClassName { get; set; }
|
||||
public string TopicName { get; set; }
|
||||
public string ItemName { get; set; }
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
//
|
||||
// OLE1PresentationObjectHeader.cs -
|
||||
//
|
||||
// Author:
|
||||
// Michael Becker <alcexhim@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2020 Mike Becker's Software
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace UniversalEditor.DataFormats.FileSystem.Microsoft.OLE.OLE1
|
||||
{
|
||||
public class OLE1PresentationObject
|
||||
{
|
||||
public string ClassName { get; set; } = null;
|
||||
|
||||
public uint Width { get; set; }
|
||||
public uint Height { get; set; }
|
||||
public byte[] Data { get; set; }
|
||||
}
|
||||
}
|
||||
@ -140,6 +140,18 @@
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\VirtualHardDisk\VHDHardDiskParentLocatorEntry.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\VirtualHardDisk\VHDHardDiskType.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\RKV\RKVDataFormat.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\OLE\OLE1\OLE1DataFormat.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\OLE\OLE1\OLE1ObjectHeader.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\OLE\OLE1\OLE1ChunkType.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\OLE\OLE1\OLE1PresentationObject.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\NTFSDataFormat.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\NTFSMediaDescriptor.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\NTFSMftEntryFlags.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\NTFSMftKnownAttribute.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\NTFSAttribute.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\Attributes\NTFSFileNameAttribute.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\Attributes\NTFSStandardInformationAttribute.cs" />
|
||||
<Compile Include="DataFormats\FileSystem\Microsoft\NTFS\Attributes\NTFSDataAttribute.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Libraries\UniversalEditor.Compression\UniversalEditor.Compression.csproj">
|
||||
@ -187,5 +199,9 @@
|
||||
<Folder Include="DataFormats\Text\Formatted\DOC\" />
|
||||
<Folder Include="DataFormats\FileSystem\Microsoft\VirtualHardDisk\" />
|
||||
<Folder Include="DataFormats\FileSystem\Microsoft\RKV\" />
|
||||
<Folder Include="DataFormats\FileSystem\Microsoft\OLE\" />
|
||||
<Folder Include="DataFormats\FileSystem\Microsoft\OLE\OLE1\" />
|
||||
<Folder Include="DataFormats\FileSystem\Microsoft\NTFS\" />
|
||||
<Folder Include="DataFormats\FileSystem\Microsoft\NTFS\Attributes\" />
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
Loading…
x
Reference in New Issue
Block a user