]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: Document UpdateArgcArgv returns EFI_INVALID_PARAMETER
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellParametersProtocol.c
index e052d24d5d336cf08a0176c42b4697768f6fc9b8..7e0c8ce42e110fe3dcb9a4feba957ba4b3365992 100644 (file)
@@ -2,23 +2,62 @@
   Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,\r
   manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.\r
 \r
+  (C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR>\r
   Copyright (C) 2014, Red Hat, Inc.\r
-  Copyright (c) 2013 Hewlett-Packard Development Company, L.P.\r
-  Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "Shell.h"\r
 \r
+BOOLEAN AsciiRedirection = FALSE;\r
+\r
+/**\r
+  Return the next parameter's end from a command line string.\r
+\r
+  @param[in] String        the string to parse\r
+**/\r
+CONST CHAR16*\r
+FindEndOfParameter(\r
+  IN CONST CHAR16 *String\r
+  )\r
+{\r
+  CONST CHAR16 *First;\r
+  CONST CHAR16 *CloseQuote;\r
+\r
+  First = FindFirstCharacter(String, L" \"", L'^');\r
+\r
+  //\r
+  // nothing, all one parameter remaining\r
+  //\r
+  if (*First == CHAR_NULL) {\r
+    return (First);\r
+  }\r
+\r
+  //\r
+  // If space before a quote (or neither found, i.e. both CHAR_NULL),\r
+  // then that's the end.\r
+  //\r
+  if (*First == L' ') {\r
+    return (First);\r
+  }\r
+\r
+  CloseQuote = FindFirstCharacter (First+1, L"\"", L'^');\r
+\r
+  //\r
+  // We did not find a terminator...\r
+  //\r
+  if (*CloseQuote == CHAR_NULL) {\r
+    return (NULL);\r
+  }\r
+\r
+  return (FindEndOfParameter (CloseQuote+1));\r
+}\r
+\r
 /**\r
-  return the next parameter from a command line string;\r
+  Return the next parameter from a command line string.\r
 \r
   This function moves the next parameter from Walker into TempParameter and moves\r
   Walker up past that parameter for recursive calling.  When the final parameter\r
   Temp Parameter must be large enough to hold the parameter before calling this\r
   function.\r
 \r
-  @param[in, out] Walker        pointer to string of command line.  Adjusted to\r
-                                reminaing command line on return\r
-  @param[in, out] TempParameter pointer to string of command line item extracted.\r
+  This will also remove all remaining ^ characters after processing.\r
 \r
+  @param[in, out] Walker          pointer to string of command line.  Adjusted to\r
+                                  remaining command line on return\r
+  @param[in, out] TempParameter   pointer to string of command line item extracted.\r
+  @param[in]      Length          buffer size of TempParameter.\r
+  @param[in]      StripQuotation  if TRUE then strip the quotation marks surrounding\r
+                                  the parameters.\r
+\r
+  @return   EFI_INVALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string.\r
+  @return   EFI_NOT_FOUND         A closing " could not be found on the specified string\r
 **/\r
-VOID\r
-EFIAPI\r
+EFI_STATUS\r
 GetNextParameter(\r
-  CHAR16 **Walker,\r
-  CHAR16 **TempParameter\r
+  IN OUT CHAR16   **Walker,\r
+  IN OUT CHAR16   **TempParameter,\r
+  IN CONST UINTN  Length,\r
+  IN BOOLEAN      StripQuotation\r
   )\r
 {\r
-  CHAR16 *NextDelim;\r
-  CHAR16 *TempLoc;\r
+  CONST CHAR16 *NextDelim;\r
+\r
+  if (Walker           == NULL\r
+    ||*Walker          == NULL\r
+    ||TempParameter    == NULL\r
+    ||*TempParameter   == NULL\r
+    ){\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
 \r
-  ASSERT(Walker           != NULL);\r
-  ASSERT(*Walker          != NULL);\r
-  ASSERT(TempParameter    != NULL);\r
-  ASSERT(*TempParameter   != NULL);\r
 \r
   //\r
   // make sure we dont have any leading spaces\r
@@ -58,81 +108,64 @@ GetNextParameter(
   // make sure we still have some params now...\r
   //\r
   if (StrLen(*Walker) == 0) {\r
-    ASSERT((*Walker)[0] == CHAR_NULL);\r
-    *Walker = NULL;\r
-    return;\r
+DEBUG_CODE_BEGIN();\r
+    *Walker        = NULL;\r
+DEBUG_CODE_END();\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
+  NextDelim = FindEndOfParameter(*Walker);\r
+\r
+  if (NextDelim == NULL){\r
+DEBUG_CODE_BEGIN();\r
+    *Walker        = NULL;\r
+DEBUG_CODE_END();\r
+    return (EFI_NOT_FOUND);\r
   }\r
 \r
+  StrnCpyS(*TempParameter, Length / sizeof(CHAR16), (*Walker), NextDelim - *Walker);\r
+\r
   //\r
-  // we have a quoted parameter\r
-  // could be the last parameter, but SHOULD have a trailing quote\r
+  // Add a CHAR_NULL if we didn't get one via the copy\r
   //\r
-  if ((*Walker)[0] == L'\"') {\r
-    NextDelim = NULL;\r
-    for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
-      if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
-        TempLoc++;\r
-      } else if (*TempLoc == L'\"') {\r
-        NextDelim = TempLoc;\r
-        break;\r
-      }\r
-    }\r
+  if (*NextDelim != CHAR_NULL) {\r
+    (*TempParameter)[NextDelim - *Walker] = CHAR_NULL;\r
+  }\r
 \r
-    if (NextDelim - ((*Walker)+1) == 0) {\r
-      //\r
-      // found ""\r
-      //\r
-      StrCpy(*TempParameter, L"");\r
-      *Walker = NextDelim + 1;\r
-    } else if (NextDelim != NULL) {\r
+  //\r
+  // Update Walker for the next iteration through the function\r
+  //\r
+  *Walker = (CHAR16*)NextDelim;\r
+\r
+  //\r
+  // Remove any non-escaped quotes in the string\r
+  // Remove any remaining escape characters in the string\r
+  //\r
+  for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", CHAR_NULL)\r
+    ; *NextDelim != CHAR_NULL\r
+    ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL)\r
+    ) {\r
+    if (*NextDelim == L'^') {\r
 \r
       //\r
-      // Copy ensuring that both quotes are left in place.\r
-      //\r
-      StrnCpy(*TempParameter, (*Walker), NextDelim - *Walker + 1);\r
-      *Walker = NextDelim + 1;\r
-    } else {\r
-      //\r
-      // last one... someone forgot the training quote!\r
+      // eliminate the escape ^\r
       //\r
-      StrCpy(*TempParameter, *Walker);\r
-      *Walker = NULL;\r
-    }\r
-    for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
-      if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
-        CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));\r
-      }\r
-    }\r
-  } else {\r
-    //\r
-    // we have a regular parameter (no quote) OR\r
-    // we have the final parameter (no trailing space)\r
-    //\r
-    NextDelim = StrStr((*Walker), L" ");\r
-    if (NextDelim != NULL) {\r
-      StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));\r
-      (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;\r
-      *Walker = NextDelim+1;\r
-    } else {\r
+      CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));\r
+      NextDelim++;\r
+    } else if (*NextDelim == L'\"') {\r
+\r
       //\r
-      // last one.\r
+      // eliminate the unescaped quote\r
       //\r
-      StrCpy(*TempParameter, *Walker);\r
-      *Walker = NULL;\r
+      if (StripQuotation) {\r
+        CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));\r
+    } else{\r
+        NextDelim++;\r
     }\r
