#include"_MFT_READER.h"
void _MFT_READER::LoadMFT()
{
	unsigned __int64 point,i,j,k,temp;
	unsigned __int64 HeaderSize;
	unsigned __int64 offset;
	PFILE_RECORD_HEADER $MFT;
	BytesPerFileRecord = boot_block.ClustersPerFileRecord < 0x80? boot_block.ClustersPerFileRecord* boot_block.SectorsPerCluster* boot_block.BytesPerSector : 1 << (0x100 - boot_block.ClustersPerFileRecord);
	$MFT = PFILE_RECORD_HEADER(new U8[BytesPerFileRecord]);
	if(!$MFT)
	{
		ErrorCode=OUT_OF_MEMORY_ERROR;
		return;
	}
	ReadSector((boot_block.MftStartLcn) * boot_block.SectorsPerCluster,	BytesPerFileRecord / boot_block.BytesPerSector, $MFT);
	for(j=1;j<=*((unsigned short*)((unsigned char*)$MFT+6));j++)
	{
		if(	*((char*)$MFT+j*boot_block.BytesPerSector-2)==
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4)))
			&&
			*((char*)$MFT+j*boot_block.BytesPerSector-1)==
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4))+1)
			)
		{
		*((char*)$MFT+j*boot_block.BytesPerSector-2)=
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4))+2*j);
		*((char*)$MFT+j*boot_block.BytesPerSector-1)=
			*((char*)$MFT+*((unsigned short*)((unsigned char*)$MFT+4))+2*j+1);
		}
	}
	point=*((unsigned short*)((unsigned char*)$MFT+20));//Offset으로 포인터 이동
	while(*((unsigned long*)((unsigned char*)$MFT+point))!=0xFFFFFFFF)
	{
		/*
			*((unsigned char*)MFT+point+9) = Attribute Name Size
			Attribute Header size : Resident=24 / Non-resident=64
		*/
		if(*((unsigned char*)$MFT+point+8))
			HeaderSize=64+*((unsigned char*)$MFT+point+9);
		else
			HeaderSize=24+*((unsigned char*)$MFT+point+9);
		switch(*((unsigned long*)((unsigned char*)$MFT+point)))
		{
		case 0x80://$DATA
			MFT=PFILE_RECORD_HEADER(new U8[*((unsigned __int64*)((unsigned char*)$MFT+point+40))]);
			if(!MFT)
			{
				delete $MFT;
				ErrorCode=OUT_OF_MEMORY_ERROR;
				return;
			}
			i=*(short*)((unsigned char*)$MFT+point+32);
			MFTLength=ReadCluster((unsigned char*)$MFT+point+i,(unsigned char*)MFT);
			break;
		}
		point+=*((unsigned long*)((unsigned char*)$MFT+point+4));
	}
	delete $MFT;
}
void _MFT_READER::ReadSector(U64 sector, U32 count, void* buffer)
{
	ULARGE_INTEGER offset;
	OVERLAPPED overlap = {0};
	U32 n;
	
	offset.QuadPart = sector * boot_block.BytesPerSector;
	overlap.Offset = offset.LowPart; 
	overlap.OffsetHigh = offset.HighPart;
	ReadFile(hVolume, buffer, count * boot_block.BytesPerSector, &n, &overlap);
}
long _MFT_READER::ReadAttribute(FILE* fp, unsigned char* point, long flag)
{
	unsigned char* offset=0;
	SYSTEMTIME time;
	int i,sub_mask;
	sub_mask=1;
	for(i=1;i<25;i++)
	{
		if(sub_mask&flag && *(long*)point==0x10*i)
		{
			if(*((unsigned char*)point+8))
			{
				if(*((unsigned __int64*)((unsigned char*)point+40)))
					offset=(new U8[*((unsigned __int64*)((unsigned char*)point+40))]);
				else
					offset=0;
				if(offset)
					ReadCluster(point+(*(short*)((unsigned char*)point+32)),offset);
			}
			else
			{
				offset=point+24+*((unsigned char*)point+9);
			}
			
		}
		sub_mask<<=1;
	}
	if(!offset)
		return *(long*)((unsigned char*)point+4);
	
	if(!((*(long*)point)&0xFFFFFF00))
	{
		switch(*(long*)point)
		{
			case 0x10://Standard Information
				fprintf(fp,"Attribute type : Standard Information\n");
				FileTimeToSystemTime((FILETIME*)offset,&time);
				fprintf(fp,"File 생성 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);
				FileTimeToSystemTime((FILETIME*)(offset+8),&time);
				fprintf(fp,"File 수정 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);
				FileTimeToSystemTime((FILETIME*)(offset+24),&time);
				fprintf(fp,"File 접근 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);
				break;
			case 0x20://Attribute List
				fprintf(fp,"Attribute type : Attribute list\n");
				break;
			case 0x30://File Name
				fprintf(fp,"Attribute type : File Name\n");
				FileTimeToSystemTime((FILETIME*)(offset+8),&time);
				fprintf(fp,"File 생성 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);
				FileTimeToSystemTime((FILETIME*)(offset+16),&time);
				fprintf(fp,"File 이름 수정 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);
				FileTimeToSystemTime((FILETIME*)(offset+32),&time);
				fprintf(fp,"File 접근 %d년 %d월 %d일\n",time.wYear,time.wMonth,time.wDay);
				fprintf(fp,"File Name Size : %d\n",*((unsigned char*)offset+64));	
				fprintf(fp,"File NameSpace : ");
				switch(*((unsigned char*)offset+65))
				{
				case 0:
					fprintf(fp,"POSIX\n");
					break;
				case 1:
					fprintf(fp,"Win32\n");
					break;
				case 2:
					fprintf(fp,"DOS\n");
					break;
				case 3:
					fprintf(fp,"Win32 & DOS\n");
					break;
				default:
					fprintf(fp,"Unkown\n");
					break;
				}
				fprintf(fp,"File Name : ");
				fwprintf(fp,L"%s",((unsigned char*)offset+66));
				fprintf(fp,"\n");
				break;
			case 0x40://Volume Version
				break;
			case 0x50://Object ID
				break;
			case 0x60://Security
				break;
		}
	}
	if(*((unsigned char*)point+8))
	{
		delete offset;
	}
	if(*(long*)((unsigned char*)point+4))
		return *(long*)((unsigned char*)point+4);
	else
		return 0;
}
//*
__int64 _MFT_READER::ReadCluster(unsigned char* point,unsigned char* info)
{
		int i=0,j=0,k;
		__int64 offset=0,temp;
		__int64 length=0;
		while(*(point+i))
		{
			length=0;
			for(k=0;k<(*(point+i)&0x0F);k++)
			{
				length<<=8;
				length+=*((point+i)+(*(point+i)&0x0F)-k);
			}
			temp=offset;	//*오프셋값은 이전 값들과 합계로 계산됨.
			offset=0;
			for(;k<(*(point+i)&0x0F)+((*(point+i)&0xF0)>>4);k++)
			{
				offset<<=8;
				offset+=*((point+i)+(*(point+i)&0x0F)+((*(point+i)&0xF0)>>4)-k+(*(point+i)&0x0F));
			}
//*
			if(offset&(0x80<<(8*(((*(point+i)&0xF0)>>4)-1))) && ((*(point+i)&0xF0)>>4)<8)
			{
				offset=offset^(0x80<<(8*(((*(point+i)&0xF0)>>4)-1)));
				offset=-offset;
			}
//*/
			offset+=temp;
			ReadSector(offset * boot_block.SectorsPerCluster,
				length * boot_block.SectorsPerCluster,
				info+j*boot_block.BytesPerSector*boot_block.SectorsPerCluster);
			i+=(*(point+i)&0x0F)+((*(point+i)&0xF0)>>4)+1;
			j+=length;
		}
		return j;
}
//*/