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;
}
}