www.pudn.com > SmartFDISK.zip > part.cpp


/**************************************************************************** 
 * 
 * Smart FDISK 
 * 
 * This program is a powerful Harddisk Partitioning Tool including a 
 * easy-to-use Boot Manager. 
 * 
 * 
 *     Copyright (C) 1999 Suzhe (suzhe@263.net) 
 * 
 * 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., 675 Mass Ave, Cambridge, MA 02139, USA. 
 * 
 ****************************************************************************/ 
/* 
 * part.cpp : Source file for Class TPartition 
 */ 
 
#define Uses_KernelObject 
#define Uses_DataType 
#define Uses_HardDrive 
#define Uses_Partition 
#define Uses_FAT16 
#define Uses_FAT32 
 
#include "Kernel.H" 
 
//Declare the partition type data 
TPartitionType PartitionTypes[MAXPTTYPENUMBER]= 
{ 
	{0x00,"Free        "},	//0 
	{0x01,"FAT-12      "},  //1 
	{0x02,"XENIX Root  "},  //2 
	{0x03,"XENIX Usr   "},  //3 
	{0x04,"FAT-16 Small"},  //4 
	{0x05,"Extended    "},  //5 
	{0x06,"FAT-16      "},  //6 
	{0x07,"HPFS/NTFS   "},  //7 
	{0x08,"AIX         "},  //8 
	{0X09,"AIX Boot    "},  //9 
	{0x0A,"Boot Manager"},  //10 
	{0x0B,"FAT-32      "},  //11 
	{0x0C,"FAT-32 LBA  "},  //12 
	{0x0E,"FAT-16 LBA  "},  //13 
	{0x0F,"Extended LBA"},  //14 
	{0x11,"Hidden FAT12"},  //15 
	{0x14,"Hidden FAT16"},  //16 
	{0x16,"Hidden FAT16"},  //17 
	{0x40,"Venix 80286 "},  //18 
	{0x50,"DM          "},  //19 
	{0x51,"Novell?     "},  //20 
	{0x52,"Microport   "},  //21 
	{0x56,"GB          "},  //22 
	{0x61,"Speed       "},  //23 
	{0x63,"GNU HURD    "},  //24 
	{0x64,"Novell 286  "},  //25 
	{0x65,"Novell 386  "},  //26 
	{0x75,"PC / IX     "},  //27 
	{0x80,"Old MINIX   "},  //28 
	{0x81,"Linux/MINIX "},  //29 
	{0x82,"Linux Swap  "},  //30 
	{0x83,"Linux       "},  //31 
	{0x85,"Linux Extend"},  //32 
	{0x93,"Amoeba      "},  //33 
	{0x94,"Amoeba BBT  "},  //34 
	{0xA0,"Hidden      "},  //35 
	{0xA5,"BSD / 386   "},  //36 
	{0xB7,"BSDI fs     "},  //37 
	{0xB8,"BSDI swap   "},  //38 
	{0xC7,"Syrinx      "},  //39 
	{0xDB,"CP/M        "},  //40 
	{0xE1,"DOS Access  "},  //41 
	{0xE3,"DOS R/O     "},  //42 
	{0xF2,"DOS Second  "},  //43 
	{0xFF,"BBT         "},  //44 
}; 
 
 
/****************************************************************************/ 
/* Member Function of class TPartition                                      */ 
/****************************************************************************/ 
 
TPartition::TPartition() 
{ 
	PreInit(); 
} 
 
TPartition::TPartition 
	( THardDrive *hd, TPartition * father, TPartitionRecord & record ) 
{ 
	Initialize(hd,father,record); 
} 
 
TPartition::TPartition 
	( THardDrive *hd, TPartition * father, BYTE type, DWORD relative, DWORD sect ) 
{ 
	Initialize( hd, father, type, True, relative, sect ); 
} 
 
void TPartition::ShutDown() 
{ 
	DeleteAllSon(); 
	if( FileSystem != NULL ) destroy(FileSystem); 
	PreInit(); 
} 
 
