www.pudn.com > SmartFDISK.zip > rootpart.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. 
 * 
 ****************************************************************************/ 
/* 
 * rootpart.cpp : Source file for Class TRootPartition 
 */ 
 
#define Uses_DataType 
#define Uses_HardDrive 
#define Uses_Partition 
#define Uses_RootPartition 
#define Uses_FileSystem 
#define Uses_BootManager 
 
#include "Kernel.H" 
/****************************************************************************/ 
/* Member Function of class TRootPartition                                   */ 
/****************************************************************************/ 
 
TRootPartition::TRootPartition( THardDrive *hd ) : 
	TPartition() 
{ 
	Initialize( hd ); 
} 
 
TRootPartition::TRootPartition() : 
	TPartition() 
{ 
} 
 
int32 TRootPartition::Initialize( THardDrive *hd ) 
{ 
	if( hd->IsUseable()==False ) return 0x102; 
	TPartition::Initialize( hd, NULL, 0, False, 0, hd->GetSectors() ); 
	MarkRootPartition( True ); 
	if( ReadPartitionTable()!=0 ) 
	{ 
		Useable = False; 
		return 0x102; 
	} 
	return 0; 
} 
 
int32 TRootPartition::ReadPartitionTable() 
{ 
	int32 errno,extCount; 
	TPartition * son; 
	TPartitionRecord PartitionTable[MAXPTNUMBER]; 
 
	char * BootRecord=NULL; 
 
	if( !IsUseable() ) return 0x200; 
 
	memset( PartitionTable, 0, sizeof(TPartitionRecord) * MAXPTNUMBER ); 
	BootRecord = new char[HardDrive->GetSectorSize()]; 
	if( BootRecord == NULL ) return 0x400; 
 
	DeleteAllSon(); 
 
	errno=Read(0, 1, BootRecord); 
 
	if( errno!=0 ) 
	{ 
		delete BootRecord; 
		return errno; 
	} 
 
	if( ((WORD *)BootRecord)[255]==GOODPTID) 
	{ 
		memcpy( PartitionTable, BootRecord + PTTABOFFSET, 
			sizeof(TPartitionRecord) * MAXPTNUMBER ); 
 
		for( int i=0; i< MAXPTNUMBER; i++ ) 
		{ 
			if( PartitionTable[i].Type != 0 ) 
			{ 
				son = new TPartition( HardDrive, this, PartitionTable[i] ); 
				InsertSon( son ); 
			} 
		} 
 
		for( son=Son, extCount=0; son!=NULL; son=son->Next ) 
		{ 
			if( (son->GetType()==0x05 || son->GetType()==0x0F) && extCount<1 ) 
			{ 
				extCount ++; 
				ReadExtPartTable( son, son ); 
			} 
		} 
		TransExtPartLink(); 
	} 
	delete BootRecord; 
	CheckFree(); 
	return 0; 
} 
 
int32 TRootPartition::WritePartitionTable() 
{ 
	int32 count; 
	int32 errno=0; 
	TPartition *part; 
	TPartitionRecord PartitionTable[MAXPTNUMBER]; 
 
	char * BootRecord=NULL; 
 
	if( !IsUseable() ) return 0x200; 
 
	AntiTransExtPartLink(); 
	for( part=Son; part!=NULL; part=part->Next ) 
		if( part->GetType()==0x05 || part->GetType()==0x0F ) 
			break; 
 
	if( part!=NULL ) 
		errno = WriteExtPartTable( part, part ); 
 
	if( errno==0 ) 
		errno = CreatePartitionTable( PartitionTable ); 
 
	TransExtPartLink(); 
 
	if( errno!=0 ) return errno; 
 
	BootRecord = new char[HardDrive->GetSectorSize()]; 
	if( BootRecord == NULL ) return 0x400; 
 
	errno=Read(0, 1, BootRecord); 
 
	if( errno!=0 ) 
	{ 
		delete BootRecord; 
		return errno; 
	} 
 
	memcpy( BootRecord + PTTABOFFSET, PartitionTable, 
		sizeof( TPartitionRecord ) * MAXPTNUMBER ); 
	((WORD *)BootRecord)[255]=GOODPTID; 
 
	errno=Write( 0, 1, BootRecord ); 
 
	delete BootRecord; 
 
	return errno; 
} 
 
