+/**\r
+ Determine if the character is valid for a filename.\r
+\r
+ @param[in] Ch The character to test.\r
+\r
+ @retval TRUE The character is valid.\r
+ @retval FALSE The character is not valid.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsValidFileNameChar (\r
+ IN CONST CHAR16 Ch\r
+ )\r
+{\r
+ //\r
+ // See if there are any illegal characters within the name\r
+ //\r
+ if (Ch < 0x20 || Ch == L'\"' || Ch == L'*' || Ch == L'/' || Ch == L'<' || Ch == L'>' || Ch == L'?' || Ch == L'|' || Ch == L' ') {\r
+ return FALSE;\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Check if file name has illegal characters.\r
+ \r
+ @param Name The filename to check.\r
+\r
+ @retval TRUE The filename is ok.\r
+ @retval FALSE The filename is not ok.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+IsValidFileName (\r
+ IN CONST CHAR16 *Name\r
+ )\r
+{\r
+\r
+ UINTN Index;\r
+ UINTN Len;\r
+\r
+ //\r
+ // check the length of Name\r
+ //\r
+ for (Len = 0, Index = StrLen (Name) - 1; Index + 1 != 0; Index--, Len++) {\r
+ if (Name[Index] == '\\' || Name[Index] == ':') {\r
+ break;\r
+ }\r
+ }\r
+\r
+ if (Len == 0 || Len > 255) {\r
+ return FALSE;\r
+ }\r
+ //\r
+ // check whether any char in Name not appears in valid file name char\r
+ //\r
+ for (Index = 0; Index < StrLen (Name); Index++) {\r
+ if (!IsValidFileNameChar (Name[Index])) {\r
+ return FALSE;\r
+ }\r
+ }\r
+\r
+ return TRUE;\r
+}\r
+\r
+/**\r
+ Find a filename that is valid (not taken) with the given extension.\r
+\r
+ @param[in] Extension The file extension.\r
+\r
+ @retval NULL Something went wrong.\r
+ @return the valid filename.\r
+**/\r
+CHAR16 *\r
+EFIAPI\r
+EditGetDefaultFileName (\r
+ IN CONST CHAR16 *Extension\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ UINTN Suffix;\r
+ BOOLEAN FoundNewFile;\r
+ CHAR16 *FileNameTmp;\r
+\r
+ Suffix = 0;\r
+ FoundNewFile = FALSE;\r
+\r
+ do {\r
+ FileNameTmp = CatSPrint (NULL, L"NewFile%d.%s", Suffix, Extension);\r
+\r
+ //\r
+ // after that filename changed to path\r
+ //\r
+ Status = ShellFileExists (FileNameTmp);\r
+\r
+ if (Status == EFI_NOT_FOUND) {\r
+ return FileNameTmp;\r
+ }\r
+\r
+ FreePool (FileNameTmp);\r
+ FileNameTmp = NULL;\r
+ Suffix++;\r
+ } while (Suffix != 0);\r
+\r
+ FreePool (FileNameTmp);\r
+ return NULL;\r
+}\r
+\r
+/**\r
+ Read a file into an allocated buffer. The buffer is the responsibility \r
+ of the caller to free.\r
+\r
+ @param[in] FileName The filename of the file to open.\r
+ @param[out] Buffer Upon successful return, the pointer to the \r
+ address of the allocated buffer. \r
+ @param[out] BufferSize If not NULL, then the pointer to the size\r
+ of the allocated buffer.\r
+ @param[out] ReadOnly Upon successful return TRUE if the file is\r
+ read only. FALSE otherwise.\r
+\r
+ @retval EFI_NOT_FOUND The filename did not represent a file in the \r
+ file system.\r
+ @retval EFI_SUCCESS The file was read into the buffer.\r
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
+ @retval EFI_LOAD_ERROR The file read operation failed.\r
+ @retval EFI_INVALID_PARAMETER A parameter was invalid.\r
+ @retval EFI_INVALID_PARAMETER FileName was NULL.\r
+ @retval EFI_INVALID_PARAMETER FileName was a directory.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ReadFileIntoBuffer (\r
+ IN CONST CHAR16 *FileName,\r
+ OUT VOID **Buffer,\r
+ OUT UINTN *BufferSize OPTIONAL,\r
+ OUT BOOLEAN *ReadOnly\r
+ )\r
+{\r
+ VOID *InternalBuffer;\r
+ UINTN FileSize;\r
+ SHELL_FILE_HANDLE FileHandle;\r
+ BOOLEAN CreateFile;\r
+ EFI_STATUS Status;\r
+ EFI_FILE_INFO *Info;\r
+\r
+ InternalBuffer = NULL;\r
+ FileSize = 0;\r
+ FileHandle = NULL;\r
+ CreateFile = FALSE;\r
+ Status = EFI_SUCCESS;\r
+ Info = NULL;\r
+\r
+ if (FileName == NULL || Buffer == NULL || ReadOnly == NULL) {\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
+\r
+ //\r
+ // try to open the file\r
+ //\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ ASSERT(CreateFile == FALSE);\r
+ if (FileHandle == NULL) {\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+\r
+ Info = ShellGetFileInfo(FileHandle);\r
+ \r
+ if (Info->Attribute & EFI_FILE_DIRECTORY) {\r
+ FreePool (Info);\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ if (Info->Attribute & EFI_FILE_READ_ONLY) {\r
+ *ReadOnly = TRUE;\r
+ } else {\r
+ *ReadOnly = FALSE;\r
+ }\r
+ //\r
+ // get file size\r
+ //\r
+ FileSize = (UINTN) Info->FileSize;\r
+\r
+ FreePool (Info);\r
+ } else if (Status == EFI_NOT_FOUND) {\r
+ //\r
+ // file not exists. add create and try again\r
+ //\r
+ Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } else {\r
+ //\r
+ // it worked. now delete it and move on with the name (now validated)\r
+ //\r
+ Status = ShellDeleteFile (&FileHandle);\r
+ if (Status == EFI_WARN_DELETE_FAILURE) {\r
+ Status = EFI_ACCESS_DENIED;\r
+ }\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ }\r
+ //\r
+ // file doesn't exist, so set CreateFile to TRUE and can't be read-only\r
+ //\r
+ CreateFile = TRUE;\r
+ *ReadOnly = FALSE;\r
+ }\r
+\r
+ //\r
+ // the file exists\r
+ //\r
+ if (!CreateFile) {\r
+ //\r
+ // allocate buffer to read file\r
+ //\r
+ InternalBuffer = AllocateZeroPool (FileSize);\r
+ if (InternalBuffer == NULL) {\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+ //\r
+ // read file into InternalBuffer\r
+ //\r
+ Status = ShellReadFile (FileHandle, &FileSize, InternalBuffer);\r
+ ShellCloseFile(&FileHandle);\r
+ FileHandle = NULL;\r
+ if (EFI_ERROR (Status)) {\r
+ SHELL_FREE_NON_NULL (InternalBuffer);\r
+ return EFI_LOAD_ERROR;\r
+ }\r
+ }\r
+ *Buffer = InternalBuffer;\r
+ if (BufferSize != NULL) {\r
+ *BufferSize = FileSize;\r
+ }\r
+ return (EFI_SUCCESS);\r
+\r
+}\r