int32 TPartition::Initialize( THardDrive *hd, TPartition * father, 
	  TPartitionRecord & record ) 
{ 
	QWORD absSect, sectors, relative; 
	WORD sector, head, cylinder; 
	TDiskGeometry geometry; 
	int32 errno; 
	if( hd == NULL || hd->IsUseable() == False ) 
	{ 
		Useable = False; 
		return 0x102; 
	} 
 
/* 
	hd->GetGeometry( geometry ); 
 
	if( geometry.Cylinders > MAXINT13CYLINDER || 
		record.StartSC == 0xFFFF ||	record.EndSC == 0xFFFF || 
		record.Type == 0x0C || record.Type == 0x0E || record.Type == 0x0F ) 
	{ 
		errno = Initialize(hd, father, record.Type, False, 
			record.RelativeSector, record.Sectors); 
		State = record.State; 
		return errno; 
	} 
*/ 
 
	errno = Initialize(hd, father, record.Type, False, 
		record.RelativeSector, record.Sectors); 
	State = record.State; 
	return errno; 
 
/* 
	sector = record.StartSC & 0x3f; 
	head = record.StartHead; 
	cylinder = (record.StartSC >> 8) | (( record.StartSC << 2 ) & 0x300); 
	hd->CHStoLBA( cylinder, head, sector, absSect ); 
 
	if( father!=NULL && father->IsUseable() ) 
		relative = absSect - father->GetAbsSector(); 
	else relative = absSect; 
 
	sector = record.EndSC & 0x3f; 
	head = record.EndHead; 
	cylinder = (record.EndSC >> 8) | (( record.EndSC << 2 ) & 0x300); 
	hd->CHStoLBA( cylinder, head, sector, sectors ); 
	sectors = sectors - absSect + 1; 
 
	errno = Initialize(hd, father, record.Type, False, relative, sectors ); 
	State = record.State; 
 
	return errno; 
*/ 
} 
 
int32 TPartition::Initialize( THardDrive *hd, TPartition * father, 
		BYTE type, Boolean IsNew, DWORD relative, DWORD sect ) 
{ 
	DWORD temp; 
	PreInit(); 
	if( (HardDrive = hd) == NULL || 
		HardDrive->IsUseable() == False) 
	{ 
		Useable=False; 
		return 0x102; 
	} 
 
	Father = father; 
	if( Father!=NULL && Father->IsUseable()==False ) 
	{ 
		Useable=False; 
		return 0x200; 
	} 
 
	Useable = True; 
	MarkNewPartition( IsNew ); 
 
	if( IsNew ) 
	{ 
		RelativeSector = CalcValidRelativeSector( relative ); 
		Sectors = CalcValidSectors( sect ); 
	} 
	else 
	{ 
		RelativeSector = relative; 
		Sectors = sect; 
	} 
 
	AbsSector = CalcAbsSector( 0 ); 
 
	Type = type; 
 
	temp = 1048576uL / HardDrive->GetSectorSize(); 
 
	SizeInMega = Sectors / temp; 
	if( (Sectors % temp) >= temp / 2 ) SizeInMega++; 
 
	AttachFileSystem(); 
 
	return 0; 
} 
 
int32 TPartition::Read( DWORD BlockNum, WORD BlockCount, void * Buffer ) 
{ 
	if( !Useable ) return 0x200; 
	if( Father == NULL ) 
		return HardDrive->Read( (QWORD)(BlockNum + RelativeSector), BlockCount, Buffer ); 
	else 
		return Father->Read( BlockNum + RelativeSector, BlockCount, Buffer ); 
} 
 
int32 TPartition::Write( DWORD BlockNum, WORD BlockCount, void * Buffer ) 
{ 
	if( !Useable ) return 0x200; 
	if( Father == NULL ) 
		return HardDrive->Write( (QWORD)(BlockNum + RelativeSector), BlockCount, Buffer ); 
	else 
		return Father->Write( BlockNum + RelativeSector, BlockCount, Buffer ); 
} 
 
int32 TPartition::Verify( DWORD BlockNum, WORD BlockCount ) 
{ 
	if( !Useable ) return 0x200; 
	if( Father == NULL ) 
		return HardDrive->Verify( (QWORD)(BlockNum + RelativeSector), BlockCount ); 
	else 
		return Father->Verify( BlockNum + RelativeSector, BlockCount ); 
} 
 
int32 TPartition::Seek  ( DWORD BlockNum ) 
{ 
	if( !Useable ) return 0x200; 
	if( Father == NULL ) 
		return HardDrive->Seek( (QWORD)(BlockNum + RelativeSector) ); 
	else 
		return Father->Seek( BlockNum + RelativeSector ); 
} 
 
