mirror of
https://github.com/reactos/reactos.git
synced 2024-08-26 21:28:48 +00:00
![Amine Khaldi](/assets/img/avatar_default.png)
* Create a branch for some evul shell experiments. svn path=/branches/shell-experiments/; revision=61927
327 lines
8.3 KiB
C
327 lines
8.3 KiB
C
/*
|
|
* ReactOS kernel
|
|
* Copyright (C) 2002 ReactOS Team
|
|
*
|
|
* 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 2 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, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
* PROJECT: ReactOS kernel
|
|
* FILE: drivers/filesystem/ntfs/mft.c
|
|
* PURPOSE: NTFS filesystem driver
|
|
* PROGRAMMER: Eric Kohl
|
|
* Updated by Valentin Verkhovsky 2003/09/12
|
|
*/
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
#include "ntfs.h"
|
|
|
|
#define NDEBUG
|
|
#include <debug.h>
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
NTSTATUS
|
|
NtfsOpenMft(PDEVICE_EXTENSION Vcb)
|
|
{
|
|
// PVOID Bitmap;
|
|
PFILE_RECORD_HEADER MftRecord;
|
|
PFILE_RECORD_HEADER FileRecord;
|
|
// PATTRIBUTE Attribute;
|
|
// PATTRIBUTE AttrData;
|
|
// PRESIDENT_ATTRIBUTE ResAttr;
|
|
|
|
NTSTATUS Status;
|
|
ULONG BytesPerFileRecord;
|
|
ULONG n;
|
|
ULONG i;
|
|
|
|
DPRINT1("NtfsOpenMft() called\n");
|
|
|
|
BytesPerFileRecord = Vcb->NtfsInfo.BytesPerFileRecord;
|
|
|
|
MftRecord = ExAllocatePoolWithTag(NonPagedPool,
|
|
BytesPerFileRecord,
|
|
TAG_NTFS);
|
|
if (MftRecord == NULL)
|
|
{
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
Status = NtfsReadSectors(Vcb->StorageDevice,
|
|
Vcb->NtfsInfo.MftStart.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
|
|
BytesPerFileRecord / Vcb->NtfsInfo.BytesPerSector,
|
|
Vcb->NtfsInfo.BytesPerSector,
|
|
(PVOID)MftRecord,
|
|
FALSE);
|
|
if (!NT_SUCCESS(Status))
|
|
{
|
|
ExFreePool(MftRecord);
|
|
return Status;
|
|
}
|
|
|
|
FixupUpdateSequenceArray(MftRecord);
|
|
|
|
// Attribute = FindAttribute(MftRecord, AttributeBitmap, 0);
|
|
|
|
/* Get number of file records*/
|
|
n = AttributeDataLength(FindAttribute(MftRecord, AttributeData, 0)) / BytesPerFileRecord;
|
|
|
|
FileRecord = ExAllocatePoolWithTag(NonPagedPool,
|
|
BytesPerFileRecord,
|
|
TAG_NTFS);
|
|
if (FileRecord == NULL)
|
|
{
|
|
ExFreePool(MftRecord);
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
/* Enumerate MFT Records */
|
|
DPRINT("Enumerate MFT records\n");
|
|
for (i = 0; i < n; i++)
|
|
{
|
|
ReadFileRecord(Vcb,
|
|
i,
|
|
FileRecord,
|
|
MftRecord);
|
|
|
|
if (FileRecord->Ntfs.Type == NRH_FILE_TYPE &&
|
|
(FileRecord->Flags & FRH_IN_USE))
|
|
{
|
|
DPRINT("\nFile %lu\n\n", i);
|
|
|
|
/* Enumerate attributtes */
|
|
NtfsDumpFileAttributes (FileRecord);
|
|
DbgPrint("\n\n");
|
|
}
|
|
}
|
|
|
|
ExFreePool(FileRecord);
|
|
ExFreePool(MftRecord);
|
|
|
|
return Status;
|
|
}
|
|
|
|
|
|
PATTRIBUTE
|
|
FindAttribute(PFILE_RECORD_HEADER FileRecord,
|
|
ATTRIBUTE_TYPE Type,
|
|
PWSTR name)
|
|
{
|
|
PATTRIBUTE Attribute;
|
|
|
|
UNREFERENCED_PARAMETER(name);
|
|
|
|
Attribute = (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
|
|
while (Attribute < (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
|
|
Attribute->AttributeType != (ATTRIBUTE_TYPE)-1)
|
|
{
|
|
if (Attribute->AttributeType == Type)
|
|
{
|
|
return Attribute;
|
|
}
|
|
|
|
Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
ULONG
|
|
AttributeAllocatedLength(PATTRIBUTE Attribute)
|
|
{
|
|
if (Attribute->Nonresident)
|
|
{
|
|
return ((PNONRESIDENT_ATTRIBUTE)Attribute)->AllocatedSize;
|
|
}
|
|
|
|
return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
|
|
}
|
|
|
|
|
|
ULONG
|
|
AttributeDataLength(PATTRIBUTE Attribute)
|
|
{
|
|
if (Attribute->Nonresident)
|
|
{
|
|
return ((PNONRESIDENT_ATTRIBUTE)Attribute)->DataSize;
|
|
}
|
|
|
|
return ((PRESIDENT_ATTRIBUTE)Attribute)->ValueLength;
|
|
}
|
|
|
|
|
|
VOID
|
|
ReadAttribute(PATTRIBUTE attr,
|
|
PVOID buffer,
|
|
PDEVICE_EXTENSION Vcb,
|
|
PDEVICE_OBJECT DeviceObject)
|
|
{
|
|
PNONRESIDENT_ATTRIBUTE NresAttr = (PNONRESIDENT_ATTRIBUTE)attr;
|
|
|
|
UNREFERENCED_PARAMETER(DeviceObject);
|
|
|
|
if (attr->Nonresident == FALSE)
|
|
{
|
|
memcpy(buffer,
|
|
(PVOID)((ULONG_PTR)attr + ((PRESIDENT_ATTRIBUTE)attr)->ValueOffset),
|
|
((PRESIDENT_ATTRIBUTE)attr)->ValueLength);
|
|
}
|
|
|
|
ReadExternalAttribute(Vcb,
|
|
NresAttr,
|
|
0,
|
|
(ULONG)(NresAttr->LastVcn) + 1,
|
|
buffer);
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ReadFileRecord(PDEVICE_EXTENSION Vcb,
|
|
ULONG index,
|
|
PFILE_RECORD_HEADER file,
|
|
PFILE_RECORD_HEADER Mft)
|
|
{
|
|
PVOID p;
|
|
ULONG BytesPerFileRecord = Vcb->NtfsInfo.BytesPerFileRecord;
|
|
ULONG clusters = max(BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster, 1);
|
|
ULONGLONG vcn = index * BytesPerFileRecord / Vcb->NtfsInfo.BytesPerCluster;
|
|
LONG m = (Vcb->NtfsInfo.BytesPerCluster / BytesPerFileRecord) - 1;
|
|
ULONG n = m > 0 ? (index & m) : 0;
|
|
|
|
p = ExAllocatePoolWithTag(NonPagedPool,
|
|
clusters * Vcb->NtfsInfo.BytesPerCluster,
|
|
TAG_NTFS);
|
|
|
|
ReadVCN (Vcb, Mft, AttributeData, vcn, clusters, p);
|
|
|
|
memcpy(file,
|
|
(PVOID)((ULONG_PTR)p + n * BytesPerFileRecord),
|
|
BytesPerFileRecord);
|
|
|
|
ExFreePool(p);
|
|
|
|
FixupUpdateSequenceArray(file);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
|
|
VOID
|
|
ReadExternalAttribute(PDEVICE_EXTENSION Vcb,
|
|
PNONRESIDENT_ATTRIBUTE NresAttr,
|
|
ULONGLONG vcn,
|
|
ULONG count,
|
|
PVOID buffer)
|
|
{
|
|
ULONGLONG lcn;
|
|
ULONGLONG runcount;
|
|
ULONG readcount;
|
|
ULONG left;
|
|
ULONG n;
|
|
|
|
PUCHAR bytes = (PUCHAR)buffer;
|
|
|
|
for (left = count; left > 0; left -= readcount)
|
|
{
|
|
FindRun(NresAttr, vcn, &lcn, &runcount);
|
|
|
|
// readcount = (ULONG)(__min(runcount, left));
|
|
readcount = (ULONG)min(runcount, left);
|
|
|
|
|
|
n = readcount * Vcb->NtfsInfo.BytesPerCluster;
|
|
|
|
if (lcn == 0)
|
|
memset(bytes, 0, n);
|
|
else
|
|
ReadLCN(Vcb, lcn, readcount, bytes);
|
|
|
|
vcn += readcount;
|
|
bytes += n;
|
|
}
|
|
}
|
|
|
|
|
|
VOID
|
|
ReadVCN(PDEVICE_EXTENSION Vcb,
|
|
PFILE_RECORD_HEADER file,
|
|
ATTRIBUTE_TYPE type,
|
|
ULONGLONG vcn,
|
|
ULONG count,
|
|
PVOID buffer)
|
|
{
|
|
PNONRESIDENT_ATTRIBUTE NresAttr;
|
|
PATTRIBUTE attr;
|
|
|
|
attr = FindAttribute(file, type, 0);
|
|
|
|
NresAttr = (PNONRESIDENT_ATTRIBUTE) attr;
|
|
|
|
if (NresAttr == 0 || (vcn < NresAttr->StartVcn ||vcn > NresAttr->LastVcn))
|
|
{
|
|
// PATTRIBUTE attrList = FindAttribute(file,AttributeAttributeList,0);
|
|
DbgPrint("Exeption \n");
|
|
// KeDebugCheck(0);
|
|
}
|
|
|
|
ReadExternalAttribute(Vcb, NresAttr, vcn, count, buffer);
|
|
}
|
|
|
|
|
|
#if 0
|
|
BOOL bitset(PUCHAR bitmap, ULONG i)
|
|
{
|
|
return (bitmap[i>>3] & (1 << (i & 7))) !=0;
|
|
}
|
|
#endif
|
|
|
|
|
|
VOID
|
|
FixupUpdateSequenceArray(PFILE_RECORD_HEADER file)
|
|
{
|
|
PUSHORT usa = (PUSHORT)((ULONG_PTR)file + file->Ntfs.UsaOffset);
|
|
PUSHORT sector = (PUSHORT)file;
|
|
ULONG i;
|
|
|
|
for (i = 1; i < file->Ntfs.UsaCount; i++)
|
|
{
|
|
sector[255] = usa[i];
|
|
sector += 256;
|
|
}
|
|
}
|
|
|
|
|
|
NTSTATUS
|
|
ReadLCN(PDEVICE_EXTENSION Vcb,
|
|
ULONGLONG lcn,
|
|
ULONG count,
|
|
PVOID buffer)
|
|
{
|
|
LARGE_INTEGER DiskSector;
|
|
|
|
DiskSector.QuadPart = lcn;
|
|
|
|
return NtfsReadSectors(Vcb->StorageDevice,
|
|
DiskSector.u.LowPart * Vcb->NtfsInfo.SectorsPerCluster,
|
|
count * Vcb->NtfsInfo.SectorsPerCluster,
|
|
Vcb->NtfsInfo.BytesPerSector,
|
|
buffer,
|
|
FALSE);
|
|
}
|
|
|
|
/* EOF */
|