-    for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) {\r
-      if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {\r
-        CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0]));\r
-      }\r
-    }\r
-    while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {\r
-      (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;\r
-    }\r
-    while ((*TempParameter)[0] == L' ') {\r
-      CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0]));\r
     }\r
   }\r
-  return;\r
+\r
+  return EFI_SUCCESS;\r
 }\r
 \r
 /**\r
@@ -142,26 +175,34 @@ GetNextParameter(
   parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL.  this supports space\r
   delimited and quote surrounded parameter definition.\r
 \r
-  @param[in] CommandLine         String of command line to parse\r
-  @param[in, out] Argv           pointer to array of strings; one for each parameter\r
-  @param[in, out] Argc           pointer to number of strings in Argv array\r
+  All special character processing (alias, environment variable, redirection,\r
+  etc... must be complete before calling this API.\r
 \r
-  @return EFI_SUCCESS           the operation was sucessful\r
+  @param[in] CommandLine          String of command line to parse\r
+  @param[in] StripQuotation       if TRUE then strip the quotation marks surrounding\r
+                                  the parameters.\r
+  @param[in, out] Argv            pointer to array of strings; one for each parameter\r
+  @param[in, out] Argc            pointer to number of strings in Argv array\r
+\r
+  @return EFI_SUCCESS           the operation was successful\r
+  @return EFI_INVALID_PARAMETER some parameters are invalid\r
   @return EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ParseCommandLineToArgs(\r
   IN CONST CHAR16 *CommandLine,\r
-  IN OUT CHAR16 ***Argv,\r
-  IN OUT UINTN *Argc\r
+  IN BOOLEAN      StripQuotation,\r
+  IN OUT CHAR16   ***Argv,\r
+  IN OUT UINTN    *Argc\r
   )\r
 {\r
   UINTN       Count;\r
   CHAR16      *TempParameter;\r
   CHAR16      *Walker;\r
   CHAR16      *NewParam;\r
+  CHAR16      *NewCommandLine;\r
   UINTN       Size;\r
+  EFI_STATUS  Status;\r
 \r
   ASSERT(Argc != NULL);\r
   ASSERT(Argv != NULL);\r
@@ -172,49 +213,62 @@ ParseCommandLineToArgs(
     return (EFI_SUCCESS);\r
   }\r
 \r
-  Size = StrSize(CommandLine);\r
+  NewCommandLine = AllocateCopyPool(StrSize(CommandLine), CommandLine);\r
+  if (NewCommandLine == NULL){\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+\r
+  TrimSpaces(&NewCommandLine);\r
+  Size = StrSize(NewCommandLine);\r
   TempParameter = AllocateZeroPool(Size);\r
   if (TempParameter == NULL) {\r
+    SHELL_FREE_NON_NULL(NewCommandLine);\r
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
 \r
   for ( Count = 0\r
-      , Walker = (CHAR16*)CommandLine\r
+      , Walker = (CHAR16*)NewCommandLine\r
       ; Walker != NULL && *Walker != CHAR_NULL\r
-      ; GetNextParameter(&Walker, &TempParameter)\r
-      , Count++\r
-     );\r
-\r
-/*  Count = 0;\r
-  Walker = (CHAR16*)CommandLine;\r
-  while(Walker != NULL) {\r
-    GetNextParameter(&Walker, &TempParameter);\r
-    Count++;\r
+      ; Count++\r
+      ) {\r
+    if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, TRUE))) {\r
+      break;\r
+    }\r
   }\r
-*/\r
+\r
   //\r
   // lets allocate the pointer array\r
   //\r
   (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
   if (*Argv == NULL) {\r
-    SHELL_FREE_NON_NULL(TempParameter);\r
-    return (EFI_OUT_OF_RESOURCES);\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
   }\r
 \r
   *Argc = 0;\r
-  Walker = (CHAR16*)CommandLine;\r
+  Walker = (CHAR16*)NewCommandLine;\r
   while(Walker != NULL && *Walker != CHAR_NULL) {\r
     SetMem16(TempParameter, Size, CHAR_NULL);\r
-    GetNextParameter(&Walker, &TempParameter);\r
-    NewParam = AllocateZeroPool(StrSize(TempParameter));\r
-    ASSERT(NewParam != NULL);\r
-    StrCpy(NewParam, TempParameter);\r
+    if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, StripQuotation))) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+\r
+    NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter);\r
+    if (NewParam == NULL){\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
     ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
     (*Argc)++;\r
   }\r
   ASSERT(Count >= (*Argc));\r
