|
|
/*++
Copyright (c) 1995-2001 Microsoft Corporation
Module Name:
bootient.c
Abstract:
Contains the Boot.ini OS boot entry and boot options abstraction implementation.
Author:
Revision History:
None.
--*/
#include <bootient.h>
//
// defines
//
#define BOIOS_SECTION_NAME_START TEXT('[')
#define BOIOS_SECTION_NAME_END TEXT(']')
#define BOIOS_SECTION_NAME_START_STR TEXT("[")
#define BOIOS_SECTION_NAME_END_STR TEXT("]")
#define BOIOS_BOOTLOADER_SECTION TEXT("boot loader")
#define BOIOS_OS_SECTION TEXT("operating systems")
#define BOIOS_TIMEOUT_KEY TEXT("timeout=")
#define BOIOS_DEFAULT_KEY TEXT("default=")
#define MAX_BOOT_INI_SIZE (4 * 1024)
static PTSTR BOIOSFixupString( IN PTSTR String, IN PTSTR SpecialChars ) { PTSTR ResultStr = String;
//
// Verify arguments
//
if (ResultStr && SpecialChars) { ULONG Index; BOOLEAN DoneWithStart = FALSE; TCHAR Buffer[MAX_PATH * 4] = {0}; TCHAR NextIndex = 0;
//
// skip unwanted characters
//
for (Index = 0; String[Index]; Index++) { if (!_tcschr(SpecialChars, String[Index])) { Buffer[NextIndex++] = String[Index]; } }
//
// Null terminate the string
//
Buffer[NextIndex] = 0;
if (!NextIndex) { ResultStr = NULL; } else { //
// Copy back the new string to the
// input / output buffer
//
_tcscpy(ResultStr, Buffer); } }
return ResultStr; }
//
// BOI_OS_SECTION Methods
//
PBOI_SECTION BOISectionCreate( IN PCTSTR SectionData ) { PBOI_SECTION This = NULL;
if (SectionData) { PTSTR Buffer = (PTSTR)SBE_MALLOC((_tcslen(SectionData) + 1) * sizeof(TCHAR));
if (Buffer && _tcscpy(Buffer, SectionData)) { PTSTR SectionNameStart = _tcschr(Buffer, BOIOS_SECTION_NAME_START); PTSTR SectionNameEnd = _tcschr(Buffer, BOIOS_SECTION_NAME_END); BOOLEAN Result = FALSE;
if (SectionNameStart && SectionNameEnd && (SectionNameEnd > SectionNameStart)) { This = (PBOI_SECTION)SBE_MALLOC(sizeof(BOI_SECTION));
if (*Buffer && This) { DWORD DataLength = (_tcslen(Buffer) + 1) * sizeof(TCHAR);
DataLength -= (((SectionNameEnd + 1) - Buffer) * sizeof(TCHAR));
//
// Init default object state
//
memset(This, 0, sizeof(BOI_SECTION));
//
// Get the name
//
_tcsncpy(This->Name, SectionNameStart + 1, SectionNameEnd - SectionNameStart - 1);
//
// Replicate the contents and keep it
//
This->Contents = (PTSTR)SBE_MALLOC(DataLength);
if (This->Contents) { _tcscpy(This->Contents, SectionNameEnd + 1); Result = TRUE; } else { Result = FALSE; } }
if (!Result) { BOISectionDelete(This); This = NULL; } }
SBE_FREE(Buffer); } }
return This; }
VOID BOISectionDelete( IN PBOI_SECTION This ) { if (This) { if (This->Contents) { SBE_FREE(This->Contents); }
SBE_FREE(This); } }
static BOOLEAN BOISectionWrite( IN PBOI_SECTION This, IN OUT PTSTR Buffer ) { BOOLEAN Result = FALSE; if (This && Buffer) { _tcscat(Buffer, BOIOS_SECTION_NAME_START_STR); _tcscat(Buffer, BOISectionGetName(This)); _tcscat(Buffer, BOIOS_SECTION_NAME_END_STR); _tcscat(Buffer, TEXT("\r\n"));
if (This->Contents) { _tcscat(Buffer, This->Contents); } }
return Result; }
//
// BOI_OS_BOOT_ENTRY Methods
//
static VOID BOIOSBEInit( IN PBOI_OS_BOOT_ENTRY This ) { This->OsBootEntry.Delete = BOIOSBEDelete; This->OsBootEntry.Flush = BOIOSBEFlush; }
PBOI_SECTION BOIOSBOFindSection( IN PBOI_OS_BOOT_OPTIONS This, IN PTSTR SectionName ) { PBOI_SECTION Entry = NULL;
for (Entry = This->Sections; Entry; Entry = Entry->Next) { if (!_tcsicmp(Entry->Name, SectionName)) { break; // found the required section
} }
return Entry; }
static POS_BOOT_ENTRY BOIOSBECreate( IN ULONG Id, IN PCTSTR BootEntryLine, IN PBOI_OS_BOOT_OPTIONS Container ) { POS_BOOT_ENTRY Entry = NULL;
if (BootEntryLine && Container) { BOOLEAN Result = FALSE; TCHAR Buffer[MAX_PATH * 4]; TCHAR Token[MAX_PATH]; PBOI_OS_BOOT_ENTRY BootEntry = (PBOI_OS_BOOT_ENTRY)SBE_MALLOC(sizeof(BOI_OS_BOOT_ENTRY)); POS_BOOT_ENTRY BaseBootEntry = (POS_BOOT_ENTRY)BootEntry; //
// Replicate the input string
//
_tcsncpy(Buffer, BootEntryLine, sizeof(Buffer)/sizeof(TCHAR));
//
// Remove unwanted charcters in the string
//
if (BootEntry && BOIOSFixupString(Buffer, TEXT("\n\r"))) { PTSTR EqualSign = _tcschr(Buffer, TEXT('='));
//
// Initialize object state
//
memset(BootEntry, 0, sizeof(BOI_OS_BOOT_ENTRY)); BOIOSBEInit(BootEntry); BaseBootEntry->Id = Id; BaseBootEntry->BootOptions = (POS_BOOT_OPTIONS)Container;
if (EqualSign) { PTSTR Slash; *EqualSign = 0; Slash = _tcschr(Buffer, TEXT('\\'));
if (Slash) { PTSTR NameStart = NULL, NameEnd = NULL; PTSTR NextToken = NULL;
Result = TRUE; *Slash = 0;
//
// Parse & set the boot device name
//
_tcscpy(Token, Buffer); BOIOSFixupString(Token, TEXT("\n\r ")); _tcslwr(Token); OSBESetBootVolumeName(BaseBootEntry, Token);
//
// if it starts with "C:" its either old OS,
// or CmdCons or WinPE or Setup entry
//
if (_tcschr(Token, TEXT(':'))) { OSBE_SET_OLDOS(BaseBootEntry); }
//
// Parse & set the boot path
//
_tcscpy(Token, Slash + 1); BOIOSFixupString(Token, TEXT("\n\r ")); OSBESetBootPath(BaseBootEntry, Token);
//
// Parse & set the friendly name
//
NameStart = _tcschr(EqualSign + 1, TEXT('\"'));
//
// Set friendly name
//
if (NameStart) { NameEnd = _tcschr(NameStart + 1, TEXT('\"')); }
if (NameEnd) { _tcsncpy(Token, NameStart, NameEnd - NameStart); Token[NameEnd - NameStart] = 0; BOIOSFixupString(Token, TEXT("\r\n\"")); OSBESetFriendlyName(BaseBootEntry, Token); } else { Result = FALSE; }
//
// Set osload options
//
NextToken = _tcschr(EqualSign + 1, TEXT('/'));
if (NextToken) { _tcscpy(Token, NextToken); BOIOSFixupString(Token, TEXT("\r\n")); OSBESetOsLoadOptions(BaseBootEntry, Token); } } }
if (!Result) { SBE_FREE(BaseBootEntry); BaseBootEntry = NULL; } else { Entry = BaseBootEntry; } } }
return Entry; }
static VOID BOIOSBEDelete( IN POS_BOOT_ENTRY Obj ) { PBOI_OS_BOOT_ENTRY This = (PBOI_OS_BOOT_ENTRY)Obj; if (This) { SBE_FREE(This); } }
static BOOLEAN BOIOSBEWrite( IN POS_BOOT_ENTRY This, IN OUT PTSTR Buffer ) { BOOLEAN Result = FALSE;
if (This && Buffer && !OSBE_IS_DELETED(This)) { _tcscat(Buffer, OSBEGetBootVolumeName(This)); _tcscat(Buffer, TEXT("\\")); _tcscat(Buffer, OSBEGetBootPath(This)); _tcscat(Buffer, TEXT("=")); _tcscat(Buffer, TEXT("\"")); _tcscat(Buffer, OSBEGetFriendlyName(This)); _tcscat(Buffer, TEXT("\"")); _tcscat(Buffer, TEXT(" ")); _tcscat(Buffer, OSBEGetOsLoadOptions(This)); _tcscat(Buffer, TEXT("\r\n")); Result = TRUE; }
return Result; }
static BOOLEAN BOIOSBEFlush( IN POS_BOOT_ENTRY Obj ) { return TRUE; // currently can't flush individual entries
}
//
// BOI_OS_BOOT_OPTIONS Methods
//
static VOID BOIOSBOInit( IN PBOI_OS_BOOT_OPTIONS This ) { This->OsBootOptions.Delete = BOIOSBODelete; This->OsBootOptions.Flush = BOIOSBOFlush; This->OsBootOptions.AddNewBootEntry = BOIOSBOAddNewBootEntry; This->OsBootOptions.DeleteBootEntry = OSBODeleteBootEntry; }
BOOLEAN BOIOSBOParseAndCreateBootEntries( IN PBOI_OS_BOOT_OPTIONS This, IN PBOI_SECTION Section ) { BOOLEAN Result = FALSE;
if (This && Section) { Result = TRUE; if (Section->Contents) { PTSTR NextLineStart = Section->Contents; PTSTR NextLineEnd; TCHAR OldChar; POS_BOOT_ENTRY FirstBootEntry = NULL; POS_BOOT_ENTRY BootEntry = NULL; POS_BOOT_ENTRY LastBootEntry = NULL; ULONG BootEntryCount;
while (NextLineStart) { NextLineEnd = _tcschr(NextLineStart, TEXT('\r'));
if (NextLineEnd) { if (*(NextLineEnd + 1) == TEXT('\n')) { NextLineEnd++; }
NextLineEnd++; OldChar = *NextLineEnd; *NextLineEnd = 0; }
//
// Each boot entry line needs to be more than 2 characters in
// length and contain an entry of "a=b" form
//
if ((!NextLineEnd || ((NextLineEnd - NextLineStart) > 2)) && (_tcschr(NextLineStart, TEXT('=')))) { BootEntry = BOIOSBECreate(This->NextEntryId++, NextLineStart, This);
if (BootEntry) { This->OsBootOptions.EntryCount++;
if (!FirstBootEntry) { FirstBootEntry = LastBootEntry = BootEntry; } else { LastBootEntry->NextEntry = BootEntry; LastBootEntry = BootEntry; } } else { Result = FALSE;
break; // don't continue on
} }
if (NextLineEnd) { *NextLineEnd = OldChar; }
NextLineStart = NextLineEnd; }
This->OsBootOptions.BootEntries = FirstBootEntry; //
// Initialize the boot order array
// NOTE : Doesn't make much sense with boot.ini currently
//
BootEntryCount = OSBOGetBootEntryCount((POS_BOOT_OPTIONS)This);
if (BootEntryCount) { PULONG BootOrder = (PULONG)SBE_MALLOC(BootEntryCount * sizeof(ULONG));
if (BootOrder) { ULONG Index = 0; memset(BootOrder, 0, sizeof(ULONG) * BootEntryCount);
BootEntry = OSBOGetFirstBootEntry((POS_BOOT_OPTIONS)This);
while (BootEntry && (Index < BootEntryCount)) { BootOrder[Index] = OSBEGetId(BootEntry); BootEntry = OSBOGetNextBootEntry((POS_BOOT_OPTIONS)This, BootEntry); }
This->OsBootOptions.BootOrder = BootOrder; This->OsBootOptions.BootOrderCount = BootEntryCount; } } } }
return Result; }
BOOLEAN BOIOSBOParseTimeoutAndActiveEntry( IN PBOI_OS_BOOT_OPTIONS This, IN PBOI_SECTION Section ) { BOOLEAN Result = FALSE;
if (This && Section && !_tcsicmp(Section->Name, BOIOS_BOOTLOADER_SECTION)) { TCHAR Buffer[MAX_PATH * 2]; TCHAR Timeout[MAX_PATH]; TCHAR Default[MAX_PATH]; PTSTR DefKey, TimeoutKey; PTSTR DefValue; DWORD TimeKeyLength = _tcslen(BOIOS_TIMEOUT_KEY); DWORD DefKeyLength = _tcslen(BOIOS_DEFAULT_KEY); DWORD CopyLength;
Result = TRUE; _tcscpy(Buffer, Section->Contents); _tcslwr(Buffer); BOIOSFixupString(Buffer, TEXT("\r\n "));
Timeout[0] = Default[0] = 0; DefKey = _tcsstr(Buffer, BOIOS_DEFAULT_KEY); TimeoutKey = _tcsstr(Buffer, BOIOS_TIMEOUT_KEY); if (DefKey && TimeoutKey) { if (DefKey > TimeoutKey) { CopyLength = DefKey - TimeoutKey - TimeKeyLength; _tcsncpy(Timeout, TimeoutKey + TimeKeyLength, CopyLength); Timeout[CopyLength] = 0; _tcscpy(Default, DefKey + DefKeyLength); } else { CopyLength = TimeoutKey - DefKey - DefKeyLength; _tcsncpy(Default, DefKey + DefKeyLength, CopyLength); Default[CopyLength] = 0; _tcscpy(Timeout, TimeoutKey + TimeKeyLength); } } else if (DefKey) { _tcscpy(Default, DefKey + DefKeyLength); } else if (TimeoutKey) { _tcscpy(Timeout, TimeoutKey + TimeKeyLength); }
if (TimeoutKey) { ULONG TimeoutValue = _ttol(Timeout);
OSBOSetTimeOut((POS_BOOT_OPTIONS)This, TimeoutValue); }
if (DefKey) { PTSTR BootPath = _tcschr(Default, TEXT('\\'));
if (BootPath) { POS_BOOT_ENTRY CurrEntry;
*BootPath = 0; CurrEntry = OSBOGetFirstBootEntry((POS_BOOT_OPTIONS)This);
while (CurrEntry) { if (_tcsstr(Default, OSBEGetBootVolumeName(CurrEntry)) && !_tcsicmp(OSBEGetBootPath(CurrEntry), BootPath + 1)) { break; }
CurrEntry = OSBOGetNextBootEntry((POS_BOOT_OPTIONS)This, CurrEntry); }
if (CurrEntry) { OSBOSetActiveBootEntry((POS_BOOT_OPTIONS)This, CurrEntry); } } else { Result = FALSE; } }
OSBO_RESET_DIRTY((POS_BOOT_OPTIONS)This); }
return Result; }
POS_BOOT_OPTIONS BOIOSBOCreate( IN PCTSTR BootIniPath, IN BOOLEAN OpenExisting ) { POS_BOOT_OPTIONS This = NULL;
if (BootIniPath) { BY_HANDLE_FILE_INFORMATION FileInfo = {0}; PCHAR FileContent = NULL; HANDLE BootIniHandle;
//
// Open the file
//
BootIniHandle = CreateFile(BootIniPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if ((BootIniHandle != INVALID_HANDLE_VALUE) && GetFileInformationByHandle(BootIniHandle, &FileInfo)){ //
// Map the file
//
HANDLE MapHandle = CreateFileMapping(BootIniHandle, NULL, PAGE_READONLY, FileInfo.nFileSizeHigh, FileInfo.nFileSizeLow, NULL);
if (MapHandle) { //
// Get hold of view for the file content
//
PVOID FileView = MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0);
if (FileView) { DWORD BytesRead = 0;
//
// Allocate the buffer and read the file contents
//
FileContent = SBE_MALLOC(FileInfo.nFileSizeLow + 1);
if (FileContent) { if (!ReadFile(BootIniHandle, FileContent, FileInfo.nFileSizeLow, &BytesRead, NULL)) { SBE_FREE(FileContent); FileContent = NULL; } else { FileContent[FileInfo.nFileSizeLow] = 0; } }
UnmapViewOfFile(FileView); }
CloseHandle(MapHandle); } CloseHandle(BootIniHandle); } else { //
// Could be that user is creating boot options fresh
//
if (!OpenExisting) { PBOI_OS_BOOT_OPTIONS Obj = (PBOI_OS_BOOT_OPTIONS)SBE_MALLOC(sizeof(BOI_OS_BOOT_OPTIONS));
if (Obj) { //
// Initialize object
//
memset(Obj, 0, sizeof(BOI_OS_BOOT_OPTIONS)); BOIOSBOInit(Obj); _tcscpy(Obj->BootIniPath, BootIniPath); }
This = (POS_BOOT_OPTIONS)Obj; } }
//
// If there is any file content then parse it
//
if (FileContent) { #ifdef UNICODE
PWSTR Content = SBE_MALLOC((FileInfo.nFileSizeLow + 1) * sizeof(WCHAR));
//
// Convert the Ansi/OEM content to unicode content
//
if (Content) { if (MultiByteToWideChar(CP_OEMCP, 0, FileContent, FileInfo.nFileSizeLow, Content, FileInfo.nFileSizeLow + 1)) { Content[FileInfo.nFileSizeLow ] = 0; } else { SBE_FREE(Content); Content = NULL; } } else { SBE_FREE(FileContent); FileContent = NULL; } #else
PCHAR Content = FileContent; #endif
if (Content && FileContent) { TCHAR NextLine[MAX_PATH * 4]; PTSTR NextSectionStart = _tcschr(Content, BOIOS_SECTION_NAME_START); PTSTR NextSectionEnd; PBOI_SECTION SectionList = NULL; PBOI_SECTION Section = NULL; PBOI_SECTION TailSection = NULL; BOOLEAN Result = TRUE;
//
// Prase the whole files and create section objects
//
while (NextSectionStart) { TCHAR OldChar; Section = NULL; NextSectionEnd = _tcschr(NextSectionStart + 1, BOIOS_SECTION_NAME_START);
if (NextSectionEnd) { OldChar = *NextSectionEnd; *NextSectionEnd = 0; // null terminate
}
//
// Create the section object
//
Section = BOISectionCreate(NextSectionStart);
if (NextSectionEnd) { *NextSectionEnd = OldChar; } if (Section) { if (!SectionList) { SectionList = Section; } else { TailSection->Next = Section; } TailSection = Section; } else { Result = FALSE; break; }
NextSectionStart = NextSectionEnd; }
if (Result) { PBOI_OS_BOOT_OPTIONS Obj = (PBOI_OS_BOOT_OPTIONS)SBE_MALLOC(sizeof(BOI_OS_BOOT_OPTIONS));
if (Obj) { //
// Initialize object
//
memset(Obj, 0, sizeof(BOI_OS_BOOT_OPTIONS)); BOIOSBOInit(Obj); _tcscpy(Obj->BootIniPath, BootIniPath);
Obj->Sections = SectionList; SectionList = NULL;
//
// Get hold of [operating systems] section and
// parse its entries and create boot entries
//
Section = BOIOSBOFindSection(Obj, BOIOS_OS_SECTION);
if (Section) { Result = BOIOSBOParseAndCreateBootEntries(Obj, Section); }
//
// Get hold of [boot loader] section and prase its
// entries
//
if (Result) { Section = BOIOSBOFindSection(Obj, BOIOS_BOOTLOADER_SECTION);
if (Section) { Result = BOIOSBOParseTimeoutAndActiveEntry(Obj, Section); } }
if (!Result) { //
// Delete the object to free up all the sections
// and the entries
//
BOIOSBODelete((POS_BOOT_OPTIONS)Obj); Obj = NULL; }
This = (POS_BOOT_OPTIONS)Obj; } else { Result = FALSE; } }
//
// free up the allocated sections, in case of failure
//
if (!Result && SectionList) { while (SectionList) { Section = SectionList; SectionList = SectionList->Next; BOISectionDelete(Section); } }
//
// Free the content
//
if ((PVOID)Content != (PVOID)FileContent) { SBE_FREE(Content); } }
SBE_FREE(FileContent); } } return This; }
static VOID BOIOSBODelete( IN POS_BOOT_OPTIONS Obj ) { PBOI_OS_BOOT_OPTIONS This = (PBOI_OS_BOOT_OPTIONS)Obj; if (This) { PBOI_SECTION CurrSection, PrevSection; //
// delete each boot entry
//
POS_BOOT_ENTRY Entry = OSBOGetFirstBootEntry(Obj); POS_BOOT_ENTRY PrevEntry;
while (Entry) { PrevEntry = Entry; Entry = OSBOGetNextBootEntry(Obj, Entry); OSBEDelete(PrevEntry); }
//
// delete all the sections
//
CurrSection = This->Sections;
while (CurrSection) { PrevSection = CurrSection; CurrSection = CurrSection->Next; BOISectionDelete(PrevSection); }
if (Obj->BootOrder) { SBE_FREE(Obj->BootOrder); }
//
// delete the main object
//
SBE_FREE(This); } }
static POS_BOOT_ENTRY BOIOSBOAddNewBootEntry( IN POS_BOOT_OPTIONS This, IN PCTSTR FriendlyName, IN PCTSTR OsLoaderVolumeName, IN PCTSTR OsLoaderPath, IN PCTSTR BootVolumeName, IN PCTSTR BootPath, IN PCTSTR OsLoadOptions ) { PBOI_OS_BOOT_ENTRY Entry = NULL;
if (This && FriendlyName && BootVolumeName && BootPath) { Entry = SBE_MALLOC(sizeof(BOI_OS_BOOT_ENTRY));
if (Entry) { ULONG OrderCount; PULONG NewOrder; POS_BOOT_ENTRY BaseEntry = (POS_BOOT_ENTRY)Entry; PBOI_OS_BOOT_OPTIONS Obj = (PBOI_OS_BOOT_OPTIONS)This; //
// init core fields
//
memset(Entry, 0, sizeof(BOI_OS_BOOT_ENTRY)); BOIOSBEInit(Entry); Entry->OsBootEntry.BootOptions = This;
//
// fill in the attributes
//
OSBESetFriendlyName((POS_BOOT_ENTRY)Entry, FriendlyName); OSBESetBootVolumeName((POS_BOOT_ENTRY)Entry, BootVolumeName); OSBESetBootPath((POS_BOOT_ENTRY)Entry, BootPath);
if (OsLoadOptions) { OSBESetOsLoadOptions((POS_BOOT_ENTRY)Entry, OsLoadOptions); }
BaseEntry->Id = Obj->NextEntryId++;
//
// Flush the entry now to get a proper Id;
//
Entry->OsBootEntry.BootOptions = (POS_BOOT_OPTIONS)This; Entry->OsBootEntry.NextEntry = This->BootEntries; This->BootEntries = (POS_BOOT_ENTRY)Entry; This->EntryCount++;
//
// Put the new entry at the end of the boot order
//
OrderCount = OSBOGetOrderedBootEntryCount(This);
NewOrder = (PULONG)SBE_MALLOC((OrderCount + 1) * sizeof(ULONG));
if (NewOrder) { memset(NewOrder, 0, sizeof(ULONG) * (OrderCount + 1));
//
// copy over the old ordered list
//
memcpy(NewOrder, This->BootOrder, sizeof(ULONG) * OrderCount); NewOrder[OrderCount] = OSBEGetId((POS_BOOT_ENTRY)Entry); SBE_FREE(This->BootOrder); This->BootOrder = NewOrder; This->BootOrderCount = OrderCount + 1; } else { OSBODeleteBootEntry(This, BaseEntry); Entry = NULL; }
if (Entry) { //
// mark it dirty and new for flushing
//
OSBE_SET_NEW(Entry); OSBE_SET_DIRTY(Entry); } } } return (POS_BOOT_ENTRY)Entry; }
static BOOLEAN BOIOSBOWrite( IN PBOI_OS_BOOT_OPTIONS This, IN PCTSTR Buffer ) { BOOLEAN Result = FALSE;
if (This && Buffer) { TCHAR BackupFileName[MAX_PATH]; PTSTR Extension; HANDLE FileHandle;
//
// Create a backup name
//
_tcscpy(BackupFileName, This->BootIniPath); Extension = _tcschr(BackupFileName, TEXT('.'));
if (Extension) { _tcscpy(Extension, TEXT(".BAK")); } else { _tcscat(BackupFileName, TEXT(".BAK")); }
//
// Delete the backup file if it exists
//
SetFileAttributes(BackupFileName, FILE_ATTRIBUTE_NORMAL); DeleteFile(BackupFileName);
//
// Copy the existing boot.ini as backup file
//
SetFileAttributes(This->BootIniPath, FILE_ATTRIBUTE_NORMAL); CopyFile(This->BootIniPath, BackupFileName, FALSE);
//
// Create new boot.ini file
//
FileHandle = CreateFile(This->BootIniPath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (FileHandle && (FileHandle != INVALID_HANDLE_VALUE)) { PCHAR AnsiBuffer; ULONG BufferLength = _tcslen(Buffer); DWORD BytesWritten = 0;
Result = TRUE; #ifdef UNICODE
//
// Convert the unicode buffer to ansi buffer
//
AnsiBuffer = (PCHAR)SBE_MALLOC(BufferLength + 1);
if (AnsiBuffer) { memset(AnsiBuffer, 0, BufferLength);
if (WideCharToMultiByte(CP_OEMCP, 0, Buffer, BufferLength, AnsiBuffer, BufferLength, NULL, NULL)) { Result = TRUE; AnsiBuffer[BufferLength] = 0; } else { Result = FALSE; } } #else
AnsiBuffer = Buffer; #endif
//
// Write the buffer to the file
//
if (AnsiBuffer && !WriteFile(FileHandle, AnsiBuffer, BufferLength, &BytesWritten, NULL)) { Result = FALSE; }
if ((PVOID)AnsiBuffer != (PVOID)Buffer) { SBE_FREE(AnsiBuffer); AnsiBuffer = NULL; }
//
// Done with the file handle
//
CloseHandle(FileHandle);
SetFileAttributes(This->BootIniPath, FILE_ATTRIBUTE_NORMAL | FILE_ATTRIBUTE_READONLY | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM); } }
return Result; }
static BOOLEAN BOIOSBOFlush( IN POS_BOOT_OPTIONS Obj ) { BOOLEAN Result = FALSE; PBOI_OS_BOOT_OPTIONS This = (PBOI_OS_BOOT_OPTIONS)Obj;
if (This) { PTSTR Buffer = (PTSTR)SBE_MALLOC(MAX_BOOT_INI_SIZE * sizeof(TCHAR));
if (Buffer) { TCHAR ScratchBuffer[MAX_PATH * 2] = {0}; POS_BOOT_ENTRY ActiveEntry = OSBOGetActiveBootEntry(Obj); POS_BOOT_ENTRY CurrentEntry; PBOI_SECTION CurrentSection;
Result = TRUE; memset(Buffer, 0, MAX_BOOT_INI_SIZE * sizeof(TCHAR));
//
// first flush the boot options
//
_tcscat(Buffer, BOIOS_SECTION_NAME_START_STR); _tcscat(Buffer, BOIOS_BOOTLOADER_SECTION); _tcscat(Buffer, BOIOS_SECTION_NAME_END_STR); _tcscat(Buffer, TEXT("\r\n"));
//
// write time out
//
_tcscat(Buffer, BOIOS_TIMEOUT_KEY); _tcscat(Buffer, _ltot(Obj->Timeout, ScratchBuffer, 10)); _tcscat(Buffer, TEXT("\r\n"));
//
// write active entry
//
if (ActiveEntry) { _tcscpy(ScratchBuffer, BOIOS_DEFAULT_KEY); _tcscat(ScratchBuffer, OSBEGetBootVolumeName(ActiveEntry)); _tcscat(ScratchBuffer, TEXT("\\")); _tcscat(ScratchBuffer, OSBEGetBootPath(ActiveEntry)); _tcscat(ScratchBuffer, TEXT("\r\n"));
_tcscat(Buffer, ScratchBuffer); }
//
// Write the boot entries section
//
_tcscat(Buffer, BOIOS_SECTION_NAME_START_STR); _tcscat(Buffer, BOIOS_OS_SECTION); _tcscat(Buffer, BOIOS_SECTION_NAME_END_STR); _tcscat(Buffer, TEXT("\r\n"));
//
// write each boot entry now
//
//
// First write the valid arc entries
//
CurrentEntry = OSBOGetFirstBootEntry(Obj);
while (Result && CurrentEntry) { if (!OSBE_IS_DELETED(CurrentEntry) && !OSBE_IS_OLDOS(CurrentEntry)) { Result = BOIOSBEWrite(CurrentEntry, Buffer); } CurrentEntry = OSBOGetNextBootEntry(Obj, CurrentEntry); }
//
// Now write the old OS entries
// NOTE : We do this for backward compatabily reasons
//
CurrentEntry = OSBOGetFirstBootEntry(Obj);
while (Result && CurrentEntry) { if (OSBE_IS_OLDOS(CurrentEntry)) { Result = BOIOSBEWrite(CurrentEntry, Buffer); } CurrentEntry = OSBOGetNextBootEntry(Obj, CurrentEntry); }
//
// Write any additions sections which were present on the
//
CurrentSection = BOIOSGetFirstSection(This);
while (Result && CurrentSection) { //
// Write all the other additional sections in boot.ini other
// than [boot loader] and [operating systems]
//
if (_tcsicmp(BOISectionGetName(CurrentSection), BOIOS_BOOTLOADER_SECTION) && _tcsicmp(BOISectionGetName(CurrentSection), BOIOS_OS_SECTION)) { Result = BOISectionWrite(CurrentSection, Buffer); }
CurrentSection = BOIOSGetNextSection(This, CurrentSection); }
Result = BOIOSBOWrite(This, Buffer);
//
// Free the allocated buffer
//
SBE_FREE(Buffer); } }
return Result; }
|