int32 TRootPartition::CreatePartitionTable(TPartitionRecord *PartitionTable) 
{ 
	int32 partCount=0; 
	TPartition *part; 
	WORD edCyl, head, edSect; 
 
	if( !IsUseable() ) return 0x200; 
 
	memset( PartitionTable, 0, sizeof( TPartitionRecord ) * MAXPTNUMBER ); 
 
	for( part = Son, partCount=0; 
		part != NULL && partCount < MAXPTNUMBER; 
		part = part->Next ) 
	{ 
		if( part->GetType() != 0 && part->IsUseable() ) 
		{ 
			part->GetRecord(PartitionTable[partCount]); 
			if( part->GetType() == 0x05 ) 
			{ 
				HardDrive->LBAtoCHS( part->GetAbsSector() + part->GetSectors() - 1 
					, edCyl, head, edSect ); 
				if( edCyl > MAXINT13CYLINDER ) 
					PartitionTable[partCount].Type = 0x0F; 
			} 
			partCount ++; 
		} 
	} 
	return 0; 
} 
 
int32 TRootPartition::WriteChange() 
{ 
	int32 errno; 
 
	if( !IsChanged() ) return 0; 
 
	errno=WritePartitionTable(); 
	if( errno!=0 ) return errno; 
 
	errno=TPartition::WriteChange(); 
	if( errno!=0 ) return errno; 
 
	return 0; 
} 
 
int32 TRootPartition::CheckFree() 
{ 
	TPartition *part, *free, *temp; 
	TDiskGeometry geometry; 
	int32 errno; 
	DWORD sect; 
 
	if( !IsUseable() ) return 0x200; 
	HardDrive->GetGeometry( geometry ); 
 
	for( part=Son; part!=NULL; part=part->Next ) 
	{ 
		if( part->GetType() == 0x05 || part->GetType() == 0x0F ) 
		{ 
			temp=part->GetLastSon(); 
			while( temp!=NULL && temp->GetType()==0 ) 
			{ 
				part->DeleteSon(temp); 
				temp = part->GetLastSon(); 
			} 
			if( temp!=NULL ) 
			{ 
				part->Resize( temp->GetRelativeSector() + temp->GetSectors() ); 
			} 
			else 
			{ 
				temp=part->Prev; 
				DeleteSon(part); 
				if( temp!=NULL ) part=temp; 
				else part=Son; 
			} 
		} 
	} 
 
	if( Son == NULL ) 
	{ 
		free = new TPartition( HardDrive, this, 0, geometry.SectorsPerTrack, 
								GetSectors() - geometry.SectorsPerTrack ); 
		InsertSon( free ); 
		return 0; 
	} 
 
	if( Son->GetRelativeSector() > geometry.SectorsPerTrack ) 
	{ 
		free = new TPartition( HardDrive, this, 0, geometry.SectorsPerTrack, 
							Son->GetRelativeSector() - geometry.SectorsPerTrack ); 
		if( free->GetRelativeSector() + free->GetSectors() <= 
			Son->GetRelativeSector() ) 
			InsertSon( free ); 
		else destroy(free); 
	} 
 
	for( part=Son; part->Next!=NULL; part=part->Next ) 
	{ 
		sect = part->GetRelativeSector() + part->GetSectors(); 
		if(  sect < part->Next->GetRelativeSector() ) 
		{ 
			free = new TPartition( HardDrive, this, 0, sect, 
					part->Next->GetRelativeSector() - sect ); 
 
			if( free->GetRelativeSector() >= sect && 
				free->GetRelativeSector() + free->GetSectors() <= 
				part->Next->GetRelativeSector() ) 
			{ 
				InsertSon( free ); 
				part=part->Next; 
			} 
			else destroy(free); 
		} 
	} 
 
	sect = part->GetRelativeSector() + part->GetSectors(); 
	if( sect < GetSectors() ) 
	{ 
		free = new TPartition( HardDrive, this, 0, sect, GetSectors() - sect ); 
 
		if( free->GetRelativeSector() >= sect && 
			free->GetRelativeSector() + free->GetSectors() <= GetSectors() ) 
			InsertSon( free ); 
		else destroy(free); 
	} 
 
	for( part=Son; part->Next!=NULL; ) 
	{ 
		if( part->GetType() == 0 && part->Next->GetType() == 0 ) 
		{ 
			free = new TPartition( HardDrive, this, 0, part->GetRelativeSector(), 
					part->Next->GetRelativeSector() + part->Next->GetSectors() - 
					part->GetRelativeSector() ); 
			DeleteSon( part->Next ); 
			DeleteSon( part ); 
			InsertSon( free ); 
			part = free; 
		} 
		else part=part->Next; 
	} 
	return 0; 
} 
 
