home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-386-Vol-2of3.iso
/
b
/
bootse.zip
/
BOOTSECT.C
next >
Wrap
C/C++ Source or Header
|
1992-08-04
|
17KB
|
529 lines
/**** Copyright (c) 1992 The Binary Tool Foundry. All rights reserved. ******
Project: Miscellaneous Tools Compuserve: 70760,2663
Author : Marcus Redivo Address : The Binary Tool Foundry
Date : July 1992 4684 Sunnymead Way
Module : bootsect.c Victoria, BC V8Y 2V5 Canada
******** WARNING ********
THIS PROGRAM CAN TRASH YOUR DRIVE C:!
******** WARNING ********
This program is provided for your use on an "as is" basis, and no
representation is made that it will work as documented on any particular
system. It is UP TO YOU to verify that the program will do no harm to your
system before executing it. See the notes below for a program overview.
Abstract:
The purpose of this program is to save the Microsoft Windows NT boot
sector in the active partition of drive C: and subsequently reinstall
either the DOS or NT boot sectors on demand. The boot sector data is
stored in the root directory of drive C: in files C:\BOOTSECT.DOS and
C:\BOOTSECT.NT. The program does this by doing absolute sector IO to
drive C:, which this program can only do in real addressing mode.
Note that if the wrong sector or the wrong data is written, the result
can be catastrophic to the data on drive C:.
Syntax:
bootsect [-save | -nt | -dos]
Options:
No option : Identify the current boot sector.
-save : Save the current boot sector to the appropriate file.
-nt : Install the Windows NT boot sector.
-dos : Install the DOS boot sector.
Operational notes:
This program must be run from DOS in real mode. It will not work
properly from a DOS box in protected mode.
This program loads the partition table from Drive C: to determine
which partition is the current boot partition. It ensures that this
partition is a DOS FAT file system, and is NOT an extended partition
(type 0x05). (This is only because I cannot test this with the equipment
available to me. If you can make it work, go right ahead and make the
necessary changes to allow this type.)
It then loads the boot sector from the active partition, and determines
whether it is a DOS or NT boot sector. (Again, I don't check for OS/2
because I don't have any means of researching or testing it.)
If you have requested saving the boot sector, it opens the appropriate
file (C:\BOOTSECT.DOS or C:\BOOTSECT.NT) and writes the boot sector
into it.
If you have requested installation of a boot sector, it opens the
appropriate file (C:\BOOTSECT.DOS or C:\BOOTSECT.NT) and validates it.
If the file checks out OK, it is installed and the program terminates.
****************************************************************************/
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <io.h>
#include <dos.h>
#include <sys\types.h>
#include <sys\stat.h>
#define DISK_SECTOR_SIZE 0x200
#define BOOT_SIGNATURE 0xAA55
#define BOOT_IS_NT 1
#define BOOT_IS_DOS 2
#define DISPLAY_CURRENT_STATUS 0
#define SAVE_CURRENT_BOOTSECT 1
#define INSTALL_NT_BOOTSECT 2
#define INSTALL_DOS_BOOTSECT 3
#define TRUE 1
#define FALSE 0
typedef unsigned char BYTE;
typedef unsigned int UINT;
typedef unsigned long ULONG;
#pragma pack(1)
typedef struct PTEntryTag
{
BYTE Active;
BYTE StartingHead;
BYTE StartingSector; /* Upper two bits are high bits of Cylinder. */
BYTE StartingCylinder;
BYTE PartitionType;
BYTE EndingHead;
BYTE EndingSector; /* Upper two bits are high bits of Cylinder. */
BYTE EndingCylinder;
ULONG PartitionStartSector;
ULONG PartitionLength;
} PTEntryT;
typedef struct PTableTag
{
BYTE LoaderPgm[DISK_SECTOR_SIZE - ((sizeof (PTEntryT) * 4) + sizeof (int))];
PTEntryT PTable[4];
UINT Signature;
} PTableT;
typedef struct BootSectorTag
{
BYTE JumpInstruction[3];
BYTE BIOSParameterBlock[59];
BYTE LoaderPgm[DISK_SECTOR_SIZE - (3 + 59 + sizeof (int))];
UINT Signature;
} BootSectorT;
#pragma pack()
/****************************************************************************
Global/Static Variables.
****************************************************************************/
extern unsigned char _osmajor;
static char szNTBootSectorFile[_MAX_PATH] = "c:\\bootsect.nt";
static char szDOSBootSectorFile[_MAX_PATH] = "c:\\bootsect.dos";
static char szBootSectorFile[_MAX_PATH];
static int hBootSectorFile;
static BootSectorT DiskBootSector;
static BootSectorT FileBootSector;
static PTableT MasterBootRecord;
/****************************************************************************
Function Declarations.
****************************************************************************/
int ReadAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
void _far *Buffer);
int WriteAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
void _far *Buffer);
int SearchSector(BYTE *Sector, char *String);
/***************************************************************************
Function . . : main()
Purpose . . : See abstract.
*/
main(int argc, char *argv[])
{
int Operation, ActivePartition, CurrentBootSector, bFileOK = TRUE;
/* Ensure we are operating at DOS 3.0 or better. */
if (_osmajor < 3)
{
printf("DOS 3.0 or higher required.\n");
exit(-1);
}
/* Determine what action has been requested. */
if (argc == 1)
{
Operation = DISPLAY_CURRENT_STATUS;
}
else
{
switch (tolower(argv[1][1]))
{
case 's': /* -save - Save current boot sector. */
Operation = SAVE_CURRENT_BOOTSECT;
break;
case 'n': /* -nt - Install NT boot sector. */
Operation = INSTALL_NT_BOOTSECT;
break;
case 'd': /* -dos - Install DOS boot sector. */
Operation = INSTALL_DOS_BOOTSECT;
break;
default:
printf("\nBOOTSECT v1.00 - Manipulate Drive C: Boot Sector\n");
printf("Copyright (c) The Binary Tool Foundry 1992.\n\n");
printf("Syntax: bootsect [-save | -nt | -dos]\n\n");
printf(" No option : Identify the current boot sector.\n");
printf(" -save : Save the current boot sector to file.\n");
printf(" -nt : Install the Windows NT boot sector.\n");
printf(" -dos : Install the DOS boot sector.\n");
exit(-1);
break;
}
}
/* Determine where the boot sector is by reading partition table. */
if (ReadAbsSector('C', 0, 0, 1, &MasterBootRecord) != 0)
{
printf("Unable to extract partition table information.\n");
exit(-1);
}
/* Validate the partition table sector. */
if (MasterBootRecord.Signature != BOOT_SIGNATURE)
{
printf("Invalid partition table!\n");
exit(-1);
}
/* Find the partition we booted from and validate it. */
for (ActivePartition=0; ActivePartition<4; ActivePartition++)
{
if (MasterBootRecord.PTable[ActivePartition].Active == 0x80)
break;
}
if (ActivePartition > 3)
{
printf("No bootable partition in table!\n");
exit(-1);
}
if ((MasterBootRecord.PTable[ActivePartition].PartitionType != 0x01) &&
(MasterBootRecord.PTable[ActivePartition].PartitionType != 0x04) &&
(MasterBootRecord.PTable[ActivePartition].PartitionType != 0x06))
{
printf("Unable to work with partition type %02x.\n",
MasterBootRecord.PTable[ActivePartition].PartitionType);
exit(-1);
}
/* Get the boot sector from active partition. */
if (ReadAbsSector('C',
MasterBootRecord.PTable[ActivePartition].StartingHead,
MasterBootRecord.PTable[ActivePartition].StartingCylinder,
MasterBootRecord.PTable[ActivePartition].StartingSector,
&DiskBootSector) != 0)
{
printf("Unable to read fixed disk boot sector.\n");
exit(-1);
}
/* Validate the boot sector. */
if (DiskBootSector.Signature != BOOT_SIGNATURE)
{
printf("Invalid boot sector!\n");
exit(-1);
}
/* Determine whether NT or DOS boot sector is currently installed. */
if (SearchSector(DiskBootSector.LoaderPgm, "NTLDR"))
{
CurrentBootSector = BOOT_IS_NT;
}
else if (SearchSector(DiskBootSector.LoaderPgm, "Non-System"))
{
CurrentBootSector = BOOT_IS_DOS;
}
else
{
printf("Unable to identify current boot sector contents.\n");
exit(-1);
}
/* At last! Perform specified action. */
switch (Operation)
{
case DISPLAY_CURRENT_STATUS:
if (CurrentBootSector == BOOT_IS_NT)
printf("Current boot sector is for Windows NT.\n");
else if (CurrentBootSector == BOOT_IS_DOS)
printf("Current boot sector is for DOS.\n");
break;
case SAVE_CURRENT_BOOTSECT:
if (CurrentBootSector == BOOT_IS_NT)
strcpy(szBootSectorFile, szNTBootSectorFile);
else if (CurrentBootSector == BOOT_IS_DOS)
strcpy(szBootSectorFile, szDOSBootSectorFile);
if ((hBootSectorFile = _open(szBootSectorFile,
_O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY,
_S_IREAD | _S_IWRITE)) == -1)
{
printf("Unable to create/open boot sector file %s.\n",
szBootSectorFile);
exit(-1);
}
else
{
if (_write(hBootSectorFile, &DiskBootSector, DISK_SECTOR_SIZE)
!= DISK_SECTOR_SIZE)
{
printf("Unable to write boot sector file %s.\n",
szBootSectorFile);
}
else
{
if (CurrentBootSector == BOOT_IS_NT)
printf("Boot sector for Windows NT saved in %s.\n",
szBootSectorFile);
else if (CurrentBootSector == BOOT_IS_DOS)
printf("Boot sector for DOS saved in %s.\n",
szBootSectorFile);
}
_close(hBootSectorFile);
}
break;
case INSTALL_NT_BOOTSECT:
case INSTALL_DOS_BOOTSECT:
if (Operation == INSTALL_NT_BOOTSECT)
strcpy(szBootSectorFile, szNTBootSectorFile);
else if (Operation == INSTALL_DOS_BOOTSECT)
strcpy(szBootSectorFile, szDOSBootSectorFile);
if ((hBootSectorFile = _open(szBootSectorFile,
_O_BINARY | _O_RDONLY )) == -1)
{
printf("Unable to open boot sector file %s.\n", szBootSectorFile);
exit(-1);
}
else
{
/* Read in the boot sector and validate it. */
if (_read(hBootSectorFile, &FileBootSector, DISK_SECTOR_SIZE)
!= DISK_SECTOR_SIZE)
{
printf("Corrupt boot sector file %s.\n", szBootSectorFile);
bFileOK = FALSE;
}
else
{
if ( FileBootSector.Signature != BOOT_SIGNATURE ||
( !SearchSector(FileBootSector.LoaderPgm, "NTLDR") &&
!SearchSector(FileBootSector.LoaderPgm, "Non-System")))
{
printf("%s is not a valid boot sector.\n", szBootSectorFile);
bFileOK = FALSE;
}
else
{
/* Ensure that the boot sector is for THIS drive. */
if (memcmp(DiskBootSector.BIOSParameterBlock,
FileBootSector.BIOSParameterBlock,
sizeof FileBootSector.BIOSParameterBlock))
{
printf("%s disk parameters do not match current boot sector.\n",
szBootSectorFile);
bFileOK = FALSE;
}
}
}
/* If the boot sector is OK, install it. */
if (bFileOK)
{
if (WriteAbsSector('C',
MasterBootRecord.PTable[ActivePartition].StartingHead,
MasterBootRecord.PTable[ActivePartition].StartingCylinder,
MasterBootRecord.PTable[ActivePartition].StartingSector,
&FileBootSector) != 0)
{
printf("Unable to write boot sector.\n");
bFileOK = FALSE;
}
else
{
if (Operation == INSTALL_NT_BOOTSECT)
printf("Boot sector for Windows NT installed.\n");
else if (Operation == INSTALL_DOS_BOOTSECT)
printf("Boot sector for DOS installed.\n");
}
}
_close(hBootSectorFile);
if (!bFileOK)
exit(-1);
}
break;
}
return(0);
}
/***************************************************************************
Function . . : ReadAbsSector()
Purpose . . : Read an absolute sector from a disk into buffer.
*/
int ReadAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
void _far *Buffer)
{
int BufferSegmnt = _FP_SEG(Buffer);
int BufferOffset = _FP_OFF(Buffer);
BYTE DriveNumber;
switch (Drive)
{
case 'A': DriveNumber = 0x00; break;
case 'B': DriveNumber = 0x01; break;
case 'C': DriveNumber = 0x80; break;
default: return(1);
}
_asm
{
mov ah, 2 ; Read sectors operation
mov al, 1 ; 1 sector
mov dl, DriveNumber
mov dh, Head
mov ch, Track
mov cl, Sector
mov es, BufferSegmnt
mov bx, BufferOffset
int 13h ; BIOS fixed disk routines.
jc RPTErr ; Carry indicates error, AX nonzero.
cmp al, 1 ; 1 sector transferred?
jne RPTErr ; If not, error occurred.
xor ax, ax ; Clear AX to indicate success.
RPTErr:
}
/* Return value present in AX register. */
}
/***************************************************************************
Function . . : WriteAbsSector()
Purpose . . : Write an absolute sector from buffer to a disk.
*/
int WriteAbsSector(BYTE Drive, BYTE Head, BYTE Track, BYTE Sector,
void _far *Buffer)
{
int BufferSegmnt = _FP_SEG(Buffer);
int BufferOffset = _FP_OFF(Buffer);
BYTE DriveNumber;
switch (Drive)
{
case 'A': DriveNumber = 0x00; break;
case 'B': DriveNumber = 0x01; break;
case 'C': DriveNumber = 0x80; break;
default: return(1);
}
_asm
{
mov ah, 3 ; Write sectors operation
mov al, 1 ; 1 sector
mov dl, DriveNumber
mov dh, Head
mov ch, Track
mov cl, Sector
mov es, BufferSegmnt
mov bx, BufferOffset
int 13h ; BIOS fixed disk routines.
jc RPTErr ; Carry indicates error, AX nonzero.
cmp al, 1 ; 1 sector transferred?
jne RPTErr ; If not, error occurred.
xor ax, ax ; Clear AX to indicate success.
RPTErr:
}
/* Return value present in AX register. */
}
/***************************************************************************
Function . . : SearchSector()
Purpose . . : Verify existence of a distinguishing string in a sector.
*/
int SearchSector(BYTE *Sector, char *String)
{
BYTE *SectorEnd = Sector + DISK_SECTOR_SIZE;
for (Sector = memchr(Sector, String[0], DISK_SECTOR_SIZE);
Sector != NULL && Sector < SectorEnd;
Sector = memchr(Sector+1, String[0], SectorEnd - Sector))
{
if (!memicmp(Sector, String, strlen(String)))
return(1);
}
return(0);
}