mirror of
https://github.com/ReneLergner/WPinternals.git
synced 2026-06-16 04:10:11 +10:00
211 lines
8.3 KiB
C#
211 lines
8.3 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 FileAttributeFlags : uint
|
|
{
|
|
None = 0x00000000,
|
|
ReadOnly = 0x00000001,
|
|
Hidden = 0x00000002,
|
|
System = 0x00000004,
|
|
Archive = 0x00000020,
|
|
Device = 0x00000040,
|
|
Normal = 0x00000080,
|
|
Temporary = 0x00000100,
|
|
Sparse = 0x00000200,
|
|
ReparsePoint = 0x00000400,
|
|
Compressed = 0x00000800,
|
|
Offline = 0x00001000,
|
|
NotIndexed = 0x00002000,
|
|
Encrypted = 0x00004000,
|
|
Directory = 0x10000000,
|
|
IndexView = 0x20000000
|
|
}
|
|
|
|
internal enum FileNameNamespace : byte
|
|
{
|
|
Posix = 0,
|
|
Win32 = 1,
|
|
Dos = 2,
|
|
Win32AndDos = 3
|
|
}
|
|
|
|
internal class FileNameRecord : IByteArraySerializable, IDiagnosticTraceable, IEquatable<FileNameRecord>
|
|
{
|
|
public FileRecordReference ParentDirectory;
|
|
public DateTime CreationTime;
|
|
public DateTime ModificationTime;
|
|
public DateTime MftChangedTime;
|
|
public DateTime LastAccessTime;
|
|
public ulong AllocatedSize;
|
|
public ulong RealSize;
|
|
public FileAttributeFlags Flags;
|
|
public uint EASizeOrReparsePointTag;
|
|
public FileNameNamespace FileNameNamespace;
|
|
public string FileName;
|
|
|
|
public FileNameRecord()
|
|
{
|
|
}
|
|
|
|
public FileNameRecord(FileNameRecord toCopy)
|
|
{
|
|
ParentDirectory = toCopy.ParentDirectory;
|
|
CreationTime = toCopy.CreationTime;
|
|
ModificationTime = toCopy.ModificationTime;
|
|
MftChangedTime = toCopy.MftChangedTime;
|
|
LastAccessTime = toCopy.LastAccessTime;
|
|
AllocatedSize = toCopy.AllocatedSize;
|
|
RealSize = toCopy.RealSize;
|
|
Flags = toCopy.Flags;
|
|
EASizeOrReparsePointTag = toCopy.EASizeOrReparsePointTag;
|
|
FileNameNamespace = toCopy.FileNameNamespace;
|
|
FileName = toCopy.FileName;
|
|
}
|
|
|
|
public FileAttributes FileAttributes
|
|
{
|
|
get { return ConvertFlags(Flags); }
|
|
}
|
|
|
|
public int Size
|
|
{
|
|
get
|
|
{
|
|
return 0x42 + (FileName.Length * 2);
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return FileName;
|
|
}
|
|
|
|
public void Dump(TextWriter writer, string indent)
|
|
{
|
|
writer.WriteLine(indent + "FILE NAME RECORD");
|
|
writer.WriteLine(indent + " Parent Directory: " + ParentDirectory);
|
|
writer.WriteLine(indent + " Creation Time: " + CreationTime);
|
|
writer.WriteLine(indent + " Modification Time: " + ModificationTime);
|
|
writer.WriteLine(indent + " MFT Changed Time: " + MftChangedTime);
|
|
writer.WriteLine(indent + " Last Access Time: " + LastAccessTime);
|
|
writer.WriteLine(indent + " Allocated Size: " + AllocatedSize);
|
|
writer.WriteLine(indent + " Real Size: " + RealSize);
|
|
writer.WriteLine(indent + " Flags: " + Flags);
|
|
|
|
if ((Flags & FileAttributeFlags.ReparsePoint) != 0)
|
|
{
|
|
writer.WriteLine(indent + " Reparse Point Tag: " + EASizeOrReparsePointTag);
|
|
}
|
|
else
|
|
{
|
|
writer.WriteLine(indent + " Ext Attr Size: " + (EASizeOrReparsePointTag & 0xFFFF));
|
|
}
|
|
|
|
writer.WriteLine(indent + " Namespace: " + FileNameNamespace);
|
|
writer.WriteLine(indent + " File Name: " + FileName);
|
|
}
|
|
|
|
public int ReadFrom(byte[] buffer, int offset)
|
|
{
|
|
ParentDirectory = new FileRecordReference(Utilities.ToUInt64LittleEndian(buffer, offset + 0x00));
|
|
CreationTime = ReadDateTime(buffer, offset + 0x08);
|
|
ModificationTime = ReadDateTime(buffer, offset + 0x10);
|
|
MftChangedTime = ReadDateTime(buffer, offset + 0x18);
|
|
LastAccessTime = ReadDateTime(buffer, offset + 0x20);
|
|
AllocatedSize = Utilities.ToUInt64LittleEndian(buffer, offset + 0x28);
|
|
RealSize = Utilities.ToUInt64LittleEndian(buffer, offset + 0x30);
|
|
Flags = (FileAttributeFlags)Utilities.ToUInt32LittleEndian(buffer, offset + 0x38);
|
|
EASizeOrReparsePointTag = Utilities.ToUInt32LittleEndian(buffer, offset + 0x3C);
|
|
byte fnLen = buffer[offset + 0x40];
|
|
FileNameNamespace = (FileNameNamespace)buffer[offset + 0x41];
|
|
FileName = Encoding.Unicode.GetString(buffer, offset + 0x42, fnLen * 2);
|
|
|
|
return 0x42 + (fnLen * 2);
|
|
}
|
|
|
|
public void WriteTo(byte[] buffer, int offset)
|
|
{
|
|
Utilities.WriteBytesLittleEndian((ulong)ParentDirectory.Value, buffer, offset + 0x00);
|
|
Utilities.WriteBytesLittleEndian((ulong)CreationTime.ToFileTimeUtc(), buffer, offset + 0x08);
|
|
Utilities.WriteBytesLittleEndian((ulong)ModificationTime.ToFileTimeUtc(), buffer, offset + 0x10);
|
|
Utilities.WriteBytesLittleEndian((ulong)MftChangedTime.ToFileTimeUtc(), buffer, offset + 0x18);
|
|
Utilities.WriteBytesLittleEndian((ulong)LastAccessTime.ToFileTimeUtc(), buffer, offset + 0x20);
|
|
Utilities.WriteBytesLittleEndian(AllocatedSize, buffer, offset + 0x28);
|
|
Utilities.WriteBytesLittleEndian(RealSize, buffer, offset + 0x30);
|
|
Utilities.WriteBytesLittleEndian((uint)Flags, buffer, offset + 0x38);
|
|
Utilities.WriteBytesLittleEndian(EASizeOrReparsePointTag, buffer, offset + 0x3C);
|
|
buffer[offset + 0x40] = (byte)FileName.Length;
|
|
buffer[offset + 0x41] = (byte)FileNameNamespace;
|
|
Encoding.Unicode.GetBytes(FileName, 0, FileName.Length, buffer, offset + 0x42);
|
|
}
|
|
|
|
public bool Equals(FileNameRecord other)
|
|
{
|
|
if (other == null)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return ParentDirectory == other.ParentDirectory
|
|
&& FileNameNamespace == other.FileNameNamespace
|
|
&& FileName == other.FileName;
|
|
}
|
|
|
|
internal static FileAttributeFlags SetAttributes(FileAttributes attrs, FileAttributeFlags flags)
|
|
{
|
|
FileAttributes attrMask = ((FileAttributes)0xFFFF) & ~FileAttributes.Directory;
|
|
return (FileAttributeFlags)(((uint)flags & 0xFFFF0000) | (uint)(attrs & attrMask));
|
|
}
|
|
|
|
internal static FileAttributes ConvertFlags(FileAttributeFlags flags)
|
|
{
|
|
FileAttributes result = (FileAttributes)(((uint)flags) & 0xFFFF);
|
|
|
|
if ((flags & FileAttributeFlags.Directory) != 0)
|
|
{
|
|
result |= FileAttributes.Directory;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
private static DateTime ReadDateTime(byte[] buffer, int offset)
|
|
{
|
|
try
|
|
{
|
|
return DateTime.FromFileTimeUtc(Utilities.ToInt64LittleEndian(buffer, offset));
|
|
}
|
|
catch (ArgumentException)
|
|
{
|
|
return DateTime.MinValue;
|
|
}
|
|
}
|
|
}
|
|
}
|