Boolean TRootPartition::IsChanged() 
{ 
	if( TPartition::IsChanged() ) return True; 
	return False; 
} 
 
int32 TRootPartition::ReadExtPartTable( TPartition *ext, TPartition *part ) 
{ 
	TPartition *temp; 
	TPartitionRecord PartitionTable[MAXPTNUMBER]; 
	char *BootRecord; 
	int32 errno,extCount; 
 
	if( !IsUseable() ) return 0x200; 
	if( ext==NULL || part==NULL || !ext->IsUseable() || !part->IsUseable() ) 
		return 0x401; 
 
	BootRecord = new char[HardDrive->GetSectorSize()]; 
	if( BootRecord == NULL ) return 0x400; 
 
	errno = part->Read( 0, 1, BootRecord ); 
	if( errno!=0 ) 
	{ 
		delete BootRecord; 
		return errno; 
	} 
 
	if( ((WORD *)BootRecord)[255]!=GOODPTID) 
	{ 
		delete BootRecord; 
		return 0x204; 
	} 
	memcpy( PartitionTable, BootRecord + PTTABOFFSET, 
		sizeof(TPartitionRecord) * MAXPTNUMBER ); 
	delete BootRecord; 
 
	extCount=0; 
	for( int i=0; iInsertSon( temp ); 
			} 
			else if( extCount<1 ) 
			{ 
				temp = new TPartition( HardDrive, ext, PartitionTable[i] ); 
				ext->InsertSon( temp ); 
				ReadExtPartTable( ext, temp ); 
				extCount++; 
			} 
		} 
	} 
	return 0; 
} 
 
int32 TRootPartition::WriteExtPartTable( TPartition *ext, TPartition *part ) 
{ 
	int32 count,errno; 
	TPartition *temp; 
	TPartitionRecord PartitionTable[MAXPTNUMBER]; 
	char *BootRecord; 
 
	if( !IsUseable() ) return 0x200; 
	if( ext==NULL || part==NULL || !ext->IsUseable() || !part->IsUseable() ) 
		return 0x401; 
 
	if( ext == part ) 
	{ 
		for( temp=ext->Son; temp!=NULL; temp=temp->Next ) 
		{ 
			if( temp->GetType()==0x05 || temp->GetType()==0x0F ) 
				WriteExtPartTable( ext, temp ); 
		} 
	} 
 
	BootRecord = new char[HardDrive->GetSectorSize()]; 
	if( BootRecord == NULL ) return 0x400; 
 
	errno=part->Read(0, 1, BootRecord); 
 
	if( errno!=0 ) 
	{ 
		delete BootRecord; 
		return errno; 
	} 
 
	CreateExtPartTable( ext, part, PartitionTable ); 
 
	memcpy( BootRecord + PTTABOFFSET, PartitionTable, 
		sizeof( TPartitionRecord ) * MAXPTNUMBER ); 
	((WORD *)BootRecord)[255]=GOODPTID; 
 
	errno=part->Write( 0, 1, BootRecord ); 
	delete BootRecord; 
	return errno; 
} 
 
