#include <precomp.h>

//
// Global Coordinates
//
#define COL_TITLE               0
#define ROW_TITLE               0
#define COL_OSOPTIONS           2
#define ROW_OSOPTIONS           2
#define COL_PROMPT              0
#define ROW_PROMPT              2
#define CLEAR_LINE              L"                                                                               "
#define PROMPT                  L"Select> "
#define NUMBER_OF_USER_OPTIONS  3               // options, plus a space seperator
#define MAX_OPTIONS_PER_VAR     7

#define BACKUPNVRFILE           L"\\bootentries.bak"
  
VOID
InitializeStdOut(
    IN struct _EFI_SYSTEM_TABLE     *SystemTable
    )
{
    //
    // Stash some of the efi stdout pointers
    //

    ConOut = SystemTable->ConOut;

    ClearScreen         = ConOut->ClearScreen;
    SetCursorPosition   = ConOut->SetCursorPosition;
    SetMode             = ConOut->SetMode;
    CursorRow           = ConOut->Mode->CursorRow;
    CursorColumn        = ConOut->Mode->CursorColumn;
    EnableCursor        = ConOut->EnableCursor;

    ConIn = SystemTable->ConIn;

    //
    // Set the mode to 80, 25 and clear the screen
    //
    SetMode( ConOut, 0 );
}

VOID
PrintTitle(
    )
{
    CHAR16 Buffer[256];
    
    ClearScreen( ConOut );
#if 0
    PrintAt( 0, 30, L"%H%s%N\n", TITLE1 );
    PrintAt( 0, 30, L"%H%s%N",   VER_PRODUCTBUILD );
#endif    

    SPrint(
        Buffer,
        sizeof(Buffer),
        L"%s [Version %d.%d.%d]",
        TITLE1,
        VER_PRODUCTMAJORVERSION,
        VER_PRODUCTMINORVERSION,
        VER_PRODUCTBUILD
        );

    PrintAt( 0, 30, L"%H%s%N\n", Buffer);
}

BOOLEAN
isWindowsOsUserSelection(
    UINTN   userSelection
    )
{
    BOOLEAN status;

    status = isWindowsOsBootOption((char*)LoadOptions[userSelection],
                                   LoadOptionsSize[userSelection]
                                   );

    return status;
}


INTN
BackupBootOptions(
    CHAR16*         filePath
    )
{
    INTN    status;

    //
    // backup current boot options
    //

    Print(L"\nBacking up boot options...\n");

    status = SaveAllBootOptions(filePath);

    if(status != -1) {
        Print(L"Backed up Boot Options to file: %H%s%N\n",filePath);
        Print(L"Use %HImport%N command to retrieve saved boot options\n");
    } else {
        Print(L"Could not backup Boot Options to file: %H%s%N!\n",filePath);
    }

    return status;
}