DWORD TPartition::CalcValidRelativeSector( DWORD relative ) 
{ 
	QWORD temp, abs; 
	WORD cylinder,head,sector; 
	TDiskGeometry geometry; 
 
	HardDrive->GetGeometry( geometry ); 
 
	abs = 0; 
	if( Father!=NULL ) 
	{ 
		if( relative==0 ) relative++; 
		abs = Father->GetAbsSector(); 
 
		if( Prev!=NULL && Prev->IsUseable() && 
			Prev->Father==Father && Prev->Next==this ) 
		{ 
			if( relative < Prev->GetSectors() + Prev->GetRelativeSector() ) 
				relative = Prev->GetSectors() + Prev->GetRelativeSector(); 
		} 
 
		if( Next!=NULL && Next->IsUseable() && 
			Next->Father==Father && Next->Prev==this ) 
		{ 
			if( relative >= Next->GetRelativeSector() ) 
				relative = Next->GetRelativeSector() - 1; 
		} 
	} 
 
	HardDrive->LBAtoCHS( relative + abs, cylinder, head, sector ); 
 
	if( sector > 1 ) 
	{ 
		sector = 1; 
		head ++; 
	} 
	if( head >= geometry.Heads ) 
	{ 
		head -= geometry.Heads; 
		cylinder ++; 
	} 
 
	HardDrive->CHStoLBA( cylinder, head, sector, temp ); 
	temp -= abs; 
 
	if( Father != NULL && temp >Father->GetSectors() ) 
		temp = Father->GetSectors(); 
 
	return temp; 
} 
 
DWORD TPartition::CalcValidSectors( DWORD sectors ) 
{ 
	QWORD temp, abs; 
	WORD cylinder, head, sector; 
	TDiskGeometry geometry; 
 
	abs = CalcAbsSector(0); 
	if( sectors==0 ) sectors++; 
 
	if( Father!=NULL ) 
	{ 
		if( Next!=NULL && Next->IsUseable() && 
			Next->Father==Father && Next->Prev==this ) 
		{ 
			if( sectors + RelativeSector > Next->GetRelativeSector() ) 
				sectors = Next->GetRelativeSector() - RelativeSector; 
		} 
		else if( sectors + RelativeSector > Father->GetSectors() ) 
			sectors = Father->GetSectors() - RelativeSector; 
	} 
 
	HardDrive->LBAtoCHS( sectors + abs - 1, cylinder, head, sector ); 
	HardDrive->GetGeometry( geometry ); 
 
	sector = geometry.SectorsPerTrack; 
	head = geometry.Heads - 1; 
 
	HardDrive->CHStoLBA( cylinder, head, sector, temp ); 
	temp = temp - abs + 1; 
	if( Father != NULL && temp + RelativeSector > Father->GetSectors() ) 
		temp = Father->GetSectors() - RelativeSector; 
	return temp; 
} 
 
DWORD TPartition::CalcAbsSector(DWORD relative) 
{ 
	if( !Useable ) return 0; 
	if( Father == NULL ) return RelativeSector + relative; 
	return RelativeSector + Father->GetAbsSector() + relative; 
} 
 
int32 TPartition::GetRecord(TPartitionRecord & record) 
{ 
	WORD stCyl, edCyl, head, stSect, edSect; 
//	TDiskGeometry geometry; 
 
	memset( &record, 0, sizeof(record) ); 
	if( !Useable ) return 0x200; 
 
//	HardDrive->GetGeometry(geometry); 
 
	record.State			= State; 
	record.Type				= Type; 
	record.RelativeSector	= RelativeSector; 
	record.Sectors			= Sectors; 
 
	HardDrive->LBAtoCHS( CalcAbsSector(0), stCyl, head, stSect ); 
	record.StartHead	= (BYTE) head; 
	HardDrive->LBAtoCHS( CalcAbsSector(0) + Sectors - 1, edCyl, head, edSect ); 
	record.EndHead		= (BYTE) head; 
 
	if( stCyl > MAXINT13CYLINDER ) 
		record.StartSC = 0xFFFF; 
	else 
	{ 
		record.StartSC |= (stSect & 0x003F); 
		record.StartSC |= ((stCyl << 8) & 0xFF00); 
		record.StartSC |= ((stCyl & 0x0300) >> 2); 
	} 
	if( edCyl > MAXINT13CYLINDER ) 
		record.EndSC = 0xFFFF; 
	else 
	{ 
		record.EndSC |= (edSect & 0x003F); 
		record.EndSC |= ((edCyl << 8) & 0xFF00); 
		record.EndSC |= ((edCyl & 0x0300) >> 2); 
	} 
 
	if( stCyl >MAXINT13CYLINDER || edCyl >MAXINT13CYLINDER ) 
	{ 
		switch( Type ) 
		{ 
			case 0x06: 
				record.Type = 0x0E; 
				break; 
			case 0x0B: 
				record.Type = 0x0C; 
				break; 
		} 
	} 
 
	return 0; 
} 
 
