www.pudn.com > SmartFDISK.zip > bootmgr.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. 
 * 
 ****************************************************************************/ 
/* 
 * bootmgr.cpp : Source file for Class TBootManager 
 */ 
 
#define Uses_BootManager 
#define Uses_TPartition 
#define Uses_THardDrive 
#define Uses_TRootPartition 
 
#include"Kernel.h" 
#define MINRESERVEDSECT		33 
 
TBootManager::TBootManager() 
{ 
	PreInit(); 
} 
 
TBootManager::TBootManager( TRootPartition *root ) 
{ 
	Initialize( root ); 
} 
 
void TBootManager::ShutDown() 
{ 
	PreInit(); 
} 
 
void TBootManager::PreInit() 
{ 
	Root = NULL; 
	LoaderInst = False; 
	KernelInst = False; 
	Useable = False; 
    UseInt13Ext= False; 
	memset(KernelSect, 0, sizeof(DWORD) * MGRCOPYNUM); 
    memset(KernelOldAddr,0,sizeof(TInt13OldAddr) * MGRCOPYNUM ); 
	memset(MainPartTable, 0, sizeof(TPartitionRecord) * MAXPTNUMBER); 
	VirusCheck = VIRCHECKINT13; 
} 
 
int32 TBootManager::Initialize( TRootPartition *root ) 
{ 
	PreInit(); 
	if( root == NULL || !root->IsUseable() ) 
		return 0x102; 
 
	Root = root; 
	Useable = True; 
    UseInt13Ext = Root->GetHardDrive()->IsUseInt13Ext(); 
 
	if( CanInstall() ) 
	{ 
		ReadLoader(); 
		ReadKernel(); 
	} 
 
	return 0; 
} 
 
int32 TBootManager::Install(TBootMgrInstData &data) 
{ 
	DWORD sect; 
	int i; 
	int32 errno; 
 
	if( !CanInstall() ) return 0x501; 
 
    UseInt13Ext = Root->GetHardDrive()->IsInt13ExtPresent(); 
 
	for( sect=1, i=0; i< MGRCOPYNUM; i++, sect+=8 ) 
		KernelSect[i] = sect; 
    AddrNewToOld(); 
 
	if( (errno=WriteLoader( data.VirusCheck )) != 0 ) return errno; 
    LoaderInst = True; 
	if( (errno=WriteKernel( data.Language, data.DelayTime, data.AutoHide )) != 0 ) return errno; 
    KernelInst = True; 
	return 0; 
} 
 
