]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/ShellProtocol.c
fixes for NULL verification.
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellProtocol.c
index 27488ab62ee238aaabc2a3a4c8b5f060076c72f7..19759cbb2bbbf5194a887f782b759818d9d7768d 100644 (file)
@@ -34,7 +34,7 @@ EfiShellClose (
   )\r
 {\r
   ShellFileHandleRemove(FileHandle);\r
-  return (FileHandleClose(FileHandle));\r
+  return (FileHandleClose(ConvertShellHandleToEfiFileProtocol(FileHandle)));\r
 }\r
 \r
 /**\r
@@ -386,6 +386,7 @@ EfiShellGetFilePathFromDevicePath(
   EFI_HANDLE                      MapHandle;\r
   EFI_STATUS                      Status;\r
   FILEPATH_DEVICE_PATH            *FilePath;\r
+  FILEPATH_DEVICE_PATH            *AlignedNode;\r
 \r
   PathForReturn = NULL;\r
   PathSize = 0;\r
@@ -436,7 +437,10 @@ EfiShellGetFilePathFromDevicePath(
           //\r
           ASSERT((PathForReturn == NULL && PathSize == 0) || (PathForReturn != NULL));\r
           PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, L"\\", 1);\r
-          PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, FilePath->PathName, 0);\r
+\r
+          AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePath), FilePath);\r
+          PathForReturn = StrnCatGrow(&PathForReturn, &PathSize, AlignedNode->PathName, 0);\r
+          FreePool(AlignedNode);\r
         }\r
       } // for loop of remaining nodes\r
     }\r
@@ -475,8 +479,12 @@ EfiShellGetDevicePathFromFilePath(
   EFI_HANDLE                      Handle;\r
   EFI_STATUS                      Status;\r
 \r
+  if (Path == NULL) {\r
+    return (NULL);\r
+  }\r
+\r
   MapName = NULL;\r
-  ASSERT(Path != NULL);\r
+  NewPath = NULL;\r
 \r
   if (StrStr(Path, L":") == NULL) {\r
     Cwd = EfiShellGetCurDir(NULL);\r
@@ -488,7 +496,7 @@ EfiShellGetDevicePathFromFilePath(
     NewPath = AllocateZeroPool(Size);\r
     ASSERT(NewPath != NULL);\r
     StrCpy(NewPath, Cwd);\r
-    if ((NewPath[0] == (CHAR16)L'\\') &&\r
+    if ((Path[0] == (CHAR16)L'\\') &&\r
         (NewPath[StrLen(NewPath)-1] == (CHAR16)L'\\')\r
        ) {\r
       ((CHAR16*)NewPath)[StrLen(NewPath)-1] = CHAR_NULL;\r
@@ -666,6 +674,9 @@ EfiShellGetDeviceName(
       }\r
       if (Language == NULL) {\r
         Lang = AllocatePool(AsciiStrSize(CompName2->SupportedLanguages));\r
+        if (Lang == NULL) {\r
+          return (EFI_OUT_OF_RESOURCES);\r
+        }\r
         AsciiStrCpy(Lang, CompName2->SupportedLanguages);\r
         TempChar = AsciiStrStr(Lang, ";");\r
         if (TempChar != NULL){\r
@@ -673,6 +684,9 @@ EfiShellGetDeviceName(
         }\r
       } else {\r
         Lang = AllocatePool(AsciiStrSize(Language));\r
+        if (Lang == NULL) {\r
+          return (EFI_OUT_OF_RESOURCES);\r
+        }\r
         AsciiStrCpy(Lang, Language);\r
       }\r
       Status = CompName2->GetControllerName(CompName2, DeviceHandle, NULL, Lang, &DeviceNameToReturn);\r
@@ -686,7 +700,7 @@ EfiShellGetDeviceName(
       FreePool(HandleList);\r
     }\r
     if (DeviceNameToReturn != NULL){\r
-      ASSERT(BestDeviceName == NULL);\r
+      ASSERT(BestDeviceName != NULL);\r
       StrnCatGrow(BestDeviceName, NULL, DeviceNameToReturn, 0);\r
       return (EFI_SUCCESS);\r
     }\r
@@ -797,6 +811,7 @@ EfiShellOpenRootByHandle(
                                 could not be opened.\r
   @retval EFI_VOLUME_CORRUPTED  The data structures in the volume were corrupted.\r
   @retval EFI_DEVICE_ERROR      The device had an error\r
+  @retval EFI_INVALID_PARAMETER FileHandle is NULL.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -808,6 +823,10 @@ EfiShellOpenRoot(
   EFI_STATUS Status;\r
   EFI_HANDLE Handle;\r
 \r
+  if (FileHandle == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
   //\r
   // find the handle of the device with that device handle and the file system\r
   //\r
@@ -870,109 +889,122 @@ InternalOpenFileDevicePath(
   EFI_FILE_PROTOCOL               *Handle1;\r
   EFI_FILE_PROTOCOL               *Handle2;\r
   EFI_DEVICE_PATH_PROTOCOL        *DpCopy;\r
+  FILEPATH_DEVICE_PATH            *AlignedNode;\r
 \r
-  ASSERT(FileHandle != NULL);\r
-  *FileHandle = NULL;\r
-  Handle1     = NULL;\r
-  DpCopy      = DevicePath;\r
+  if (FileHandle == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+  *FileHandle   = NULL;\r
+  Handle1       = NULL;\r
+  Handle2       = NULL;\r
+  Handle        = NULL;\r
+  DpCopy        = DevicePath;\r
+  ShellHandle   = NULL;\r
+  FilePathNode  = NULL;\r
+  AlignedNode   = NULL;\r
 \r
   Status = EfiShellOpenRoot(DevicePath, &ShellHandle);\r
 \r
   if (!EFI_ERROR(Status)) {\r
     Handle1 = ConvertShellHandleToEfiFileProtocol(ShellHandle);\r
-    //\r
-    // chop off the begining part before the file system part...\r
-    //\r
-    ///@todo BlockIo?\r
-    Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,\r
-                                   &DevicePath,\r
-                                   &Handle);\r
-      if (!EFI_ERROR(Status)) {\r
+    if (Handle1 != NULL) {\r
       //\r
-      // To access as a file system, the file path should only\r
-      // contain file path components.  Follow the file path nodes\r
-      // and find the target file\r
+      // chop off the begining part before the file system part...\r
       //\r
-      for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath\r
-          ; !IsDevicePathEnd (&FilePathNode->Header)\r
-          ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)\r
-         ){\r
-        //\r
-        // For file system access each node should be a file path component\r
-        //\r
-        if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
-            DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP\r
-           ) {\r
-          Status = EFI_UNSUPPORTED;\r
-          break;\r
-        }\r
-\r
-        //\r
-        // Open this file path node\r
-        //\r
-        Handle2 = Handle1;\r
-        Handle1 = NULL;\r
-\r
+      ///@todo BlockIo?\r
+      Status = gBS->LocateDevicePath(&gEfiSimpleFileSystemProtocolGuid,\r
+                                     &DevicePath,\r
+                                     &Handle);\r
+        if (!EFI_ERROR(Status)) {\r
         //\r
-        // if this is the last node in the DevicePath always create (if that was requested).\r
+        // To access as a file system, the file path should only\r
+        // contain file path components.  Follow the file path nodes\r
+        // and find the target file\r
         //\r
-        if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) {\r
-          Status = Handle2->Open (\r
-                                Handle2,\r
-                                &Handle1,\r
-                                FilePathNode->PathName,\r
-                                OpenMode,\r
-                                Attributes\r
-                               );\r
-        } else {\r
-\r
+        for ( FilePathNode = (FILEPATH_DEVICE_PATH *)DevicePath\r
+            ; !IsDevicePathEnd (&FilePathNode->Header)\r
+            ; FilePathNode = (FILEPATH_DEVICE_PATH *) NextDevicePathNode (&FilePathNode->Header)\r
+           ){\r
+          SHELL_FREE_NON_NULL(AlignedNode);\r
+          AlignedNode = AllocateCopyPool (DevicePathNodeLength(FilePathNode), FilePathNode);\r
           //\r
-          //  This is not the last node and we dont want to 'create' existing\r
-          //  directory entries...\r
+          // For file system access each node should be a file path component\r
           //\r
+          if (DevicePathType (&FilePathNode->Header) != MEDIA_DEVICE_PATH ||\r
+              DevicePathSubType (&FilePathNode->Header) != MEDIA_FILEPATH_DP\r
+             ) {\r
+            Status = EFI_UNSUPPORTED;\r
+            break;\r
+          }\r
 \r
           //\r
-          // open without letting it create\r
-          // prevents error on existing files/directories\r
+          // Open this file path node\r
           //\r
-          Status = Handle2->Open (\r
-                                Handle2,\r
-                                &Handle1,\r
-                                FilePathNode->PathName,\r
-                                OpenMode &~EFI_FILE_MODE_CREATE,\r
-                                Attributes\r
-                               );\r
+          Handle2 = Handle1;\r
+          Handle1 = NULL;\r
+\r
           //\r
-          // if above failed now open and create the 'item'\r
-          // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)\r
+          // if this is the last node in the DevicePath always create (if that was requested).\r
           //\r
-          if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {\r
+          if (IsDevicePathEnd ((NextDevicePathNode (&FilePathNode->Header)))) {\r
             Status = Handle2->Open (\r
                                   Handle2,\r
                                   &Handle1,\r
-                                  FilePathNode->PathName,\r
+                                  AlignedNode->PathName,\r
                                   OpenMode,\r
                                   Attributes\r
                                  );\r
+          } else {\r
+\r
+            //\r
+            //  This is not the last node and we dont want to 'create' existing\r
+            //  directory entries...\r
+            //\r
+\r
+            //\r
+            // open without letting it create\r
+            // prevents error on existing files/directories\r
+            //\r
+            Status = Handle2->Open (\r
+                                  Handle2,\r
+                                  &Handle1,\r
+                                  AlignedNode->PathName,\r
+                                  OpenMode &~EFI_FILE_MODE_CREATE,\r
+                                  Attributes\r
+                                 );\r
+            //\r
+            // if above failed now open and create the 'item'\r
+            // if OpenMode EFI_FILE_MODE_CREATE bit was on (but disabled above)\r
+            //\r
+            if ((EFI_ERROR (Status)) && ((OpenMode & EFI_FILE_MODE_CREATE) != 0)) {\r
+              Status = Handle2->Open (\r
+                                    Handle2,\r
+                                    &Handle1,\r
+                                    AlignedNode->PathName,\r
+                                    OpenMode,\r
+                                    Attributes\r
+                                   );\r
+            }\r
           }\r
-        }\r
-        //\r
-        // Close the last node\r
-        //\r
-        Handle2->Close (Handle2);\r
+          //\r
+          // Close the last node\r
+          //\r
+          ShellInfoObject.NewEfiShellProtocol->CloseFile (Handle2);\r
 \r
-        //\r
-        // If there's been an error, stop\r
-        //\r
-        if (EFI_ERROR (Status)) {\r
-          break;\r
-        }\r
-      } // for loop\r
+          //\r
+          // If there's been an error, stop\r
+          //\r
+          if (EFI_ERROR (Status)) {\r
+            break;\r
+          }\r
+        } // for loop\r
+      }\r
     }\r
   }\r
+  SHELL_FREE_NON_NULL(AlignedNode);\r
   if (EFI_ERROR(Status)) {\r
     if (Handle1 != NULL) {\r
-      Handle1->Close(Handle1);\r
+      ShellInfoObject.NewEfiShellProtocol->CloseFile(Handle1);\r
     }\r
   } else {\r
     *FileHandle = ConvertEfiFileProtocolToShellHandle(Handle1, ShellFileHandleGetPath(ShellHandle));\r
@@ -1861,11 +1893,6 @@ UpdateFileName(
   If FileHandle is a file and matches all of the remaining Pattern (which would be\r
   on its last node), then add a EFI_SHELL_FILE_INFO object for this file to fileList.\r
 \r
-  if FileList is NULL, then ASSERT\r
-  if FilePattern is NULL, then ASSERT\r
-  if UnicodeCollation is NULL, then ASSERT\r
-  if FileHandle is NULL, then ASSERT\r
-\r
   Upon a EFI_SUCCESS return fromt he function any the caller is responsible to call\r
   FreeFileList with FileList.\r
 \r
@@ -1874,6 +1901,7 @@ UpdateFileName(
   @param[in] FileHandle         The FileHandle to start with\r
   @param[in,out] FileList       pointer to pointer to list of found files.\r
   @param[in] ParentNode         The node for the parent. Same file as identified by HANDLE.\r
+  @param[in] MapName            The file system name this file is on.\r
 \r
   @retval EFI_SUCCESS           all files were found and the FileList contains a list.\r
   @retval EFI_NOT_FOUND         no files were found\r
@@ -1886,7 +1914,8 @@ ShellSearchHandle(
   IN           EFI_UNICODE_COLLATION_PROTOCOL *UnicodeCollation,\r
   IN           SHELL_FILE_HANDLE              FileHandle,\r
   IN OUT       EFI_SHELL_FILE_INFO            **FileList,\r
-  IN     CONST EFI_SHELL_FILE_INFO            *ParentNode OPTIONAL\r
+  IN     CONST EFI_SHELL_FILE_INFO            *ParentNode OPTIONAL,\r
+  IN     CONST CHAR16                         *MapName\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -1896,6 +1925,8 @@ ShellSearchHandle(
   EFI_SHELL_FILE_INFO *ShellInfoNode;\r
   EFI_SHELL_FILE_INFO *NewShellNode;\r
   BOOLEAN             Directory;\r
+  CHAR16              *NewFullName;\r
+  UINTN               Size;\r
 \r
   if ( FilePattern      == NULL\r
     || UnicodeCollation == NULL\r
@@ -1959,7 +1990,20 @@ ShellSearchHandle(
           ; ShellInfoNode = (EFI_SHELL_FILE_INFO*)GetNextNode(&ShellInfo->Link, &ShellInfoNode->Link)\r
          ){\r
         if (UnicodeCollation->MetaiMatch(UnicodeCollation, (CHAR16*)ShellInfoNode->FileName, CurrentFilePattern)){\r
-          if (Directory){\r
+          if (ShellInfoNode->FullName != NULL && StrStr(ShellInfoNode->FullName, L":") == NULL) {\r
+            Size = StrSize(ShellInfoNode->FullName);\r
+            Size += StrSize(MapName) + sizeof(CHAR16);\r
+            NewFullName = AllocateZeroPool(Size);\r
+            if (NewFullName == NULL) {\r
+              Status = EFI_OUT_OF_RESOURCES;\r
+            } else {\r
+              StrCpy(NewFullName, MapName);\r
+              StrCat(NewFullName, ShellInfoNode->FullName+1);\r
+              FreePool((VOID*)ShellInfoNode->FullName);\r
+              ShellInfoNode->FullName = NewFullName;\r
+            }\r
+          }\r
+          if (Directory && !EFI_ERROR(Status) && ShellInfoNode->FullName != NULL && ShellInfoNode->FileName != NULL){\r
             //\r
             // should be a directory\r
             //\r
@@ -1973,7 +2017,6 @@ ShellSearchHandle(
               //\r
               //\r
               //\r
-              ASSERT_EFI_ERROR(Status);\r
               if (EFI_ERROR(Status)) {\r
                 break;\r
               }\r
@@ -1985,9 +2028,9 @@ ShellSearchHandle(
               //\r
               // recurse with the next part of the pattern\r
               //\r
-              Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode);\r
+              Status = ShellSearchHandle(NextFilePatternStart, UnicodeCollation, ShellInfoNode->Handle, FileList, ShellInfoNode, MapName);\r
             }\r
-          } else {\r
+          } else if (!EFI_ERROR(Status)) {\r
             //\r
             // should be a file\r
             //\r
@@ -2103,18 +2146,14 @@ EfiShellFindFiles(
             ; *PatternCurrentLocation != ':'\r
             ; PatternCurrentLocation++);\r
         PatternCurrentLocation++;\r
-        Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL);\r
+        Status = ShellSearchHandle(PatternCurrentLocation, gUnicodeCollation, RootFileHandle, FileList, NULL, MapName);\r
       }\r
       FreePool(RootDevicePath);\r
     }\r
   }\r
 \r
-  if (PatternCopy != NULL) {\r
-    FreePool(PatternCopy);\r
-  }\r
-  if (MapName != NULL) {\r
-    FreePool(MapName);\r
-  }\r
+  SHELL_FREE_NON_NULL(PatternCopy);\r
+  SHELL_FREE_NON_NULL(MapName);\r
 \r
   return(Status);\r
 }\r
@@ -2270,6 +2309,12 @@ EfiShellGetEnv(
     Size += 2*sizeof(CHAR16);\r
 \r
     Buffer = AllocateZeroPool(Size);\r
+    if (Buffer == NULL) {\r
+      if (!IsListEmpty (&List)) {\r
+        FreeEnvironmentVariableList(&List);\r
+      }\r
+      return (NULL);\r
+    }\r
     CurrentWriteLocation = (CHAR16*)Buffer;\r
 \r
     for ( Node = (ENV_VAR_LIST*)GetFirstNode(&List)\r
@@ -2284,7 +2329,9 @@ EfiShellGetEnv(
     //\r
     // Free the list...\r
     //\r
-    FreeEnvironmentVariableList(&List);\r
+    if (!IsListEmpty (&List)) {\r
+      FreeEnvironmentVariableList(&List);\r
+    }\r
   } else {\r
     //\r
     // We are doing a specific environment variable\r
@@ -2506,7 +2553,7 @@ EfiShellSetCurDir(
   TempString    = NULL;\r
   DirectoryName = NULL;\r
 \r
-  if (FileSystem == NULL && Dir == NULL) {\r
+  if ((FileSystem == NULL && Dir == NULL) || Dir == NULL) {\r
     return (EFI_INVALID_PARAMETER);\r
   }\r
 \r
@@ -2733,6 +2780,10 @@ InternalEfiShellGetListAlias(
   RetSize       = 0;\r
   RetVal        = NULL;\r
 \r
+  if (VariableName == NULL) {\r
+    return (NULL);\r
+  }\r
+\r
   VariableName[0] = CHAR_NULL;\r
 \r
   while (TRUE) {\r
@@ -2978,23 +3029,26 @@ CreatePopulateInstallShellProtocol (
   UINTN                       HandleCounter;\r
   SHELL_PROTOCOL_HANDLE_LIST  *OldProtocolNode;\r
 \r
+  if (NewShell == NULL) {\r
+    return (EFI_INVALID_PARAMETER);\r
+  }\r
+\r
   BufferSize = 0;\r
   Buffer = NULL;\r
   OldProtocolNode = NULL;\r
   InitializeListHead(&ShellInfoObject.OldShellList.Link);\r
 \r
-  ASSERT(NewShell != NULL);\r
-\r
   //\r
   // Initialize EfiShellProtocol object...\r
   //\r
-  *NewShell = &mShellProtocol;\r
   Status = gBS->CreateEvent(0,\r
                             0,\r
                             NULL,\r
                             NULL,\r
                             &mShellProtocol.ExecutionBreak);\r
-  ASSERT_EFI_ERROR(Status);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
+  }\r
 \r
   //\r
   // Get the size of the buffer we need.\r
@@ -3009,13 +3063,18 @@ CreatePopulateInstallShellProtocol (
     // Allocate and recall with buffer of correct size\r
     //\r
     Buffer = AllocateZeroPool(BufferSize);\r
-    ASSERT(Buffer != NULL);\r
+    if (Buffer == NULL) {\r
+      return (EFI_OUT_OF_RESOURCES);\r
+    }\r
     Status = gBS->LocateHandle(ByProtocol,\r
                                &gEfiShellProtocolGuid,\r
                                NULL,\r
                                &BufferSize,\r
                                Buffer);\r
-    ASSERT_EFI_ERROR(Status);\r
+    if (EFI_ERROR(Status)) {\r
+      FreePool(Buffer);\r
+      return (Status);\r
+    }\r
     //\r
     // now overwrite each of them, but save the info to restore when we end.\r
     //\r
@@ -3038,7 +3097,7 @@ CreatePopulateInstallShellProtocol (
                             OldProtocolNode->Handle,\r
                             &gEfiShellProtocolGuid,\r
                             OldProtocolNode->Interface,\r
-                            (VOID*)(*NewShell));\r
+                            (VOID*)(&mShellProtocol));\r
         if (!EFI_ERROR(Status)) {\r
           //\r
           // we reinstalled sucessfully.  log this so we can reverse it later.\r
@@ -3061,7 +3120,7 @@ CreatePopulateInstallShellProtocol (
                       &gImageHandle,\r
                       &gEfiShellProtocolGuid,\r
                       EFI_NATIVE_INTERFACE,\r
-                      (VOID*)(*NewShell));\r
+                      (VOID*)(&mShellProtocol));\r
   }\r
 \r
   if (PcdGetBool(PcdShellSupportOldProtocols)){\r
@@ -3069,6 +3128,9 @@ CreatePopulateInstallShellProtocol (
     ///@todo do we need to support ShellEnvironment (not ShellEnvironment2) also?\r
   }\r
 \r
+  if (!EFI_ERROR(Status)) {\r
+    *NewShell = &mShellProtocol;\r
+  }\r
   return (Status);\r
 }\r
 \r
@@ -3088,8 +3150,9 @@ CleanUpShellProtocol (
   IN OUT EFI_SHELL_PROTOCOL  *NewShell\r
   )\r
 {\r
-  EFI_STATUS Status;\r
-  SHELL_PROTOCOL_HANDLE_LIST  *Node2;\r
+  EFI_STATUS                        Status;\r
+  SHELL_PROTOCOL_HANDLE_LIST        *Node2;\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
 \r
   //\r
   // if we need to restore old protocols...\r
@@ -3104,7 +3167,6 @@ CleanUpShellProtocol (
                                                &gEfiShellProtocolGuid,\r
                                                NewShell,\r
                                                Node2->Interface);\r
-      ASSERT_EFI_ERROR(Status);\r
       FreePool(Node2);\r
     }\r
   } else {\r
@@ -3114,11 +3176,116 @@ CleanUpShellProtocol (
     Status = gBS->UninstallProtocolInterface(gImageHandle,\r
                                              &gEfiShellProtocolGuid,\r
                                              NewShell);\r
-    ASSERT_EFI_ERROR(Status);\r
   }\r
   Status = gBS->CloseEvent(NewShell->ExecutionBreak);\r
+  NewShell->ExecutionBreak = NULL;\r
+\r
+  Status = gBS->OpenProtocol(\r
+    gST->ConsoleInHandle,\r
+    &gEfiSimpleTextInputExProtocolGuid,\r
+    (VOID**)&SimpleEx,\r
+    gImageHandle,\r
+    NULL,\r
+    EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle1);\r
+  Status = SimpleEx->UnregisterKeyNotify(SimpleEx, ShellInfoObject.CtrlCNotifyHandle2);\r
 \r
   return (Status);\r
 }\r
 \r
+/**\r
+  Notification function for keystrokes.\r
+\r
+  @param[in] KeyData    The key that was pressed.\r
 \r
+  @retval EFI_SUCCESS   The operation was successful.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+NotificationFunction(\r
+  IN EFI_KEY_DATA *KeyData\r
+  )\r
+{\r
+  if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
+    return (EFI_UNSUPPORTED);\r
+  }\r
+  return (gBS->SignalEvent(ShellInfoObject.NewEfiShellProtocol->ExecutionBreak));\r
+}\r
+\r
+/**\r
+  Function to start monitoring for CTRL-C using SimpleTextInputEx.  This \r
+  feature's enabled state was not known when the shell initially launched.\r
+\r
+  @retval EFI_SUCCESS           The feature is enabled.\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough mnemory available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InernalEfiShellStartMonitor(\r
+  VOID\r
+  )\r
+{\r
+  EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+  EFI_KEY_DATA                      KeyData;\r
+  EFI_STATUS                        Status;\r
+\r
+  Status = gBS->OpenProtocol(\r
+    gST->ConsoleInHandle,\r
+    &gEfiSimpleTextInputExProtocolGuid,\r
+    (VOID**)&SimpleEx,\r
+    gImageHandle,\r
+    NULL,\r
+    EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx(\r
+      -1, \r
+      -1, \r
+      NULL,\r
+      STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
+      ShellInfoObject.HiiHandle);\r
+    return (EFI_SUCCESS);\r
+  }\r
+\r
+  if (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak == NULL) {\r
+    return (EFI_UNSUPPORTED);\r
+  }\r
+\r
+  KeyData.KeyState.KeyToggleState = 0;\r
+  KeyData.Key.ScanCode            = 0;\r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+  KeyData.Key.UnicodeChar         = L'c';\r
+\r
+  Status = SimpleEx->RegisterKeyNotify(\r
+    SimpleEx,\r
+    &KeyData,\r
+    NotificationFunction,\r
+    &ShellInfoObject.CtrlCNotifyHandle1);\r
+  \r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = SimpleEx->RegisterKeyNotify(\r
+      SimpleEx,\r
+      &KeyData,\r
+      NotificationFunction,\r
+      &ShellInfoObject.CtrlCNotifyHandle2);\r
+  }\r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+  KeyData.Key.UnicodeChar         = 3;\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = SimpleEx->RegisterKeyNotify(\r
+      SimpleEx,\r
+      &KeyData,\r
+      NotificationFunction,\r
+      &ShellInfoObject.CtrlCNotifyHandle3);\r
+  }\r
+  KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+  if (!EFI_ERROR(Status)) {\r
+    Status = SimpleEx->RegisterKeyNotify(\r
+      SimpleEx,\r
+      &KeyData,\r
+      NotificationFunction,\r
+      &ShellInfoObject.CtrlCNotifyHandle4);\r
+  }\r
+  return (Status);\r
+}\r