const char * TPartition::GetTypeName() 
{ 
	static char *Unknown="Unknown   "; 
	for( int i=0; i< MAXPTTYPENUMBER; i++ ) 
		if( Type == PartitionTypes[i].Type ) 
			return PartitionTypes[i].Name; 
	return Unknown; 
} 
 
Boolean TPartition::IsChanged() 
{ 
	TPartition *part; 
	if( !IsUseable() ) return False; 
	for( part=Son; part!=NULL; part=part->Next ) 
		if( part->GetType()!=0 && part->IsChanged() ) 
			return True; 
 
    if( FileSystem!=NULL && FileSystem->IsUseable() && FileSystem->IsChanged() ) 
    	return True; 
 
	return (Boolean) (((ExtState & PARTCHANGED) != 0) || IsNewPartition()); 
} 
 
int32 TPartition::WriteChange() 
{ 
	char *byte; 
	TPartition *part; 
	int32 errno=0; 
 
	if( !Useable ) return 0x200; 
	if( !IsChanged() ) return 0; 
 
	if( IsNewPartition() && GetValidSonNumber() == 0 ) 
	{ 
		byte = new char[HardDrive->GetSectorSize()]; 
		if( byte == NULL ) return 0x400; 
		memset( byte, 0, HardDrive->GetSectorSize() ); 
		errno = Write( 0, 1, byte ); 
		delete byte; 
		if( errno!= 0 ) return errno; 
	} 
 
	for( part=Son; part!=NULL; part=part->Next ) 
	{ 
		if( part->GetType() != 0 && part->IsChanged() ) 
		{ 
			errno=part->WriteChange(); 
			if( errno!=0 ) return errno; 
		} 
	} 
 
	MarkChanged( False ); 
	MarkNewPartition( False ); 
 
    if( FileSystem!=NULL && FileSystem->IsUseable() && FileSystem->IsChanged() ) 
    	errno = FileSystem->WriteChange(); 
 
	return errno; 
} 
 
int32 TPartition::Resize( DWORD size ) 
{ 
	DWORD temp; 
	TPartition *last; 
	if( !IsUseable() ) return 0x200; 
 
	if( Son!=NULL ) 
	{ 
		last = GetLastSon(); 
		if( last->GetRelativeSector() + last->GetSectors() > size ) 
			size = last->GetRelativeSector() + last->GetSectors(); 
	} 
 
	size = CalcValidSectors( size ); 
 
	if( Father!=NULL ) 
	{ 
		if( Next!=NULL && Next->IsUseable() && 
			Next->Father==Father && Next->Prev==this ) 
		{ 
			if( size > Next->GetRelativeSector() + Next->GetSectors() ) 
				size = Next->GetRelativeSector() + Next->GetSectors(); 
		} 
		else if( size + RelativeSector > Father->GetSectors() ) 
			size = Father->GetSectors() - RelativeSector; 
	} 
 
	Sectors = size; 
 
	temp = 1048576uL / HardDrive->GetSectorSize(); 
 
	SizeInMega = Sectors / temp; 
	if( (Sectors % temp) >= temp / 2 ) SizeInMega++; 
 
	if( IsNewPartition() ) MarkChanged(True); 
	return 0; 
} 
 
void TPartition::MarkBootable( Boolean bootable ) 
{ 
	if( bootable ) ExtState |= BOOTABLE; 
	else ExtState &= ~BOOTABLE; 
} 
 
void TPartition::MarkActive( Boolean active ) 
{ 
	if( active ) State = HardDrive->GetDriveNumber(); 
	else State = 0; 
} 
 
void TPartition::MarkChanged( Boolean changed ) 
{ 
	if( changed ) ExtState |= PARTCHANGED; 
	else ExtState &= ~PARTCHANGED; 
} 
 