int32 TBootManager::Uninstall() 
{ 
	BYTE *buf; 
	DWORD sect; 
	int32 errno; 
	if( !IsUseable() || !IsKernelInst() ) 
		return 0x502; 
 
	buf = new BYTE[LOADERSIZE]; 
	if( buf==NULL ) return 0x400; 
 
	memset( buf, 0, LOADERSIZE ); 
	for( sect=1; sectWrite( sect, 1, buf ); 
 
	KernelInst = False; 
	LoaderInst = False; 
 
	delete buf; 
 
	errno = RepairMBR(False); 
	ReadKernel(); 
	return errno; 
 
} 
 
int32 TBootManager::WriteBootMenu() 
{ 
	BYTE *kernel; 
	BYTE *mbr; 
 
	TKernelData *data; 
	TBootPartEntry *entry; 
	TPartition *son, *father; 
    TPartitionRecord record; 
	int32 PartNum; 
	int32 i, totalSon, SonIndex; 
	int32 errno, writeError[MGRCOPYNUM]; 
 
	if( !IsUseable() ) return 0x503; 
	if( !IsKernelInst() ) return 0x502; 
 
	if( (kernel = new BYTE[KERNELSIZE]) == NULL ) return 0x400; 
	if( (mbr = new BYTE[LOADERSIZE]) == NULL ) 
	{ 
		delete kernel; 
		return 0x400; 
	} 
 
	data = (TKernelData *)( kernel + KERNELDATAOFFSET ); 
 
	if( (errno = Root->Read(0, 1, mbr)) != 0 ) 
	{ 
		delete mbr; 
		delete kernel; 
		return errno; 
	} 
 
	for( i=0; iRead( KernelSect[i], KERNELSECTS, kernel ) == 0 && 
			strncmp( (char*) data->Version, (char*) KernelVersion, 23) == 0 ) 
			if( CalcKernelCheckSum( kernel ) == data->CheckSum ) 
				break; 
	} 
 
	if( i==MGRCOPYNUM ) 
	{ 
		KernelInst = False; 
		delete kernel; 
		delete mbr; 
		return 0x502; 
	} 
 
	if( !IsLoaderInst()) 
	{ 
    	UseInt13Ext = (Boolean)( data->NotUseInt13Ext == 0 ); 
        if( UseInt13Ext ) 
        { 
			for( i=0; iKernelAddr[i].Sector; 
            AddrNewToOld(); 
        } 
        else 
        { 
			for( i=0; iKernelAddr[i].old; 
            AddrOldToNew(); 
        } 
	} 
 
	totalSon = Root->GetTotalSonNumber(); 
	PartNum = 0; 
	father=NULL; 
	for( i=0; i< totalSon && PartNumFindSonByIndex(i); 
		if( son!=NULL && father!=son->Father ) 
		{ 
			father = son->Father; 
			SonIndex = 0; 
		} 
		if( son!=NULL && son->IsUseable() && 
			son->GetType()!=0 && son->IsBootable() ) 
		{ 
			entry = data->BootPartList + PartNum; 
			entry->State = son->GetState(); 
			entry->Type = son->GetType(); 
			entry->Hidden = son->GetType(); 
			entry->Index = SonIndex; 
			SonIndex ++; 
            if( UseInt13Ext ) 
            { 
				entry->FatherAddr.Sector = son->Father->GetAbsSector(); 
				entry->AbsAddr.Sector = son->GetAbsSector(); 
            } 
            else 
            { 
            	son->Father->GetRecord( record ); 
                entry->FatherAddr.old.Head = record.StartHead; 
                entry->FatherAddr.old.CyldSect = record.StartSC; 
                son->GetRecord( record ); 
                entry->AbsAddr.old.Head = record.StartHead; 
                entry->AbsAddr.old.CyldSect = record.StartSC; 
            } 
			entry->RelativeSect = son->GetRelativeSector(); 
			strncpy( (char*) entry->Name, son->GetName(), MAXPTNAMELENGTH ); 
			entry->Name[MAXPTNAMELENGTH]=0; 
 
			for( int i=strlen((char*) entry->Name); iName[i]=0x20; 
			PartNum ++; 
		} 
	} 
 
	for( i=PartNum; iBootPartList + i; 
		memset( entry, 0, sizeof( TBootPartEntry ) ); 
	} 
 
	memcpy( data->MainPartTable, mbr + PTTABOFFSET, 
			sizeof( TPartitionRecord ) * MAXPTNUMBER ); 
 
    data->DriveNumber = Root->GetHardDrive()->GetDriveNumber(); 
 
	data->CheckSum = CalcKernelCheckSum( kernel ); 
 
	for( i=0; iWrite( KernelSect[i], KERNELSECTS, kernel ); 
 
	for( i=0; iRead(0, 1, loader)) != 0 ) 
	{ 
		delete loader; 
		return errno; 
	} 
 
	if( strncmp((char*) data->Version, (char*) LoaderVersion, 16) == 0 && 
		data->DriveNumber == Root->GetHardDrive()->GetDriveNumber() ) 
	{ 
		errno = 0; 
        UseInt13Ext = (Boolean) ( data->NotUseInt13Ext == 0 ); 
        if( UseInt13Ext ) 
        { 
			for( i=0; iKernelAddr[i].Sector; 
            AddrNewToOld(); 
        } 
        else 
        { 
        	for( i=0; iKernelAddr[i].old; 
            AddrOldToNew(); 
        } 
		VirusCheck = data->VirusSwitch; 
	} 
	else errno = 1; 
 
	delete loader; 
	if( errno==0 ) LoaderInst = True; 
	return errno; 
 
} 
 
int32 TBootManager::ReadKernel() 
{ 
	BYTE *kernel; 
	TKernelData *data; 
	int32 errno; 
	int32 i; 
	TPartition *son; 
	int32 totalSon; 
	int32 index; 
    TPartitionRecord record; 
 
	if( !IsUseable() ) return 0x503; 
 
	totalSon = Root->GetTotalSonNumber(); 
 
	for( index=0; indexFindSonByIndex(index); 
		if( son!=NULL && son->IsUseable() && son->GetType()!=0 
			&& !son->IsNewPartition() ) 
			son->MarkBootable( False ); 
	} 
 
	if( (kernel = new BYTE[KERNELSIZE]) == NULL ) return 0x400; 
	data = (TKernelData *)( kernel + KERNELDATAOFFSET ); 
 
	for( i=0; iRead( KernelSect[i], KERNELSECTS, kernel ) == 0 && 
			strncmp((char*) data->Version, (char*) KernelVersion, 23) == 0 ) 
			if( CalcKernelCheckSum( kernel ) == data->CheckSum ) 
				break; 
	} 
	if( i==MGRCOPYNUM ) 
	{ 
		delete kernel; 
		KernelInst = False; 
		return 0x502; 
	} 
 
	if( !IsLoaderInst()) 
	{ 
    	UseInt13Ext = (Boolean)( data->NotUseInt13Ext == 0 ); 
        if( UseInt13Ext ) 
        { 
			for( i=0; iKernelAddr[i].Sector; 
            AddrNewToOld(); 
        } 
        else 
        { 
			for( i=0; iKernelAddr[i].old; 
            AddrOldToNew(); 
        } 
	} 
 
	memcpy( MainPartTable, data->MainPartTable, sizeof(TPartitionRecord) * MAXPTNUMBER ); 
 
	for( index=0; indexFindSonByIndex(index); 
		if( son!=NULL && son->IsUseable() && son->GetType()!=0 
			&& !son->IsNewPartition() ) 
		{ 
            son->GetRecord( record ); 
			for( i=0; i< BOOTMENUENTRYNUM; i++ ) 
			{ 
				if( data->BootPartList[i].Type != 0 ) 
                { 
                	if( (UseInt13Ext && (son->GetAbsSector() == data->BootPartList[i].AbsAddr.Sector)) || 
						(!UseInt13Ext && (record.StartHead == data->BootPartList[i].AbsAddr.old.Head) && 
                        (record.StartSC == data->BootPartList[i].AbsAddr.old.CyldSect)) ) 
					{ 
						for(int j=MAXPTNAMELENGTH-1; 
							data->BootPartList[i].Name[j] == 0x20 && j>=0; j-- ) 
 
						data->BootPartList[i].Name[j+1]=0; 
 
						son->SetName( (char*) data->BootPartList[i].Name ); 
						son->MarkBootable( True ); 
 
						if(	data->BootPartList[i].Type != HIDDENCODE && 
							son->GetType() == HIDDENCODE ) 
                        { 
							son->SetType( data->BootPartList[i].Type ); 
                            son->Father->MarkChanged( True ); 
                        } 
						break; 
					} 
                } 
			} 
		} 
	} 
	delete kernel; 
	KernelInst = True; 
	return 0; 
} 
 
int32 TBootManager::WriteLoader(int32 virus) 
{ 
	BYTE * loader; 
	TLoaderData *data; 
	int32 errno; 
 
	if( !IsUseable() ) return 0x502; 
 
	if( (loader=new BYTE[LOADERSIZE]) == NULL ) 
		return 0x400; 
 
	data = (TLoaderData*)(loader + LOADERDATAOFFSET); 
 
	if( (errno=Root->Read(0, 1, loader)) != 0 ) 
	{ 
		delete loader; 
		return errno; 
	} 
 
    if( UseInt13Ext ) 
		memcpy( loader, LoaderCode, PTTABOFFSET - 1 ); 
    else memcpy( loader, LoaderCodeOld, PTTABOFFSET - 1 ); 
 
	*((WORD*)(loader + LOADERSIZE - 2)) = GOODPTID; 
 
	memcpy( data->Version, LoaderVersion, strlen( (char*) LoaderVersion ) ); 
	data->DriveNumber = Root->GetHardDrive()->GetDriveNumber(); 
	data->VirusSwitch = virus; 
 
    if( UseInt13Ext ) 
    { 
		for( int i=0; i< MGRCOPYNUM; i++ ) 
			data->KernelAddr[i].Sector = KernelSect[i]; 
    } 
    else 
    { 
		for( int i=0; i< MGRCOPYNUM; i++ ) 
			data->KernelAddr[i].old = KernelOldAddr[i]; 
    } 
 
	errno = Root->Write(0, 1, loader); 
	delete loader; 
 
	return errno; 
} 
 
int32 TBootManager::WriteKernel(int32 language, int32 delayTime, int32 autoHide) 
{ 
	BYTE *kernel; 
	BYTE *mbr; 
	TKernelData *data; 
	int32 errno,writeError[MGRCOPYNUM]; 
    int i; 
 
	if( !IsUseable() ) return 0x503; 
 
	if( (kernel = new BYTE[KERNELSIZE]) == NULL ) return 0x400; 
	if( (mbr = new BYTE[LOADERSIZE]) == NULL ) 
	{ 
		delete kernel; 
		return 0x400; 
	} 
	data = (TKernelData *)( kernel + KERNELDATAOFFSET ); 
 
	if( (errno = Root->Read(0, 1, mbr)) != 0 ) 
	{ 
		delete mbr; 
		delete kernel; 
		return errno; 
	} 
 
    if( UseInt13Ext ) 
    { 
		if( language == BTMGRENG ) 
			memcpy( kernel, KernelEngCode, KERNELSIZE ); 
		else memcpy( kernel, KernelChnCode, KERNELSIZE ); 
    } 
    else 
    { 
		if( language == BTMGRENG ) 
			memcpy( kernel, KernelEngCodeOld, KERNELSIZE ); 
		else memcpy( kernel, KernelChnCodeOld, KERNELSIZE ); 
    } 
 
	memset( data, 0, sizeof( TKernelData ) ); 
 
    if( UseInt13Ext ) data->NotUseInt13Ext = 0; 
    else data->NotUseInt13Ext = 1; 
 
	memcpy( data->MainPartTable, mbr + PTTABOFFSET, 
			sizeof( TPartitionRecord) * MAXPTNUMBER ); 
 
	strcpy( (char*) data->Version, (char*) KernelVersion ); 
 
    if( UseInt13Ext ) 
	{ 
		for( i=0; iKernelAddr[i].Sector = KernelSect[i]; 
	} 
	else 
	{ 
		for( i=0; i< MGRCOPYNUM; i++ ) 
			data->KernelAddr[i].old = KernelOldAddr[i]; 
	} 
 
	data->DriveNumber = Root->GetHardDrive()->GetDriveNumber(); 
	data->OriginTime = delayTime; 
	if( autoHide != 0 )	data->AutoHide = 1; 
	else data->AutoHide = 0; 
 
	data->CheckSum = CalcKernelCheckSum( kernel ); 
 
	for( i=0; iWrite( KernelSect[i], KERNELSECTS, kernel ); 
 
	for( i=0; iRead( 0, 1, mbr )) == 0 ) 
	{ 
		memcpy( mbr, MasterBootCode, PTTABOFFSET - 1 ); 
		*((WORD*)(mbr + LOADERSIZE - 2)) = GOODPTID; 
 
		if( IsKernelInst() && Rescue ) 
			memcpy(mbr + PTTABOFFSET, MainPartTable, 
				sizeof( TPartitionRecord ) * MAXPTNUMBER ); 
 
		errno = Root->Write( 0, 1, mbr ); 
		delete mbr; 
	} 
 
	if( IsKernelInst() && errno== 0 ) 
		errno =WriteLoader(VirusCheck); 
 
	if( errno == 0 ) 
		ReadLoader(); 
 
	return errno; 
} 
 
Boolean TBootManager::IsPartTableChanged() 
{ 
	BYTE *mbr; 
	TPartitionRecord *record; 
 
	if( !IsUseable() ) return False; 
 
	if( !IsKernelInst() ) return False; 
 
	if( (mbr= new BYTE[LOADERSIZE]) == NULL ) return False; 
	if( Root->Read( 0, 1, mbr ) == 0 ) 
	{ 
		record = (TPartitionRecord*)( mbr + PTTABOFFSET ); 
		for( int i=0; iSon != NULL && Root->Son->GetAbsSector()>=MINRESERVEDSECT) ); 
} 
 
void TBootManager::AddrNewToOld() 
{ 
    WORD Cyld,Head,Sector; 
	if( !IsUseable() ) return; 
    for( int i=0;iGetHardDrive()->LBAtoCHS(KernelSect[i],Cyld,Head,Sector); 
        KernelOldAddr[i].Head = (BYTE)Head; 
        KernelOldAddr[i].CyldSect = Sector & 0x003F; 
        KernelOldAddr[i].CyldSect |= ((Cyld << 8) & 0xFF00); 
        KernelOldAddr[i].CyldSect |= ((Cyld & 0x0300) >> 2); 
    } 
} 
 
void TBootManager::AddrOldToNew() 
{ 
    WORD Cyld,Sector; 
	QWORD tmp; 
	if( !IsUseable() ) return; 
    for( int i=0;i> 8) | ((KernelOldAddr[i].CyldSect <<2) & 0x0300); 
        Root->GetHardDrive()->CHStoLBA(Cyld,KernelOldAddr[i].Head,Sector,tmp); 
        KernelSect[i] = (DWORD) tmp; 
    } 
}