int32 TRootPartition::TransExtPartLink() 
{ 
	TPartition *ext, *extSon, *part, *temp; 
	if( !IsUseable() ) return 0x200; 
	for( ext=Son; ext!=NULL; ext=ext->Next ) 
		if( ext->GetType()==0x05 || ext->GetType()==0x0F ) 
			break; 
	if( ext==NULL ) return 0; 
 
	for( extSon=ext->Son; extSon!=NULL; extSon=extSon->Next ) 
		if( extSon->GetType()==0x05 || extSon->GetType()==0x0F ) 
			break; 
	if( extSon==NULL ) return 0; 
 
	for( part=extSon; part!=NULL; ) 
	{ 
		temp=part->Next; 
		part->ChangeFather( this ); 
		ext->RemoveSon( part ); 
		InsertSon( part ); 
		part=temp; 
	} 
	extSon = ext->GetLastSon(); 
	if( extSon!=NULL ) 
		ext->Resize( extSon->GetRelativeSector() + extSon->GetSectors() ); 
	return 0; 
} 
 
int32 TRootPartition::AntiTransExtPartLink() 
{ 
	TPartition *firstExt, *lastExt, *part, *temp, *ext; 
 
	if( !IsUseable() ) return 0x200; 
	for( firstExt=Son; firstExt!=NULL; firstExt=firstExt->Next ) 
		if( firstExt->GetType()==0x05 || firstExt->GetType()==0x0F ) 
			break; 
	if( firstExt==NULL ) return 0; 
 
	for( lastExt=GetLastSon(); lastExt!=NULL; lastExt=lastExt->Prev ) 
		if( lastExt->GetType()==0x05 || lastExt->GetType()==0x0F ) 
			break; 
	if( lastExt==firstExt ) return 0; 
 
	ext=firstExt->Next; 
	while( ext!=lastExt ) 
	{ 
		part=ext->Next; 
		ext->ChangeFather( firstExt ); 
		RemoveSon( ext ); 
		firstExt->InsertSon( ext ); 
		ext=part; 
	} 
	ext->ChangeFather( firstExt ); 
	RemoveSon( ext ); 
	firstExt->InsertSon( ext ); 
	firstExt->Resize( lastExt->GetRelativeSector() + lastExt->GetSectors() ); 
	return 0; 
} 
 
int32 TRootPartition::CreateExtPartTable 
	( TPartition *ext, TPartition *part, TPartitionRecord * table ) 
{ 
	TPartition *son; 
	int32 count,extCount; 
 
	if( !IsUseable() ) return 0x200; 
	if( ext==NULL || part==NULL || table==NULL || 
		!ext->IsUseable() || !part->IsUseable() ) 
		return 0x401; 
 
	memset( table, 0, sizeof(TPartitionRecord) * MAXPTNUMBER ); 
 
	if( ext == part ) 
	{ 
		for( son=ext->Son, count=0, extCount=0; 
			son!=NULL && countNext ) 
			if( son->GetType()!=0 ) 
			{ 
				if(son->GetType()!=0x05 && son->GetType()!=0x0F ) 
				{ 
					son->GetRecord(table[count]); 
					count ++; 
				} 
				else if( extCount<1 ) 
				{ 
					son->GetRecord(table[count]); 
					count ++; 
					extCount ++; 
				} 
			} 
	} 
	else 
	{ 
		count=0; 
		extCount=0; 
		for( son=part->Son; son!=NULL && countNext ) 
			if( son->GetType()!=0 && son->GetType()!=0x05 && son->GetType()!=0x0F ) 
			{ 
				son->GetRecord( table[count] ); 
				count++; 
			} 
		for( son=part->Next; son!=NULL && countNext ) 
			if( (son->GetType()==0x05 || son->GetType()==0x0F) && extCount<1 ) 
			{ 
				son->GetRecord( table[count] ); 
				count++; 
				extCount++; 
			} 
	} 
	return 0; 
} 
 
 
 