void TPartition::MarkNewPartition( Boolean newPart ) 
{ 
	if( newPart ) ExtState |= NEWPARTITION; 
	else ExtState &= ~NEWPARTITION; 
} 
 
void TPartition::MarkRootPartition( Boolean root ) 
{ 
	if( root ) ExtState |= ROOTPARTITION; 
	else ExtState &= ~ROOTPARTITION; 
} 
void TPartition::SetName( const char * name ) 
{ 
	if( name==NULL ) return; 
	strncpy(Name, name, MAXPTNAMELENGTH); 
	Name[MAXPTNAMELENGTH]=0; 
} 
 
void TPartition::PreInit() 
{ 
	Useable			= False; 
	HardDrive		= NULL; 
	SizeInMega		= 0; 
	State			= 0; 
	Type			= 0; 
	ExtState		= 0; 
	RelativeSector	= 0; 
	Sectors			= 0; 
	Name[0]			= 0; 
	FileSystem		= NULL; 
	Father			= NULL; 
	Prev			= NULL; 
	Next			= NULL; 
	Son				= NULL; 
} 
 
int32 TPartition::GetValidSonNumber() 
{ 
	TPartition *part; 
	int32 num; 
	if( !IsUseable() ) return 0; 
	for( part=Son, num=0; part!=NULL; part=part->Next ) 
	{ 
		if( part->GetType()!=0 && part->IsUseable() ) num++; 
	} 
	return num; 
} 
 
int32 TPartition::InsertSon( TPartition * part ) 
{ 
	TPartition *temp; 
	if( FindSon(part)!=NULL ) return 0x201; 
	if( part->Father!=this ) return 0x202; 
 
	if( Son==NULL ) 
	{ 
		Son = part; 
		Son->Prev=NULL; 
		Son->Next=NULL; 
		return 0; 
	} 
	if( part->GetRelativeSector() + part->GetSectors() <= 
		Son->GetRelativeSector() ) 
	{ 
		temp = Son; 
		Son = part; 
		Son->Next = temp; 
		Son->Prev = NULL; 
		temp->Prev = Son; 
		return 0; 
	} 
	for( temp=Son; temp!=NULL; temp=temp->Next ) 
	{ 
		if( part->GetRelativeSector() >= temp->GetRelativeSector() ) 
		{ 
			if( temp->Next==NULL ||	(temp->Next!=NULL && 
				part->GetRelativeSector() + part->GetSectors() <= 
				temp->Next->GetRelativeSector() ) ) 
			{ 
				part->Prev=temp; 
				part->Next=temp->Next; 
				temp->Next=part; 
				if( part->Next!=NULL ) part->Next->Prev=part; 
				return 0; 
			} 
		} 
	} 
	return 1; 
} 
 
int32 TPartition::DeleteSon( TPartition * part ) 
{ 
	int32 errno; 
	if( (errno=RemoveSon(part))!=0 ) return errno; 
 
	destroy(part); 
	return 0; 
} 
 
int32 TPartition::RemoveSon( TPartition * part ) 
{ 
	if( FindSon(part)==NULL ) return 0x203; 
 
	if( part->Prev!=NULL ) part->Prev->Next = part->Next; 
	else Son = part->Next; 
 
	if( part->Next!=NULL ) part->Next->Prev = part->Prev; 
	return 0; 
} 
 
void TPartition::DeleteAllSon() 
{ 
	if( Son==NULL ) return; 
	while( Son!=NULL ) DeleteSon( Son ); 
} 
 
TPartition * TPartition::GetFirstValidSon() 
{ 
	TPartition *valid; 
	for( valid = Son; valid!=NULL && valid->GetType() == 0; valid=valid->Next ) 
		NULL; 
	return valid; 
} 
 
TPartition * TPartition::GetLastSon() 
{ 
	TPartition *part; 
	for( part=Son; part!=NULL && part->Next!=NULL; part=part->Next ) NULL; 
 
	return part; 
} 
 
TPartition * TPartition::FindSon(TPartition * part) 
{ 
	TPartition *temp; 
	for( temp=Son; temp!=NULL; temp=temp->Next ) 
		if( temp==part ) 
			return part; 
	return NULL; 
} 
 
