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.
 
 
 
 
 
 

6428 lines
209 KiB

/******************************************************************************
Copyright(c) Microsoft Corporation
Module Name:
BootCfg64.cpp
Abstract:
This file is intended to have the functionality for
configuring, displaying, changing and deleting boot.ini
settings for the local host for a 64 bit system.
Author:
J.S.Vasu 17/1/2001 .
Revision History:
J.S.Vasu 17/1/2001 Created it.
SanthoshM.B 10/2/2001 Modified it.
J.S.Vasu 15/2/2001 Modified it.
******************************************************************************/
#include "pch.h"
#include "resource.h"
#include "BootCfg.h"
#include "BootCfg64.h"
#include <strsafe.h>
#define BOOTFILE_PATH1 L"signature({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x})%s"
#define BOOTFILE_PATH L"signature({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x})%s\\ia64ldr.efi"
NTSTATUS ModifyBootEntry( IN WCHAR *pwszInstallPath, IN PBOOT_ENTRY pSourceEntry);
NTSTATUS FindBootEntry(IN PVOID pEntryListHead,IN WCHAR *pwszTarget, OUT PBOOT_ENTRY *ppTargetEntry);
LPVOID MEMALLOC( ULONG size ) ;
VOID MEMFREE ( LPVOID block ) ;
NTSTATUS EnumerateBootEntries( IN PVOID *ppEntryListHead);
NTSTATUS AcquirePrivilege(IN CONST ULONG ulPrivilege,IN CONST BOOLEAN bEnable);
DWORD ListDeviceInfo(DWORD dwVal);
//Global Linked lists for storing the boot entries
LIST_ENTRY BootEntries;
LIST_ENTRY ActiveUnorderedBootEntries;
LIST_ENTRY InactiveUnorderedBootEntries;
DWORD InitializeEFI(void)
/*++
Routine Description :
This routine initializes the EFI environment required.
Initializes the function pointers for the
NT Boot Entry Management API's
Arguments : None
Return Type : DWORD
Returns EXIT_SUCCESS if successful,
returns EXIT_FAILURE otherwise.
--*/
{
DWORD error;
NTSTATUS status;
BOOLEAN wasEnabled;
HMODULE hModule;
PBOOT_ENTRY_LIST ntBootEntries = NULL;
PMY_BOOT_ENTRY bootEntry;
PLIST_ENTRY listEntry;
PULONG BootEntryOrder;
ULONG BootEntryOrderCount;
ULONG length, i, myId;
TCHAR dllName[MAX_PATH];
if( FALSE == IsUserAdmin() )
{
ShowMessage( stderr, GetResString(IDS_NOT_ADMINISTRATOR_64 ));
ReleaseGlobals();
return EXIT_FAILURE;
}
// Enable the privilege that is necessary to query/set NVRAM.
status = RtlAdjustPrivilege(SE_SYSTEM_ENVIRONMENT_PRIVILEGE,
TRUE,
FALSE,
&wasEnabled
);
if (!NT_SUCCESS(status))
{
error = RtlNtStatusToDosError( status );
ShowMessage( stderr, GetResString(IDS_INSUFF_PRIV));
return EXIT_FAILURE ;
}
// Load ntdll.dll from the system directory. This is used to get the
// function addresses for the various NT Boot Entry Management API's used by
// this tool.
if(!GetSystemDirectory( dllName, MAX_PATH ))
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
return EXIT_FAILURE ;
}
StringConcat(dllName, _T("\\ntdll.dll"), SIZE_OF_ARRAY(dllName));
hModule = LoadLibrary( dllName );
if ( hModule == NULL )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
return EXIT_FAILURE ;
}
// Get the system boot order list.
length = 0;
status = NtQueryBootEntryOrder( NULL, &length );
if ( status != STATUS_BUFFER_TOO_SMALL )
{
if ( status == STATUS_SUCCESS )
{
length = 0;
}
else
{
error = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_QUERY_BOOTENTRY) );
return EXIT_FAILURE ;
}
}
if ( length != 0 )
{
BootEntryOrder = (PULONG)AllocateMemory( length * sizeof(ULONG) );
if(BootEntryOrder == NULL)
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return EXIT_FAILURE ;
}
status = NtQueryBootEntryOrder( BootEntryOrder, &length );
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_QUERY_BOOTENTRY) );
if(BootEntryOrder)
{
FreeMemory((LPVOID *)&BootEntryOrder);
}
return EXIT_FAILURE ;
}
}
BootEntryOrderCount = length;
//Enumerate all the boot entries
status = BootCfg_EnumerateBootEntries(&ntBootEntries);
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
//free the ntBootEntries list
if(ntBootEntries)
{
FreeMemory((LPVOID *)&ntBootEntries);
}
if(BootEntryOrder)
{
FreeMemory((LPVOID *)&BootEntryOrder);
}
return EXIT_FAILURE ;
}
//Initialize the various head pointers
InitializeListHead( &BootEntries );
InitializeListHead( &ActiveUnorderedBootEntries );
InitializeListHead( &InactiveUnorderedBootEntries );
//Convert the bootentries into our know format -- MY_BOOT_ENTRIES.
if(ConvertBootEntries( ntBootEntries ) == EXIT_FAILURE)
{
if(ntBootEntries)
{
FreeMemory((LPVOID *)&ntBootEntries);
}
if(BootEntryOrder)
{
FreeMemory((LPVOID *)&BootEntryOrder);
}
return EXIT_FAILURE ;
}
//free the memory allocated for the enumeration
if(ntBootEntries)
{
FreeMemory((LPVOID *)&ntBootEntries);
}
// Build the ordered boot entry list.
myId = 1;
for ( i = 0; i < BootEntryOrderCount; i++ )
{
ULONG id = BootEntryOrder[i];
for ( listEntry = ActiveUnorderedBootEntries.Flink;
listEntry != &ActiveUnorderedBootEntries;
listEntry = listEntry->Flink )
{
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if ( bootEntry->Id == id )
{
//Mark this entry as "Ordered" as the ordered id is found
bootEntry->Ordered = 1;
//Assign the internal ID
bootEntry->myId = myId++;
listEntry = listEntry->Blink;
RemoveEntryList( &bootEntry->ListEntry );
InsertTailList( &BootEntries, &bootEntry->ListEntry );
bootEntry->ListHead = &BootEntries;
}
}
for ( listEntry = InactiveUnorderedBootEntries.Flink;
listEntry != &InactiveUnorderedBootEntries;
listEntry = listEntry->Flink )
{
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if ( bootEntry->Id == id )
{
//Mark this entry as ordered as the ordered id is found
bootEntry->Ordered = 1;
//Assign the internal ID
bootEntry->myId = myId++;
listEntry = listEntry->Blink;
RemoveEntryList( &bootEntry->ListEntry );
InsertTailList( &BootEntries, &bootEntry->ListEntry );
bootEntry->ListHead = &BootEntries;
}
}
}
//Now add the boot entries that are not a part of the ordered list
for (listEntry = ActiveUnorderedBootEntries.Flink;
listEntry != &ActiveUnorderedBootEntries;
listEntry = listEntry->Flink )
{
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if ( bootEntry->Ordered != 1 )
{
//Assign the internal ID
bootEntry->myId = myId++;
listEntry = listEntry->Blink;
RemoveEntryList( &bootEntry->ListEntry );
InsertTailList( &BootEntries, &bootEntry->ListEntry );
bootEntry->ListHead = &BootEntries;
}
}
for (listEntry = InactiveUnorderedBootEntries.Flink;listEntry != &InactiveUnorderedBootEntries;listEntry = listEntry->Flink)
{
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if ( bootEntry->Id != 1 )
{
//Assign the internal ID
bootEntry->myId = myId++;
listEntry = listEntry->Blink;
RemoveEntryList( &bootEntry->ListEntry );
InsertTailList( &BootEntries, &bootEntry->ListEntry );
bootEntry->ListHead = &BootEntries;
}
}
if(BootEntryOrder)
{
FreeMemory((LPVOID *)&BootEntryOrder);
}
return EXIT_SUCCESS ;
}
BOOL QueryBootIniSettings_IA64( DWORD argc, LPCTSTR argv[])
/*++
Name : QueryBootIniSettings_IA64
Synopsis : This routine is displays the boot entries and their settings
for an EFI based machine
Parameters : None
Return Type : VOID
Global Variables: Global Linked lists for storing the boot entries
LIST_ENTRY BootEntries;
--*/
{
// Builiding the TCMDPARSER structure
BOOL bQuery = FALSE ;
BOOL bUsage = FALSE ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[2];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_QUERY;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bQuery;
//usage option
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_QUERY_USAGE));
return ( EXIT_FAILURE );
}
if( bUsage )
{
displayQueryUsage();
return EXIT_SUCCESS ;
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
if(DisplayBootOptions() == EXIT_FAILURE)
{
return EXIT_FAILURE;
}
DisplayBootEntry();
//Remember to free the memory for the linked lists here
Freelist();
return EXIT_SUCCESS;
}
NTSTATUS
BootCfg_EnumerateBootEntries(
PBOOT_ENTRY_LIST *ntBootEntries
)
/*++
Routine Description :
This routine enumerates the boot entries and fills the
BootEntryList
This routine will fill in the Boot entry list. The caller
of this function needs to free the memory for ntBootEntries.
Arguments
ntBootEntries : Pointer to the BOOT_ENTRY_LIST structure
Return Type : NTSTATUS
--*/
{
DWORD error;
NTSTATUS status;
ULONG length = 0;
// Query all existing boot entries.
status = NtEnumerateBootEntries( NULL, &length );
if ( status != STATUS_BUFFER_TOO_SMALL )
{
if ( status == STATUS_SUCCESS )
{
length = 0;
}
else
{
error = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_ENUM_BOOTENTRY) );
}
}
if ( length != 0 )
{
*ntBootEntries = (PBOOT_ENTRY_LIST)AllocateMemory( length );
if(*ntBootEntries == NULL)
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return STATUS_UNSUCCESSFUL;
}
status = NtEnumerateBootEntries( *ntBootEntries, &length );
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
FreeMemory((LPVOID *)&(*ntBootEntries) );
ShowMessage(stderr,GetResString(IDS_ERROR_ENUM_BOOTENTRY) );
}
}
return status;
}
NTSTATUS
BootCfg_QueryBootOptions( IN PBOOT_OPTIONS *ppBootOptions)
/*++
Routine Description :
This routine enumerates the boot options and fills the
BOOT_OPTIONS
The caller of this function needs to free the memory for
BOOT_OPTIONS.
Arguments
ppBootOptions : Pointer to the BOOT_ENTRY_LIST structure
Return Type : NTSTATUS
--*/
{
DWORD error;
NTSTATUS status;
ULONG length = 0;
//Querying the Boot options
status = NtQueryBootOptions( NULL, &length );
if ( status == STATUS_NOT_IMPLEMENTED )
{
ShowMessage( stderr,GetResString(IDS_NO_EFINVRAM) );
return STATUS_UNSUCCESSFUL;
}
if ( status != STATUS_BUFFER_TOO_SMALL )
{
error = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_QUERY_BOOTOPTIONS) );
return STATUS_UNSUCCESSFUL;
}
*ppBootOptions = (PBOOT_OPTIONS)AllocateMemory(length);
if(*ppBootOptions == NULL)
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return STATUS_UNSUCCESSFUL;
}
status = NtQueryBootOptions( *ppBootOptions, &length );
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_QUERY_BOOTOPTIONS) );
FreeMemory( (LPVOID *) &*ppBootOptions );
return STATUS_UNSUCCESSFUL;
}
return status;
}
DWORD
RawStringOsOptions_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
Allows the user to add the OS load options specifed
as a raw string at the cmdline to the boot
Arguments
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
Returns EXIT_SUCCESS if function is successful,
returns EXIT_FAILURE otherwise.
--*/
{
BOOL bUsage = FALSE ;
BOOL bRaw = FALSE ;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
PBOOT_ENTRY bootEntry;
STRING256 szRawString = NULL_STRING ;
BOOL bAppendFlag = FALSE ;
STRING256 szAppendString = NULL_STRING ;
PWINDOWS_OS_OPTIONS pWindowsOptions;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[5];
PTCMDPARSER2 pcmdOption;
// Building the TCMDPARSER structure
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_RAW;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bRaw;
//usage option
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
//id option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
//default option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEFAULT;
pcmdOption->dwFlags = CP2_DEFAULT | CP2_MANDATORY | CP2_VALUE_TRIMINPUT;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szRawString;
pcmdOption->dwLength= MAX_STRING_LENGTH;
//append option
pcmdOption = &cmdOptions[4];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_APPEND;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bAppendFlag;
// Parsing the copy option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_RAW_USAGE));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayRawUsage_IA64();
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//Trim any leading or trailing spaces
if(StringLengthW(szRawString,0) != 0)
{
TrimString(szRawString, TRIM_ALL);
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries;listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
bootEntry = &mybootEntry->NtBootEntry;
//Check whether the bootEntry is a Windows one or not.
//The OS load options can be added only to a Windows boot entry.
if(!IsBootEntryWindows(bootEntry))
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
dwExitCode = EXIT_FAILURE;
break;
}
pWindowsOptions = (PWINDOWS_OS_OPTIONS)bootEntry->OsOptions;
if(bAppendFlag == TRUE )
{
StringCopy(szAppendString,pWindowsOptions->OsLoadOptions, SIZE_OF_ARRAY(szAppendString));
StringConcat(szAppendString,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szAppendString) );
StringConcat(szAppendString,szRawString, SIZE_OF_ARRAY(szAppendString));
}
else
{
StringCopy(szAppendString,szRawString, SIZE_OF_ARRAY(szAppendString));
}
//display error message if Os Load options is more than 254
// characters.
if(StringLengthW(szAppendString, 0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
//
//Change the OS load options.
//Pass NULL to friendly name as we are not changing the same
//szAppendString is the Os load options specified by the user
//to be appended or to be overwritten over the existing options
//
dwExitCode = ChangeBootEntry(bootEntry, NULL, szAppendString);
if(dwExitCode == ERROR_SUCCESS)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_SUCCESS_OSOPTIONS),dwBootID);
}
else
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
}
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
dwExitCode = EXIT_FAILURE;
}
//Remember to free memory allocated for the linked lists
Freelist();
return (dwExitCode);
}
DWORD
ChangeBootEntry( IN PBOOT_ENTRY bootEntry,
IN LPTSTR lpNewFriendlyName,
IN LPTSTR lpOSLoadOptions)
/*++
Routine Description:
This routine is used to change the FriendlyName and the
OS Options for a boot entry.
Arguments
[ in ] bootEntry -Pointer to a BootEntry structure
for which the changes needs to be made
[ in ] lpNewFriendlyName -String specifying the new friendly name.
[ in ] lpOSLoadOptions - String specifying the OS load options.
Return Type : DWORD -- ERROR_SUCCESS on success
-- ERROR_FAILURE on failure
--*/
{
PBOOT_ENTRY bootEntryCopy;
PMY_BOOT_ENTRY myBootEntry;
PWINDOWS_OS_OPTIONS osOptions;
ULONG length;
PMY_BOOT_ENTRY myChBootEntry;
NTSTATUS status;
DWORD error, dwErrorCode = ERROR_SUCCESS;
// Calculate the length of our internal structure. This includes
// the base part of MY_BOOT_ENTRY plus the NT BOOT_ENTRY.
//
length = FIELD_OFFSET(MY_BOOT_ENTRY, NtBootEntry) + bootEntry->Length;
myBootEntry = (PMY_BOOT_ENTRY)AllocateMemory(length);
if( NULL == myBootEntry )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return EXIT_FAILURE;
}
RtlZeroMemory(myBootEntry, length);
//
// Copy the NT BOOT_ENTRY into the allocated buffer.
//
bootEntryCopy = &myBootEntry->NtBootEntry;
memcpy(bootEntryCopy, bootEntry, bootEntry->Length);
myBootEntry->Id = bootEntry->Id;
myBootEntry->Attributes = bootEntry->Attributes;
//Change the friendly name if lpNewFriendlyName is not NULL
if(lpNewFriendlyName)
{
myBootEntry->FriendlyName = lpNewFriendlyName;
myBootEntry->FriendlyNameLength = ((ULONG)StringLengthW(lpNewFriendlyName, 0) + 1) * sizeof(WCHAR);
}
else
{
myBootEntry->FriendlyName = (PWSTR)ADD_OFFSET(bootEntryCopy, FriendlyNameOffset);
myBootEntry->FriendlyNameLength = ((ULONG)StringLengthW(myBootEntry->FriendlyName, 0) + 1) * sizeof(WCHAR);
}
myBootEntry->BootFilePath = (PFILE_PATH)ADD_OFFSET(bootEntryCopy, BootFilePathOffset);
// If this is an NT boot entry, capture the NT-specific information in
// the OsOptions.
osOptions = (PWINDOWS_OS_OPTIONS)bootEntryCopy->OsOptions;
if ((bootEntryCopy->OsOptionsLength >= FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions)) &&
(strcmp((char *)osOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE) == 0))
{
MBE_SET_IS_NT( myBootEntry );
//To change the OS Load options
if(lpOSLoadOptions)
{
myBootEntry->OsLoadOptions = lpOSLoadOptions;
myBootEntry->OsLoadOptionsLength = ((ULONG)StringLengthW(lpOSLoadOptions, 0) + 1) * sizeof(WCHAR);
}
else
{
myBootEntry->OsLoadOptions = osOptions->OsLoadOptions;
myBootEntry->OsLoadOptionsLength = ((ULONG)StringLengthW(myBootEntry->OsLoadOptions, 0) + 1) * sizeof(WCHAR);
}
myBootEntry->OsFilePath = (PFILE_PATH)ADD_OFFSET(osOptions, OsLoadPathOffset);
}
else
{
// Foreign boot entry. Just capture whatever OS options exist.
//
myBootEntry->ForeignOsOptions = bootEntryCopy->OsOptions;
myBootEntry->ForeignOsOptionsLength = bootEntryCopy->OsOptionsLength;
}
myChBootEntry = CreateBootEntryFromBootEntry(myBootEntry);
if(myChBootEntry == NULL)
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
if(myBootEntry)
{
FreeMemory((LPVOID *)&myBootEntry);
}
return EXIT_FAILURE;
}
//Call the modify API
status = NtModifyBootEntry(&myChBootEntry->NtBootEntry);
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
dwErrorCode = error;
ShowMessage(stderr,GetResString(IDS_ERROR_MODIFY_BOOTENTRY) );
}
//free the memory
if(myChBootEntry)
{
FreeMemory((LPVOID *)&myChBootEntry);
}
if(myBootEntry)
{
FreeMemory((LPVOID *)&myBootEntry);
}
return dwErrorCode;
}
PMY_BOOT_ENTRY
CreateBootEntryFromBootEntry (IN PMY_BOOT_ENTRY OldBootEntry)
/*++
Routine Description :
This routine is used to create a new MY_BOOT_ENTRY struct.
The caller of this function needs to free the memory allocated
for the MY_BOOT_ENTRY struct.
Arguments :
[ in ] bootEntry - Pointer to a BootEntry structure
for which the changes needs to be made
[ in ] lpNewFriendlyName - String specifying the new friendly name.
[ in ] lpOSLoadOptions - String specifying the OS load options.
Return Type : PMY_BOOT_ENTRY - Pointer to the new MY_BOOT_ENTRY strucure.
NULL on failure
--*/
{
ULONG requiredLength;
ULONG osOptionsOffset;
ULONG osLoadOptionsLength;
ULONG osLoadPathOffset;
ULONG osLoadPathLength;
ULONG osOptionsLength;
ULONG friendlyNameOffset;
ULONG friendlyNameLength;
ULONG bootPathOffset;
ULONG bootPathLength;
PMY_BOOT_ENTRY newBootEntry;
PBOOT_ENTRY ntBootEntry;
PWINDOWS_OS_OPTIONS osOptions;
PFILE_PATH osLoadPath;
PWSTR friendlyName;
PFILE_PATH bootPath;
// Calculate how long the internal boot entry needs to be. This includes
// our internal structure, plus the BOOT_ENTRY structure that the NT APIs
// use.
//
// Our structure:
//
requiredLength = FIELD_OFFSET(MY_BOOT_ENTRY, NtBootEntry);
// Base part of NT structure:
//
requiredLength += FIELD_OFFSET(BOOT_ENTRY, OsOptions);
// Save offset to BOOT_ENTRY.OsOptions. Add in base part of
// WINDOWS_OS_OPTIONS. Calculate length in bytes of OsLoadOptions
// and add that in.
//
osOptionsOffset = requiredLength;
if ( MBE_IS_NT( OldBootEntry ) )
{
// Add in base part of WINDOWS_OS_OPTIONS. Calculate length in
// bytes of OsLoadOptions and add that in.
//
requiredLength += FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions);
osLoadOptionsLength = OldBootEntry->OsLoadOptionsLength;
requiredLength += osLoadOptionsLength;
// Round up to a ULONG boundary for the OS FILE_PATH in the
// WINDOWS_OS_OPTIONS. Save offset to OS FILE_PATH. Calculate length
// in bytes of FILE_PATH and add that in. Calculate total length of
// WINDOWS_OS_OPTIONS.
//
requiredLength = ALIGN_UP(requiredLength, ULONG);
osLoadPathOffset = requiredLength;
requiredLength += OldBootEntry->OsFilePath->Length;
osLoadPathLength = requiredLength - osLoadPathOffset;
}
else
{
// Add in length of foreign OS options.
//
requiredLength += OldBootEntry->ForeignOsOptionsLength;
osLoadOptionsLength = 0;
osLoadPathOffset = 0;
osLoadPathLength = 0;
}
osOptionsLength = requiredLength - osOptionsOffset;
// Round up to a ULONG boundary for the friendly name in the BOOT_ENTRY.
// Save offset to friendly name. Calculate length in bytes of friendly name
// and add that in.
//
requiredLength = ALIGN_UP(requiredLength, ULONG);
friendlyNameOffset = requiredLength;
friendlyNameLength = OldBootEntry->FriendlyNameLength;
requiredLength += friendlyNameLength;
// Round up to a ULONG boundary for the boot FILE_PATH in the BOOT_ENTRY.
// Save offset to boot FILE_PATH. Calculate length in bytes of FILE_PATH
// and add that in.
//
requiredLength = ALIGN_UP(requiredLength, ULONG);
bootPathOffset = requiredLength;
requiredLength += OldBootEntry->BootFilePath->Length;
bootPathLength = requiredLength - bootPathOffset;
// Allocate memory for the boot entry.
//
newBootEntry = (PMY_BOOT_ENTRY)AllocateMemory(requiredLength);
if(newBootEntry == NULL)
{
return NULL;
}
RtlZeroMemory(newBootEntry, requiredLength);
// Calculate addresses of various substructures using the saved offsets.
//
ntBootEntry = &newBootEntry->NtBootEntry;
osOptions = (PWINDOWS_OS_OPTIONS)ntBootEntry->OsOptions;
osLoadPath = (PFILE_PATH)((PUCHAR)newBootEntry + osLoadPathOffset);
friendlyName = (PWSTR)((PUCHAR)newBootEntry + friendlyNameOffset);
bootPath = (PFILE_PATH)((PUCHAR)newBootEntry + bootPathOffset);
// Fill in the internal-format structure.
//
// newBootEntry->AllocationEnd = (PUCHAR)newBootEntry + requiredLength;
newBootEntry->Status = OldBootEntry->Status & MBE_STATUS_IS_NT;
newBootEntry->Attributes = OldBootEntry->Attributes;
newBootEntry->Id = OldBootEntry->Id;
newBootEntry->FriendlyName = friendlyName;
newBootEntry->FriendlyNameLength = friendlyNameLength;
newBootEntry->BootFilePath = bootPath;
if ( MBE_IS_NT( OldBootEntry ) )
{
newBootEntry->OsLoadOptions = osOptions->OsLoadOptions;
newBootEntry->OsLoadOptionsLength = osLoadOptionsLength;
newBootEntry->OsFilePath = osLoadPath;
}
// Fill in the base part of the NT boot entry.
//
ntBootEntry->Version = BOOT_ENTRY_VERSION;
ntBootEntry->Length = requiredLength - FIELD_OFFSET(MY_BOOT_ENTRY, NtBootEntry);
ntBootEntry->Attributes = OldBootEntry->Attributes;
ntBootEntry->Id = OldBootEntry->Id;
ntBootEntry->FriendlyNameOffset = (ULONG)((PUCHAR)friendlyName - (PUCHAR)ntBootEntry);
ntBootEntry->BootFilePathOffset = (ULONG)((PUCHAR)bootPath - (PUCHAR)ntBootEntry);
ntBootEntry->OsOptionsLength = osOptionsLength;
if ( MBE_IS_NT( OldBootEntry ) )
{
// Fill in the base part of the WINDOWS_OS_OPTIONS, including the
// OsLoadOptions.
//
StringCopyA((char *)osOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE, sizeof(WINDOWS_OS_OPTIONS_SIGNATURE));
osOptions->Version = WINDOWS_OS_OPTIONS_VERSION;
osOptions->Length = osOptionsLength;
osOptions->OsLoadPathOffset = (ULONG)((PUCHAR)osLoadPath - (PUCHAR)osOptions);
StringCopy(osOptions->OsLoadOptions, OldBootEntry->OsLoadOptions, osOptions->Length );
// Copy the OS FILE_PATH.
//
memcpy( osLoadPath, OldBootEntry->OsFilePath, osLoadPathLength );
}
else
{
// Copy the foreign OS options.
memcpy( osOptions, OldBootEntry->ForeignOsOptions, osOptionsLength );
}
// Copy the friendly name.
StringCopy(friendlyName, OldBootEntry->FriendlyName, friendlyNameLength );
// Copy the boot FILE_PATH.
memcpy( bootPath, OldBootEntry->BootFilePath, bootPathLength );
return newBootEntry;
} // CreateBootEntryFromBootEntry
DWORD
DeleteBootIniSettings_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
//
// Routine Description : This routine deletes an existing boot entry from an EFI
// based machine
//
// Arguments :
// [ in ] argc - Number of command line arguments
// [ in ] argv - Array containing command line arguments
//
// Return Type : DWORD
// Returns EXIT_SUCCESS if successful,
// returns EXIT_FAILURE otherwise.
//
//
--*/
{
BOOL bDelete = FALSE ;
BOOL bUsage = FALSE;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
NTSTATUS status;
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[3];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
// Building the TCMDPARSER structure
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DELETE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bDelete;
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
// Parsing the delete option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_DELETE_USAGE));
return ( EXIT_FAILURE );
}
// Displaying delete usage if user specified -? with -delete option
if( bUsage )
{
displayDeleteUsage_IA64();
return EXIT_SUCCESS;
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries;listEntry = listEntry->Flink)
{
//
//display an error message if there is only 1 boot entry saying
//that it cannot be deleted.
//
if (listEntry->Flink == NULL)
{
ShowMessage(stderr,GetResString(IDS_ONLY_ONE_OS));
dwExitCode = EXIT_FAILURE;
break ;
}
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
//Delete the boot entry specified by the user.
status = NtDeleteBootEntry(mybootEntry->Id);
if(status == STATUS_SUCCESS)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_DELETE_SUCCESS),dwBootID);
}
else
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_DELETE_FAILURE),dwBootID);
}
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
dwExitCode = EXIT_FAILURE;
}
//Remember to free the memory allocated to the linked lists
Freelist();
return (dwExitCode);
}
BOOL
IsBootEntryWindows(PBOOT_ENTRY bootEntry)
/*++
//
//
// Routine Description :
// Checks whether the boot entry is a Windows or a foreign one
//
// Arguments :
// [ in ] bootEntry - Boot entry structure describing the
// boot entry.
//
// Return Type : BOOL
// TRUE if bootEntry is an windows entry,
// FALSE otherwise
//
--*/
{
PWINDOWS_OS_OPTIONS osOptions;
osOptions = (PWINDOWS_OS_OPTIONS)bootEntry->OsOptions;
if ((bootEntry->OsOptionsLength >= FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions)) &&
(strcmp((char *)osOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE) == 0))
{
return TRUE;
}
return FALSE;
}
PWSTR GetNtNameForFilePath(IN PFILE_PATH FilePath)
/*++
Routine Description :
Converts the FilePath into a NT file path.
Arguments :
[ in ] FilePath - The File path.
Return Type : PWSTR
The NT file path.
--*/
{
NTSTATUS status;
ULONG length;
PFILE_PATH ntPath;
PWSTR osDeviceNtName;
PWSTR osDirectoryNtName;
PWSTR fullNtName;
length = 0;
status = NtTranslateFilePath(
FilePath,
FILE_PATH_TYPE_NT,
NULL,
&length
);
if ( status != STATUS_BUFFER_TOO_SMALL )
{
return NULL;
}
ntPath = (PFILE_PATH)AllocateMemory( length );
if(ntPath == NULL)
{
return NULL;
}
status = NtTranslateFilePath(
FilePath,
FILE_PATH_TYPE_NT,
ntPath,
&length
);
if ( !NT_SUCCESS(status) )
{
if(ntPath)
{
FreeMemory((LPVOID *)&ntPath);
}
return NULL;
}
osDeviceNtName = (PWSTR)ntPath->FilePath;
osDirectoryNtName = osDeviceNtName + StringLengthW(osDeviceNtName,0) + 1;
length = (ULONG)(StringLengthW(osDeviceNtName,0) + StringLengthW(osDirectoryNtName, 0) + 1) * sizeof(WCHAR);
fullNtName = (PWSTR)AllocateMemory( length );
if(fullNtName == NULL)
{
if(ntPath)
{
FreeMemory((LPVOID *)&ntPath);
}
return NULL;
}
StringCopy( fullNtName, osDeviceNtName, GetBufferSize(fullNtName)/sizeof(WCHAR) );
StringConcat( fullNtName, osDirectoryNtName, GetBufferSize(fullNtName)/sizeof(WCHAR) );
if(ntPath)
{
FreeMemory((LPVOID *) &ntPath );
}
return fullNtName;
} // GetNtNameForFilePath
DWORD
CopyBootIniSettings_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
This routine copies and existing boot entry for an EFI
based machine. The user can then add the various OS load
options.
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
Returns EXIT_SUCCESS if successful,
returns EXIT_FAILURE otherwise
--*/
{
BOOL bCopy = FALSE ;
BOOL bUsage = FALSE;
DWORD dwExitCode = EXIT_SUCCESS;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
PBOOT_ENTRY bootEntry;
DWORD dwExitcode = 0 ;
STRING256 szDescription = NULL_STRING;
BOOL bFlag = FALSE ;
TCMDPARSER2 cmdOptions[4];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_COPY;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bCopy;
//description option
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_DESCRIPTION;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_VALUE_TRIMINPUT;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szDescription;
pcmdOption->dwLength= FRIENDLY_NAME_LENGTH;
// usage
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
//id option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
// Parsing the copy option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_COPY_USAGE));
return ( EXIT_FAILURE );
}
// Displaying copy usage if user specified -? with -copy option
if( bUsage )
{
displayCopyUsage_IA64();
dwExitCode = EXIT_SUCCESS;
return dwExitCode;
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
if(cmdOptions[1].dwActuals != 0)
{
bFlag = TRUE ;
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries; listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
bootEntry = &mybootEntry->NtBootEntry;
//Copy the boot entry specified by the user.
dwExitCode = CopyBootEntry(bootEntry, szDescription,bFlag);
if(dwExitCode == EXIT_SUCCESS)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_COPY_SUCCESS),dwBootID);
}
else
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_COPY_ERROR),dwBootID);
return EXIT_FAILURE ;
}
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
return (EXIT_FAILURE) ;
}
//Remember to free the memory allocated for the linked lists
Freelist();
return EXIT_SUCCESS;
}
DWORD
CopyBootEntry( IN PBOOT_ENTRY bootEntry,
IN LPTSTR lpNewFriendlyName,
IN BOOL bFlag)
/*++
Routine Description :
This routine is used to add / copy a boot entry.
Arguments :
[ in ] bootEntry - Pointer to a BootEntry structure for which the changes needs to be made
[ in ] lpNewFriendlyName - String specifying the new friendly name.
Return Type : DWORD -- ERROR_SUCCESS on success
-- EXIT_FAILURE on failure
--*/
{
PBOOT_ENTRY bootEntryCopy;
PMY_BOOT_ENTRY myBootEntry;
PWINDOWS_OS_OPTIONS osOptions;
ULONG length, Id;
PMY_BOOT_ENTRY myChBootEntry;
NTSTATUS status;
DWORD error, dwErrorCode = ERROR_SUCCESS;
WCHAR szString[500] ;
PULONG BootEntryOrder, NewBootEntryOrder, NewTempBootEntryOrder;
// Calculate the length of our internal structure. This includes
// the base part of MY_BOOT_ENTRY plus the NT BOOT_ENTRY.
//
length = FIELD_OFFSET(MY_BOOT_ENTRY, NtBootEntry) + bootEntry->Length;
myBootEntry = (PMY_BOOT_ENTRY)AllocateMemory(length);
if(myBootEntry == NULL)
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
RtlZeroMemory(myBootEntry, length);
//
// Copy the NT BOOT_ENTRY into the allocated buffer.
//
bootEntryCopy = &myBootEntry->NtBootEntry;
memcpy(bootEntryCopy, bootEntry, bootEntry->Length);
myBootEntry->Id = bootEntry->Id;
myBootEntry->Attributes = bootEntry->Attributes;
//Change the friendly name if lpNewFriendlyName is not NULL
//if(lpNewFriendlyName && (lstrlen(lpNewFriendlyName) != 0))
//if(( cmdOptions[4].dwActuals == 0) )
if(TRUE == bFlag)
//if(lstrlen(lpNewFriendlyName) != 0)
{
myBootEntry->FriendlyName = lpNewFriendlyName;
myBootEntry->FriendlyNameLength = ((ULONG)StringLengthW(lpNewFriendlyName,0) + 1) * sizeof(WCHAR);
}
else
{
StringCopy(szString,GetResString(IDS_COPY_OF), SIZE_OF_ARRAY(szString));
StringConcat(szString,(PWSTR)ADD_OFFSET(bootEntryCopy, FriendlyNameOffset), SIZE_OF_ARRAY(szString));
if(StringLengthW(szString, 0) >= 67)
{
StringCopy(szString,szString,67);
}
myBootEntry->FriendlyName = szString ;
myBootEntry->FriendlyNameLength = ((ULONG)StringLengthW(szString,0) + 1) * sizeof(WCHAR);
}
myBootEntry->BootFilePath = (PFILE_PATH)ADD_OFFSET(bootEntryCopy, BootFilePathOffset);
// If this is an NT boot entry, capture the NT-specific information in
// the OsOptions.
osOptions = (PWINDOWS_OS_OPTIONS)bootEntryCopy->OsOptions;
if ((bootEntryCopy->OsOptionsLength >= FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions)) &&
(strcmp((char *)osOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE) == 0))
{
MBE_SET_IS_NT( myBootEntry );
//To change the OS Load options
myBootEntry->OsLoadOptions = osOptions->OsLoadOptions;
myBootEntry->OsLoadOptionsLength = ((ULONG)StringLengthW(myBootEntry->OsLoadOptions, 0) + 1) * sizeof(WCHAR);
myBootEntry->OsFilePath = (PFILE_PATH)ADD_OFFSET(osOptions, OsLoadPathOffset);
}
else
{
// Foreign boot entry. Just capture whatever OS options exist.
//
myBootEntry->ForeignOsOptions = bootEntryCopy->OsOptions;
myBootEntry->ForeignOsOptionsLength = bootEntryCopy->OsOptionsLength;
}
myChBootEntry = CreateBootEntryFromBootEntry(myBootEntry);
if(myChBootEntry == NULL)
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
if(myBootEntry)
{
FreeMemory((LPVOID *)&myBootEntry);
}
ShowLastError(stderr);
return (EXIT_FAILURE);
}
//Call the NtAddBootEntry API
status = NtAddBootEntry(&myChBootEntry->NtBootEntry, &Id);
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
dwErrorCode = error;
ShowMessage(stderr,GetResString(IDS_ERROR_UNEXPECTED) );
}
// Get the system boot order list.
length = 0;
status = NtQueryBootEntryOrder( NULL, &length );
if ( status != STATUS_BUFFER_TOO_SMALL )
{
if ( status == STATUS_SUCCESS )
{
length = 0;
}
else
{
error = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_QUERY_BOOTENTRY) );
if(myBootEntry)
{
FreeMemory((LPVOID *)&myBootEntry);
}
if(myChBootEntry)
{
FreeMemory((LPVOID *)&myChBootEntry);
}
return FALSE;
}
}
if ( length != 0 )
{
BootEntryOrder = (PULONG)AllocateMemory( length * sizeof(ULONG) );
if(BootEntryOrder == NULL)
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
if(myBootEntry)
{
FreeMemory((LPVOID *)&myBootEntry);
}
if(myChBootEntry)
{
FreeMemory((LPVOID *)&myChBootEntry);
}
return (EXIT_FAILURE);
}
status = NtQueryBootEntryOrder( BootEntryOrder, &length );
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_QUERY_BOOTENTRY));
dwErrorCode = error;
FreeMemory((LPVOID *)&myBootEntry);
FreeMemory((LPVOID *)&BootEntryOrder);
FreeMemory((LPVOID *)&myChBootEntry);
return dwErrorCode;
}
}
//Allocate memory for the new boot entry order.
NewBootEntryOrder = (PULONG)AllocateMemory((length+1) * sizeof(ULONG));
if(NULL == NewBootEntryOrder )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
FreeMemory((LPVOID *)&myBootEntry);
FreeMemory((LPVOID *)&BootEntryOrder);
FreeMemory((LPVOID *)&myChBootEntry);
return (EXIT_FAILURE);
}
NewTempBootEntryOrder = NewBootEntryOrder;
memcpy(NewTempBootEntryOrder,BootEntryOrder,length*sizeof(ULONG));
NewTempBootEntryOrder = NewTempBootEntryOrder + length;
*NewTempBootEntryOrder = Id;
status = NtSetBootEntryOrder(NewBootEntryOrder, length+1);
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
dwErrorCode = error;
ShowMessage(stderr,GetResString(IDS_ERROR_SET_BOOTENTRY));
}
//free the memory
FreeMemory((LPVOID *)&NewBootEntryOrder);
FreeMemory((LPVOID *)&myBootEntry);
FreeMemory((LPVOID *)&BootEntryOrder);
FreeMemory((LPVOID *)&myChBootEntry);
return dwErrorCode;
}
DWORD
ChangeTimeOut_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
This routine chnages the Timeout value in the system
global boot options.
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DOWRD
Returns EXIT_SUCCESS if it successfull,
returns EXIT_FAILURE otherwise.
--*/
{
DWORD dwTimeOut = 0;
DWORD dwExitCode = EXIT_SUCCESS;
ULONG Flag = 0;
DWORD dwExitcode = 0;
BOOL bTimeout = FALSE;
BOOL bUsage = FALSE;
TCMDPARSER2 cmdOptions[3];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_TIMEOUT;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bTimeout;
//default timeout value
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEFAULT;
pcmdOption->dwFlags = CP2_DEFAULT | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwTimeOut;
//usage option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
if( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_TIMEOUT_USAGE));
return ( EXIT_FAILURE );
}
if(bUsage)
{
displayTimeOutUsage_IA64();
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//Check for the limit of Timeout value entered by the user.
if(dwTimeOut > TIMEOUT_MAX )
{
ShowMessage(stderr,GetResString(IDS_TIMEOUT_RANGE));
return (EXIT_FAILURE );
}
//Call the ModifyBootOptions function with the BOOT_OPTIONS_FIELD_COUNTDOWN
Flag |= BOOT_OPTIONS_FIELD_COUNTDOWN;
dwExitCode = ModifyBootOptions(dwTimeOut, NULL, 0, Flag);
return dwExitCode;
}
DWORD
ModifyBootOptions( IN ULONG Timeout,
IN LPTSTR pHeadlessRedirection,
IN ULONG NextBootEntryID,
IN ULONG Flag
)
/*++
Routine Description :
This routine Modifies the Boot options
-Timeout
-NextBootEntryID
-HeadlessRedirection
Arguments :
[ in ] Timeout - The new Timeout value
[ in ] pHeadlessRedirection - The Headless redirection string
[ in ] NextBootEntryID - The NextBootEntryID
[ in ] Flag - The Flags indicating what fields that needs to be changed
BOOT_OPTIONS_FIELD_COUNTDOWN
BOOT_OPTIONS_FIELD_NEXT_BOOT_ENTRY_ID
BOOT_OPTIONS_FIELD_HEADLESS_REDIRECTION
Return Type : DOWRD
Returns EXIT_SUCCESS if successful,
returns EXIT_FAILURE otherwise.
--*/
{
PBOOT_OPTIONS pBootOptions;
PBOOT_OPTIONS pModifiedBootOptions;
DWORD error;
NTSTATUS status;
ULONG newlength=0;
DWORD dwExitCode = EXIT_SUCCESS;
NextBootEntryID = 0;
//Query the existing Boot options and modify based on the Flag value
status = BootCfg_QueryBootOptions(&pBootOptions);
if(status != STATUS_SUCCESS)
{
error = RtlNtStatusToDosError( status );
FreeMemory((LPVOID *)&pBootOptions);
return (error);
}
//Calculate the new length of the BOOT_OPTIONS struct based on the fields that needs to be changed.
newlength = FIELD_OFFSET(BOOT_OPTIONS, HeadlessRedirection);
if((Flag & BOOT_OPTIONS_FIELD_HEADLESS_REDIRECTION))
{
newlength = FIELD_OFFSET(BOOT_OPTIONS, HeadlessRedirection);
newlength += StringLengthW(pHeadlessRedirection,0);
newlength = ALIGN_UP(newlength, ULONG);
}
else
{
newlength = pBootOptions->Length;
}
//Also allocate the memory for a new Boot option struct
pModifiedBootOptions = (PBOOT_OPTIONS)AllocateMemory(newlength);
if(pModifiedBootOptions == NULL)
{
FreeMemory((LPVOID *)&pBootOptions);
return (EXIT_FAILURE);
}
//Fill in the new boot options struct
pModifiedBootOptions->Version = BOOT_OPTIONS_VERSION;
pModifiedBootOptions->Length = newlength;
if((Flag & BOOT_OPTIONS_FIELD_COUNTDOWN))
{
pModifiedBootOptions->Timeout = Timeout;
}
else
{
pModifiedBootOptions->Timeout = pBootOptions->Timeout;
}
//Cannot change the CurrentBootEntryId.So just pass what u got.
pModifiedBootOptions->CurrentBootEntryId = pBootOptions->CurrentBootEntryId;
if((Flag & BOOT_OPTIONS_FIELD_NEXT_BOOT_ENTRY_ID))
{
pModifiedBootOptions->NextBootEntryId = pBootOptions->NextBootEntryId;
}
else
{
pModifiedBootOptions->NextBootEntryId = pBootOptions->NextBootEntryId;
}
if((Flag & BOOT_OPTIONS_FIELD_HEADLESS_REDIRECTION))
{
StringCopy(pModifiedBootOptions->HeadlessRedirection, pBootOptions->HeadlessRedirection, StringLengthW(pBootOptions->HeadlessRedirection,0));
}
else
{
StringCopy(pModifiedBootOptions->HeadlessRedirection, pBootOptions->HeadlessRedirection, StringLengthW(pBootOptions->HeadlessRedirection,0));
}
//Set the boot options in the NVRAM
status = NtSetBootOptions(pModifiedBootOptions, Flag);
if(status != STATUS_SUCCESS)
{
dwExitCode = EXIT_SUCCESS;
if((Flag & BOOT_OPTIONS_FIELD_COUNTDOWN))
{
DISPLAY_MESSAGE(stderr,GetResString(IDS_ERROR_MODIFY_TIMEOUT));
}
if((Flag & BOOT_OPTIONS_FIELD_NEXT_BOOT_ENTRY_ID))
{
DISPLAY_MESSAGE(stderr,GetResString(IDS_ERROR_MODIFY_NEXTBOOTID));
}
if((Flag & BOOT_OPTIONS_FIELD_HEADLESS_REDIRECTION))
{
DISPLAY_MESSAGE(stderr,GetResString(IDS_ERROR_MODIFY_HEADLESS));
}
}
else
{
dwExitCode = EXIT_SUCCESS;
if((Flag & BOOT_OPTIONS_FIELD_COUNTDOWN))
{
ShowMessage(stdout,GetResString(IDS_SUCCESS_MODIFY_TIMEOUT));
}
if((Flag & BOOT_OPTIONS_FIELD_NEXT_BOOT_ENTRY_ID))
{
ShowMessage(stdout,GetResString(IDS_SUCCESS_MODIFY_NEXTBOOTID));
}
if((Flag & BOOT_OPTIONS_FIELD_HEADLESS_REDIRECTION))
{
ShowMessage(stdout,GetResString(IDS_SUCCESS_MODIFY_HEADLESS));
}
}
//free the memory
FreeMemory((LPVOID *) &pModifiedBootOptions);
FreeMemory((LPVOID *) &pBootOptions);
return dwExitCode;
}
DWORD
ConvertBootEntries(PBOOT_ENTRY_LIST NtBootEntries)
/*++
Routine Description :
Convert boot entries read from EFI NVRAM into our internal format.
Arguments :
[ in ] NtBootEntries - The boot entry list given by the enumeration
Return Type : DWORD
--*/
{
PBOOT_ENTRY_LIST bootEntryList;
PBOOT_ENTRY bootEntry;
PBOOT_ENTRY bootEntryCopy;
PMY_BOOT_ENTRY myBootEntry;
PWINDOWS_OS_OPTIONS osOptions;
ULONG length = 0;
DWORD dwErrorCode = EXIT_SUCCESS;
BOOL bNoBreak = TRUE;
bootEntryList = NtBootEntries;
do
{
bootEntry = &bootEntryList->BootEntry;
//
// Calculate the length of our internal structure. This includes
// the base part of MY_BOOT_ENTRY plus the NT BOOT_ENTRY.
//
length = FIELD_OFFSET(MY_BOOT_ENTRY, NtBootEntry) + bootEntry->Length;
//Remember to check for the NULL pointer
myBootEntry = (PMY_BOOT_ENTRY)AllocateMemory(length);
if(myBootEntry == NULL)
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
RtlZeroMemory(myBootEntry, length);
//
// Link the new entry into the list.
//
if ( (bootEntry->Attributes & BOOT_ENTRY_ATTRIBUTE_ACTIVE) )
{
InsertTailList( &ActiveUnorderedBootEntries, &myBootEntry->ListEntry );
myBootEntry->ListHead = &ActiveUnorderedBootEntries;
}
else
{
InsertTailList( &InactiveUnorderedBootEntries, &myBootEntry->ListEntry );
myBootEntry->ListHead = &InactiveUnorderedBootEntries;
}
//
// Copy the NT BOOT_ENTRY into the allocated buffer.
//
bootEntryCopy = &myBootEntry->NtBootEntry;
memcpy(bootEntryCopy, bootEntry, bootEntry->Length);
//
// Fill in the base part of the structure.
//
myBootEntry->AllocationEnd = (PUCHAR)myBootEntry + length - 1;
myBootEntry->Id = bootEntry->Id;
//Assign 0 to the Ordered field currently so that
//once the boot order is known, we can assign 1 if this entry is a part of the ordered list.
myBootEntry->Ordered = 0;
myBootEntry->Attributes = bootEntry->Attributes;
myBootEntry->FriendlyName = (PWSTR)ADD_OFFSET(bootEntryCopy, FriendlyNameOffset);
myBootEntry->FriendlyNameLength =((ULONG)StringLengthW(myBootEntry->FriendlyName,0) + 1) * sizeof(WCHAR);
myBootEntry->BootFilePath = (PFILE_PATH)ADD_OFFSET(bootEntryCopy, BootFilePathOffset);
//
// If this is an NT boot entry, capture the NT-specific information in
// the OsOptions.
//
osOptions = (PWINDOWS_OS_OPTIONS)bootEntryCopy->OsOptions;
if ((bootEntryCopy->OsOptionsLength >= FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions)) &&
(strcmp((char *)osOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE) == 0))
{
MBE_SET_IS_NT( myBootEntry );
myBootEntry->OsLoadOptions = osOptions->OsLoadOptions;
myBootEntry->OsLoadOptionsLength =((ULONG)StringLengthW(myBootEntry->OsLoadOptions,0) + 1) * sizeof(WCHAR);
myBootEntry->OsFilePath = (PFILE_PATH)ADD_OFFSET(osOptions, OsLoadPathOffset);
}
else
{
//
// Foreign boot entry. Just capture whatever OS options exist.
//
myBootEntry->ForeignOsOptions = bootEntryCopy->OsOptions;
myBootEntry->ForeignOsOptionsLength = bootEntryCopy->OsOptionsLength;
}
//
// Move to the next entry in the enumeration list, if any.
//
if (bootEntryList->NextEntryOffset == 0)
{
bNoBreak = FALSE;
break;
}
bootEntryList = (PBOOT_ENTRY_LIST)ADD_OFFSET(bootEntryList, NextEntryOffset);
} while ( TRUE == bNoBreak );
return dwErrorCode;
} // ConvertBootEntries
DWORD DisplayBootOptions()
/*++
Name : DisplayBootOptions
Synopsis : Display the boot options
Parameters : NONE
Return Type : DWORD
Global Variables: Global Linked lists for storing the boot entries
LIST_ENTRY BootEntries;
--*/
{
DWORD error;
NTSTATUS status;
PBOOT_OPTIONS pBootOptions;
TCHAR szDisplay[MAX_RES_STRING+1] = NULL_STRING;
//Query the boot options
status = BootCfg_QueryBootOptions(&pBootOptions);
if(status != STATUS_SUCCESS)
{
error = RtlNtStatusToDosError( status );
if(pBootOptions)
{
FreeMemory((LPVOID *)&pBootOptions);
}
return EXIT_FAILURE;
}
//Printout the boot options
ShowMessage(stdout,_T("\n"));
ShowMessage(stdout,GetResString(IDS_OUTPUT_IA64A));
ShowMessage(stdout,GetResString(IDS_OUTPUT_IA64B));
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64C), pBootOptions->Timeout);
//display default boot entry id
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64P), GetDefaultBootEntry());
//Get the CurrentBootEntryId from the actual Id present in the boot options
SecureZeroMemory( szDisplay, SIZE_OF_ARRAY(szDisplay) );
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64D), GetCurrentBootEntryID(pBootOptions->CurrentBootEntryId));
ShowMessage(stdout,L"\n");
#if 0
if(StringLengthW(pBootOptions->HeadlessRedirection) == 0)
{
ShowMessage(stdout,GetResString(IDS_OUTPUT_IA64E));
}
else
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64F), pBootOptions->HeadlessRedirection);
}
#endif //Commenting out the display of the Headless redirection
//as we cannot query the same through API (its Firmware controlled)
if(pBootOptions)
{
FreeMemory((LPVOID *)&pBootOptions);
}
return EXIT_SUCCESS;
}
VOID DisplayBootEntry()
/*++
Routine Description : Display the boot entries (in an order)
Parameters : NONE
Return Type : DWORD
--*/
{
PLIST_ENTRY listEntry;
PMY_BOOT_ENTRY bootEntry;
PWSTR NtFilePath;
//Printout the boot entires
ShowMessage(stdout,GetResString(IDS_OUTPUT_IA64G));
ShowMessage(stdout,GetResString(IDS_OUTPUT_IA64H));
for (listEntry = BootEntries.Flink;listEntry != &BootEntries; listEntry = listEntry->Flink)
{
//Get the boot entry
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64I), bootEntry->myId);
//friendly name
if(StringLengthW(bootEntry->FriendlyName,0)!=0)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64J), bootEntry->FriendlyName);
}
else
{
ShowMessage(stdout,GetResString(IDS_OUTPUT_IA64K));
}
if(MBE_IS_NT(bootEntry))
{
//the OS load options
if(StringLengthW(bootEntry->OsLoadOptions, 0)!=0)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64L), bootEntry->OsLoadOptions);
}
else
{
ShowMessage(stdout,GetResString(IDS_OUTPUT_IA64M));
}
//Get the BootFilePath
NtFilePath = GetNtNameForFilePath(bootEntry->BootFilePath);
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64N), NtFilePath);
//free the memory
if(NtFilePath)
{
FreeMemory((LPVOID *)&NtFilePath);
}
//Get the OS load path
NtFilePath = GetNtNameForFilePath(bootEntry->OsFilePath);
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_OUTPUT_IA64O), NtFilePath);
//free the memory
if(NtFilePath)
{
FreeMemory((LPVOID *)&NtFilePath);
}
}
else
{
ShowMessage(stdout,_T("\n"));
}
}
}
DWORD GetCurrentBootEntryID(DWORD Id)
/*++
Routine Description :
Gets the Boot entry ID generated by us from the BootId given by the NVRAM
Arguments :
[ in ] Id - The current boot id (BootId given by the NVRAM)
Return Type : DWORD
Returns EXIT_SUCCESS if successful,
returns EXIT_FAILURE otherwise
--*/
{
PLIST_ENTRY listEntry;
PMY_BOOT_ENTRY bootEntry;
for (listEntry = BootEntries.Flink;listEntry != &BootEntries;listEntry = listEntry->Flink)
{
//Get the boot entry
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(bootEntry->Id == Id)
{
return bootEntry->myId;
}
}
return 0;
}
DWORD
ChangeDefaultBootEntry_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
This routine is to change the Default boot entry in the NVRAM
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
--*/
{
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
NTSTATUS status;
PULONG BootEntryOrder, NewBootEntryOrder;
DWORD dwBootID = 0;
BOOL bDefaultOs = FALSE ;
DWORD dwExitCode = ERROR_SUCCESS;
BOOL bBootIdFound = FALSE;
BOOL bIdFoundInBootOrderList = FALSE;
ULONG length, i, j, defaultId = 0;
DWORD error = 0;
DWORD dwExitcode = 0;
BOOL bUsage = FALSE;
TCMDPARSER2 cmdOptions[3];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEFAULTOS;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bDefaultOs;
//id option
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
//usage option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
if( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE );
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_DEFAULTOS_USAGE));
return ( EXIT_FAILURE );
}
if(bUsage)
{
displayDefaultEntryUsage_IA64();
return EXIT_SUCCESS;
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//Check whether the boot entry entered bu the user is a valid boot entry id or not.
for (listEntry = BootEntries.Flink;listEntry != &BootEntries;listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
//store the default ID
defaultId = mybootEntry->Id;
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
return (EXIT_FAILURE);
}
// Get the system boot order list.
length = 0;
status = NtQueryBootEntryOrder( NULL, &length );
if ( status != STATUS_BUFFER_TOO_SMALL )
{
if ( status == STATUS_SUCCESS )
{
length = 0;
}
else
{
error = RtlNtStatusToDosError( status );
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_DEFAULT_ENTRY),dwBootID);
return (EXIT_FAILURE);
}
}
if ( length != 0 )
{
BootEntryOrder = (PULONG)AllocateMemory( length * sizeof(ULONG) );
if(BootEntryOrder == NULL)
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
status = NtQueryBootEntryOrder( BootEntryOrder, &length );
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_DEFAULT_ENTRY),dwBootID);
FreeMemory((LPVOID *)&BootEntryOrder);
return EXIT_FAILURE;
}
}
//Check if the boot id entered by the user is a part of the Boot entry order.
//If not for the time being do not make it the default.
for(i=0;i<length;i++)
{
if(*(BootEntryOrder+i) == defaultId)
{
bIdFoundInBootOrderList = TRUE;
break;
}
}
if(bIdFoundInBootOrderList == FALSE)
{
FreeMemory((LPVOID *)&BootEntryOrder);
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_DEFAULT_ENTRY),dwBootID);
return (EXIT_FAILURE);
}
//Allocate memory for storing the new boot entry order.
NewBootEntryOrder = (PULONG)AllocateMemory((length) * sizeof(ULONG));
if(NewBootEntryOrder == NULL)
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
FreeMemory((LPVOID *)&BootEntryOrder);
return (EXIT_FAILURE);
}
*NewBootEntryOrder = defaultId;
j=0;
for(i=0;i<length;i++)
{
if(*(BootEntryOrder+i) == defaultId)
{
continue;
}
*(NewBootEntryOrder+(j+1)) = *(BootEntryOrder+i);
j++;
}
status = NtSetBootEntryOrder(NewBootEntryOrder, length);
if ( status != STATUS_SUCCESS )
{
error = RtlNtStatusToDosError( status );
dwExitCode = error;
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_DEFAULT_ENTRY),dwBootID);
}
else
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_SUCCESS_DEFAULT_ENTRY),dwBootID);
}
//free the memory
FreeMemory((LPVOID *)&NewBootEntryOrder);
FreeMemory((LPVOID *)&BootEntryOrder);
return dwExitCode;
}
DWORD
ProcessDebugSwitch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
Allows the user to add the OS load options specifed
as a debug string at the cmdline to the boot
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
Returns EXIT_SUCCESS if successful,
returns EXIT_FAILURE otherwise.
--*/
{
BOOL bUsage = FALSE ;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
PBOOT_ENTRY bootEntry;
TCHAR szPort[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szBaudRate[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szDebug[MAX_RES_STRING+1] = NULL_STRING ;
BOOL bDebug = FALSE ;
PWINDOWS_OS_OPTIONS pWindowsOptions = NULL ;
TCHAR szOsLoadOptions[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szTemp[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szTmpBuffer[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[6];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEBUG;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bDebug;
//usage
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
//id option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
//port option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_PORT;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MODE_VALUES | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szPort;
pcmdOption->pwszValues = COM_PORT_RANGE;
pcmdOption->dwLength= MAX_STRING_LENGTH;
//baud option
pcmdOption = &cmdOptions[4];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_BAUD;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MODE_VALUES | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szBaudRate;
pcmdOption->pwszValues = BAUD_RATE_VALUES_DEBUG;
pcmdOption->dwLength= MAX_STRING_LENGTH;
//default on/off option
pcmdOption = &cmdOptions[5];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEFAULT;
pcmdOption->dwFlags = CP2_DEFAULT | CP2_MANDATORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szDebug;
pcmdOption->dwLength= MAX_STRING_LENGTH;
// Parsing the copy option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_DEBUG));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayDebugUsage_IA64();
return (ERROR_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//Trim any leading or trailing spaces
if(StringLengthW(szDebug, 0)!=0)
{
TrimString(szDebug, TRIM_ALL);
}
if( !( ( StringCompare(szDebug,VALUE_ON,TRUE,0)== 0) || (StringCompare(szDebug,VALUE_OFF,TRUE,0)== 0 ) ||(StringCompare(szDebug,EDIT_STRING,TRUE,0)== 0) ) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_DEBUG));
return EXIT_FAILURE;
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries; listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
bootEntry = &mybootEntry->NtBootEntry;
//Check whether the bootEntry is a Windows one or not.
//The OS load options can be added only to a Windows boot entry.
if(!IsBootEntryWindows(bootEntry))
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
dwExitCode = EXIT_FAILURE;
break;
}
//Change the OS load options. Pass NULL to friendly name as we are not changing the same
//szRawString is the Os load options specified by the user
pWindowsOptions = (PWINDOWS_OS_OPTIONS)bootEntry->OsOptions;
if(StringLengthW(pWindowsOptions->OsLoadOptions, 0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
// copy the existing OS Loadoptions into a string.
StringCopy(szOsLoadOptions,pWindowsOptions->OsLoadOptions, SIZE_OF_ARRAY(szOsLoadOptions));
//check if the user has entered On option
if( StringCompare(szDebug,VALUE_ON,TRUE,0)== 0)
{
//display an error message
if ( (FindString(szOsLoadOptions,DEBUG_SWITCH, 0) != 0 )&& (StringLengthW(szPort, 0)==0) &&(StringLengthW(szBaudRate, 0)==0) )
{
ShowMessage(stderr,GetResString(IDS_DUPL_DEBUG));
dwExitCode = EXIT_FAILURE;
break;
}
//display a error message and exit if the 1394 port is already present.
if(FindString(szOsLoadOptions,DEBUGPORT_1394, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_1394_ALREADY_PRESENT));
dwExitCode = EXIT_FAILURE;
break;
}
//
//display an duplicate entry error message if substring is already present.
//
if(StringLengthW(szBaudRate, 0)==0)
{
if ( GetSubString(szOsLoadOptions,TOKEN_DEBUGPORT,szTemp) == EXIT_SUCCESS )
{
ShowMessage(stderr,GetResString(IDS_DUPLICATE_ENTRY));
return EXIT_FAILURE ;
}
}
if(StringLengthW(szTemp, 0)!=0)
{
ShowMessage(stderr,GetResString(IDS_DUPLICATE_ENTRY));
dwExitCode = EXIT_FAILURE;
break;
}
//check if the Os load options already contains
// debug switch
if(FindString(szOsLoadOptions,DEBUG_SWITCH, 0) == 0 )
{
if(StringLengthW(szOsLoadOptions, 0)!=0)
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,DEBUG_SWITCH, SIZE_OF_ARRAY(szOsLoadOptions) );
}
else
{
StringCopy(szTmpBuffer,DEBUG_SWITCH, SIZE_OF_ARRAY(szOsLoadOptions) );
}
}
if(StringLengthW(szPort, 0)!= 0)
{
if(StringLengthW(szTmpBuffer, 0)==0)
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
StringConcat(szTmpBuffer,TOKEN_DEBUGPORT, SIZE_OF_ARRAY(szTmpBuffer)) ;
StringConcat(szTmpBuffer,TOKEN_EQUAL, SIZE_OF_ARRAY(szTmpBuffer)) ;
CharUpper(szPort);
StringConcat(szTmpBuffer,szPort, SIZE_OF_ARRAY(szTmpBuffer));
}
//Check if the OS Load Options contains the baud rate already specified.
if(StringLengthW(szBaudRate, 0)!=0)
{
StringCopy(szTemp,NULL_STRING, SIZE_OF_ARRAY(szTemp) );
GetBaudRateVal(szOsLoadOptions,szTemp) ;
if(StringLengthW(szTemp, 0)!=0)
{
ShowMessage(stderr,GetResString(IDS_DUPLICATE_BAUD_RATE));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
if(StringLengthW(szTmpBuffer, 0)==0)
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
StringConcat(szTmpBuffer,BAUD_RATE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,TOKEN_EQUAL, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,szBaudRate, SIZE_OF_ARRAY(szTmpBuffer));
}
}
}
//check if the user has entered OFF option
if( StringCompare(szDebug,VALUE_OFF,TRUE,0)== 0)
{
// If the user enters either com port or baud rate then display error message and exit.
if ((StringLengthW(szPort, 0)!=0) ||(StringLengthW(szBaudRate, 0)!=0))
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_DEBUG));
dwExitCode = EXIT_FAILURE;
break;
}
// if debug port is absent print message and exit.
if (FindString(szOsLoadOptions,DEBUG_SWITCH, 0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_DEBUG_ABSENT));
dwExitCode = EXIT_FAILURE;
break;
}
//remove the debug switch from the OSLoad Options
removeSubString(szOsLoadOptions,DEBUG_SWITCH);
if(FindString(szOsLoadOptions,DEBUGPORT_1394, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_ERROR_1394_REMOVE));
dwExitCode = EXIT_FAILURE;
break;
}
GetSubString(szOsLoadOptions, TOKEN_DEBUGPORT,szTemp);
if(StringLengthW(szTemp, 0)!=0)
{
// remove the /debugport=comport switch if it is present from the Boot Entry
removeSubString(szOsLoadOptions,szTemp);
}
StringCopy(szTemp , NULL_STRING, SIZE_OF_ARRAY(szTemp) );
//remove the baud rate switch if it is present.
GetBaudRateVal(szOsLoadOptions,szTemp) ;
// if the OSLoadOptions contains baudrate then delete it.
if (StringLengthW(szTemp, 0 )!= 0)
{
removeSubString(szOsLoadOptions,szTemp);
}
}
//if the user selected the edit option .
if( StringCompare(szDebug,EDIT_STRING,TRUE,0)== 0)
{
//check if the debug switch is present in the Osload options else display error message.
if (FindString(szOsLoadOptions,DEBUG_SWITCH, 0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_DEBUG_ABSENT));
dwExitCode = EXIT_FAILURE;
break;
}
if( FindString(szOsLoadOptions,DEBUGPORT_1394, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_ERROR_EDIT_1394_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
//check if the user enters COM port or baud rate else display error message.
if((StringLengthW(szPort, 0)==0)&&(StringLengthW(szBaudRate, 0)==0))
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_DEBUG));
dwExitCode = EXIT_FAILURE;
break;
}
if( StringLengthW(szPort, 0)!=0 )
{
if ( GetSubString(szOsLoadOptions,TOKEN_DEBUGPORT,szTemp) == EXIT_FAILURE)
{
ShowMessage(stderr,GetResString(IDS_NO_DEBUGPORT));
return EXIT_FAILURE ;
}
if(StringLengthW(szTemp, 0)!=0)
{
//remove the existing entry from the OsLoadOptions String.
removeSubString(szOsLoadOptions,szTemp);
}
//Add the port entry specified by user into the OsLoadOptions String.
if(StringLengthW(szTmpBuffer, 0)==0)
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
StringConcat(szTmpBuffer,TOKEN_DEBUGPORT, SIZE_OF_ARRAY(szTmpBuffer)) ;
StringConcat(szTmpBuffer,TOKEN_EQUAL, SIZE_OF_ARRAY(szTmpBuffer)) ;
CharUpper(szPort);
StringConcat(szTmpBuffer,szPort, SIZE_OF_ARRAY(szTmpBuffer));
}
//Check if the OS Load Options contains the baud rate already specified.
if(StringLengthW(szBaudRate, 0)!=0)
{
StringCopy(szTemp,NULL_STRING, SIZE_OF_ARRAY(szTemp));
GetBaudRateVal(szOsLoadOptions,szTemp) ;
if(StringLengthW(szTemp, 0)!=0)
{
removeSubString(szOsLoadOptions,szTemp);
}
//add the baud rate value to boot entry
if(StringLengthW(szTmpBuffer, 0) == 0)
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
StringConcat(szTmpBuffer,BAUD_RATE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,TOKEN_EQUAL, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,szBaudRate, SIZE_OF_ARRAY(szTmpBuffer));
}
}
//display error message if Os Load options is more than 254
// characters.
if(StringLengthW(szOsLoadOptions, 0) + StringLengthW(szTmpBuffer,0)> MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
else
{
StringConcat(szOsLoadOptions,szTmpBuffer, SIZE_OF_ARRAY(szOsLoadOptions));
}
// modify the Boot Entry with the modified OsLoad Options.
dwExitCode = ChangeBootEntry(bootEntry, NULL, szOsLoadOptions);
if(dwExitCode == ERROR_SUCCESS)
{
ShowMessageEx(stdout,1,TRUE, GetResString(IDS_SUCCESS_CHANGE_OSOPTIONS),dwBootID);
}
else
{
ShowMessageEx(stderr,1,TRUE, GetResString(IDS_ERROR_CHANGE_OSOPTIONS),dwBootID);
}
break;
}
}
if(FALSE == bBootIdFound )
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
dwExitCode = EXIT_FAILURE;
}
//Remember to free memory allocated for the linked lists
Freelist();
return (dwExitCode);
}
VOID
GetComPortType_IA64( IN LPTSTR szString,
IN LPTSTR szTemp
)
/*++
Routine Description:
Get the Type of Com Port present in Boot Entry
Arguments :
[ in ] szString : The String which is to be searched.
[ in ] szTemp : String which will get the com port type
Return Type : VOID
--*/
{
if(FindString(szString,PORT_COM1A, 0)!=0)
{
StringCopy(szTemp,PORT_COM1A, MAX_RES_STRING);
}
else if(FindString(szString,PORT_COM2A,0)!=0)
{
StringCopy(szTemp,PORT_COM2A, MAX_RES_STRING);
}
else if(FindString(szString,PORT_COM3A,0)!=0)
{
StringCopy(szTemp,PORT_COM3A, MAX_RES_STRING);
}
else if(FindString(szString,PORT_COM4A,0)!=0)
{
StringCopy(szTemp,PORT_COM4A, MAX_RES_STRING);
}
else if(FindString(szString,PORT_1394A,0)!=0)
{
StringCopy(szTemp,PORT_1394A, MAX_RES_STRING);
}
}
DWORD
ProcessEmsSwitch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
Which process the ems switch.
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
--*/
{
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
PBOOT_ENTRY bootEntry;
PWINDOWS_OS_OPTIONS pWindowsOptions = NULL ;
BOOL bUsage = FALSE ;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
TCHAR szEms[MAX_STRING_LENGTH+1] = NULL_STRING ;
BOOL bEms = FALSE ;
TCHAR szOsLoadOptions[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szTmpBuffer[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[4];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_EMS;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bEms;
//usage
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
//id option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
//default on/off option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEFAULT;
pcmdOption->dwFlags = CP2_DEFAULT | CP2_MANDATORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szEms;
pcmdOption->dwLength= MAX_STRING_LENGTH;
// Parsing the ems option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_EMS));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayEmsUsage_IA64();
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//display error message if the user enters any other string other that on/off.
if( !((StringCompare(szEms,VALUE_ON,TRUE,0)== 0) || (StringCompare(szEms,VALUE_OFF,TRUE,0)== 0)))
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_EMS));
return EXIT_FAILURE ;
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries;listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
bootEntry = &mybootEntry->NtBootEntry;
//Check whether the bootEntry is a Windows one or not.
//The OS load options can be added only to a Windows boot entry.
if(!IsBootEntryWindows(bootEntry))
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
dwExitCode = EXIT_FAILURE;
break;
}
pWindowsOptions = (PWINDOWS_OS_OPTIONS)bootEntry->OsOptions;
if(StringLengthW(pWindowsOptions->OsLoadOptions, 0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
// copy the existing OS Loadoptions into a string.
StringCopy(szOsLoadOptions,pWindowsOptions->OsLoadOptions, SIZE_OF_ARRAY(szOsLoadOptions));
//check if the user has entered On option
if( StringCompare(szEms,VALUE_ON,TRUE,0)== 0)
{
if (FindString(szOsLoadOptions,REDIRECT_SWITCH, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_DUPL_REDIRECT));
dwExitCode = EXIT_FAILURE;
break;
}
// add the redirect switch to the OS Load Options string.
if( StringLength(szOsLoadOptions,0) != 0 )
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,REDIRECT_SWITCH, SIZE_OF_ARRAY(szTmpBuffer) );
}
else
{
StringCopy(szTmpBuffer,REDIRECT_SWITCH, SIZE_OF_ARRAY(szTmpBuffer) );
}
}
//check if the user has entered OFF option
if( StringCompare(szEms,VALUE_OFF,TRUE,0)== 0)
{
// If the user enters either com port or baud rate then display error message and exit.
if (FindString(szOsLoadOptions,REDIRECT_SWITCH, 0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_REDIRECT_ABSENT));
dwExitCode = EXIT_FAILURE;
break;
}
//remove the debug switch from the OSLoad Options
removeSubString(szOsLoadOptions,REDIRECT_SWITCH);
}
//display error message if Os Load options is more than 254
// characters.
if(StringLengthW(szOsLoadOptions, 0)+StringLength(szTmpBuffer,0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
else
{
StringConcat( szOsLoadOptions, szTmpBuffer, SIZE_OF_ARRAY(szOsLoadOptions) );
}
// modify the Boot Entry with the modified OsLoad Options.
dwExitCode = ChangeBootEntry(bootEntry, NULL, szOsLoadOptions);
if(dwExitCode == ERROR_SUCCESS)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_SUCCESS_CHANGE_OSOPTIONS),dwBootID);
}
else
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_CHANGE_OSOPTIONS),dwBootID);
}
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
dwExitCode = EXIT_FAILURE;
}
//free the global linked lists
Freelist();
return (dwExitCode);
}
DWORD
ProcessAddSwSwitch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
Which implements the Addsw switch.
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
Returns EXIT_SUCCESS if it is successful,
return EXIT_FAILURE otherwise.
--*/
{
BOOL bUsage = FALSE ;
BOOL bAddSw = FALSE ;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
PBOOT_ENTRY bootEntry;
BOOL bBaseVideo = FALSE ;
BOOL bNoGui = FALSE ;
BOOL bSos = FALSE ;
DWORD dwMaxmem = 0 ;
PWINDOWS_OS_OPTIONS pWindowsOptions = NULL ;
TCHAR szOsLoadOptions[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szTmpBuffer[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szMaxmem[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[7];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_ADDSW;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bAddSw;
// usage
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
//id option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
//maxmem option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_MAXMEM;
pcmdOption->dwFlags = CP_VALUE_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwMaxmem;
//basvideo option
pcmdOption = &cmdOptions[4];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_BASEVIDEO;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bBaseVideo;
//nogui option
pcmdOption = &cmdOptions[5];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_NOGUIBOOT;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bNoGui;
//nogui option
pcmdOption = &cmdOptions[6];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_SOS;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bSos;
// Parsing the copy option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_ADDSW));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayAddSwUsage_IA64();
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
if((0==dwMaxmem)&&(cmdOptions[3].dwActuals!=0))
{
ShowMessage(stderr,GetResString(IDS_ERROR_MAXMEM_VALUES));
return EXIT_FAILURE ;
}
//display an error mesage if none of the options are specified.
if((!bSos)&&(!bBaseVideo)&&(!bNoGui)&&(dwMaxmem==0))
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_ADDSW));
return EXIT_FAILURE ;
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries; listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
bootEntry = &mybootEntry->NtBootEntry;
//Check whether the bootEntry is a Windows one or not.
//The OS load options can be added only to a Windows boot entry.
if(!IsBootEntryWindows(bootEntry))
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
dwExitCode = EXIT_FAILURE;
break;
}
pWindowsOptions = (PWINDOWS_OS_OPTIONS)bootEntry->OsOptions;
if(StringLengthW(pWindowsOptions->OsLoadOptions,0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
// copy the existing OS Loadoptions into a string.
StringCopy(szOsLoadOptions,pWindowsOptions->OsLoadOptions, SIZE_OF_ARRAY(szOsLoadOptions));
//check if the user has entered -basevideo option
if(bBaseVideo)
{
if (FindString(szOsLoadOptions,BASEVIDEO_VALUE, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_DUPL_BASEVIDEO_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
StringCopy(szTmpBuffer,BASEVIDEO_VALUE, SIZE_OF_ARRAY(szTmpBuffer) );
}
}
if(bSos)
{
if (FindString(szOsLoadOptions,SOS_VALUE, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_DUPL_SOS_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
// add the sos switch to the OS Load Options string.
if(StringLengthW(szTmpBuffer, 0) != 0)
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,SOS_VALUE, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringCopy(szTmpBuffer,SOS_VALUE, SIZE_OF_ARRAY(szTmpBuffer));
}
}
}
if(bNoGui)
{
if (FindString(szOsLoadOptions,NOGUI_VALUE, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_DUPL_NOGUI_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
// add the no gui switch to the OS Load Options string.
if(StringLengthW(szTmpBuffer, 0) != 0)
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,NOGUI_VALUE, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringCopy(szTmpBuffer,NOGUI_VALUE, SIZE_OF_ARRAY(szTmpBuffer));
}
}
}
if(dwMaxmem!=0)
{
// check if the maxmem value is in the valid range.
if( (dwMaxmem < 32) )
{
ShowMessage(stderr,GetResString(IDS_ERROR_MAXMEM_VALUES));
dwExitCode = EXIT_FAILURE;
break;
}
if (FindString(szOsLoadOptions,MAXMEM_VALUE1, 0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_DUPL_MAXMEM_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
// add the maxmem switch to the OS Load Options string.
if(StringLengthW(szTmpBuffer, 0) != 0)
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,MAXMEM_VALUE1, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,TOKEN_EQUAL, SIZE_OF_ARRAY(szTmpBuffer));
_ltow(dwMaxmem,szMaxmem,10);
StringConcat(szTmpBuffer,szMaxmem, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringCopy(szTmpBuffer,MAXMEM_VALUE1, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,TOKEN_EQUAL, SIZE_OF_ARRAY(szTmpBuffer));
_ltow(dwMaxmem,szMaxmem,10);
StringConcat(szTmpBuffer,szMaxmem, SIZE_OF_ARRAY(szTmpBuffer));
}
}
}
//display error message if Os Load options is more than 254
// characters.
if(StringLengthW(szOsLoadOptions, 0)+StringLength(szTmpBuffer,0) + StringLength(TOKEN_EMPTYSPACE,0)> MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
else
{
if( StringLength(szOsLoadOptions,0) != 0 )
{
StringConcat(szOsLoadOptions,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szOsLoadOptions));
StringConcat(szOsLoadOptions,szTmpBuffer,SIZE_OF_ARRAY(szOsLoadOptions));
}
else
{
StringCopy(szOsLoadOptions,szTmpBuffer,SIZE_OF_ARRAY(szOsLoadOptions));
}
}
//Change the OS load options. Pass NULL to friendly name as we are not changing the same
//szRawString is the Os load options specified by the user
dwExitCode = ChangeBootEntry(bootEntry, NULL, szOsLoadOptions);
if(dwExitCode == ERROR_SUCCESS)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_SUCCESS_OSOPTIONS),dwBootID);
}
else
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
}
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
dwExitCode = EXIT_FAILURE;
}
//Remember to free memory allocated for the linked lists
Freelist();
return (dwExitCode);
}
DWORD
ProcessRmSwSwitch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
Process the rmsw switch
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
Returns EXIT_SUCCESS if it is successful,
returns EXIT_FAILURE otherwise.
--*/
{
BOOL bUsage = FALSE ;
BOOL bRmSw = FALSE ;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
PBOOT_ENTRY bootEntry;
BOOL bBaseVideo = FALSE ;
BOOL bNoGui = FALSE ;
BOOL bSos = FALSE ;
BOOL bMaxmem = FALSE ;
PWINDOWS_OS_OPTIONS pWindowsOptions = NULL ;
TCHAR szOsLoadOptions[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szTemp[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[7];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_RMSW;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bRmSw;
// usage
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
//id option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
//maxmem option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_MAXMEM;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bMaxmem;
//basvideo option
pcmdOption = &cmdOptions[4];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_BASEVIDEO;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bBaseVideo;
//nogui option
pcmdOption = &cmdOptions[5];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_NOGUIBOOT;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bNoGui;
//sos option
pcmdOption = &cmdOptions[6];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_SOS;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bSos;
// Parsing the copy option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_RMSW));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayRmSwUsage_IA64();
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//display an error mesage if none of the options are specified.
if((!bSos)&&(!bBaseVideo)&&(!bNoGui)&&(!bMaxmem))
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_RMSW));
return EXIT_FAILURE;
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries;listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
bootEntry = &mybootEntry->NtBootEntry;
//Check whether the bootEntry is a Windows one or not.
//The OS load options can be added only to a Windows boot entry.
if(!IsBootEntryWindows(bootEntry))
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
dwExitCode = EXIT_FAILURE;
break;
}
pWindowsOptions = (PWINDOWS_OS_OPTIONS)bootEntry->OsOptions;
if(StringLengthW(pWindowsOptions->OsLoadOptions, 0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
// copy the existing OS Loadoptions into a string.
StringCopy(szOsLoadOptions,pWindowsOptions->OsLoadOptions, SIZE_OF_ARRAY(szOsLoadOptions));
//check if the user has entered -basevideo option
if(bBaseVideo)
{
if (FindString(szOsLoadOptions,BASEVIDEO_VALUE, 0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_NO_BV_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
// remove the basevideo switch from the OS Load Options string.
removeSubString(szOsLoadOptions,BASEVIDEO_VALUE);
}
}
if(bSos)
{
if (FindString(szOsLoadOptions,SOS_VALUE, 0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_NO_SOS_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
// remove the /sos switch from the Load Options string.
removeSubString(szOsLoadOptions,SOS_VALUE);
}
}
if(bNoGui)
{
if (FindString(szOsLoadOptions,NOGUI_VALUE,0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_NO_NOGUI_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
// remove the noguiboot switch to the OS Load Options string.
removeSubString(szOsLoadOptions,NOGUI_VALUE);
}
}
if(bMaxmem)
{
if (FindString(szOsLoadOptions,MAXMEM_VALUE1,0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_NO_MAXMEM_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
else
{
// add the redirect switch to the OS Load Options string.
//for, a temporary string of form /maxmem=xx so that it
//can be checked in the Os load options,
if ( GetSubString(szOsLoadOptions,MAXMEM_VALUE1,szTemp) == EXIT_FAILURE)
{
return EXIT_FAILURE ;
}
removeSubString(szOsLoadOptions,szTemp);
if(FindString(szOsLoadOptions,MAXMEM_VALUE1,0)!=0)
{
ShowMessage(stderr,GetResString(IDS_NO_MAXMEM) );
return EXIT_FAILURE ;
}
}
}
//display error message if Os Load options is more than 254
// characters.
if(StringLengthW(szOsLoadOptions,0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
//Change the OS load options. Pass NULL to friendly name as we are not changing the same
//szRawString is the Os load options specified by the user
dwExitCode = ChangeBootEntry(bootEntry, NULL, szOsLoadOptions);
if(dwExitCode == ERROR_SUCCESS)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_SUCCESS_CHANGE_OSOPTIONS),dwBootID);
}
else
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
}
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
dwExitCode = EXIT_FAILURE;
}
Freelist();
return (dwExitCode);
}
DWORD
ProcessDbg1394Switch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
Which process the dbg1394 switch
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
Returns EXIT_SUCCESS if it is successful,
returns EXIT_FAILURE otherwise.
--*/
{
BOOL bUsage = FALSE ;
BOOL bDbg1394 = FALSE ;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
PMY_BOOT_ENTRY mybootEntry;
PLIST_ENTRY listEntry;
PBOOT_ENTRY bootEntry;
PWINDOWS_OS_OPTIONS pWindowsOptions = NULL ;
TCHAR szOsLoadOptions[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szTemp[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szTmpBuffer[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szChannel[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szDefault[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwChannel = 0 ;
DWORD dwCode = 0 ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[5];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DBG1394;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bDbg1394;
//id usage
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
//default option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
//id option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_CHANNEL;
pcmdOption->dwFlags = CP_VALUE_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwChannel;
//default option
pcmdOption = &cmdOptions[4];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEFAULT;
pcmdOption->dwFlags = CP2_DEFAULT | CP2_MANDATORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL;;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szDefault;
pcmdOption->dwLength= MAX_STRING_LENGTH;
// Parsing the copy option switches
if ( !DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) )
{
ShowLastErrorEx( stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_DBG1394));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayDbg1394Usage_IA64() ;
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
if((cmdOptions[2].dwActuals == 0) &&(dwBootID == 0 ))
{
ShowMessage(stderr,GetResString(IDS_ERROR_ID_MISSING));
ShowMessage(stderr,GetResString(IDS_1394_HELP));
return (EXIT_FAILURE);
}
//
//display error message if user enters a value
// other than on or off
//
if( ( StringCompare(szDefault,OFF_STRING,TRUE,0)!=0 ) && (StringCompare(szDefault,ON_STRING,TRUE,0)!=0 ) )
{
ShowMessage(stderr,GetResString(IDS_ERROR_DEFAULT_MISSING));
ShowMessage(stderr,GetResString(IDS_1394_HELP));
return (EXIT_FAILURE);
}
if(( StringCompare(szDefault,OFF_STRING,TRUE,0)==0 ) && (cmdOptions[3].dwActuals != 0) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_SYNTAX_DBG1394));
return (EXIT_FAILURE);
}
if(( StringCompare(szDefault,ON_STRING,TRUE,0)==0 ) && (cmdOptions[3].dwActuals == 0) )
{
ShowMessage(stderr,GetResString(IDS_MISSING_CHANNEL));
return (EXIT_FAILURE);
}
if(( StringCompare(szDefault,ON_STRING,TRUE,0)==0 ) && (cmdOptions[3].dwActuals != 0) &&( (dwChannel < 1) || (dwChannel > 64 ) ) )
{
ShowMessage(stderr,GetResString(IDS_INVALID_CH_RANGE));
return (EXIT_FAILURE);
}
//Query the boot entries till u get the BootID specified by the user
for (listEntry = BootEntries.Flink;listEntry != &BootEntries;listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
bootEntry = &mybootEntry->NtBootEntry;
//Check whether the bootEntry is a Windows one or not.
//The OS load options can be added only to a Windows boot entry.
if(!IsBootEntryWindows(bootEntry))
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
dwExitCode = EXIT_FAILURE;
break;
}
pWindowsOptions = (PWINDOWS_OS_OPTIONS)bootEntry->OsOptions;
if(StringLengthW(pWindowsOptions->OsLoadOptions,0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
// copy the existing OS Loadoptions into a string.
StringCopy(szOsLoadOptions,pWindowsOptions->OsLoadOptions, SIZE_OF_ARRAY(szOsLoadOptions));
//check if the user has entered on option
if(StringCompare(szDefault,ON_STRING,TRUE,0)==0 )
{
if(FindString(szOsLoadOptions,DEBUGPORT,0) != 0)
{
ShowMessage(stderr,GetResString(IDS_DUPLICATE_ENTRY));
dwExitCode = EXIT_FAILURE;
break;
}
if(FindString(szOsLoadOptions,BAUD_TOKEN,0) != 0)
{
ShowMessage(stderr,GetResString(IDS_ERROR_BAUD_RATE));
dwExitCode = EXIT_FAILURE ;
break;
}
if( FindString(szOsLoadOptions,DEBUG_SWITCH,0)== 0)
{
if( StringLength(szOsLoadOptions,0) != 0 )
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,DEBUG_SWITCH, SIZE_OF_ARRAY(szOsLoadOptions));
}
else
{
StringCopy(szTmpBuffer,DEBUG_SWITCH, SIZE_OF_ARRAY(szOsLoadOptions));
}
}
if(StringLength(szTmpBuffer,0) == 0)
{
StringCopy(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
else
{
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE, SIZE_OF_ARRAY(szTmpBuffer));
}
StringConcat(szTmpBuffer,DEBUGPORT_1394, SIZE_OF_ARRAY(szTmpBuffer)) ;
if(dwChannel!=0)
{
//frame the string and concatenate to the Os Load options.
StringConcat(szTmpBuffer,TOKEN_EMPTYSPACE,SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,TOKEN_CHANNEL,SIZE_OF_ARRAY(szTmpBuffer));
StringConcat(szTmpBuffer,TOKEN_EQUAL,SIZE_OF_ARRAY(szTmpBuffer));
_ltow(dwChannel,szChannel,10);
StringConcat(szTmpBuffer,szChannel,SIZE_OF_ARRAY(szTmpBuffer));
}
}
if(StringCompare(szDefault,OFF_STRING,TRUE,0)==0 )
{
if(FindString(szOsLoadOptions,DEBUGPORT_1394,0) == 0)
{
ShowMessage(stderr,GetResString(IDS_NO_1394_SWITCH));
dwExitCode = EXIT_FAILURE;
break;
}
//
//remove the port from the Os Load options string.
//
removeSubString(szOsLoadOptions,DEBUGPORT_1394);
// check if the string contains the channel token
// and if present remove that also.
//
if(FindString(szOsLoadOptions,TOKEN_CHANNEL,0)!=0)
{
StringCopy(szTemp,NULL_STRING, MAX_RES_STRING);
dwCode = GetSubString(szOsLoadOptions,TOKEN_CHANNEL,szTemp);
if(dwCode == EXIT_SUCCESS)
{
//
//Remove the channel token if present.
//
if(StringLengthW(szTemp,0)!= 0)
{
removeSubString(szOsLoadOptions,szTemp);
removeSubString(szOsLoadOptions,DEBUG_SWITCH);
}
}
}
removeSubString(szOsLoadOptions,DEBUG_SWITCH);
}
//display error message if Os Load options is more than 254
// characters.
if(StringLengthW(szOsLoadOptions,0)+StringLength(szTmpBuffer,0) > MAX_RES_STRING)
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_STRING_LENGTH1),MAX_RES_STRING);
return EXIT_FAILURE ;
}
else
{
StringConcat(szOsLoadOptions, szTmpBuffer, SIZE_OF_ARRAY(szOsLoadOptions) );
}
//Change the OS load options. Pass NULL to friendly name as we are not changing the same
//szRawString is the Os load options specified by the user
dwExitCode = ChangeBootEntry(bootEntry, NULL, szOsLoadOptions);
if(dwExitCode == ERROR_SUCCESS)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_SUCCESS_CHANGE_OSOPTIONS),dwBootID);
}
else
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
}
break;
}
}
if(bBootIdFound == FALSE)
{
//Could not find the BootID specified by the user so output the message and return failure
ShowMessage(stderr,GetResString(IDS_INVALID_BOOTID));
dwExitCode = EXIT_FAILURE;
}
Freelist();
return (dwExitCode);
}
DWORD
ProcessMirrorSwitch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description :
process the mirror switch
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
Returns EXIT_SUCCESS if it is successful,
returns EXIT_FAILURE otherwise.
--*/
{
BOOL bUsage = FALSE ;
DWORD dwBootID = 0;
BOOL bBootIdFound = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
PMY_BOOT_ENTRY mybootEntry;
TCHAR szAdd[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szLoaderPath[MAX_RES_STRING+1] = NULL_STRING ;
BOOL bMirror = FALSE ;
NTSTATUS status ;
DWORD error = 0 ;
TCHAR szFinalStr[256] = NULL_STRING ;
TCHAR szResult[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwActuals = 0 ;
PBOOT_ENTRY_LIST ntBootEntries = NULL;
PBOOT_ENTRY pBootEntry = NULL ;
PFILE_PATH pFilePath = NULL ;
PWSTR NtFilePath ;
PTCHAR szPartition = NULL ;
TCHAR szOsLoaderPath[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szSystemPartition[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szBrackets[] = _T("{}");
PLIST_ENTRY listEntry;
BOOL bFlag = TRUE ;
TCHAR szFriendlyName[MAX_STRING_LENGTH] = NULL_STRING ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[5];
PTCMDPARSER2 pcmdOption;
BOOL bNobreak = TRUE;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_MIRROR;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bMirror;
//id usage
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
// add option
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_ADD;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_VALUE_TRIMINPUT | CP2_VALUE_NONULL | CP2_MANDATORY;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szAdd;
pcmdOption->dwLength= MAX_STRING_LENGTH;
//id option
pcmdOption = &cmdOptions[3];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_ID;
pcmdOption->dwFlags = CP_VALUE_MANDATORY;
pcmdOption->dwType = CP_TYPE_UNUMERIC;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &dwBootID;
// friendly option
pcmdOption = &cmdOptions[4];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = SWITCH_DESCRIPTION;
pcmdOption->dwFlags = CP_VALUE_MANDATORY | CP2_VALUE_TRIMINPUT;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szFriendlyName;
pcmdOption->dwLength= MAX_STRING_LENGTH;
// Parsing the copy option switches
if ( !(DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_MIRROR_SYNTAX));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayMirrorUsage_IA64() ;
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
// If the user enters empty string after add option then display an error
// message.
TrimString(szAdd,TRIM_ALL);
TrimString(szFriendlyName,TRIM_ALL);
//
//copy the default friendly name from resource file if no
//friendly name is specified.
//
if(cmdOptions[4].dwActuals == 0)
{
StringCopy(szFriendlyName,GetResString(IDS_MIRROR_NAME), SIZE_OF_ARRAY(szFriendlyName));
}
if(StringLengthW(szAdd,0) !=0)
{
//Trim of the Brackets which may be specified
//along with the GUID.
TrimString2(szAdd, szBrackets, TRIM_ALL);
dwActuals = 0 ;
//get the ARC signature path corresponding to the GUID specified.
if (GetDeviceInfo(szAdd,szFinalStr,0,dwActuals) == EXIT_FAILURE )
{
return EXIT_FAILURE ;
}
StringConcat(szFinalStr,_T("\\WINDOWS"), SIZE_OF_ARRAY(szFinalStr));
//
//if the user does specifies /id option
// then retreive the OS Load Path from the
// registry
//
if(cmdOptions[3].dwActuals == 0 )
{
//retreive the Os Loader Path from the registry.
if(GetBootPath(IDENTIFIER_VALUE2,szResult) != ERROR_SUCCESS )
{
ShowMessage(stderr,GetResString(IDS_ERROR_UNEXPECTED));
return EXIT_FAILURE ;
}
//retreive the Os Loader Path from the registry.
if( GetBootPath(IDENTIFIER_VALUE3,szLoaderPath)!= ERROR_SUCCESS )
{
ShowMessage(stderr,GetResString(IDS_ERROR_UNEXPECTED));
return EXIT_FAILURE ;
}
bFlag = TRUE ;
//call the function which adds the mirror plex.
if (AddMirrorPlex(szFinalStr,szLoaderPath,szResult,bFlag,szFriendlyName) == EXIT_FAILURE )
{
return EXIT_FAILURE ;
}
}
else
{
// query the information from the NVRAM .
status = BootCfg_EnumerateBootEntries(&ntBootEntries);
if( !NT_SUCCESS(status) )
{
error = RtlNtStatusToDosError( status );
return EXIT_FAILURE ;
}
for (listEntry = BootEntries.Flink; listEntry != &BootEntries; listEntry = listEntry->Flink)
{
//Get the boot entry
mybootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
//check for the id specified by the user matches the
// id
if(mybootEntry->myId == dwBootID)
{
bBootIdFound = TRUE;
pBootEntry = &mybootEntry->NtBootEntry;
//Check whether the bootEntry is a Windows one or not.
//The OS load options can be added only to a Windows boot entry.
if(!IsBootEntryWindows(pBootEntry))
{
ShowMessageEx(stderr, 1, TRUE, GetResString(IDS_ERROR_OSOPTIONS),dwBootID);
dwExitCode = EXIT_FAILURE;
break;
}
}
}
// display an error
if (pBootEntry == NULL)
{
ShowMessage(stderr,GetResString(IDS_PARTITION_ERROR));
SAFEFREE(ntBootEntries);
return EXIT_FAILURE ;
}
//Get a pointer to the FILE_PATH structure.
pFilePath = (PFILE_PATH)ADD_OFFSET(pBootEntry, BootFilePathOffset);
//get the name of the .
NtFilePath = GetNtNameForFilePath(pFilePath );
if(NtFilePath == NULL)
{
ShowMessage(stderr,GetResString(IDS_ERROR_MIRROR));
SAFEFREE(ntBootEntries);
return EXIT_FAILURE ;
}
// split the path to get the SystemPartition path and the
// OsLoader Path .
szPartition = _tcstok(NtFilePath,_T("\\"));
//display error message and exit if szPartition is null.
if(szPartition == NULL)
{
ShowMessage(stderr,GetResString(IDS_TOKEN_ABSENT));
SAFEFREE(ntBootEntries);
return EXIT_FAILURE ;
}
//concatenate the "\" to frame the path .
StringConcat(szOsLoaderPath,_T("\\"), SIZE_OF_ARRAY(szOsLoaderPath));
StringConcat(szOsLoaderPath,szPartition, SIZE_OF_ARRAY(szOsLoaderPath) );
StringConcat(szOsLoaderPath,_T("\\"), SIZE_OF_ARRAY(szOsLoaderPath));
szPartition = _tcstok(NULL,_T("\\"));
//display error message and exit if szPartition is null.
if(NULL == szPartition )
{
ShowMessage(stderr,GetResString(IDS_TOKEN_ABSENT));
SAFEFREE(ntBootEntries);
return EXIT_FAILURE ;
}
StringConcat(szOsLoaderPath,szPartition, SIZE_OF_ARRAY(szOsLoaderPath));
//Framing the OsLoader Path
do
{
szPartition = _tcstok(NULL,_T("\\"));
if(szPartition == NULL)
{
break ;
bNobreak = FALSE;
}
StringConcat(szSystemPartition,_T("\\"), SIZE_OF_ARRAY(szSystemPartition));
StringConcat(szSystemPartition,szPartition, SIZE_OF_ARRAY(szSystemPartition));
}while(TRUE == bNobreak );
//This flag is for determining if the boot path should be BOOTFILE_PATH1
//or BOOTFILE_PATH
bFlag = FALSE ;
//call the function which adds the mirror plex.
if ( AddMirrorPlex(szFinalStr,szSystemPartition,szOsLoaderPath,bFlag,szFriendlyName) == EXIT_FAILURE )
{
return EXIT_FAILURE ;
}
}
}
SAFEFREE(ntBootEntries);
Freelist();
return EXIT_SUCCESS ;
}
NTSTATUS
FindBootEntry(IN PVOID pEntryListHead,
IN WCHAR *pwszTarget,
OUT PBOOT_ENTRY *ppTargetEntry
)
/*++
Routine description : Routine finds a boot entry in the list of all boot
entries and returns a pointer into the list for the found entry.
Arguments:
pEntryListHead - The address of a pointer to a BOOT_ENTRY_LIST struct.
pwszTarget - The OsLoadPath (install path) string.
"signature(<part GUID>-<part#>-<part_start>-<part_len>)"
OR
"signature(<part GUID>-<part#>-<part_start>-<part_len>)\\WINDOWS"
on input. If we find the entry in NVRAM, we copy the
full install path back to the input string so that it includes
the directory name.
ppTargetEntry - The address of a BOOT_ENTRY pointer, points to the
found entry at return.
Return Value : NT status
STATUS_INSUFFICIENT_RESOURCES
STATUS_ACCESS_VIOLATION
STATUS_UNSUPPORTED
STATUS_OBJECT_NAME_NOT_FOUND
STATUS_SUCCESS and *ppTargetEntry should be non-NULL for success.
--*/
{
LONG status = STATUS_SUCCESS;
PBOOT_ENTRY_LIST pEntryList = NULL;
PBOOT_ENTRY pEntry = NULL;
PWINDOWS_OS_OPTIONS pOsOptions = NULL;
PFILE_PATH pTransEntry = NULL;
DWORD dwTransSize = 0L;
DWORD i = 0L;
BOOL bFlag = FALSE ;
BOOL bNobreak = FALSE ;
DWORD dwCount = 0L ;
TCHAR szFinalStr[256] = NULL_STRING ;
DWORD dwFailCount = 0L;
DWORD dwSuccessCount = 0L;
if ( !pEntryListHead || !pwszTarget || !ppTargetEntry )
{
ShowMessage(stderr,GetResString(IDS_FIND_BOOT_ENTRY) );
return STATUS_INVALID_PARAMETER;
}
*ppTargetEntry = NULL;
pEntryList = (PBOOT_ENTRY_LIST) pEntryListHead;
//
// Iterate over all the entries returned looking for the target
// boot partition's entry. Convert the install path for each
// entry to the signature format, then compare to the
// input partition signature formatted path.
//
bNobreak = TRUE;
do
{
//
// Translate the entry's install path to signature format.
//
if ( pEntryList )
{
pEntry = &pEntryList->BootEntry;
}
else
{
ShowMessage(stderr,GetResString(IDS_FIND_BOOT_ENTRY_NULL));
status = STATUS_OBJECT_NAME_NOT_FOUND;
bNobreak = FALSE;
break;
}
//
// If this entry does not have the BOOT_ENTRY_ATTRIBUTE_WINDOWS
// attribute set, or, the attribute is set and this entry has
// an invalid OsOptions structure length, move to the next entry
// and continue searching and check the next boot entry
//
if ( !(pEntry->Attributes & BOOT_ENTRY_ATTRIBUTE_WINDOWS) || ( (pEntry->Attributes & BOOT_ENTRY_ATTRIBUTE_WINDOWS) && pEntry->OsOptionsLength < sizeof(WINDOWS_OS_OPTIONS) ) )
{
//exit from the loop if we have reached the last Boot Entry.
if ( !pEntryList->NextEntryOffset )
{
bNobreak = FALSE;
break;
}
//
// Continue with the next iteration
// after obtaining the pointer to the next entry.
//
pEntryList = (PBOOT_ENTRY_LIST)(((PBYTE)pEntryList) + pEntryList->NextEntryOffset);
continue;
}
//
// Use the entry's current length to start and resize
// if necessary.
//
dwTransSize = pEntry->Length;
for ( i = 1; i <= 2; i++ )
{
if ( pTransEntry )
{
MEMFREE(pTransEntry);
pTransEntry = NULL;
}
pTransEntry = (PFILE_PATH) MEMALLOC(dwTransSize);
if ( !pTransEntry )
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
status = STATUS_NO_MEMORY;
SAFEMEMFREE(pTransEntry);
return status ;
}
pOsOptions = (WINDOWS_OS_OPTIONS *)&pEntry->OsOptions;
status = NtTranslateFilePath
(
(PFILE_PATH)( ((PBYTE) pOsOptions) + pOsOptions->OsLoadPathOffset ),
FILE_PATH_TYPE_ARC_SIGNATURE,
pTransEntry,
&dwTransSize
);
if ( STATUS_INSUFFICIENT_RESOURCES == status )
{
continue;
}
else
{
break;
}
}
//
// Ignore STATUS_OBJECT_NAME_NOT_FOUND
// We shouldn't get that error anyway, since we are using
// the long signature format.
//
if ( !NT_SUCCESS(status)&& STATUS_OBJECT_NAME_NOT_FOUND != status )
{
DISPLAY_MESSAGE( stderr,GetResString(IDS_TRANSLATE_FAIL));
SAFEMEMFREE(pTransEntry);
return status ;
}
//
// Compare this entry's install path to the current boot
// partition's signature formatted install path.
// If the input install path may not include the install
// directory name.
//
//
// Check if the GUID specified by the User matches with the set of GUID's
// already present
//
if ( NT_SUCCESS(status) && !(wcsncmp( (WCHAR*)&pTransEntry->FilePath, pwszTarget, 48 ) ) )
{
// Set the flag to true indicating that the
// specified GUID matches
//
bFlag = TRUE ;
//
// Check if the ARC Path specified by the User matches with the ARC Path
// of the entry already present and if so display an error message and exit.
//
if( !(StringCompare( (WCHAR*)&pTransEntry->FilePath, pwszTarget, TRUE, StringLengthW(pwszTarget,0) ) ) )
{
ShowMessage(stderr,GetResString(IDS_ALREADY_UPDATED));
SAFEMEMFREE(pTransEntry) ;
return STATUS_OBJECT_NAME_NOT_FOUND;
}
else
{
*ppTargetEntry = pEntry;
//concatenate the string "\WINDOWS" to the path formed.
StringCopy ( szFinalStr, NULL_STRING, SIZE_OF_ARRAY(szFinalStr));
StringConcat(szFinalStr,pwszTarget,SIZE_OF_ARRAY(szFinalStr));
StringConcat(szFinalStr,_T("\\WINDOWS"), SIZE_OF_ARRAY(szFinalStr));
//
//modify the Boot Entry with the Arc Signature path specified.
//
status = ModifyBootEntry(szFinalStr,*ppTargetEntry);
if ( !NT_SUCCESS(status) )
{
//If unsuccessful to update the Boot_Entry then increment the Failure
//count.
dwFailCount++ ;
}
else
{
//If successfully updated the Boot_Entry then increment the Success
//count.
dwSuccessCount++;
}
if ( !pEntryList->NextEntryOffset )
{
bNobreak = FALSE;
break;
}
else
{
pEntryList = (PBOOT_ENTRY_LIST)( ((PBYTE)pEntryList) + pEntryList->NextEntryOffset );
continue ;
}
}
}
else
{
if ( !pEntryList->NextEntryOffset )
{
bNobreak = FALSE;
break;
}
pEntryList = (PBOOT_ENTRY_LIST)( ((PBYTE)pEntryList) + pEntryList->NextEntryOffset );
}
}while(TRUE == bNobreak );
// Depending upon the number of entries successfully updated
// display appropriate messages.
if((0 != dwFailCount)&&(0 == dwSuccessCount))
{
ShowMessage(stdout,GetResString(IDS_MODIFY_FAIL));
}
if(( 0 != dwSuccessCount )&&(0 == dwFailCount))
{
ShowMessage(stdout,GetResString(IDS_GUID_MODIFIED));
}
else if( ( 0 != dwSuccessCount )&&(0 != dwFailCount))
{
ShowMessage(stdout,GetResString(IDS_PARTIAL_UPDATE));
}
//display an error message if the GUID specified does not match with the GUID's present.
if(FALSE == bFlag )
{
//ShowMessage(stderr,GetResString(IDS_FIND_FAIL));
SAFEMEMFREE(pTransEntry) ;
return STATUS_INVALID_PARAMETER;
}
SAFEMEMFREE(pTransEntry)
return status;
}
LPVOID
MEMALLOC( ULONG size )
/*++
Routine Description : Allocates the memory Block.
Arguments :
[ in ] block : Size of the block to be allocated.
Return Type : LPVOID
--*/
{
HANDLE hProcessHeap;
hProcessHeap = GetProcessHeap();
if (hProcessHeap == NULL ||
size > 0x7FFF8) {
return NULL;
}
else {
return HeapAlloc (hProcessHeap, HEAP_ZERO_MEMORY, size);
}
}
VOID MEMFREE ( LPVOID block ) {
/*++
Routine Description : Frees the memory Allocated.
Arguments :
[ in ] block : Block to be freed.
Return Type : VOID
--*/
HANDLE hProcessHeap;
hProcessHeap = GetProcessHeap();
if (hProcessHeap != NULL) {
HeapFree(hProcessHeap, 0, block);
}
}
NTSTATUS
ModifyBootEntry( IN WCHAR *pwszInstallPath,
IN PBOOT_ENTRY pSourceEntry
)
/*++
Routine description : This routine is used to modify a boot entry in the NVRAM.
Arguments:
pwszInstallPath - The new install path
pSourceEntry - Entry that we will modify
Return Value : NT status
--*/
{
LONG status = STATUS_SUCCESS;
PFILE_PATH pLoaderFile = NULL;
ULONG dwLoaderFileSize = 0L;
PFILE_PATH pInstallPath = NULL; // new install path
ULONG dwInstallPathSize = 0L; // new install path size
PWINDOWS_OS_OPTIONS pWinOpt = NULL;
ULONG dwWinOptSize = 0L;
PBOOT_ENTRY pSetEntry = 0L; // new, modified entry
ULONG dwSetEntrySize = 0L;
DWORD dwFriendlyNameSize = 0L;
DWORD dwAlign = 0L;
PWINDOWS_OS_OPTIONS pSourceWinOpt = NULL; // old, source entry options to be modified
PFILE_PATH pSourceInstallPath = NULL; // old, source entry install path to be modified
//
// Validate params.
//
if ( !pwszInstallPath
|| !(StringLengthW(pwszInstallPath,0))
|| !pSourceEntry )
{
return STATUS_INVALID_PARAMETER;
}
//
// Setup the BootFilePath member of the BOOT_ENTRY.
//
dwLoaderFileSize = ( (PFILE_PATH) (((PBYTE)pSourceEntry) + pSourceEntry->BootFilePathOffset) )->Length;
pLoaderFile = (PFILE_PATH)MEMALLOC(dwLoaderFileSize);
if ( NULL == pLoaderFile )
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return STATUS_NO_MEMORY ;
}
RtlCopyMemory(pLoaderFile,((PBYTE)pSourceEntry) + pSourceEntry->BootFilePathOffset,
dwLoaderFileSize
);
//
// Setup the OsLoadPath member of the WINDOWS_OS_OPTIONS struct.
//
dwInstallPathSize = FIELD_OFFSET(FILE_PATH, FilePath) + ( (StringLengthW(pwszInstallPath,0)+1) * sizeof(WCHAR) );
pInstallPath = (PFILE_PATH)MEMALLOC(dwInstallPathSize);
if ( NULL == pInstallPath )
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
SAFEMEMFREE(pLoaderFile);
return STATUS_NO_MEMORY ;
}
pSourceWinOpt = (PWINDOWS_OS_OPTIONS) &pSourceEntry->OsOptions;
pSourceInstallPath = (PFILE_PATH)( ((PBYTE)pSourceWinOpt)+ pSourceWinOpt->OsLoadPathOffset );
pInstallPath->Version = pSourceInstallPath->Version;
pInstallPath->Length = dwInstallPathSize; // new install path size
pInstallPath->Type = FILE_PATH_TYPE_ARC_SIGNATURE;
RtlCopyMemory(pInstallPath->FilePath, // new path to the OS on the boot partition, "signature(partition_guid)\WINDOWS"
pwszInstallPath,
(StringLengthW(pwszInstallPath,0) + 1) * sizeof(WCHAR)
);
//
// Setup the OsOptions member of the BOOT_ENTRY
//
dwWinOptSize = FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions)
+ ( (StringLengthW(pSourceWinOpt->OsLoadOptions,0) + 1) * sizeof(WCHAR) ) // old OsLoadOptions
+ dwInstallPathSize // new OsLoadPath
+ sizeof(DWORD); // Need to align the FILE_PATH struct
pWinOpt = (PWINDOWS_OS_OPTIONS) MEMALLOC(dwWinOptSize);
if ( NULL == pWinOpt )
{
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
SAFEMEMFREE(pLoaderFile);
SAFEMEMFREE(pInstallPath);
return STATUS_NO_MEMORY ;
}
RtlCopyMemory( pWinOpt->Signature, pSourceWinOpt->Signature, sizeof(WINDOWS_OS_OPTIONS_SIGNATURE) );
pWinOpt->Version = pSourceWinOpt->Version;
pWinOpt->Length = dwWinOptSize;
pWinOpt->OsLoadPathOffset = FIELD_OFFSET(WINDOWS_OS_OPTIONS, OsLoadOptions)
+ ((StringLengthW(pSourceWinOpt->OsLoadOptions,0) + 1) * sizeof(WCHAR));
//
// Need to align the OsLoadPathOffset on a 4 byte boundary.
//
dwAlign = ( pWinOpt->OsLoadPathOffset & (sizeof(DWORD) - 1) );
if ( dwAlign != 0 )
{
pWinOpt->OsLoadPathOffset += sizeof(DWORD) - dwAlign;
}
StringCopy(pWinOpt->OsLoadOptions, pSourceWinOpt->OsLoadOptions, (StringLengthW(pSourceWinOpt->OsLoadOptions,0)));
RtlCopyMemory( ((PBYTE)pWinOpt) + pWinOpt->OsLoadPathOffset, pInstallPath, dwInstallPathSize );
//
// Setup the BOOT_ENTRY struct.
//
dwFriendlyNameSize = ( StringLengthW( (WCHAR *)(((PBYTE)pSourceEntry) + pSourceEntry->FriendlyNameOffset), 0 ) + 1)*sizeof(WCHAR);
dwSetEntrySize = FIELD_OFFSET(BOOT_ENTRY, OsOptions)
+ dwWinOptSize // OsOptions
+ dwFriendlyNameSize // FriendlyName including the NULL terminator
+ dwLoaderFileSize // BootFilePath
+ sizeof(WCHAR) // Need to align the FriendlyName on WCHAR
+ sizeof(DWORD); // Need to align the BootFilePath on DWORD
pSetEntry = (PBOOT_ENTRY) MEMALLOC(dwSetEntrySize);
if ( NULL == pSetEntry )
{
SAFEMEMFREE(pLoaderFile);
SAFEMEMFREE(pInstallPath);
SAFEMEMFREE(pWinOpt);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return STATUS_NO_MEMORY;
}
pSetEntry->Version = pSourceEntry->Version;
pSetEntry->Length = dwSetEntrySize;
pSetEntry->Id = pSourceEntry->Id; // not used, output param
pSetEntry->Attributes = pSourceEntry->Attributes;
pSetEntry->FriendlyNameOffset = FIELD_OFFSET(BOOT_ENTRY, OsOptions)
+ dwWinOptSize;
//
// Need to align the unicode string on a 2 byte boundary.
//
dwAlign = ( pSetEntry->FriendlyNameOffset & (sizeof(WCHAR) - 1) );
if ( dwAlign != 0 )
{
pSetEntry->FriendlyNameOffset += sizeof(WCHAR) - dwAlign;
}
pSetEntry->BootFilePathOffset = pSetEntry->FriendlyNameOffset + dwFriendlyNameSize;
//
// Need to align the FILE_PATH struct on a 4 byte boundary.
//
dwAlign = ( pSetEntry->BootFilePathOffset & (sizeof(DWORD) - 1) );
if ( dwAlign != 0 )
{
pSetEntry->BootFilePathOffset += sizeof(DWORD) - dwAlign;
}
pSetEntry->OsOptionsLength = dwWinOptSize;
RtlCopyMemory( pSetEntry->OsOptions, pWinOpt, dwWinOptSize );
RtlCopyMemory( ((PBYTE)pSetEntry) + pSetEntry->FriendlyNameOffset,
((PBYTE)pSourceEntry) + pSourceEntry->FriendlyNameOffset,
dwFriendlyNameSize
);
RtlCopyMemory( ((PBYTE)pSetEntry) + pSetEntry->BootFilePathOffset,
pLoaderFile,
dwLoaderFileSize
);
status = NtModifyBootEntry( pSetEntry );
if(!NT_SUCCESS(status))
{
ShowMessage(stderr,GetResString(IDS_MODIFY_FAIL));
}
SAFEMEMFREE(pLoaderFile);
SAFEMEMFREE(pInstallPath);
SAFEMEMFREE(pWinOpt);
SAFEMEMFREE(pSetEntry);
return status;
}
DWORD
ListDeviceInfo(DWORD dwDriveNum)
/*++
Routine description : This routine is used to retrieve the list of device partitions.
Arguments:
szGUID : The address of a pointer to a BOOT_ENTRY_LIST struct.
szFinalStr : The String containing the final ARG signature path.
Return Value : DWORD
EXIT_SUCCESS if it is successful,
EXIT_FAILURE otherwise.
--*/
{
HRESULT hr = S_OK;
HANDLE hDevice ;
BOOL bResult = FALSE ;
PPARTITION_INFORMATION_EX pInfo=NULL ;
PDRIVE_LAYOUT_INFORMATION_EX Drive=NULL;
DWORD dwBytesCount = 0 ;
TCHAR szDriveName[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwStructSize = 0 ;
TCHAR szInstallPath[MAX_RES_STRING+1] = NULL_STRING;
TCHAR szWindowsDirectory[MAX_PATH*2] = NULL_STRING;
PTCHAR pszTok = NULL ;
PPARTITION_INFORMATION_GPT pGptPartition=NULL;
DWORD dwPartitionId = 0 ;
CHAR szTempBuffer[ 33 ] = "\0";
WCHAR wszOffsetStr[ 33 ] = L"\0";
CHAR szTempBuffer1[ 33 ] = "\0";
WCHAR wszPartitionStr[ 33 ] = L"\0";
WCHAR szOutputStr[MAX_RES_STRING+1] = NULL_STRING ;
NTSTATUS ntstatus;
SecureZeroMemory(szDriveName, SIZE_OF_ARRAY(szDriveName));
hr = StringCchPrintf(szDriveName, SIZE_OF_ARRAY(szDriveName), _T("\\\\.\\physicaldrive%d"),dwDriveNum);
//get a handle after opening the File.
hDevice = CreateFile(szDriveName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if(hDevice == INVALID_HANDLE_VALUE)
{
ShowMessage(stderr,GetResString(IDS_INVALID_DISK));
return EXIT_FAILURE ;
}
Drive = (PDRIVE_LAYOUT_INFORMATION_EX)AllocateMemory(sizeof(DRIVE_LAYOUT_INFORMATION_EX) +5000) ;
if(NULL == Drive)
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
dwStructSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) ;
bResult = DeviceIoControl(
hDevice,
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
NULL,
0,
Drive,
sizeof(DRIVE_LAYOUT_INFORMATION_EX)+5000,
&dwBytesCount,
NULL);
if(bResult ==0)
{
SAFEFREE(Drive);
DISPLAY_MESSAGE( stderr, ERROR_TAG);
ShowLastError(stderr);
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_LIST0),dwDriveNum);
ShowMessage(stdout,GetResString(IDS_LIST1));
for(dwPartitionId = 0 ;dwPartitionId < Drive->PartitionCount ; dwPartitionId++)
{
//get a pointer to the corresponding partition.
pInfo = (PPARTITION_INFORMATION_EX)(&Drive->PartitionEntry[dwPartitionId] ) ;
ShowMessageEx(stdout,1, TRUE, GetResString(IDS_LIST2),dwPartitionId+1);
switch(Drive->PartitionStyle )
{
case PARTITION_STYLE_MBR :
ShowMessage(stdout,GetResString(IDS_LIST3));
break;
case PARTITION_STYLE_GPT :
ShowMessage(stdout,GetResString(IDS_LIST4));
break;
case PARTITION_STYLE_RAW :
ShowMessage(stdout,GetResString(IDS_LIST5));
break;
}
ntstatus = RtlLargeIntegerToChar( &pInfo->StartingOffset, 10, SIZE_OF_ARRAY( szTempBuffer ), szTempBuffer );
if ( ! NT_SUCCESS( ntstatus ) )
{
SAFEFREE(Drive);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
ntstatus = RtlLargeIntegerToChar( &pInfo->PartitionLength, 10, SIZE_OF_ARRAY( szTempBuffer1 ), szTempBuffer1 );
if ( ! NT_SUCCESS( ntstatus ) )
{
SAFEFREE(Drive);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
MultiByteToWideChar( _DEFAULT_CODEPAGE, 0, szTempBuffer, -1, wszOffsetStr, SIZE_OF_ARRAY(wszOffsetStr) );
if( ConvertintoLocale( wszOffsetStr,szOutputStr )== EXIT_FAILURE )
{
SAFEFREE(Drive);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
ShowMessage(stdout,GetResString(IDS_LIST6));
ShowMessage(stdout,_X3(szOutputStr));
ShowMessage(stdout,L"\n");
MultiByteToWideChar( _DEFAULT_CODEPAGE, 0, szTempBuffer1, -1, wszPartitionStr, SIZE_OF_ARRAY(wszOffsetStr) );
if( ConvertintoLocale( wszPartitionStr,szOutputStr )== EXIT_FAILURE )
{
SAFEFREE(Drive);
DISPLAY_MESSAGE( stderr, ERROR_TAG);
ShowLastError(stderr);
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
ShowMessage(stdout,GetResString(IDS_LIST7));
ShowMessage(stdout,_X3(szOutputStr));
ShowMessage(stdout,L"\n");
//get a pointer to the PARTITION_INFORMATION_GPT structure.
pGptPartition = AllocateMemory( sizeof( PARTITION_INFORMATION_GPT));
if(NULL == pGptPartition )
{
SAFEFREE(Drive);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
CopyMemory(pGptPartition,&pInfo->Gpt,sizeof(PARTITION_INFORMATION_GPT) );
ShowMessage(stdout, GetResString(IDS_LIST8));
ShowMessageEx(stdout, 11, TRUE, _T("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
pGptPartition->PartitionId.Data1,
pGptPartition->PartitionId.Data2,
pGptPartition->PartitionId.Data3,
pGptPartition->PartitionId.Data4[0],
pGptPartition->PartitionId.Data4[1],
pGptPartition->PartitionId.Data4[2],
pGptPartition->PartitionId.Data4[3],
pGptPartition->PartitionId.Data4[4],
pGptPartition->PartitionId.Data4[5],
pGptPartition->PartitionId.Data4[6],
pGptPartition->PartitionId.Data4[7] );
ShowMessage(stdout, GetResString(IDS_LIST9));
ShowMessageEx(stdout, 11, TRUE,
_T("{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}"),
pGptPartition->PartitionType.Data1,
pGptPartition->PartitionType.Data2,
pGptPartition->PartitionType.Data3,
pGptPartition->PartitionType.Data4[0],
pGptPartition->PartitionType.Data4[1],
pGptPartition->PartitionType.Data4[2],
pGptPartition->PartitionType.Data4[3],
pGptPartition->PartitionType.Data4[4],
pGptPartition->PartitionType.Data4[5],
pGptPartition->PartitionType.Data4[6],
pGptPartition->PartitionType.Data4[7] );
//partition name.
if(StringLengthW(pGptPartition->Name,0) != 0)
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_LIST10),pGptPartition->Name);
}
else
{
ShowMessageEx(stdout, 1, TRUE, GetResString(IDS_LIST10),_T("N/A"));
}
}
if( 0 == GetWindowsDirectory(szWindowsDirectory,MAX_PATH) )
{
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
ShowMessage(stderr,GetResString(IDS_ERROR_DRIVE));
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
StringConcat(szWindowsDirectory,_T("*"), SIZE_OF_ARRAY(szWindowsDirectory));
pszTok = _tcstok(szWindowsDirectory,_T("\\"));
if(pszTok == NULL)
{
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
DISPLAY_MESSAGE(stderr,GetResString(IDS_TOKEN_ABSENT));
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
pszTok = _tcstok(NULL,_T("*"));
if(pszTok == NULL)
{
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
DISPLAY_MESSAGE(stderr,GetResString(IDS_TOKEN_ABSENT));
CloseHandle(hDevice);
return EXIT_FAILURE ;
}
SecureZeroMemory(szInstallPath, SIZE_OF_ARRAY(szInstallPath));
hr = StringCchPrintf( szInstallPath, SIZE_OF_ARRAY(szInstallPath),
_T("signature({%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}-%08x-%016I64x-%016I64x)"),
pGptPartition->PartitionId.Data1,
pGptPartition->PartitionId.Data2,
pGptPartition->PartitionId.Data3,
pGptPartition->PartitionId.Data4[0],
pGptPartition->PartitionId.Data4[1],
pGptPartition->PartitionId.Data4[2],
pGptPartition->PartitionId.Data4[3],
pGptPartition->PartitionId.Data4[4],
pGptPartition->PartitionId.Data4[5],
pGptPartition->PartitionId.Data4[6],
pGptPartition->PartitionId.Data4[7],
pInfo->PartitionNumber,
pInfo->StartingOffset,
pInfo->PartitionLength
);
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
CloseHandle(hDevice);
return EXIT_SUCCESS ;
}
NTSTATUS
AcquirePrivilege( IN CONST ULONG ulPrivilege,
IN CONST BOOLEAN bEnable
)
/*++
Routine description : This routine is used to set or reset a privilege
on a process token.
Arguments:
ulPrivilege - The privilege t enable or disable.
bEnable - TRUE to enable the priviliege, FALSE to disable.
Return Value : NTSTATUS
--*/
{
NTSTATUS status;
BOOLEAN bPrevState;
if ( bEnable ) {
status = RtlAdjustPrivilege( ulPrivilege,
TRUE, // enable
FALSE, // adjust the process token
&bPrevState
);
}
else {
status = RtlAdjustPrivilege( ulPrivilege,
FALSE, // disable
FALSE, // adjust the process token
&bPrevState
);
}
return status;
}
NTSTATUS
EnumerateBootEntries( IN PVOID *ppEntryListHead)
/*++
Routine description : This routine is used to retrieve the list of boot entries.
Arguments:
ppEntryListHead - The address of a pointer to a BOOT_ENTRY_LIST struct.
Return Value : NTSTATUS
--*/
{
LONG status = STATUS_SUCCESS;
DWORD dwEntryListSize = 0x0001000; // 4k
BOOL bNobreak = TRUE;
if ( !ppEntryListHead )
{
ShowMessage(stderr,GetResString(IDS_ERROR_ENUMERATE));
return STATUS_INVALID_PARAMETER;
}
do
{
*ppEntryListHead = (PBOOT_ENTRY_LIST) MEMALLOC(dwEntryListSize);
if ( !*ppEntryListHead )
{
ShowMessage(stderr,GetResString(IDS_ERROR_ENUMERATE));
status = STATUS_NO_MEMORY;
bNobreak = FALSE;
break;
}
status = NtEnumerateBootEntries(
(PVOID) *ppEntryListHead,
&dwEntryListSize
);
if ( !NT_SUCCESS(status) )
{
if ( *ppEntryListHead ) {
MEMFREE(*ppEntryListHead);
*ppEntryListHead = NULL;
}
if ( STATUS_INSUFFICIENT_RESOURCES == status ) {
dwEntryListSize += 0x0001000;
continue;
}
else
{
ShowMessage(stderr,GetResString(IDS_ERROR_ENUMERATE));
bNobreak = FALSE;
break;
}
}
else {
break;
}
}while (TRUE==bNobreak);
return status;
}
DWORD
GetDeviceInfo( IN LPTSTR szGUID,
OUT LPTSTR szFinalStr,
IN DWORD dwDriveNum,
IN DWORD dwActuals)
/*++
Routine description : This routine is used to retrieve the list of boot entries.
Arguments:
[ in ] szGUID : The address of a pointer to a BOOT_ENTRY_LIST struct.
[ out ] szFinalStr : The String containing the final ARG signature path.
[ in ] dwDriveNum : Specifies the drive number
[ in ] dwActuals : Specifies
Return Value : DWORD
Returns EXIT_SUCCESS if it is successful,
returnS EXIT_FAILURE otherwise.
--*/
{
HRESULT hr = S_OK;
HANDLE hDevice ;
BOOL bResult = FALSE ;
PPARTITION_INFORMATION_EX pInfo ;
PDRIVE_LAYOUT_INFORMATION_EX Drive ;
DWORD dwBytesCount = 0 ;
TCHAR szDriveName[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwErrCode = 0 ;
DWORD dwStructSize = 0 ;
TCHAR szInstallPath[MAX_RES_STRING+1] = NULL_STRING;
TCHAR szInstallPath1[MAX_RES_STRING*2] = NULL_STRING;
TCHAR szWindowsDirectory[MAX_PATH*2] = NULL_STRING;
TCHAR szMessage[MAX_RES_STRING+1] = NULL_STRING;
PTCHAR pszTok = NULL ;
PPARTITION_INFORMATION_GPT pGptPartition ;
UUID MyGuid ;
DWORD dwPartitionId = 0 ;
BOOL bGuidFlag = FALSE ;
BOOL bFoundFlag = TRUE ;
DWORD dwReqdSize = 0 ;
if ( UuidFromString(szGUID,&MyGuid) != RPC_S_OK )
{
ShowMessage(stderr,GetResString(IDS_INVALID_GUID));
return EXIT_FAILURE ;
}
while(bFoundFlag == TRUE)
{
SecureZeroMemory(szDriveName, SIZE_OF_ARRAY(szDriveName));
hr = StringCchPrintf(szDriveName, SIZE_OF_ARRAY(szDriveName), _T("\\\\.\\physicaldrive%d"), dwDriveNum );
hDevice = CreateFile(szDriveName,
GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
0,
NULL);
if(hDevice == INVALID_HANDLE_VALUE)
{
dwErrCode = GetLastError();
bFoundFlag =FALSE ;
// Display ann error message and exit if the user has mentioned
// any disk number.
if ( dwActuals == 1)
{
ShowMessage(stderr,GetResString(IDS_INVALID_DISK) );
return EXIT_FAILURE ;
}
else
{
break ;
}
}
//increase the drive number.
dwDriveNum++ ;
//Drive = (PDRIVE_LAYOUT_INFORMATION_EX)malloc(sizeof(DRIVE_LAYOUT_INFORMATION_EX) +5000) ;
dwReqdSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX)+ sizeof(PARTITION_INFORMATION)*50 ;
Drive = (PDRIVE_LAYOUT_INFORMATION_EX)AllocateMemory(sizeof(DRIVE_LAYOUT_INFORMATION_EX) + sizeof(PARTITION_INFORMATION)*50) ;
if(Drive == NULL)
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
CloseHandle(hDevice );
return EXIT_FAILURE ;
}
dwStructSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) ;
bResult = DeviceIoControl(
hDevice,
IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
NULL,
0,
Drive,
dwReqdSize,
&dwBytesCount,
NULL);
//Drive = realloc(Drive,malloc(sizeof(DRIVE_LAYOUT_INFORMATION_EX) )+500 ) ;
if(bResult ==0)
{
SAFEFREE(Drive);
dwErrCode = GetLastError();
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
CloseHandle(hDevice );
return EXIT_FAILURE ;
}
//get a pointer to the PARTITION_INFORMATION_EX structure
for(dwPartitionId = 0 ;dwPartitionId < Drive->PartitionCount ; dwPartitionId++)
{
//get a pointer to the corresponding partition.
pInfo = (PPARTITION_INFORMATION_EX)(&Drive->PartitionEntry[dwPartitionId] ) ;
//get a pointer to the PARTITION_INFORMATION_GPT structure.
pGptPartition = AllocateMemory( sizeof( PARTITION_INFORMATION_GPT));
if(pGptPartition == NULL)
{
SAFEFREE(Drive);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_SYSTEM );
CloseHandle(hDevice );
return EXIT_FAILURE ;
}
CopyMemory(pGptPartition,&pInfo->Gpt,sizeof(PARTITION_INFORMATION_GPT) );
if( ( MyGuid.Data1 == pGptPartition->PartitionId.Data1 ) &&
( MyGuid.Data2 == pGptPartition->PartitionId.Data2 )
&& (MyGuid.Data3 == pGptPartition->PartitionId.Data3)
&& (MyGuid.Data4[0] == pGptPartition->PartitionId.Data4[0])
&& (MyGuid.Data4[1] == pGptPartition->PartitionId.Data4[1])
&& (MyGuid.Data4[2] == pGptPartition->PartitionId.Data4[2])
&&(MyGuid.Data4[3] == pGptPartition->PartitionId.Data4[3])
&& (MyGuid.Data4[4]== pGptPartition->PartitionId.Data4[4] )
&& (MyGuid.Data4[5]== pGptPartition->PartitionId.Data4[5] )
&& (MyGuid.Data4[6]== pGptPartition->PartitionId.Data4[6] )
&& (MyGuid.Data4[7]== pGptPartition->PartitionId.Data4[7] ) )
{
SecureZeroMemory(szMessage, SIZE_OF_ARRAY(szMessage));
hr = StringCchPrintf(szMessage, SIZE_OF_ARRAY(szMessage),GetResString(IDS_GUID_FOUND),dwPartitionId+1);
bGuidFlag = TRUE ;
bFoundFlag =FALSE ;
goto out ;
}
}
CloseHandle(hDevice );
}
if(bGuidFlag == FALSE )
{
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
ShowMessage(stdout,GetResString(IDS_GUID_ABSENT));
CloseHandle(hDevice );
return EXIT_FAILURE ;
}
out: if( 0 == GetWindowsDirectory(szWindowsDirectory,MAX_PATH) )
{
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
ShowMessage(stderr,GetResString(IDS_ERROR_DRIVE));
CloseHandle(hDevice );
return EXIT_FAILURE ;
}
StringConcat(szWindowsDirectory,_T("*"), SIZE_OF_ARRAY(szWindowsDirectory));
pszTok = _tcstok(szWindowsDirectory,_T("\\"));
if(pszTok == NULL)
{ SAFEFREE(Drive);
SAFEFREE(pGptPartition);
ShowMessage(stderr,GetResString(IDS_TOKEN_ABSENT));
CloseHandle(hDevice );
return EXIT_FAILURE ;
}
pszTok = _tcstok(NULL,_T("*"));
if(pszTok == NULL)
{
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
ShowMessage(stderr,GetResString(IDS_TOKEN_ABSENT));
CloseHandle(hDevice );
return EXIT_FAILURE ;
}
//prints the path into the string.
hr = StringCchPrintf( szInstallPath, SIZE_OF_ARRAY(szInstallPath),
ARC_SIGNATURE,
pGptPartition->PartitionId.Data1,
pGptPartition->PartitionId.Data2,
pGptPartition->PartitionId.Data3,
pGptPartition->PartitionId.Data4[0],
pGptPartition->PartitionId.Data4[1],
pGptPartition->PartitionId.Data4[2],
pGptPartition->PartitionId.Data4[3],
pGptPartition->PartitionId.Data4[4],
pGptPartition->PartitionId.Data4[5],
pGptPartition->PartitionId.Data4[6],
pGptPartition->PartitionId.Data4[7],
dwPartitionId + 1 ,
pInfo->StartingOffset,
pInfo->PartitionLength
);
SecureZeroMemory(szInstallPath1, SIZE_OF_ARRAY(szInstallPath1) );
hr = StringCchPrintf( szInstallPath1, SIZE_OF_ARRAY(szInstallPath1), _T("%s\\%s"), szInstallPath, pszTok);
StringCopy(szFinalStr,szInstallPath, MAX_RES_STRING+1 );
SAFEFREE(Drive);
SAFEFREE(pGptPartition);
CloseHandle(hDevice );
return EXIT_SUCCESS ;
}
DWORD
ProcessListSwitch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine description : This routine is used to retrieve and display the list of boot entries.
Arguments:
argc : command line arguments count.
argv :
Return Value : DWORD
Returns EXIT_SUCCESS if it is successful,
returns EXIT_FAILURE otherwise.
--*/
{
BOOL bUsage = FALSE ;
BOOL bList = FALSE;
DWORD dwExitCode = ERROR_SUCCESS;
DWORD dwList = 0 ;
TCHAR szList[MAX_STRING_LENGTH] = NULL_STRING ;
LPTSTR pszStopStr = NULL;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[3];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_LIST;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->pValue = &bList;
//main option
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_DEFAULT;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwFlags = CP2_DEFAULT;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szList;
pcmdOption->dwLength = MAX_STRING_LENGTH;
//id usage
pcmdOption = &cmdOptions[2];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
// Parsing the copy option switches
if ( !(DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_LIST_SYNTAX));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayListUsage_IA64() ;
return (EXIT_SUCCESS);
}
TrimString(szList,TRIM_ALL);
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
//if empty value is specified
if( cmdOptions[1].dwActuals != 0 && StringLength(szList,0) == 0 )
{
ShowMessage(stderr,GetResString(IDS_LIST_SYNTAX));
return ( EXIT_FAILURE );
}
dwList = _tcstoul(szList,&pszStopStr, 10);
if ( StringLengthW(pszStopStr,0) != 0 )
{
ShowMessage(stderr,GetResString(IDS_INVALID_LISTVALUE));
return EXIT_FAILURE;
}
if(dwList > 0)
{
dwExitCode= ListDeviceInfo(dwList );
return (dwExitCode);
}
else
{
dwList = 0 ;
dwExitCode = ListDeviceInfo(dwList);
return (dwExitCode);
}
return EXIT_SUCCESS ;
}
VOID
displayListUsage_IA64()
/*++
Routine Description : Display the help for the list option (IA64).
Arguments :
: NONE
Return Type : VOID
--*/
{
DWORD dwIndex = IDS_LIST_BEGIN_IA64 ;
for(;dwIndex <=IDS_LIST_END_IA64 ;dwIndex++)
{
ShowMessage(stdout,GetResString(dwIndex));
}
}
VOID
displayUpdateUsage_IA64()
/*++
Routine Description : Display the help for the update option (IA64).
Arguments :
: NONE
Return Type : VOID
--*/
{
DWORD dwIndex = IDS_UPDATE_BEGIN_IA64 ;
for(;dwIndex <=IDS_UPDATE_END_IA64 ;dwIndex++)
{
ShowMessage(stdout,GetResString(dwIndex));
}
}
DWORD
ProcessUpdateSwitch_IA64( IN DWORD argc,
IN LPCTSTR argv[]
)
/*++
Routine Description : Allows the user to update the OS load options specifed
based on the plex
Arguments :
[ in ] argc - Number of command line arguments
[ in ] argv - Array containing command line arguments
Return Type : DWORD
--*/
{
BOOL bUsage = FALSE ;
TCHAR szUpdate[MAX_RES_STRING+1] = NULL_STRING ;
DWORD dwList = 0 ;
NTSTATUS status ;
TCHAR szFinalStr[MAX_RES_STRING+1] = NULL_STRING ;
TCHAR szBrackets[] = _T("{}");
PBOOT_ENTRY_LIST pEntryListHead = NULL;
PBOOT_ENTRY pTargetEntry = NULL;
DWORD dwActuals = 0 ;
DWORD dwExitcode = 0 ;
TCMDPARSER2 cmdOptions[2];
PTCMDPARSER2 pcmdOption;
SecureZeroMemory(cmdOptions, SIZE_OF_ARRAY(cmdOptions)*sizeof(TCMDPARSER2) );
//main option
pcmdOption = &cmdOptions[0];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_UPDATE;
pcmdOption->dwType = CP_TYPE_TEXT;
pcmdOption->dwFlags= CP2_VALUE_OPTIONAL;
pcmdOption->dwCount = 1;
pcmdOption->pValue = szUpdate;
pcmdOption->dwLength = MAX_STRING_LENGTH;
//id usage
pcmdOption = &cmdOptions[1];
StringCopyA( pcmdOption->szSignature, "PARSER2", 8 );
pcmdOption->pwszOptions = CMDOPTION_USAGE;
pcmdOption->dwFlags = CP2_USAGE;
pcmdOption->dwType = CP_TYPE_BOOLEAN;
pcmdOption->dwCount = 1;
pcmdOption->pValue = &bUsage;
// Parsing the copy option switches
if ( !(DoParseParam2( argc, argv, 0, SIZE_OF_ARRAY(cmdOptions ), cmdOptions, 0 ) ) )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return (EXIT_FAILURE);
}
//check if usage is specified with more than one option
if( (TRUE == bUsage) && (argc > 3) )
{
ShowMessage(stderr,GetResString(IDS_UPDATE_SYNTAX));
return ( EXIT_FAILURE );
}
// Displaying query usage if user specified -? with -query option
if( bUsage )
{
displayUpdateUsage_IA64() ;
return (EXIT_SUCCESS);
}
dwExitcode = InitializeEFI();
if(EXIT_FAILURE == dwExitcode )
{
return EXIT_FAILURE ;
}
if(!bUsage && (StringLengthW(szUpdate,0) ==0) )
{
ShowMessage(stderr,GetResString(IDS_UPDATE_SYNTAX));
return EXIT_FAILURE ;
}
if(StringLengthW(szUpdate,0) !=0)
{
//
// Pass the GUID specified by the User
// and convert that into the ARC signature Path.
//
//Trim the Leading and trailing brackets specified
// by the user.
StrTrim(szUpdate, szBrackets);
//dwActuals = cmdOptions[2].dwActuals ;
dwActuals = 0 ;
if (GetDeviceInfo(szUpdate,szFinalStr,dwList,dwActuals) == EXIT_FAILURE )
{
return EXIT_FAILURE ;
}
//acquire the necessary privilages for querying and manipulating the NV RAM.
status = AcquirePrivilege( SE_SYSTEM_ENVIRONMENT_PRIVILEGE, TRUE );
if ( !NT_SUCCESS(status) )
{
ShowMessage(stderr,GetResString(IDS_INSUFF_PRIV));
return HRESULT_FROM_NT(status);
}
//Enumerate the list of Boot Entries in the NV Ram.
status = EnumerateBootEntries( (PVOID *) &pEntryListHead );
if ( !NT_SUCCESS(status) || !pEntryListHead )
{
if ( !pEntryListHead )
{
return EXIT_FAILURE ;
}
}
//
// Find The BootEntry corresponding to the ARC Signature path specified by the user.
//
//
status = FindBootEntry( pEntryListHead,szFinalStr,&pTargetEntry);
if ( !NT_SUCCESS(status) && STATUS_OBJECT_NAME_NOT_FOUND != status)
{
DISPLAY_MESSAGE(stderr,GetResString(IDS_FIND_FAIL) );
return EXIT_FAILURE ;
}
}
return EXIT_SUCCESS ;
}
DWORD
GetBootPath(IN LPTSTR szValue,
IN LPTSTR szResult
)
/*++
Routine Description : retreive the information from registry
Arguments :
[ in ] Keyname : System name
Return Type : DWORD
ERROR_SUCCESS : if successful in retreiving information.
ERROR_RETREIVE_REGISTRY : if error occurs while retreving information.
--*/
{
HKEY hKey1 = 0;
HKEY hRemoteKey = 0;
TCHAR szPath[MAX_STRING_LENGTH + 1] = SUBKEY1 ;
DWORD dwValueSize = MAX_STRING_LENGTH + 1;
DWORD dwRetCode = ERROR_SUCCESS;
DWORD dwError = 0;
TCHAR szTmpCompName[MAX_STRING_LENGTH+1] = NULL_STRING;
DWORD dwLength = MAX_STRING_LENGTH ;
LPTSTR szReturnValue = NULL ;
DWORD dwCode = 0 ;
szReturnValue = ( LPTSTR ) AllocateMemory( dwLength*sizeof( TCHAR ) );
if(szReturnValue == NULL)
{
return ERROR_RETREIVE_REGISTRY ;
}
// Get Remote computer local machine key
dwError = RegConnectRegistry(szTmpCompName,HKEY_LOCAL_MACHINE,&hRemoteKey);
if (dwError == ERROR_SUCCESS)
{
dwError = RegOpenKeyEx(hRemoteKey,szPath,0,KEY_READ,&hKey1);
if (dwError == ERROR_SUCCESS)
{
dwRetCode = RegQueryValueEx(hKey1, szValue, NULL, NULL,(LPBYTE) szReturnValue, &dwValueSize);
if (dwRetCode == ERROR_MORE_DATA)
{
if ( szReturnValue != NULL )
{
FreeMemory((LPVOID *) &szReturnValue );
szReturnValue = NULL;
}
szReturnValue = ( LPTSTR ) AllocateMemory( dwValueSize*sizeof( TCHAR ) );
if(szReturnValue == NULL)
{
RegCloseKey(hKey1);
RegCloseKey(hRemoteKey);
SAFEFREE(szReturnValue);
return ERROR_RETREIVE_REGISTRY ;
}
dwRetCode = RegQueryValueEx(hKey1, szValue, NULL, NULL,(LPBYTE) szReturnValue, &dwValueSize);
}
if(dwRetCode != ERROR_SUCCESS)
{
RegCloseKey(hKey1);
RegCloseKey(hRemoteKey);
SAFEFREE(szReturnValue);
return ERROR_RETREIVE_REGISTRY ;
}
}
else
{
RegCloseKey(hRemoteKey);
SAFEFREE(szReturnValue);
return ERROR_RETREIVE_REGISTRY ;
}
RegCloseKey(hKey1);
}
else
{
RegCloseKey(hRemoteKey);
SAFEFREE(szReturnValue);
return ERROR_RETREIVE_REGISTRY ;
}
RegCloseKey(hRemoteKey);
StringCopy(szResult,szReturnValue, MAX_RES_STRING+1);
SAFEFREE(szReturnValue);
return dwCode ;
}
NTSTATUS
LowGetPartitionInfo(
IN HANDLE handle,
OUT PARTITION_INFORMATION_EX *partitionData
)
/*++
Routine Description:
This routine gets the partition information given a handle to a partition.
Arguments:
handle - A handle to the partition.
partitionData - Returns a partition information structure.
Return Value:
Returns STATUS_SUCESS if successful, otherwise it returns the error code.
--*/
{
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK statusBlock;
RtlZeroMemory( &statusBlock, sizeof(IO_STATUS_BLOCK) );
if ( (NULL == partitionData)
|| (sizeof(*partitionData) < sizeof(PARTITION_INFORMATION_EX))
|| (NULL == handle)
|| (INVALID_HANDLE_VALUE == handle) )
{
return STATUS_INVALID_PARAMETER;
}
RtlZeroMemory( partitionData, sizeof(PARTITION_INFORMATION_EX) );
status = NtDeviceIoControlFile(handle,
0,
NULL,
NULL,
&statusBlock,
IOCTL_DISK_GET_PARTITION_INFO_EX,
NULL,
0,
partitionData,
sizeof(PARTITION_INFORMATION_EX)
);
return status;
}
LONG
DmCommonNtOpenFile(
IN PWSTR Name,
IN ULONG access,
IN PHANDLE Handle
)
/*++
Routine Description:
This is a routine to handle open requests.
Arguments:
Name - pointer to the NT name for the open.
Handle - pointer for the handle returned.
Return Value:
NT status
--*/
{
OBJECT_ATTRIBUTES oa;
NTSTATUS status;
IO_STATUS_BLOCK statusBlock;
UNICODE_STRING unicodeName;
int i = 0 ;
status = RtlCreateUnicodeString(&unicodeName, Name);
if (!NT_SUCCESS(status))
{
return status;
}
RtlZeroMemory(&statusBlock, sizeof(IO_STATUS_BLOCK));
RtlZeroMemory(&oa, sizeof(OBJECT_ATTRIBUTES));
oa.Length = sizeof(OBJECT_ATTRIBUTES);
oa.ObjectName = &unicodeName;
oa.Attributes = OBJ_CASE_INSENSITIVE;
// If a sharing violation occurs,retry it for
// max. 10 seconds
for (i = 0; i < 5; i++)
{
status = NtOpenFile(Handle,
SYNCHRONIZE | access,
&oa,
&statusBlock,
FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SYNCHRONOUS_IO_ALERT
);
if (status == STATUS_SHARING_VIOLATION) {
Sleep(2000);
}
else {
break;
}
}
RtlFreeUnicodeString(&unicodeName);
return status;
}
DWORD
AddMirrorPlex( IN LPTSTR szOsLoadPath ,
IN LPTSTR szLoaderPath ,
IN LPTSTR szValue ,
IN BOOL bFlag,
IN LPTSTR szFriendlyName
)
/*++
Routine Description:
This is a routine to Add a new mirror Entry
Arguments:
Return Value:
DWORD.
--*/
{
// local variables
HRESULT hr = S_OK;
BOOLEAN wasEnabled = TRUE;
DWORD dwAlign = 0;
DWORD dwError = 0;
DWORD dwLength = 0;
DWORD dwBootEntrySize = 0;
DWORD dwBootFilePathSize = 0;
DWORD dwOsLoadPathSize = 0;
DWORD dwWindowsOptionsSize = 0;
PBOOT_ENTRY pBootEntry = NULL;
PWINDOWS_OS_OPTIONS pWindowsOptions = NULL;
PFILE_PATH pBootFilePath = NULL;
PFILE_PATH pOsLoadPath = NULL;
ULONG* pdwIdsArray = NULL;
ULONG ulId = 0;
ULONG ulIdCount = 0;
NTSTATUS status;
TCHAR pwszBootFilePath[MAX_RES_STRING+1] = NULL_STRING;
PFILE_PATH pFilePath = NULL;
HANDLE hPart = INVALID_HANDLE_VALUE;
GUID guid;
PARTITION_INFORMATION_EX PartitionInfo;
TCHAR szBootPath[MAX_RES_STRING+1] = NULL_STRING;
// enable the privilege that is necessary to query/set NVRAM.
status = RtlAdjustPrivilege( SE_SYSTEM_ENVIRONMENT_PRIVILEGE, TRUE, FALSE, &wasEnabled );
if ( !NT_SUCCESS( status ) )
{
dwError = RtlNtStatusToDosError( status );
DISPLAY_MESSAGE( stderr, GetResString(IDS_INSUFF_PRIV));
return EXIT_FAILURE;
}
//
// open the system device
//
status = DmCommonNtOpenFile( szValue, GENERIC_READ, &hPart );
if ( status || !hPart || INVALID_HANDLE_VALUE == hPart )
{
dwError = RtlNtStatusToDosError( status );
DISPLAY_MESSAGE(stderr,GetResString(IDS_ERROR_ADD));
return EXIT_FAILURE;
}
//
// The structure is zero'ed in this call before retrieving the data.
//
status = LowGetPartitionInfo( hPart, &PartitionInfo );
if ( status )
{
dwError = RtlNtStatusToDosError( status );
DISPLAY_MESSAGE(stderr,GetResString(IDS_PARTITION_ERROR));
return EXIT_FAILURE;
}
if ( PARTITION_STYLE_GPT != PartitionInfo.PartitionStyle )
{
dwError = RtlNtStatusToDosError( status );
DISPLAY_MESSAGE(stderr,GetResString(IDS_ERROR_PARTITION_STYLE));
return EXIT_FAILURE;
}
//
// Setup the OSLoader file path.
//
guid = PartitionInfo.Gpt.PartitionId;
if (bFlag)
{
StringCopy(szBootPath,BOOTFILE_PATH, SIZE_OF_ARRAY(szBootPath));
}
else
{
StringCopy(szBootPath,BOOTFILE_PATH1, SIZE_OF_ARRAY(szBootPath) );
}
SecureZeroMemory(pwszBootFilePath, sizeof(pwszBootFilePath) );
hr = StringCchPrintf( pwszBootFilePath, SIZE_OF_ARRAY(pwszBootFilePath)-1,
szBootPath,
guid.Data1,
guid.Data2,
guid.Data3,
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7],
szLoaderPath);
//
// prepare the boot file path
//
//
// determine the length of the BOOTFILE_PATH
dwLength = StringLengthW( pwszBootFilePath,0) + 1;
// now determine the memory size that needs to be allocated for FILE_PATH structure
// and align up to the even memory bounday
dwBootFilePathSize = FIELD_OFFSET( FILE_PATH, FilePath ) + (dwLength * sizeof( WCHAR ));
// allocate the memory
pBootFilePath = (PFILE_PATH) AllocateMemory( sizeof( BYTE )*dwBootFilePathSize );
if ( NULL == pBootFilePath )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL);
return EXIT_FAILURE;
}
// set the values now
SecureZeroMemory( pBootFilePath, dwBootFilePathSize ); // double init
pBootFilePath->Length = dwBootFilePathSize;
pBootFilePath->Type = FILE_PATH_TYPE_ARC_SIGNATURE;
pBootFilePath->Version = FILE_PATH_VERSION;
CopyMemory( pBootFilePath->FilePath, pwszBootFilePath, dwLength * sizeof( WCHAR ) );
//
// testing translating
//
pFilePath = (PFILE_PATH) AllocateMemory( sizeof( BYTE )* 1024 );
if(NULL == pFilePath )
{
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return EXIT_FAILURE;
}
ulId = 1024;
status = NtTranslateFilePath( pBootFilePath, FILE_PATH_TYPE_NT, pFilePath, &ulId );
if ( ! NT_SUCCESS( status ) )
{
dwError = RtlNtStatusToDosError( status );
DISPLAY_MESSAGE(stderr,GetResString(IDS_ERROR_ADD));
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath );
return EXIT_FAILURE;
}
//
// determine the length of the OSLOAD PATH
//
dwLength = StringLengthW( szOsLoadPath,0 ) + 1;
// now determine the memory size that needs to be allocated for FILE_PATH structure
// and align up to the even memory bounday
dwOsLoadPathSize = FIELD_OFFSET( FILE_PATH, FilePath ) + (dwLength * sizeof( WCHAR ));
// allocate the memory
pOsLoadPath = (PFILE_PATH) AllocateMemory( sizeof( BYTE )*dwOsLoadPathSize );
if(pOsLoadPath == NULL)
{
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
DISPLAY_MESSAGE( stderr, ERROR_TAG);
ShowLastError(stderr);
return EXIT_FAILURE;
}
// set the values now
SecureZeroMemory( pOsLoadPath, dwOsLoadPathSize ); // double init
pOsLoadPath->Length = dwOsLoadPathSize;
pOsLoadPath->Type = FILE_PATH_TYPE_ARC_SIGNATURE;
pOsLoadPath->Version = FILE_PATH_VERSION;
CopyMemory( pOsLoadPath->FilePath, szOsLoadPath, dwLength * sizeof( WCHAR ) );
//
// windows os options
//
// determine the size needed
dwLength = 1; // os load options is empty string
dwWindowsOptionsSize = sizeof(WINDOWS_OS_OPTIONS) +
dwOsLoadPathSize + sizeof(DWORD); // Need to align the FILE_PATH struct
// allocate the memory
pWindowsOptions = (PWINDOWS_OS_OPTIONS) AllocateMemory( dwWindowsOptionsSize*sizeof( BYTE ) );
if(pWindowsOptions == NULL)
{
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL);
return EXIT_FAILURE;
}
// set the values now
SecureZeroMemory( pWindowsOptions, dwWindowsOptionsSize ); // double init
CopyMemory( (BYTE*) pWindowsOptions->Signature, WINDOWS_OS_OPTIONS_SIGNATURE, sizeof(WINDOWS_OS_OPTIONS_SIGNATURE) );
pWindowsOptions->Length = dwWindowsOptionsSize;
pWindowsOptions->Version = WINDOWS_OS_OPTIONS_VERSION;
pWindowsOptions->OsLoadPathOffset = sizeof( WINDOWS_OS_OPTIONS );
//
// Need to align the OsLoadPathOffset on a 4 byte boundary.
//
dwAlign = ( pWindowsOptions->OsLoadPathOffset & (sizeof(DWORD) - 1) );
if ( dwAlign != 0 )
{
pWindowsOptions->OsLoadPathOffset += sizeof(DWORD) - dwAlign;
}
StringCopy(pWindowsOptions->OsLoadOptions, L"", StringLengthW(L"",0) );
CopyMemory( ((BYTE*) pWindowsOptions) + pWindowsOptions->OsLoadPathOffset, pOsLoadPath, dwOsLoadPathSize );
//
// prepare the boot entry
//
// find the length of the friendly name
dwLength = StringLengthW( szFriendlyName, 0 ) + 1;
// determine the size of the structure
dwBootEntrySize = FIELD_OFFSET( BOOT_ENTRY, OsOptions ) +
dwWindowsOptionsSize +
( dwLength * sizeof( WCHAR ) ) +
dwBootFilePathSize +
+ sizeof(WCHAR) // Need to align the FriendlyName on WCHAR
+ sizeof(DWORD); // Need to align the BootFilePath on DWORD
// allocate memory
pBootEntry = (PBOOT_ENTRY) AllocateMemory( sizeof( BYTE )*dwBootEntrySize );
if(pBootEntry == NULL)
{
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR|SLE_INTERNAL );
return EXIT_FAILURE;
}
// set the values now
SecureZeroMemory( pBootEntry, dwBootEntrySize );
pBootEntry->Version = BOOT_ENTRY_VERSION;
pBootEntry->Length = dwBootEntrySize;
pBootEntry->Id = 0L;
pBootEntry->Attributes = BOOT_ENTRY_ATTRIBUTE_ACTIVE;
pBootEntry->FriendlyNameOffset = FIELD_OFFSET(BOOT_ENTRY, OsOptions) + dwWindowsOptionsSize;
//
// Need to align the unicode string on a 2 byte boundary.
//
dwAlign = ( pBootEntry->FriendlyNameOffset & (sizeof(WCHAR) - 1) );
if ( dwAlign != 0 )
{
pBootEntry->FriendlyNameOffset += sizeof(WCHAR) - dwAlign;
}
pBootEntry->BootFilePathOffset = pBootEntry->FriendlyNameOffset + ( dwLength * sizeof(WCHAR) );
//
// Need to align the FILE_PATH struct on a 4 byte boundary.
//
dwAlign = ( pBootEntry->BootFilePathOffset & (sizeof(DWORD) - 1) );
if ( dwAlign != 0 )
{
pBootEntry->BootFilePathOffset += sizeof(DWORD) - dwAlign;
}
pBootEntry->OsOptionsLength = dwWindowsOptionsSize;
CopyMemory( pBootEntry->OsOptions, pWindowsOptions, dwWindowsOptionsSize );
CopyMemory( ((PBYTE) pBootEntry) + pBootEntry->FriendlyNameOffset, szFriendlyName, ( dwLength * sizeof(WCHAR) ) );
CopyMemory( ((PBYTE) pBootEntry) + pBootEntry->BootFilePathOffset, pBootFilePath, dwBootFilePathSize );
//
// add the prepared boot entry
//
status = NtAddBootEntry( pBootEntry, &ulId );
if ( ! NT_SUCCESS( status ) )
{
dwError = RtlNtStatusToDosError( status );
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
DISPLAY_MESSAGE(stderr,GetResString(IDS_ERROR_ADD));
return EXIT_FAILURE;
}
else
{
DISPLAY_MESSAGE(stdout,GetResString(IDS_MIRROR_ADDED));
}
//
// Add the entry to the boot order.
//
ulIdCount = 32L;
pdwIdsArray = (PULONG) AllocateMemory(ulIdCount * sizeof(ULONG));
if(!pdwIdsArray)
{
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
SAFEFREE( pBootEntry);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return EXIT_FAILURE;
}
status = NtQueryBootEntryOrder( pdwIdsArray, &ulIdCount );
if (! NT_SUCCESS( status ) )
{
ShowMessage(stderr,GetResString(IDS_ERROR_SET_BOOTENTRY));
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
SAFEFREE( pBootEntry);
SAFEFREE( pdwIdsArray);
return EXIT_SUCCESS ;
}
//
// Need room in the buffer for the new entry.
//
if ( 31L < ulIdCount )
{
pdwIdsArray = (PULONG) AllocateMemory( (ulIdCount+1) * sizeof(ULONG));
if(!pdwIdsArray)
{
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
SAFEFREE( pBootEntry);
SAFEFREE( pdwIdsArray);
ShowLastErrorEx(stderr, SLE_TYPE_ERROR | SLE_INTERNAL );
return EXIT_FAILURE;
}
status = NtQueryBootEntryOrder( pdwIdsArray, &ulIdCount );
}
if ( !NT_SUCCESS(status) )
{
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
SAFEFREE( pBootEntry);
SAFEFREE( pdwIdsArray);
dwError = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_ADD));
return EXIT_FAILURE;
}
ulIdCount++;
*(pdwIdsArray + (ulIdCount - 1)) = ulId;
status = NtSetBootEntryOrder( pdwIdsArray, ulIdCount );
if ( !NT_SUCCESS(status) )
{
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
SAFEFREE( pBootEntry);
SAFEFREE( pdwIdsArray);
dwError = RtlNtStatusToDosError( status );
ShowMessage(stderr,GetResString(IDS_ERROR_ADD));
return EXIT_FAILURE;
}
//
// release the allocated memory
//
SAFEFREE( pBootFilePath );
SAFEFREE( pFilePath);
SAFEFREE( pOsLoadPath);
SAFEFREE( pWindowsOptions);
SAFEFREE( pBootEntry);
SAFEFREE( pdwIdsArray);
return EXIT_SUCCESS;
}
DWORD
ConvertintoLocale( IN LPWSTR szTempBuf,
OUT LPWSTR szOutputStr )
/*++
Routine Description:
Converts into Locale and Gets the Locale information
Arguments:
LPWSTR szTempBuf [in] -- Locale Information to get
LPWSTR szOutputStr [out] -- Locale value corresponding to the given
information
Return Value:
DWORD
--*/
{
NUMBERFMT numberfmt;
WCHAR szGrouping[MAX_RES_STRING+1] = NULL_STRING;
WCHAR szDecimalSep[MAX_RES_STRING+1] = NULL_STRING;
WCHAR szThousandSep[MAX_RES_STRING+1] = NULL_STRING;
WCHAR szTemp[MAX_RES_STRING+1] = NULL_STRING;
LPWSTR szTemp1 = NULL;
LPWSTR pszStoppedString = NULL;
DWORD dwStatus = 0;
DWORD dwGrouping = 0;
//make the fractional digits and leading zeros to nothing
numberfmt.NumDigits = 0;
numberfmt.LeadingZero = 0;
//get the decimal seperate character
if(GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SDECIMAL, szDecimalSep, SIZE_OF_ARRAY(szDecimalSep) ) == 0)
{
return EXIT_FAILURE;
}
numberfmt.lpDecimalSep = szDecimalSep;
if(GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_STHOUSAND, szThousandSep, SIZE_OF_ARRAY(szThousandSep) ) == 0)
{
return EXIT_FAILURE;
}
numberfmt.lpThousandSep = szThousandSep;
if(GetLocaleInfo( LOCALE_USER_DEFAULT, LOCALE_SGROUPING, szGrouping, SIZE_OF_ARRAY(szGrouping) ) == 0)
{
return EXIT_FAILURE;
}
szTemp1 = wcstok( szGrouping, L";");
do
{
StringConcat( szTemp, szTemp1, SIZE_OF_ARRAY(szTemp));
szTemp1 = wcstok( NULL, L";" );
}while( szTemp1 != NULL && StringCompare( szTemp1, L"0", TRUE, 0) != 0);
dwGrouping = wcstol( szTemp, &pszStoppedString, 10);
numberfmt.Grouping = (UINT)dwGrouping ;
numberfmt.NegativeOrder = 2;
dwStatus = GetNumberFormat( LOCALE_USER_DEFAULT, 0, szTempBuf, &numberfmt, szOutputStr, MAX_RES_STRING+1);
return(EXIT_SUCCESS);
}
void Freelist()
/*++
Routine Description : Function used to free the global linked list
Arguments:
Return Type :
--*/
{
PLIST_ENTRY listEntry;
PLIST_ENTRY listEntry1;
PMY_BOOT_ENTRY bootEntry;
listEntry = BootEntries.Flink;
while( listEntry != &BootEntries)
{
listEntry1 = listEntry;
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
RemoveEntryList( &bootEntry->ListEntry );
listEntry = listEntry->Flink;
if( listEntry1 != NULL )
{
FreeMemory((LPVOID *) &listEntry1 );
}
}
}
PWSTR GetDefaultBootEntry()
/*++
Routine Description :
Gets the default Boot entry.
Arguments :
Return Type : PWSTR
Returns the first entry in the list.
--*/
{
PLIST_ENTRY listEntry;
PMY_BOOT_ENTRY bootEntry;
PWSTR NtFilePath=NULL;
listEntry = BootEntries.Flink;
bootEntry = CONTAINING_RECORD( listEntry, MY_BOOT_ENTRY, ListEntry );
NtFilePath = GetNtNameForFilePath(bootEntry->OsFilePath);
return (NtFilePath);
}