Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1289 lines
33 KiB

#include "precomp.h"
#pragma hdrstop
// cmdcons boot dir
#ifndef CMDCONS_BOOT_DIR_A
#define CMDCONS_BOOT_DIR_A "CMDCONS"
#endif
#ifndef CMDCONS_BOOT_DIR_W
#define CMDCONS_BOOT_DIR_W L"CMDCONS"
#endif
#ifndef AUX_BOOT_SECTOR_NAME_A
#define AUX_BOOT_SECTOR_NAME_A "BOOTSECT.DAT"
#endif
#ifndef AUX_BOOT_SECTOR_NAME_W
#define AUX_BOOT_SECTOR_NAME_W L"BOOTSECT.DAT"
#endif
#define FLEXBOOT_SECTION1 "[flexboot]"
#define FLEXBOOT_SECTION2 "[boot loader]"
#define FLEXBOOT_SECTION3 "[multiboot]"
#define BOOTINI_OS_SECTION "[operating systems]"
#define TIMEOUT "timeout"
#define DEFAULT "default"
#define CRLF "\r\n"
#define EQUALS "="
//
// NOTE : Use a single string which can take care of XP and Whistler branding
//
#define BOOTINI_RECOVERY_CONSOLE_STR "Microsoft Windows Recovery Console"
#define BOOTINI_WINPE_DESCRIPTION "\"Microsoft Preinstall Environment\" /cmdcons"
#define BOOTINI_WINPE_ENTRY "c:\\cmdcons\\bootsect.dat"
#define BOOTINI_WINPE_TIMEOUT "5"
// prototypes
#if defined(_AMD64_) || defined(_X86_)
VOID
PatchBootIni(
VOID
);
VOID
PatchBootSectDat(
VOID
);
#endif
#define BOOTFONTBIN_SIGNATURE 0x5465644d
typedef struct _st_BOOTFONT_LANG {
ULONG Signature;
ULONG LangId;
} BOOTFONT_LANG, * PBOOTFONT_LANG;
BOOL
LoadBootIniString(
IN HINSTANCE ModuleHandle,
IN DWORD MsgId,
OUT PSTR Buffer,
IN DWORD Size
)
/*++
Routine Description:
Loads the appropriate string needed for writing into boot.ini
file. Does so, by looking for bootfont.bin file. If bootfont.bin
file is present a simple LoadStringA(...) should give us the
appropriate string (in most of the cases).
Arguments:
ModuleHandle - The module handle where resources are present
MsgId - String resource identifier
Buffer - Buffer to copy the string into
Size - Size of the buffer (in characters)
Return Value:
TRUE, if localized string was loaded using LoadStringA(...)
otherwise FALSE. FALSE indicates that english version of the string
resource needs to be written into boot.ini
--*/
{
BOOL Result = FALSE;
static BOOL BootFontPresent = FALSE;
static BOOL Initialized = FALSE;
if (!Initialized) {
TCHAR BootFontFile[MAX_PATH];
HANDLE BootFontHandle;
Initialized = TRUE;
//
// Open the bootfont.bin file
//
wsprintf(BootFontFile, TEXT("%s"), NativeSourcePaths[0]);
ConcatenatePaths(BootFontFile,
TEXT("bootfont.bin"),
sizeof(BootFontFile)/sizeof(TCHAR));
BootFontHandle = CreateFile(BootFontFile,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
0);
if (BootFontHandle != INVALID_HANDLE_VALUE) {
BOOTFONT_LANG BootFontHdr;
DWORD BytesRead = 0;
//
// Verify the bootfont.bin file header
//
ZeroMemory(&BootFontHdr, sizeof(BOOTFONT_LANG));
if (ReadFile(BootFontHandle, &BootFontHdr, sizeof(BOOTFONT_LANG),
&BytesRead, NULL)) {
if ((BytesRead == sizeof(BOOTFONT_LANG)) &&
(BootFontHdr.Signature == BOOTFONTBIN_SIGNATURE)) {
BootFontPresent = TRUE;
}
}
CloseHandle(BootFontHandle);
}
}
//
// Load the message if bootfont is present
//
if (BootFontPresent) {
Result = (LoadStringA(ModuleHandle, MsgId, Buffer, Size) != 0);
}
return Result;
}
DWORD
MapFileForReadWrite(
IN LPCTSTR FileName,
OUT PDWORD FileSize,
OUT PHANDLE FileHandle,
OUT PHANDLE MappingHandle,
OUT PVOID *BaseAddress
);
//
// routine that builds the cmdcons installation
//
VOID
DoBuildCmdcons(
VOID
)
{
DWORD rc;
TCHAR buffer[MAX_PATH];
TCHAR buffer2[MAX_PATH];
BOOLEAN bSilentInstall = (BOOLEAN) UnattendedOperation;
//
// NT5 ntdetect.com is not compatible NT4's on NEC98 system.
// We need check setup OS Version if Command console is
// setuped on NEC98.
//
#ifdef _X86_ //NEC98
if (IsNEC98() && (!ISNT() || OsVersion.dwMajorVersion < 5)){
return;
}
#endif
//
// Don't popup the confirmation dialog box if install
// is running in silent mode
//
if (!bSilentInstall) {
rc = MessageBoxFromMessage(
NULL,
MSG_CMDCONS_ASK,
FALSE,
AppTitleStringId,
MB_YESNO | MB_ICONWARNING
);
if( rc == IDNO ) {
return;
}
}
//
// we don't want a local source
//
UserSpecifiedLocalSourceDrive = FALSE;
//
// use unattended to force winnt32 to build a ~bt
//
UnattendedOperation = TRUE;
if( UnattendedScriptFile ) {
FREE( UnattendedScriptFile );
UnattendedScriptFile = NULL;
}
//
// make sure we're not upgrading
//
Upgrade = FALSE;
//
// We don't want a local source.
//
MakeLocalSource = FALSE;
//
// do it.
//
Wizard();
if(GlobalResult) {
//
// delete the current CMDCONS directory
//
BuildSystemPartitionPathToFile (TEXT("cmdcons"), buffer, MAX_PATH);
MyDelnode( buffer );
//
// delete the current CMLDR
//
BuildSystemPartitionPathToFile (TEXT("cmldr"), buffer, MAX_PATH);
SetFileAttributes( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFile( buffer );
#if defined(_AMD64_) || defined(_X86_)
//
// delete the new boot.ini
//
BuildSystemPartitionPathToFile (TEXT("boot.ini"), buffer, MAX_PATH);
SetFileAttributes( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFile( buffer );
//
// restore the old boot.ini and patch it
//
BuildSystemPartitionPathToFile (TEXT("boot.bak"), buffer2, MAX_PATH);
CopyFile( buffer2, buffer, FALSE );
PatchBootIni();
#endif
//
// rename $LDR$ to CMLDR
//
BuildSystemPartitionPathToFile (TEXT("$LDR$"), buffer, MAX_PATH);
BuildSystemPartitionPathToFile (TEXT("cmldr"), buffer2, MAX_PATH);
MoveFile( buffer, buffer2 );
//
// flag CMLDR +r +s +h
//
SetFileAttributes( buffer2,
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_READONLY );
//
// rename \$WIN_NT$.~BT to \CMDCONS
//
BuildSystemPartitionPathToFile (TEXT("$WIN_NT$.~BT"), buffer, MAX_PATH);
BuildSystemPartitionPathToFile (TEXT("cmdcons"), buffer2, MAX_PATH);
if (!MoveFile( buffer, buffer2 )){
TCHAR tempbuffer[MAX_PATH];
GlobalResult = FALSE;
//
// Delete the ~BT folder and cmldr file in case of failure.
// Blow away the local boot dir.
//
if(LocalBootDirectory[0]) {
MyDelnode(LocalBootDirectory);
}
//
// Blow away cmldr off the root of the system partition.
//
if (BuildSystemPartitionPathToFile (TEXT("cmldr"), tempbuffer, MAX_PATH)){
if (SetFileAttributes(tempbuffer,FILE_ATTRIBUTE_NORMAL)){
DeleteFile(tempbuffer);
}
}
}else{
#if defined(_AMD64_) || defined(_X86_)
//
// fix \cmdcons\bootsect.dat
//
PatchBootSectDat();
#endif
// flag \CMDCONS +r +s +h
SetFileAttributes( buffer2,
FILE_ATTRIBUTE_HIDDEN |
FILE_ATTRIBUTE_SYSTEM |
FILE_ATTRIBUTE_READONLY );
}
//
// delete TXTSETUP.SIF
//
BuildSystemPartitionPathToFile (TEXT("TXTSETUP.SIF"), buffer, MAX_PATH);
SetFileAttributes( buffer, FILE_ATTRIBUTE_NORMAL );
DeleteFile( buffer );
}
//
// popup completion status only if not a silent install
//
if (!bSilentInstall) {
if(GlobalResult) {
//
// popup success dialog box
//
rc = MessageBoxFromMessage(
NULL,
MSG_CMDCONS_DONE,
FALSE,
AppTitleStringId,
MB_OK | MB_ICONINFORMATION
);
} else {
//
// popup failure dialog box
//
rc = MessageBoxFromMessage(
NULL,
MSG_CMDCONS_DID_NOT_FINISH,
FALSE,
AppTitleStringId,
MB_OK | MB_ICONERROR
);
}
}
//
// make sure the machine does not reboot automatically.
//
AutomaticallyShutDown = FALSE;
return;
}
BOOL
__inline
WriteToBootIni(
IN HANDLE Handle,
IN PCHAR Line
)
{
DWORD bw,l;
l = lstrlenA(Line);
return(WriteFile(Handle,Line,l,&bw,NULL) && (bw == l));
}
#if defined(_AMD64_) || defined(_X86_)
DWORD
InitBootIni(
IN PCTSTR BootIniName,
IN PCSTR DefaultEntry,
IN PCSTR DefaultEntryDescription,
IN PCSTR Timeout
)
/*++
Routine Description:
Initializes a boot.ini file for e.g. while installing
WinPE on to harddisk a dummy boot.ini is created for WinPE.
Arguments:
BootIniName - Fully qualified boot.ini file name
DefaultEntry - The default entry string that points
to an installation.
DefaultEntryDescription - The description for the default
boot entry.
Timeout - The timeout value (in secs)
Return Value:
Appropriate Win32 error code.
--*/
{
DWORD ErrorCode = ERROR_INVALID_PARAMETER;
if (BootIniName && DefaultEntry && DefaultEntryDescription) {
HANDLE BootIniHandle = CreateFile(BootIniName,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
CREATE_ALWAYS,
0,
NULL);
if (BootIniHandle != INVALID_HANDLE_VALUE) {
//
// write the [boot loader section]
//
BOOL Result = WriteToBootIni(BootIniHandle,
FLEXBOOT_SECTION2);
Result = Result && WriteToBootIni(BootIniHandle,
CRLF);
//
// write the timeout value
//
if (Timeout) {
Result = Result && WriteToBootIni(BootIniHandle,
TIMEOUT);
Result = Result && WriteToBootIni(BootIniHandle,
EQUALS);
Result = Result && WriteToBootIni(BootIniHandle,
(PSTR)Timeout);
Result = Result && WriteToBootIni(BootIniHandle,
CRLF);
}
//
// write the default installation
//
Result = Result && WriteToBootIni(BootIniHandle,
DEFAULT);
Result = Result && WriteToBootIni(BootIniHandle,
EQUALS);
Result = Result && WriteToBootIni(BootIniHandle,
(PSTR)DefaultEntry);
Result = Result && WriteToBootIni(BootIniHandle,
CRLF);
//
// write the [operating systems] section
//
Result = Result && WriteToBootIni(BootIniHandle,
BOOTINI_OS_SECTION);
Result = Result && WriteToBootIni(BootIniHandle,
CRLF);
//
// write the cmdcons entry
//
Result = Result && WriteToBootIni(BootIniHandle,
(PSTR)DefaultEntry);
Result = Result && WriteToBootIni(BootIniHandle,
EQUALS);
Result = Result && WriteToBootIni(BootIniHandle,
(PSTR)DefaultEntryDescription);
Result = Result && WriteToBootIni(BootIniHandle,
CRLF);
if (!Result) {
ErrorCode = GetLastError();
} else {
ErrorCode = NO_ERROR;
}
CloseHandle(BootIniHandle);
} else {
ErrorCode = GetLastError();
}
}
return ErrorCode;
}
VOID
PatchBootIni(
VOID
)
{
CHAR c;
CHAR Text[256];
TCHAR BootIniName[MAX_PATH] = {0};
TCHAR BootIniBackup[MAX_PATH] = {0};
UCHAR temp;
UCHAR BootSectorImageSpec[29];
PUCHAR Buffer;
PUCHAR pszBLoader = NULL;
PUCHAR p,next;
PUCHAR DefSwitches;
PUCHAR DefSwEnd;
HANDLE h;
DWORD BootIniSize;
DWORD BytesRead;
DWORD OldAttributes;
DWORD d;
BOOL b;
BOOL InOsSection;
CHAR HeadlessRedirectSwitches[160] = {0};
//
// Determine the size of boot.ini, allocate a buffer,
// and read it in. If it isn't there then it will be created.
//
BuildSystemPartitionPathToFile (TEXT("BOOT.INI"), BootIniName, MAX_PATH);
BuildSystemPartitionPathToFile (TEXT("BOOT.BAK"), BootIniBackup, MAX_PATH);
h = CreateFile(BootIniName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,0,NULL);
if(h == INVALID_HANDLE_VALUE) {
//
// If the file doesn't exist -- create one in WinPE
//
if (IsWinPEMode()) {
CHAR Buffer[MAX_PATH] = {0};
PSTR WinPEDescription = Buffer;
if (!LoadBootIniString(hInst,
IDS_WINPE_INSTALLATION,
Buffer,
sizeof(Buffer))) {
WinPEDescription = BOOTINI_WINPE_DESCRIPTION;
}
if (InitBootIni(BootIniName,
BOOTINI_WINPE_ENTRY,
WinPEDescription,
BOOTINI_WINPE_TIMEOUT) == NO_ERROR) {
return;
}
}
//
// Yikes. Setup should have already created one of these for us.
//
d = GetLastError();
b = FALSE;
goto c0;
} else {
//
// Figure out how big the file is.
// Allocate 3 extra characters for final NUL we'll add to make
// parsing easier, and a cr/lf in case the last line is incomplete.
//
BootIniSize = GetFileSize(h,NULL);
if(BootIniSize == (DWORD)(-1)) {
d = GetLastError();
CloseHandle(h);
b = FALSE;
goto c0;
}
OldAttributes = GetFileAttributes( BootIniName );
Buffer = MALLOC(BootIniSize+3);
if(!Buffer) {
CloseHandle(h);
b = FALSE;
d = ERROR_NOT_ENOUGH_MEMORY;
goto c0;
}
b = ReadFile(h,Buffer,BootIniSize,&BytesRead,NULL);
d = GetLastError();
CloseHandle(h);
if(!b) {
goto c1;
}
}
//
// Make sure the last line is properly terminated, and add a terminating nul
// to make parsing a little easier.
//
if(BootIniSize && (Buffer[BootIniSize-1] != '\n') && (Buffer[BootIniSize-1] != '\r')) {
Buffer[BootIniSize++] = '\r';
Buffer[BootIniSize++] = '\n';
}
Buffer[BootIniSize] = 0;
//
// Truncate at control-z if any.
//
if(p = strchr(Buffer,26)) {
if((p > Buffer) && (*(p - 1) != '\n') && (*(p - 1) != '\r')) {
*(p++) = '\r';
*(p++) = '\n';
}
*p = 0;
BootIniSize = (DWORD)(p - Buffer);
}
//
// Make sure we can write boot.ini.
//
SetFileAttributes(BootIniName,FILE_ATTRIBUTE_NORMAL);
h = CreateFile(
BootIniName,
GENERIC_WRITE,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM,
NULL
);
if(h == INVALID_HANDLE_VALUE) {
d = GetLastError();
b = FALSE;
goto c2;
}
//
// Regardless of the actual drive letter of the system partition,
// the spec in boot.ini is always C:\...
//
wsprintfA(BootSectorImageSpec,"C:\\%hs\\%hs",CMDCONS_BOOT_DIR_A,AUX_BOOT_SECTOR_NAME_A);
// write out the first section unchanged
for(p=Buffer; *p && (p < Buffer+BootIniSize - (sizeof("[operating systems]")-1)); p++) {
//
// Headless 'redirect' setting.
//
if(!_strnicmp(p,"redirect=",sizeof("redirect=")-1)) {
PUCHAR q, r;
UCHAR Temp;
//
// Jump over the headless settings, but record them if the
// user didn't give us any specific settings.
//
q = p + strlen("redirect=");
r = q;
while( (*r != '\n') &&
(*r != '\r') &&
(*r) &&
(*r != '[') ) {
r++;
}
//
// Now jump over the whitespace too.
//
while( (*r == '\n') ||
(*r == '\r') ) {
r++;
}
if( *r ) {
Temp = *r;
*r = '\0';
if( HeadlessSelection[0] == TEXT('\0') ) {
//
// Record this headless setting because the user
// didn't specify any headless setting.
//
#ifdef UNICODE
swprintf( HeadlessSelection, TEXT("%s"), q );
#else
strcpy( HeadlessSelection, q );
#endif
}
*r = Temp;
//
// Now copy the remaining buffer ontop of this
// headless setting.
//
strcpy( p, r );
}
}
//
// Headless 'redirectbaudrate' setting.
//
if(!_strnicmp(p,"redirectbaudrate=",sizeof("redirectbaudrate=")-1)) {
PUCHAR q, r;
UCHAR Temp;
//
// Jump over the headless settings, but record them if the
// user didn't give us any specific settings.
//
q = p + strlen("redirectbaudrate=");
r = q;
while( (*r != '\n') &&
(*r != '\r') &&
(*r) &&
(*r != '[') ) {
r++;
}
//
// Now jump over the whitespace too.
//
while( (*r == '\n') ||
(*r == '\r') ) {
r++;
}
if( *r ) {
Temp = *r;
*r = '\0';
if( HeadlessBaudRate == 0 ) {
//
// Record this headless setting because the user
// didn't specify any headless setting.
//
HeadlessBaudRate = atoi(q);
}
*r = Temp;
//
// Now copy the remaining buffer ontop of this
// headless setting.
//
strcpy( p, r );
}
}
if(!_strnicmp(p,"[operating systems]",sizeof("[operating systems]")-1)) {
break;
}
}
pszBLoader = MALLOC( (UINT_PTR)p - (UINT_PTR)Buffer + 1 );
pszBLoader[(UINT_PTR)p - (UINT_PTR)Buffer ] = 0;
if( pszBLoader ) {
strncpy( pszBLoader, Buffer, (UINT_PTR)p - (UINT_PTR)Buffer );
if(!WriteToBootIni(h,pszBLoader)) {
d = GetLastError();
b = FALSE;
goto c3;
}
FREE( pszBLoader );
} else {
d = GetLastError();
b = FALSE;
goto c3;
}
//
// Do headless stuff. We want to set the "redirect=comX"
// entry in boot.ini. Make sure the user really asked
// us to add this in though.
//
if( HeadlessSelection[0] != TEXT('\0') ) {
CHAR tmp[80];
BOOLEAN PreviousRedirectLine = FALSE;
//
// They told winnt32.exe some specific headless settings.
// Use these.
//
//
// Convert the user's request into ASCII.
//
#ifdef UNICODE
WideCharToMultiByte( CP_ACP,
0,
HeadlessSelection,
-1,
tmp,
sizeof(tmp),
NULL,
NULL );
wsprintfA( HeadlessRedirectSwitches,
"redirect=%s\r\n",
tmp );
#else
wsprintfA( HeadlessRedirectSwitches,
"redirect=%s\r\n",
HeadlessSelection );
#endif
}
if( HeadlessRedirectSwitches[0] != '\0' ) {
//
// We got some 'redirect' setting, either from a command-line parameter
// or from boot.ini. Write it out, and go dig up a baudrate setting.
//
if(!WriteToBootIni(h,HeadlessRedirectSwitches)) {
d = GetLastError();
b = FALSE;
goto c3;
}
//
// Now do the "redirectbaudrate=..." line.
//
HeadlessRedirectSwitches[0] = '\0';
if( HeadlessBaudRate != 0 ) {
//
// Convert the user's request into ASCII.
//
wsprintfA( HeadlessRedirectSwitches,
"redirectbaudrate=%d\r\n",
HeadlessBaudRate );
}
if( HeadlessRedirectSwitches[0] != '\0' ) {
if(!WriteToBootIni(h,HeadlessRedirectSwitches)) {
d = GetLastError();
b = FALSE;
goto c3;
}
}
}
//
// Now write out the [Operating Systems] section name.
//
if(!WriteToBootIni(h,"[operating systems]\r\n")) {
d = GetLastError();
b = FALSE;
goto c3;
}
//
// Process each line in boot.ini.
// If it's the setup boot sector line, we'll throw it out.
// For comparison with lines in boot.ini, the drive letter
// is always C even if the system partition is not actually C:.
//
InOsSection = FALSE;
b = TRUE;
for(p=Buffer; *p && b; p=next) {
while((*p==' ') || (*p=='\t')) {
p++;
}
if(*p) {
//
// Find first byte of next line.
//
for(next=p; *next && (*next++ != '\n'); );
//
// Look for start of [operating systems] section
// or at each line in that section.
//
if(InOsSection) {
switch(*p) {
case '[': // end of section.
*p=0; // force break out of loop
break;
case 'C':
case 'c': // potential start of c:\ line
//
// See if it's a line for setup boot.
// If so, ignore it.
//
if(!_strnicmp(p,BootSectorImageSpec,lstrlenA(BootSectorImageSpec))) {
break;
}
//
// Not a special line, FALL THROUGH to write it out as-is.
//
default:
//
// Random line. write it out.
//
c = *next;
*next = 0;
b = WriteToBootIni(h,p);
*next = c;
break;
}
} else {
if(!_strnicmp(p,"[operating systems]",19)) {
InOsSection = TRUE;
}
}
}
}
//
// Write out our line.
//
if(b) {
//
// NOTE : This is intentional. If we have a boot font then we convert the unicode
// string we got from message resoure to DBCS using LoadStringA(...) else we just
// write English string out in boot.ini for recovery console.
//
if (!LoadBootIniString(hInst, IDS_RECOVERY_CONSOLE, Text, sizeof(Text))) {
strcpy(Text, BOOTINI_RECOVERY_CONSOLE_STR);
}
if((b=WriteToBootIni(h,BootSectorImageSpec))
&& (b=WriteToBootIni(h,"=\""))
&& (b=WriteToBootIni(h,Text))
&& (b=WriteToBootIni(h,"\" /cmdcons" ))) {
b = WriteToBootIni(h,"\r\n");
}
}
#if 0
//
// Write out previous OS line if directed to do so.
//
if(b && SetPreviousOs) {
if(b = WriteToBootIni(h,"C:\\=\"")) {
LoadStringA(hInst,IDS_MICROSOFT_WINDOWS,Text,sizeof(Text));
if(b = WriteToBootIni(h,Text)) {
b = WriteToBootIni(h,"\"\r\n");
}
}
}
#endif
if(!b) {
d = GetLastError();
goto c3;
}
d = NO_ERROR;
c3:
CloseHandle(h);
c2:
//
// Restore boot.ini.
//
if(!b && (OldAttributes != (DWORD)(-1))) {
SetFileAttributes(BootIniName,FILE_ATTRIBUTE_NORMAL);
CopyFile(BootIniBackup,BootIniName,FALSE);
SetFileAttributes(BootIniName,OldAttributes);
SetFileAttributes(BootIniBackup,FILE_ATTRIBUTE_NORMAL);
DeleteFile(BootIniBackup);
}
c1:
FREE(Buffer);
c0:
if(!b) {
MessageBoxFromMessageAndSystemError(
NULL,
MSG_BOOT_FILE_ERROR,
d,
AppTitleStringId,
MB_OK | MB_ICONERROR | MB_TASKMODAL,
BootIniName
);
GlobalResult = FALSE;
}
}
VOID
PatchBootSectDat(
VOID
)
{
TCHAR buffer[MAX_PATH];
DWORD rc;
DWORD fileSize;
DWORD curpos;
HANDLE fileHandle;
HANDLE mappingHandle;
LPBYTE bootSectDat;
TCHAR DrivePath[MAX_PATH];
DWORD DontCare;
TCHAR NameBuffer[100];
BOOL Ntfs = FALSE;
//
// find out what the file system is
//
BuildSystemPartitionPathToFile (TEXT(""), DrivePath, MAX_PATH);
//BUGBUG
rc = GetVolumeInformation(
DrivePath,
NULL,
0,
NULL,
&DontCare,
&DontCare,
NameBuffer,
sizeof(NameBuffer)/sizeof(TCHAR)
);
if (rc == 0) {
return;
}
if (!lstrcmpi(NameBuffer,TEXT("NTFS"))) {
Ntfs = TRUE;
}
//
// form the path
//
BuildSystemPartitionPathToFile (TEXT("CMDCONS\\BOOTSECT.DAT"), buffer, MAX_PATH);
//
// map the file into RAM
//
rc = MapFileForReadWrite( buffer,
&fileSize,
&fileHandle,
&mappingHandle,
(PVOID*)&bootSectDat
);
if( rc == NO_ERROR ) {
__try {
for (curpos = 0; curpos < fileSize; curpos++) {
if (Ntfs) {
if( bootSectDat[curpos] == '$' &&
bootSectDat[curpos+2] == 'L' &&
bootSectDat[curpos+4] == 'D' &&
bootSectDat[curpos+6] == 'R' &&
bootSectDat[curpos+8] == '$' ) {
// patch CMLDR
bootSectDat[curpos] = 'C';
bootSectDat[curpos+2] = 'M';
bootSectDat[curpos+4] = 'L';
bootSectDat[curpos+6] = 'D';
bootSectDat[curpos+8] = 'R';
break;
}
} else {
if( bootSectDat[curpos] == '$' &&
bootSectDat[curpos+1] == 'L' &&
bootSectDat[curpos+2] == 'D' &&
bootSectDat[curpos+3] == 'R' &&
bootSectDat[curpos+4] == '$' ) {
// patch CMLDR
bootSectDat[curpos] = 'C';
bootSectDat[curpos+1] = 'M';
bootSectDat[curpos+2] = 'L';
bootSectDat[curpos+3] = 'D';
bootSectDat[curpos+4] = 'R';
break;
}
}
}
} except ( EXCEPTION_EXECUTE_HANDLER ) {
}
}
FlushViewOfFile( (PVOID)bootSectDat, 0 );
UnmapFile( mappingHandle, (PVOID)bootSectDat );
CloseHandle( fileHandle );
}
#endif
DWORD
MapFileForReadWrite(
IN LPCTSTR FileName,
OUT PDWORD FileSize,
OUT PHANDLE FileHandle,
OUT PHANDLE MappingHandle,
OUT PVOID *BaseAddress
)
/*++
Routine Description:
Open and map an entire file for read access. The file must
not be 0-length or the routine fails.
Arguments:
FileName - supplies pathname to file to be mapped.
FileSize - receives the size in bytes of the file.
FileHandle - receives the win32 file handle for the open file.
The file will be opened for generic read access.
MappingHandle - receives the win32 handle for the file mapping
object. This object will be for read access. This value is
undefined if the file being opened is 0 length.
BaseAddress - receives the address where the file is mapped. This
value is undefined if the file being opened is 0 length.
Return Value:
NO_ERROR if the file was opened and mapped successfully.
The caller must unmap the file with UnmapFile when
access to the file is no longer desired.
Win32 error code if the file was not successfully mapped.
--*/
{
DWORD rc;
//
// Open the file -- fail if it does not exist.
//
*FileHandle = CreateFile(
FileName,
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL,
OPEN_EXISTING,
0,
NULL
);
if(*FileHandle == INVALID_HANDLE_VALUE) {
rc = GetLastError();
} else {
//
// Get the size of the file.
//
*FileSize = GetFileSize(*FileHandle,NULL);
if(*FileSize == (DWORD)(-1)) {
rc = GetLastError();
} else {
//
// Create file mapping for the whole file.
//
*MappingHandle = CreateFileMapping(
*FileHandle,
NULL,
PAGE_READWRITE,
0,
*FileSize,
NULL
);
if(*MappingHandle) {
//
// Map the whole file.
//
*BaseAddress = MapViewOfFile(
*MappingHandle,
FILE_MAP_ALL_ACCESS,
0,
0,
*FileSize
);
if(*BaseAddress) {
return(NO_ERROR);
}
rc = GetLastError();
CloseHandle(*MappingHandle);
} else {
rc = GetLastError();
}
}
CloseHandle(*FileHandle);
}
return(rc);
}