Boolean TRootPartition::CanCreatePrimary( TPartition *part ) 
{ 
	TPartition *temp; 
	int32 extCount1, extCount2; 
    TDiskGeometry geometry; 
 
	if( !IsUseable() || part==NULL || part->GetType() != 0 || 
		FindSon(part) == NULL || GetPrimaryNumber() >= MAXPTNUMBER ) 
		return False; 
 
	extCount1=extCount2=0; 
 
	for( temp = Son; temp != part; temp=temp->Next ) 
		if( temp->GetType() == 0x05 || temp->GetType() == 0x0F ) 
			extCount1++; 
 
	for( temp = part->Next; temp != NULL; temp=temp->Next ) 
		if( temp->GetType() == 0x05 || temp->GetType() == 0x0F ) 
			extCount2++; 
 
	if( extCount1 != 0  && extCount2 != 0 ) 
		return False; 
 
    GetHardDrive()->GetGeometry( geometry ); 
    if( part->GetSectors() < 
		geometry.SectorsPerCylinder - geometry.SectorsPerTrack ) 
    	return False; 
 
	return True; 
} 
 
Boolean TRootPartition::CanCreateLogical( TPartition *part ) 
{ 
	TPartition *temp; 
	int32 extCount1, extCount2; 
    TDiskGeometry geometry; 
 
	if( !IsUseable() || part==NULL || part->GetType() != 0 || FindSon(part)==NULL || 
		( GetPrimaryNumber() >= MAXPTNUMBER && GetLogicalNumber() ==0 ) ) 
		return False; 
 
	if( GetLogicalNumber() != 0 ) 
	{ 
		extCount1=extCount2=0; 
		for( temp=part->Prev; temp != NULL && temp->GetType()==0; temp=temp->Prev ) 
			NULL; 
		if( temp != NULL && ( temp->GetType() == 0x05 || temp->GetType() == 0x0F ) ) 
			extCount1 ++; 
 
		for( temp=part->Next; temp != NULL && temp->GetType()==0; temp=temp->Next ) 
			NULL; 
		if( temp != NULL && ( temp->GetType() == 0x05 || temp->GetType() == 0x0F ) ) 
			extCount2 ++; 
 
		if( extCount1 == 0 && extCount2 == 0 ) 
			return False; 
    } 
 
    GetHardDrive()->GetGeometry( geometry ); 
 
    if( part->GetSectors() < geometry.SectorsPerCylinder ) 
    	return False; 
 
	return True; 
} 
 
Boolean TRootPartition::CanDelete( TPartition *part ) 
{ 
	if( !IsUseable() || part == NULL || part->GetType() == 0 || GetSonIndex(part) < 0 ) 
		return False; 
	return True; 
} 
 
Boolean TRootPartition::CanBoot( TPartition *part ) 
{ 
	if( !IsUseable() || part == NULL || part->GetType() == 0 || 
		part->GetType() == 0x05 || part->GetType() == 0x0F || 
		part->GetTotalSonNumber()!=0 || GetSonIndex(part) < 0) 
		return False; 
	return True; 
} 
 
Boolean TRootPartition::CanActive( TPartition *part ) 
{ 
	if( !IsUseable() || part == NULL || part->GetType() == 0 || 
		part->GetType() == 0x05 || part->GetType() == 0x0F || 
		part->GetTotalSonNumber()!=0 || FindSon(part) == NULL || 
		GetSonLevel(part) != 0 ) 
		return False; 
	return True; 
} 
 
