Comment's added and fixed.
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellParametersProtocol.c
1 /** @file\r
2   Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,\r
3   manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.\r
4 \r
5   Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
6   This program and the accompanying materials\r
7   are licensed and made available under the terms and conditions of the BSD License\r
8   which accompanies this distribution.  The full text of the license may be found at\r
9   http://opensource.org/licenses/bsd-license.php\r
10 \r
11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13 \r
14 **/\r
15 \r
16 #include "ShellParametersProtocol.h"\r
17 #include "ConsoleWrappers.h"\r
18 \r
19 /**\r
20   return the next parameter from a command line string;\r
21 \r
22   This function moves the next parameter from Walker into TempParameter and moves\r
23   Walker up past that parameter for recursive calling.  When the final parameter\r
24   is moved *Walker will be set to NULL;\r
25 \r
26   Temp Parameter must be large enough to hold the parameter before calling this\r
27   function.\r
28 \r
29   @param[in,out] Walker        pointer to string of command line.  Adjusted to\r
30                                 reminaing command line on return\r
31   @param[in,out] TempParameter pointer to string of command line item extracted.\r
32 \r
33 **/\r
34 VOID\r
35 EFIAPI\r
36 GetNextParameter(\r
37   CHAR16 **Walker,\r
38   CHAR16 **TempParameter\r
39   )\r
40 {\r
41   CHAR16 *NextDelim;\r
42   CHAR16 *TempLoc;\r
43 \r
44   ASSERT(Walker           != NULL);\r
45   ASSERT(*Walker          != NULL);\r
46   ASSERT(TempParameter    != NULL);\r
47   ASSERT(*TempParameter   != NULL);\r
48 \r
49   //\r
50   // make sure we dont have any leading spaces\r
51   //\r
52   while ((*Walker)[0] == L' ') {\r
53       (*Walker)++;\r
54   }\r
55 \r
56   //\r
57   // make sure we still have some params now...\r
58   //\r
59   if (StrLen(*Walker) == 0) {\r
60     ASSERT((*Walker)[0] == CHAR_NULL);\r
61     *Walker = NULL;\r
62     return;\r
63   }\r
64 \r
65   //\r
66   // we have a quoted parameter\r
67   // could be the last parameter, but SHOULD have a trailing quote\r
68   //\r
69   if ((*Walker)[0] == L'\"') {\r
70     NextDelim = NULL;\r
71     for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
72       if (*TempLoc == L'^' && *(TempLoc+1) == L'^') {\r
73         TempLoc++;\r
74       } else if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
75         TempLoc++;\r
76       } else if (*TempLoc == L'\"') {\r
77         NextDelim = TempLoc;\r
78         break;\r
79       }\r
80     }\r
81 \r
82     if (NextDelim - ((*Walker)+1) == 0) {\r
83       //\r
84       // found ""\r
85       //\r
86       StrCpy(*TempParameter, L"");\r
87       *Walker = NextDelim + 1;\r
88     } else if (NextDelim != NULL) {\r
89       StrnCpy(*TempParameter, (*Walker)+1, NextDelim - ((*Walker)+1));\r
90       *Walker = NextDelim + 1;\r
91     } else {\r
92       //\r
93       // last one... someone forgot the training quote!\r
94       //\r
95       StrCpy(*TempParameter, *Walker);\r
96       *Walker = NULL;\r
97     }\r
98     for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
99       if ((*TempLoc == L'^' && *(TempLoc+1) == L'^')\r
100        || (*TempLoc == L'^' && *(TempLoc+1) == L'|')\r
101        || (*TempLoc == L'^' && *(TempLoc+1) == L'\"')\r
102       ){\r
103         CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));\r
104       }\r
105     }\r
106   } else {\r
107     //\r
108     // we have a regular parameter (no quote) OR\r
109     // we have the final parameter (no trailing space)\r
110     //\r
111     NextDelim = StrStr((*Walker), L" ");\r
112     if (NextDelim != NULL) {\r
113       StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));\r
114       (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;\r
115       *Walker = NextDelim+1;\r
116     } else {\r
117       //\r
118       // last one.\r
119       //\r
120       StrCpy(*TempParameter, *Walker);\r
121       *Walker = NULL;\r
122     }\r
123     for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) {\r
124       if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {\r
125         CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0]));\r
126       }/* else if (*NextDelim == L'^') {\r
127         *NextDelim = L' ';\r
128       }*/\r
129     }\r
130     while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {\r
131       (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;\r
132     }\r
133     while ((*TempParameter)[0] == L' ') {\r
134       CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0]));\r
135     }\r
136   }\r
137   return;\r
138 }\r
139 \r
140 /**\r
141   Function to populate Argc and Argv.\r
142 \r
143   This function parses the CommandLine and divides it into standard C style Argc/Argv\r
144   parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL.  this supports space\r
145   delimited and quote surrounded parameter definition.\r
146 \r
147   @param[in] CommandLine        String of command line to parse\r
148   @param[in,out] Argv           pointer to array of strings; one for each parameter\r
149   @param[in,out] Argc           pointer to number of strings in Argv array\r
150 \r
151   @return EFI_SUCCESS           the operation was sucessful\r
152   @return EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
153 **/\r
154 EFI_STATUS\r
155 EFIAPI\r
156 ParseCommandLineToArgs(\r
157   IN CONST CHAR16 *CommandLine,\r
158   IN OUT CHAR16 ***Argv,\r
159   IN OUT UINTN *Argc\r
160   )\r
161 {\r
162   UINTN       Count;\r
163   CHAR16      *TempParameter;\r
164   CHAR16      *Walker;\r
165   CHAR16      *NewParam;\r
166   UINTN       Size;\r
167 \r
168   ASSERT(Argc != NULL);\r
169   ASSERT(Argv != NULL);\r
170 \r
171   if (CommandLine == NULL || StrLen(CommandLine)==0) {\r
172     (*Argc) = 0;\r
173     (*Argv) = NULL;\r
174     return (EFI_SUCCESS);\r
175   }\r
176 \r
177   Size = StrSize(CommandLine);\r
178   TempParameter = AllocateZeroPool(Size);\r
179   if (TempParameter == NULL) {\r
180     return (EFI_OUT_OF_RESOURCES);\r
181   }\r
182 \r
183   for ( Count = 0\r
184       , Walker = (CHAR16*)CommandLine\r
185       ; Walker != NULL && *Walker != CHAR_NULL\r
186       ; GetNextParameter(&Walker, &TempParameter)\r
187       , Count++\r
188      );\r
189 \r
190 /*  Count = 0;\r
191   Walker = (CHAR16*)CommandLine;\r
192   while(Walker != NULL) {\r
193     GetNextParameter(&Walker, &TempParameter);\r
194     Count++;\r
195   }\r
196 */\r
197   //\r
198   // lets allocate the pointer array\r
199   //\r
200   (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
201   if (*Argv == NULL) {\r
202     return (EFI_OUT_OF_RESOURCES);\r
203   }\r
204 \r
205   *Argc = 0;\r
206   Walker = (CHAR16*)CommandLine;\r
207   while(Walker != NULL && *Walker != CHAR_NULL) {\r
208     SetMem16(TempParameter, Size, CHAR_NULL);\r
209     GetNextParameter(&Walker, &TempParameter);\r
210     NewParam = AllocateZeroPool(StrSize(TempParameter));\r
211     ASSERT(NewParam != NULL);\r
212     StrCpy(NewParam, TempParameter);\r
213     ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
214     (*Argc)++;\r
215   }\r
216   ASSERT(Count >= (*Argc));\r
217   return (EFI_SUCCESS);\r
218 }\r
219 \r
220 /**\r
221   creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
222   installs it on our handle and if there is an existing version of the protocol\r
223   that one is cached for removal later.\r
224 \r
225   @param[in,out] NewShellParameters on a successful return, a pointer to pointer\r
226                                      to the newly installed interface.\r
227   @param[in,out] RootShellInstance  on a successful return, pointer to boolean.\r
228                                      TRUE if this is the root shell instance.\r
229 \r
230   @retval EFI_SUCCESS               the operation completed successfully.\r
231   @return other                     the operation failed.\r
232   @sa ReinstallProtocolInterface\r
233   @sa InstallProtocolInterface\r
234   @sa ParseCommandLineToArgs\r
235 **/\r
236 EFI_STATUS\r
237 EFIAPI\r
238 CreatePopulateInstallShellParametersProtocol (\r
239   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  **NewShellParameters,\r
240   IN OUT BOOLEAN                        *RootShellInstance\r
241   )\r
242 {\r
243   EFI_STATUS Status;\r
244   EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
245   CHAR16                    *FullCommandLine;\r
246   UINTN                     Size;\r
247 \r
248   Size = 0;\r
249   FullCommandLine = NULL;\r
250   LoadedImage = NULL;\r
251 \r
252   //\r
253   // Assert for valid parameters\r
254   //\r
255   ASSERT(NewShellParameters != NULL);\r
256   ASSERT(RootShellInstance  != NULL);\r
257 \r
258   //\r
259   // See if we have a shell parameters placed on us\r
260   //\r
261   Status = gBS->OpenProtocol (\r
262                 gImageHandle,\r
263                 &gEfiShellParametersProtocolGuid,\r
264                 (VOID **) &ShellInfoObject.OldShellParameters,\r
265                 gImageHandle,\r
266                 NULL,\r
267                 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
268                );\r
269   //\r
270   // if we don't then we must be the root shell (error is expected)\r
271   //\r
272   if (EFI_ERROR (Status)) {\r
273     *RootShellInstance = TRUE;\r
274   }\r
275 \r
276   //\r
277   // Allocate the new structure\r
278   //\r
279   *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
280   if ((*NewShellParameters) == NULL) {\r
281     return (EFI_OUT_OF_RESOURCES);\r
282   }\r
283 \r
284   //\r
285   // get loaded image protocol\r
286   //\r
287   Status = gBS->OpenProtocol (\r
288                 gImageHandle,\r
289                 &gEfiLoadedImageProtocolGuid,\r
290                 (VOID **) &LoadedImage,\r
291                 gImageHandle,\r
292                 NULL,\r
293                 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
294                );\r
295   ASSERT_EFI_ERROR(Status);\r
296   //\r
297   // Build the full command line\r
298   //\r
299   Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
300   if (Status == EFI_BUFFER_TOO_SMALL) {\r
301     FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
302     Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
303   }\r
304   if (Status == EFI_NOT_FOUND) {\r
305     //\r
306     // no parameters via environment... ok\r
307     //\r
308   } else {\r
309     if (EFI_ERROR(Status)) {\r
310       return (Status);\r
311     }\r
312   }\r
313   if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
314     ASSERT(FullCommandLine == NULL);\r
315     //\r
316     // Now we need to include a NULL terminator in the size.\r
317     //\r
318     Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
319     FullCommandLine = AllocateZeroPool(Size);\r
320   }\r
321   if (FullCommandLine != NULL) {\r
322     if (LoadedImage->LoadOptionsSize != 0){\r
323       StrCpy(FullCommandLine, LoadedImage->LoadOptions);\r
324     }\r
325     //\r
326     // Populate Argc and Argv\r
327     //\r
328     Status = ParseCommandLineToArgs(FullCommandLine,\r
329                                     &(*NewShellParameters)->Argv,\r
330                                     &(*NewShellParameters)->Argc);\r
331 \r
332     FreePool(FullCommandLine);\r
333 \r
334     ASSERT_EFI_ERROR(Status);\r
335   } else {\r
336     (*NewShellParameters)->Argv = NULL;\r
337     (*NewShellParameters)->Argc = 0;\r
338   }\r
339 \r
340   //\r
341   // Populate the 3 faked file systems...\r
342   //\r
343   if (*RootShellInstance) {\r
344     (*NewShellParameters)->StdIn  = &FileInterfaceStdIn;\r
345     (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
346     (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
347     Status = gBS->InstallProtocolInterface(&gImageHandle,\r
348                                            &gEfiShellParametersProtocolGuid,\r
349                                            EFI_NATIVE_INTERFACE,\r
350                                            (VOID*)(*NewShellParameters));\r
351   } else {\r
352     //\r
353     // copy from the existing ones\r
354     //\r
355     (*NewShellParameters)->StdIn  = ShellInfoObject.OldShellParameters->StdIn;\r
356     (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
357     (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
358     Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
359                                              &gEfiShellParametersProtocolGuid,\r
360                                              (VOID*)ShellInfoObject.OldShellParameters,\r
361                                              (VOID*)(*NewShellParameters));\r
362   }\r
363 \r
364   return (Status);\r
365 }\r
366 \r
367 /**\r
368   frees all memory used by createion and installation of shell parameters protocol\r
369   and if there was an old version installed it will restore that one.\r
370 \r
371   @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
372   being cleaned up.\r
373 \r
374   @retval EFI_SUCCESS     the cleanup was successful\r
375   @return other           the cleanup failed\r
376   @sa ReinstallProtocolInterface\r
377   @sa UninstallProtocolInterface\r
378 **/\r
379 EFI_STATUS\r
380 EFIAPI\r
381 CleanUpShellParametersProtocol (\r
382   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *NewShellParameters\r
383   )\r
384 {\r
385   EFI_STATUS Status;\r
386   UINTN LoopCounter;\r
387 \r
388   //\r
389   // If the old exists we need to restore it\r
390   //\r
391   if (ShellInfoObject.OldShellParameters != NULL) {\r
392     Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
393                                              &gEfiShellParametersProtocolGuid,\r
394                                              (VOID*)NewShellParameters,\r
395                                              (VOID*)ShellInfoObject.OldShellParameters);\r
396     DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
397   } else {\r
398     //\r
399     // No old one, just uninstall us...\r
400     //\r
401     Status = gBS->UninstallProtocolInterface(gImageHandle,\r
402                                              &gEfiShellParametersProtocolGuid,\r
403                                              (VOID*)NewShellParameters);\r
404   }\r
405   if (NewShellParameters->Argv != NULL) {\r
406     for ( LoopCounter = 0\r
407         ; LoopCounter < NewShellParameters->Argc\r
408         ; LoopCounter++\r
409        ){\r
410       FreePool(NewShellParameters->Argv[LoopCounter]);\r
411     }\r
412     FreePool(NewShellParameters->Argv);\r
413   }\r
414   FreePool(NewShellParameters);\r
415   return (Status);\r
416 }\r
417 \r
418 /**\r
419   Determin if a file name represents a unicode file.\r
420 \r
421   @param[in] FileName     Pointer to the filename to open.\r
422 \r
423   @retval EFI_SUCCESS     The file is a unicode file.\r
424   @return An error upon failure.\r
425 **/\r
426 EFI_STATUS\r
427 EFIAPI\r
428 IsUnicodeFile(\r
429   IN CONST CHAR16 *FileName\r
430   )\r
431 {\r
432   SHELL_FILE_HANDLE Handle;\r
433   EFI_STATUS        Status;\r
434   UINT64            OriginalFilePosition;\r
435   UINTN             CharSize;\r
436   CHAR16            CharBuffer;\r
437 \r
438   Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);\r
439   if (EFI_ERROR(Status)) {\r
440     return (Status);\r
441   }\r
442   gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
443   gEfiShellProtocol->SetFilePosition(Handle, 0);\r
444   CharSize = sizeof(CHAR16);\r
445   Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
446   if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {\r
447     Status = EFI_BUFFER_TOO_SMALL;\r
448   }\r
449   gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
450   gEfiShellProtocol->CloseFile(Handle);\r
451   return (Status);  \r
452 }\r
453 \r
454 /**\r
455   Strips out quotes sections of a string.\r
456 \r
457   All of the characters between quotes is replaced with spaces.\r
458 **/\r
459 VOID\r
460 EFIAPI\r
461 StripQuotes (\r
462   IN OUT CHAR16 *TheString\r
463   )\r
464 {\r
465   BOOLEAN RemoveNow;\r
466 \r
467   for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {\r
468     if (*TheString == L'^' && *(TheString + 1) == L'\"') {\r
469       TheString++;\r
470     } else if (*TheString == L'\"') {\r
471       RemoveNow = (BOOLEAN)!RemoveNow;\r
472     } else if (RemoveNow) {\r
473       *TheString = L' ';\r
474     }\r
475   }\r
476 }\r
477 \r
478 /**\r
479   Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
480   structure by parsing NewCommandLine.  The current values are returned to the\r
481   user.\r
482 \r
483   This will also update the system table.\r
484 \r
485   @param[in,out] ShellParameters        Pointer to parameter structure to modify.\r
486   @param[in] NewCommandLine             The new command line to parse and use.\r
487   @param[out] OldStdIn                  Pointer to old StdIn.\r
488   @param[out] OldStdOut                 Pointer to old StdOut.\r
489   @param[out] OldStdErr                 Pointer to old StdErr.\r
490   @param[out] SystemTableInfo           Pointer to old system table information.\r
491 \r
492   @retval   EFI_SUCCESS                 Operation was sucessful, Argv and Argc are valid.\r
493   @retval   EFI_OUT_OF_RESOURCES        A memory allocation failed.\r
494 **/\r
495 EFI_STATUS\r
496 EFIAPI\r
497 UpdateStdInStdOutStdErr(\r
498   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
499   IN CHAR16                             *NewCommandLine,\r
500   OUT SHELL_FILE_HANDLE                 *OldStdIn,\r
501   OUT SHELL_FILE_HANDLE                 *OldStdOut,\r
502   OUT SHELL_FILE_HANDLE                 *OldStdErr,\r
503   OUT SYSTEM_TABLE_INFO                 *SystemTableInfo\r
504   )\r
505 {\r
506   CHAR16            *CommandLineCopy;\r
507   CHAR16            *CommandLineWalker;\r
508   CHAR16            *StdErrFileName;\r
509   CHAR16            *StdOutFileName;\r
510   CHAR16            *StdInFileName;\r
511   CHAR16            *StdInVarName;\r
512   CHAR16            *StdOutVarName;\r
513   CHAR16            *StdErrVarName;\r
514   EFI_STATUS        Status;\r
515   SHELL_FILE_HANDLE TempHandle;\r
516   UINT64            FileSize;\r
517   BOOLEAN           OutUnicode;\r
518   BOOLEAN           InUnicode;\r
519   BOOLEAN           ErrUnicode;\r
520   BOOLEAN           OutAppend;\r
521   BOOLEAN           ErrAppend;\r
522   UINTN             Size;\r
523   CHAR16            TagBuffer[2];\r
524   SPLIT_LIST        *Split;\r
525   CHAR16            *FirstLocation;\r
526 \r
527   OutUnicode      = TRUE;\r
528   InUnicode       = TRUE;\r
529   ErrUnicode      = TRUE;\r
530   StdInVarName    = NULL;\r
531   StdOutVarName   = NULL;\r
532   StdErrVarName   = NULL;\r
533   StdErrFileName  = NULL;\r
534   StdInFileName   = NULL;\r
535   StdOutFileName  = NULL;\r
536   ErrAppend       = FALSE;\r
537   OutAppend       = FALSE;\r
538   CommandLineCopy = NULL;\r
539   FirstLocation   = NULL;\r
540 \r
541   if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
542     return (EFI_INVALID_PARAMETER);\r
543   }\r
544 \r
545   SystemTableInfo->ConIn          = gST->ConIn;\r
546   SystemTableInfo->ConInHandle    = gST->ConsoleInHandle;\r
547   SystemTableInfo->ConOut         = gST->ConOut;\r
548   SystemTableInfo->ConOutHandle   = gST->ConsoleOutHandle;\r
549   SystemTableInfo->ConErr         = gST->StdErr;\r
550   SystemTableInfo->ConErrHandle   = gST->StandardErrorHandle;\r
551   *OldStdIn                       = ShellParameters->StdIn;\r
552   *OldStdOut                      = ShellParameters->StdOut;\r
553   *OldStdErr                      = ShellParameters->StdErr;\r
554 \r
555   if (NewCommandLine == NULL) {\r
556     return (EFI_SUCCESS);\r
557   }\r
558 \r
559   CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
560   Status          = EFI_SUCCESS;\r
561   Split           = NULL;\r
562   FirstLocation   = CommandLineCopy + StrLen(CommandLineCopy);\r
563 \r
564   StripQuotes(CommandLineCopy);\r
565 \r
566   if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
567     Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
568     if (Split != NULL && Split->SplitStdIn != NULL) {\r
569       ShellParameters->StdIn  = Split->SplitStdIn;\r
570     }\r
571     if (Split != NULL && Split->SplitStdOut != NULL) {\r
572       ShellParameters->StdOut = Split->SplitStdOut;\r
573     }\r
574   }\r
575 \r
576   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
577     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
578     SetMem16(CommandLineWalker, 12, L' ');\r
579     StdErrVarName   = CommandLineWalker += 6;\r
580     ErrAppend       = TRUE;\r
581     if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
582       Status = EFI_NOT_FOUND;\r
583     }\r
584   }\r
585   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
586     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
587     SetMem16(CommandLineWalker, 12, L' ');\r
588     StdOutVarName   = CommandLineWalker += 6;\r
589     OutAppend       = TRUE;\r
590     if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
591       Status = EFI_NOT_FOUND;\r
592     }\r
593   } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
594     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
595     SetMem16(CommandLineWalker, 10, L' ');\r
596     StdOutVarName   = CommandLineWalker += 5;\r
597     OutAppend       = TRUE;\r
598     if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
599       Status = EFI_NOT_FOUND;\r
600     }\r
601   } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
602     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
603     SetMem16(CommandLineWalker, 8, L' ');\r
604     StdOutVarName   = CommandLineWalker += 4;\r
605     OutAppend       = FALSE;\r
606     if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
607       Status = EFI_NOT_FOUND;\r
608     }\r
609   }\r
610   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
611     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
612     SetMem16(CommandLineWalker, 12, L' ');\r
613     StdOutFileName  = CommandLineWalker += 6;\r
614     OutAppend       = TRUE;\r
615     OutUnicode      = FALSE;\r
616     if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
617       Status = EFI_NOT_FOUND;\r
618     }\r
619   }\r
620   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
621     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
622     SetMem16(CommandLineWalker, 10, L' ');\r
623     if (StdOutFileName != NULL) {\r
624       Status = EFI_INVALID_PARAMETER;\r
625     } else {\r
626       StdOutFileName  = CommandLineWalker += 5;\r
627       OutAppend       = TRUE;\r
628     }\r
629     if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
630       Status = EFI_NOT_FOUND;\r
631     }\r
632   } \r
633   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
634     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
635     SetMem16(CommandLineWalker, 8, L' ');\r
636     if (StdOutFileName != NULL) {\r
637       Status = EFI_INVALID_PARAMETER;\r
638     } else {\r
639       StdOutFileName  = CommandLineWalker += 4;\r
640       OutAppend       = TRUE;\r
641     }\r
642     if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
643       Status = EFI_NOT_FOUND;\r
644     }\r
645   }\r
646   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
647     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
648     SetMem16(CommandLineWalker, 10, L' ');\r
649     if (StdOutFileName != NULL) {\r
650       Status = EFI_INVALID_PARAMETER;\r
651     } else {\r
652       StdOutFileName  = CommandLineWalker += 5;\r
653       OutAppend       = TRUE;\r
654       OutUnicode      = FALSE;\r
655     }\r
656     if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
657       Status = EFI_NOT_FOUND;\r
658     }\r
659   } \r
660   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
661     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
662     SetMem16(CommandLineWalker, 10, L' ');\r
663     if (StdOutFileName != NULL) {\r
664       Status = EFI_INVALID_PARAMETER;\r
665     } else {\r
666       StdOutFileName  = CommandLineWalker += 5;\r
667       OutAppend       = FALSE;\r
668       OutUnicode      = FALSE;\r
669     }\r
670     if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
671       Status = EFI_NOT_FOUND;\r
672     }\r
673   } \r
674   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
675     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
676     SetMem16(CommandLineWalker, 8, L' ');\r
677     if (StdOutFileName != NULL) {\r
678       Status = EFI_INVALID_PARAMETER;\r
679     } else {\r
680       StdOutFileName  = CommandLineWalker += 4;\r
681       OutAppend       = FALSE;\r
682       OutUnicode      = FALSE;\r
683     }\r
684     if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
685       Status = EFI_NOT_FOUND;\r
686     }\r
687   }\r
688   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
689     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
690     SetMem16(CommandLineWalker, 10, L' ');\r
691     if (StdErrFileName != NULL) {\r
692       Status = EFI_INVALID_PARAMETER;\r
693     } else {\r
694       StdErrFileName  = CommandLineWalker += 5;\r
695       ErrAppend       = TRUE;\r
696     }\r
697     if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
698       Status = EFI_NOT_FOUND;\r
699     }\r
700   }\r
701 \r
702   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
703     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
704     SetMem16(CommandLineWalker, 10, L' ');\r
705     if (StdErrVarName != NULL) {\r
706       Status = EFI_INVALID_PARAMETER;\r
707     } else {\r
708       StdErrVarName   = CommandLineWalker += 5;\r
709       ErrAppend       = FALSE;\r
710     }\r
711     if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
712       Status = EFI_NOT_FOUND;\r
713     }\r
714   }\r
715   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
716     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
717     SetMem16(CommandLineWalker, 10, L' ');\r
718     if (StdOutVarName != NULL) {\r
719       Status = EFI_INVALID_PARAMETER;\r
720     } else {\r
721       StdOutVarName   = CommandLineWalker += 5;\r
722       OutAppend       = FALSE;\r
723     }\r
724     if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
725       Status = EFI_NOT_FOUND;\r
726     }\r
727   }\r
728   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
729     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
730     SetMem16(CommandLineWalker, 10, L' ');\r
731     if (StdErrFileName != NULL) {\r
732       Status = EFI_INVALID_PARAMETER;\r
733     } else {\r
734       StdErrFileName  = CommandLineWalker += 5;\r
735       ErrAppend       = FALSE;\r
736       ErrUnicode      = FALSE;\r
737     }\r
738     if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
739       Status = EFI_NOT_FOUND;\r
740     }\r
741   }\r
742   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
743     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
744     SetMem16(CommandLineWalker, 8, L' ');\r
745     if (StdErrFileName != NULL) {\r
746       Status = EFI_INVALID_PARAMETER;\r
747     } else {\r
748       StdErrFileName  = CommandLineWalker += 4;\r
749       ErrAppend       = FALSE;\r
750     }\r
751     if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
752       Status = EFI_NOT_FOUND;\r
753     }\r
754   }\r
755 \r
756   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
757     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
758     SetMem16(CommandLineWalker, 8, L' ');\r
759     if (StdOutFileName != NULL) {\r
760       Status = EFI_INVALID_PARAMETER;\r
761     } else {\r
762       StdOutFileName  = CommandLineWalker += 4;\r
763       OutAppend       = FALSE;\r
764     }\r
765     if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
766       Status = EFI_NOT_FOUND;\r
767     }\r
768   }\r
769 \r
770   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
771     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
772     SetMem16(CommandLineWalker, 6, L' ');\r
773     if (StdOutFileName != NULL) {\r
774       Status = EFI_INVALID_PARAMETER;\r
775     } else {\r
776       StdOutFileName  = CommandLineWalker += 3;\r
777       OutAppend       = FALSE;\r
778     }\r
779     if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
780       Status = EFI_NOT_FOUND;\r
781     }\r
782   }\r
783 \r
784   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
785     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
786     SetMem16(CommandLineWalker, 6, L' ');\r
787     if (StdInFileName != NULL) {\r
788       Status = EFI_INVALID_PARAMETER;\r
789     } else {\r
790       StdInFileName  = CommandLineWalker += 3;\r
791     }\r
792     if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
793       Status = EFI_NOT_FOUND;\r
794     }\r
795   }\r
796   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
797     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
798     SetMem16(CommandLineWalker, 8, L' ');\r
799     if (StdInFileName != NULL) {\r
800       Status = EFI_INVALID_PARAMETER;\r
801     } else {\r
802       StdInFileName   = CommandLineWalker += 4;\r
803       InUnicode       = FALSE;\r
804     }\r
805     if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
806       Status = EFI_NOT_FOUND;\r
807     }\r
808   }\r
809   if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
810     FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
811     SetMem16(CommandLineWalker, 8, L' ');\r
812     if (StdInVarName != NULL) {\r
813       Status = EFI_INVALID_PARAMETER;\r
814     } else {\r
815       StdInVarName  = CommandLineWalker += 4;\r
816     }\r
817     if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
818       Status = EFI_NOT_FOUND;\r
819     }\r
820   }\r
821 \r
822   if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
823     && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
824     ){\r
825     *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
826   }\r
827 \r
828   if (!EFI_ERROR(Status)) {\r
829     if (StdErrFileName != NULL && (CommandLineWalker = StrStr(StdErrFileName, L" ")) != NULL) {\r
830       CommandLineWalker[0] = CHAR_NULL;\r
831     }\r
832     if (StdOutFileName != NULL && (CommandLineWalker = StrStr(StdOutFileName, L" ")) != NULL) {\r
833       CommandLineWalker[0] = CHAR_NULL;\r
834     }\r
835     if (StdInFileName  != NULL && (CommandLineWalker = StrStr(StdInFileName , L" ")) != NULL) {\r
836       CommandLineWalker[0] = CHAR_NULL;\r
837     }\r
838     if (StdErrVarName  != NULL && (CommandLineWalker = StrStr(StdErrVarName , L" ")) != NULL) {\r
839       CommandLineWalker[0] = CHAR_NULL;\r
840     }\r
841     if (StdOutVarName  != NULL && (CommandLineWalker = StrStr(StdOutVarName , L" ")) != NULL) {\r
842       CommandLineWalker[0] = CHAR_NULL;\r
843     }\r
844     if (StdInVarName   != NULL && (CommandLineWalker = StrStr(StdInVarName  , L" ")) != NULL) {\r
845       CommandLineWalker[0] = CHAR_NULL;\r
846     }\r
847 \r
848     //\r
849     // Verify not the same and not duplicating something from a split\r
850     //\r
851     if (\r
852       //\r
853       // Check that no 2 filenames are the same\r
854       //\r
855       (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
856       ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
857       ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
858       //\r
859       // Check that no 2 variable names are the same\r
860       //\r
861       ||(StdErrVarName  != NULL && StdInVarName  != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName  ) == 0)\r
862       ||(StdOutVarName  != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName  ) == 0)\r
863       ||(StdErrVarName  != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
864       //\r
865       // When a split (using | operator) is in place some are not allowed\r
866       //\r
867       ||(Split != NULL && Split->SplitStdIn  != NULL && (StdInVarName  != NULL || StdInFileName  != NULL))\r
868       ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
869       //\r
870       // Check that nothing is trying to be output to 2 locations.\r
871       //\r
872       ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
873       ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
874       ||(StdInFileName  != NULL && StdInVarName  != NULL)\r
875       //\r
876       // Check for no volatile environment variables\r
877       //\r
878       ||(StdErrVarName  != NULL && !IsVolatileEnv(StdErrVarName))\r
879       ||(StdOutVarName  != NULL && !IsVolatileEnv(StdOutVarName))\r
880       //\r
881       // Cant redirect during a reconnect operation.\r
882       //\r
883       ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
884          && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
885       //\r
886       // Check that filetypes (Unicode/Ascii) do not change during an append\r
887       //\r
888       ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
889       ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
890       ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
891       ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
892       ){\r
893       Status = EFI_INVALID_PARAMETER;\r
894     } else if (!EFI_ERROR(Status)){\r
895       //\r
896       // Open the Std<Whatever> and we should not have conflicts here...\r
897       //\r
898 \r
899       //\r
900       // StdErr to a file\r
901       //\r
902       if (StdErrFileName != NULL) {\r
903         if (!ErrAppend) {\r
904           //\r
905           // delete existing file.\r
906           //\r
907           ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
908         }\r
909         Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
910         if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
911           //\r
912           // Write out the gUnicodeFileTag\r
913           //\r
914           Size = sizeof(CHAR16);\r
915           TagBuffer[0] = gUnicodeFileTag;\r
916           TagBuffer[1] = CHAR_NULL;\r
917           ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
918         }\r
919         if (!ErrUnicode && !EFI_ERROR(Status)) {\r
920           TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
921           ASSERT(TempHandle != NULL);\r
922         }\r
923         if (!EFI_ERROR(Status)) {\r
924           ShellParameters->StdErr = TempHandle;\r
925           gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
926         }\r
927       }\r
928 \r
929       //\r
930       // StdOut to a file\r
931       //\r
932       if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
933         if (!OutAppend) {\r
934           //\r
935           // delete existing file.\r
936           //\r
937           ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
938         }\r
939         Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
940         if (TempHandle == NULL) {\r
941           Status = EFI_INVALID_PARAMETER;\r
942         } else {\r
943           if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
944             //no-op\r
945           } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
946             //\r
947             // Write out the gUnicodeFileTag\r
948             //\r
949             Size = sizeof(CHAR16);\r
950             TagBuffer[0] = gUnicodeFileTag;\r
951             TagBuffer[1] = CHAR_NULL;\r
952             ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
953           } else if (OutAppend) {\r
954             //\r
955             // Move to end of file\r
956             //\r
957             Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
958             if (!EFI_ERROR(Status)) {\r
959               Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
960             }\r
961           }\r
962           if (!OutUnicode && !EFI_ERROR(Status)) {\r
963             TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
964             ASSERT(TempHandle != NULL);\r
965           }\r
966           if (!EFI_ERROR(Status)) {\r
967             ShellParameters->StdOut = TempHandle;\r
968             gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
969           }\r
970         }\r
971       }\r
972 \r
973       //\r
974       // StdOut to a var\r
975       //\r
976       if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
977         if (!OutAppend) {\r
978           //\r
979           // delete existing variable.\r
980           //\r
981           SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
982         }\r
983         TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
984         ASSERT(TempHandle != NULL);\r
985         ShellParameters->StdOut = TempHandle;\r
986         gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
987       }\r
988 \r
989       //\r
990       // StdErr to a var\r
991       //\r
992       if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
993         if (!ErrAppend) {\r
994           //\r
995           // delete existing variable.\r
996           //\r
997           SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
998         }\r
999         TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1000         ASSERT(TempHandle != NULL);\r
1001         ShellParameters->StdErr = TempHandle;\r
1002         gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
1003       }\r
1004 \r
1005       //\r
1006       // StdIn from a var\r
1007       //\r
1008       if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1009         TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
1010         if (!InUnicode) {\r
1011           TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1012         }\r
1013         Size = 0;\r
1014         ASSERT(TempHandle != NULL);\r
1015         if (((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
1016           Status = EFI_INVALID_PARAMETER;\r
1017         } else {\r
1018           ShellParameters->StdIn = TempHandle;\r
1019           gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1020         }\r
1021       }\r
1022 \r
1023       //\r
1024       // StdIn from a file\r
1025       //\r
1026       if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1027         Status = ShellOpenFileByName(\r
1028           StdInFileName,\r
1029           &TempHandle,\r
1030           EFI_FILE_MODE_READ,\r
1031           0);\r
1032         if (!InUnicode && !EFI_ERROR(Status)) {\r
1033           TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1034         }\r
1035         if (!EFI_ERROR(Status)) {\r
1036           ShellParameters->StdIn = TempHandle;\r
1037           gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1038         }\r
1039       }\r
1040     }\r
1041   }\r
1042   FreePool(CommandLineCopy);\r
1043 \r
1044   if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1045     return (EFI_OUT_OF_RESOURCES);\r
1046   }\r
1047   return (Status);\r
1048 }\r
1049 \r
1050 /**\r
1051   Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1052   structure with StdIn and StdOut.  The current values are de-allocated.\r
1053 \r
1054   @param[in,out] ShellParameters      Pointer to parameter structure to modify.\r
1055   @param[in] OldStdIn                 Pointer to old StdIn.\r
1056   @param[in] OldStdOut                Pointer to old StdOut.\r
1057   @param[in] OldStdErr                Pointer to old StdErr.\r
1058   @param[in] SystemTableInfo          Pointer to old system table information.\r
1059 **/\r
1060 EFI_STATUS\r
1061 EFIAPI\r
1062 RestoreStdInStdOutStdErr (\r
1063   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
1064   IN  SHELL_FILE_HANDLE                 *OldStdIn,\r
1065   IN  SHELL_FILE_HANDLE                 *OldStdOut,\r
1066   IN  SHELL_FILE_HANDLE                 *OldStdErr,\r
1067   IN  SYSTEM_TABLE_INFO                 *SystemTableInfo\r
1068   )\r
1069 {\r
1070   SPLIT_LIST        *Split;\r
1071 \r
1072   if (ShellParameters == NULL \r
1073     ||OldStdIn        == NULL\r
1074     ||OldStdOut       == NULL\r
1075     ||OldStdErr       == NULL\r
1076     ||SystemTableInfo == NULL) {\r
1077     return (EFI_INVALID_PARAMETER);\r
1078   }\r
1079   if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1080     Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1081   } else {\r
1082     Split = NULL;\r
1083   }\r
1084   if (ShellParameters->StdIn  != *OldStdIn) {\r
1085     if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1086       gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1087     }\r
1088     ShellParameters->StdIn = *OldStdIn;\r
1089   }\r
1090   if (ShellParameters->StdOut != *OldStdOut) {\r
1091     if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1092       gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1093     }\r
1094     ShellParameters->StdOut = *OldStdOut;\r
1095   }\r
1096   if (ShellParameters->StdErr != *OldStdErr) {\r
1097     gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1098     ShellParameters->StdErr = *OldStdErr;\r
1099   }\r
1100 \r
1101   if (gST->ConIn != SystemTableInfo->ConIn) {\r
1102     CloseSimpleTextInOnFile(gST->ConIn);\r
1103     gST->ConIn                = SystemTableInfo->ConIn;\r
1104     gST->ConsoleInHandle      = SystemTableInfo->ConInHandle;\r
1105   }\r
1106   if (gST->ConOut != SystemTableInfo->ConOut) {\r
1107     CloseSimpleTextOutOnFile(gST->ConOut);\r
1108     gST->ConOut               = SystemTableInfo->ConOut;\r
1109     gST->ConsoleOutHandle     = SystemTableInfo->ConOutHandle;\r
1110   }\r
1111   if (gST->StdErr != SystemTableInfo->ConErr) {\r
1112     CloseSimpleTextOutOnFile(gST->StdErr);\r
1113     gST->StdErr               = SystemTableInfo->ConErr;\r
1114     gST->StandardErrorHandle  = SystemTableInfo->ConErrHandle;\r
1115   }\r
1116 \r
1117   return (EFI_SUCCESS);\r
1118 }\r
1119 /**\r
1120   Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1121   structure by parsing NewCommandLine.  The current values are returned to the\r
1122   user.\r
1123 \r
1124   If OldArgv or OldArgc is NULL then that value is not returned.\r
1125 \r
1126   @param[in,out] ShellParameters        Pointer to parameter structure to modify.\r
1127   @param[in] NewCommandLine             The new command line to parse and use.\r
1128   @param[out] OldArgv                   Pointer to old list of parameters.\r
1129   @param[out] OldArgc                   Pointer to old number of items in Argv list.\r
1130 \r
1131   @retval   EFI_SUCCESS                 Operation was sucessful, Argv and Argc are valid.\r
1132   @retval   EFI_OUT_OF_RESOURCES        A memory allocation failed.\r
1133 **/\r
1134 EFI_STATUS\r
1135 EFIAPI\r
1136 UpdateArgcArgv(\r
1137   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
1138   IN CONST CHAR16                       *NewCommandLine,\r
1139   OUT CHAR16                            ***OldArgv OPTIONAL,\r
1140   OUT UINTN                             *OldArgc OPTIONAL\r
1141   )\r
1142 {\r
1143   ASSERT(ShellParameters != NULL);\r
1144 \r
1145   if (OldArgc != NULL) {\r
1146     *OldArgc = ShellParameters->Argc;\r
1147   }\r
1148   if (OldArgc != NULL) {\r
1149     *OldArgv = ShellParameters->Argv;\r
1150   }\r
1151 \r
1152   return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1153 }\r
1154 \r
1155 /**\r
1156   Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1157   structure with Argv and Argc.  The current values are de-allocated and the\r
1158   OldArgv must not be deallocated by the caller.\r
1159 \r
1160   @param[in,out] ShellParameters       pointer to parameter structure to modify\r
1161   @param[in] OldArgv                   pointer to old list of parameters\r
1162   @param[in] OldArgc                   pointer to old number of items in Argv list\r
1163 **/\r
1164 VOID\r
1165 EFIAPI\r
1166 RestoreArgcArgv(\r
1167   IN OUT EFI_SHELL_PARAMETERS_PROTOCOL  *ShellParameters,\r
1168   IN CHAR16                             ***OldArgv,\r
1169   IN UINTN                              *OldArgc\r
1170   )\r
1171 {\r
1172   UINTN LoopCounter;\r
1173   ASSERT(ShellParameters != NULL);\r
1174   ASSERT(OldArgv         != NULL);\r
1175   ASSERT(OldArgc         != NULL);\r
1176 \r
1177   if (ShellParameters->Argv != NULL) {\r
1178     for ( LoopCounter = 0\r
1179         ; LoopCounter < ShellParameters->Argc\r
1180         ; LoopCounter++\r
1181        ){\r
1182       FreePool(ShellParameters->Argv[LoopCounter]);\r
1183     }\r
1184     FreePool(ShellParameters->Argv);\r
1185   }\r
1186   ShellParameters->Argv = *OldArgv;\r
1187   *OldArgv = NULL;\r
1188   ShellParameters->Argc = *OldArgc;\r
1189   *OldArgc = 0;\r
1190 }\r