public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
* [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0: when typing fs0:<TAB>
@ 2016-08-09  5:43 Ruiyu Ni
  2016-08-09  5:44 ` Ni, Ruiyu
  2016-08-09 15:08 ` Shah, Tapan
  0 siblings, 2 replies; 3+ messages in thread
From: Ruiyu Ni @ 2016-08-09  5:43 UTC (permalink / raw)
  To: edk2-devel; +Cc: Jaben Carsey

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Jaben Carsey <jaben.carsey@intel.com>
---
 ShellPkg/Application/Shell/FileHandleWrappers.c | 312 ++++++++++++++----------
 1 file changed, 185 insertions(+), 127 deletions(-)

diff --git a/ShellPkg/Application/Shell/FileHandleWrappers.c b/ShellPkg/Application/Shell/FileHandleWrappers.c
index f6a82ee..0091934 100644
--- a/ShellPkg/Application/Shell/FileHandleWrappers.c
+++ b/ShellPkg/Application/Shell/FileHandleWrappers.c
@@ -293,6 +293,134 @@ FileInterfaceNulWrite(
 }
 
 /**
+  Create the TAB completion list.
+
+  @param[in]  InputString       The command line to expand.
+  @param[in]  StringLen         Length of the command line.
+  @param[in]  BufferSize        Buffer size.
+  @param[out] TabCompletionList Return the TAB completion list.
+  @param[out] TabUpdatePos      Return the TAB update position.
+**/
+EFI_STATUS
+EFIAPI
+CreateTabCompletionList (
+  IN CONST CHAR16             *InputString,
+  IN CONST UINTN              StringLen, 
+  IN CONST UINTN              BufferSize,
+  IN OUT EFI_SHELL_FILE_INFO  **TabCompletionList,
+  IN OUT   UINTN              *TabUpdatePos
+)
+{
+  BOOLEAN             InQuotation;
+  UINTN               TabPos;
+  UINTN               Index;
+  CONST CHAR16        *Cwd;
+  EFI_STATUS          Status;
+  CHAR16              *TabStr;
+  EFI_SHELL_FILE_INFO *FileList;
+  EFI_SHELL_FILE_INFO *FileInfo;
+  EFI_SHELL_FILE_INFO *TempFileInfo;
+
+  //
+  // Allocate buffers
+  //
+  TabStr = AllocateZeroPool (BufferSize);
+  if (TabStr == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // handle auto complete of file and directory names...
+  // E.g.: cd fs0:\EFI\Bo<TAB>
+  //          ^        ^
+  //          TabPos   TabUpdatePos
+  //
+  TabPos        = 0;
+  *TabUpdatePos = 0;
+  FileList      = NULL;
+  InQuotation   = FALSE;
+  for (Index = 0; Index < StringLen; Index++) {
+    switch (InputString[Index]) {
+    case L'\"':
+      InQuotation = (BOOLEAN) (!InQuotation);
+      break;
+
+    case L' ':
+      if (!InQuotation) {
+        TabPos = Index + 1;
+        *TabUpdatePos = TabPos;
+      }
+      break;
+
+    case L':':
+      //
+      // handle the case "fs0:<TAB>"
+      // Update the TabUpdatePos as well.
+      //
+    case L'\\':
+      *TabUpdatePos = Index + 1;
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  if (StrStr (InputString + TabPos, L":") == NULL) {
+    //
+    // If file path doesn't contain ":", it's a path relative to current directory.
+    //
+    Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL);
+    if (Cwd != NULL) {
+      StrnCpyS (TabStr, (BufferSize) / sizeof (CHAR16), Cwd, (BufferSize) / sizeof (CHAR16) - 1);
+      if (InputString[TabPos] != L'\\') {
+        StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\");
+      }
+    }
+  }
+  StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString + TabPos, StringLen - TabPos);
+  StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr));
+  Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FileList);
+
+  //
+  // Filter out the non-directory for "CD" command
+  // Filter "." and ".." for all
+  //
+  if (!EFI_ERROR (Status) && FileList != NULL) {
+    //
+    // Skip the spaces in the beginning
+    //
+    while (*InputString == L' ') {
+      InputString++;
+    }
+
+    for (FileInfo = (EFI_SHELL_FILE_INFO *) GetFirstNode (&FileList->Link); !IsNull (&FileList->Link, &FileInfo->Link); ) {
+      if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) ||
+          (((InputString[0] == L'c' || InputString[0] == L'C') && (InputString[1] == L'd' || InputString[1] == L'D')) &&
+           (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS))) {
+        TempFileInfo = FileInfo;
+        FileInfo = (EFI_SHELL_FILE_INFO *) RemoveEntryList (&FileInfo->Link);
+        InternalFreeShellFileInfoNode (TempFileInfo);
+      } else {
+        FileInfo = (EFI_SHELL_FILE_INFO *) GetNextNode (&FileList->Link, &FileInfo->Link);
+      }
+    }
+  }
+
+  if (FileList != NULL && !IsListEmpty (&FileList->Link)) {
+    Status = EFI_SUCCESS;
+  } else {
+    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList);
+    Status = EFI_NOT_FOUND;
+  }
+
+  FreePool (TabStr);
+
+  *TabCompletionList = FileList;
+  return Status;
+}
+
+/**
   File style interface for console (Read).
 
   This will return a single line of input from the console.
@@ -326,6 +454,7 @@ FileInterfaceStdInRead(
 {
   CHAR16              *CurrentString;
   BOOLEAN             Done;
+  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke
   UINTN               Column;         // Column of current cursor
   UINTN               Row;            // Row of current cursor
   UINTN               StartColumn;    // Column at the beginning of the line
@@ -334,7 +463,6 @@ FileInterfaceStdInRead(
   UINTN               StringLen;      // Total length of the line
   UINTN               StringCurPos;   // Line index corresponding to the cursor
   UINTN               MaxStr;         // Maximum possible line length
-  UINTN               Index;
   UINTN               TotalColumn;     // Num of columns in the console
   UINTN               TotalRow;       // Num of rows in the console
   UINTN               SkipLength;
@@ -348,18 +476,10 @@ FileInterfaceStdInRead(
   BOOLEAN             InScrolling;
   EFI_STATUS          Status;
   BOOLEAN             InTabScrolling; // Whether in TAB-completion state
-  EFI_SHELL_FILE_INFO *FoundFileList;
-  EFI_SHELL_FILE_INFO *TabLinePos;
-  EFI_SHELL_FILE_INFO *TempPos;
-  CHAR16              *TabStr;
-  CHAR16              *TabOutputStr;
-  BOOLEAN             InQuotationMode;
-  CHAR16              *TempStr;
-  UINTN               TabPos;         // Start index of the string to search for TAB completion.
-  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke
-//  UINTN               Count;
+  EFI_SHELL_FILE_INFO *TabCompleteList;
+  EFI_SHELL_FILE_INFO *TabCurrent;
   UINTN               EventIndex;
-  CONST CHAR16        *Cwd;
+  CHAR16              *TabOutputStr;
 
   //
   // If buffer is not large enough to hold a CHAR16, return minimum buffer size
@@ -380,24 +500,10 @@ FileInterfaceStdInRead(
   InScrolling       = FALSE;
   InTabScrolling    = FALSE;
   Status            = EFI_SUCCESS;
-  TabLinePos        = NULL;
-  FoundFileList     = NULL;
-  TempPos           = NULL;
-  TabPos            = 0;
+  TabOutputStr      = NULL;
   TabUpdatePos      = 0;
-
-  //
-  // Allocate buffers
-  //
-  TabStr            = AllocateZeroPool (*BufferSize);
-  if (TabStr == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-  TabOutputStr      = AllocateZeroPool (*BufferSize);
-  if (TabOutputStr == NULL) {
-    FreePool(TabStr);
-    return EFI_OUT_OF_RESOURCES;
-  }
+  TabCompleteList   = NULL;
+  TabCurrent        = NULL;
 
   //
   // Get the screen setting and the current cursor location
@@ -454,11 +560,11 @@ FileInterfaceStdInRead(
     // If we are quitting TAB scrolling...
     //
     if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) {
-        if (FoundFileList != NULL) {
-          ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
-          DEBUG_CODE(FoundFileList = NULL;);
-        }
-        InTabScrolling = FALSE;
+      if (TabCompleteList != NULL) {
+        ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);
+        DEBUG_CODE(TabCompleteList = NULL;);
+      }
+      InTabScrolling = FALSE;
     }
 
     switch (Key.UnicodeChar) {
@@ -491,95 +597,39 @@ FileInterfaceStdInRead(
       break;
 
     case CHAR_TAB:
-      //
-      // handle auto complete of file and directory names...
-      //
-      if (InTabScrolling) {
-        ASSERT(FoundFileList != NULL);
-        ASSERT(TabLinePos != NULL);
-        TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
-        if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {
-          TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
-        }
-      } else {
-        TabPos          = 0;
-        TabUpdatePos    = 0;
-        InQuotationMode = FALSE;
-        for (Index = 0; Index < StringLen; Index++) {
-          if (CurrentString[Index] == L'\"') {
-            InQuotationMode = (BOOLEAN)(!InQuotationMode);
-          }
-          if (CurrentString[Index] == L' ' && !InQuotationMode) {
-            TabPos = Index + 1;
-            TabUpdatePos = Index + 1;
-          }
-          if (CurrentString[Index] == L'\\') {
-            TabUpdatePos = Index + 1;
-          }
+      if (!InTabScrolling) {
+        TabCurrent = NULL;
+        //
+        // Initialize a tab complete operation.
+        //
+        Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize, &TabCompleteList, &TabUpdatePos);
+        if (!EFI_ERROR(Status)) {
+          InTabScrolling = TRUE;
         }
-        if (StrStr(CurrentString + TabPos, L":") == NULL) {
-          Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);
-          if (Cwd != NULL) {
-            StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), Cwd, (*BufferSize)/sizeof(CHAR16) - 1);
-            StrCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"\\");
-            if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {
-              TabStr[StrLen(TabStr)-1] = CHAR_NULL;
-            }
-            StrnCatS( TabStr, 
-                      (*BufferSize)/sizeof(CHAR16), 
-                      CurrentString + TabPos, 
-                      StringLen - TabPos
-                      );
-          } else {
-            *TabStr = CHAR_NULL;
-            StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, StringLen - TabPos);
-          }
+
+        //
+        // We do not set up the replacement.
+        // The next section will do that.
+        //
+      }
+
+      if (InTabScrolling) {
+        //
+        // We are in a tab complete operation.
+        // set up the next replacement.
+        //
+        ASSERT(TabCompleteList != NULL);
+        if (TabCurrent == NULL) {
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetFirstNode (&TabCompleteList->Link);
         } else {
-          StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, (*BufferSize)/sizeof(CHAR16) - 1);
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);
         }
-        StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"*", (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr));
-        FoundFileList = NULL;
-        Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);
-        for ( TempStr = CurrentString
-            ; *TempStr == L' '
-            ; TempStr++); // note the ';'... empty for loop
+
         //
-        // make sure we have a list before we do anything more...
+        // Skip over the empty list beginning node
         //
-        if (EFI_ERROR (Status) || FoundFileList == NULL) {
-          InTabScrolling = FALSE;
-          TabLinePos = NULL;
-          continue;
-        } else {
-          //
-          // enumerate through the list of files
-          //
-          for ( TempPos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))
-              ; !IsNull(&FoundFileList->Link, &TempPos->Link)
-              ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &(TempPos->Link))
-             ){
-            //
-            // If "cd" is typed, only directory name will be auto-complete filled
-            // in either case . and .. will be removed.
-            //
-            if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&
-                (TempStr[1] == L'd' || TempStr[1] == L'D')
-               ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)
-                ||(StrCmp(TempPos->FileName, L".") == 0)
-                ||(StrCmp(TempPos->FileName, L"..") == 0)
-               )) || ((StrCmp(TempPos->FileName, L".") == 0)
-                ||(StrCmp(TempPos->FileName, L"..") == 0))){
-                TabLinePos = TempPos;
-                TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos->Link))->BackLink);
-                InternalFreeShellFileInfoNode(TabLinePos);
-            }
-          }
-          if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {
-            TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList->Link);
-            InTabScrolling = TRUE;
-          } else {
-            ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
-          }
+        if (IsNull(&TabCompleteList->Link, &TabCurrent->Link)) {
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);
         }
       }
       break;
@@ -720,23 +770,31 @@ FileInterfaceStdInRead(
     // the next file or directory name
     //
     if (InTabScrolling) {
+      TabOutputStr = AllocateZeroPool (*BufferSize);
+      if (TabOutputStr == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+      }
+    }
+
+    if (InTabScrolling && TabOutputStr != NULL) {
+
       //
       // Adjust the column and row to the start of TAB-completion string.
       //
       Column = (StartColumn + TabUpdatePos) % TotalColumn;
       Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;
-      OutputLength = StrLen (TabLinePos->FileName);
+      OutputLength = StrLen (TabCurrent->FileName);
       //
       // if the output string contains  blank space, quotation marks L'\"'
       // should be added to the output.
       //
-      if (StrStr(TabLinePos->FileName, L" ") != NULL){
+      if (StrStr(TabCurrent->FileName, L" ") != NULL){
         TabOutputStr[0] = L'\"';
-        CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
+        CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength * sizeof (CHAR16));
         TabOutputStr[OutputLength + 1] = L'\"';
         TabOutputStr[OutputLength + 2] = CHAR_NULL;
       } else {
-        CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
+        CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength * sizeof (CHAR16));
         TabOutputStr[OutputLength] = CHAR_NULL;
       }
       OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;
@@ -747,6 +805,8 @@ FileInterfaceStdInRead(
       if (StringLen > TabUpdatePos + OutputLength) {
         Delete = StringLen - TabUpdatePos - OutputLength;
       }
+
+      FreePool(TabOutputStr);
     }
 
     //
@@ -850,8 +910,6 @@ FileInterfaceStdInRead(
     AddLineToCommandHistory(CurrentString);
   }
 
-  FreePool (TabStr);
-  FreePool (TabOutputStr);
   //
   // Return the data to the caller
   //
@@ -861,10 +919,10 @@ FileInterfaceStdInRead(
   // if this was used it should be deallocated by now...
   // prevent memory leaks...
   //
-  if (FoundFileList != NULL) {
-    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
+  if (TabCompleteList != NULL) {
+    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);
   }
-  ASSERT(FoundFileList == NULL);
+  ASSERT(TabCompleteList == NULL);
 
   return Status;
 }
-- 
2.9.0.windows.1



^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0: when typing fs0:<TAB>
  2016-08-09  5:43 [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0: when typing fs0:<TAB> Ruiyu Ni
@ 2016-08-09  5:44 ` Ni, Ruiyu
  2016-08-09 15:08 ` Shah, Tapan
  1 sibling, 0 replies; 3+ messages in thread
From: Ni, Ruiyu @ 2016-08-09  5:44 UTC (permalink / raw)
  To: Ni, Ruiyu, edk2-devel@lists.01.org; +Cc: Carsey, Jaben

This v2 patch fixed VS2012 build failure.

Thanks/Ray

> -----Original Message-----
> From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of
> Ruiyu Ni
> Sent: Tuesday, August 9, 2016 1:44 PM
> To: edk2-devel@lists.01.org
> Cc: Carsey, Jaben <jaben.carsey@intel.com>
> Subject: [edk2] [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0:
> when typing fs0:<TAB>
> 
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
> Cc: Jaben Carsey <jaben.carsey@intel.com>
> ---
>  ShellPkg/Application/Shell/FileHandleWrappers.c | 312 ++++++++++++++---
> -------
>  1 file changed, 185 insertions(+), 127 deletions(-)
> 
> diff --git a/ShellPkg/Application/Shell/FileHandleWrappers.c
> b/ShellPkg/Application/Shell/FileHandleWrappers.c
> index f6a82ee..0091934 100644
> --- a/ShellPkg/Application/Shell/FileHandleWrappers.c
> +++ b/ShellPkg/Application/Shell/FileHandleWrappers.c
> @@ -293,6 +293,134 @@ FileInterfaceNulWrite(  }
> 
>  /**
> +  Create the TAB completion list.
> +
> +  @param[in]  InputString       The command line to expand.
> +  @param[in]  StringLen         Length of the command line.
> +  @param[in]  BufferSize        Buffer size.
> +  @param[out] TabCompletionList Return the TAB completion list.
> +  @param[out] TabUpdatePos      Return the TAB update position.
> +**/
> +EFI_STATUS
> +EFIAPI
> +CreateTabCompletionList (
> +  IN CONST CHAR16             *InputString,
> +  IN CONST UINTN              StringLen,
> +  IN CONST UINTN              BufferSize,
> +  IN OUT EFI_SHELL_FILE_INFO  **TabCompletionList,
> +  IN OUT   UINTN              *TabUpdatePos
> +)
> +{
> +  BOOLEAN             InQuotation;
> +  UINTN               TabPos;
> +  UINTN               Index;
> +  CONST CHAR16        *Cwd;
> +  EFI_STATUS          Status;
> +  CHAR16              *TabStr;
> +  EFI_SHELL_FILE_INFO *FileList;
> +  EFI_SHELL_FILE_INFO *FileInfo;
> +  EFI_SHELL_FILE_INFO *TempFileInfo;
> +
> +  //
> +  // Allocate buffers
> +  //
> +  TabStr = AllocateZeroPool (BufferSize);  if (TabStr == NULL) {
> +    return EFI_OUT_OF_RESOURCES;
> +  }
> +
> +  //
> +  // handle auto complete of file and directory names...
> +  // E.g.: cd fs0:\EFI\Bo<TAB>
> +  //          ^        ^
> +  //          TabPos   TabUpdatePos
> +  //
> +  TabPos        = 0;
> +  *TabUpdatePos = 0;
> +  FileList      = NULL;
> +  InQuotation   = FALSE;
> +  for (Index = 0; Index < StringLen; Index++) {
> +    switch (InputString[Index]) {
> +    case L'\"':
> +      InQuotation = (BOOLEAN) (!InQuotation);
> +      break;
> +
> +    case L' ':
> +      if (!InQuotation) {
> +        TabPos = Index + 1;
> +        *TabUpdatePos = TabPos;
> +      }
> +      break;
> +
> +    case L':':
> +      //
> +      // handle the case "fs0:<TAB>"
> +      // Update the TabUpdatePos as well.
> +      //
> +    case L'\\':
> +      *TabUpdatePos = Index + 1;
> +      break;
> +
> +    default:
> +      break;
> +    }
> +  }
> +
> +  if (StrStr (InputString + TabPos, L":") == NULL) {
> +    //
> +    // If file path doesn't contain ":", it's a path relative to current directory.
> +    //
> +    Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL);
> +    if (Cwd != NULL) {
> +      StrnCpyS (TabStr, (BufferSize) / sizeof (CHAR16), Cwd, (BufferSize) /
> sizeof (CHAR16) - 1);
> +      if (InputString[TabPos] != L'\\') {
> +        StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\");
> +      }
> +    }
> +  }
> +  StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString +
> + TabPos, StringLen - TabPos);  StrnCatS (TabStr, (BufferSize) / sizeof
> + (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr));
> + Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr,
> + &FileList);
> +
> +  //
> +  // Filter out the non-directory for "CD" command  // Filter "." and
> + ".." for all  //  if (!EFI_ERROR (Status) && FileList != NULL) {
> +    //
> +    // Skip the spaces in the beginning
> +    //
> +    while (*InputString == L' ') {
> +      InputString++;
> +    }
> +
> +    for (FileInfo = (EFI_SHELL_FILE_INFO *) GetFirstNode (&FileList-
> >Link); !IsNull (&FileList->Link, &FileInfo->Link); ) {
> +      if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo-
> >FileName, L"..") == 0)) ||
> +          (((InputString[0] == L'c' || InputString[0] == L'C') && (InputString[1] ==
> L'd' || InputString[1] == L'D')) &&
> +           (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS))) {
> +        TempFileInfo = FileInfo;
> +        FileInfo = (EFI_SHELL_FILE_INFO *) RemoveEntryList (&FileInfo->Link);
> +        InternalFreeShellFileInfoNode (TempFileInfo);
> +      } else {
> +        FileInfo = (EFI_SHELL_FILE_INFO *) GetNextNode (&FileList->Link,
> &FileInfo->Link);
> +      }
> +    }
> +  }
> +
> +  if (FileList != NULL && !IsListEmpty (&FileList->Link)) {
> +    Status = EFI_SUCCESS;
> +  } else {
> +    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList);
> +    Status = EFI_NOT_FOUND;
> +  }
> +
> +  FreePool (TabStr);
> +
> +  *TabCompletionList = FileList;
> +  return Status;
> +}
> +
> +/**
>    File style interface for console (Read).
> 
>    This will return a single line of input from the console.
> @@ -326,6 +454,7 @@ FileInterfaceStdInRead(  {
>    CHAR16              *CurrentString;
>    BOOLEAN             Done;
> +  UINTN               TabUpdatePos;   // Start index of the string updated by TAB
> stroke
>    UINTN               Column;         // Column of current cursor
>    UINTN               Row;            // Row of current cursor
>    UINTN               StartColumn;    // Column at the beginning of the line
> @@ -334,7 +463,6 @@ FileInterfaceStdInRead(
>    UINTN               StringLen;      // Total length of the line
>    UINTN               StringCurPos;   // Line index corresponding to the cursor
>    UINTN               MaxStr;         // Maximum possible line length
> -  UINTN               Index;
>    UINTN               TotalColumn;     // Num of columns in the console
>    UINTN               TotalRow;       // Num of rows in the console
>    UINTN               SkipLength;
> @@ -348,18 +476,10 @@ FileInterfaceStdInRead(
>    BOOLEAN             InScrolling;
>    EFI_STATUS          Status;
>    BOOLEAN             InTabScrolling; // Whether in TAB-completion state
> -  EFI_SHELL_FILE_INFO *FoundFileList;
> -  EFI_SHELL_FILE_INFO *TabLinePos;
> -  EFI_SHELL_FILE_INFO *TempPos;
> -  CHAR16              *TabStr;
> -  CHAR16              *TabOutputStr;
> -  BOOLEAN             InQuotationMode;
> -  CHAR16              *TempStr;
> -  UINTN               TabPos;         // Start index of the string to search for TAB
> completion.
> -  UINTN               TabUpdatePos;   // Start index of the string updated by TAB
> stroke
> -//  UINTN               Count;
> +  EFI_SHELL_FILE_INFO *TabCompleteList;  EFI_SHELL_FILE_INFO
> + *TabCurrent;
>    UINTN               EventIndex;
> -  CONST CHAR16        *Cwd;
> +  CHAR16              *TabOutputStr;
> 
>    //
>    // If buffer is not large enough to hold a CHAR16, return minimum buffer
> size @@ -380,24 +500,10 @@ FileInterfaceStdInRead(
>    InScrolling       = FALSE;
>    InTabScrolling    = FALSE;
>    Status            = EFI_SUCCESS;
> -  TabLinePos        = NULL;
> -  FoundFileList     = NULL;
> -  TempPos           = NULL;
> -  TabPos            = 0;
> +  TabOutputStr      = NULL;
>    TabUpdatePos      = 0;
> -
> -  //
> -  // Allocate buffers
> -  //
> -  TabStr            = AllocateZeroPool (*BufferSize);
> -  if (TabStr == NULL) {
> -    return EFI_OUT_OF_RESOURCES;
> -  }
> -  TabOutputStr      = AllocateZeroPool (*BufferSize);
> -  if (TabOutputStr == NULL) {
> -    FreePool(TabStr);
> -    return EFI_OUT_OF_RESOURCES;
> -  }
> +  TabCompleteList   = NULL;
> +  TabCurrent        = NULL;
> 
>    //
>    // Get the screen setting and the current cursor location @@ -454,11
> +560,11 @@ FileInterfaceStdInRead(
>      // If we are quitting TAB scrolling...
>      //
>      if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) {
> -        if (FoundFileList != NULL) {
> -          ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
> -          DEBUG_CODE(FoundFileList = NULL;);
> -        }
> -        InTabScrolling = FALSE;
> +      if (TabCompleteList != NULL) {
> +        ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);
> +        DEBUG_CODE(TabCompleteList = NULL;);
> +      }
> +      InTabScrolling = FALSE;
>      }
> 
>      switch (Key.UnicodeChar) {
> @@ -491,95 +597,39 @@ FileInterfaceStdInRead(
>        break;
> 
>      case CHAR_TAB:
> -      //
> -      // handle auto complete of file and directory names...
> -      //
> -      if (InTabScrolling) {
> -        ASSERT(FoundFileList != NULL);
> -        ASSERT(TabLinePos != NULL);
> -        TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList-
> >Link), &TabLinePos->Link);
> -        if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {
> -          TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList-
> >Link), &TabLinePos->Link);
> -        }
> -      } else {
> -        TabPos          = 0;
> -        TabUpdatePos    = 0;
> -        InQuotationMode = FALSE;
> -        for (Index = 0; Index < StringLen; Index++) {
> -          if (CurrentString[Index] == L'\"') {
> -            InQuotationMode = (BOOLEAN)(!InQuotationMode);
> -          }
> -          if (CurrentString[Index] == L' ' && !InQuotationMode) {
> -            TabPos = Index + 1;
> -            TabUpdatePos = Index + 1;
> -          }
> -          if (CurrentString[Index] == L'\\') {
> -            TabUpdatePos = Index + 1;
> -          }
> +      if (!InTabScrolling) {
> +        TabCurrent = NULL;
> +        //
> +        // Initialize a tab complete operation.
> +        //
> +        Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize,
> &TabCompleteList, &TabUpdatePos);
> +        if (!EFI_ERROR(Status)) {
> +          InTabScrolling = TRUE;
>          }
> -        if (StrStr(CurrentString + TabPos, L":") == NULL) {
> -          Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);
> -          if (Cwd != NULL) {
> -            StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), Cwd,
> (*BufferSize)/sizeof(CHAR16) - 1);
> -            StrCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"\\");
> -            if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) ==
> L'\\' ) {
> -              TabStr[StrLen(TabStr)-1] = CHAR_NULL;
> -            }
> -            StrnCatS( TabStr,
> -                      (*BufferSize)/sizeof(CHAR16),
> -                      CurrentString + TabPos,
> -                      StringLen - TabPos
> -                      );
> -          } else {
> -            *TabStr = CHAR_NULL;
> -            StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString +
> TabPos, StringLen - TabPos);
> -          }
> +
> +        //
> +        // We do not set up the replacement.
> +        // The next section will do that.
> +        //
> +      }
> +
> +      if (InTabScrolling) {
> +        //
> +        // We are in a tab complete operation.
> +        // set up the next replacement.
> +        //
> +        ASSERT(TabCompleteList != NULL);
> +        if (TabCurrent == NULL) {
> +          TabCurrent = (EFI_SHELL_FILE_INFO*) GetFirstNode
> + (&TabCompleteList->Link);
>          } else {
> -          StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos,
> (*BufferSize)/sizeof(CHAR16) - 1);
> +          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode
> + (&TabCompleteList->Link, &TabCurrent->Link);
>          }
> -        StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"*",
> (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr));
> -        FoundFileList = NULL;
> -        Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr,
> &FoundFileList);
> -        for ( TempStr = CurrentString
> -            ; *TempStr == L' '
> -            ; TempStr++); // note the ';'... empty for loop
> +
>          //
> -        // make sure we have a list before we do anything more...
> +        // Skip over the empty list beginning node
>          //
> -        if (EFI_ERROR (Status) || FoundFileList == NULL) {
> -          InTabScrolling = FALSE;
> -          TabLinePos = NULL;
> -          continue;
> -        } else {
> -          //
> -          // enumerate through the list of files
> -          //
> -          for ( TempPos =
> (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))
> -              ; !IsNull(&FoundFileList->Link, &TempPos->Link)
> -              ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList-
> >Link), &(TempPos->Link))
> -             ){
> -            //
> -            // If "cd" is typed, only directory name will be auto-complete filled
> -            // in either case . and .. will be removed.
> -            //
> -            if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&
> -                (TempStr[1] == L'd' || TempStr[1] == L'D')
> -               ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)
> -                ||(StrCmp(TempPos->FileName, L".") == 0)
> -                ||(StrCmp(TempPos->FileName, L"..") == 0)
> -               )) || ((StrCmp(TempPos->FileName, L".") == 0)
> -                ||(StrCmp(TempPos->FileName, L"..") == 0))){
> -                TabLinePos = TempPos;
> -                TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos-
> >Link))->BackLink);
> -                InternalFreeShellFileInfoNode(TabLinePos);
> -            }
> -          }
> -          if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {
> -            TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList-
> >Link);
> -            InTabScrolling = TRUE;
> -          } else {
> -            ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
> -          }
> +        if (IsNull(&TabCompleteList->Link, &TabCurrent->Link)) {
> +          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode
> + (&TabCompleteList->Link, &TabCurrent->Link);
>          }
>        }
>        break;
> @@ -720,23 +770,31 @@ FileInterfaceStdInRead(
>      // the next file or directory name
>      //
>      if (InTabScrolling) {
> +      TabOutputStr = AllocateZeroPool (*BufferSize);
> +      if (TabOutputStr == NULL) {
> +        Status = EFI_OUT_OF_RESOURCES;
> +      }
> +    }
> +
> +    if (InTabScrolling && TabOutputStr != NULL) {
> +
>        //
>        // Adjust the column and row to the start of TAB-completion string.
>        //
>        Column = (StartColumn + TabUpdatePos) % TotalColumn;
>        Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn +
> TabUpdatePos) / TotalColumn;
> -      OutputLength = StrLen (TabLinePos->FileName);
> +      OutputLength = StrLen (TabCurrent->FileName);
>        //
>        // if the output string contains  blank space, quotation marks L'\"'
>        // should be added to the output.
>        //
> -      if (StrStr(TabLinePos->FileName, L" ") != NULL){
> +      if (StrStr(TabCurrent->FileName, L" ") != NULL){
>          TabOutputStr[0] = L'\"';
> -        CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength *
> sizeof (CHAR16));
> +        CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength *
> + sizeof (CHAR16));
>          TabOutputStr[OutputLength + 1] = L'\"';
>          TabOutputStr[OutputLength + 2] = CHAR_NULL;
>        } else {
> -        CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength *
> sizeof (CHAR16));
> +        CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength *
> + sizeof (CHAR16));
>          TabOutputStr[OutputLength] = CHAR_NULL;
>        }
>        OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen
> (TabOutputStr) : MaxStr - 1; @@ -747,6 +805,8 @@ FileInterfaceStdInRead(
>        if (StringLen > TabUpdatePos + OutputLength) {
>          Delete = StringLen - TabUpdatePos - OutputLength;
>        }
> +
> +      FreePool(TabOutputStr);
>      }
> 
>      //
> @@ -850,8 +910,6 @@ FileInterfaceStdInRead(
>      AddLineToCommandHistory(CurrentString);
>    }
> 
> -  FreePool (TabStr);
> -  FreePool (TabOutputStr);
>    //
>    // Return the data to the caller
>    //
> @@ -861,10 +919,10 @@ FileInterfaceStdInRead(
>    // if this was used it should be deallocated by now...
>    // prevent memory leaks...
>    //
> -  if (FoundFileList != NULL) {
> -    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
> +  if (TabCompleteList != NULL) {
> +    ShellInfoObject.NewEfiShellProtocol->FreeFileList
> + (&TabCompleteList);
>    }
> -  ASSERT(FoundFileList == NULL);
> +  ASSERT(TabCompleteList == NULL);
> 
>    return Status;
>  }
> --
> 2.9.0.windows.1
> 
> _______________________________________________
> edk2-devel mailing list
> edk2-devel@lists.01.org
> https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0: when typing fs0:<TAB>
  2016-08-09  5:43 [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0: when typing fs0:<TAB> Ruiyu Ni
  2016-08-09  5:44 ` Ni, Ruiyu
@ 2016-08-09 15:08 ` Shah, Tapan
  1 sibling, 0 replies; 3+ messages in thread
From: Shah, Tapan @ 2016-08-09 15:08 UTC (permalink / raw)
  To: Ruiyu Ni, edk2-devel@lists.01.org; +Cc: Jaben Carsey

Series Reviewed By: Tapan Shah <tapandshah@hpe.com>

-----Original Message-----
From: edk2-devel [mailto:edk2-devel-bounces@lists.01.org] On Behalf Of Ruiyu Ni
Sent: Tuesday, August 09, 2016 12:44 AM
To: edk2-devel@lists.01.org
Cc: Jaben Carsey <jaben.carsey@intel.com>
Subject: [edk2] [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0: when typing fs0:<TAB>

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Cc: Jaben Carsey <jaben.carsey@intel.com>
---
 ShellPkg/Application/Shell/FileHandleWrappers.c | 312 ++++++++++++++----------
 1 file changed, 185 insertions(+), 127 deletions(-)

diff --git a/ShellPkg/Application/Shell/FileHandleWrappers.c b/ShellPkg/Application/Shell/FileHandleWrappers.c
index f6a82ee..0091934 100644
--- a/ShellPkg/Application/Shell/FileHandleWrappers.c
+++ b/ShellPkg/Application/Shell/FileHandleWrappers.c
@@ -293,6 +293,134 @@ FileInterfaceNulWrite(
 }
 
 /**
+  Create the TAB completion list.
+
+  @param[in]  InputString       The command line to expand.
+  @param[in]  StringLen         Length of the command line.
+  @param[in]  BufferSize        Buffer size.
+  @param[out] TabCompletionList Return the TAB completion list.
+  @param[out] TabUpdatePos      Return the TAB update position.
+**/
+EFI_STATUS
+EFIAPI
+CreateTabCompletionList (
+  IN CONST CHAR16             *InputString,
+  IN CONST UINTN              StringLen, 
+  IN CONST UINTN              BufferSize,
+  IN OUT EFI_SHELL_FILE_INFO  **TabCompletionList,
+  IN OUT   UINTN              *TabUpdatePos
+)
+{
+  BOOLEAN             InQuotation;
+  UINTN               TabPos;
+  UINTN               Index;
+  CONST CHAR16        *Cwd;
+  EFI_STATUS          Status;
+  CHAR16              *TabStr;
+  EFI_SHELL_FILE_INFO *FileList;
+  EFI_SHELL_FILE_INFO *FileInfo;
+  EFI_SHELL_FILE_INFO *TempFileInfo;
+
+  //
+  // Allocate buffers
+  //
+  TabStr = AllocateZeroPool (BufferSize);
+  if (TabStr == NULL) {
+    return EFI_OUT_OF_RESOURCES;
+  }
+
+  //
+  // handle auto complete of file and directory names...
+  // E.g.: cd fs0:\EFI\Bo<TAB>
+  //          ^        ^
+  //          TabPos   TabUpdatePos
+  //
+  TabPos        = 0;
+  *TabUpdatePos = 0;
+  FileList      = NULL;
+  InQuotation   = FALSE;
+  for (Index = 0; Index < StringLen; Index++) {
+    switch (InputString[Index]) {
+    case L'\"':
+      InQuotation = (BOOLEAN) (!InQuotation);
+      break;
+
+    case L' ':
+      if (!InQuotation) {
+        TabPos = Index + 1;
+        *TabUpdatePos = TabPos;
+      }
+      break;
+
+    case L':':
+      //
+      // handle the case "fs0:<TAB>"
+      // Update the TabUpdatePos as well.
+      //
+    case L'\\':
+      *TabUpdatePos = Index + 1;
+      break;
+
+    default:
+      break;
+    }
+  }
+
+  if (StrStr (InputString + TabPos, L":") == NULL) {
+    //
+    // If file path doesn't contain ":", it's a path relative to current directory.
+    //
+    Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir (NULL);
+    if (Cwd != NULL) {
+      StrnCpyS (TabStr, (BufferSize) / sizeof (CHAR16), Cwd, (BufferSize) / sizeof (CHAR16) - 1);
+      if (InputString[TabPos] != L'\\') {
+        StrCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"\\");
+      }
+    }
+  }
+  StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), InputString + TabPos, StringLen - TabPos);
+  StrnCatS (TabStr, (BufferSize) / sizeof (CHAR16), L"*", (BufferSize) / sizeof (CHAR16) - 1 - StrLen (TabStr));
+  Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FileList);
+
+  //
+  // Filter out the non-directory for "CD" command
+  // Filter "." and ".." for all
+  //
+  if (!EFI_ERROR (Status) && FileList != NULL) {
+    //
+    // Skip the spaces in the beginning
+    //
+    while (*InputString == L' ') {
+      InputString++;
+    }
+
+    for (FileInfo = (EFI_SHELL_FILE_INFO *) GetFirstNode (&FileList->Link); !IsNull (&FileList->Link, &FileInfo->Link); ) {
+      if (((StrCmp (FileInfo->FileName, L".") == 0) || (StrCmp (FileInfo->FileName, L"..") == 0)) ||
+          (((InputString[0] == L'c' || InputString[0] == L'C') && (InputString[1] == L'd' || InputString[1] == L'D')) &&
+           (ShellIsDirectory (FileInfo->FullName) != EFI_SUCCESS))) {
+        TempFileInfo = FileInfo;
+        FileInfo = (EFI_SHELL_FILE_INFO *) RemoveEntryList (&FileInfo->Link);
+        InternalFreeShellFileInfoNode (TempFileInfo);
+      } else {
+        FileInfo = (EFI_SHELL_FILE_INFO *) GetNextNode (&FileList->Link, &FileInfo->Link);
+      }
+    }
+  }
+
+  if (FileList != NULL && !IsListEmpty (&FileList->Link)) {
+    Status = EFI_SUCCESS;
+  } else {
+    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FileList);
+    Status = EFI_NOT_FOUND;
+  }
+
+  FreePool (TabStr);
+
+  *TabCompletionList = FileList;
+  return Status;
+}
+
+/**
   File style interface for console (Read).
 
   This will return a single line of input from the console.
@@ -326,6 +454,7 @@ FileInterfaceStdInRead(
 {
   CHAR16              *CurrentString;
   BOOLEAN             Done;
+  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke
   UINTN               Column;         // Column of current cursor
   UINTN               Row;            // Row of current cursor
   UINTN               StartColumn;    // Column at the beginning of the line
@@ -334,7 +463,6 @@ FileInterfaceStdInRead(
   UINTN               StringLen;      // Total length of the line
   UINTN               StringCurPos;   // Line index corresponding to the cursor
   UINTN               MaxStr;         // Maximum possible line length
-  UINTN               Index;
   UINTN               TotalColumn;     // Num of columns in the console
   UINTN               TotalRow;       // Num of rows in the console
   UINTN               SkipLength;
@@ -348,18 +476,10 @@ FileInterfaceStdInRead(
   BOOLEAN             InScrolling;
   EFI_STATUS          Status;
   BOOLEAN             InTabScrolling; // Whether in TAB-completion state
-  EFI_SHELL_FILE_INFO *FoundFileList;
-  EFI_SHELL_FILE_INFO *TabLinePos;
-  EFI_SHELL_FILE_INFO *TempPos;
-  CHAR16              *TabStr;
-  CHAR16              *TabOutputStr;
-  BOOLEAN             InQuotationMode;
-  CHAR16              *TempStr;
-  UINTN               TabPos;         // Start index of the string to search for TAB completion.
-  UINTN               TabUpdatePos;   // Start index of the string updated by TAB stroke
-//  UINTN               Count;
+  EFI_SHELL_FILE_INFO *TabCompleteList;
+  EFI_SHELL_FILE_INFO *TabCurrent;
   UINTN               EventIndex;
-  CONST CHAR16        *Cwd;
+  CHAR16              *TabOutputStr;
 
   //
   // If buffer is not large enough to hold a CHAR16, return minimum buffer size
@@ -380,24 +500,10 @@ FileInterfaceStdInRead(
   InScrolling       = FALSE;
   InTabScrolling    = FALSE;
   Status            = EFI_SUCCESS;
-  TabLinePos        = NULL;
-  FoundFileList     = NULL;
-  TempPos           = NULL;
-  TabPos            = 0;
+  TabOutputStr      = NULL;
   TabUpdatePos      = 0;
-
-  //
-  // Allocate buffers
-  //
-  TabStr            = AllocateZeroPool (*BufferSize);
-  if (TabStr == NULL) {
-    return EFI_OUT_OF_RESOURCES;
-  }
-  TabOutputStr      = AllocateZeroPool (*BufferSize);
-  if (TabOutputStr == NULL) {
-    FreePool(TabStr);
-    return EFI_OUT_OF_RESOURCES;
-  }
+  TabCompleteList   = NULL;
+  TabCurrent        = NULL;
 
   //
   // Get the screen setting and the current cursor location
@@ -454,11 +560,11 @@ FileInterfaceStdInRead(
     // If we are quitting TAB scrolling...
     //
     if (InTabScrolling && Key.UnicodeChar != CHAR_TAB) {
-        if (FoundFileList != NULL) {
-          ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
-          DEBUG_CODE(FoundFileList = NULL;);
-        }
-        InTabScrolling = FALSE;
+      if (TabCompleteList != NULL) {
+        ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);
+        DEBUG_CODE(TabCompleteList = NULL;);
+      }
+      InTabScrolling = FALSE;
     }
 
     switch (Key.UnicodeChar) {
@@ -491,95 +597,39 @@ FileInterfaceStdInRead(
       break;
 
     case CHAR_TAB:
-      //
-      // handle auto complete of file and directory names...
-      //
-      if (InTabScrolling) {
-        ASSERT(FoundFileList != NULL);
-        ASSERT(TabLinePos != NULL);
-        TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
-        if (IsNull(&(FoundFileList->Link), &TabLinePos->Link)) {
-          TabLinePos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &TabLinePos->Link);
-        }
-      } else {
-        TabPos          = 0;
-        TabUpdatePos    = 0;
-        InQuotationMode = FALSE;
-        for (Index = 0; Index < StringLen; Index++) {
-          if (CurrentString[Index] == L'\"') {
-            InQuotationMode = (BOOLEAN)(!InQuotationMode);
-          }
-          if (CurrentString[Index] == L' ' && !InQuotationMode) {
-            TabPos = Index + 1;
-            TabUpdatePos = Index + 1;
-          }
-          if (CurrentString[Index] == L'\\') {
-            TabUpdatePos = Index + 1;
-          }
+      if (!InTabScrolling) {
+        TabCurrent = NULL;
+        //
+        // Initialize a tab complete operation.
+        //
+        Status = CreateTabCompletionList (CurrentString, StringLen, *BufferSize, &TabCompleteList, &TabUpdatePos);
+        if (!EFI_ERROR(Status)) {
+          InTabScrolling = TRUE;
         }
-        if (StrStr(CurrentString + TabPos, L":") == NULL) {
-          Cwd = ShellInfoObject.NewEfiShellProtocol->GetCurDir(NULL);
-          if (Cwd != NULL) {
-            StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), Cwd, (*BufferSize)/sizeof(CHAR16) - 1);
-            StrCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"\\");
-            if (TabStr[StrLen(TabStr)-1] == L'\\' && *(CurrentString + TabPos) == L'\\' ) {
-              TabStr[StrLen(TabStr)-1] = CHAR_NULL;
-            }
-            StrnCatS( TabStr, 
-                      (*BufferSize)/sizeof(CHAR16), 
-                      CurrentString + TabPos, 
-                      StringLen - TabPos
-                      );
-          } else {
-            *TabStr = CHAR_NULL;
-            StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, StringLen - TabPos);
-          }
+
+        //
+        // We do not set up the replacement.
+        // The next section will do that.
+        //
+      }
+
+      if (InTabScrolling) {
+        //
+        // We are in a tab complete operation.
+        // set up the next replacement.
+        //
+        ASSERT(TabCompleteList != NULL);
+        if (TabCurrent == NULL) {
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetFirstNode (&TabCompleteList->Link);
         } else {
-          StrnCpyS(TabStr, (*BufferSize)/sizeof(CHAR16), CurrentString + TabPos, (*BufferSize)/sizeof(CHAR16) - 1);
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);
         }
-        StrnCatS(TabStr, (*BufferSize)/sizeof(CHAR16), L"*", (*BufferSize)/sizeof(CHAR16) - 1 - StrLen(TabStr));
-        FoundFileList = NULL;
-        Status  = ShellInfoObject.NewEfiShellProtocol->FindFiles(TabStr, &FoundFileList);
-        for ( TempStr = CurrentString
-            ; *TempStr == L' '
-            ; TempStr++); // note the ';'... empty for loop
+
         //
-        // make sure we have a list before we do anything more...
+        // Skip over the empty list beginning node
         //
-        if (EFI_ERROR (Status) || FoundFileList == NULL) {
-          InTabScrolling = FALSE;
-          TabLinePos = NULL;
-          continue;
-        } else {
-          //
-          // enumerate through the list of files
-          //
-          for ( TempPos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&(FoundFileList->Link))
-              ; !IsNull(&FoundFileList->Link, &TempPos->Link)
-              ; TempPos = (EFI_SHELL_FILE_INFO*)GetNextNode(&(FoundFileList->Link), &(TempPos->Link))
-             ){
-            //
-            // If "cd" is typed, only directory name will be auto-complete filled
-            // in either case . and .. will be removed.
-            //
-            if ((((TempStr[0] == L'c' || TempStr[0] == L'C') &&
-                (TempStr[1] == L'd' || TempStr[1] == L'D')
-               ) && ((ShellIsDirectory(TempPos->FullName) != EFI_SUCCESS)
-                ||(StrCmp(TempPos->FileName, L".") == 0)
-                ||(StrCmp(TempPos->FileName, L"..") == 0)
-               )) || ((StrCmp(TempPos->FileName, L".") == 0)
-                ||(StrCmp(TempPos->FileName, L"..") == 0))){
-                TabLinePos = TempPos;
-                TempPos = (EFI_SHELL_FILE_INFO*)(RemoveEntryList(&(TempPos->Link))->BackLink);
-                InternalFreeShellFileInfoNode(TabLinePos);
-            }
-          }
-          if (FoundFileList != NULL && !IsListEmpty(&FoundFileList->Link)) {
-            TabLinePos = (EFI_SHELL_FILE_INFO*)GetFirstNode(&FoundFileList->Link);
-            InTabScrolling = TRUE;
-          } else {
-            ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
-          }
+        if (IsNull(&TabCompleteList->Link, &TabCurrent->Link)) {
+          TabCurrent = (EFI_SHELL_FILE_INFO*) GetNextNode (&TabCompleteList->Link, &TabCurrent->Link);
         }
       }
       break;
@@ -720,23 +770,31 @@ FileInterfaceStdInRead(
     // the next file or directory name
     //
     if (InTabScrolling) {
+      TabOutputStr = AllocateZeroPool (*BufferSize);
+      if (TabOutputStr == NULL) {
+        Status = EFI_OUT_OF_RESOURCES;
+      }
+    }
+
+    if (InTabScrolling && TabOutputStr != NULL) {
+
       //
       // Adjust the column and row to the start of TAB-completion string.
       //
       Column = (StartColumn + TabUpdatePos) % TotalColumn;
       Row -= (StartColumn + StringCurPos) / TotalColumn - (StartColumn + TabUpdatePos) / TotalColumn;
-      OutputLength = StrLen (TabLinePos->FileName);
+      OutputLength = StrLen (TabCurrent->FileName);
       //
       // if the output string contains  blank space, quotation marks L'\"'
       // should be added to the output.
       //
-      if (StrStr(TabLinePos->FileName, L" ") != NULL){
+      if (StrStr(TabCurrent->FileName, L" ") != NULL){
         TabOutputStr[0] = L'\"';
-        CopyMem (TabOutputStr + 1, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
+        CopyMem (TabOutputStr + 1, TabCurrent->FileName, OutputLength * sizeof (CHAR16));
         TabOutputStr[OutputLength + 1] = L'\"';
         TabOutputStr[OutputLength + 2] = CHAR_NULL;
       } else {
-        CopyMem (TabOutputStr, TabLinePos->FileName, OutputLength * sizeof (CHAR16));
+        CopyMem (TabOutputStr, TabCurrent->FileName, OutputLength * sizeof (CHAR16));
         TabOutputStr[OutputLength] = CHAR_NULL;
       }
       OutputLength = StrLen (TabOutputStr) < MaxStr - 1 ? StrLen (TabOutputStr) : MaxStr - 1;
@@ -747,6 +805,8 @@ FileInterfaceStdInRead(
       if (StringLen > TabUpdatePos + OutputLength) {
         Delete = StringLen - TabUpdatePos - OutputLength;
       }
+
+      FreePool(TabOutputStr);
     }
 
     //
@@ -850,8 +910,6 @@ FileInterfaceStdInRead(
     AddLineToCommandHistory(CurrentString);
   }
 
-  FreePool (TabStr);
-  FreePool (TabOutputStr);
   //
   // Return the data to the caller
   //
@@ -861,10 +919,10 @@ FileInterfaceStdInRead(
   // if this was used it should be deallocated by now...
   // prevent memory leaks...
   //
-  if (FoundFileList != NULL) {
-    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&FoundFileList);
+  if (TabCompleteList != NULL) {
+    ShellInfoObject.NewEfiShellProtocol->FreeFileList (&TabCompleteList);
   }
-  ASSERT(FoundFileList == NULL);
+  ASSERT(TabCompleteList == NULL);
 
   return Status;
 }
-- 
2.9.0.windows.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel


^ permalink raw reply related	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2016-08-09 15:08 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2016-08-09  5:43 [PATCH v2 1/6] ShellPkg: TAB logic incorrectly chops out fs0: when typing fs0:<TAB> Ruiyu Ni
2016-08-09  5:44 ` Ni, Ruiyu
2016-08-09 15:08 ` Shah, Tapan

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox