]> git.proxmox.com Git - mirror_edk2.git/commitdiff
EmulatorPkg/Win: Add SimpleFileSystem support
authorRuiyu Ni <ruiyu.ni@intel.com>
Thu, 23 Aug 2018 05:43:00 +0000 (13:43 +0800)
committerRuiyu Ni <ruiyu.ni@intel.com>
Mon, 27 Aug 2018 07:20:58 +0000 (15:20 +0800)
Contributed-under: TianoCore Contribution Agreement 1.1
Signed-off-by: Ruiyu Ni <ruiyu.ni@intel.com>
Reviewed-by: Hao A Wu <hao.a.wu@intel.com>
Cc: Andrew Fish <afish@apple.com>
EmulatorPkg/Win/Host/WinFileSystem.c [new file with mode: 0644]
EmulatorPkg/Win/Host/WinHost.c
EmulatorPkg/Win/Host/WinHost.h
EmulatorPkg/Win/Host/WinHost.inf

diff --git a/EmulatorPkg/Win/Host/WinFileSystem.c b/EmulatorPkg/Win/Host/WinFileSystem.c
new file mode 100644 (file)
index 0000000..0d43dda
--- /dev/null
@@ -0,0 +1,2409 @@
+/*++ @file\r
+  Support OS native directory access.\r
+\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+This program and the accompanying materials\r
+are licensed and made available under the terms and conditions of the BSD License\r
+which accompanies this distribution.  The full text of the license may be found at\r
+http://opensource.org/licenses/bsd-license.php\r
+\r
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+\r
+\r
+**/\r
+\r
+#include "WinHost.h"\r
+\r
+\r
+#define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 'f', 's')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+  EMU_IO_THUNK_PROTOCOL           *Thunk;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFileSystem;\r
+  CHAR16                          *FilePath;\r
+  CHAR16                          *VolumeLabel;\r
+} WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE;\r
+\r
+#define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE, \\r
+      SimpleFileSystem, \\r
+      WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \\r
+      )\r
+\r
+\r
+#define WIN_NT_EFI_FILE_PRIVATE_SIGNATURE SIGNATURE_32 ('l', 'o', 'f', 's')\r
+\r
+typedef struct {\r
+  UINTN                           Signature;\r
+  EMU_IO_THUNK_PROTOCOL           *Thunk;\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;\r
+  EFI_FILE_PROTOCOL               EfiFile;\r
+  HANDLE                          LHandle;\r
+  HANDLE                          DirHandle;\r
+  BOOLEAN                         IsRootDirectory;\r
+  BOOLEAN                         IsDirectoryPath;\r
+  BOOLEAN                         IsOpenedByRead;\r
+  CHAR16                          *FilePath;\r
+  WCHAR                           *FileName;\r
+  BOOLEAN                         IsValidFindBuf;\r
+  WIN32_FIND_DATA                 FindBuf;\r
+} WIN_NT_EFI_FILE_PRIVATE;\r
+\r
+#define WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \\r
+  CR (a, \\r
+      WIN_NT_EFI_FILE_PRIVATE, \\r
+      EfiFile, \\r
+      WIN_NT_EFI_FILE_PRIVATE_SIGNATURE \\r
+      )\r
+\r
+extern EFI_FILE_PROTOCOL gWinNtFileProtocol;\r
+extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol;\r
+\r
+EFI_STATUS\r
+WinNtFileGetInfo (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN EFI_GUID                 *InformationType,\r
+  IN OUT UINTN                *BufferSize,\r
+  OUT VOID                    *Buffer\r
+  );\r
+\r
+EFI_STATUS\r
+WinNtFileSetInfo (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN EFI_GUID                 *InformationType,\r
+  IN UINTN                    BufferSize,\r
+  IN VOID                     *Buffer\r
+  );\r
+\r
+\r
+\r
+CHAR16 *\r
+EfiStrChr (\r
+  IN CHAR16   *Str,\r
+  IN CHAR16   Chr\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  Locate the first occurance of a character in a string.\r
+\r
+Arguments:\r
+\r
+  Str - Pointer to NULL terminated unicode string.\r
+  Chr - Character to locate.\r
+\r
+Returns:\r
+\r
+  If Str is NULL, then NULL is returned.\r
+  If Chr is not contained in Str, then NULL is returned.\r
+  If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.\r
+\r
+--*/\r
+{\r
+  if (Str == NULL) {\r
+    return Str;\r
+  }\r
+\r
+  while (*Str != '\0' && *Str != Chr) {\r
+    ++Str;\r
+  }\r
+\r
+  return (*Str == Chr) ? Str : NULL;\r
+}\r
+\r
+\r
+\r
+BOOLEAN\r
+IsZero (\r
+  IN VOID   *Buffer,\r
+  IN UINTN  Length\r
+  )\r
+{\r
+  if (Buffer == NULL || Length == 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (*(UINT8 *) Buffer != 0) {\r
+    return FALSE;\r
+  }\r
+\r
+  if (Length > 1) {\r
+    if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) {\r
+      return FALSE;\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+VOID\r
+CutPrefix (\r
+  IN  CHAR16  *Str,\r
+  IN  UINTN   Count\r
+  )\r
+{\r
+  CHAR16  *Pointer;\r
+\r
+  if (StrLen (Str) < Count) {\r
+    ASSERT (0);\r
+  }\r
+\r
+  if (Count != 0) {\r
+  for (Pointer = Str; *(Pointer + Count); Pointer++) {\r
+    *Pointer = *(Pointer + Count);\r
+  }\r
+\r
+  *Pointer = *(Pointer + Count);\r
+  }\r
+}\r
+/**\r
+  Open the root directory on a volume.\r
+\r
+  @param  This Protocol instance pointer.\r
+  @param  Root Returns an Open file handle for the root directory\r
+\r
+  @retval EFI_SUCCESS          The device was opened.\r
+  @retval EFI_UNSUPPORTED      This volume does not support the file system.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_ACCESS_DENIED    The service denied access to the file.\r
+  @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtOpenVolume (\r
+  IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL    *This,\r
+  OUT EFI_FILE_PROTOCOL                 **Root\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
+  WIN_NT_EFI_FILE_PRIVATE           *PrivateFile;\r
+  CHAR16                            *TempFileName;\r
+  UINTN                             Size;\r
+\r
+  if (This == NULL || Root == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  PrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));\r
+  if (PrivateFile == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  PrivateFile->FileName = AllocatePool (StrSize (Private->FilePath));\r
+  if (PrivateFile->FileName == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  PrivateFile->FilePath = AllocatePool (StrSize (Private->FilePath));\r
+  if (PrivateFile->FilePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  StrCpy (PrivateFile->FilePath, Private->FilePath);\r
+  StrCpy (PrivateFile->FileName, PrivateFile->FilePath);\r
+  PrivateFile->Signature = WIN_NT_EFI_FILE_PRIVATE_SIGNATURE;\r
+  PrivateFile->Thunk = Private->Thunk;\r
+  PrivateFile->SimpleFileSystem = This;\r
+  PrivateFile->IsRootDirectory = TRUE;\r
+  PrivateFile->IsDirectoryPath = TRUE;\r
+  PrivateFile->IsOpenedByRead = TRUE;\r
+  CopyMem (&PrivateFile->EfiFile, &gWinNtFileProtocol, sizeof (gWinNtFileProtocol));\r
+  PrivateFile->IsValidFindBuf = FALSE;\r
+\r
+  //\r
+  // Set DirHandle\r
+  //\r
+  PrivateFile->DirHandle = CreateFile (\r
+    PrivateFile->FilePath,\r
+    GENERIC_READ,\r
+    FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+    NULL,\r
+    OPEN_EXISTING,\r
+    FILE_FLAG_BACKUP_SEMANTICS,\r
+    NULL\r
+  );\r
+\r
+  if (PrivateFile->DirHandle == INVALID_HANDLE_VALUE) {\r
+    Status = EFI_NOT_FOUND;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Find the first file under it\r
+  //\r
+  Size = StrSize (PrivateFile->FilePath);\r
+  Size += StrSize (L"\\*");\r
+  TempFileName = AllocatePool (Size);\r
+  if (TempFileName == NULL) {\r
+    goto Done;\r
+  }\r
+  StrCpy (TempFileName, PrivateFile->FilePath);\r
+  StrCat (TempFileName, L"\\*");\r
+\r
+  PrivateFile->LHandle = FindFirstFile (TempFileName, &PrivateFile->FindBuf);\r
+  FreePool (TempFileName);\r
+\r
+  if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+    PrivateFile->IsValidFindBuf = FALSE;\r
+  } else {\r
+    PrivateFile->IsValidFindBuf = TRUE;\r
+  }\r
+  *Root = &PrivateFile->EfiFile;\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+Done:\r
+  if (EFI_ERROR (Status)) {\r
+    if (PrivateFile) {\r
+      if (PrivateFile->FileName) {\r
+        FreePool (PrivateFile->FileName);\r
+      }\r
+\r
+      if (PrivateFile->FilePath) {\r
+        FreePool (PrivateFile->FilePath);\r
+      }\r
+\r
+      FreePool (PrivateFile);\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Count the number of Leading Dot in FileNameToken.\r
+\r
+  @param FileNameToken  A string representing a token in the path name.\r
+\r
+  @return  UINTN             The number of leading dot in the name.\r
+\r
+**/\r
+UINTN\r
+CountLeadingDots (\r
+  IN CONST CHAR16 * FileNameToken\r
+)\r
+{\r
+  UINTN          Num;\r
+\r
+  Num = 0;\r
+  while (*FileNameToken == L'.') {\r
+    Num++;\r
+    FileNameToken++;\r
+  }\r
+\r
+  return Num;\r
+}\r
+\r
+\r
+BOOLEAN\r
+IsFileNameTokenValid (\r
+  IN CONST CHAR16 * FileNameToken\r
+)\r
+{\r
+  UINTN Num;\r
+  if (StrStr (FileNameToken, L"/") != NULL) {\r
+    //\r
+    // No L'/' in file name.\r
+    //\r
+    return FALSE;\r
+  } else {\r
+    //\r
+    // If Token has all dot, the number should not exceed 2\r
+    //\r
+    Num = CountLeadingDots (FileNameToken);\r
+\r
+    if (Num == StrLen (FileNameToken)) {\r
+      //\r
+      // If the FileNameToken only contains a number of L'.'.\r
+      //\r
+      if (Num > 2) {\r
+        return FALSE;\r
+      }\r
+    }\r
+  }\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Return the first string token found in the indirect pointer a String named by FileName.\r
+\r
+  On input, FileName is a indirect pointer pointing to a String.\r
+  On output, FileName is a updated to point to the next character after the first\r
+  found L"\" or NULL if there is no L"\" found.\r
+\r
+  @param FileName  A indirect pointer pointing to a FileName.\r
+\r
+  @return  Token      The first string token found before a L"\".\r
+\r
+**/\r
+CHAR16 *\r
+GetNextFileNameToken (\r
+  IN OUT CONST CHAR16 ** FileName\r
+)\r
+{\r
+  CHAR16 *SlashPos;\r
+  CHAR16 *Token;\r
+  UINTN  Offset;\r
+  ASSERT (**FileName != L'\\');\r
+  ASSERT (**FileName != L'\0');\r
+\r
+  SlashPos = StrStr (*FileName, L"\\");\r
+  if (SlashPos == NULL) {\r
+    Token = AllocateCopyPool (StrSize (*FileName), *FileName);\r
+    *FileName = NULL;\r
+  } else {\r
+    Offset = SlashPos - *FileName;\r
+    Token = AllocateZeroPool ((Offset + 1) * sizeof (CHAR16));\r
+    StrnCpy (Token, *FileName, Offset);\r
+    //\r
+    // Point *FileName to the next character after L'\'.\r
+    //\r
+    *FileName = *FileName + Offset + 1;\r
+    //\r
+    // If *FileName is an empty string, then set *FileName to NULL\r
+    //\r
+    if (**FileName == L'\0') {\r
+      *FileName = NULL;\r
+    }\r
+  }\r
+\r
+  return Token;\r
+}\r
+\r
+\r
+/**\r
+  Check if a FileName contains only Valid Characters.\r
+\r
+  If FileName contains only a single L'\', return TRUE.\r
+  If FileName contains two adjacent L'\', return FALSE.\r
+  If FileName conatins L'/' , return FALSE.\r
+  If FielName contains more than two dots seperated with other FileName characters\r
+  by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.\r
+\r
+  @param FileName  The File Name String to check.\r
+\r
+  @return  TRUE        FileName only contains valid characters.\r
+  @return  FALSE       FileName contains at least one invalid character.\r
+\r
+**/\r
+\r
+BOOLEAN\r
+IsFileNameValid (\r
+  IN CONST CHAR16 *FileName\r
+  )\r
+{\r
+  CHAR16       *Token;\r
+  BOOLEAN      Valid;\r
+\r
+  //\r
+  // If FileName is just L'\', then it is a valid pathname.\r
+  //\r
+  if (StrCmp (FileName, L"\\") == 0) {\r
+    return TRUE;\r
+  }\r
+  //\r
+  // We don't support two or more adjacent L'\'.\r
+  //\r
+  if (StrStr (FileName, L"\\\\") != NULL) {\r
+    return FALSE;\r
+  }\r
+\r
+  //\r
+  // Is FileName has a leading L"\", skip to next character.\r
+  //\r
+  if (FileName [0] == L'\\') {\r
+    FileName++;\r
+  }\r
+\r
+  do {\r
+    Token = GetNextFileNameToken (&FileName);\r
+    Valid = IsFileNameTokenValid (Token);\r
+    FreePool (Token);\r
+\r
+    if (!Valid)\r
+      return FALSE;\r
+  } while (FileName != NULL);\r
+\r
+  return TRUE;\r
+}\r
+\r
+\r
+/**\r
+  Opens a new file relative to the source file's location.\r
+\r
+  @param  This       The protocol instance pointer.\r
+  @param  NewHandle  Returns File Handle for FileName.\r
+  @param  FileName   Null terminated string. "\", ".", and ".." are supported.\r
+  @param  OpenMode   Open mode for file.\r
+  @param  Attributes Only used for EFI_FILE_MODE_CREATE.\r
+\r
+  @retval EFI_SUCCESS          The device was opened.\r
+  @retval EFI_NOT_FOUND        The specified file could not be found on the device.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_MEDIA_CHANGED    The media has changed.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_ACCESS_DENIED    The service denied access to the file.\r
+  @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.\r
+  @retval EFI_VOLUME_FULL      The volume is full.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileOpen (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  OUT EFI_FILE_PROTOCOL       **NewHandle,\r
+  IN CHAR16                   *FileName,\r
+  IN UINT64                   OpenMode,\r
+  IN UINT64                   Attributes\r
+  )\r
+{\r
+  WIN_NT_EFI_FILE_PRIVATE           *PrivateFile;\r
+  WIN_NT_EFI_FILE_PRIVATE           *NewPrivateFile;\r
+  WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
+  EFI_STATUS                        Status;\r
+  CHAR16                            *RealFileName;\r
+  CHAR16                            *TempFileName;\r
+  CHAR16                            *ParseFileName;\r
+  CHAR16                            *GuardPointer;\r
+  CHAR16                            TempChar;\r
+  DWORD                             LastError;\r
+  UINTN                             Count;\r
+  BOOLEAN                           LoopFinish;\r
+  UINTN                             InfoSize;\r
+  EFI_FILE_INFO                     *Info;\r
+  UINTN                             Size;\r
+\r
+\r
+  //\r
+  // Init local variables\r
+  //\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+  PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
+  NewPrivateFile = NULL;\r
+\r
+  //\r
+  // Allocate buffer for FileName as the passed in FileName may be read only\r
+  //\r
+  TempFileName = AllocatePool (StrSize (FileName));\r
+  if (TempFileName == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+  StrCpy (TempFileName, FileName);\r
+  FileName = TempFileName;\r
+\r
+  if (FileName[StrLen (FileName) - 1] == L'\\') {\r
+    FileName[StrLen (FileName) - 1] = 0;\r
+  }\r
+\r
+  //\r
+  // If file name does not equal to "." or ".." and not trailed with "\..",\r
+  // then we trim the leading/trailing blanks and trailing dots\r
+  //\r
+  if (StrCmp (FileName, L".") != 0 && StrCmp (FileName, L"..") != 0 &&\r
+    ((StrLen (FileName) >= 3) ? (StrCmp (&FileName[StrLen (FileName) - 3], L"\\..") != 0) : TRUE)) {\r
+    //\r
+    // Trim leading blanks\r
+    //\r
+    Count = 0;\r
+    for (TempFileName = FileName;\r
+      *TempFileName != 0 && *TempFileName == L' ';\r
+      TempFileName++) {\r
+      Count++;\r
+    }\r
+    CutPrefix (FileName, Count);\r
+    //\r
+    // Trim trailing blanks\r
+    //\r
+    for (TempFileName = FileName + StrLen (FileName) - 1;\r
+      TempFileName >= FileName && (*TempFileName == L' ');\r
+      TempFileName--) {\r
+      ;\r
+    }\r
+    *(TempFileName + 1) = 0;\r
+  }\r
+\r
+  //\r
+  // Attempt to open the file\r
+  //\r
+  NewPrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));\r
+  if (NewPrivateFile == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  CopyMem (NewPrivateFile, PrivateFile, sizeof (WIN_NT_EFI_FILE_PRIVATE));\r
+\r
+  NewPrivateFile->FilePath = AllocatePool (StrSize (PrivateFile->FileName));\r
+  if (NewPrivateFile->FilePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  if (PrivateFile->IsDirectoryPath) {\r
+    StrCpy (NewPrivateFile->FilePath, PrivateFile->FileName);\r
+  } else {\r
+    StrCpy (NewPrivateFile->FilePath, PrivateFile->FilePath);\r
+  }\r
+\r
+  Size = StrSize (NewPrivateFile->FilePath);\r
+  Size += StrSize (L"\\");\r
+  Size += StrSize (FileName);\r
+  NewPrivateFile->FileName = AllocatePool (Size);\r
+  if (NewPrivateFile->FileName == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  if (*FileName == L'\\') {\r
+    StrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);\r
+    StrCat (NewPrivateFile->FileName, L"\\");\r
+    StrCat (NewPrivateFile->FileName, FileName + 1);\r
+  } else {\r
+    StrCpy (NewPrivateFile->FileName, NewPrivateFile->FilePath);\r
+    if (StrCmp (FileName, L"") != 0) {\r
+      //\r
+      // In case the filename becomes empty, especially after trimming dots and blanks\r
+      //\r
+      StrCat (NewPrivateFile->FileName, L"\\");\r
+      StrCat (NewPrivateFile->FileName, FileName);\r
+    }\r
+  }\r
+\r
+  if (!IsFileNameValid (NewPrivateFile->FileName)) {\r
+    Status = EFI_NOT_FOUND;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Get rid of . and .., except leading . or ..\r
+  //\r
+\r
+  //\r
+  // GuardPointer protect simplefilesystem root path not be destroyed\r
+  //\r
+  GuardPointer = NewPrivateFile->FileName + StrLen (PrivateRoot->FilePath);\r
+\r
+  LoopFinish = FALSE;\r
+\r
+  while (!LoopFinish) {\r
+\r
+    LoopFinish = TRUE;\r
+\r
+    for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {\r
+      if (*ParseFileName == L'.' &&\r
+        (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == L'\\') &&\r
+        *(ParseFileName - 1) == L'\\'\r
+        ) {\r
+\r
+        //\r
+        // cut \.\r
+        //\r
+        CutPrefix (ParseFileName - 1, 2);\r
+        LoopFinish = FALSE;\r
+        break;\r
+      }\r
+\r
+      if (*ParseFileName == L'.' &&\r
+        *(ParseFileName + 1) == L'.' &&\r
+        (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == L'\\') &&\r
+        *(ParseFileName - 1) == L'\\'\r
+        ) {\r
+\r
+        ParseFileName--;\r
+        Count = 3;\r
+\r
+        while (ParseFileName != GuardPointer) {\r
+          ParseFileName--;\r
+          Count++;\r
+          if (*ParseFileName == L'\\') {\r
+            break;\r
+          }\r
+        }\r
+\r
+        //\r
+        // cut \.. and its left directory\r
+        //\r
+        CutPrefix (ParseFileName, Count);\r
+        LoopFinish = FALSE;\r
+        break;\r
+      }\r
+    }\r
+  }\r
+\r
+  RealFileName = NewPrivateFile->FileName;\r
+  while (EfiStrChr (RealFileName, L'\\') != NULL) {\r
+    RealFileName = EfiStrChr (RealFileName, L'\\') + 1;\r
+  }\r
+\r
+  TempChar = 0;\r
+  if (RealFileName != NewPrivateFile->FileName) {\r
+    TempChar = *(RealFileName - 1);\r
+    *(RealFileName - 1) = 0;\r
+  }\r
+\r
+  FreePool (NewPrivateFile->FilePath);\r
+  NewPrivateFile->FilePath = NULL;\r
+  NewPrivateFile->FilePath = AllocatePool (StrSize (NewPrivateFile->FileName));\r
+  if (NewPrivateFile->FilePath == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  StrCpy (NewPrivateFile->FilePath, NewPrivateFile->FileName);\r
+  if (TempChar != 0) {\r
+    *(RealFileName - 1) = TempChar;\r
+  }\r
+\r
+  NewPrivateFile->IsRootDirectory = FALSE;\r
+\r
+  //\r
+  // Test whether file or directory\r
+  //\r
+  if (OpenMode & EFI_FILE_MODE_CREATE) {\r
+    if (Attributes & EFI_FILE_DIRECTORY) {\r
+      NewPrivateFile->IsDirectoryPath = TRUE;\r
+    } else {\r
+      NewPrivateFile->IsDirectoryPath = FALSE;\r
+    }\r
+  } else {\r
+    NewPrivateFile->LHandle = CreateFile (\r
+      NewPrivateFile->FileName,\r
+      GENERIC_READ,\r
+      FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+      NULL,\r
+      OPEN_EXISTING,\r
+      0,\r
+      NULL\r
+    );\r
+\r
+    if (NewPrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
+      NewPrivateFile->IsDirectoryPath = FALSE;\r
+      CloseHandle (NewPrivateFile->LHandle);\r
+    } else {\r
+      NewPrivateFile->IsDirectoryPath = TRUE;\r
+    }\r
+\r
+    NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
+  }\r
+\r
+  if (OpenMode & EFI_FILE_MODE_WRITE) {\r
+    NewPrivateFile->IsOpenedByRead = FALSE;\r
+  } else {\r
+    NewPrivateFile->IsOpenedByRead = TRUE;\r
+  }\r
+\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // deal with directory\r
+  //\r
+  if (NewPrivateFile->IsDirectoryPath) {\r
+\r
+    Size = StrSize (NewPrivateFile->FileName);\r
+    Size += StrSize (L"\\*");\r
+    TempFileName = AllocatePool (Size);\r
+    if (TempFileName == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy (TempFileName, NewPrivateFile->FileName);\r
+\r
+    if ((OpenMode & EFI_FILE_MODE_CREATE)) {\r
+      //\r
+      // Create a directory\r
+      //\r
+      if (!CreateDirectory (TempFileName, NULL)) {\r
+\r
+        LastError = GetLastError ();\r
+        if (LastError != ERROR_ALREADY_EXISTS) {\r
+          FreePool (TempFileName);\r
+          Status = EFI_ACCESS_DENIED;\r
+          goto Done;\r
+        }\r
+      }\r
+    }\r
+\r
+    NewPrivateFile->DirHandle = CreateFile (\r
+      TempFileName,\r
+      NewPrivateFile->IsOpenedByRead ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),\r
+      FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+      NULL,\r
+      OPEN_EXISTING,\r
+      FILE_FLAG_BACKUP_SEMANTICS,\r
+      NULL\r
+    );\r
+\r
+    if (NewPrivateFile->DirHandle == INVALID_HANDLE_VALUE) {\r
+\r
+      NewPrivateFile->DirHandle = CreateFile (\r
+        TempFileName,\r
+        GENERIC_READ,\r
+        FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+        NULL,\r
+        OPEN_EXISTING,\r
+        FILE_FLAG_BACKUP_SEMANTICS,\r
+        NULL\r
+      );\r
+\r
+      if (NewPrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
+        CloseHandle (NewPrivateFile->DirHandle);\r
+        NewPrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
+        Status = EFI_ACCESS_DENIED;\r
+      } else {\r
+        Status = EFI_NOT_FOUND;\r
+      }\r
+\r
+      FreePool (TempFileName);\r
+      goto Done;\r
+    }\r
+\r
+    //\r
+    // Find the first file under it\r
+    //\r
+    StrCat (TempFileName, L"\\*");\r
+    NewPrivateFile->LHandle = FindFirstFile (TempFileName, &NewPrivateFile->FindBuf);\r
+    FreePool (TempFileName);\r
+\r
+    if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+      NewPrivateFile->IsValidFindBuf = FALSE;\r
+    } else {\r
+      NewPrivateFile->IsValidFindBuf = TRUE;\r
+    }\r
+  } else {\r
+    //\r
+    // deal with file\r
+    //\r
+    if (!NewPrivateFile->IsOpenedByRead) {\r
+      NewPrivateFile->LHandle = CreateFile (\r
+        NewPrivateFile->FileName,\r
+        GENERIC_READ | GENERIC_WRITE,\r
+        FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+        NULL,\r
+        (OpenMode & EFI_FILE_MODE_CREATE) ? OPEN_ALWAYS : OPEN_EXISTING,\r
+        0,\r
+        NULL\r
+      );\r
+\r
+      if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+        NewPrivateFile->LHandle = CreateFile (\r
+          NewPrivateFile->FileName,\r
+          GENERIC_READ,\r
+          FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+          NULL,\r
+          OPEN_EXISTING,\r
+          0,\r
+          NULL\r
+        );\r
+\r
+        if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+          Status = EFI_NOT_FOUND;\r
+        } else {\r
+          Status = EFI_ACCESS_DENIED;\r
+          CloseHandle (NewPrivateFile->LHandle);\r
+          NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
+        }\r
+      }\r
+    } else {\r
+      NewPrivateFile->LHandle = CreateFile (\r
+        NewPrivateFile->FileName,\r
+        GENERIC_READ,\r
+        FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+        NULL,\r
+        OPEN_EXISTING,\r
+        0,\r
+        NULL\r
+      );\r
+\r
+      if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+        Status = EFI_NOT_FOUND;\r
+      }\r
+    }\r
+  }\r
+\r
+  if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {\r
+    //\r
+    // Set the attribute\r
+    //\r
+    InfoSize = 0;\r
+    Info = NULL;\r
+\r
+    Status = WinNtFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
+\r
+    if (Status != EFI_BUFFER_TOO_SMALL) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Done;\r
+    }\r
+\r
+    Info = AllocatePool (InfoSize);\r
+    if (Info == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    Status = WinNtFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      FreePool (Info);\r
+      goto Done;\r
+    }\r
+\r
+    Info->Attribute = Attributes;\r
+\r
+    WinNtFileSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);\r
+    FreePool (Info);\r
+  }\r
+\r
+Done:\r
+  FreePool (FileName);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    if (NewPrivateFile) {\r
+      if (NewPrivateFile->FileName) {\r
+        FreePool (NewPrivateFile->FileName);\r
+      }\r
+\r
+      if (NewPrivateFile->FilePath) {\r
+        FreePool (NewPrivateFile->FilePath);\r
+      }\r
+\r
+      FreePool (NewPrivateFile);\r
+    }\r
+  } else {\r
+    *NewHandle = &NewPrivateFile->EfiFile;\r
+    if (StrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {\r
+      NewPrivateFile->IsRootDirectory = TRUE;\r
+    }\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Close the file handle\r
+\r
+  @param  This          Protocol instance pointer.\r
+\r
+  @retval EFI_SUCCESS   The device was opened.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileClose (\r
+  IN EFI_FILE_PROTOCOL  *This\r
+  )\r
+{\r
+  WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
+    if (PrivateFile->IsDirectoryPath) {\r
+      FindClose (PrivateFile->LHandle);\r
+    } else {\r
+      CloseHandle (PrivateFile->LHandle);\r
+    }\r
+\r
+    PrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
+  }\r
+\r
+  if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
+    CloseHandle (PrivateFile->DirHandle);\r
+    PrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
+  }\r
+\r
+  if (PrivateFile->FileName) {\r
+    FreePool (PrivateFile->FileName);\r
+  }\r
+\r
+  if (PrivateFile->FilePath) {\r
+    FreePool (PrivateFile->FilePath);\r
+  }\r
+\r
+  FreePool (PrivateFile);\r
+\r
+  return EFI_SUCCESS;\r
+\r
+}\r
+\r
+\r
+/**\r
+  Close and delete the file handle.\r
+\r
+  @param  This                     Protocol instance pointer.\r
+\r
+  @retval EFI_SUCCESS              The device was opened.\r
+  @retval EFI_WARN_DELETE_FAILURE  The handle was closed but the file was not deleted.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileDelete (\r
+  IN EFI_FILE_PROTOCOL  *This\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  Status = EFI_WARN_DELETE_FAILURE;\r
+\r
+  if (PrivateFile->IsDirectoryPath) {\r
+    if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
+      FindClose (PrivateFile->LHandle);\r
+    }\r
+\r
+    if (PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
+      CloseHandle (PrivateFile->DirHandle);\r
+      PrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
+    }\r
+\r
+    if (RemoveDirectory (PrivateFile->FileName)) {\r
+      Status = EFI_SUCCESS;\r
+    }\r
+  } else {\r
+    CloseHandle (PrivateFile->LHandle);\r
+    PrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
+\r
+    if (!PrivateFile->IsOpenedByRead) {\r
+      if (DeleteFile (PrivateFile->FileName)) {\r
+        Status = EFI_SUCCESS;\r
+      }\r
+    }\r
+  }\r
+\r
+  FreePool (PrivateFile->FileName);\r
+  FreePool (PrivateFile->FilePath);\r
+  FreePool (PrivateFile);\r
+\r
+  return Status;\r
+}\r
+\r
+VOID\r
+WinNtSystemTimeToEfiTime (\r
+  IN SYSTEMTIME             *SystemTime,\r
+  IN TIME_ZONE_INFORMATION  *TimeZone,\r
+  OUT EFI_TIME              *Time\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  SystemTime  - TODO: add argument description\r
+  TimeZone    - TODO: add argument description\r
+  Time        - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+{\r
+  Time->Year = (UINT16)SystemTime->wYear;\r
+  Time->Month = (UINT8)SystemTime->wMonth;\r
+  Time->Day = (UINT8)SystemTime->wDay;\r
+  Time->Hour = (UINT8)SystemTime->wHour;\r
+  Time->Minute = (UINT8)SystemTime->wMinute;\r
+  Time->Second = (UINT8)SystemTime->wSecond;\r
+  Time->Nanosecond = (UINT32)SystemTime->wMilliseconds * 1000000;\r
+  Time->TimeZone = (INT16)TimeZone->Bias;\r
+\r
+  if (TimeZone->StandardDate.wMonth) {\r
+    Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
+  }\r
+}\r
+\r
+/**\r
+  Convert the FileTime to EfiTime.\r
+\r
+  @param PrivateFile  Pointer to WIN_NT_EFI_FILE_PRIVATE.\r
+  @param TimeZone     Pointer to the current time zone.\r
+  @param FileTime     Pointer to file time.\r
+  @param EfiTime      Pointer to EFI time.\r
+**/\r
+VOID\r
+WinNtFileTimeToEfiTime (\r
+  IN CONST WIN_NT_EFI_FILE_PRIVATE *PrivateFile,\r
+  IN       TIME_ZONE_INFORMATION   *TimeZone,\r
+  IN CONST FILETIME                *FileTime,\r
+  OUT      EFI_TIME                *EfiTime\r
+)\r
+{\r
+  FILETIME                         TempFileTime;\r
+  SYSTEMTIME                       SystemTime;\r
+\r
+  FileTimeToLocalFileTime (FileTime, &TempFileTime);\r
+  FileTimeToSystemTime (&TempFileTime, &SystemTime);\r
+  WinNtSystemTimeToEfiTime (&SystemTime, TimeZone, EfiTime);\r
+}\r
+\r
+\r
+/**\r
+  Read data from the file.\r
+\r
+  @param  This       Protocol instance pointer.\r
+  @param  BufferSize On input size of buffer, on output amount of data in buffer.\r
+  @param  Buffer     The buffer in which data is read.\r
+\r
+  @retval EFI_SUCCESS          Data was read.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_BUFFER_TO_SMALL  BufferSize is too small. BufferSize contains required size.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileRead (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN OUT UINTN                *BufferSize,\r
+  OUT VOID                    *Buffer\r
+  )\r
+{\r
+  WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
+  EFI_STATUS              Status;\r
+  UINTN                   Size;\r
+  UINTN                   NameSize;\r
+  UINTN                   ResultSize;\r
+  UINTN                   Index;\r
+  EFI_FILE_INFO           *Info;\r
+  WCHAR                   *pw;\r
+  TIME_ZONE_INFORMATION   TimeZone;\r
+  EFI_FILE_INFO           *FileInfo;\r
+  UINT64                  Pos;\r
+  UINT64                  FileSize;\r
+  UINTN                   FileInfoSize;\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  if (!PrivateFile->IsDirectoryPath) {\r
+\r
+    if (This->GetPosition (This, &Pos) != EFI_SUCCESS) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Done;\r
+    }\r
+\r
+    FileInfoSize = SIZE_OF_EFI_FILE_SYSTEM_INFO;\r
+    FileInfo = AllocatePool (FileInfoSize);\r
+\r
+    Status = This->GetInfo (\r
+      This,\r
+      &gEfiFileInfoGuid,\r
+      &FileInfoSize,\r
+      FileInfo\r
+    );\r
+\r
+    if (Status == EFI_BUFFER_TOO_SMALL) {\r
+      FreePool (FileInfo);\r
+      FileInfo = AllocatePool (FileInfoSize);\r
+      Status = This->GetInfo (\r
+        This,\r
+        &gEfiFileInfoGuid,\r
+        &FileInfoSize,\r
+        FileInfo\r
+      );\r
+    }\r
+\r
+    if (EFI_ERROR (Status)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Done;\r
+    }\r
+\r
+    FileSize = FileInfo->FileSize;\r
+\r
+    FreePool (FileInfo);\r
+\r
+    if (Pos >= FileSize) {\r
+      *BufferSize = 0;\r
+      if (Pos == FileSize) {\r
+        Status = EFI_SUCCESS;\r
+        goto Done;\r
+      } else {\r
+        Status = EFI_DEVICE_ERROR;\r
+        goto Done;\r
+      }\r
+    }\r
+\r
+    Status = ReadFile (\r
+      PrivateFile->LHandle,\r
+      Buffer,\r
+      (DWORD)*BufferSize,\r
+      (LPDWORD)BufferSize,\r
+      NULL\r
+    ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Read on a directory.  Perform a find next\r
+  //\r
+  if (!PrivateFile->IsValidFindBuf) {\r
+    *BufferSize = 0;\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  Size = SIZE_OF_EFI_FILE_INFO;\r
+\r
+  NameSize = StrSize (PrivateFile->FindBuf.cFileName);\r
+\r
+  ResultSize = Size + NameSize;\r
+\r
+  Status = EFI_BUFFER_TOO_SMALL;\r
+\r
+  if (*BufferSize >= ResultSize) {\r
+    Status = EFI_SUCCESS;\r
+\r
+    Info = Buffer;\r
+    ZeroMem (Info, ResultSize);\r
+\r
+    Info->Size = ResultSize;\r
+\r
+    GetTimeZoneInformation (&TimeZone);\r
+    WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftCreationTime, &Info->CreateTime);\r
+    WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastAccessTime, &Info->LastAccessTime);\r
+    WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastWriteTime, &Info->ModificationTime);\r
+\r
+    Info->FileSize = PrivateFile->FindBuf.nFileSizeLow;\r
+\r
+    Info->PhysicalSize = PrivateFile->FindBuf.nFileSizeLow;\r
+\r
+    if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {\r
+      Info->Attribute |= EFI_FILE_ARCHIVE;\r
+    }\r
+\r
+    if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {\r
+      Info->Attribute |= EFI_FILE_HIDDEN;\r
+    }\r
+\r
+    if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {\r
+      Info->Attribute |= EFI_FILE_SYSTEM;\r
+    }\r
+\r
+    if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
+      Info->Attribute |= EFI_FILE_READ_ONLY;\r
+    }\r
+\r
+    if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\r
+      Info->Attribute |= EFI_FILE_DIRECTORY;\r
+    }\r
+\r
+    NameSize = NameSize / sizeof (WCHAR);\r
+\r
+    pw = (WCHAR *)(((CHAR8 *)Buffer) + Size);\r
+\r
+    for (Index = 0; Index < NameSize; Index++) {\r
+      pw[Index] = PrivateFile->FindBuf.cFileName[Index];\r
+    }\r
+\r
+    if (FindNextFile (PrivateFile->LHandle, &PrivateFile->FindBuf)) {\r
+      PrivateFile->IsValidFindBuf = TRUE;\r
+    } else {\r
+      PrivateFile->IsValidFindBuf = FALSE;\r
+    }\r
+  }\r
+\r
+  *BufferSize = ResultSize;\r
+\r
+Done:\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Write data to a file.\r
+\r
+  @param  This       Protocol instance pointer.\r
+  @param  BufferSize On input size of buffer, on output amount of data in buffer.\r
+  @param  Buffer     The buffer in which data to write.\r
+\r
+  @retval EFI_SUCCESS          Data was written.\r
+  @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_DEVICE_ERROR     An attempt was made to write to a deleted file.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED  The device is write protected.\r
+  @retval EFI_ACCESS_DENIED    The file was open for read only.\r
+  @retval EFI_VOLUME_FULL      The volume is full.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileWrite (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN OUT UINTN                *BufferSize,\r
+  IN VOID                     *Buffer\r
+  )\r
+{\r
+  WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
+  EFI_STATUS              Status;\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  if (PrivateFile->IsDirectoryPath) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  if (PrivateFile->IsOpenedByRead) {\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto Done;\r
+  }\r
+\r
+  Status = WriteFile (\r
+    PrivateFile->LHandle,\r
+    Buffer,\r
+    (DWORD)*BufferSize,\r
+    (LPDWORD)BufferSize,\r
+    NULL\r
+  ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
+\r
+Done:\r
+  return Status;\r
+\r
+  //\r
+  // bugbug: need to access windows error reporting\r
+  //\r
+}\r
+\r
+\r
+\r
+/**\r
+  Set a files current position\r
+\r
+  @param  This            Protocol instance pointer.\r
+  @param  Position        Byte position from the start of the file.\r
+\r
+  @retval EFI_SUCCESS     Data was written.\r
+  @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileSetPossition (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN UINT64                   Position\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
+  UINT32                  PosLow;\r
+  UINT32                  PosHigh;\r
+  CHAR16                  *FileName;\r
+  UINTN                   Size;\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (PrivateFile->IsDirectoryPath) {\r
+    if (Position != 0) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Done;\r
+    }\r
+\r
+    Size = StrSize (PrivateFile->FileName);\r
+    Size += StrSize (L"\\*");\r
+    FileName = AllocatePool (Size);\r
+    if (FileName == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy (FileName, PrivateFile->FileName);\r
+    StrCat (FileName, L"\\*");\r
+\r
+    if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
+      FindClose (PrivateFile->LHandle);\r
+    }\r
+\r
+    PrivateFile->LHandle = FindFirstFile (FileName, &PrivateFile->FindBuf);\r
+\r
+    if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+      PrivateFile->IsValidFindBuf = FALSE;\r
+    } else {\r
+      PrivateFile->IsValidFindBuf = TRUE;\r
+    }\r
+\r
+    FreePool (FileName);\r
+\r
+    Status = (PrivateFile->LHandle == INVALID_HANDLE_VALUE) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
+  } else {\r
+    if (Position == (UINT64)-1) {\r
+      PosLow = SetFilePointer (PrivateFile->LHandle, (ULONG)0, NULL, FILE_END);\r
+    } else {\r
+      PosHigh = (UINT32)RShiftU64 (Position, 32);\r
+\r
+      PosLow = SetFilePointer (PrivateFile->LHandle, (ULONG)Position, (PLONG)&PosHigh, FILE_BEGIN);\r
+    }\r
+\r
+    Status = (PosLow == 0xFFFFFFFF) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
+  }\r
+\r
+Done:\r
+  return Status;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Get a file's current position\r
+\r
+  @param  This            Protocol instance pointer.\r
+  @param  Position        Byte position from the start of the file.\r
+\r
+  @retval EFI_SUCCESS     Data was written.\r
+  @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileGetPossition (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  OUT UINT64                  *Position\r
+  )\r
+{\r
+  EFI_STATUS              Status;\r
+  WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
+  INT32                   PositionHigh;\r
+  UINT64                  PosHigh64;\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  PositionHigh = 0;\r
+  PosHigh64 = 0;\r
+\r
+  if (PrivateFile->IsDirectoryPath) {\r
+\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+\r
+  } else {\r
+\r
+    PositionHigh = 0;\r
+    *Position = SetFilePointer (\r
+      PrivateFile->LHandle,\r
+      0,\r
+      (PLONG)&PositionHigh,\r
+      FILE_CURRENT\r
+    );\r
+\r
+    Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    PosHigh64 = PositionHigh;\r
+    *Position += LShiftU64 (PosHigh64, 32);\r
+  }\r
+\r
+Done:\r
+  return Status;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+WinNtSimpleFileSystemFileInfo (\r
+  IN     WIN_NT_EFI_FILE_PRIVATE  *PrivateFile,\r
+  IN OUT UINTN                    *BufferSize,\r
+  OUT    VOID                     *Buffer\r
+)\r
+/*++\r
+\r
+Routine Description:\r
+\r
+  TODO: Add function description\r
+\r
+Arguments:\r
+\r
+  PrivateFile - TODO: add argument description\r
+  BufferSize  - TODO: add argument description\r
+  Buffer      - TODO: add argument description\r
+\r
+Returns:\r
+\r
+  TODO: add return values\r
+\r
+--*/\r
+{\r
+  EFI_STATUS                  Status;\r
+  UINTN                       Size;\r
+  UINTN                       NameSize;\r
+  UINTN                       ResultSize;\r
+  EFI_FILE_INFO               *Info;\r
+  BY_HANDLE_FILE_INFORMATION  FileInfo;\r
+  CHAR16                      *RealFileName;\r
+  CHAR16                      *TempPointer;\r
+  TIME_ZONE_INFORMATION       TimeZone;\r
+\r
+  Size = SIZE_OF_EFI_FILE_INFO;\r
+\r
+  RealFileName = PrivateFile->FileName;\r
+  TempPointer = RealFileName;\r
+  while (*TempPointer) {\r
+    if (*TempPointer == '\\') {\r
+      RealFileName = TempPointer + 1;\r
+    }\r
+\r
+    TempPointer++;\r
+  }\r
+  NameSize = StrSize (RealFileName);\r
+\r
+  ResultSize = Size + NameSize;\r
+\r
+  Status = EFI_BUFFER_TOO_SMALL;\r
+  if (*BufferSize >= ResultSize) {\r
+    Status = EFI_SUCCESS;\r
+\r
+    Info = Buffer;\r
+    ZeroMem (Info, ResultSize);\r
+\r
+    Info->Size = ResultSize;\r
+    GetFileInformationByHandle (\r
+      PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,\r
+      &FileInfo\r
+    );\r
+    Info->FileSize = FileInfo.nFileSizeLow;\r
+    Info->PhysicalSize = Info->FileSize;\r
+\r
+    GetTimeZoneInformation (&TimeZone);\r
+    WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftCreationTime, &Info->CreateTime);\r
+    WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastAccessTime, &Info->LastAccessTime);\r
+    WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastWriteTime, &Info->ModificationTime);\r
+\r
+    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {\r
+      Info->Attribute |= EFI_FILE_ARCHIVE;\r
+    }\r
+\r
+    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {\r
+      Info->Attribute |= EFI_FILE_HIDDEN;\r
+    }\r
+\r
+    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
+      Info->Attribute |= EFI_FILE_READ_ONLY;\r
+    }\r
+\r
+    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {\r
+      Info->Attribute |= EFI_FILE_SYSTEM;\r
+    }\r
+\r
+    if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\r
+      Info->Attribute |= EFI_FILE_DIRECTORY;\r
+    }\r
+\r
+    if (PrivateFile->IsDirectoryPath) {\r
+      Info->Attribute |= EFI_FILE_DIRECTORY;\r
+    }\r
+\r
+    if (PrivateFile->IsRootDirectory) {\r
+      *((CHAR8 *)Buffer + Size) = 0;\r
+    } else {\r
+      CopyMem ((CHAR8 *)Buffer + Size, RealFileName, NameSize);\r
+    }\r
+  }\r
+\r
+  *BufferSize = ResultSize;\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Get information about a file.\r
+\r
+  @param  This            Protocol instance pointer.\r
+  @param  InformationType Type of information to return in Buffer.\r
+  @param  BufferSize      On input size of buffer, on output amount of data in buffer.\r
+  @param  Buffer          The buffer to return data.\r
+\r
+  @retval EFI_SUCCESS          Data was returned.\r
+  @retval EFI_UNSUPPORTED      InformationType is not supported.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED  The device is write protected.\r
+  @retval EFI_ACCESS_DENIED    The file was open for read only.\r
+  @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileGetInfo (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN EFI_GUID                 *InformationType,\r
+  IN OUT UINTN                *BufferSize,\r
+  OUT VOID                    *Buffer\r
+  )\r
+{\r
+  EFI_STATUS                        Status;\r
+  WIN_NT_EFI_FILE_PRIVATE           *PrivateFile;\r
+  EFI_FILE_SYSTEM_INFO              *FileSystemInfoBuffer;\r
+  UINT32                            SectorsPerCluster;\r
+  UINT32                            BytesPerSector;\r
+  UINT32                            FreeClusters;\r
+  UINT32                            TotalClusters;\r
+  UINT32                            BytesPerCluster;\r
+  CHAR16                            *DriveName;\r
+  BOOLEAN                           DriveNameFound;\r
+  BOOL                              NtStatus;\r
+  UINTN                             Index;\r
+  WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
+\r
+  if (This == NULL || InformationType == NULL || BufferSize == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+  PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
+\r
+  Status = EFI_UNSUPPORTED;\r
+\r
+  if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
+    Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);\r
+  }\r
+\r
+  if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
+    if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
+      *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto Done;\r
+    }\r
+\r
+    FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *)Buffer;\r
+    FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
+    FileSystemInfoBuffer->ReadOnly = FALSE;\r
+\r
+    //\r
+    // Try to get the drive name\r
+    //\r
+    DriveNameFound = FALSE;\r
+    DriveName = AllocatePool (StrSize (PrivateFile->FilePath) + 1);\r
+    if (DriveName == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy (DriveName, PrivateFile->FilePath);\r
+    for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) {\r
+      ;\r
+    }\r
+\r
+    if (DriveName[Index] == ':') {\r
+      DriveName[Index + 1] = '\\';\r
+      DriveName[Index + 2] = 0;\r
+      DriveNameFound = TRUE;\r
+    } else if (DriveName[0] == '\\' && DriveName[1] == '\\') {\r
+      for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {\r
+        ;\r
+      }\r
+\r
+      if (DriveName[Index] == '\\') {\r
+        DriveNameFound = TRUE;\r
+        for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {\r
+          ;\r
+        }\r
+\r
+        DriveName[Index] = '\\';\r
+        DriveName[Index + 1] = 0;\r
+      }\r
+    }\r
+\r
+    //\r
+    // Try GetDiskFreeSpace first\r
+    //\r
+    NtStatus = GetDiskFreeSpace (\r
+      DriveNameFound ? DriveName : NULL,\r
+      (LPDWORD)&SectorsPerCluster,\r
+      (LPDWORD)&BytesPerSector,\r
+      (LPDWORD)&FreeClusters,\r
+      (LPDWORD)&TotalClusters\r
+    );\r
+    if (DriveName) {\r
+      FreePool (DriveName);\r
+    }\r
+\r
+    if (NtStatus) {\r
+      //\r
+      // Succeeded\r
+      //\r
+      BytesPerCluster = BytesPerSector * SectorsPerCluster;\r
+      FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster);\r
+      FileSystemInfoBuffer->FreeSpace = MultU64x32 (FreeClusters, BytesPerCluster);\r
+      FileSystemInfoBuffer->BlockSize = BytesPerCluster;\r
+\r
+    } else {\r
+      //\r
+      // try GetDiskFreeSpaceEx then\r
+      //\r
+      FileSystemInfoBuffer->BlockSize = 0;\r
+      NtStatus = GetDiskFreeSpaceEx (\r
+        PrivateFile->FilePath,\r
+        (PULARGE_INTEGER)(&FileSystemInfoBuffer->FreeSpace),\r
+        (PULARGE_INTEGER)(&FileSystemInfoBuffer->VolumeSize),\r
+        NULL\r
+      );\r
+      if (!NtStatus) {\r
+        Status = EFI_DEVICE_ERROR;\r
+        goto Done;\r
+      }\r
+    }\r
+\r
+    StrCpy ((CHAR16 *)FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);\r
+    *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+  if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
+    if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
+      *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
+      Status = EFI_BUFFER_TOO_SMALL;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy ((CHAR16 *)Buffer, PrivateRoot->VolumeLabel);\r
+    *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
+    Status = EFI_SUCCESS;\r
+  }\r
+\r
+Done:\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Set information about a file\r
+\r
+  @param  File            Protocol instance pointer.\r
+  @param  InformationType Type of information in Buffer.\r
+  @param  BufferSize      Size of buffer.\r
+  @param  Buffer          The data to write.\r
+\r
+  @retval EFI_SUCCESS          Data was returned.\r
+  @retval EFI_UNSUPPORTED      InformationType is not supported.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED  The device is write protected.\r
+  @retval EFI_ACCESS_DENIED    The file was open for read only.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileSetInfo (\r
+  IN EFI_FILE_PROTOCOL        *This,\r
+  IN EFI_GUID                 *InformationType,\r
+  IN UINTN                    BufferSize,\r
+  IN VOID                     *Buffer\r
+  )\r
+{\r
+  WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
+  WIN_NT_EFI_FILE_PRIVATE           *PrivateFile;\r
+  EFI_FILE_INFO                     *OldFileInfo;\r
+  EFI_FILE_INFO                     *NewFileInfo;\r
+  EFI_STATUS                        Status;\r
+  UINTN                             OldInfoSize;\r
+  INTN                              NtStatus;\r
+  UINT32                            NewAttr;\r
+  UINT32                            OldAttr;\r
+  CHAR16                            *OldFileName;\r
+  CHAR16                            *NewFileName;\r
+  CHAR16                            *TempFileName;\r
+  CHAR16                            *CharPointer;\r
+  BOOLEAN                           AttrChangeFlag;\r
+  BOOLEAN                           NameChangeFlag;\r
+  BOOLEAN                           SizeChangeFlag;\r
+  BOOLEAN                           TimeChangeFlag;\r
+  UINT64                            CurPos;\r
+  SYSTEMTIME                        NewCreationSystemTime;\r
+  SYSTEMTIME                        NewLastAccessSystemTime;\r
+  SYSTEMTIME                        NewLastWriteSystemTime;\r
+  FILETIME                          NewCreationFileTime;\r
+  FILETIME                          NewLastAccessFileTime;\r
+  FILETIME                          NewLastWriteFileTime;\r
+  WIN32_FIND_DATA                   FindBuf;\r
+  EFI_FILE_SYSTEM_INFO              *NewFileSystemInfo;\r
+  UINTN                             Size;\r
+\r
+  //\r
+  // Initialise locals.\r
+  //\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+  PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
+\r
+  Status = EFI_UNSUPPORTED;\r
+  OldFileInfo = NewFileInfo = NULL;\r
+  OldFileName = NewFileName = NULL;\r
+  AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;\r
+\r
+  //\r
+  // Set file system information.\r
+  //\r
+  if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
+    NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;\r
+    if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (NewFileSystemInfo->VolumeLabel)) {\r
+      Status = EFI_BAD_BUFFER_SIZE;\r
+      goto Done;\r
+    }\r
+\r
+\r
+    FreePool (PrivateRoot->VolumeLabel);\r
+    PrivateRoot->VolumeLabel = AllocatePool (StrSize (NewFileSystemInfo->VolumeLabel));\r
+    if (PrivateRoot->VolumeLabel == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);\r
+\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Set volume label information.\r
+  //\r
+  if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
+    if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
+      Status = EFI_BAD_BUFFER_SIZE;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *)Buffer);\r
+\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
+    Status = EFI_UNSUPPORTED;\r
+    goto Done;\r
+  }\r
+\r
+  if (BufferSize < SIZE_OF_EFI_FILE_INFO) {\r
+    Status = EFI_BAD_BUFFER_SIZE;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Set file/directory information.\r
+  //\r
+\r
+  //\r
+  // Check for invalid set file information parameters.\r
+  //\r
+  NewFileInfo = (EFI_FILE_INFO *)Buffer;\r
+\r
+  if ((NewFileInfo->Size <= SIZE_OF_EFI_FILE_INFO) ||\r
+    (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||\r
+    (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)\r
+    ) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // bugbug: - This is not safe.  We need something like EfiStrMaxSize()\r
+  // that would have an additional parameter that would be the size\r
+  // of the string array just in case there are no NULL characters in\r
+  // the string array.\r
+  //\r
+  //\r
+  // Get current file information so we can determine what kind\r
+  // of change request this is.\r
+  //\r
+  OldInfoSize = 0;\r
+  Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL);\r
+\r
+  if (Status != EFI_BUFFER_TOO_SMALL) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  OldFileInfo = AllocatePool (OldInfoSize);\r
+  if (OldFileInfo == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto Done;\r
+  }\r
+\r
+  OldFileName = AllocatePool (StrSize (PrivateFile->FileName));\r
+  if (OldFileName == NULL) {\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
+  }\r
+\r
+  StrCpy (OldFileName, PrivateFile->FileName);\r
+\r
+  //\r
+  // Make full pathname from new filename and rootpath.\r
+  //\r
+  if (NewFileInfo->FileName[0] == '\\') {\r
+    Size = StrSize (PrivateRoot->FilePath);\r
+    Size += StrSize (L"\\");\r
+    Size += StrSize (NewFileInfo->FileName);\r
+    NewFileName = AllocatePool (Size);\r
+    if (NewFileName == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy (NewFileName, PrivateRoot->FilePath);\r
+    StrCat (NewFileName, L"\\");\r
+    StrCat (NewFileName, NewFileInfo->FileName + 1);\r
+  } else {\r
+    Size = StrSize (PrivateFile->FilePath);\r
+    Size += StrSize (L"\\");\r
+    Size += StrSize (NewFileInfo->FileName);\r
+    NewFileName = AllocatePool (Size);\r
+    if (NewFileName == NULL) {\r
+      Status = EFI_OUT_OF_RESOURCES;\r
+      goto Done;\r
+    }\r
+\r
+    StrCpy (NewFileName, PrivateFile->FilePath);\r
+    StrCat (NewFileName, L"\\");\r
+    StrCat (NewFileName, NewFileInfo->FileName);\r
+  }\r
+\r
+  //\r
+  // Is there an attribute change request?\r
+  //\r
+  if (NewFileInfo->Attribute != OldFileInfo->Attribute) {\r
+    if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
+      Status = EFI_INVALID_PARAMETER;\r
+      goto Done;\r
+    }\r
+\r
+    AttrChangeFlag = TRUE;\r
+  }\r
+\r
+  //\r
+  // Is there a name change request?\r
+  // bugbug: - Need EfiStrCaseCmp()\r
+  //\r
+  if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {\r
+    NameChangeFlag = TRUE;\r
+  }\r
+\r
+  //\r
+  // Is there a size change request?\r
+  //\r
+  if (NewFileInfo->FileSize != OldFileInfo->FileSize) {\r
+    SizeChangeFlag = TRUE;\r
+  }\r
+\r
+  //\r
+  // Is there a time stamp change request?\r
+  //\r
+  if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&\r
+    CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))\r
+    ) {\r
+    TimeChangeFlag = TRUE;\r
+  } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&\r
+    CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))\r
+    ) {\r
+    TimeChangeFlag = TRUE;\r
+  } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&\r
+    CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))\r
+    ) {\r
+    TimeChangeFlag = TRUE;\r
+  }\r
+\r
+  //\r
+  // All done if there are no change requests being made.\r
+  //\r
+  if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  //\r
+  // Set file or directory information.\r
+  //\r
+  OldAttr = GetFileAttributes (OldFileName);\r
+\r
+  //\r
+  // Name change.\r
+  //\r
+  if (NameChangeFlag) {\r
+    //\r
+    // Close the handles first\r
+    //\r
+    if (PrivateFile->IsOpenedByRead) {\r
+      Status = EFI_ACCESS_DENIED;\r
+      goto Done;\r
+    }\r
+\r
+    for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {\r
+    }\r
+\r
+    if (*CharPointer != 0) {\r
+      Status = EFI_ACCESS_DENIED;\r
+      goto Done;\r
+    }\r
+\r
+    if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
+      if (PrivateFile->IsDirectoryPath) {\r
+        FindClose (PrivateFile->LHandle);\r
+      } else {\r
+        CloseHandle (PrivateFile->LHandle);\r
+        PrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
+      }\r
+    }\r
+\r
+    if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
+      CloseHandle (PrivateFile->DirHandle);\r
+      PrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
+    }\r
+\r
+    NtStatus = MoveFile (OldFileName, NewFileName);\r
+\r
+    if (NtStatus) {\r
+      //\r
+      // modify file name\r
+      //\r
+      FreePool (PrivateFile->FileName);\r
+\r
+      PrivateFile->FileName = AllocatePool (StrSize (NewFileName));\r
+      if (PrivateFile->FileName == NULL) {\r
+        Status = EFI_OUT_OF_RESOURCES;\r
+        goto Done;\r
+      }\r
+\r
+      StrCpy (PrivateFile->FileName, NewFileName);\r
+\r
+      Size = StrSize (NewFileName);\r
+      Size += StrSize (L"\\*");\r
+      TempFileName = AllocatePool (Size);\r
+\r
+      StrCpy (TempFileName, NewFileName);\r
+\r
+      if (!PrivateFile->IsDirectoryPath) {\r
+        PrivateFile->LHandle = CreateFile (\r
+          TempFileName,\r
+          PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
+          FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+          NULL,\r
+          OPEN_EXISTING,\r
+          0,\r
+          NULL\r
+        );\r
+\r
+        FreePool (TempFileName);\r
+\r
+        //\r
+        //  Flush buffers just in case\r
+        //\r
+        if (FlushFileBuffers (PrivateFile->LHandle) == 0) {\r
+          Status = EFI_DEVICE_ERROR;\r
+          goto Done;\r
+        }\r
+      } else {\r
+        PrivateFile->DirHandle = CreateFile (\r
+          TempFileName,\r
+          PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
+          FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+          NULL,\r
+          OPEN_EXISTING,\r
+          FILE_FLAG_BACKUP_SEMANTICS,\r
+          NULL\r
+        );\r
+\r
+        StrCat (TempFileName, L"\\*");\r
+        PrivateFile->LHandle = FindFirstFile (TempFileName, &FindBuf);\r
+\r
+        FreePool (TempFileName);\r
+      }\r
+    } else {\r
+      Status = EFI_ACCESS_DENIED;\r
+    Reopen:;\r
+\r
+      NtStatus = SetFileAttributes (OldFileName, OldAttr);\r
+\r
+      if (!NtStatus) {\r
+        goto Done;\r
+      }\r
+\r
+      Size = StrSize (OldFileName);\r
+      Size += StrSize (L"\\*");\r
+      TempFileName = AllocatePool (Size);\r
+\r
+      StrCpy (TempFileName, OldFileName);\r
+\r
+      if (!PrivateFile->IsDirectoryPath) {\r
+        PrivateFile->LHandle = CreateFile (\r
+          TempFileName,\r
+          PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
+          FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+          NULL,\r
+          OPEN_EXISTING,\r
+          0,\r
+          NULL\r
+        );\r
+      } else {\r
+        PrivateFile->DirHandle = CreateFile (\r
+          TempFileName,\r
+          PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
+          FILE_SHARE_READ | FILE_SHARE_WRITE,\r
+          NULL,\r
+          OPEN_EXISTING,\r
+          FILE_FLAG_BACKUP_SEMANTICS,\r
+          NULL\r
+        );\r
+\r
+        StrCat (TempFileName, L"\\*");\r
+        PrivateFile->LHandle = FindFirstFile (TempFileName, &FindBuf);\r
+      }\r
+\r
+      FreePool (TempFileName);\r
+\r
+      goto Done;\r
+\r
+    }\r
+  }\r
+\r
+  //\r
+  //  Size change\r
+  //\r
+  if (SizeChangeFlag) {\r
+    if (PrivateFile->IsDirectoryPath) {\r
+      Status = EFI_UNSUPPORTED;\r
+      goto Done;\r
+    }\r
+\r
+    if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
+      Status = EFI_ACCESS_DENIED;\r
+      goto Done;\r
+    }\r
+\r
+    Status = This->GetPosition (This, &CurPos);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    Status = This->SetPosition (This, NewFileInfo->FileSize);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+\r
+    if (SetEndOfFile (PrivateFile->LHandle) == 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Done;\r
+    }\r
+\r
+    Status = This->SetPosition (This, CurPos);\r
+    if (EFI_ERROR (Status)) {\r
+      goto Done;\r
+    }\r
+  }\r
+\r
+  //\r
+  // Time change\r
+  //\r
+  if (TimeChangeFlag) {\r
+\r
+    NewCreationSystemTime.wYear = NewFileInfo->CreateTime.Year;\r
+    NewCreationSystemTime.wMonth = NewFileInfo->CreateTime.Month;\r
+    NewCreationSystemTime.wDay = NewFileInfo->CreateTime.Day;\r
+    NewCreationSystemTime.wHour = NewFileInfo->CreateTime.Hour;\r
+    NewCreationSystemTime.wMinute = NewFileInfo->CreateTime.Minute;\r
+    NewCreationSystemTime.wSecond = NewFileInfo->CreateTime.Second;\r
+    NewCreationSystemTime.wMilliseconds = 0;\r
+\r
+    if (!SystemTimeToFileTime (\r
+      &NewCreationSystemTime,\r
+      &NewCreationFileTime\r
+    )) {\r
+      goto Done;\r
+    }\r
+\r
+    if (!LocalFileTimeToFileTime (\r
+      &NewCreationFileTime,\r
+      &NewCreationFileTime\r
+    )) {\r
+      goto Done;\r
+    }\r
+\r
+    NewLastAccessSystemTime.wYear = NewFileInfo->LastAccessTime.Year;\r
+    NewLastAccessSystemTime.wMonth = NewFileInfo->LastAccessTime.Month;\r
+    NewLastAccessSystemTime.wDay = NewFileInfo->LastAccessTime.Day;\r
+    NewLastAccessSystemTime.wHour = NewFileInfo->LastAccessTime.Hour;\r
+    NewLastAccessSystemTime.wMinute = NewFileInfo->LastAccessTime.Minute;\r
+    NewLastAccessSystemTime.wSecond = NewFileInfo->LastAccessTime.Second;\r
+    NewLastAccessSystemTime.wMilliseconds = 0;\r
+\r
+    if (!SystemTimeToFileTime (\r
+      &NewLastAccessSystemTime,\r
+      &NewLastAccessFileTime\r
+    )) {\r
+      goto Done;\r
+    }\r
+\r
+    if (!LocalFileTimeToFileTime (\r
+      &NewLastAccessFileTime,\r
+      &NewLastAccessFileTime\r
+    )) {\r
+      goto Done;\r
+    }\r
+\r
+    NewLastWriteSystemTime.wYear = NewFileInfo->ModificationTime.Year;\r
+    NewLastWriteSystemTime.wMonth = NewFileInfo->ModificationTime.Month;\r
+    NewLastWriteSystemTime.wDay = NewFileInfo->ModificationTime.Day;\r
+    NewLastWriteSystemTime.wHour = NewFileInfo->ModificationTime.Hour;\r
+    NewLastWriteSystemTime.wMinute = NewFileInfo->ModificationTime.Minute;\r
+    NewLastWriteSystemTime.wSecond = NewFileInfo->ModificationTime.Second;\r
+    NewLastWriteSystemTime.wMilliseconds = 0;\r
+\r
+    if (!SystemTimeToFileTime (\r
+      &NewLastWriteSystemTime,\r
+      &NewLastWriteFileTime\r
+    )) {\r
+      goto Done;\r
+    }\r
+\r
+    if (!LocalFileTimeToFileTime (\r
+      &NewLastWriteFileTime,\r
+      &NewLastWriteFileTime\r
+    )) {\r
+      goto Done;\r
+    }\r
+\r
+    if (!SetFileTime (\r
+      PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,\r
+      &NewCreationFileTime,\r
+      &NewLastAccessFileTime,\r
+      &NewLastWriteFileTime\r
+    )) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto Done;\r
+    }\r
+\r
+  }\r
+\r
+  //\r
+  // No matter about AttrChangeFlag, Attribute must be set.\r
+  // Because operation before may cause attribute change.\r
+  //\r
+  NewAttr = OldAttr;\r
+\r
+  if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) {\r
+    NewAttr |= FILE_ATTRIBUTE_ARCHIVE;\r
+  } else {\r
+    NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE;\r
+  }\r
+\r
+  if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) {\r
+    NewAttr |= FILE_ATTRIBUTE_HIDDEN;\r
+  } else {\r
+    NewAttr &= ~FILE_ATTRIBUTE_HIDDEN;\r
+  }\r
+\r
+  if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) {\r
+    NewAttr |= FILE_ATTRIBUTE_SYSTEM;\r
+  } else {\r
+    NewAttr &= ~FILE_ATTRIBUTE_SYSTEM;\r
+  }\r
+\r
+  if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
+    NewAttr |= FILE_ATTRIBUTE_READONLY;\r
+  } else {\r
+    NewAttr &= ~FILE_ATTRIBUTE_READONLY;\r
+  }\r
+\r
+  NtStatus = SetFileAttributes (NewFileName, NewAttr);\r
+\r
+  if (!NtStatus) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Reopen;\r
+  }\r
+\r
+Done:\r
+  if (OldFileInfo != NULL) {\r
+    FreePool (OldFileInfo);\r
+  }\r
+\r
+  if (OldFileName != NULL) {\r
+    FreePool (OldFileName);\r
+  }\r
+\r
+  if (NewFileName != NULL) {\r
+    FreePool (NewFileName);\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+\r
+/**\r
+  Flush data back for the file handle.\r
+\r
+  @param  This Protocol instance pointer.\r
+\r
+  @retval EFI_SUCCESS          Data was written.\r
+  @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.\r
+  @retval EFI_NO_MEDIA         The device has no media.\r
+  @retval EFI_DEVICE_ERROR     The device reported an error.\r
+  @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.\r
+  @retval EFI_WRITE_PROTECTED  The device is write protected.\r
+  @retval EFI_ACCESS_DENIED    The file was open for read only.\r
+  @retval EFI_VOLUME_FULL      The volume is full.\r
+\r
+**/\r
+EFI_STATUS\r
+WinNtFileFlush (\r
+  IN EFI_FILE_PROTOCOL  *This\r
+  )\r
+{\r
+  BY_HANDLE_FILE_INFORMATION  FileInfo;\r
+  WIN_NT_EFI_FILE_PRIVATE     *PrivateFile;\r
+  EFI_STATUS                  Status;\r
+\r
+  PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
+\r
+  if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto Done;\r
+  }\r
+\r
+  if (PrivateFile->IsDirectoryPath) {\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
+  }\r
+\r
+  if (PrivateFile->IsOpenedByRead) {\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto Done;\r
+  }\r
+\r
+  GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo);\r
+\r
+  if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
+    Status = EFI_ACCESS_DENIED;\r
+    goto Done;\r
+  }\r
+\r
+  Status = FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
+\r
+Done:\r
+  return Status;\r
+  //\r
+  // bugbug: - Use Windows error reporting.\r
+  //\r
+\r
+}\r
+\r
+\r
+\r
+EFI_STATUS\r
+WinNtFileSystmeThunkOpen (\r
+  IN  EMU_IO_THUNK_PROTOCOL   *This\r
+  )\r
+{\r
+  WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *Private;\r
+\r
+  Private = AllocateZeroPool (sizeof (*Private));\r
+  if (Private == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Private->FilePath = AllocateCopyPool (StrSize (This->ConfigString), This->ConfigString);\r
+  if (Private->FilePath == NULL) {\r
+    FreePool (Private);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Private->VolumeLabel = AllocateCopyPool (StrSize (L"EFI_EMULATED"), L"EFI_EMULATED");\r
+  if (Private->VolumeLabel == NULL) {\r
+    FreePool (Private->FilePath);\r
+    FreePool (Private);\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
+\r
+  Private->Signature = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;\r
+  Private->Thunk     = This;\r
+  CopyMem (&Private->SimpleFileSystem, &gWinNtFileSystemProtocol, sizeof (Private->SimpleFileSystem));\r
+\r
+  This->Interface = &Private->SimpleFileSystem;\r
+  This->Private   = Private;\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_STATUS\r
+WinNtFileSystmeThunkClose (\r
+  IN  EMU_IO_THUNK_PROTOCOL   *This\r
+  )\r
+{\r
+  WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *Private;\r
+\r
+  Private = This->Private;\r
+  ASSERT (Private != NULL);\r
+\r
+  if (Private->VolumeLabel != NULL) {\r
+    FreePool (Private->VolumeLabel);\r
+  }\r
+  if (Private->FilePath != NULL) {\r
+    FreePool (Private->FilePath);\r
+  }\r
+  FreePool (Private);\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+EFI_FILE_PROTOCOL gWinNtFileProtocol = {\r
+  EFI_FILE_REVISION,\r
+  WinNtFileOpen,\r
+  WinNtFileClose,\r
+  WinNtFileDelete,\r
+  WinNtFileRead,\r
+  WinNtFileWrite,\r
+  WinNtFileGetPossition,\r
+  WinNtFileSetPossition,\r
+  WinNtFileGetInfo,\r
+  WinNtFileSetInfo,\r
+  WinNtFileFlush\r
+};\r
+\r
+EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol = {\r
+  EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,\r
+  WinNtOpenVolume\r
+};\r
+\r
+\r
+EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo = {\r
+  &gEfiSimpleFileSystemProtocolGuid,\r
+  NULL,\r
+  NULL,\r
+  0,\r
+  WinNtFileSystmeThunkOpen,\r
+  WinNtFileSystmeThunkClose,\r
+  NULL\r
+};\r
+\r
+\r
index f8d21d26d9ff329e2d06374d36374169a86b395f..266ae5938275992ace23d4c5db9f8fe782e1e681 100644 (file)
@@ -428,6 +428,7 @@ Returns:
   // Emulator Bus Driver Thunks\r
   //\r
   AddThunkProtocol (&mWinNtWndThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuGop), TRUE);\r
+  AddThunkProtocol (&mWinNtFileSystemThunkIo, (CHAR16 *)PcdGetPtr (PcdEmuFileSystem), TRUE);\r
 \r
   //\r
   // Allocate space for gSystemMemory Array\r
index 3dc6a7e641379dcba2a90ca6a6f4db5e3e1be657..3c7529fa91ea6380792cac57ee998153d1e80482 100644 (file)
@@ -26,8 +26,12 @@ Abstract:
 \r
 #include <PiPei.h>\r
 #include <IndustryStandard/PeImage.h>\r
+#include <Guid/FileInfo.h>\r
+#include <Guid/FileSystemInfo.h>\r
+#include <Guid/FileSystemVolumeLabelInfo.h>\r
 #include <Ppi/EmuThunk.h>\r
 #include <Protocol/EmuThunk.h>\r
+#include <Protocol/SimpleFileSystem.h>\r
 \r
 \r
 #include <Library/BaseLib.h>\r
@@ -198,4 +202,5 @@ SecInitializeThunk (
 );\r
 extern EMU_THUNK_PROTOCOL    gEmuThunkProtocol;\r
 extern EMU_IO_THUNK_PROTOCOL mWinNtWndThunkIo;\r
+extern EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo;\r
 #endif
\ No newline at end of file
index b62791bcfaf99c235585e7671510c3016f5f7165..358d0008579902c2390af2f32512d4f9cda2fb91 100644 (file)
@@ -33,6 +33,7 @@
   WinGopInput.c\r
   WinGopScreen.c\r
   WinGop.h\r
+  WinFileSystem.c\r
   WinThunk.c\r
   WinHost.h\r
   WinHost.c\r
 [Protocols]\r
   gEmuIoThunkProtocolGuid\r
   gEmuGraphicsWindowProtocolGuid\r
+  gEfiSimpleFileSystemProtocolGuid\r
+\r
+[Guids]\r
+  gEfiFileSystemVolumeLabelInfoIdGuid           # SOMETIMES_CONSUMED\r
+  gEfiFileInfoGuid                              # SOMETIMES_CONSUMED\r
+  gEfiFileSystemInfoGuid                        # SOMETIMES_CONSUMED\r
+\r
 [Pcd]\r
   gEfiMdeModulePkgTokenSpaceGuid.PcdInitValueInTempStack\r
 \r
@@ -69,6 +77,7 @@
   gEmulatorPkgTokenSpaceGuid.PcdEmuMemorySize\r
   gEmulatorPkgTokenSpaceGuid.PcdEmuFdBaseAddress\r
   gEmulatorPkgTokenSpaceGuid.PcdEmuGop|L"GOP Window"\r
+  gEmulatorPkgTokenSpaceGuid.PcdEmuFileSystem\r
   gEmulatorPkgTokenSpaceGuid.PcdPeiServicesTablePage\r
 \r
 [BuildOptions]\r