📄 ntfs.cpp
字号:
/*
Command Line Tools for DOS(V32) Prgram v0.1.0 write by 孙宝建
6-20-2004
(暂停)
*/
#include "stdafx.h"
#ifndef __commcpp_h
#include "commcpp.hpp"
#endif
#ifndef _INCLUDE_SLIB_FUNC_HPP_INCLUDE
#include "slib_func.hpp"
#endif
#ifndef _INCLUDE_SLIB_ERROR_HPP_INCLUDE
#include "slib_error.hpp"
#endif
#ifndef _INT13_H
#include "int13.hpp"
#endif
#ifndef _NTFS_H
#include "ntfs.hpp"
#endif
using namespace SLib;
SLIB_DEFINE_FILE_NAME_VARIABLE
#ifdef _WIN32
ULONG CNtfs::RunLength(PUCHAR run)
{
return (*run&0x0f)+((*run>>4)&0x0f)+1;
}
LONGLONG CNtfs::RunLCN(PUCHAR run)
{
UCHAR n1=*run&0x0f;
UCHAR n2=(*run>>4)&0x0f;
LONGLONG lcn=n2==0?0:CHAR (run[n1+n2]);
for(LONG i=n1+n2-1;i>n1;i--)
lcn=(lcn<<8)+run[i];
return lcn;
}
ULONGLONG CNtfs::RunCount(PUCHAR run)
{
UCHAR n=*run&0x0f;
ULONGLONG count=0;
for(ULONG i=n;i>0;i--)
count=(count<<8)+run[i];
return count;
}
BOOL CNtfs::FindRun(PNONRESIDENT_ATTRIBUTE attr,ULONGLONG vcn,PULONGLONG lcn,PULONGLONG count)
{
if(vcn<attr->LowVcn||vcn>attr->HighVcn)return FALSE;
*lcn=0;
ULONGLONG base=attr->LowVcn;
for(PUCHAR run=PUCHAR (Padd(attr,attr->RunArrayOffset));*run!=0;run+=RunLength(run))
{
*lcn+=RunLCN(run);
*count=RunCount(run);
if(base<=vcn&&vcn<base+*count)
{
*lcn=RunLCN(run)==0?0:*lcn+vcn-base;
*count-=ULONG(vcn-base);
return TRUE;
}
else
base+=*count;
}
return FALSE;
}
PATTRIBUTE CNtfs::FindAttribute(PFILE_RECORD_HEADER file,ATTRIBUTE_TYPE type,PWSTR name)
{
for(PATTRIBUTE attr=PATTRIBUTE(Padd(file,file->AttributesOffset));
attr->AttributeType!=-1;
attr=Padd(attr,attr->Length))
{
if(attr->AttributeType==type)
{
if(name==0&&attr->NameLength==0)
return attr;
if( name!=0
&&wcslen(name)==attr->NameLength
&&wcsicmp(name,PWSTR(Padd(attr,attr->NameOffset)))==0
)
return attr;
}
}
return 0;
}
VOID CNtfs::FixupUpdateSequenceArray(PFILE_RECORD_HEADER file)
{
PUSHORT usa=PUSHORT(Padd(file,file->Ntfs.UsaOffset));
PUSHORT sector=PUSHORT(file);
for(ULONG i=1;i<file->Ntfs.UsaCount;i++)
{
sector[255]=usa[i];
sector+=256;
}
}
BOOL CNtfs::ReadSector(ULONGLONG sector,ULONG count,PVOID buffer)
{
/* ULARGE_INTEGER offset;
OVERLAPPED overlap={0};
ULONG n;
offset.QuadPart=sector*m_BootB.BytesPerSector;
overlap.Offset=offset.LowPart;
overlap.OffsetHigh=offset.HighPart;
ReadFile(hVolume,buffer,count*m_BootB.BytesPerSector,&n,&overlap);
*/
return m_pInt13->ReadSector(sector+m_BootBlockPos,count, buffer);
}
BOOL CNtfs::WriteSector(ULONGLONG sector,ULONG count,PVOID buffer)
{
/* ULARGE_INTEGER offset;
OVERLAPPED overlap={0};
ULONG n;
offset.QuadPart=sector*m_BootB.BytesPerSector;
overlap.Offset=offset.LowPart;
overlap.OffsetHigh=offset.HighPart;
ReadFile(hVolume,buffer,count*m_BootB.BytesPerSector,&n,&overlap);
*/
return m_pInt13->WriteSector(sector+m_BootBlockPos,count,buffer);
}
VOID CNtfs::ReadLCN (ULONGLONG lcn,ULONG count,PVOID buffer)
{
ReadSector(lcn*m_BootB.SectorsPerCluster,
count*m_BootB.SectorsPerCluster,buffer);
}
VOID CNtfs::ReadExternalAttribute(PNONRESIDENT_ATTRIBUTE attr,ULONGLONG vcn,ULONG count,PVOID buffer)
{
ULONGLONG lcn,runcount;
ULONG readcount,left;
PUCHAR bytes=PUCHAR(buffer);
for(left=count;left>0;left-=readcount)
{
FindRun(attr,vcn,&lcn,&runcount);
readcount=ULONG(min(runcount,left));
ULONG n=readcount*m_BootB.BytesPerSector*m_BootB.SectorsPerCluster;
if(lcn==0)
memset(bytes,0,n);
else
ReadLCN(lcn,readcount,bytes);
vcn+=n;
}
}
ULONG CNtfs::AttributeLength(PATTRIBUTE attr)
{
return attr->Nonresident==FALSE?PRESIDENT_ATTRIBUTE (attr)->ValueLength
:ULONG(PNONRESIDENT_ATTRIBUTE(attr)->DataSize);
}
ULONG CNtfs::AttributeLengthAllocated(PATTRIBUTE attr)
{
return attr->Nonresident==FALSE?PRESIDENT_ATTRIBUTE(attr)->ValueLength
:ULONG(PNONRESIDENT_ATTRIBUTE(attr)->AllocatedSize);
}
VOID CNtfs::ReadAttribute(PATTRIBUTE attr,PVOID buffer)
{
if(attr->Nonresident==FALSE)
{
PRESIDENT_ATTRIBUTE rattr=PRESIDENT_ATTRIBUTE (attr);
memcpy(buffer,Padd(rattr,rattr->ValueOffset),rattr->ValueLength);
}
else
{
PNONRESIDENT_ATTRIBUTE nattr=PNONRESIDENT_ATTRIBUTE(attr);
ReadExternalAttribute(nattr,0,ULONG(nattr->HighVcn)+1,buffer);
}
}
VOID CNtfs::ReadVCN(PFILE_RECORD_HEADER file,ATTRIBUTE_TYPE type
,ULONGLONG vcn ,ULONG count,PVOID buffer)
{
PNONRESIDENT_ATTRIBUTE attr
=PNONRESIDENT_ATTRIBUTE(FindAttribute(file,type,0));
if(attr==0||(vcn<attr->LowVcn
||vcn>attr->HighVcn))
{
PATTRIBUTE attrlist=FindAttribute(file,AttributeAttributeList,0);
DebugBreak();
}
ReadExternalAttribute(attr,vcn,count,buffer);
}
VOID CNtfs::ReadFileRecord(ULONG index,PFILE_RECORD_HEADER file)
{
ULONG clusters=m_BootB.ClustersPerFileRecord;
if(clusters>0x80)
clusters=1;
PUCHAR p=new UCHAR [m_BootB.BytesPerSector*m_BootB.SectorsPerCluster*clusters];
ULONGLONG vcn=ULONGLONG(index)*BytesPerFileRecord
/m_BootB.BytesPerSector
/m_BootB.SectorsPerCluster;
ReadVCN(MFT,AttributeData,vcn,clusters,p);
LONG m=(m_BootB.SectorsPerCluster*m_BootB.BytesPerSector/BytesPerFileRecord);
delete []p;
FixupUpdateSequenceArray(file);
}
BOOL CNtfs::LoadMFT(DWORD64 bootBlockSector)
{
// if(!ReadSector(bootBlockSector,1,&m_BootB))
// return FALSE;
BytesPerFileRecord=m_BootB.ClustersPerFileRecord<0x80
?m_BootB.ClustersPerFileRecord*m_BootB.BytesPerSector*m_BootB.SectorsPerCluster
// :i<<(0x100-BytesPerFileRecord);
:1 << (0x100-BytesPerFileRecord);
MFT=PFILE_RECORD_HEADER (new UCHAR[BytesPerFileRecord]);
if( !ReadSector(m_BootB.MftStartLcn*m_BootB.SectorsPerCluster
,BytesPerFileRecord/m_BootB.BytesPerSector,MFT) )
return FALSE;
//FixupUpdateSequenceArray(MFT);
return TRUE;
}
BOOL CNtfs::BitSet(PUCHAR bitmap,ULONG i)
{
return (bitmap[i>>3]&&(i<<(i&7)))!=0;
}
VOID CNtfs::FindDeleted()
{
PATTRIBUTE attr=FindAttribute(MFT,AttributeBitmap,0);
PUCHAR bitmap=new UCHAR[AttributeLengthAllocated(attr)];
ReadAttribute(attr,bitmap);
ULONG n=AttributeLength(FindAttribute(MFT,AttributeBitmap,0));
PFILE_RECORD_HEADER file=PFILE_RECORD_HEADER(new UCHAR[BytesPerFileRecord]);
for(ULONG i=0;i<n;i++)
{
if(BitSet(bitmap,i))
continue;
ReadFileRecord(i,file);
if(file->Ntfs.Type=='ELIF'
&&(file->Flags&1)==0)
{
attr=FindAttribute(file,AttributeFileName,0);
if(attr==0)
continue;
PFILENAME_ATTRIBUTE name=PFILENAME_ATTRIBUTE (
Padd(attr,PRESIDENT_ATTRIBUTE( attr)->ValueOffset));
wostringstream ostr;
ostr.fill(L'0');
ostr.setf(ios_base::right,ios_base::adjustfield);
ostr.setf(ios_base::uppercase| ios_base::showbase);
ostr.setf(ios_base::hex,ios_base::basefield);
ostr<<setw(10) << i << dec <<unsigned int (name->NameLength)<<name->Name;
wcout<<ostr.str();
}
}
}
#endif //_WIN32
#ifdef _WIN32
VOID CNtfs::DumpData(ULONG index,PCSTR filename)
{
PFILE_RECORD_HEADER file=PFILE_RECORD_HEADER(new UCHAR[BytesPerFileRecord]);
ULONG n;
ReadFileRecord(index,file);
if(file->Ntfs.Type!='ELIF')
return ;
PATTRIBUTE attr=FindAttribute(file,AttributeData,0);
if(attr==0)
return;
PUCHAR buf=new UCHAR[AttributeLengthAllocated(attr)];
ReadAttribute(attr,buf);
HANDLE hFile=CreateFile(filename,GENERIC_WRITE,0,0,CREATE_ALWAYS,0,0);
WriteFile(hFile,buf,AttributeLength(attr),&n,0);
//
//
delete []buf;
}
#ifndef _WINNT_
#include <winnt.h>
#endif
typedef ULONG NTSTATUS;
extern "C"
{
NTSTATUS NTAPI RtlDecompressBuffer(USHORT CompressionFormat,
PVOID OUtputBuffer,ULONG OutputBufferLength,
PVOID InputBuffer,ULONG InputBufferLength,
PULONG ReturnLength);
}
void CNtfs::DecompressFile(IN tstring compressFile,OUT tstring decompressFile)
{
HANDLE hFile1=CreateFile(compressFile.c_str(),GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,0,0);
HANDLE hFile2=CreateFile(decompressFile.c_str(),GENERIC_WRITE,FILE_SHARE_READ,0,CREATE_ALWAYS,0,0);
ULONG n=GetFileSize(hFile1,0);
HANDLE hMapping1=CreateFileMapping(hFile1,0,PAGE_READONLY,0,0,0);
HANDLE hMapping2=CreateFileMapping(hFile2,0,PAGE_READWRITE,0,n,0);
PCHAR p=PCHAR(MapViewOfFileEx(hMapping1,FILE_MAP_READ,0,0,0,0));
PCHAR q=PCHAR(MapViewOfFileEx(hMapping2,FILE_MAP_WRITE,0,0,0,0));
//for(ULONG m,i=0;i<n;i+=m)
// RtlDecompressBuffer(COMPRESSION_FORMAT_LZNT1,q++,n-i,p+i,n+i,&m); //ntddk.h
}
#endif //_WIN32
CNtfs::CNtfs(CInt13 *pInt13,CSError *perror) : m_pInt13(pInt13),m_pError(perror)
{
SVERIFY_ARGUMENTS(pInt13!=NULL);
}
CNtfs::~CNtfs(void)
{
}
tstring CNtfs::BootBToString(void)
{
ostringstream ostr;
ostr.fill('0');
ostr.setf(ios_base::right,ios_base::adjustfield);
ostr.setf(ios_base::uppercase| ios_base::showbase);
ostr.setf(ios_base::hex,ios_base::basefield);
ostr<< "Format[8]: \t" << (char*) m_BootB.Format << endl
<< "BytesPerSector: \t" << setw(6) << m_BootB.BytesPerSector << endl
<< "SectorsPerCluster: \t" << setw(4) <<(unsigned short)m_BootB.SectorsPerCluster << endl
<< "BootSectors: \t" << setw(6) << m_BootB.BootSectors << endl
<< "Mbz1: \t" << setw(4) << m_BootB.Mbz1 << endl
<< "Mbz2: \t" << setw(6) << m_BootB.Mbz2 << endl
<< "Reserved1: \t" << setw(6) << m_BootB.Reserved1 << endl
<< "MediaType: \t" << setw(4) <<(unsigned short)m_BootB.MediaType << endl
<< "Mbz3: \t" << setw(6) << m_BootB.Mbz3 << endl
<< "SectorsPerTrack: \t" << setw(6) << m_BootB.SectorsPerTrack << endl
<< "NmberOfheads: \t" << setw(6) << m_BootB.NmberOfheads << endl
<< "PartitionOffset: \t" << setw(10) << m_BootB.PartitionOffset << endl
<< "dwMbzTotalSectors: \t" << setw(18) << m_BootB.dwMbzTotalSectors << endl
<< "Mbz4: \t" << setw(10) << m_BootB.Mbz4 << endl
<< "TotalSectors: \t" << setw(18) << m_BootB.TotalSectors << endl
<< "MftStartLcn: \t" << setw(18) << m_BootB.MftStartLcn << endl
<< "Mft2StartLcn: \t" << setw(18) << m_BootB.Mft2StartLcn << endl
<< "ClustersPerFileRecord: \t" << setw(10) << m_BootB.ClustersPerFileRecord << endl
<< "ClustersPerIndexBlock: \t" << setw(10) << m_BootB.ClustersPerIndexBlock << endl
<< "VolumeSerialNumber: \t" << setw(18) << m_BootB.VolumeSerialNumber << endl
<< "BootSignature: \t" << setw(6) << m_BootB.BootSignature << endl
<< endl;
return ostr.str();
}
BOOL CNtfs::LoadBootBlock(DWORD64 bootBlockSector)
{
m_BootBlockPos=bootBlockSector;
// return m_pInt13->ReadSector(bootBlockSector,1,&m_BootB);
if(m_pInt13->ReadSector(bootBlockSector,1,&m_BootB) )
{
//return LoadMFT(bootBlockSector);
return TRUE;
}
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -