mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-16 04:10:11 +10:00
200 lines
6.0 KiB
C#
200 lines
6.0 KiB
C#
//
|
|
// Copyright (c) 2008-2011, Kenneth Bell
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a
|
|
// copy of this software and associated documentation files (the "Software"),
|
|
// to deal in the Software without restriction, including without limitation
|
|
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
|
// and/or sell copies of the Software, and to permit persons to whom the
|
|
// Software is furnished to do so, subject to the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
// DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
namespace DiscUtils.Ntfs
|
|
{
|
|
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
|
|
[Flags]
|
|
internal enum AttributeFlags : ushort
|
|
{
|
|
None = 0x0000,
|
|
Compressed = 0x0001,
|
|
Encrypted = 0x4000,
|
|
Sparse = 0x8000
|
|
}
|
|
|
|
internal abstract class AttributeRecord : IComparable<AttributeRecord>
|
|
{
|
|
protected AttributeType _type;
|
|
protected byte _nonResidentFlag;
|
|
protected AttributeFlags _flags;
|
|
protected ushort _attributeId;
|
|
|
|
protected string _name;
|
|
|
|
public AttributeRecord()
|
|
{
|
|
}
|
|
|
|
public AttributeRecord(AttributeType type, string name, ushort id, AttributeFlags flags)
|
|
{
|
|
_type = type;
|
|
_name = name;
|
|
_attributeId = id;
|
|
_flags = flags;
|
|
}
|
|
|
|
public AttributeType AttributeType
|
|
{
|
|
get { return _type; }
|
|
}
|
|
|
|
public ushort AttributeId
|
|
{
|
|
get { return _attributeId; }
|
|
set { _attributeId = value; }
|
|
}
|
|
|
|
public abstract long AllocatedLength
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public abstract long StartVcn
|
|
{
|
|
get;
|
|
}
|
|
|
|
public abstract long DataLength
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public abstract long InitializedDataLength
|
|
{
|
|
get;
|
|
set;
|
|
}
|
|
|
|
public bool IsNonResident
|
|
{
|
|
get { return _nonResidentFlag != 0; }
|
|
}
|
|
|
|
public string Name
|
|
{
|
|
get { return _name; }
|
|
}
|
|
|
|
public AttributeFlags Flags
|
|
{
|
|
get { return _flags; }
|
|
set { _flags = value; }
|
|
}
|
|
|
|
public abstract int Size { get; }
|
|
|
|
public static AttributeRecord FromBytes(byte[] buffer, int offset, out int length)
|
|
{
|
|
if (Utilities.ToUInt32LittleEndian(buffer, offset) == 0xFFFFFFFF)
|
|
{
|
|
length = 0;
|
|
return null;
|
|
}
|
|
else if (buffer[offset + 0x08] != 0x00)
|
|
{
|
|
return new NonResidentAttributeRecord(buffer, offset, out length);
|
|
}
|
|
else
|
|
{
|
|
return new ResidentAttributeRecord(buffer, offset, out length);
|
|
}
|
|
}
|
|
|
|
public static int CompareStartVcns(AttributeRecord x, AttributeRecord y)
|
|
{
|
|
if (x.StartVcn < y.StartVcn)
|
|
{
|
|
return -1;
|
|
}
|
|
else if (x.StartVcn == y.StartVcn)
|
|
{
|
|
return 0;
|
|
}
|
|
else
|
|
{
|
|
return 1;
|
|
}
|
|
}
|
|
|
|
public abstract Range<long, long>[] GetClusters();
|
|
|
|
public abstract IBuffer GetReadOnlyDataBuffer(INtfsContext context);
|
|
|
|
public int CompareTo(AttributeRecord other)
|
|
{
|
|
int val = ((int)_type) - (int)other._type;
|
|
if (val != 0)
|
|
{
|
|
return val;
|
|
}
|
|
|
|
val = string.Compare(_name, other._name, StringComparison.OrdinalIgnoreCase);
|
|
if (val != 0)
|
|
{
|
|
return val;
|
|
}
|
|
|
|
return ((int)_attributeId) - (int)other._attributeId;
|
|
}
|
|
|
|
public abstract int Write(byte[] buffer, int offset);
|
|
|
|
public virtual void Dump(TextWriter writer, string indent)
|
|
{
|
|
writer.WriteLine(indent + "ATTRIBUTE RECORD");
|
|
writer.WriteLine(indent + " Type: " + _type);
|
|
writer.WriteLine(indent + " Non-Resident: " + _nonResidentFlag);
|
|
writer.WriteLine(indent + " Name: " + _name);
|
|
writer.WriteLine(indent + " Flags: " + _flags);
|
|
writer.WriteLine(indent + " AttributeId: " + _attributeId);
|
|
}
|
|
|
|
protected virtual void Read(byte[] buffer, int offset, out int length)
|
|
{
|
|
_type = (AttributeType)Utilities.ToUInt32LittleEndian(buffer, offset + 0x00);
|
|
length = Utilities.ToInt32LittleEndian(buffer, offset + 0x04);
|
|
|
|
_nonResidentFlag = buffer[offset + 0x08];
|
|
byte nameLength = buffer[offset + 0x09];
|
|
ushort nameOffset = Utilities.ToUInt16LittleEndian(buffer, offset + 0x0A);
|
|
_flags = (AttributeFlags)Utilities.ToUInt16LittleEndian(buffer, offset + 0x0C);
|
|
_attributeId = Utilities.ToUInt16LittleEndian(buffer, offset + 0x0E);
|
|
|
|
if (nameLength != 0x00)
|
|
{
|
|
if (nameLength + nameOffset > length)
|
|
{
|
|
throw new IOException("Corrupt attribute, name outside of attribute");
|
|
}
|
|
|
|
_name = Encoding.Unicode.GetString(buffer, offset + nameOffset, nameLength * 2);
|
|
}
|
|
}
|
|
}
|
|
}
|