mirror of
https://github.com/reactos/reactos.git
synced 2025-01-10 16:18:16 +00:00
c424146e2c
svn path=/branches/cmake-bringup/; revision=48236
320 lines
7.2 KiB
C
320 lines
7.2 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>
|
|
|
|
/* GLOBALS *****************************************************************/
|
|
|
|
|
|
/* 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;
|
|
|
|
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;
|
|
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 */
|