int32 TPartition::ChangeFather( TPartition * newFather ) 
{ 
	if( !IsUseable() ) return 0x200; 
	if( newFather==NULL ) 
	{ 
		RelativeSector = AbsSector; 
		Father=NULL; 
		return 0; 
	} 
	else if( newFather->IsUseable()==False || 
			newFather->GetAbsSector() >= AbsSector ) 
		return 0x200; 
	else 
	{ 
		RelativeSector = AbsSector - newFather->GetAbsSector(); 
		Father=newFather; 
		return 0; 
	} 
} 
 
WORD  TPartition::GetSectorSize() 
{ 
	if( !IsUseable() ) return 0; 
	return HardDrive->GetSectorSize(); 
} 
 
int32 TPartition::AttachFileSystem() 
{ 
	if( !IsUseable() || IsRootPartition() ) 
		return 0x200; 
	if( FileSystem!=NULL ) destroy(FileSystem); 
	FileSystem = NULL; 
 
	switch( GetType() ) 
	{ 
		case 0x01: 
		case 0x04: 
		case 0x06: 
		case 0x0E: 
		case 0x11: 
		case 0x14: 
		case 0x16: 
			FileSystem = new TFAT16( this ); 
			break; 
		case 0x0B: 
		case 0x0C: 
			FileSystem = new TFAT32( this ); 
			break; 
		case 0: 
			FileSystem = new TRawFileSystem( this ); 
	} 
 
	if( FileSystem != NULL ) 
	{ 
		if( FileSystem->IsUseable() == False ) 
		{ 
			destroy(FileSystem); 
			FileSystem = NULL; 
		} 
        else if( FileSystem->GetFileSysType() !=0 ) 
			Type = FileSystem->GetFileSysType(); 
    } 
	return 0; 
} 
 
int32 TPartition::GetSonIndex( TPartition *part ) 
{ 
	int32 index, ok, test; 
	TPartition *temp, *ext; 
	if( !IsUseable() || part == NULL ) return -1; 
 
	index=ok=0; 
 
	for( temp = Son; temp != NULL; temp = temp->Next ) 
	{ 
		if( temp == part ){ ok=1; break; } 
		else if( temp->GetType() == 0x05 || temp->GetType() == 0x0F ) 
		{ 
			test = temp->GetSonIndex( part ); 
			if( test >= 0 ) 
			{ 
				index += test; 
				ok = 1; 
				break; 
			} 
			else index += temp->GetTotalSonNumber(); 
		} 
		else index ++; 
	} 
	if( ok ) return index; 
	return -1; 
} 
 
TPartition * TPartition::FindSonByIndex( int32 index ) 
{ 
	int32 count; 
	TPartition *part, *result; 
	if( !IsUseable() || index < 0 ) return NULL; 
 
	result=NULL; 
	for( count = 0, part = Son; part != NULL; part=part->Next ) 
	{ 
		if( part->GetType() == 0x05 || part->GetType() == 0x0F ) 
			if( (result=part->FindSonByIndex( index - count )) != NULL ) 
				break; 
		if( count == index ) 
		{ 
			result = part; 
			break; 
		} 
		if( (++ count) > index ) break; 
	} 
	return result; 
} 
 
int32 TPartition::GetTotalSonNumber() 
{ 
	int32 total,test; 
	TPartition *part; 
	total=0; 
	for( part=Son; part != NULL; part=part->Next ) 
	{ 
		if( part->GetType() == 0x05 || part->GetType() == 0x0F ) 
		{ 
			test = part->GetTotalSonNumber(); 
			if( test != 0 ) total += test; 
			else total ++; 
		} 
		else total ++; 
	} 
	return total; 
} 
 
void TPartition::SetType(BYTE type) 
{ 
	Type = type; 
	AttachFileSystem(); 
} 
 
/* 
TBadBlockList *TPartition::SurfaceScan( CallBackFunc CallBack ) 
{ 
	if( FileSystem != NULL && FileSystem->IsUseable() ) 
		return FileSystem->SurfaceScan( CallBack ); 
	return NULL; 
} 
*/ 
 
DWORD TPartition::GetBlockSize() 
{ 
	if( FileSystem!=NULL && FileSystem->IsFormated() ) 
		return FileSystem->GetBlockSize(); 
	else return (DWORD)GetSectorSize(); 
} 
 
int32 TPartition::GetLevel() 
{ 
	int32 level; 
	TPartition *temp; 
 
	if( !IsUseable() || Father == NULL ) 
		return -1; 
	level=0; 
	for( temp = Father; temp!=NULL && temp->Father != NULL ; temp = temp->Father ) 
		level++; 
	return level; 
}