VOID
DisplayMainMenu(
    )
{
    UINT32 done = FALSE;
    UINT32 nUserSelection, nSubUserSelection, nModifyVar;
    CHAR16 szUserSelection[1024];
    CHAR16 szOsLoader[1024];
    CHAR16 szInput[512];
    VOID* SourceBuffer = NULL;
    UINT32 PartitionCount;
    EFI_DEVICE_PATH *FilePath;

    //
    // Display boot options from nvram.
    //
    PrintTitle();
    GetBootManagerVars();
    DisplayBootOptions();

    //
    // Process user input.
    //
    while( !done )  {

        GetUserSelection( szUserSelection );
        
        //
        // Handle char string commands
        //
        if( (!StriCmp( szUserSelection, L"q")) || (!StriCmp( szUserSelection, L"quit"))
            || (!StriCmp( szUserSelection, L"Q")) || (!StriCmp( szUserSelection, L"exit")) ) {

            //
            // Quit
            //
            done = TRUE;

        }
        else if( (!StriCmp( szUserSelection, L"d")) || (!StriCmp( szUserSelection, L"D"))
            || (!StriCmp( szUserSelection, L"display")) ) {
            //
            // Display command
            //

            //
            // Choose selection
            //
            Print( L"\n" );
            nSubUserSelection = GetSubUserSelection( L"Enter boot option to display: ", (UINT32) GetBootOrderCount() );

            if( nSubUserSelection != 0 ) {
                nSubUserSelection--;

                if (isWindowsOsUserSelection(nSubUserSelection) == FALSE) {
                
                    Print (L"\n\nThis tool only displays Windows OS boot options\n");

                } else {
                    
                    if(DisplayExtended( nSubUserSelection ))
                        ;
                    else {
                        Print( L"\n" );
                        Print( L"Wrong Boot Option %d Selected\n", nSubUserSelection+1 );
                    }

                }

                Print( L"\n" );
                Input( L"Press enter to continue", szInput, sizeof(szInput) );
            }

            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        }
        else if( (!StriCmp( szUserSelection, L"e")) || (!StriCmp( szUserSelection, L"E"))
            || (!StriCmp( szUserSelection, L"erase")) ) {
            //
            // Erase command
            //

            BOOLEAN     selectedAll;    

            //
            // Choose selection
            //
            Print( L"\n" );
            nSubUserSelection = GetSubUserSelectionOrAll( L"Enter OS boot option to erase (* = All): ", 
                                                          (UINT32) GetBootOrderCount(),
                                                          &selectedAll
                                                          );
            //
            // choose the path based on if the user wants all the os boot options whacked or not
            //

            if (selectedAll) {
            
                //
                // get user confirmation
                //
                Print( L"\n" );
                Input( L"This will erase all OS boot options. Are you Sure? ", szInput, sizeof(szInput) );
                
                if( (!StriCmp( szInput, L"y")) || (!StriCmp( szInput, L"Y"))) {
                    
                    //
                    // backup current boot options first
                    //
                    if (BackupBootOptions(BACKUPNVRFILE) != -1) {
                      
                        if(EraseAllOsBootOptions()) {
                            
                            Print(L"\nAll OS Boot Options Erased.\n");
                            GetBootManagerVars();
                        
                        }
                        else {
                            
                            Print(L"\nThere are no OS Boot Options to Erase.\n");
                        
                        }
                    }
                    
                    Print( L"\n" );
                    Input( L"Press enter to continue", szInput, sizeof(szInput) );
                }
            
            } else {

                CHAR16  buf[256];

                if( nSubUserSelection > 0 ) {
                    
                    SPrint (buf, sizeof(buf), L"This will erase OS boot option %d. Are you Sure? ", nSubUserSelection);

                    // get user confirmation
                    //
                    Print( L"\n" );
                    Input( buf, szInput, sizeof(szInput) );

                    if( (!StriCmp( szInput, L"y")) || (!StriCmp( szInput, L"Y"))) {
                        nSubUserSelection--;

                        if(EraseOsBootOption(nSubUserSelection)) {

                           Print(L"\nBoot Option %d erased.\n", nSubUserSelection + 1);

                           FreeBootManagerVars();
                           GetBootManagerVars();

                        }
                        else {
                           Print(L"\nInvalid OS Boot Options specified.\n");
                        }

                        Print( L"\n" );
                        Input( L"Press enter to continue", szInput, sizeof(szInput) );
                    }
                }
            }

            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        } else if( (!StriCmp( szUserSelection, L"p")) || (!StriCmp( szUserSelection, L"P"))
            || (!StriCmp( szUserSelection, L"push")) ) {
            //
            // Push command
            //

            //
            // Choose selection
            //
            Print( L"\n" );
            nSubUserSelection = GetSubUserSelection( L"Enter the boot option you want to push to top? ", (UINT32) GetBootOrderCount() );

            if( nSubUserSelection > 0 ) {
                nSubUserSelection--;
                if(PushToTop( nSubUserSelection )) {
                    FreeBootManagerVars();
                    GetBootManagerVars();
                    Print( L"\n" );
                    Print( L"OS Boot Option %d pushed to top of boot order\n", nSubUserSelection+1 );
                }
                else {
                    Print( L"\n" );
                    Print( L"Wrong Boot Option %d Selected\n", nSubUserSelection+1 );
                }
                Input( L"Press enter to continue", szInput, sizeof(szInput) );
            }
            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        } else if( (!StriCmp( szUserSelection, L"c")) || (!StriCmp( szUserSelection, L"C"))
            || (!StriCmp( szUserSelection, L"copy")) ) {

            //
            // Copy command
            //

            //
            // Choose selection
            //
            Print( L"\n" );
            nSubUserSelection = GetSubUserSelection( L"Enter OS boot option to copy: ", (UINT32) GetBootOrderCount() );

            if( nSubUserSelection != 0 ) {

                nSubUserSelection--;
                if(!CopyVar( nSubUserSelection )) {
                    Print( L"\n" );
                    Print( L"Wrong Boot Option %d Selected\n",nSubUserSelection+1);
                }
                else {
                    SetBootManagerVars();
                    FreeBootManagerVars();
                    GetBootManagerVars();
                    Print( L"\n" );
                    Print( L"Boot Option %d Copied. ",nSubUserSelection+1);
                 }
                
                Print( L"\n" );
                Input( L"Press enter to continue", szInput, sizeof(szInput) );
            }

            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        } else if( (!StriCmp( szUserSelection, L"x")) || (!StriCmp( szUserSelection, L"X"))
            || (!StriCmp( szUserSelection, L"export")) ) {
            //
            // Save command
            //
            
            CHAR16      filePath[512];
            BOOLEAN     selectedAll;    

            //
            // Choose selection
            //
            Print( L"\n" );
            nSubUserSelection = GetSubUserSelectionOrAll( L"Enter OS boot option to export (* = All): ", 
                                                          (UINT32) GetBootOrderCount(),
                                                          &selectedAll
                                                          );
            if (nSubUserSelection > 0 || selectedAll) {
                
                Print( L"\n" );
                Input( L"Enter EXPORT file path: ", filePath, sizeof(filePath) );
                
                if (StrLen(filePath) > 0) {

                    //
                    // choose the path based on if the user wants all the os boot options exported or just one
                    //

                    if (selectedAll) {


                        Print(L"\nSaving %d boot options...\n", GetBootOrderCount());

                        if(SaveAllBootOptions(filePath) != -1) {
                            Print(L"Saved Boot Options to file: %H%s%N\n",filePath);
                            Print(L"Use %HImport%N command to retrieve saved boot options\n");
                        } else {
                            Print(L"Could not save Boot Options to file: %H%s%N!\n",filePath);
                        }

                    } else {

                        Print(L"\nSaving boot option %d...\n", nSubUserSelection);

                        if(SaveBootOption(filePath, nSubUserSelection-1) != -1) {
                            Print(L"Saved Boot Option %d to file: %H%s%N\n",nSubUserSelection, filePath);
                            Print(L"Use %HImport%N command to retrieve saved boot option\n");
                        } else {
                            Print(L"Could not save Boot Option to file: %H%s%N!\n",filePath);
                        }

                    }
                }
            }

            Print( L"\n" );
            Input( L"Press enter to continue", szInput, sizeof(szInput) );
            
            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        } else if( (!StriCmp( szUserSelection, L"i")) || (!StriCmp( szUserSelection, L"I"))
            || (!StriCmp( szUserSelection, L"import")) ) {
            //
            // Restore command
            //

            CHAR16  filePath[512];

            Print( L"\n" );
            Input( L"Enter IMPORT file path: ", filePath, sizeof(filePath) );

            if (StrLen(filePath) > 0) {
                if(RestoreFileExists(filePath) == TRUE) {

                    if(RestoreNvr(filePath) != -1) {

                        Print( L"\n" );
                        Print(L"Imported Boot Options from file: %H%s%N\n",filePath);

                        FreeBootManagerVars();
                        GetBootManagerVars();   

                    }
                    else {

                        Print(L"Restore failed!\n");

                    }

                } else {

                    Print(L"\n\nError: Restore file not found: %s\n\n", filePath);
                
                }
            }

            Print( L"\n" );
            Input( L"Press enter to continue", szInput, sizeof(szInput) );

            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        } 
#if 0
        else if( (!StriCmp( szUserSelection, L"a")) || (!StriCmp( szUserSelection, L"A"))
            || (!StriCmp( szUserSelection, L"add")) ) {
            //
            // Add command
            //

            //
            // Get EFI system partition
            //
            PartitionCount = GetPartitions();

            if( PartitionCount > 0 ) {
                    Print( L"\n" );
                    Input( L"Name of New BootOption: ", szInput, sizeof(szInput) );

                    FilePath = FileDevicePath( 
                                GetDeviceHandleForPartition(), 
                                L"os\\winnt50\\ia64ldr.efi" 
                                );

                    PackAndWriteToNvr(
                        -1,
                        "multi(0)disk(0)rdisk(0)partition(1)",
                        "multi(0)disk(0)rdisk(0)partition(1)\\os\\winnt50\\ia64ldr.efi",
                        "multi(0)disk(0)rdisk(0)partition(2)",
                        "\\WINNT64",
                        szInput[0] ? szInput : L"New Boot Option",
                        "",
                        (char*) FilePath
                        );

                    Print( L"\nAdded %H%s%N. Use %HModify%N command to change any of the default values.\n", 
                        szInput[0] ? szInput : L"New Boot Option" );
                    Input( L"Press enter to continue", szInput, sizeof(szInput) );

                    FreeBootManagerVars();
                    GetBootManagerVars();
            } else {
                Print( L"No partitions found. To use this option, you must have an EFI or FAT16\n" );
                Print( L"partition that will be used as your System Partition.\n" ); 
                Input( L"Press enter to continue", szInput, sizeof(szInput) );
            }

            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        } 
#endif 
        else if( (!StriCmp( szUserSelection, L"h")) || (!StriCmp( szUserSelection, L"H"))
            || (!StriCmp( szUserSelection, L"help")) ) {
            //
            // Help command
            //

            PrintTitle();

            //
            // Display Help text.
            //
            Print( L"\n" );
            Print( L"%HDisplay%N - Display an OS boot option's environment variables.\n" );
            Print( L"%HModify%N  - Modify an OS boot option's environment variable.\n" );
            Print( L"%HCopy%N    - Copy (duplicate) an OS boot option.\n" );
            Print( L"%HExport%N  - Export all/one OS boot option(s) to disk.\n" );
            Print( L"%HImport%N  - Import (and append) OS boot option(s) from disk.\n" );
            Print( L"%HErase%N   - Erase all OS boot options from NVRAM.\n" );
            Print( L"%HPush%N    - Push a OS boot option to top of boot order.\n" );
            Print( L"%HHelp%N    - This display.\n" );
            Print( L"%HQuit%N    - Quit.\n" );
            Print( L"\n");
            Print( L"Note: When importing/exporting boot options, all specified file paths\n");
            Print( L"      are absolute and relative to the current disk device.\n");
            Print( L"\n");
            Print( L"      Example: To import Boot0000 from the Windows loader directory WINNT50.0\n");
            Print( L"               on fs1, you would run nvrboot.efi on fs1 and use the path:\n");
            Print( L"\n");
            Print( L"               \\EFI\\Microsoft\\WINNT50.0\\Boot0000\n");
            Print( L"\n");
            Input( L"Press enter to continue", szInput, sizeof(szInput) );

            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();

        }
        else if( (!StriCmp( szUserSelection, L"m")) || (!StriCmp( szUserSelection, L"M")) 
            || (!StriCmp( szUserSelection, L"modify")) ) {
            //
            // Modify command
            //
            
            //
            // Choose selection
            //
            Print( L"\n" );
            nSubUserSelection = GetSubUserSelection( L"Enter OS boot option to modify: ", (UINT32) GetBootOrderCount() );

                               
            if( nSubUserSelection > 0 ) {
                
                nSubUserSelection--;

                if (isWindowsOsUserSelection(nSubUserSelection) == FALSE) {

                    Print( L"\n\nThis tool only modifies Windows OS boot options\n" );
                
                } else {
                    
                    if(DisplayExtended( nSubUserSelection )) {
                        
                        //
                        // Choose var
                        //
                        nModifyVar = GetSubUserSelection( L"Enter var to modify: ", MAX_OPTIONS_PER_VAR );
                        
                        if( nModifyVar > 0) {
                            Print( L"\n" );
                        
                            //
                            // Map variable to env var
                            //
                            switch( nModifyVar ) {
                        
                            case 1:
                                Input( L"LoadIdentifier = ", szInput, sizeof(szInput) );
                                nModifyVar = DESCRIPTION;
                                break;
                            case 2:
                                Input( L"OsLoadOptions = ", szInput, sizeof(szInput) );
                                nModifyVar = OSLOADOPTIONS;
                                break;
                            case 3:
                                Print (L"This field currently not modifiable\n");
#if 0
                                Input( L"EfiOsLoaderFilePath = ", szInput, sizeof(szInput) );
#endif                                
                                nModifyVar = EFIFILEPATHLIST;
                                break;
                            case 4:
                                Print (L"This field currently not modifiable\n");
#if 0
                                Input( L"OsLoaderFilePath = ", szInput, sizeof(szInput) );
#endif                                
                                nModifyVar = OSFILEPATHLIST;
                                break;
                        
                            default:
                                break;
                            }
                        
                            //
                            // Write all vars to NV-RAM
                            //
                            SetFieldFromLoadOption(
                                nSubUserSelection,
                                nModifyVar,
                                szInput
                                );
                            
                            DisplayExtended(nSubUserSelection);

                            FreeBootManagerVars();
                            GetBootManagerVars();
                        }
                        
                        Print( L"\n" );
                    }
                }
                Input( L"Press enter to continue", szInput, sizeof(szInput) );
            }
            
        }

            //
            // Display boot options from nvram
            //
            PrintTitle();
            DisplayBootOptions();
    }
}