+  Status = EFI_SUCCESS;\r
+\r
+Done:\r
   SHELL_FREE_NON_NULL(TempParameter);\r
-  return (EFI_SUCCESS);\r
+  SHELL_FREE_NON_NULL(NewCommandLine);\r
+  return (Status);\r
 }\r
 \r
 /**\r
@@ -234,7 +288,6 @@ ParseCommandLineToArgs(
   @sa ParseCommandLineToArgs\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 CreatePopulateInstallShellParametersProtocol (\r
   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  **NewShellParameters,\r
   IN OUT BOOLEAN                        *RootShellInstance\r
@@ -324,6 +377,7 @@ CreatePopulateInstallShellParametersProtocol (
     // Populate Argc and Argv\r
     //\r
     Status = ParseCommandLineToArgs(FullCommandLine,\r
+                                    TRUE,\r
                                     &(*NewShellParameters)->Argv,\r
                                     &(*NewShellParameters)->Argc);\r
 \r
@@ -363,7 +417,7 @@ CreatePopulateInstallShellParametersProtocol (
 }\r
 \r
 /**\r
-  frees all memory used by createion and installation of shell parameters protocol\r
+  frees all memory used by creation and installation of shell parameters protocol\r
   and if there was an old version installed it will restore that one.\r
 \r
   @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
@@ -375,7 +429,6 @@ CreatePopulateInstallShellParametersProtocol (
   @sa UninstallProtocolInterface\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 CleanUpShellParametersProtocol (\r
   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *NewShellParameters\r
   )\r
@@ -414,7 +467,7 @@ CleanUpShellParametersProtocol (
 }\r
 \r
 /**\r
-  Determin if a file name represents a unicode file.\r
+  Determine if a file name represents a unicode file.\r
 \r
   @param[in] FileName     Pointer to the filename to open.\r
 \r
@@ -422,7 +475,6 @@ CleanUpShellParametersProtocol (
   @return An error upon failure.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 IsUnicodeFile(\r
   IN CONST CHAR16 *FileName\r
   )\r
@@ -446,7 +498,7 @@ IsUnicodeFile(
   }\r
   gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
   gEfiShellProtocol->CloseFile(Handle);\r
-  return (Status);  \r
+  return (Status);\r
 }\r
 \r
 /**\r
@@ -457,7 +509,6 @@ IsUnicodeFile(
   @param[in, out] TheString  A pointer to the string to update.\r
 **/\r
 VOID\r
