You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
755 lines
21 KiB
755 lines
21 KiB
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
bootsect.c
|
|
|
|
Abstract:
|
|
|
|
This module implements access to the boot sector.
|
|
|
|
Author:
|
|
|
|
Wesley Witt (wesw) 21-Oct-1998
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "cmdcons.h"
|
|
#pragma hdrstop
|
|
|
|
#include <boot98f.h>
|
|
#include <boot98f2.h>
|
|
#include <boot98n.h>
|
|
#include <bootetfs.h>
|
|
#include <bootf32.h>
|
|
#include <bootfat.h>
|
|
#include <bootntfs.h>
|
|
|
|
#pragma hdrstop
|
|
|
|
extern unsigned ConsoleX;
|
|
|
|
WCHAR TemporaryBuffer[16384];
|
|
WCHAR DriveLetterSpecified;
|
|
BOOLEAN DidIt;
|
|
|
|
NTSTATUS
|
|
pSpBootCodeIoC(
|
|
IN PWSTR FilePath,
|
|
IN PWSTR AdditionalFilePath, OPTIONAL
|
|
IN ULONG BytesToRead,
|
|
IN PUCHAR *Buffer,
|
|
IN ULONG OpenDisposition,
|
|
IN BOOLEAN Write,
|
|
IN ULONGLONG Offset,
|
|
IN ULONG BytesPerSector
|
|
);
|
|
|
|
VOID
|
|
SpDetermineOsTypeFromBootSectorC(
|
|
IN PWSTR CColonPath,
|
|
IN PUCHAR BootSector,
|
|
OUT PUCHAR *OsDescription,
|
|
OUT PBOOLEAN IsNtBootcode,
|
|
OUT PBOOLEAN IsOtherOsInstalled,
|
|
IN WCHAR DriveLetter
|
|
);
|
|
|
|
// prototypes
|
|
ULONG
|
|
RcStampBootSectorOntoDisk(
|
|
VOID
|
|
);
|
|
|
|
BOOL
|
|
RcEnumDiskRegionsCallback(
|
|
IN PPARTITIONED_DISK Disk,
|
|
IN PDISK_REGION Region,
|
|
IN ULONG_PTR Ignore
|
|
);
|
|
|
|
VOID
|
|
RcLayBootCode(
|
|
IN OUT PDISK_REGION CColonRegion
|
|
);
|
|
|
|
|
|
|
|
ULONG
|
|
RcCmdFixBootSect(
|
|
IN PTOKENIZED_LINE TokenizedLine
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Top-level routine supporting the FIXBOOT command in the setup diagnostic
|
|
command interpreter.
|
|
|
|
FIXBOOT writes a new bootsector onto the system partition.
|
|
|
|
Arguments:
|
|
|
|
TokenizedLine - supplies structure built by the line parser describing
|
|
each string on the line as typed by the user.
|
|
|
|
Return Value:
|
|
|
|
TRUE.
|
|
|
|
--*/
|
|
|
|
{
|
|
/*
|
|
WCHAR szText[2];
|
|
PWSTR szYesNo = NULL;
|
|
BOOLEAN bConfirmed = FALSE;
|
|
WCHAR szMsg[512] = {0};
|
|
PWSTR szDriveSpecified = 0;
|
|
PWSTR szConfirmMsg = 0;
|
|
*/
|
|
|
|
if (RcCmdParseHelp(TokenizedLine, MSG_FIXBOOT_HELP)) {
|
|
return 1;
|
|
}
|
|
|
|
if (TokenizedLine->TokenCount == 2) {
|
|
//
|
|
// a drive letter is specified
|
|
//
|
|
DriveLetterSpecified = TokenizedLine->Tokens->Next->String[0];
|
|
// szDriveSpecified = TokenizedLine->Tokens->Next->String;
|
|
} else {
|
|
DriveLetterSpecified = 0;
|
|
}
|
|
|
|
/*
|
|
if (!InBatchMode) {
|
|
szYesNo = SpRetreiveMessageText(ImageBase, MSG_YESNO, NULL, 0);
|
|
szConfirmMsg = SpRetreiveMessageText(ImageBase,
|
|
MSG_FIXBOOT_ARE_YOU_SURE, NULL, 0);
|
|
|
|
if(!szYesNo || !szConfirmMsg) {
|
|
bConfirmed = TRUE;
|
|
}
|
|
|
|
while (!bConfirmed) {
|
|
swprintf(szMsg, szConfirmMsg, szDriveSpecified);
|
|
RcTextOut(szMsg);
|
|
|
|
if(RcLineIn(szText,2)) {
|
|
if((szText[0] == szYesNo[0]) || (szText[0] == szYesNo[1])) {
|
|
//
|
|
// Wants to do it.
|
|
//
|
|
bConfirmed = TRUE;
|
|
} else {
|
|
if((szText[0] == szYesNo[2]) || (szText[0] == szYesNo[3])) {
|
|
//
|
|
// Doesn't want to do it.
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (bConfirmed)
|
|
*/
|
|
RcStampBootSectorOntoDisk();
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
ULONG
|
|
RcStampBootSectorOntoDisk(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Setup the enumerate disk regions call, so we can do the boot sector.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
TRUE.
|
|
|
|
--*/
|
|
|
|
|
|
{
|
|
// enumerate the partitions
|
|
DidIt = FALSE;
|
|
|
|
SpEnumerateDiskRegions( (PSPENUMERATEDISKREGIONS)RcEnumDiskRegionsCallback, 1 );
|
|
|
|
if (!DidIt) {
|
|
RcMessageOut( MSG_FIXBOOT_INVALID );
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL
|
|
RcEnumDiskRegionsCallback(
|
|
IN PPARTITIONED_DISK Disk,
|
|
IN PDISK_REGION Region,
|
|
IN ULONG_PTR Ignore
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Callback routine passed to SpEnumDiskRegions.
|
|
|
|
Arguments:
|
|
|
|
Region - a pointer to a disk region returned by SpEnumDiskRegions
|
|
Ignore - ignored parameter
|
|
|
|
Return Value:
|
|
|
|
TRUE - to continue enumeration
|
|
FALSE - to end enumeration
|
|
|
|
--*/
|
|
|
|
{
|
|
if (Region->PartitionedSpace) {
|
|
if (DriveLetterSpecified) {
|
|
if( RcToUpper(DriveLetterSpecified) == RcToUpper(Region->DriveLetter) ) {
|
|
RcMessageOut( MSG_FIXBOOT_INFO1, Region->DriveLetter );
|
|
RcLayBootCode( Region );
|
|
DidIt = TRUE;
|
|
return FALSE;
|
|
}
|
|
|
|
} else if (Region->IsSystemPartition) {
|
|
DEBUG_PRINTF(( "system partition is %wc\n", Region->DriveLetter ));
|
|
RcMessageOut( MSG_FIXBOOT_INFO1, Region->DriveLetter );
|
|
RcLayBootCode( Region );
|
|
DidIt = TRUE;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
VOID
|
|
RcLayBootCode(
|
|
IN OUT PDISK_REGION CColonRegion
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
RcLayBootCode contains the code that replaces the boot sector on the
|
|
targetted disk region.
|
|
|
|
Arguments:
|
|
|
|
CColonRegion - the startup partition for the system.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
|
|
{
|
|
PUCHAR NewBootCode;
|
|
ULONG BootCodeSize;
|
|
PUCHAR ExistingBootCode = NULL;
|
|
NTSTATUS Status;
|
|
NTSTATUS rc;
|
|
PUCHAR ExistingBootCodeOs = NULL;
|
|
PWSTR CColonPath;
|
|
HANDLE PartitionHandle;
|
|
//PWSTR BootsectDosName = L"\\bootsect.dos";
|
|
//PWSTR OldBootsectDosName = L"\\bootsect.bak";
|
|
//PWSTR BootSectDosFullName, OldBootSectDosFullName, p;
|
|
BOOLEAN IsNtBootcode,OtherOsInstalled, FileExist;
|
|
UNICODE_STRING UnicodeString;
|
|
OBJECT_ATTRIBUTES Obja;
|
|
IO_STATUS_BLOCK IoStatusBlock;
|
|
BOOLEAN BootSectorCorrupt = FALSE;
|
|
ULONG MirrorSector;
|
|
ULONG BytesPerSector;
|
|
ULONG SectorsPerTrack;
|
|
ULONG TracksPerCylinder;
|
|
ULONGLONG ActualSectorCount, hidden_sectors, super_area_size;
|
|
UCHAR SysId;
|
|
ULONGLONG HiddenSectorCount,VolumeSectorCount; //NEC98
|
|
PUCHAR DiskArraySectorData,TmpBuffer; //NEC98
|
|
IO_STATUS_BLOCK StatusBlock;
|
|
UCHAR InfoBuffer[2048];
|
|
WCHAR szText[2];
|
|
PWSTR szYesNo = NULL;
|
|
BOOLEAN bConfirmed = FALSE;
|
|
//WCHAR szMsg[512] = {0};
|
|
WCHAR szDriveSpecified[8] = {0};
|
|
|
|
if (!InBatchMode) {
|
|
//
|
|
// get confirmation from user before proceeding
|
|
//
|
|
szYesNo = SpRetreiveMessageText(ImageBase, MSG_YESNO, NULL, 0);
|
|
szDriveSpecified[0] = CColonRegion->DriveLetter;
|
|
szDriveSpecified[1] = L':';
|
|
szDriveSpecified[2] = 0;
|
|
|
|
if(!szYesNo || !szDriveSpecified[0]) {
|
|
bConfirmed = TRUE;
|
|
}
|
|
|
|
while (!bConfirmed) {
|
|
RcMessageOut(MSG_FIXBOOT_ARE_YOU_SURE, szDriveSpecified);
|
|
|
|
if(RcLineIn(szText,2)) {
|
|
if((szText[0] == szYesNo[0]) || (szText[0] == szYesNo[1])) {
|
|
//
|
|
// Wants to do it.
|
|
//
|
|
bConfirmed = TRUE;
|
|
} else {
|
|
if((szText[0] == szYesNo[2]) || (szText[0] == szYesNo[3])) {
|
|
//
|
|
// Doesn't want to do it.
|
|
//
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!bConfirmed)
|
|
return; // user did not want to proceed
|
|
|
|
switch( CColonRegion->Filesystem ) {
|
|
case FilesystemNewlyCreated:
|
|
//
|
|
// If the filesystem is newly-created, then there is
|
|
// nothing to do, because there can be no previous
|
|
// operating system.
|
|
//
|
|
return;
|
|
|
|
case FilesystemNtfs:
|
|
NewBootCode = (!IsNEC_98) ? NtfsBootCode : PC98NtfsBootCode; //NEC98
|
|
BootCodeSize = (!IsNEC_98) ? sizeof(NtfsBootCode) : sizeof(PC98NtfsBootCode); //NEC98
|
|
ASSERT(BootCodeSize == 8192);
|
|
RcMessageOut( MSG_FIXBOOT_FS, L"NTFS" );
|
|
break;
|
|
|
|
case FilesystemFat:
|
|
NewBootCode = (!IsNEC_98) ? FatBootCode : PC98FatBootCode; //NEC98
|
|
BootCodeSize = (!IsNEC_98) ? sizeof(FatBootCode) : sizeof(PC98FatBootCode); //NEC98
|
|
ASSERT(BootCodeSize == 512);
|
|
RcMessageOut( MSG_FIXBOOT_FS, L"FAT" );
|
|
break;
|
|
|
|
case FilesystemFat32:
|
|
//
|
|
// Special hackage required for Fat32 because its NT boot code
|
|
// is discontiguous.
|
|
//
|
|
ASSERT(sizeof(Fat32BootCode) == 1536);
|
|
NewBootCode = (!IsNEC_98) ? Fat32BootCode : PC98Fat32BootCode; //NEC98
|
|
BootCodeSize = 512;
|
|
RcMessageOut( MSG_FIXBOOT_FS, L"FAT32" );
|
|
break;
|
|
|
|
default:
|
|
// we assume that the boot sector is corrupt if it is
|
|
// not a FAT or NTFS boot partition.
|
|
BootSectorCorrupt = TRUE;
|
|
DEBUG_PRINTF(("CMDCONS: bogus filesystem %u for C:!\n",CColonRegion->Filesystem));
|
|
RcMessageOut( MSG_FIXBOOT_NO_VALID_FS );
|
|
}
|
|
|
|
//
|
|
// Form the device path to C: and open the partition.
|
|
//
|
|
|
|
SpNtNameFromRegion( CColonRegion,
|
|
TemporaryBuffer,
|
|
sizeof(TemporaryBuffer),
|
|
PartitionOrdinalCurrent );
|
|
|
|
CColonPath = SpDupStringW( TemporaryBuffer );
|
|
|
|
INIT_OBJA(&Obja,&UnicodeString,CColonPath);
|
|
|
|
Status = ZwCreateFile( &PartitionHandle,
|
|
FILE_GENERIC_READ | FILE_GENERIC_WRITE,
|
|
&Obja,
|
|
&IoStatusBlock,
|
|
NULL,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
|
FILE_OPEN,
|
|
FILE_SYNCHRONOUS_IO_NONALERT,
|
|
NULL,
|
|
0 );
|
|
|
|
if (!NT_SUCCESS(Status)) {
|
|
DEBUG_PRINTF(("CMDCONS: unable to open the partition for C:!\n"));
|
|
RcMessageOut( MSG_FIXBOOT_FAILED1 );
|
|
return;
|
|
}
|
|
|
|
//
|
|
// get disk geometry
|
|
//
|
|
|
|
rc = ZwDeviceIoControlFile( PartitionHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&StatusBlock,
|
|
IOCTL_DISK_GET_DRIVE_GEOMETRY,
|
|
NULL,
|
|
0,
|
|
InfoBuffer,
|
|
sizeof( InfoBuffer ) );
|
|
|
|
if (!NT_SUCCESS( rc )) {
|
|
|
|
RcMessageOut( MSG_FIXBOOT_READ_ERROR );
|
|
|
|
} else {
|
|
//
|
|
// retrieve the sector size and other info
|
|
//
|
|
BytesPerSector = ((DISK_GEOMETRY*)InfoBuffer)->BytesPerSector;
|
|
TracksPerCylinder = ((DISK_GEOMETRY*)InfoBuffer)->TracksPerCylinder;
|
|
SectorsPerTrack = ((DISK_GEOMETRY*)InfoBuffer)->SectorsPerTrack;
|
|
}
|
|
|
|
//
|
|
// Enable extended DASD I/O so we can read the last sector on the
|
|
// disk.
|
|
//
|
|
|
|
rc = ZwFsControlFile( PartitionHandle,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
&StatusBlock,
|
|
FSCTL_ALLOW_EXTENDED_DASD_IO,
|
|
NULL,
|
|
0,
|
|
NULL,
|
|
0 );
|
|
|
|
ASSERT( NT_SUCCESS(rc) );
|
|
|
|
//
|
|
// Allocate a buffer and read in the boot sector(s) currently on the disk.
|
|
//
|
|
|
|
if (BootSectorCorrupt) {
|
|
|
|
//
|
|
// The partition is UNKNOWN or cannot be determined by the system.
|
|
//
|
|
|
|
//
|
|
// We can't determine the file system type from the boot sector, so
|
|
// we assume it's NTFS if we find a mirror sector, and FAT otherwise.
|
|
//
|
|
|
|
RcMessageOut( MSG_FIXBOOT_DETERMINE );
|
|
DEBUG_PRINTF(( "BootSectorCorrupt TRUE\n" ));
|
|
|
|
//
|
|
// First, attempt to find an NTFS mirror boot sector.
|
|
//
|
|
|
|
MirrorSector = NtfsMirrorBootSector (PartitionHandle,
|
|
BytesPerSector,
|
|
&ExistingBootCode);
|
|
|
|
if (MirrorSector) {
|
|
|
|
//
|
|
// It's NTFS - use the mirror boot sector to recover the drive.
|
|
//
|
|
|
|
RcMessageOut( MSG_FIXBOOT_FOUND_NTFS );
|
|
|
|
NewBootCode = (!IsNEC_98) ? NtfsBootCode : PC98NtfsBootCode; //NEC98
|
|
BootCodeSize = (!IsNEC_98) ? sizeof(NtfsBootCode) : sizeof(PC98NtfsBootCode); //NEC98
|
|
ASSERT(BootCodeSize == 8192);
|
|
|
|
CColonRegion->Filesystem = FilesystemNtfs;
|
|
IsNtBootcode = TRUE;
|
|
|
|
} else {
|
|
|
|
//
|
|
// It's FAT - create a new boot sector since there's no mirror.
|
|
//
|
|
|
|
RcMessageOut( MSG_FIXBOOT_FOUND_FAT );
|
|
|
|
NewBootCode = (!IsNEC_98) ? FatBootCode : PC98FatBootCode; //NEC98
|
|
BootCodeSize = (!IsNEC_98) ? sizeof(FatBootCode) : sizeof(PC98FatBootCode); //NEC98
|
|
ASSERT(BootCodeSize == 512);
|
|
|
|
CColonRegion->Filesystem = FilesystemFat;
|
|
IsNtBootcode = FALSE;
|
|
|
|
SpPtGetSectorLayoutInformation( CColonRegion,
|
|
&hidden_sectors,
|
|
&ActualSectorCount );
|
|
|
|
//
|
|
// No alignment requirement here
|
|
//
|
|
|
|
ExistingBootCode = SpMemAlloc(BytesPerSector);
|
|
|
|
//
|
|
// This will actually fail with STATUS_BUFFER_TOO_SMALL
|
|
// but it will fill in the bpb info, which is what we want.
|
|
//
|
|
|
|
FmtFillFormatBuffer ( ActualSectorCount,
|
|
BytesPerSector,
|
|
SectorsPerTrack,
|
|
TracksPerCylinder,
|
|
hidden_sectors,
|
|
ExistingBootCode,
|
|
BytesPerSector,
|
|
&super_area_size,
|
|
NULL,
|
|
0,
|
|
&SysId );
|
|
|
|
}
|
|
|
|
Status = STATUS_SUCCESS;
|
|
|
|
} else if( CColonRegion->Filesystem == FilesystemNtfs ) {
|
|
|
|
//
|
|
// The partition is NTFS.
|
|
//
|
|
|
|
//
|
|
// We use the mirror sector to repair a NTFS file system
|
|
// if we can find one.
|
|
//
|
|
|
|
MirrorSector = NtfsMirrorBootSector( PartitionHandle,
|
|
BytesPerSector,
|
|
&ExistingBootCode );
|
|
|
|
if( !MirrorSector ) {
|
|
|
|
//
|
|
// Just use existing NTFS boot code.
|
|
//
|
|
Status = pSpBootCodeIoC( CColonPath,
|
|
NULL,
|
|
BootCodeSize,
|
|
&ExistingBootCode,
|
|
FILE_OPEN,
|
|
FALSE,
|
|
0,
|
|
BytesPerSector );
|
|
}
|
|
|
|
} else {
|
|
|
|
//
|
|
// The partition is FAT.
|
|
//
|
|
|
|
//
|
|
// Just use existing boot code since
|
|
// there is no mirror sector on FAT.
|
|
//
|
|
|
|
Status = pSpBootCodeIoC( CColonPath,
|
|
NULL,
|
|
BootCodeSize,
|
|
&ExistingBootCode,
|
|
FILE_OPEN,
|
|
FALSE,
|
|
0,
|
|
BytesPerSector );
|
|
|
|
}
|
|
|
|
if( NT_SUCCESS(Status) ) {
|
|
|
|
//
|
|
// Determine the type of operating system the existing boot sector(s) are for
|
|
// and whether that os is actually installed. Note that we don't need to call
|
|
// this for NTFS.
|
|
//
|
|
|
|
// RcMessageOut( MSG_FIXBOOT_CHECKING_OS );
|
|
|
|
if( BootSectorCorrupt ) {
|
|
|
|
//
|
|
// If the boot sector is corrupt, we don't assume
|
|
// another OS was installed.
|
|
//
|
|
|
|
OtherOsInstalled = FALSE;
|
|
ExistingBootCodeOs = NULL;
|
|
|
|
} else if( CColonRegion->Filesystem != FilesystemNtfs ) {
|
|
|
|
// If the file system is FAT, DOS could have been installed
|
|
// previously.
|
|
|
|
SpDetermineOsTypeFromBootSectorC( CColonPath,
|
|
ExistingBootCode,
|
|
&ExistingBootCodeOs,
|
|
&IsNtBootcode,
|
|
&OtherOsInstalled,
|
|
CColonRegion->DriveLetter );
|
|
|
|
} else {
|
|
|
|
//
|
|
// Otherwise, it's NTFS, and another OS type
|
|
// couldn't have been installed.
|
|
//
|
|
|
|
IsNtBootcode = TRUE;
|
|
OtherOsInstalled = FALSE;
|
|
ExistingBootCodeOs = NULL;
|
|
|
|
}
|
|
|
|
if( NT_SUCCESS(Status) ) {
|
|
|
|
//
|
|
// Transfer the bpb from the existing boot sector into the boot code buffer
|
|
// and make sure the physical drive field is set to hard disk (0x80).
|
|
//
|
|
// The first three bytes of the NT boot code are going to be something like
|
|
// EB 3C 90, which is intel jump instruction to an offset in the boot sector,
|
|
// past the BPB, to continue execution. We want to preserve everything in the
|
|
// current boot sector up to the start of that code. Instead of hard coding
|
|
// a value, we'll use the offset of the jump instruction to determine how many
|
|
// bytes must be preserved.
|
|
//
|
|
|
|
RtlMoveMemory(NewBootCode+3,ExistingBootCode+3,NewBootCode[1]-1);
|
|
|
|
if( CColonRegion->Filesystem != FilesystemFat32 ) {
|
|
//
|
|
// On fat32 this overwrites the BigNumFatSecs field,
|
|
// a very bad thing to do indeed!
|
|
//
|
|
NewBootCode[36] = 0x80;
|
|
}
|
|
|
|
//
|
|
// get Hidden sector informatin.
|
|
//
|
|
if( IsNEC_98 ) { //NEC98
|
|
SpPtGetSectorLayoutInformation(
|
|
CColonRegion,
|
|
&HiddenSectorCount,
|
|
&VolumeSectorCount // not used
|
|
);
|
|
} //NEC98
|
|
|
|
//
|
|
// Write out boot code buffer, which now contains the valid bpb,
|
|
// to the boot sector(s).
|
|
//
|
|
|
|
RcMessageOut( MSG_FIXBOOT_WRITING );
|
|
|
|
Status = pSpBootCodeIoC(
|
|
CColonPath,
|
|
NULL,
|
|
BootCodeSize,
|
|
&NewBootCode,
|
|
FILE_OPEN,
|
|
TRUE,
|
|
0,
|
|
BytesPerSector
|
|
);
|
|
|
|
|
|
//
|
|
// Special case for Fat32, which has a second sector of boot code
|
|
// at sector 12, discontiguous from the code on sector 0.
|
|
//
|
|
|
|
if( NT_SUCCESS(Status) && (CColonRegion->Filesystem == FilesystemFat32) ) {
|
|
|
|
NewBootCode = (!IsNEC_98) ? Fat32BootCode + 1024
|
|
: PC98Fat32BootCode + 1024; //NEC98
|
|
|
|
|
|
Status = pSpBootCodeIoC(
|
|
CColonPath,
|
|
NULL,
|
|
BootCodeSize,
|
|
&NewBootCode,
|
|
FILE_OPEN,
|
|
TRUE,
|
|
12*512,
|
|
BytesPerSector
|
|
);
|
|
}
|
|
|
|
//
|
|
// Update the mirror boot sector.
|
|
//
|
|
if( (CColonRegion->Filesystem == FilesystemNtfs) && MirrorSector ) {
|
|
|
|
WriteNtfsBootSector(PartitionHandle,BytesPerSector,NewBootCode,MirrorSector);
|
|
|
|
}
|
|
}
|
|
|
|
if( ExistingBootCodeOs ) {
|
|
SpMemFree(ExistingBootCodeOs);
|
|
}
|
|
}
|
|
|
|
if( ExistingBootCode ) {
|
|
SpMemFree(ExistingBootCode);
|
|
}
|
|
|
|
SpMemFree(CColonPath);
|
|
ZwClose (PartitionHandle);
|
|
|
|
//
|
|
// Handle the error case.
|
|
//
|
|
if (!NT_SUCCESS(Status)) {
|
|
RcMessageOut( MSG_FIXBOOT_FIX_ERROR );
|
|
} else {
|
|
RcMessageOut( MSG_FIXBOOT_DONE );
|
|
}
|
|
}
|