UINT32
GetConfirmation(
    IN CHAR16 *szConfirm
    )
{
    CHAR16 szIn[80];
    UINT32 saveRow;

    Print( L"\n" );

    saveRow = CursorRow;

    if( szConfirm ) {
        Input( szConfirm, szIn, sizeof(szIn) );
    } else {
        Input( L"Are you sure? ", szIn, sizeof(szIn) );
    }

    // Clear previous input
    SetCursorPosition( ConOut, 0, saveRow );
    PrintAt( 0, saveRow, CLEAR_LINE );

    if( (!StriCmp( szIn, L"y")) || (!StriCmp( szIn, L"yes")) )
        return TRUE;

    return FALSE;
}

VOID
GetUserSelection(
    OUT CHAR16 *szUserSelection
    )
{
    UINT32 numSelections;
    UINT32 row, col;

    numSelections = (UINT32) GetOsBootOptionsCount();

    numSelections += NUMBER_OF_USER_OPTIONS;

    // note, we use ROW_PROMPT as an offset
    row = ROW_OSOPTIONS + numSelections + ROW_PROMPT;
    col = COL_PROMPT;

    // Clear previous input
    SetCursorPosition( ConOut, col, row );
    PrintAt( col, row, CLEAR_LINE );

    // Get the input
    SetCursorPosition( ConOut, col, row );
    Input( PROMPT, szUserSelection, 1024 );
}