-EFIAPI\r
 StripQuotes (\r
   IN OUT CHAR16 *TheString\r
   )\r
@@ -476,7 +527,7 @@ StripQuotes (
 }\r
 \r
 /**\r
-  Calcualte the 32-bit CRC in a EFI table using the service provided by the\r
+  Calculate the 32-bit CRC in a EFI table using the service provided by the\r
   gRuntime service.\r
 \r
   @param  Hdr                    Pointer to an EFI standard header\r
@@ -509,7 +560,6 @@ CalculateEfiHdrCrc (
   @return       The modified FileName.\r
 **/\r
 CHAR16*\r
-EFIAPI\r
 FixFileName (\r
   IN CHAR16 *FileName\r
   )\r
@@ -525,7 +575,7 @@ FixFileName (
     Copy = FileName+1;\r
     if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {\r
       TempLocation[0] = CHAR_NULL;\r
-    }    \r
+    }\r
   } else {\r
     Copy = FileName;\r
     while(Copy[0] == L' ') {\r
@@ -533,7 +583,7 @@ FixFileName (
     }\r
     if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
       TempLocation[0] = CHAR_NULL;\r
-    }    \r
+    }\r
   }\r
 \r
   if (Copy[0] == CHAR_NULL) {\r
@@ -552,7 +602,6 @@ FixFileName (
   @return       The modified FileName.\r
 **/\r
 CHAR16*\r
-EFIAPI\r
 FixVarName (\r
   IN CHAR16 *FileName\r
   )\r
@@ -566,37 +615,12 @@ FixVarName (
     Copy = FileName+1;\r
     if ((TempLocation = StrStr(Copy , L"%")) != NULL) {\r
       TempLocation[0] = CHAR_NULL;\r
-    }    \r
+    }\r
   }\r
 \r
   return (FixFileName(Copy));\r
 }\r
 \r
