- Fixed lots of bugs in NTFS code and added correct update sequence

fixups handling and untested NTFS 3+ sparse file support.

svn path=/trunk/; revision=10467
This commit is contained in:
Filip Navara 2004-08-10 09:28:56 +00:00
parent 99e5dd3e01
commit 5775259453
4 changed files with 140 additions and 80 deletions

View file

@ -1,3 +1,8 @@
Changes in v1.8.22 (21/05/2004) (navaraf)
- Fixed lots of bugs in NTFS code and added correct update sequence
fixups handling and untested NTFS 3+ sparse file support.
Changes in v1.8.21 (21/05/2004) (navaraf) Changes in v1.8.21 (21/05/2004) (navaraf)
- Experimental NTFS reading support with no boot code yet. - Experimental NTFS reading support with no boot code yet.

View file

@ -1,7 +1,4 @@
/* /*
* FreeLoader
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
*
* FreeLoader NTFS support * FreeLoader NTFS support
* Copyright (C) 2004 Filip Navara <xnavara@volny.cz> * Copyright (C) 2004 Filip Navara <xnavara@volny.cz>
* *
@ -25,10 +22,6 @@
* - No support for compressed files. * - No support for compressed files.
* - No attribute list support. * - No attribute list support.
* - May crash on currupted filesystem. * - May crash on currupted filesystem.
*
* Bugs:
* - I encountered file names like 'KERNEL~1.EE' stored on
* the disk. These aren't handled correctly yet.
*/ */
#include <freeldr.h> #include <freeldr.h>
@ -40,7 +33,6 @@
#include <debug.h> #include <debug.h>
#include <cache.h> #include <cache.h>
#define NTFS_DEFS
#include "ntfs.h" #include "ntfs.h"
PNTFS_BOOTSECTOR NtfsBootSector; PNTFS_BOOTSECTOR NtfsBootSector;
@ -56,7 +48,7 @@ PUCHAR NtfsDecodeRun(PUCHAR DataRun, S64 *DataRunOffset, U64 *DataRunLength)
{ {
U8 DataRunOffsetSize; U8 DataRunOffsetSize;
U8 DataRunLengthSize; U8 DataRunLengthSize;
U8 i; S8 i;
DataRunOffsetSize = (*DataRun >> 4) & 0xF; DataRunOffsetSize = (*DataRun >> 4) & 0xF;
DataRunLengthSize = *DataRun & 0xF; DataRunLengthSize = *DataRun & 0xF;
@ -68,16 +60,27 @@ PUCHAR NtfsDecodeRun(PUCHAR DataRun, S64 *DataRunOffset, U64 *DataRunLength)
*DataRunLength += *DataRun << (i << 3); *DataRunLength += *DataRun << (i << 3);
DataRun++; DataRun++;
} }
for (i = 0; i < DataRunOffsetSize; i++)
/* NTFS 3+ sparse files */
if (DataRunOffsetSize == 0)
{ {
*DataRunOffset += *DataRun << (i << 3); *DataRunOffset = -1;
DataRun++; }
else
{
for (i = 0; i < DataRunOffsetSize - 1; i++)
{
*DataRunOffset += *DataRun << (i << 3);
DataRun++;
}
/* The last byte contains sign so we must process it different way. */
*DataRunOffset = ((S8)(*(DataRun++)) << (i << 3)) + *DataRunOffset;
} }
DbgPrint((DPRINT_FILESYSTEM, "DataRunOffsetSize: %x\n", DataRunOffsetSize)); DbgPrint((DPRINT_FILESYSTEM, "DataRunOffsetSize: %x\n", DataRunOffsetSize));
DbgPrint((DPRINT_FILESYSTEM, "DataRunLengthSize: %x\n", DataRunLengthSize)); DbgPrint((DPRINT_FILESYSTEM, "DataRunLengthSize: %x\n", DataRunLengthSize));
DbgPrint((DPRINT_FILESYSTEM, "DataRunOffset: %x\n", DataRunOffset)); DbgPrint((DPRINT_FILESYSTEM, "DataRunOffset: %x\n", *DataRunOffset));
DbgPrint((DPRINT_FILESYSTEM, "DataRunLength: %x\n", DataRunLength)); DbgPrint((DPRINT_FILESYSTEM, "DataRunLength: %x\n", *DataRunLength));
return DataRun; return DataRun;
} }
@ -97,7 +100,7 @@ BOOL NtfsFindAttribute(PNTFS_ATTR_CONTEXT Context, PNTFS_MFT_RECORD MftRecord, U
while (AttrRecord < AttrRecordEnd) while (AttrRecord < AttrRecordEnd)
{ {
if (AttrRecord->Type == ATTR_TYPE_END) if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
break; break;
if (AttrRecord->Type == Type) if (AttrRecord->Type == Type)
@ -117,6 +120,7 @@ BOOL NtfsFindAttribute(PNTFS_ATTR_CONTEXT Context, PNTFS_MFT_RECORD MftRecord, U
Context->CacheRun = (PUCHAR)Context->Record + Context->Record->NonResident.MappingPairsOffset; Context->CacheRun = (PUCHAR)Context->Record + Context->Record->NonResident.MappingPairsOffset;
Context->CacheRunOffset = 0; Context->CacheRunOffset = 0;
Context->CacheRun = NtfsDecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength); Context->CacheRun = NtfsDecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength);
Context->CacheRunLength = DataRunLength;
if (DataRunOffset != -1) if (DataRunOffset != -1)
{ {
/* Normal run. */ /* Normal run. */
@ -147,6 +151,9 @@ BOOL NtfsDiskRead(U64 Offset, U64 Length, PCHAR Buffer)
{ {
U16 ReadLength; U16 ReadLength;
DbgPrint((DPRINT_FILESYSTEM, "NtfsDiskRead - Offset: %I64d Length: %I64d\n", Offset, Length));
RtlZeroMemory((PCHAR)DISKREADBUFFER, 0x1000);
/* I. Read partial first sector if needed */ /* I. Read partial first sector if needed */
if (Offset % NtfsBootSector->BytesPerSector) if (Offset % NtfsBootSector->BytesPerSector)
{ {
@ -216,6 +223,7 @@ U64 NtfsReadAttribute(PNTFS_ATTR_CONTEXT Context, U64 Offset, PCHAR Buffer, U64
DataRun = Context->CacheRun; DataRun = Context->CacheRun;
LastLCN = Context->CacheRunLastLCN; LastLCN = Context->CacheRunLastLCN;
DataRunStartLCN = Context->CacheRunStartLCN; DataRunStartLCN = Context->CacheRunStartLCN;
DataRunLength = Context->CacheRunLength;
CurrentOffset = Context->CacheRunCurrentOffset; CurrentOffset = Context->CacheRunCurrentOffset;
} }
else else
@ -239,6 +247,8 @@ U64 NtfsReadAttribute(PNTFS_ATTR_CONTEXT Context, U64 Offset, PCHAR Buffer, U64
DataRunStartLCN = -1; DataRunStartLCN = -1;
} }
DbgPrint((DPRINT_FILESYSTEM, "YYY - %I64x\n", DataRunStartLCN));
if (Offset >= CurrentOffset && if (Offset >= CurrentOffset &&
Offset < CurrentOffset + (DataRunLength * NtfsClusterSize)) Offset < CurrentOffset + (DataRunLength * NtfsClusterSize))
{ {
@ -270,6 +280,10 @@ U64 NtfsReadAttribute(PNTFS_ATTR_CONTEXT Context, U64 Offset, PCHAR Buffer, U64
Buffer += ReadLength; Buffer += ReadLength;
AlreadyRead += ReadLength; AlreadyRead += ReadLength;
/* We finished this request, but there still data in this data run. */
if (Length == 0 && ReadLength != DataRunLength * NtfsClusterSize)
break;
/* /*
* Go to next run in the list. * Go to next run in the list.
*/ */
@ -294,15 +308,47 @@ U64 NtfsReadAttribute(PNTFS_ATTR_CONTEXT Context, U64 Offset, PCHAR Buffer, U64
Context->CacheRun = DataRun; Context->CacheRun = DataRun;
Context->CacheRunOffset = Offset + AlreadyRead; Context->CacheRunOffset = Offset + AlreadyRead;
Context->CacheRunStartLCN = DataRunStartLCN; Context->CacheRunStartLCN = DataRunStartLCN;
Context->CacheRunLength = DataRunLength;
Context->CacheRunLastLCN = LastLCN; Context->CacheRunLastLCN = LastLCN;
Context->CacheRunCurrentOffset = CurrentOffset; Context->CacheRunCurrentOffset = CurrentOffset;
return AlreadyRead; return AlreadyRead;
} }
BOOL NtfsFixupRecord(PNTFS_RECORD Record)
{
U16 *USA;
U16 USANumber;
U16 USACount;
U16 *Block;
USA = (U16*)((PCHAR)Record + Record->USAOffset);
USANumber = *(USA++);
USACount = Record->USACount - 1; /* Exclude the USA Number. */
Block = (U16*)((PCHAR)Record + NtfsBootSector->BytesPerSector - 2);
while (USACount)
{
if (*Block != USANumber)
return FALSE;
*Block = *(USA++);
Block = (U16*)((PCHAR)Block + NtfsBootSector->BytesPerSector);
USACount--;
}
return TRUE;
}
BOOL NtfsReadMftRecord(U32 MFTIndex, PNTFS_MFT_RECORD Buffer) BOOL NtfsReadMftRecord(U32 MFTIndex, PNTFS_MFT_RECORD Buffer)
{ {
return NtfsReadAttribute(&NtfsMFTContext, MFTIndex * NtfsMftRecordSize, (PCHAR)Buffer, NtfsMftRecordSize) == NtfsMftRecordSize; U64 BytesRead;
BytesRead = NtfsReadAttribute(&NtfsMFTContext, MFTIndex * NtfsMftRecordSize, (PCHAR)Buffer, NtfsMftRecordSize);
if (BytesRead != NtfsMftRecordSize)
return FALSE;
/* Apply update sequence array fixups. */
return NtfsFixupRecord((PNTFS_RECORD)Buffer);
} }
#ifdef DEBUG #ifdef DEBUG
@ -341,7 +387,7 @@ BOOL NtfsCompareFileName(PCHAR FileName, PNTFS_INDEX_ENTRY IndexEntry)
return FALSE; return FALSE;
/* Do case-sensitive compares for Posix file names. */ /* Do case-sensitive compares for Posix file names. */
if (IndexEntry->FileName.FileNameType == FILE_NAME_POSIX) if (IndexEntry->FileName.FileNameType == NTFS_FILE_NAME_POSIX)
{ {
for (i = 0; i < EntryFileNameLength; i++) for (i = 0; i < EntryFileNameLength; i++)
if (EntryFileName[i] != FileName[i]) if (EntryFileName[i] != FileName[i])
@ -383,7 +429,7 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex)
{ {
Magic = MftRecord->Magic; Magic = MftRecord->Magic;
if (!NtfsFindAttribute(&IndexRootCtx, MftRecord, ATTR_TYPE_INDEX_ROOT, L"$I30")) if (!NtfsFindAttribute(&IndexRootCtx, MftRecord, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30"))
{ {
MmFreeMemory(MftRecord); MmFreeMemory(MftRecord);
return FALSE; return FALSE;
@ -405,7 +451,7 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex)
DbgPrint((DPRINT_FILESYSTEM, "NtfsIndexRecordSize: %x IndexBlockSize: %x\n", NtfsIndexRecordSize, IndexRoot->IndexBlockSize)); DbgPrint((DPRINT_FILESYSTEM, "NtfsIndexRecordSize: %x IndexBlockSize: %x\n", NtfsIndexRecordSize, IndexRoot->IndexBlockSize));
while (IndexEntry < IndexEntryEnd && while (IndexEntry < IndexEntryEnd &&
!(IndexEntry->Flags & INDEX_ENTRY_END)) !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
{ {
if (NtfsCompareFileName(FileName, IndexEntry)) if (NtfsCompareFileName(FileName, IndexEntry))
{ {
@ -417,13 +463,13 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex)
IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length); IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
} }
if (IndexRoot->IndexHeader.Flags & LARGE_INDEX) if (IndexRoot->IndexHeader.Flags & NTFS_LARGE_INDEX)
{ {
DbgPrint((DPRINT_FILESYSTEM, "Large Index!\n")); DbgPrint((DPRINT_FILESYSTEM, "Large Index!\n"));
IndexBlockSize = IndexRoot->IndexBlockSize; IndexBlockSize = IndexRoot->IndexBlockSize;
if (!NtfsFindAttribute(&IndexBitmapCtx, MftRecord, ATTR_TYPE_BITMAP, L"$I30")) if (!NtfsFindAttribute(&IndexBitmapCtx, MftRecord, NTFS_ATTR_TYPE_BITMAP, L"$I30"))
{ {
DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n")); DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n"));
MmFreeMemory(MftRecord); MmFreeMemory(MftRecord);
@ -443,7 +489,7 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex)
} }
NtfsReadAttribute(&IndexBitmapCtx, 0, BitmapData, BitmapDataSize); NtfsReadAttribute(&IndexBitmapCtx, 0, BitmapData, BitmapDataSize);
if (!NtfsFindAttribute(&IndexAllocationCtx, MftRecord, ATTR_TYPE_INDEX_ALLOCATION, L"$I30")) if (!NtfsFindAttribute(&IndexAllocationCtx, MftRecord, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30"))
{ {
DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n")); DbgPrint((DPRINT_FILESYSTEM, "Corrupted filesystem!\n"));
MmFreeMemory(BitmapData); MmFreeMemory(BitmapData);
@ -463,7 +509,7 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex)
DbgPrint((DPRINT_FILESYSTEM, "RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize)); DbgPrint((DPRINT_FILESYSTEM, "RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize));
for (; RecordOffset < IndexAllocationSize;) for (; RecordOffset < IndexAllocationSize;)
{ {
U8 Bit = 1 << ((RecordOffset / IndexBlockSize) & 3); U8 Bit = 1 << ((RecordOffset / IndexBlockSize) & 7);
U32 Byte = (RecordOffset / IndexBlockSize) >> 3; U32 Byte = (RecordOffset / IndexBlockSize) >> 3;
if ((BitmapData[Byte] & Bit)) if ((BitmapData[Byte] & Bit))
break; break;
@ -471,16 +517,23 @@ BOOL NtfsFindMftRecord(U32 MFTIndex, PCHAR FileName, U32 *OutMFTIndex)
} }
if (RecordOffset >= IndexAllocationSize) if (RecordOffset >= IndexAllocationSize)
{
break; break;
}
NtfsReadAttribute(&IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize); NtfsReadAttribute(&IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
if (!NtfsFixupRecord((PNTFS_RECORD)IndexRecord))
{
break;
}
/* FIXME */ /* FIXME */
IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(U16 *)(IndexRecord + 0x18)); IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(U16 *)(IndexRecord + 0x18));
IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize); IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize);
while (IndexEntry < IndexEntryEnd && while (IndexEntry < IndexEntryEnd &&
!(IndexEntry->Flags & INDEX_ENTRY_END)) !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
{ {
if (NtfsCompareFileName(FileName, IndexEntry)) if (NtfsCompareFileName(FileName, IndexEntry))
{ {
@ -520,7 +573,7 @@ BOOL NtfsLookupFile(PUCHAR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONT
DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile() FileName = %s\n", FileName)); DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile() FileName = %s\n", FileName));
CurrentMFTIndex = FILE_ROOT; CurrentMFTIndex = NTFS_FILE_ROOT;
NumberOfPathParts = FsGetNumPathParts(FileName); NumberOfPathParts = FsGetNumPathParts(FileName);
for (i = 0; i < NumberOfPathParts; i++) for (i = 0; i < NumberOfPathParts; i++)
{ {
@ -545,7 +598,7 @@ BOOL NtfsLookupFile(PUCHAR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_ATTR_CONT
return FALSE; return FALSE;
} }
if (!NtfsFindAttribute(DataContext, MftRecord, ATTR_TYPE_DATA, L"")) if (!NtfsFindAttribute(DataContext, MftRecord, NTFS_ATTR_TYPE_DATA, L""))
{ {
DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile: Can't find data attribute\n")); DbgPrint((DPRINT_FILESYSTEM, "NtfsLookupFile: Can't find data attribute\n"));
return FALSE; return FALSE;
@ -619,7 +672,7 @@ BOOL NtfsOpenVolume(U32 DriveNumber, U32 VolumeStartSector)
RtlCopyMemory(NtfsMasterFileTable, (PCHAR)DISKREADBUFFER, NtfsMftRecordSize); RtlCopyMemory(NtfsMasterFileTable, (PCHAR)DISKREADBUFFER, NtfsMftRecordSize);
DbgPrint((DPRINT_FILESYSTEM, "Searching for DATA attribute...\n")); DbgPrint((DPRINT_FILESYSTEM, "Searching for DATA attribute...\n"));
if (!NtfsFindAttribute(&NtfsMFTContext, NtfsMasterFileTable, ATTR_TYPE_DATA, L"")) if (!NtfsFindAttribute(&NtfsMFTContext, NtfsMasterFileTable, NTFS_ATTR_TYPE_DATA, L""))
{ {
FileSystemError("Can't find data attribute for Master File Table."); FileSystemError("Can't find data attribute for Master File Table.");
return FALSE; return FALSE;

View file

@ -1,7 +1,4 @@
/* /*
* FreeLoader
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
*
* FreeLoader NTFS support * FreeLoader NTFS support
* Copyright (C) 2004 Filip Navara <xnavara@volny.cz> * Copyright (C) 2004 Filip Navara <xnavara@volny.cz>
* *
@ -23,76 +20,80 @@
#ifndef __NTFS_H #ifndef __NTFS_H
#define __NTFS_H #define __NTFS_H
#ifdef NTFS_DEFS #define NTFS_FILE_MFT 0
#define NTFS_FILE_MFTMIRR 1
#define NTFS_FILE_LOGFILE 2
#define NTFS_FILE_VOLUME 3
#define NTFS_FILE_ATTRDEF 4
#define NTFS_FILE_ROOT 5
#define NTFS_FILE_BITMAP 6
#define NTFS_FILE_BOOT 7
#define NTFS_FILE_BADCLUS 8
#define NTFS_FILE_QUOTA 9
#define NTFS_FILE_UPCASE 10
#define FILE_MFT 0 #define NTFS_ATTR_TYPE_STANDARD_INFORMATION 0x10
#define FILE_MFTMIRR 1 #define NTFS_ATTR_TYPE_ATTRIBUTE_LIST 0x20
#define FILE_LOGFILE 2 #define NTFS_ATTR_TYPE_FILENAME 0x30
#define FILE_VOLUME 3 #define NTFS_ATTR_TYPE_SECURITY_DESCRIPTOR 0x50
#define FILE_ATTRDEF 4 #define NTFS_ATTR_TYPE_DATA 0x80
#define FILE_ROOT 5 #define NTFS_ATTR_TYPE_INDEX_ROOT 0x90
#define FILE_BITMAP 6 #define NTFS_ATTR_TYPE_INDEX_ALLOCATION 0xa0
#define FILE_BOOT 7 #define NTFS_ATTR_TYPE_BITMAP 0xb0
#define FILE_BADCLUS 8 #define NTFS_ATTR_TYPE_SYMLINK 0xc0
#define FILE_QUOTA 9 #define NTFS_ATTR_TYPE_END 0xffffffff
#define FILE_UPCASE 10
#define ATTR_TYPE_STANDARD_INFORMATION 0x10 #define NTFS_ATTR_NORMAL 0
#define ATTR_TYPE_ATTRIBUTE_LIST 0x20 #define NTFS_ATTR_COMPRESSED 1
#define ATTR_TYPE_FILENAME 0x30 #define NTFS_ATTR_RESIDENT 2
#define ATTR_TYPE_SECURITY_DESCRIPTOR 0x50 #define NTFS_ATTR_ENCRYPTED 0x4000
#define ATTR_TYPE_DATA 0x80
#define ATTR_TYPE_INDEX_ROOT 0x90
#define ATTR_TYPE_INDEX_ALLOCATION 0xa0
#define ATTR_TYPE_BITMAP 0xb0
#define ATTR_TYPE_SYMLINK 0xc0
#define ATTR_TYPE_END 0xffffffff
#define ATTR_NORMAL 0 #define NTFS_SMALL_INDEX 0
#define ATTR_COMPRESSED 1 #define NTFS_LARGE_INDEX 1
#define ATTR_RESIDENT 2
#define ATTR_ENCRYPTED 0x4000
#define SMALL_INDEX 0 #define NTFS_INDEX_ENTRY_NODE 1
#define LARGE_INDEX 1 #define NTFS_INDEX_ENTRY_END 2
#define INDEX_ENTRY_NODE 1 #define NTFS_FILE_NAME_POSIX 0
#define INDEX_ENTRY_END 2 #define NTFS_FILE_NAME_WIN32 1
#define NTFS_FILE_NAME_DOS 2
#define FILE_NAME_POSIX 0 #define NTFS_FILE_NAME_WIN32_AND_DOS 3
#define FILE_NAME_WIN32 1
#define FILE_NAME_DOS 2
#define FILE_NAME_WIN32_AND_DOS 3
#endif
typedef struct typedef struct
{ {
U8 JumpBoot[3]; // Jump to the boot loader routine U8 JumpBoot[3]; // Jump to the boot loader routine
U8 SystemId[8]; // System Id ("NTFS ") U8 SystemId[8]; // System Id ("NTFS ")
U16 BytesPerSector; // Bytes per sector U16 BytesPerSector; // Bytes per sector
U8 SectorsPerCluster; // Number of sectors in a cluster U8 SectorsPerCluster; // Number of sectors in a cluster
U8 Unused1[7]; U8 Unused1[7];
U8 MediaDescriptor; // Media descriptor byte U8 MediaDescriptor; // Media descriptor byte
U8 Unused2[2]; U8 Unused2[2];
U16 SectorsPerTrack; // Number of sectors in a track U16 SectorsPerTrack; // Number of sectors in a track
U16 NumberOfHeads; // Number of heads on the disk U16 NumberOfHeads; // Number of heads on the disk
U8 Unused3[8]; U8 Unused3[8];
U8 DriveNumber; // Int 0x13 drive number (e.g. 0x80) U8 DriveNumber; // Int 0x13 drive number (e.g. 0x80)
U8 CurrentHead; U8 CurrentHead;
U8 BootSignature; // Extended boot signature (0x80) U8 BootSignature; // Extended boot signature (0x80)
U8 Unused4; U8 Unused4;
U64 VolumeSectorCount; // Number of sectors in the volume U64 VolumeSectorCount; // Number of sectors in the volume
U64 MftLocation; U64 MftLocation;
U64 MftMirrorLocation; U64 MftMirrorLocation;
S8 ClustersPerMftRecord; // Clusters per MFT Record S8 ClustersPerMftRecord; // Clusters per MFT Record
U8 Unused5[3]; U8 Unused5[3];
S8 ClustersPerIndexRecord; // Clusters per Index Record S8 ClustersPerIndexRecord; // Clusters per Index Record
U8 Unused6[3]; U8 Unused6[3];
U64 VolumeSerialNumber; // Volume serial number U64 VolumeSerialNumber; // Volume serial number
U8 BootCodeAndData[430]; // The remainder of the boot sector U8 BootCodeAndData[430]; // The remainder of the boot sector
U16 BootSectorMagic; // 0xAA55 U16 BootSectorMagic; // 0xAA55
} PACKED NTFS_BOOTSECTOR, *PNTFS_BOOTSECTOR; } PACKED NTFS_BOOTSECTOR, *PNTFS_BOOTSECTOR;
typedef struct
{
U32 Magic;
U16 USAOffset; // Offset to the Update Sequence Array from the start of the ntfs record
U16 USACount;
} PACKED NTFS_RECORD, *PNTFS_RECORD;
typedef struct typedef struct
{ {
U32 Magic; U32 Magic;
@ -206,6 +207,7 @@ typedef struct
PUCHAR CacheRun; PUCHAR CacheRun;
U64 CacheRunOffset; U64 CacheRunOffset;
S64 CacheRunStartLCN; S64 CacheRunStartLCN;
U64 CacheRunLength;
S64 CacheRunLastLCN; S64 CacheRunLastLCN;
U64 CacheRunCurrentOffset; U64 CacheRunCurrentOffset;
} NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT; } NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT;

View file

@ -22,7 +22,7 @@
/* just some stuff */ /* just some stuff */
#define VERSION "FreeLoader v1.8.21" #define VERSION "FreeLoader v1.8.22"
#define COPYRIGHT "Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>" #define COPYRIGHT "Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>"
#define AUTHOR_EMAIL "<brianp@sginet.com>" #define AUTHOR_EMAIL "<brianp@sginet.com>"
#define BY_AUTHOR "by Brian Palmer" #define BY_AUTHOR "by Brian Palmer"
@ -36,7 +36,7 @@
// //
#define FREELOADER_MAJOR_VERSION 1 #define FREELOADER_MAJOR_VERSION 1
#define FREELOADER_MINOR_VERSION 8 #define FREELOADER_MINOR_VERSION 8
#define FREELOADER_PATCH_VERSION 21 #define FREELOADER_PATCH_VERSION 22
#ifndef ASM #ifndef ASM