ntfs.c
来自「一个类似windows」· C语言 代码 · 共 733 行 · 第 1/2 页
C
733 行
UCHAR EntryFileNameLength;
UCHAR i;
EntryFileName = IndexEntry->FileName.FileName;
EntryFileNameLength = IndexEntry->FileName.FileNameLength;
#ifdef DEBUG
NtfsPrintFile(IndexEntry);
#endif
if (strlen(FileName) != EntryFileNameLength)
return FALSE;
/* Do case-sensitive compares for Posix file names. */
if (IndexEntry->FileName.FileNameType == NTFS_FILE_NAME_POSIX)
{
for (i = 0; i < EntryFileNameLength; i++)
if (EntryFileName[i] != FileName[i])
return FALSE;
}
else
{
for (i = 0; i < EntryFileNameLength; i++)
if (tolower(EntryFileName[i]) != tolower(FileName[i]))
return FALSE;
}
return TRUE;
}
static BOOL NtfsFindMftRecord(ULONG MFTIndex, PCHAR FileName, ULONG *OutMFTIndex)
{
PNTFS_MFT_RECORD MftRecord;
ULONG Magic;
NTFS_ATTR_CONTEXT IndexRootCtx;
NTFS_ATTR_CONTEXT IndexBitmapCtx;
NTFS_ATTR_CONTEXT IndexAllocationCtx;
PNTFS_INDEX_ROOT IndexRoot;
ULONGLONG BitmapDataSize;
ULONGLONG IndexAllocationSize;
PCHAR BitmapData;
PCHAR IndexRecord;
PNTFS_INDEX_ENTRY IndexEntry, IndexEntryEnd;
ULONG RecordOffset;
ULONG IndexBlockSize;
MftRecord = MmAllocateMemory(NtfsMftRecordSize);
if (MftRecord == NULL)
{
return FALSE;
}
if (NtfsReadMftRecord(MFTIndex, MftRecord))
{
Magic = MftRecord->Magic;
if (!NtfsFindAttribute(&IndexRootCtx, MftRecord, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30"))
{
MmFreeMemory(MftRecord);
return FALSE;
}
IndexRecord = MmAllocateMemory(NtfsIndexRecordSize);
if (IndexRecord == NULL)
{
MmFreeMemory(MftRecord);
return FALSE;
}
NtfsReadAttribute(&IndexRootCtx, 0, IndexRecord, NtfsIndexRecordSize);
IndexRoot = (PNTFS_INDEX_ROOT)IndexRecord;
IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)&IndexRoot->IndexHeader + IndexRoot->IndexHeader.EntriesOffset);
/* Index root is always resident. */
IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexRootCtx.Record->Resident.ValueLength);
DbgPrint((DPRINT_FILESYSTEM, "NtfsIndexRecordSize: %x IndexBlockSize: %x\n", NtfsIndexRecordSize, IndexRoot->IndexBlockSize));
while (IndexEntry < IndexEntryEnd &&
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
{
if (NtfsCompareFileName(FileName, IndexEntry))
{
*OutMFTIndex = IndexEntry->Data.Directory.IndexedFile;
MmFreeMemory(IndexRecord);
MmFreeMemory(MftRecord);
return TRUE;
}
IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
}
if (IndexRoot->IndexHeader.Flags & NTFS_LARGE_INDEX)
{
DbgPrint((DPRINT_FILESYSTEM, "Large Index!\n"));
IndexBlockSize = IndexRoot->IndexBlockSize;
if (!NtfsFindAttribute(&IndexBitmapCtx, MftRecord, NTFS_ATTR_TYPE_BITMAP, L"$I30"))
{
DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n"));
MmFreeMemory(MftRecord);
return FALSE;
}
if (IndexBitmapCtx.Record->IsNonResident)
BitmapDataSize = IndexBitmapCtx.Record->NonResident.DataSize;
else
BitmapDataSize = IndexBitmapCtx.Record->Resident.ValueLength;
DbgPrint((DPRINT_FILESYSTEM, "BitmapDataSize: %x\n", BitmapDataSize));
BitmapData = MmAllocateMemory(BitmapDataSize);
if (BitmapData == NULL)
{
MmFreeMemory(IndexRecord);
MmFreeMemory(MftRecord);
return FALSE;
}
NtfsReadAttribute(&IndexBitmapCtx, 0, BitmapData, BitmapDataSize);
if (!NtfsFindAttribute(&IndexAllocationCtx, MftRecord, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30"))
{
DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n"));
MmFreeMemory(BitmapData);
MmFreeMemory(IndexRecord);
MmFreeMemory(MftRecord);
return FALSE;
}
if (IndexAllocationCtx.Record->IsNonResident)
IndexAllocationSize = IndexAllocationCtx.Record->NonResident.DataSize;
else
IndexAllocationSize = IndexAllocationCtx.Record->Resident.ValueLength;
RecordOffset = 0;
for (;;)
{
DbgPrint((DPRINT_FILESYSTEM, "RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize));
for (; RecordOffset < IndexAllocationSize;)
{
UCHAR Bit = 1 << ((RecordOffset / IndexBlockSize) & 7);
ULONG Byte = (RecordOffset / IndexBlockSize) >> 3;
if ((BitmapData[Byte] & Bit))
break;
RecordOffset += IndexBlockSize;
}
if (RecordOffset >= IndexAllocationSize)
{
break;
}
NtfsReadAttribute(&IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
if (!NtfsFixupRecord((PNTFS_RECORD)IndexRecord))
{
break;
}
/* FIXME */
IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(USHORT *)(IndexRecord + 0x18));
IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize);
while (IndexEntry < IndexEntryEnd &&
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
{
if (NtfsCompareFileName(FileName, IndexEntry))
{
DbgPrint((DPRINT_FILESYSTEM, "File found\n"));
*OutMFTIndex = IndexEntry->Data.Directory.IndexedFile;
MmFreeMemory(BitmapData);
MmFreeMemory(IndexRecord);
MmFreeMemory(MftRecord);
return TRUE;
}
IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
}
RecordOffset += IndexBlockSize;
}
MmFreeMemory(BitmapData);
}
MmFreeMemory(IndexRecord);
}
else
{
DbgPrint((DPRINT_FILESYSTEM, "Can't read MFT record\n"));
}
MmFreeMemory(MftRecord);
return FALSE;
}
static BOOL NtfsLookupFile(PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONTEXT DataContext)
{
ULONG NumberOfPathParts;
CHAR PathPart[261];
ULONG CurrentMFTIndex;
UCHAR i;
DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile() FileName = %s\n", FileName));
CurrentMFTIndex = NTFS_FILE_ROOT;
NumberOfPathParts = FsGetNumPathParts(FileName);
for (i = 0; i < NumberOfPathParts; i++)
{
FsGetFirstNameFromPath(PathPart, FileName);
for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
;
FileName++;
DbgPrint((DPRINT_FILESYSTEM, "- Lookup: %s\n", PathPart));
if (!NtfsFindMftRecord(CurrentMFTIndex, PathPart, &CurrentMFTIndex))
{
DbgPrint((DPRINT_FILESYSTEM, "- Failed\n"));
return FALSE;
}
DbgPrint((DPRINT_FILESYSTEM, "- Lookup: %x\n", CurrentMFTIndex));
}
if (!NtfsReadMftRecord(CurrentMFTIndex, MftRecord))
{
DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile: Can't read MFT record\n"));
return FALSE;
}
if (!NtfsFindAttribute(DataContext, MftRecord, NTFS_ATTR_TYPE_DATA, L""))
{
DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile: Can't find data attribute\n"));
return FALSE;
}
return TRUE;
}
BOOL NtfsOpenVolume(ULONG DriveNumber, ULONG VolumeStartSector)
{
NtfsBootSector = (PNTFS_BOOTSECTOR)DISKREADBUFFER;
DbgPrint((DPRINT_FILESYSTEM, "NtfsOpenVolume() DriveNumber = 0x%x VolumeStartSector = 0x%x\n", DriveNumber, VolumeStartSector));
if (!MachDiskReadLogicalSectors(DriveNumber, VolumeStartSector, 1, (PCHAR)DISKREADBUFFER))
{
FileSystemError("Failed to read the boot sector.");
return FALSE;
}
if (!RtlEqualMemory(NtfsBootSector->SystemId, "NTFS", 4))
{
FileSystemError("Invalid NTFS signature.");
return FALSE;
}
NtfsBootSector = MmAllocateMemory(NtfsBootSector->BytesPerSector);
if (NtfsBootSector == NULL)
{
return FALSE;
}
RtlCopyMemory(NtfsBootSector, (PCHAR)DISKREADBUFFER, ((PNTFS_BOOTSECTOR)DISKREADBUFFER)->BytesPerSector);
NtfsClusterSize = NtfsBootSector->SectorsPerCluster * NtfsBootSector->BytesPerSector;
if (NtfsBootSector->ClustersPerMftRecord > 0)
NtfsMftRecordSize = NtfsBootSector->ClustersPerMftRecord * NtfsClusterSize;
else
NtfsMftRecordSize = 1 << (-NtfsBootSector->ClustersPerMftRecord);
if (NtfsBootSector->ClustersPerIndexRecord > 0)
NtfsIndexRecordSize = NtfsBootSector->ClustersPerIndexRecord * NtfsClusterSize;
else
NtfsIndexRecordSize = 1 << (-NtfsBootSector->ClustersPerIndexRecord);
DbgPrint((DPRINT_FILESYSTEM, "NtfsClusterSize: 0x%x\n", NtfsClusterSize));
DbgPrint((DPRINT_FILESYSTEM, "ClustersPerMftRecord: %d\n", NtfsBootSector->ClustersPerMftRecord));
DbgPrint((DPRINT_FILESYSTEM, "ClustersPerIndexRecord: %d\n", NtfsBootSector->ClustersPerIndexRecord));
DbgPrint((DPRINT_FILESYSTEM, "NtfsMftRecordSize: 0x%x\n", NtfsMftRecordSize));
DbgPrint((DPRINT_FILESYSTEM, "NtfsIndexRecordSize: 0x%x\n", NtfsIndexRecordSize));
NtfsDriveNumber = DriveNumber;
NtfsSectorOfClusterZero = VolumeStartSector;
DbgPrint((DPRINT_FILESYSTEM, "Reading MFT index...\n"));
if (!MachDiskReadLogicalSectors(DriveNumber,
NtfsSectorOfClusterZero +
(NtfsBootSector->MftLocation * NtfsBootSector->SectorsPerCluster),
NtfsMftRecordSize / NtfsBootSector->BytesPerSector, (PCHAR)DISKREADBUFFER))
{
FileSystemError("Failed to read the Master File Table record.");
return FALSE;
}
NtfsMasterFileTable = MmAllocateMemory(NtfsMftRecordSize);
if (NtfsMasterFileTable == NULL)
{
MmFreeMemory(NtfsBootSector);
return FALSE;
}
RtlCopyMemory(NtfsMasterFileTable, (PCHAR)DISKREADBUFFER, NtfsMftRecordSize);
DbgPrint((DPRINT_FILESYSTEM, "Searching for DATA attribute...\n"));
if (!NtfsFindAttribute(&NtfsMFTContext, NtfsMasterFileTable, NTFS_ATTR_TYPE_DATA, L""))
{
FileSystemError("Can't find data attribute for Master File Table.");
return FALSE;
}
return TRUE;
}
FILE* NtfsOpenFile(PCSTR FileName)
{
PNTFS_FILE_HANDLE FileHandle;
PNTFS_MFT_RECORD MftRecord;
FileHandle = MmAllocateMemory(sizeof(NTFS_FILE_HANDLE) + NtfsMftRecordSize);
if (FileHandle == NULL)
{
return NULL;
}
MftRecord = (PNTFS_MFT_RECORD)(FileHandle + 1);
if (!NtfsLookupFile(FileName, MftRecord, &FileHandle->DataContext))
{
MmFreeMemory(FileHandle);
return NULL;
}
FileHandle->Offset = 0;
return (FILE*)FileHandle;
}
BOOL NtfsReadFile(FILE *File, ULONG BytesToRead, ULONG* BytesRead, PVOID Buffer)
{
PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File;
ULONGLONG BytesRead64;
BytesRead64 = NtfsReadAttribute(&FileHandle->DataContext, FileHandle->Offset, Buffer, BytesToRead);
if (BytesRead64)
{
*BytesRead = (ULONG)BytesRead64;
FileHandle->Offset += BytesRead64;
return TRUE;
}
return FALSE;
}
ULONG NtfsGetFileSize(FILE *File)
{
PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File;
if (FileHandle->DataContext.Record->IsNonResident)
return (ULONG)FileHandle->DataContext.Record->NonResident.DataSize;
else
return (ULONG)FileHandle->DataContext.Record->Resident.ValueLength;
}
VOID NtfsSetFilePointer(FILE *File, ULONG NewFilePointer)
{
PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File;
FileHandle->Offset = NewFilePointer;
}
ULONG NtfsGetFilePointer(FILE *File)
{
PNTFS_FILE_HANDLE FileHandle = (PNTFS_FILE_HANDLE)File;
return FileHandle->Offset;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?