VOID
DisplayBootOptions(
    )
{
    UINT32 i;
    UINT32 j;
    CHAR16 LoadIdentifier[200];
    UINTN   bootOrderCount;

    bootOrderCount = GetBootOrderCount();

    if (bootOrderCount > 0) {

        for ( i=0,j=0; i<GetBootOrderCount(); i++ ) {

            if(LoadOptionsSize[i] == 0) {
                //
                // It's possible a null load option could be in the list
                // we naturally want to catch this...
                //
#if EFI_DEBUG
                Print(L"\nNVRAM Boot Entry %d has 0 length!\n", i);
                ASSERT(LoadOptionsSize[i] > 0);
#endif

                //
                // if we are not in debug mode, just let the use know what is
                // going on other wise the menu may be screwed up
                //
                PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + j, L"%2d. (0 length Boot Entry)\n", i+1);
            } else if(GetLoadIdentifier( i, LoadIdentifier)) {

                if (isWindowsOsBootOption((char*)LoadOptions[i], LoadOptionsSize[i]) == TRUE)
                {
                    PrintAt( COL_OSOPTIONS - 1, ROW_OSOPTIONS + j, L"*%2d. %s\n", i+1, LoadIdentifier );
                }
                else {

                    PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + j, L"%2d. %s\n", i+1, LoadIdentifier );
                }
                j++;
            }
        }

        PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"* = Windows OS boot option\n" );
        j++;
    
    } else {

        PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS, L"[No Boot Entries Present]\n");
        
        j = 2;

    }

    //
    // Display Maitainence Menu
    //