Boolean TRootPartition::CanFormat( TPartition *part ) 
{ 
	if( !IsUseable() || part == NULL || part->GetType() == 0 || 
		part->GetType() == 0x05 || part->GetType() == 0x0F || 
		GetSonIndex(part) < 0 || part->GetFileSystem() == NULL ) 
		return False; 
	return part->GetFileSystem()->CanFormat(); 
} 
 
Boolean TRootPartition::CanSurfaceScan( TPartition *part ) 
{ 
	if( !IsUseable() || part == NULL || !part->IsUseable() || 
		GetSonIndex(part) < 0 || part->GetFileSystem()==NULL || 
		!part->GetFileSystem()->IsUseable() || 
		(part->GetType()!=0 && !part->GetFileSystem()->IsFormated()) ) 
		return False; 
	return True; 
} 
 
int32 TRootPartition::GetSonLevel( TPartition *part ) 
{ 
	int32 level; 
	TPartition *temp; 
 
	if( !IsUseable() || part == NULL || GetSonIndex( part ) < 0 ) 
		return -1; 
	level=0; 
	for( temp = part->Father; temp != this && temp != NULL; temp = temp->Father ) 
		level++; 
	return level; 
} 
 
int32 TRootPartition::GetPrimaryNumber() 
{ 
	int32 count, extCount; 
	TPartition *part; 
	if( !IsUseable() ) return 0; 
 
	count = extCount = 0; 
	for( part = Son; part != NULL; part = part->Next ) 
	{ 
		if( (part->GetType() == 0x05 || part->GetType() == 0x0F) ) 
		{ 
			if( extCount == 0 )	count ++; 
			extCount ++; 
		} 
		else if( part->GetType() != 0 ) 
			count ++; 
	} 
	return count; 
} 
 
int32 TRootPartition::GetLogicalNumber() 
{ 
	int32 count; 
	TPartition *part; 
 
	count =0; 
	for( part = Son; part != NULL; part = part->Next ) 
		if( (part->GetType() == 0x05 || part->GetType() == 0x0F) ) 
			count ++; 
	return count; 
} 
 
int32 TRootPartition::CreatePrimary 
	( TPartition *free, BYTE type, DWORD mega, int32 pos, char * name ) 
{ 
	TPartition *part; 
	DWORD relative, sectors, oldSect; 
 
	if( !CanCreatePrimary( free ) ) return 0x205; 
	if( mega > free->GetSizeInMega() || mega <= 0) return 0x401; 
	if( type == 0 ) return 0x401; 
 
	if( mega == free->GetSizeInMega() ) 
	{ 
		free->MarkNewPartition( True ); 
		free->SetType( type ); 
		free->SetName( name ); 
	} 
	else if( pos == 0 ) 
	{ 
		relative = free->GetRelativeSector(); 
		sectors = ( mega - 1 ) * 2048uL; 
		if( sectors > free->GetSectors() ) sectors = free->GetSectors(); 
		part = new TPartition( HardDrive, this, type, relative, sectors ); 
		if( part==NULL || part->IsUseable()==False ) 
			return 0x400; 
		part->SetName( name ); 
		DeleteSon( free ); 
		InsertSon( part ); 
	} 
	else 
	{ 
		oldSect = free->GetSectors(); 
		sectors = ( free->GetSizeInMega() - mega - 1uL) * 2048uL; 
		free->Resize( sectors ); 
		relative = free->GetRelativeSector() + free->GetSectors(); 
		sectors = oldSect - free->GetSectors(); 
		part = new TPartition( HardDrive, this, type, relative, sectors ); 
		if( part==NULL || part->IsUseable()==False ) 
			return 0x400; 
		part->SetName( name ); 
		InsertSon( part ); 
	} 
	CheckFree(); 
	MarkChanged(True); 
	return 0; 
} 
 