-/**\r
-  Remove the unicode file tag from the begining of the file buffer since that will not be\r
-  used by StdIn.\r
-  \r
-  @param[in]  Handle    Pointer to the handle of the file to be processed.\r
-  \r
-  @retval EFI_SUCCESS   The unicode file tag has been moved successfully.\r
-**/\r
-EFI_STATUS\r
-EFIAPI\r
-RemoveFileTag(\r
-  IN SHELL_FILE_HANDLE *Handle\r
-  )\r
-{\r
-  UINTN             CharSize;\r
-  CHAR16            CharBuffer;\r
-\r
-  CharSize    = sizeof(CHAR16);\r
-  CharBuffer  = 0;\r
-  gEfiShellProtocol->ReadFile(*Handle, &CharSize, &CharBuffer);\r
-  if (CharBuffer != gUnicodeFileTag) {\r
-    gEfiShellProtocol->SetFilePosition(*Handle, 0);\r
-  }\r
-  return (EFI_SUCCESS);\r
-}\r
 \r
 /**\r
   Write the unicode file tag to the specified file.\r
@@ -628,7 +652,7 @@ WriteFileTag (
 \r
 \r
 /**\r
-  Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
+  Function will replace the current StdIn and StdOut in the ShellParameters protocol\r
   structure by parsing NewCommandLine.  The current values are returned to the\r
   user.\r
 \r
@@ -641,11 +665,10 @@ WriteFileTag (
   @param[out] OldStdErr                  Pointer to old StdErr.\r
   @param[out] SystemTableInfo            Pointer to old system table information.\r
 \r
-  @retval   EFI_SUCCESS                 Operation was sucessful, Argv and Argc are valid.\r
+  @retval   EFI_SUCCESS                 Operation was successful, Argv and Argc are valid.\r
   @retval   EFI_OUT_OF_RESOURCES        A memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 UpdateStdInStdOutStdErr(\r
   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
   IN CHAR16                             *NewCommandLine,\r
@@ -674,9 +697,11 @@ UpdateStdInStdOutStdErr(
   UINTN             Size;\r
   SPLIT_LIST        *Split;\r
   CHAR16            *FirstLocation;\r
+  BOOLEAN           Volatile;\r
 \r
   OutUnicode      = TRUE;\r
   InUnicode       = TRUE;\r
+  AsciiRedirection = FALSE;\r
   ErrUnicode      = TRUE;\r
   StdInVarName    = NULL;\r
   StdOutVarName   = NULL;\r
@@ -783,7 +808,7 @@ UpdateStdInStdOutStdErr(
     if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
       Status = EFI_NOT_FOUND;\r
     }\r
-  } \r
+  }\r
   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
     SetMem16(CommandLineWalker, 8, L' ');\r
@@ -810,7 +835,7 @@ UpdateStdInStdOutStdErr(
     if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
       Status = EFI_NOT_FOUND;\r
     }\r
-  } \r
+  }\r
   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
     SetMem16(CommandLineWalker, 10, L' ');\r
@@ -824,7 +849,7 @@ UpdateStdInStdOutStdErr(
     if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
       Status = EFI_NOT_FOUND;\r
     }\r
-  } \r
+  }\r
   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
     SetMem16(CommandLineWalker, 8, L' ');\r
@@ -955,6 +980,7 @@ UpdateStdInStdOutStdErr(
     } else {\r
       StdInFileName   = CommandLineWalker += 4;\r
       InUnicode       = FALSE;\r
+      AsciiRedirection = TRUE;\r
     }\r
     if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
       Status = EFI_NOT_FOUND;\r
@@ -976,12 +1002,12 @@ UpdateStdInStdOutStdErr(
   //\r
   // re-populate the string to support any filenames that were in quotes.\r
   //\r
-  StrCpy(CommandLineCopy, NewCommandLine);\r
+  StrnCpyS(CommandLineCopy, StrSize(CommandLineCopy)/sizeof(CHAR16), NewCommandLine, StrLen(NewCommandLine));\r
 \r
   if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
-    && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
+    && (((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof(CHAR16) < StrLen(NewCommandLine))\r
     ){\r
-    *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
+    *(NewCommandLine + ((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof(CHAR16)) = CHAR_NULL;\r
   }\r
 \r
   if (!EFI_ERROR(Status)) {\r
@@ -1047,12 +1073,12 @@ UpdateStdInStdOutStdErr(
       //\r
       // Check for no volatile environment variables\r
       //\r
-      ||(StdErrVarName  != NULL && !IsVolatileEnv(StdErrVarName))\r
-      ||(StdOutVarName  != NULL && !IsVolatileEnv(StdOutVarName))\r
+      ||(StdErrVarName  != NULL && !EFI_ERROR (IsVolatileEnv (StdErrVarName, &Volatile)) && !Volatile)\r
+      ||(StdOutVarName  != NULL && !EFI_ERROR (IsVolatileEnv (StdOutVarName, &Volatile)) && !Volatile)\r
       //\r
       // Cant redirect during a reconnect operation.\r
       //\r
-      ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
+      ||(StrStr(NewCommandLine, L"connect -r") != NULL\r
          && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
       //\r
       // Check that filetypes (Unicode/Ascii) do not change during an append\r
@@ -1109,7 +1135,7 @@ UpdateStdInStdOutStdErr(
         if (TempHandle == NULL) {\r
           Status = EFI_INVALID_PARAMETER;\r
         } else {\r
-          if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
+          if (gUnicodeCollation->MetaiMatch (gUnicodeCollation, StdOutFileName, L"NUL")) {\r
             //no-op\r
           } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
             Status = WriteFileTag (TempHandle);\r
@@ -1201,18 +1227,13 @@ UpdateStdInStdOutStdErr(
           &TempHandle,\r
           EFI_FILE_MODE_READ,\r
           0);\r
-        if (InUnicode) {\r
-          //\r
-          // Chop off the 0xFEFF if it's there...\r
-          //\r
-          RemoveFileTag(&TempHandle);\r
-        } else if (!EFI_ERROR(Status)) {\r
-          //\r
-          // Create the ASCII->Unicode conversion layer\r
-          //\r
-          TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
-        }\r
         if (!EFI_ERROR(Status)) {\r
+          if (!InUnicode) {\r
+            //\r
+            // Create the ASCII->Unicode conversion layer\r
+            //\r
+            TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
+          }\r
           ShellParameters->StdIn = TempHandle;\r
           gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
         }\r
@@ -1237,7 +1258,7 @@ UpdateStdInStdOutStdErr(
 }\r
 \r
 /**\r
-  Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
+  Function will replace the current StdIn and StdOut in the ShellParameters protocol\r
   structure with StdIn and StdOut.  The current values are de-allocated.\r
 \r
   @param[in, out] ShellParameters      Pointer to parameter structure to modify.\r
@@ -1247,7 +1268,6 @@ UpdateStdInStdOutStdErr(
   @param[in] SystemTableInfo           Pointer to old system table information.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 RestoreStdInStdOutStdErr (\r
   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
   IN  SHELL_FILE_HANDLE                 *OldStdIn,\r
@@ -1258,7 +1278,7 @@ RestoreStdInStdOutStdErr (
 {\r
   SPLIT_LIST        *Split;\r
 \r
-  if (ShellParameters == NULL \r
+  if (ShellParameters == NULL\r
     ||OldStdIn        == NULL\r
     ||OldStdOut       == NULL\r
     ||OldStdErr       == NULL\r
@@ -1308,7 +1328,7 @@ RestoreStdInStdOutStdErr (
   return (EFI_SUCCESS);\r
 }\r
 /**\r
-  Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
+  Function will replace the current Argc and Argv in the ShellParameters protocol\r
   structure by parsing NewCommandLine.  The current values are returned to the\r
   user.\r
 \r
@@ -1316,22 +1336,28 @@ RestoreStdInStdOutStdErr (
 \r
   @param[in, out] ShellParameters        Pointer to parameter structure to modify.\r
   @param[in] NewCommandLine              The new command line to parse and use.\r
+  @param[in] Type                        The type of operation.\r
   @param[out] OldArgv                    Pointer to old list of parameters.\r
   @param[out] OldArgc                    Pointer to old number of items in Argv list.\r
 \r
-  @retval   EFI_SUCCESS                 Operation was sucessful, Argv and Argc are valid.\r
+\r
+  @retval   EFI_SUCCESS                 Operation was successful, Argv and Argc are valid.\r
+  @return   EFI_INVALID_PARAMETER       Some parameters are invalid.\r
   @retval   EFI_OUT_OF_RESOURCES        A memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 UpdateArgcArgv(\r
   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
   IN CONST CHAR16                       *NewCommandLine,\r
+  IN SHELL_OPERATION_TYPES              Type,\r
   OUT CHAR16                            ***OldArgv OPTIONAL,\r
   OUT UINTN                             *OldArgc OPTIONAL\r
   )\r
 {\r
+  BOOLEAN                 StripParamQuotation;\r
+\r
   ASSERT(ShellParameters != NULL);\r
+  StripParamQuotation = TRUE;\r
 \r
   if (OldArgc != NULL) {\r
     *OldArgc = ShellParameters->Argc;\r
@@ -1340,11 +1366,19 @@ UpdateArgcArgv(
     *OldArgv = ShellParameters->Argv;\r
   }\r
 \r
-  return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
+  if (Type == Script_File_Name) {\r
+    StripParamQuotation = FALSE;\r
+  }\r
+\r
+  return ParseCommandLineToArgs( NewCommandLine,\r
+                                 StripParamQuotation,\r
+                                 &(ShellParameters->Argv),\r
+                                 &(ShellParameters->Argc)\r
+                                );\r
 }\r
 \r
 /**\r
-  Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
+  Function will replace the current Argc and Argv in the ShellParameters protocol\r
   structure with Argv and Argc.  The current values are de-allocated and the\r
   OldArgv must not be deallocated by the caller.\r
 \r
@@ -1353,7 +1387,6 @@ UpdateArgcArgv(
   @param[in] OldArgc                    pointer to old number of items in Argv list\r
 **/\r
 VOID\r
-EFIAPI\r
 RestoreArgcArgv(\r
   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
   IN CHAR16                             ***OldArgv,\r