#if 0
    PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(D)%Nisplay %H(M)%Nodify %H(C)%Nopy\n" );
    PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(S)%Nave %H(R)%Nestore %H(E)%Nrase\n" );
//    PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(A)%Ndd %H(P)%Nush %H(H)%Nelp   %H(Q)%Nuit\n" );
    PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(P)%Nush %H(H)%Nelp   %H(Q)%Nuit\n" );
#endif
    
    PrintAt( COL_OSOPTIONS, ROW_OSOPTIONS + ++j, L"%H(D)%Nisplay %H(M)%Nodify %H(C)%Nopy E%H(x)%Nport %H(I)%Nmport %H(E)%Nrase %H(P)%Nush %H(H)%Nelp %H(Q)%Nuit\n" );
}

#if 0
#define L_SYSTEMPARTITION   L"SystemPartition"
#define L_OSLOADER          L"OsLoader"
#define L_OSLOADPARTITION   L"OsLoadPartition"
#define L_OSLOADFILENAME    L"OsLoadFilename"
#define L_LOADIDENTIFIER    L"LoadIdentifier"
#define L_OSLOADOPTIONS     L"OsLoadOptions"
#define L_OSLOADPATH        L"OsLoadOptions"
#define L_EFIFILEPATH       L"EfiOsLoaderFilePath"
#define L_COUNTDOWN         L"COUNTDOWN"
#define L_AUTOLOAD          L"AUTOLOAD"
#define L_LASTKNOWNGOOD     L"LastKnownGood"
#define L_BOOTSELECTION     L"BootSelection"
#endif