int32 TRootPartition::CreateLogical 
	( TPartition *free, BYTE type, DWORD mega, int32 pos, char * name ) 
{ 
	TPartition *part, *logical; 
	QWORD relative, sectors, freeSize; 
    QWORD extRelative, extSectors; 
    WORD cyl, sect, head; 
 
	if( !CanCreateLogical( free ) ) return 0x206; 
	if( mega <= 0 || type == 0 ) return 0x401; 
 
    relative = free->GetRelativeSector(); 
    sectors = free->GetSectors(); 
    HardDrive->LBAtoCHS( relative, cyl, head, sect ); 
    if( head > 0 ) 
    { 
    	head = 0; 
        cyl ++; 
    } 
	HardDrive->CHStoLBA( cyl, head, sect, extRelative ); 
    extSectors = sectors - ( extRelative - relative ); 
    if( extSectors == 0 ) return 0x206; 
 
    DeleteSon( free ); 
    free = new TPartition( HardDrive, this, 0, extRelative, extSectors ); 
    InsertSon( free ); 
 
	if( mega >= free->GetSizeInMega() ) 
	{ 
		free->MarkNewPartition( True ); 
		free->SetType( 0x05 ); 
		part = free; 
	} 
 
	else if( pos == 0 ) 
	{ 
		sectors = ( mega - 1 ) * ( 1048576uL / HardDrive->GetSectorSize() ); 
		if( sectors > free->GetSectors() ) sectors = free->GetSectors(); 
        free->Resize( sectors ); 
		free->MarkNewPartition( True ); 
        free->SetType( 0x05 ); 
		part = free; 
	} 
	else 
	{ 
		freeSize = free->GetSectors(); 
		sectors = ( free->GetSizeInMega() - mega - 1uL ) * 
				  (1048576uL / free->GetSectorSize()); 
		free->Resize( sectors ); 
		relative = free->GetRelativeSector() + free->GetSectors(); 
		sectors = freeSize - free->GetSectors(); 
		part = new TPartition( HardDrive, this, 0x05, relative, sectors ); 
		if( part==NULL || part->IsUseable()==False ) 
        { 
            CheckFree(); 
			return 0x400; 
        } 
		InsertSon( part ); 
	} 
 
	relative = 1; 
	sectors = part->GetSectors() - relative; 
	logical = new TPartition( HardDrive, part, type, relative, sectors ); 
	if( logical==NULL || logical->IsUseable()==False ) 
    { 
        CheckFree(); 
		return 0x400; 
    } 
	logical->SetName( name ); 
	part->InsertSon( logical ); 
	CheckFree(); 
	MarkChanged(True); 
	return 0; 
} 
 
int32 TRootPartition::Delete( TPartition *part ) 
{ 
	if( !CanDelete( part ) ) return 0x207; 
	if( part->Father !=0 ) part->Father->DeleteSon( part ); 
	CheckFree(); 
	MarkChanged(True); 
	return 0; 
} 
 
int32 TRootPartition::MarkAsActive( TPartition *part ) 
{ 
	TPartition *temp; 
	if( !CanActive( part ) ) return 0x208; 
	for( int i=0; iGetType()!=0 && temp->IsActive() ) 
		{ 
			temp->MarkActive( False ); 
			temp->Father->MarkChanged(True); 
		} 
	} 
	part->MarkActive( True ); 
	part->Father->MarkChanged(True); 
	return 0; 
} 
 
int32 TRootPartition::ToggleBootable( TPartition *part ) 
{ 
    TPartition *son; 
    int32 sonNum; 
    int32 bootNum; 
 
	if( !CanBoot( part ) ) return 0x209; 
 
    if( !part->IsBootable() ) 
    { 
        sonNum = GetTotalSonNumber(); 
        bootNum=0; 
    	for( int i=0; iIsUseable() && 
				son->GetType()!=0 && son->IsBootable() ) 
                bootNum++; 
        } 
        if( bootNum >= BOOTMENUENTRYNUM ) 
        	return 0x504; 
    } 
 
	part->MarkBootable( (Boolean) (!part->IsBootable()) ); 
	part->Father->MarkChanged(True); 
	return 0; 
}