BOOLEAN
DisplayExtended(
    IN UINT32 Selection
    )
{
    char                OsLoadOptions[200];
    CHAR16              LoadIdentifier[200];
    unsigned char       EfiFilePath[1024];
    unsigned char       OsLoadPath[1024];
    CHAR16              FilePathShort[200];
    BOOLEAN             status;
    PFILE_PATH          pFilePath;
    
#if DEBUG_PACK
    DisplayELOFromLoadOption(Selection);
#endif

    status = GetOsLoadOptionVars(
                Selection,
                LoadIdentifier,
                OsLoadOptions,
                EfiFilePath,
                OsLoadPath
                );
    if (status == FALSE) {
        return status;
    }
    
    Print( L"\n" );
    Print( L"1. LoadIdentifier = %s\n", LoadIdentifier );
    Print( L"2. OsLoadOptions = %s\n", OsLoadOptions );
    
    GetFilePathShort( (EFI_DEVICE_PATH*) EfiFilePath, FilePathShort );
    Print( L"3. EfiOsLoaderFilePath = %s\n", FilePathShort );
    
    pFilePath = (FILE_PATH*)OsLoadPath;

    GetFilePathShort( (EFI_DEVICE_PATH*)pFilePath->FilePath, FilePathShort );
    Print( L"4. OsLoaderFilePath = %s\n", FilePathShort );
    
    return TRUE;
}

UINT32
GetSubUserSelectionOrAll(
    IN  CHAR16*     szConfirm,
    IN  UINT32      MaxSelection,
    OUT BOOLEAN*    selectedAll
    )
{
    CHAR16 szIn[80];
    UINT32 nUserSelection = 0;

    if( szConfirm ) {
        Input( szConfirm, szIn, sizeof(szIn) );
    } else {
        Input( L"Enter Selection (* = ALL)? ", szIn, sizeof(szIn) );
    }

    *selectedAll = FALSE;

    if (StrCmp(szIn, L"*") == 0) {
        
        *selectedAll = TRUE;
    
    } else {

        nUserSelection = (int) Atoi( szIn );

        if(( nUserSelection>0 ) && ( nUserSelection <= MaxSelection))
            return nUserSelection;
    
    }

    return 0;
}


UINT32
GetSubUserSelection(
    IN CHAR16 *szConfirm,
    IN UINT32 MaxSelection
    )
{
    CHAR16 szIn[80];
    UINT32 nUserSelection = 0;

    if( szConfirm ) {
        Input( szConfirm, szIn, sizeof(szIn) );
    } else {
        Input( L"Enter Selection? ", szIn, sizeof(szIn) );
    }

    nUserSelection = (int) Atoi( szIn );

    if(( nUserSelection>0 ) && ( nUserSelection <= MaxSelection))
        return nUserSelection;

    return 0;
}