REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the EmulatorPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			2427 lines
		
	
	
		
			68 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2427 lines
		
	
	
		
			68 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*++ @file
 | |
|   Support OS native directory access.
 | |
| 
 | |
| Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
 | |
| SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
| 
 | |
| **/
 | |
| 
 | |
| #include "WinHost.h"
 | |
| 
 | |
| #define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE  SIGNATURE_32 ('N', 'T', 'f', 's')
 | |
| 
 | |
| typedef struct {
 | |
|   UINTN                              Signature;
 | |
|   EMU_IO_THUNK_PROTOCOL              *Thunk;
 | |
|   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL    SimpleFileSystem;
 | |
|   CHAR16                             *FilePath;
 | |
|   CHAR16                             *VolumeLabel;
 | |
| } WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE;
 | |
| 
 | |
| #define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \
 | |
|   CR (a, \
 | |
|       WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE, \
 | |
|       SimpleFileSystem, \
 | |
|       WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \
 | |
|       )
 | |
| 
 | |
| #define WIN_NT_EFI_FILE_PRIVATE_SIGNATURE  SIGNATURE_32 ('l', 'o', 'f', 's')
 | |
| 
 | |
| typedef struct {
 | |
|   UINTN                              Signature;
 | |
|   EMU_IO_THUNK_PROTOCOL              *Thunk;
 | |
|   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL    *SimpleFileSystem;
 | |
|   EFI_FILE_PROTOCOL                  EfiFile;
 | |
|   HANDLE                             LHandle;
 | |
|   HANDLE                             DirHandle;
 | |
|   BOOLEAN                            IsRootDirectory;
 | |
|   BOOLEAN                            IsDirectoryPath;
 | |
|   BOOLEAN                            IsOpenedByRead;
 | |
|   CHAR16                             *FilePath;
 | |
|   WCHAR                              *FileName;
 | |
|   BOOLEAN                            IsValidFindBuf;
 | |
|   WIN32_FIND_DATA                    FindBuf;
 | |
| } WIN_NT_EFI_FILE_PRIVATE;
 | |
| 
 | |
| #define WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \
 | |
|   CR (a, \
 | |
|       WIN_NT_EFI_FILE_PRIVATE, \
 | |
|       EfiFile, \
 | |
|       WIN_NT_EFI_FILE_PRIVATE_SIGNATURE \
 | |
|       )
 | |
| 
 | |
| extern EFI_FILE_PROTOCOL                gWinNtFileProtocol;
 | |
| extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  gWinNtFileSystemProtocol;
 | |
| 
 | |
| EFI_STATUS
 | |
| WinNtFileGetInfo (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN EFI_GUID           *InformationType,
 | |
|   IN OUT UINTN          *BufferSize,
 | |
|   OUT VOID              *Buffer
 | |
|   );
 | |
| 
 | |
| EFI_STATUS
 | |
| WinNtFileSetInfo (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN EFI_GUID           *InformationType,
 | |
|   IN UINTN              BufferSize,
 | |
|   IN VOID               *Buffer
 | |
|   );
 | |
| 
 | |
| CHAR16 *
 | |
| EfiStrChr (
 | |
|   IN CHAR16  *Str,
 | |
|   IN CHAR16  Chr
 | |
|   )
 | |
| 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   Locate the first occurance of a character in a string.
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   Str - Pointer to NULL terminated unicode string.
 | |
|   Chr - Character to locate.
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   If Str is NULL, then NULL is returned.
 | |
|   If Chr is not contained in Str, then NULL is returned.
 | |
|   If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   if (Str == NULL) {
 | |
|     return Str;
 | |
|   }
 | |
| 
 | |
|   while (*Str != '\0' && *Str != Chr) {
 | |
|     ++Str;
 | |
|   }
 | |
| 
 | |
|   return (*Str == Chr) ? Str : NULL;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsZero (
 | |
|   IN VOID   *Buffer,
 | |
|   IN UINTN  Length
 | |
|   )
 | |
| {
 | |
|   if ((Buffer == NULL) || (Length == 0)) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (*(UINT8 *)Buffer != 0) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   if (Length > 1) {
 | |
|     if (!CompareMem (Buffer, (UINT8 *)Buffer + 1, Length - 1)) {
 | |
|       return FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| CutPrefix (
 | |
|   IN  CHAR16  *Str,
 | |
|   IN  UINTN   Count
 | |
|   )
 | |
| {
 | |
|   CHAR16  *Pointer;
 | |
| 
 | |
|   if (StrLen (Str) < Count) {
 | |
|     ASSERT (0);
 | |
|   }
 | |
| 
 | |
|   if (Count != 0) {
 | |
|     for (Pointer = Str; *(Pointer + Count); Pointer++) {
 | |
|       *Pointer = *(Pointer + Count);
 | |
|     }
 | |
| 
 | |
|     *Pointer = *(Pointer + Count);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Open the root directory on a volume.
 | |
| 
 | |
|   @param  This Protocol instance pointer.
 | |
|   @param  Root Returns an Open file handle for the root directory
 | |
| 
 | |
|   @retval EFI_SUCCESS          The device was opened.
 | |
|   @retval EFI_UNSUPPORTED      This volume does not support the file system.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_ACCESS_DENIED    The service denied access to the file.
 | |
|   @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtOpenVolume (
 | |
|   IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  *This,
 | |
|   OUT EFI_FILE_PROTOCOL               **Root
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                         Status;
 | |
|   WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *Private;
 | |
|   WIN_NT_EFI_FILE_PRIVATE            *PrivateFile;
 | |
|   CHAR16                             *TempFileName;
 | |
|   UINTN                              Size;
 | |
| 
 | |
|   if ((This == NULL) || (Root == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   PrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));
 | |
|   if (PrivateFile == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   PrivateFile->FileName = AllocatePool (StrSize (Private->FilePath));
 | |
|   if (PrivateFile->FileName == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   PrivateFile->FilePath = AllocatePool (StrSize (Private->FilePath));
 | |
|   if (PrivateFile->FilePath == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   StrCpyS (
 | |
|     PrivateFile->FilePath,
 | |
|     StrSize (Private->FilePath) / sizeof (CHAR16),
 | |
|     Private->FilePath
 | |
|     );
 | |
|   StrCpyS (
 | |
|     PrivateFile->FileName,
 | |
|     StrSize (Private->FilePath) / sizeof (CHAR16),
 | |
|     PrivateFile->FilePath
 | |
|     );
 | |
|   PrivateFile->Signature        = WIN_NT_EFI_FILE_PRIVATE_SIGNATURE;
 | |
|   PrivateFile->Thunk            = Private->Thunk;
 | |
|   PrivateFile->SimpleFileSystem = This;
 | |
|   PrivateFile->IsRootDirectory  = TRUE;
 | |
|   PrivateFile->IsDirectoryPath  = TRUE;
 | |
|   PrivateFile->IsOpenedByRead   = TRUE;
 | |
|   CopyMem (&PrivateFile->EfiFile, &gWinNtFileProtocol, sizeof (gWinNtFileProtocol));
 | |
|   PrivateFile->IsValidFindBuf = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Set DirHandle
 | |
|   //
 | |
|   PrivateFile->DirHandle = CreateFile (
 | |
|                              PrivateFile->FilePath,
 | |
|                              GENERIC_READ,
 | |
|                              FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                              NULL,
 | |
|                              OPEN_EXISTING,
 | |
|                              FILE_FLAG_BACKUP_SEMANTICS,
 | |
|                              NULL
 | |
|                              );
 | |
| 
 | |
|   if (PrivateFile->DirHandle == INVALID_HANDLE_VALUE) {
 | |
|     Status = EFI_NOT_FOUND;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Find the first file under it
 | |
|   //
 | |
|   Size         = StrSize (PrivateFile->FilePath);
 | |
|   Size        += StrSize (L"\\*");
 | |
|   TempFileName = AllocatePool (Size);
 | |
|   if (TempFileName == NULL) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   StrCpyS (TempFileName, Size / sizeof (CHAR16), PrivateFile->FilePath);
 | |
|   StrCatS (TempFileName, Size / sizeof (CHAR16), L"\\*");
 | |
| 
 | |
|   PrivateFile->LHandle = FindFirstFile (TempFileName, &PrivateFile->FindBuf);
 | |
|   FreePool (TempFileName);
 | |
| 
 | |
|   if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|     PrivateFile->IsValidFindBuf = FALSE;
 | |
|   } else {
 | |
|     PrivateFile->IsValidFindBuf = TRUE;
 | |
|   }
 | |
| 
 | |
|   *Root = &PrivateFile->EfiFile;
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
| Done:
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (PrivateFile) {
 | |
|       if (PrivateFile->FileName) {
 | |
|         FreePool (PrivateFile->FileName);
 | |
|       }
 | |
| 
 | |
|       if (PrivateFile->FilePath) {
 | |
|         FreePool (PrivateFile->FilePath);
 | |
|       }
 | |
| 
 | |
|       FreePool (PrivateFile);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Count the number of Leading Dot in FileNameToken.
 | |
| 
 | |
|   @param FileNameToken  A string representing a token in the path name.
 | |
| 
 | |
|   @return  UINTN             The number of leading dot in the name.
 | |
| 
 | |
| **/
 | |
| UINTN
 | |
| CountLeadingDots (
 | |
|   IN CONST CHAR16  *FileNameToken
 | |
|   )
 | |
| {
 | |
|   UINTN  Num;
 | |
| 
 | |
|   Num = 0;
 | |
|   while (*FileNameToken == L'.') {
 | |
|     Num++;
 | |
|     FileNameToken++;
 | |
|   }
 | |
| 
 | |
|   return Num;
 | |
| }
 | |
| 
 | |
| BOOLEAN
 | |
| IsFileNameTokenValid (
 | |
|   IN CONST CHAR16  *FileNameToken
 | |
|   )
 | |
| {
 | |
|   UINTN  Num;
 | |
| 
 | |
|   if (StrStr (FileNameToken, L"/") != NULL) {
 | |
|     //
 | |
|     // No L'/' in file name.
 | |
|     //
 | |
|     return FALSE;
 | |
|   } else {
 | |
|     //
 | |
|     // If Token has all dot, the number should not exceed 2
 | |
|     //
 | |
|     Num = CountLeadingDots (FileNameToken);
 | |
| 
 | |
|     if (Num == StrLen (FileNameToken)) {
 | |
|       //
 | |
|       // If the FileNameToken only contains a number of L'.'.
 | |
|       //
 | |
|       if (Num > 2) {
 | |
|         return FALSE;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Return the first string token found in the indirect pointer a String named by FileName.
 | |
| 
 | |
|   On input, FileName is a indirect pointer pointing to a String.
 | |
|   On output, FileName is a updated to point to the next character after the first
 | |
|   found L"\" or NULL if there is no L"\" found.
 | |
| 
 | |
|   @param FileName  A indirect pointer pointing to a FileName.
 | |
| 
 | |
|   @return  Token      The first string token found before a L"\".
 | |
| 
 | |
| **/
 | |
| CHAR16 *
 | |
| GetNextFileNameToken (
 | |
|   IN OUT CONST CHAR16  **FileName
 | |
|   )
 | |
| {
 | |
|   CHAR16  *SlashPos;
 | |
|   CHAR16  *Token;
 | |
|   UINTN   Offset;
 | |
| 
 | |
|   ASSERT (**FileName != L'\\');
 | |
|   ASSERT (**FileName != L'\0');
 | |
| 
 | |
|   SlashPos = StrStr (*FileName, L"\\");
 | |
|   if (SlashPos == NULL) {
 | |
|     Token     = AllocateCopyPool (StrSize (*FileName), *FileName);
 | |
|     *FileName = NULL;
 | |
|   } else {
 | |
|     Offset = SlashPos - *FileName;
 | |
|     Token  = AllocateZeroPool ((Offset + 1) * sizeof (CHAR16));
 | |
|     StrnCpyS (Token, Offset + 1, *FileName, Offset);
 | |
|     //
 | |
|     // Point *FileName to the next character after L'\'.
 | |
|     //
 | |
|     *FileName = *FileName + Offset + 1;
 | |
|     //
 | |
|     // If *FileName is an empty string, then set *FileName to NULL
 | |
|     //
 | |
|     if (**FileName == L'\0') {
 | |
|       *FileName = NULL;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Token;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Check if a FileName contains only Valid Characters.
 | |
| 
 | |
|   If FileName contains only a single L'\', return TRUE.
 | |
|   If FileName contains two adjacent L'\', return FALSE.
 | |
|   If FileName conatins L'/' , return FALSE.
 | |
|   If FileName contains more than two dots separated with other FileName characters
 | |
|   by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
 | |
| 
 | |
|   @param FileName  The File Name String to check.
 | |
| 
 | |
|   @return  TRUE        FileName only contains valid characters.
 | |
|   @return  FALSE       FileName contains at least one invalid character.
 | |
| 
 | |
| **/
 | |
| BOOLEAN
 | |
| IsFileNameValid (
 | |
|   IN CONST CHAR16  *FileName
 | |
|   )
 | |
| {
 | |
|   CHAR16   *Token;
 | |
|   BOOLEAN  Valid;
 | |
| 
 | |
|   //
 | |
|   // If FileName is just L'\', then it is a valid pathname.
 | |
|   //
 | |
|   if (StrCmp (FileName, L"\\") == 0) {
 | |
|     return TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // We don't support two or more adjacent L'\'.
 | |
|   //
 | |
|   if (StrStr (FileName, L"\\\\") != NULL) {
 | |
|     return FALSE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Is FileName has a leading L"\", skip to next character.
 | |
|   //
 | |
|   if (FileName[0] == L'\\') {
 | |
|     FileName++;
 | |
|   }
 | |
| 
 | |
|   do {
 | |
|     Token = GetNextFileNameToken (&FileName);
 | |
|     Valid = IsFileNameTokenValid (Token);
 | |
|     FreePool (Token);
 | |
| 
 | |
|     if (!Valid) {
 | |
|       return FALSE;
 | |
|     }
 | |
|   } while (FileName != NULL);
 | |
| 
 | |
|   return TRUE;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Opens a new file relative to the source file's location.
 | |
| 
 | |
|   @param  This       The protocol instance pointer.
 | |
|   @param  NewHandle  Returns File Handle for FileName.
 | |
|   @param  FileName   Null terminated string. "\", ".", and ".." are supported.
 | |
|   @param  OpenMode   Open mode for file.
 | |
|   @param  Attributes Only used for EFI_FILE_MODE_CREATE.
 | |
| 
 | |
|   @retval EFI_SUCCESS          The device was opened.
 | |
|   @retval EFI_NOT_FOUND        The specified file could not be found on the device.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_MEDIA_CHANGED    The media has changed.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_ACCESS_DENIED    The service denied access to the file.
 | |
|   @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileOpen (
 | |
|   IN EFI_FILE_PROTOCOL   *This,
 | |
|   OUT EFI_FILE_PROTOCOL  **NewHandle,
 | |
|   IN CHAR16              *FileName,
 | |
|   IN UINT64              OpenMode,
 | |
|   IN UINT64              Attributes
 | |
|   )
 | |
| {
 | |
|   WIN_NT_EFI_FILE_PRIVATE            *PrivateFile;
 | |
|   WIN_NT_EFI_FILE_PRIVATE            *NewPrivateFile;
 | |
|   WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *PrivateRoot;
 | |
|   EFI_STATUS                         Status;
 | |
|   CHAR16                             *RealFileName;
 | |
|   CHAR16                             *TempFileName;
 | |
|   CHAR16                             *ParseFileName;
 | |
|   CHAR16                             *GuardPointer;
 | |
|   CHAR16                             TempChar;
 | |
|   DWORD                              LastError;
 | |
|   UINTN                              Count;
 | |
|   BOOLEAN                            LoopFinish;
 | |
|   UINTN                              InfoSize;
 | |
|   EFI_FILE_INFO                      *Info;
 | |
|   UINTN                              Size;
 | |
| 
 | |
|   //
 | |
|   // Init local variables
 | |
|   //
 | |
|   PrivateFile    = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
|   PrivateRoot    = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
 | |
|   NewPrivateFile = NULL;
 | |
| 
 | |
|   //
 | |
|   // Allocate buffer for FileName as the passed in FileName may be read only
 | |
|   //
 | |
|   TempFileName = AllocatePool (StrSize (FileName));
 | |
|   if (TempFileName == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   StrCpyS (TempFileName, StrSize (FileName) / sizeof (CHAR16), FileName);
 | |
|   FileName = TempFileName;
 | |
| 
 | |
|   if (FileName[StrLen (FileName) - 1] == L'\\') {
 | |
|     FileName[StrLen (FileName) - 1] = 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // If file name does not equal to "." or ".." and not trailed with "\..",
 | |
|   // then we trim the leading/trailing blanks and trailing dots
 | |
|   //
 | |
|   if ((StrCmp (FileName, L".") != 0) && (StrCmp (FileName, L"..") != 0) &&
 | |
|       ((StrLen (FileName) >= 3) ? (StrCmp (&FileName[StrLen (FileName) - 3], L"\\..") != 0) : TRUE))
 | |
|   {
 | |
|     //
 | |
|     // Trim leading blanks
 | |
|     //
 | |
|     Count = 0;
 | |
|     for (TempFileName = FileName;
 | |
|          *TempFileName != 0 && *TempFileName == L' ';
 | |
|          TempFileName++)
 | |
|     {
 | |
|       Count++;
 | |
|     }
 | |
| 
 | |
|     CutPrefix (FileName, Count);
 | |
|     //
 | |
|     // Trim trailing blanks
 | |
|     //
 | |
|     for (TempFileName = FileName + StrLen (FileName) - 1;
 | |
|          TempFileName >= FileName && (*TempFileName == L' ');
 | |
|          TempFileName--)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     *(TempFileName + 1) = 0;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Attempt to open the file
 | |
|   //
 | |
|   NewPrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));
 | |
|   if (NewPrivateFile == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   CopyMem (NewPrivateFile, PrivateFile, sizeof (WIN_NT_EFI_FILE_PRIVATE));
 | |
| 
 | |
|   NewPrivateFile->FilePath = AllocatePool (StrSize (PrivateFile->FileName));
 | |
|   if (NewPrivateFile->FilePath == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->IsDirectoryPath) {
 | |
|     StrCpyS (
 | |
|       NewPrivateFile->FilePath,
 | |
|       StrSize (PrivateFile->FileName) / sizeof (CHAR16),
 | |
|       PrivateFile->FileName
 | |
|       );
 | |
|   } else {
 | |
|     StrCpyS (
 | |
|       NewPrivateFile->FilePath,
 | |
|       StrSize (PrivateFile->FileName) / sizeof (CHAR16),
 | |
|       PrivateFile->FilePath
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   Size                     = StrSize (NewPrivateFile->FilePath);
 | |
|   Size                    += StrSize (L"\\");
 | |
|   Size                    += StrSize (FileName);
 | |
|   NewPrivateFile->FileName = AllocatePool (Size);
 | |
|   if (NewPrivateFile->FileName == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (*FileName == L'\\') {
 | |
|     StrCpyS (NewPrivateFile->FileName, Size / sizeof (CHAR16), PrivateRoot->FilePath);
 | |
|     StrCatS (NewPrivateFile->FileName, Size / sizeof (CHAR16), L"\\");
 | |
|     StrCatS (NewPrivateFile->FileName, Size / sizeof (CHAR16), FileName + 1);
 | |
|   } else {
 | |
|     StrCpyS (NewPrivateFile->FileName, Size / sizeof (CHAR16), NewPrivateFile->FilePath);
 | |
|     if (StrCmp (FileName, L"") != 0) {
 | |
|       //
 | |
|       // In case the filename becomes empty, especially after trimming dots and blanks
 | |
|       //
 | |
|       StrCatS (NewPrivateFile->FileName, Size / sizeof (CHAR16), L"\\");
 | |
|       StrCatS (NewPrivateFile->FileName, Size / sizeof (CHAR16), FileName);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (!IsFileNameValid (NewPrivateFile->FileName)) {
 | |
|     Status = EFI_NOT_FOUND;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Get rid of . and .., except leading . or ..
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // GuardPointer protect simplefilesystem root path not be destroyed
 | |
|   //
 | |
|   GuardPointer = NewPrivateFile->FileName + StrLen (PrivateRoot->FilePath);
 | |
| 
 | |
|   LoopFinish = FALSE;
 | |
| 
 | |
|   while (!LoopFinish) {
 | |
|     LoopFinish = TRUE;
 | |
| 
 | |
|     for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {
 | |
|       if ((*ParseFileName == L'.') &&
 | |
|           ((*(ParseFileName + 1) == 0) || (*(ParseFileName + 1) == L'\\')) &&
 | |
|           (*(ParseFileName - 1) == L'\\')
 | |
|           )
 | |
|       {
 | |
|         //
 | |
|         // cut \.
 | |
|         //
 | |
|         CutPrefix (ParseFileName - 1, 2);
 | |
|         LoopFinish = FALSE;
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       if ((*ParseFileName == L'.') &&
 | |
|           (*(ParseFileName + 1) == L'.') &&
 | |
|           ((*(ParseFileName + 2) == 0) || (*(ParseFileName + 2) == L'\\')) &&
 | |
|           (*(ParseFileName - 1) == L'\\')
 | |
|           )
 | |
|       {
 | |
|         ParseFileName--;
 | |
|         Count = 3;
 | |
| 
 | |
|         while (ParseFileName != GuardPointer) {
 | |
|           ParseFileName--;
 | |
|           Count++;
 | |
|           if (*ParseFileName == L'\\') {
 | |
|             break;
 | |
|           }
 | |
|         }
 | |
| 
 | |
|         //
 | |
|         // cut \.. and its left directory
 | |
|         //
 | |
|         CutPrefix (ParseFileName, Count);
 | |
|         LoopFinish = FALSE;
 | |
|         break;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   RealFileName = NewPrivateFile->FileName;
 | |
|   while (EfiStrChr (RealFileName, L'\\') != NULL) {
 | |
|     RealFileName = EfiStrChr (RealFileName, L'\\') + 1;
 | |
|   }
 | |
| 
 | |
|   TempChar = 0;
 | |
|   if (RealFileName != NewPrivateFile->FileName) {
 | |
|     TempChar            = *(RealFileName - 1);
 | |
|     *(RealFileName - 1) = 0;
 | |
|   }
 | |
| 
 | |
|   FreePool (NewPrivateFile->FilePath);
 | |
|   NewPrivateFile->FilePath = NULL;
 | |
|   NewPrivateFile->FilePath = AllocatePool (StrSize (NewPrivateFile->FileName));
 | |
|   if (NewPrivateFile->FilePath == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   StrCpyS (
 | |
|     NewPrivateFile->FilePath,
 | |
|     StrSize (NewPrivateFile->FileName) / sizeof (CHAR16),
 | |
|     NewPrivateFile->FileName
 | |
|     );
 | |
|   if (TempChar != 0) {
 | |
|     *(RealFileName - 1) = TempChar;
 | |
|   }
 | |
| 
 | |
|   NewPrivateFile->IsRootDirectory = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Test whether file or directory
 | |
|   //
 | |
|   if (OpenMode & EFI_FILE_MODE_CREATE) {
 | |
|     if (Attributes & EFI_FILE_DIRECTORY) {
 | |
|       NewPrivateFile->IsDirectoryPath = TRUE;
 | |
|     } else {
 | |
|       NewPrivateFile->IsDirectoryPath = FALSE;
 | |
|     }
 | |
|   } else {
 | |
|     NewPrivateFile->LHandle = CreateFile (
 | |
|                                 NewPrivateFile->FileName,
 | |
|                                 GENERIC_READ,
 | |
|                                 FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                 NULL,
 | |
|                                 OPEN_EXISTING,
 | |
|                                 0,
 | |
|                                 NULL
 | |
|                                 );
 | |
| 
 | |
|     if (NewPrivateFile->LHandle != INVALID_HANDLE_VALUE) {
 | |
|       NewPrivateFile->IsDirectoryPath = FALSE;
 | |
|       CloseHandle (NewPrivateFile->LHandle);
 | |
|     } else {
 | |
|       NewPrivateFile->IsDirectoryPath = TRUE;
 | |
|     }
 | |
| 
 | |
|     NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;
 | |
|   }
 | |
| 
 | |
|   if (OpenMode & EFI_FILE_MODE_WRITE) {
 | |
|     NewPrivateFile->IsOpenedByRead = FALSE;
 | |
|   } else {
 | |
|     NewPrivateFile->IsOpenedByRead = TRUE;
 | |
|   }
 | |
| 
 | |
|   Status = EFI_SUCCESS;
 | |
| 
 | |
|   //
 | |
|   // deal with directory
 | |
|   //
 | |
|   if (NewPrivateFile->IsDirectoryPath) {
 | |
|     Size         = StrSize (NewPrivateFile->FileName);
 | |
|     Size        += StrSize (L"\\*");
 | |
|     TempFileName = AllocatePool (Size);
 | |
|     if (TempFileName == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (TempFileName, Size / sizeof (CHAR16), NewPrivateFile->FileName);
 | |
| 
 | |
|     if ((OpenMode & EFI_FILE_MODE_CREATE)) {
 | |
|       //
 | |
|       // Create a directory
 | |
|       //
 | |
|       if (!CreateDirectory (TempFileName, NULL)) {
 | |
|         LastError = GetLastError ();
 | |
|         if (LastError != ERROR_ALREADY_EXISTS) {
 | |
|           FreePool (TempFileName);
 | |
|           Status = EFI_ACCESS_DENIED;
 | |
|           goto Done;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     NewPrivateFile->DirHandle = CreateFile (
 | |
|                                   TempFileName,
 | |
|                                   NewPrivateFile->IsOpenedByRead ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
 | |
|                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                   NULL,
 | |
|                                   OPEN_EXISTING,
 | |
|                                   FILE_FLAG_BACKUP_SEMANTICS,
 | |
|                                   NULL
 | |
|                                   );
 | |
| 
 | |
|     if (NewPrivateFile->DirHandle == INVALID_HANDLE_VALUE) {
 | |
|       NewPrivateFile->DirHandle = CreateFile (
 | |
|                                     TempFileName,
 | |
|                                     GENERIC_READ,
 | |
|                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                     NULL,
 | |
|                                     OPEN_EXISTING,
 | |
|                                     FILE_FLAG_BACKUP_SEMANTICS,
 | |
|                                     NULL
 | |
|                                     );
 | |
| 
 | |
|       if (NewPrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
 | |
|         CloseHandle (NewPrivateFile->DirHandle);
 | |
|         NewPrivateFile->DirHandle = INVALID_HANDLE_VALUE;
 | |
|         Status                    = EFI_ACCESS_DENIED;
 | |
|       } else {
 | |
|         Status = EFI_NOT_FOUND;
 | |
|       }
 | |
| 
 | |
|       FreePool (TempFileName);
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Find the first file under it
 | |
|     //
 | |
|     StrCatS (TempFileName, Size / sizeof (CHAR16), L"\\*");
 | |
|     NewPrivateFile->LHandle = FindFirstFile (TempFileName, &NewPrivateFile->FindBuf);
 | |
|     FreePool (TempFileName);
 | |
| 
 | |
|     if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|       NewPrivateFile->IsValidFindBuf = FALSE;
 | |
|     } else {
 | |
|       NewPrivateFile->IsValidFindBuf = TRUE;
 | |
|     }
 | |
|   } else {
 | |
|     //
 | |
|     // deal with file
 | |
|     //
 | |
|     if (!NewPrivateFile->IsOpenedByRead) {
 | |
|       NewPrivateFile->LHandle = CreateFile (
 | |
|                                   NewPrivateFile->FileName,
 | |
|                                   GENERIC_READ | GENERIC_WRITE,
 | |
|                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                   NULL,
 | |
|                                   (OpenMode & EFI_FILE_MODE_CREATE) ? OPEN_ALWAYS : OPEN_EXISTING,
 | |
|                                   0,
 | |
|                                   NULL
 | |
|                                   );
 | |
| 
 | |
|       if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|         NewPrivateFile->LHandle = CreateFile (
 | |
|                                     NewPrivateFile->FileName,
 | |
|                                     GENERIC_READ,
 | |
|                                     FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                     NULL,
 | |
|                                     OPEN_EXISTING,
 | |
|                                     0,
 | |
|                                     NULL
 | |
|                                     );
 | |
| 
 | |
|         if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|           Status = EFI_NOT_FOUND;
 | |
|         } else {
 | |
|           Status = EFI_ACCESS_DENIED;
 | |
|           CloseHandle (NewPrivateFile->LHandle);
 | |
|           NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;
 | |
|         }
 | |
|       }
 | |
|     } else {
 | |
|       NewPrivateFile->LHandle = CreateFile (
 | |
|                                   NewPrivateFile->FileName,
 | |
|                                   GENERIC_READ,
 | |
|                                   FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                   NULL,
 | |
|                                   OPEN_EXISTING,
 | |
|                                   0,
 | |
|                                   NULL
 | |
|                                   );
 | |
| 
 | |
|       if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|         Status = EFI_NOT_FOUND;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if ((OpenMode & EFI_FILE_MODE_CREATE) && (Status == EFI_SUCCESS)) {
 | |
|     //
 | |
|     // Set the attribute
 | |
|     //
 | |
|     InfoSize = 0;
 | |
|     Info     = NULL;
 | |
| 
 | |
|     Status = WinNtFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
 | |
| 
 | |
|     if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Info = AllocatePool (InfoSize);
 | |
|     if (Info == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = WinNtFileGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       FreePool (Info);
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Info->Attribute = Attributes;
 | |
| 
 | |
|     WinNtFileSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);
 | |
|     FreePool (Info);
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   FreePool (FileName);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     if (NewPrivateFile) {
 | |
|       if (NewPrivateFile->FileName) {
 | |
|         FreePool (NewPrivateFile->FileName);
 | |
|       }
 | |
| 
 | |
|       if (NewPrivateFile->FilePath) {
 | |
|         FreePool (NewPrivateFile->FilePath);
 | |
|       }
 | |
| 
 | |
|       FreePool (NewPrivateFile);
 | |
|     }
 | |
|   } else {
 | |
|     *NewHandle = &NewPrivateFile->EfiFile;
 | |
|     if (StrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {
 | |
|       NewPrivateFile->IsRootDirectory = TRUE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Close the file handle
 | |
| 
 | |
|   @param  This          Protocol instance pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS   The device was opened.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileClose (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
 | |
|     if (PrivateFile->IsDirectoryPath) {
 | |
|       FindClose (PrivateFile->LHandle);
 | |
|     } else {
 | |
|       CloseHandle (PrivateFile->LHandle);
 | |
|     }
 | |
| 
 | |
|     PrivateFile->LHandle = INVALID_HANDLE_VALUE;
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->IsDirectoryPath && (PrivateFile->DirHandle != INVALID_HANDLE_VALUE)) {
 | |
|     CloseHandle (PrivateFile->DirHandle);
 | |
|     PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->FileName) {
 | |
|     FreePool (PrivateFile->FileName);
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->FilePath) {
 | |
|     FreePool (PrivateFile->FilePath);
 | |
|   }
 | |
| 
 | |
|   FreePool (PrivateFile);
 | |
| 
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Close and delete the file handle.
 | |
| 
 | |
|   @param  This                     Protocol instance pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS              The device was opened.
 | |
|   @retval EFI_WARN_DELETE_FAILURE  The handle was closed but the file was not deleted.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileDelete (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   Status = EFI_WARN_DELETE_FAILURE;
 | |
| 
 | |
|   if (PrivateFile->IsDirectoryPath) {
 | |
|     if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
 | |
|       FindClose (PrivateFile->LHandle);
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
 | |
|       CloseHandle (PrivateFile->DirHandle);
 | |
|       PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
 | |
|     }
 | |
| 
 | |
|     if (RemoveDirectory (PrivateFile->FileName)) {
 | |
|       Status = EFI_SUCCESS;
 | |
|     }
 | |
|   } else {
 | |
|     CloseHandle (PrivateFile->LHandle);
 | |
|     PrivateFile->LHandle = INVALID_HANDLE_VALUE;
 | |
| 
 | |
|     if (!PrivateFile->IsOpenedByRead) {
 | |
|       if (DeleteFile (PrivateFile->FileName)) {
 | |
|         Status = EFI_SUCCESS;
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   FreePool (PrivateFile->FileName);
 | |
|   FreePool (PrivateFile->FilePath);
 | |
|   FreePool (PrivateFile);
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| VOID
 | |
| WinNtSystemTimeToEfiTime (
 | |
|   IN SYSTEMTIME             *SystemTime,
 | |
|   IN TIME_ZONE_INFORMATION  *TimeZone,
 | |
|   OUT EFI_TIME              *Time
 | |
|   )
 | |
| 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   SystemTime  - TODO: add argument description
 | |
|   TimeZone    - TODO: add argument description
 | |
|   Time        - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   Time->Year       = (UINT16)SystemTime->wYear;
 | |
|   Time->Month      = (UINT8)SystemTime->wMonth;
 | |
|   Time->Day        = (UINT8)SystemTime->wDay;
 | |
|   Time->Hour       = (UINT8)SystemTime->wHour;
 | |
|   Time->Minute     = (UINT8)SystemTime->wMinute;
 | |
|   Time->Second     = (UINT8)SystemTime->wSecond;
 | |
|   Time->Nanosecond = (UINT32)SystemTime->wMilliseconds * 1000000;
 | |
|   Time->TimeZone   = (INT16)TimeZone->Bias;
 | |
| 
 | |
|   if (TimeZone->StandardDate.wMonth) {
 | |
|     Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Convert the FileTime to EfiTime.
 | |
| 
 | |
|   @param PrivateFile  Pointer to WIN_NT_EFI_FILE_PRIVATE.
 | |
|   @param TimeZone     Pointer to the current time zone.
 | |
|   @param FileTime     Pointer to file time.
 | |
|   @param EfiTime      Pointer to EFI time.
 | |
| **/
 | |
| VOID
 | |
| WinNtFileTimeToEfiTime (
 | |
|   IN CONST WIN_NT_EFI_FILE_PRIVATE  *PrivateFile,
 | |
|   IN       TIME_ZONE_INFORMATION    *TimeZone,
 | |
|   IN CONST FILETIME                 *FileTime,
 | |
|   OUT      EFI_TIME                 *EfiTime
 | |
|   )
 | |
| {
 | |
|   FILETIME    TempFileTime;
 | |
|   SYSTEMTIME  SystemTime;
 | |
| 
 | |
|   FileTimeToLocalFileTime (FileTime, &TempFileTime);
 | |
|   FileTimeToSystemTime (&TempFileTime, &SystemTime);
 | |
|   WinNtSystemTimeToEfiTime (&SystemTime, TimeZone, EfiTime);
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Read data from the file.
 | |
| 
 | |
|   @param  This       Protocol instance pointer.
 | |
|   @param  BufferSize On input size of buffer, on output amount of data in buffer.
 | |
|   @param  Buffer     The buffer in which data is read.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was read.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_BUFFER_TO_SMALL  BufferSize is too small. BufferSize contains required size.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileRead (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN OUT UINTN          *BufferSize,
 | |
|   OUT VOID              *Buffer
 | |
|   )
 | |
| {
 | |
|   WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
 | |
|   EFI_STATUS               Status;
 | |
|   UINTN                    Size;
 | |
|   UINTN                    NameSize;
 | |
|   UINTN                    ResultSize;
 | |
|   UINTN                    Index;
 | |
|   EFI_FILE_INFO            *Info;
 | |
|   WCHAR                    *pw;
 | |
|   TIME_ZONE_INFORMATION    TimeZone;
 | |
|   EFI_FILE_INFO            *FileInfo;
 | |
|   UINT64                   Pos;
 | |
|   UINT64                   FileSize;
 | |
|   UINTN                    FileInfoSize;
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (!PrivateFile->IsDirectoryPath) {
 | |
|     if (This->GetPosition (This, &Pos) != EFI_SUCCESS) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     FileInfoSize = SIZE_OF_EFI_FILE_SYSTEM_INFO;
 | |
|     FileInfo     = AllocatePool (FileInfoSize);
 | |
| 
 | |
|     Status = This->GetInfo (
 | |
|                      This,
 | |
|                      &gEfiFileInfoGuid,
 | |
|                      &FileInfoSize,
 | |
|                      FileInfo
 | |
|                      );
 | |
| 
 | |
|     if (Status == EFI_BUFFER_TOO_SMALL) {
 | |
|       FreePool (FileInfo);
 | |
|       FileInfo = AllocatePool (FileInfoSize);
 | |
|       Status   = This->GetInfo (
 | |
|                          This,
 | |
|                          &gEfiFileInfoGuid,
 | |
|                          &FileInfoSize,
 | |
|                          FileInfo
 | |
|                          );
 | |
|     }
 | |
| 
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     FileSize = FileInfo->FileSize;
 | |
| 
 | |
|     FreePool (FileInfo);
 | |
| 
 | |
|     if (Pos >= FileSize) {
 | |
|       *BufferSize = 0;
 | |
|       if (Pos == FileSize) {
 | |
|         Status = EFI_SUCCESS;
 | |
|         goto Done;
 | |
|       } else {
 | |
|         Status = EFI_DEVICE_ERROR;
 | |
|         goto Done;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     Status = ReadFile (
 | |
|                PrivateFile->LHandle,
 | |
|                Buffer,
 | |
|                (DWORD)*BufferSize,
 | |
|                (LPDWORD)BufferSize,
 | |
|                NULL
 | |
|                ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Read on a directory.  Perform a find next
 | |
|   //
 | |
|   if (!PrivateFile->IsValidFindBuf) {
 | |
|     *BufferSize = 0;
 | |
|     Status      = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Size = SIZE_OF_EFI_FILE_INFO;
 | |
| 
 | |
|   NameSize = StrSize (PrivateFile->FindBuf.cFileName);
 | |
| 
 | |
|   ResultSize = Size + NameSize;
 | |
| 
 | |
|   Status = EFI_BUFFER_TOO_SMALL;
 | |
| 
 | |
|   if (*BufferSize >= ResultSize) {
 | |
|     Status = EFI_SUCCESS;
 | |
| 
 | |
|     Info = Buffer;
 | |
|     ZeroMem (Info, ResultSize);
 | |
| 
 | |
|     Info->Size = ResultSize;
 | |
| 
 | |
|     GetTimeZoneInformation (&TimeZone);
 | |
|     WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftCreationTime, &Info->CreateTime);
 | |
|     WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastAccessTime, &Info->LastAccessTime);
 | |
|     WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastWriteTime, &Info->ModificationTime);
 | |
| 
 | |
|     Info->FileSize = PrivateFile->FindBuf.nFileSizeLow;
 | |
| 
 | |
|     Info->PhysicalSize = PrivateFile->FindBuf.nFileSizeLow;
 | |
| 
 | |
|     if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
 | |
|       Info->Attribute |= EFI_FILE_ARCHIVE;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
 | |
|       Info->Attribute |= EFI_FILE_HIDDEN;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
 | |
|       Info->Attribute |= EFI_FILE_SYSTEM;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
 | |
|       Info->Attribute |= EFI_FILE_READ_ONLY;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
 | |
|       Info->Attribute |= EFI_FILE_DIRECTORY;
 | |
|     }
 | |
| 
 | |
|     NameSize = NameSize / sizeof (WCHAR);
 | |
| 
 | |
|     pw = (WCHAR *)(((CHAR8 *)Buffer) + Size);
 | |
| 
 | |
|     for (Index = 0; Index < NameSize; Index++) {
 | |
|       pw[Index] = PrivateFile->FindBuf.cFileName[Index];
 | |
|     }
 | |
| 
 | |
|     if (FindNextFile (PrivateFile->LHandle, &PrivateFile->FindBuf)) {
 | |
|       PrivateFile->IsValidFindBuf = TRUE;
 | |
|     } else {
 | |
|       PrivateFile->IsValidFindBuf = FALSE;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *BufferSize = ResultSize;
 | |
| 
 | |
| Done:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Write data to a file.
 | |
| 
 | |
|   @param  This       Protocol instance pointer.
 | |
|   @param  BufferSize On input size of buffer, on output amount of data in buffer.
 | |
|   @param  Buffer     The buffer in which data to write.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was written.
 | |
|   @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_DEVICE_ERROR     An attempt was made to write to a deleted file.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileWrite (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN OUT UINTN          *BufferSize,
 | |
|   IN VOID               *Buffer
 | |
|   )
 | |
| {
 | |
|   WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
 | |
|   EFI_STATUS               Status;
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->IsDirectoryPath) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->IsOpenedByRead) {
 | |
|     Status = EFI_ACCESS_DENIED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = WriteFile (
 | |
|              PrivateFile->LHandle,
 | |
|              Buffer,
 | |
|              (DWORD)*BufferSize,
 | |
|              (LPDWORD)BufferSize,
 | |
|              NULL
 | |
|              ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
 | |
| 
 | |
| Done:
 | |
|   return Status;
 | |
| 
 | |
|   //
 | |
|   // bugbug: need to access windows error reporting
 | |
|   //
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set a files current position
 | |
| 
 | |
|   @param  This            Protocol instance pointer.
 | |
|   @param  Position        Byte position from the start of the file.
 | |
| 
 | |
|   @retval EFI_SUCCESS     Data was written.
 | |
|   @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileSetPossition (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN UINT64             Position
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
 | |
|   UINT32                   PosLow;
 | |
|   UINT32                   PosHigh;
 | |
|   CHAR16                   *FileName;
 | |
|   UINTN                    Size;
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (PrivateFile->IsDirectoryPath) {
 | |
|     if (Position != 0) {
 | |
|       Status = EFI_UNSUPPORTED;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Size     = StrSize (PrivateFile->FileName);
 | |
|     Size    += StrSize (L"\\*");
 | |
|     FileName = AllocatePool (Size);
 | |
|     if (FileName == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (FileName, Size / sizeof (CHAR16), PrivateFile->FileName);
 | |
|     StrCatS (FileName, Size / sizeof (CHAR16), L"\\*");
 | |
| 
 | |
|     if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
 | |
|       FindClose (PrivateFile->LHandle);
 | |
|     }
 | |
| 
 | |
|     PrivateFile->LHandle = FindFirstFile (FileName, &PrivateFile->FindBuf);
 | |
| 
 | |
|     if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|       PrivateFile->IsValidFindBuf = FALSE;
 | |
|     } else {
 | |
|       PrivateFile->IsValidFindBuf = TRUE;
 | |
|     }
 | |
| 
 | |
|     FreePool (FileName);
 | |
| 
 | |
|     Status = (PrivateFile->LHandle == INVALID_HANDLE_VALUE) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
 | |
|   } else {
 | |
|     if (Position == (UINT64)-1) {
 | |
|       PosLow = SetFilePointer (PrivateFile->LHandle, (ULONG)0, NULL, FILE_END);
 | |
|     } else {
 | |
|       PosHigh = (UINT32)RShiftU64 (Position, 32);
 | |
| 
 | |
|       PosLow = SetFilePointer (PrivateFile->LHandle, (ULONG)Position, (PLONG)&PosHigh, FILE_BEGIN);
 | |
|     }
 | |
| 
 | |
|     Status = (PosLow == 0xFFFFFFFF) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get a file's current position
 | |
| 
 | |
|   @param  This            Protocol instance pointer.
 | |
|   @param  Position        Byte position from the start of the file.
 | |
| 
 | |
|   @retval EFI_SUCCESS     Data was written.
 | |
|   @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileGetPossition (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   OUT UINT64            *Position
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS               Status;
 | |
|   WIN_NT_EFI_FILE_PRIVATE  *PrivateFile;
 | |
|   INT32                    PositionHigh;
 | |
|   UINT64                   PosHigh64;
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   PositionHigh = 0;
 | |
|   PosHigh64    = 0;
 | |
| 
 | |
|   if (PrivateFile->IsDirectoryPath) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Done;
 | |
|   } else {
 | |
|     PositionHigh = 0;
 | |
|     *Position    = SetFilePointer (
 | |
|                      PrivateFile->LHandle,
 | |
|                      0,
 | |
|                      (PLONG)&PositionHigh,
 | |
|                      FILE_CURRENT
 | |
|                      );
 | |
| 
 | |
|     Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS;
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     PosHigh64  = PositionHigh;
 | |
|     *Position += LShiftU64 (PosHigh64, 32);
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WinNtSimpleFileSystemFileInfo (
 | |
|   IN     WIN_NT_EFI_FILE_PRIVATE  *PrivateFile,
 | |
|   IN OUT UINTN                    *BufferSize,
 | |
|   OUT    VOID                     *Buffer
 | |
|   )
 | |
| 
 | |
| /*++
 | |
| 
 | |
| Routine Description:
 | |
| 
 | |
|   TODO: Add function description
 | |
| 
 | |
| Arguments:
 | |
| 
 | |
|   PrivateFile - TODO: add argument description
 | |
|   BufferSize  - TODO: add argument description
 | |
|   Buffer      - TODO: add argument description
 | |
| 
 | |
| Returns:
 | |
| 
 | |
|   TODO: add return values
 | |
| 
 | |
| --*/
 | |
| {
 | |
|   EFI_STATUS                  Status;
 | |
|   UINTN                       Size;
 | |
|   UINTN                       NameSize;
 | |
|   UINTN                       ResultSize;
 | |
|   EFI_FILE_INFO               *Info;
 | |
|   BY_HANDLE_FILE_INFORMATION  FileInfo;
 | |
|   CHAR16                      *RealFileName;
 | |
|   CHAR16                      *TempPointer;
 | |
|   TIME_ZONE_INFORMATION       TimeZone;
 | |
| 
 | |
|   Size = SIZE_OF_EFI_FILE_INFO;
 | |
| 
 | |
|   RealFileName = PrivateFile->FileName;
 | |
|   TempPointer  = RealFileName;
 | |
|   while (*TempPointer) {
 | |
|     if (*TempPointer == '\\') {
 | |
|       RealFileName = TempPointer + 1;
 | |
|     }
 | |
| 
 | |
|     TempPointer++;
 | |
|   }
 | |
| 
 | |
|   NameSize = StrSize (RealFileName);
 | |
| 
 | |
|   ResultSize = Size + NameSize;
 | |
| 
 | |
|   Status = EFI_BUFFER_TOO_SMALL;
 | |
|   if (*BufferSize >= ResultSize) {
 | |
|     Status = EFI_SUCCESS;
 | |
| 
 | |
|     Info = Buffer;
 | |
|     ZeroMem (Info, ResultSize);
 | |
| 
 | |
|     Info->Size = ResultSize;
 | |
|     GetFileInformationByHandle (
 | |
|       PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,
 | |
|       &FileInfo
 | |
|       );
 | |
|     Info->FileSize     = FileInfo.nFileSizeLow;
 | |
|     Info->PhysicalSize = Info->FileSize;
 | |
| 
 | |
|     GetTimeZoneInformation (&TimeZone);
 | |
|     WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftCreationTime, &Info->CreateTime);
 | |
|     WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastAccessTime, &Info->LastAccessTime);
 | |
|     WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastWriteTime, &Info->ModificationTime);
 | |
| 
 | |
|     if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
 | |
|       Info->Attribute |= EFI_FILE_ARCHIVE;
 | |
|     }
 | |
| 
 | |
|     if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
 | |
|       Info->Attribute |= EFI_FILE_HIDDEN;
 | |
|     }
 | |
| 
 | |
|     if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
 | |
|       Info->Attribute |= EFI_FILE_READ_ONLY;
 | |
|     }
 | |
| 
 | |
|     if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
 | |
|       Info->Attribute |= EFI_FILE_SYSTEM;
 | |
|     }
 | |
| 
 | |
|     if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
 | |
|       Info->Attribute |= EFI_FILE_DIRECTORY;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->IsDirectoryPath) {
 | |
|       Info->Attribute |= EFI_FILE_DIRECTORY;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->IsRootDirectory) {
 | |
|       *((CHAR8 *)Buffer + Size) = 0;
 | |
|     } else {
 | |
|       CopyMem ((CHAR8 *)Buffer + Size, RealFileName, NameSize);
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   *BufferSize = ResultSize;
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Get information about a file.
 | |
| 
 | |
|   @param  This            Protocol instance pointer.
 | |
|   @param  InformationType Type of information to return in Buffer.
 | |
|   @param  BufferSize      On input size of buffer, on output amount of data in buffer.
 | |
|   @param  Buffer          The buffer to return data.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was returned.
 | |
|   @retval EFI_UNSUPPORTED      InformationType is not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
|   @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileGetInfo (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN EFI_GUID           *InformationType,
 | |
|   IN OUT UINTN          *BufferSize,
 | |
|   OUT VOID              *Buffer
 | |
|   )
 | |
| {
 | |
|   EFI_STATUS                         Status;
 | |
|   WIN_NT_EFI_FILE_PRIVATE            *PrivateFile;
 | |
|   EFI_FILE_SYSTEM_INFO               *FileSystemInfoBuffer;
 | |
|   UINT32                             SectorsPerCluster;
 | |
|   UINT32                             BytesPerSector;
 | |
|   UINT32                             FreeClusters;
 | |
|   UINT32                             TotalClusters;
 | |
|   UINT32                             BytesPerCluster;
 | |
|   CHAR16                             *DriveName;
 | |
|   BOOLEAN                            DriveNameFound;
 | |
|   BOOL                               NtStatus;
 | |
|   UINTN                              Index;
 | |
|   WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *PrivateRoot;
 | |
| 
 | |
|   if ((This == NULL) || (InformationType == NULL) || (BufferSize == NULL)) {
 | |
|     return EFI_INVALID_PARAMETER;
 | |
|   }
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
|   PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
 | |
| 
 | |
|   Status = EFI_UNSUPPORTED;
 | |
| 
 | |
|   if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
 | |
|     Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);
 | |
|   }
 | |
| 
 | |
|   if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
 | |
|     if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
 | |
|       *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
 | |
|       Status      = EFI_BUFFER_TOO_SMALL;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     FileSystemInfoBuffer           = (EFI_FILE_SYSTEM_INFO *)Buffer;
 | |
|     FileSystemInfoBuffer->Size     = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
 | |
|     FileSystemInfoBuffer->ReadOnly = FALSE;
 | |
| 
 | |
|     //
 | |
|     // Try to get the drive name
 | |
|     //
 | |
|     DriveNameFound = FALSE;
 | |
|     DriveName      = AllocatePool (StrSize (PrivateFile->FilePath) + 1);
 | |
|     if (DriveName == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (
 | |
|       DriveName,
 | |
|       (StrSize (PrivateFile->FilePath) + 1) / sizeof (CHAR16),
 | |
|       PrivateFile->FilePath
 | |
|       );
 | |
|     for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) {
 | |
|     }
 | |
| 
 | |
|     if (DriveName[Index] == ':') {
 | |
|       DriveName[Index + 1] = '\\';
 | |
|       DriveName[Index + 2] = 0;
 | |
|       DriveNameFound       = TRUE;
 | |
|     } else if ((DriveName[0] == '\\') && (DriveName[1] == '\\')) {
 | |
|       for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
 | |
|       }
 | |
| 
 | |
|       if (DriveName[Index] == '\\') {
 | |
|         DriveNameFound = TRUE;
 | |
|         for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
 | |
|         }
 | |
| 
 | |
|         DriveName[Index]     = '\\';
 | |
|         DriveName[Index + 1] = 0;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     //
 | |
|     // Try GetDiskFreeSpace first
 | |
|     //
 | |
|     NtStatus = GetDiskFreeSpace (
 | |
|                  DriveNameFound ? DriveName : NULL,
 | |
|                  (LPDWORD)&SectorsPerCluster,
 | |
|                  (LPDWORD)&BytesPerSector,
 | |
|                  (LPDWORD)&FreeClusters,
 | |
|                  (LPDWORD)&TotalClusters
 | |
|                  );
 | |
|     if (DriveName) {
 | |
|       FreePool (DriveName);
 | |
|     }
 | |
| 
 | |
|     if (NtStatus) {
 | |
|       //
 | |
|       // Succeeded
 | |
|       //
 | |
|       BytesPerCluster                  = BytesPerSector * SectorsPerCluster;
 | |
|       FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster);
 | |
|       FileSystemInfoBuffer->FreeSpace  = MultU64x32 (FreeClusters, BytesPerCluster);
 | |
|       FileSystemInfoBuffer->BlockSize  = BytesPerCluster;
 | |
|     } else {
 | |
|       //
 | |
|       // try GetDiskFreeSpaceEx then
 | |
|       //
 | |
|       FileSystemInfoBuffer->BlockSize = 0;
 | |
|       NtStatus                        = GetDiskFreeSpaceEx (
 | |
|                                           PrivateFile->FilePath,
 | |
|                                           (PULARGE_INTEGER)(&FileSystemInfoBuffer->FreeSpace),
 | |
|                                           (PULARGE_INTEGER)(&FileSystemInfoBuffer->VolumeSize),
 | |
|                                           NULL
 | |
|                                           );
 | |
|       if (!NtStatus) {
 | |
|         Status = EFI_DEVICE_ERROR;
 | |
|         goto Done;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     StrCpyS (
 | |
|       (CHAR16 *)FileSystemInfoBuffer->VolumeLabel,
 | |
|       (*BufferSize - SIZE_OF_EFI_FILE_SYSTEM_INFO) / sizeof (CHAR16),
 | |
|       PrivateRoot->VolumeLabel
 | |
|       );
 | |
|     *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
 | |
|     Status      = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
|   if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
 | |
|     if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
 | |
|       *BufferSize = StrSize (PrivateRoot->VolumeLabel);
 | |
|       Status      = EFI_BUFFER_TOO_SMALL;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (
 | |
|       (CHAR16 *)Buffer,
 | |
|       *BufferSize / sizeof (CHAR16),
 | |
|       PrivateRoot->VolumeLabel
 | |
|       );
 | |
|     *BufferSize = StrSize (PrivateRoot->VolumeLabel);
 | |
|     Status      = EFI_SUCCESS;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Set information about a file
 | |
| 
 | |
|   @param  File            Protocol instance pointer.
 | |
|   @param  InformationType Type of information in Buffer.
 | |
|   @param  BufferSize      Size of buffer.
 | |
|   @param  Buffer          The data to write.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was returned.
 | |
|   @retval EFI_UNSUPPORTED      InformationType is not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileSetInfo (
 | |
|   IN EFI_FILE_PROTOCOL  *This,
 | |
|   IN EFI_GUID           *InformationType,
 | |
|   IN UINTN              BufferSize,
 | |
|   IN VOID               *Buffer
 | |
|   )
 | |
| {
 | |
|   WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *PrivateRoot;
 | |
|   WIN_NT_EFI_FILE_PRIVATE            *PrivateFile;
 | |
|   EFI_FILE_INFO                      *OldFileInfo;
 | |
|   EFI_FILE_INFO                      *NewFileInfo;
 | |
|   EFI_STATUS                         Status;
 | |
|   UINTN                              OldInfoSize;
 | |
|   INTN                               NtStatus;
 | |
|   UINT32                             NewAttr;
 | |
|   UINT32                             OldAttr;
 | |
|   CHAR16                             *OldFileName;
 | |
|   CHAR16                             *NewFileName;
 | |
|   CHAR16                             *TempFileName;
 | |
|   CHAR16                             *CharPointer;
 | |
|   BOOLEAN                            AttrChangeFlag;
 | |
|   BOOLEAN                            NameChangeFlag;
 | |
|   BOOLEAN                            SizeChangeFlag;
 | |
|   BOOLEAN                            TimeChangeFlag;
 | |
|   UINT64                             CurPos;
 | |
|   SYSTEMTIME                         NewCreationSystemTime;
 | |
|   SYSTEMTIME                         NewLastAccessSystemTime;
 | |
|   SYSTEMTIME                         NewLastWriteSystemTime;
 | |
|   FILETIME                           NewCreationFileTime;
 | |
|   FILETIME                           NewLastAccessFileTime;
 | |
|   FILETIME                           NewLastWriteFileTime;
 | |
|   WIN32_FIND_DATA                    FindBuf;
 | |
|   EFI_FILE_SYSTEM_INFO               *NewFileSystemInfo;
 | |
|   UINTN                              Size;
 | |
| 
 | |
|   //
 | |
|   // Initialise locals.
 | |
|   //
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
|   PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
 | |
| 
 | |
|   Status         = EFI_UNSUPPORTED;
 | |
|   OldFileInfo    = NewFileInfo = NULL;
 | |
|   OldFileName    = NewFileName = NULL;
 | |
|   AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;
 | |
| 
 | |
|   //
 | |
|   // Set file system information.
 | |
|   //
 | |
|   if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
 | |
|     NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *)Buffer;
 | |
|     if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (NewFileSystemInfo->VolumeLabel)) {
 | |
|       Status = EFI_BAD_BUFFER_SIZE;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     FreePool (PrivateRoot->VolumeLabel);
 | |
|     PrivateRoot->VolumeLabel = AllocatePool (StrSize (NewFileSystemInfo->VolumeLabel));
 | |
|     if (PrivateRoot->VolumeLabel == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (
 | |
|       PrivateRoot->VolumeLabel,
 | |
|       StrSize (NewFileSystemInfo->VolumeLabel) / sizeof (CHAR16),
 | |
|       NewFileSystemInfo->VolumeLabel
 | |
|       );
 | |
| 
 | |
|     Status = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set volume label information.
 | |
|   //
 | |
|   if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
 | |
|     if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
 | |
|       Status = EFI_BAD_BUFFER_SIZE;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (
 | |
|       PrivateRoot->VolumeLabel,
 | |
|       StrSize (PrivateRoot->VolumeLabel) / sizeof (CHAR16),
 | |
|       (CHAR16 *)Buffer
 | |
|       );
 | |
| 
 | |
|     Status = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {
 | |
|     Status = EFI_UNSUPPORTED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (BufferSize < SIZE_OF_EFI_FILE_INFO) {
 | |
|     Status = EFI_BAD_BUFFER_SIZE;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set file/directory information.
 | |
|   //
 | |
| 
 | |
|   //
 | |
|   // Check for invalid set file information parameters.
 | |
|   //
 | |
|   NewFileInfo = (EFI_FILE_INFO *)Buffer;
 | |
| 
 | |
|   if ((NewFileInfo->Size <= SIZE_OF_EFI_FILE_INFO) ||
 | |
|       (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||
 | |
|       ((sizeof (UINTN) == 4) && (NewFileInfo->Size > 0xFFFFFFFF))
 | |
|       )
 | |
|   {
 | |
|     Status = EFI_INVALID_PARAMETER;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // bugbug: - This is not safe.  We need something like EfiStrMaxSize()
 | |
|   // that would have an additional parameter that would be the size
 | |
|   // of the string array just in case there are no NULL characters in
 | |
|   // the string array.
 | |
|   //
 | |
|   //
 | |
|   // Get current file information so we can determine what kind
 | |
|   // of change request this is.
 | |
|   //
 | |
|   OldInfoSize = 0;
 | |
|   Status      = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL);
 | |
| 
 | |
|   if (Status != EFI_BUFFER_TOO_SMALL) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   OldFileInfo = AllocatePool (OldInfoSize);
 | |
|   if (OldFileInfo == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo);
 | |
| 
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   OldFileName = AllocatePool (StrSize (PrivateFile->FileName));
 | |
|   if (OldFileName == NULL) {
 | |
|     Status = EFI_OUT_OF_RESOURCES;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   StrCpyS (
 | |
|     OldFileName,
 | |
|     StrSize (PrivateFile->FileName) / sizeof (CHAR16),
 | |
|     PrivateFile->FileName
 | |
|     );
 | |
| 
 | |
|   //
 | |
|   // Make full pathname from new filename and rootpath.
 | |
|   //
 | |
|   if (NewFileInfo->FileName[0] == '\\') {
 | |
|     Size        = StrSize (PrivateRoot->FilePath);
 | |
|     Size       += StrSize (L"\\");
 | |
|     Size       += StrSize (NewFileInfo->FileName);
 | |
|     NewFileName = AllocatePool (Size);
 | |
|     if (NewFileName == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (NewFileName, Size / sizeof (CHAR16), PrivateRoot->FilePath);
 | |
|     StrCatS (NewFileName, Size / sizeof (CHAR16), L"\\");
 | |
|     StrCatS (NewFileName, Size / sizeof (CHAR16), NewFileInfo->FileName + 1);
 | |
|   } else {
 | |
|     Size        = StrSize (PrivateFile->FilePath);
 | |
|     Size       += StrSize (L"\\");
 | |
|     Size       += StrSize (NewFileInfo->FileName);
 | |
|     NewFileName = AllocatePool (Size);
 | |
|     if (NewFileName == NULL) {
 | |
|       Status = EFI_OUT_OF_RESOURCES;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     StrCpyS (NewFileName, Size / sizeof (CHAR16), PrivateFile->FilePath);
 | |
|     StrCatS (NewFileName, Size / sizeof (CHAR16), L"\\");
 | |
|     StrCatS (NewFileName, Size / sizeof (CHAR16), NewFileInfo->FileName);
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Is there an attribute change request?
 | |
|   //
 | |
|   if (NewFileInfo->Attribute != OldFileInfo->Attribute) {
 | |
|     if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
 | |
|       Status = EFI_INVALID_PARAMETER;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     AttrChangeFlag = TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Is there a name change request?
 | |
|   // bugbug: - Need EfiStrCaseCmp()
 | |
|   //
 | |
|   if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {
 | |
|     NameChangeFlag = TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Is there a size change request?
 | |
|   //
 | |
|   if (NewFileInfo->FileSize != OldFileInfo->FileSize) {
 | |
|     SizeChangeFlag = TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Is there a time stamp change request?
 | |
|   //
 | |
|   if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&
 | |
|       CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))
 | |
|       )
 | |
|   {
 | |
|     TimeChangeFlag = TRUE;
 | |
|   } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&
 | |
|              CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))
 | |
|              )
 | |
|   {
 | |
|     TimeChangeFlag = TRUE;
 | |
|   } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&
 | |
|              CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))
 | |
|              )
 | |
|   {
 | |
|     TimeChangeFlag = TRUE;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // All done if there are no change requests being made.
 | |
|   //
 | |
|   if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {
 | |
|     Status = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Set file or directory information.
 | |
|   //
 | |
|   OldAttr = GetFileAttributes (OldFileName);
 | |
| 
 | |
|   //
 | |
|   // Name change.
 | |
|   //
 | |
|   if (NameChangeFlag) {
 | |
|     //
 | |
|     // Close the handles first
 | |
|     //
 | |
|     if (PrivateFile->IsOpenedByRead) {
 | |
|       Status = EFI_ACCESS_DENIED;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {
 | |
|     }
 | |
| 
 | |
|     if (*CharPointer != 0) {
 | |
|       Status = EFI_ACCESS_DENIED;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
 | |
|       if (PrivateFile->IsDirectoryPath) {
 | |
|         FindClose (PrivateFile->LHandle);
 | |
|       } else {
 | |
|         CloseHandle (PrivateFile->LHandle);
 | |
|         PrivateFile->LHandle = INVALID_HANDLE_VALUE;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->IsDirectoryPath && (PrivateFile->DirHandle != INVALID_HANDLE_VALUE)) {
 | |
|       CloseHandle (PrivateFile->DirHandle);
 | |
|       PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
 | |
|     }
 | |
| 
 | |
|     NtStatus = MoveFile (OldFileName, NewFileName);
 | |
| 
 | |
|     if (NtStatus) {
 | |
|       //
 | |
|       // modify file name
 | |
|       //
 | |
|       FreePool (PrivateFile->FileName);
 | |
| 
 | |
|       PrivateFile->FileName = AllocatePool (StrSize (NewFileName));
 | |
|       if (PrivateFile->FileName == NULL) {
 | |
|         Status = EFI_OUT_OF_RESOURCES;
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       StrCpyS (PrivateFile->FileName, StrSize (NewFileName) / sizeof (CHAR16), NewFileName);
 | |
| 
 | |
|       Size         = StrSize (NewFileName);
 | |
|       Size        += StrSize (L"\\*");
 | |
|       TempFileName = AllocatePool (Size);
 | |
| 
 | |
|       StrCpyS (TempFileName, Size / sizeof (CHAR16), NewFileName);
 | |
| 
 | |
|       if (!PrivateFile->IsDirectoryPath) {
 | |
|         PrivateFile->LHandle = CreateFile (
 | |
|                                  TempFileName,
 | |
|                                  PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
 | |
|                                  FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                  NULL,
 | |
|                                  OPEN_EXISTING,
 | |
|                                  0,
 | |
|                                  NULL
 | |
|                                  );
 | |
| 
 | |
|         FreePool (TempFileName);
 | |
| 
 | |
|         //
 | |
|         //  Flush buffers just in case
 | |
|         //
 | |
|         if (FlushFileBuffers (PrivateFile->LHandle) == 0) {
 | |
|           Status = EFI_DEVICE_ERROR;
 | |
|           goto Done;
 | |
|         }
 | |
|       } else {
 | |
|         PrivateFile->DirHandle = CreateFile (
 | |
|                                    TempFileName,
 | |
|                                    PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
 | |
|                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                    NULL,
 | |
|                                    OPEN_EXISTING,
 | |
|                                    FILE_FLAG_BACKUP_SEMANTICS,
 | |
|                                    NULL
 | |
|                                    );
 | |
| 
 | |
|         StrCatS (TempFileName, Size / sizeof (CHAR16), L"\\*");
 | |
|         PrivateFile->LHandle = FindFirstFile (TempFileName, &FindBuf);
 | |
| 
 | |
|         FreePool (TempFileName);
 | |
|       }
 | |
|     } else {
 | |
|       Status = EFI_ACCESS_DENIED;
 | |
| Reopen:;
 | |
| 
 | |
|       NtStatus = SetFileAttributes (OldFileName, OldAttr);
 | |
| 
 | |
|       if (!NtStatus) {
 | |
|         goto Done;
 | |
|       }
 | |
| 
 | |
|       Size         = StrSize (OldFileName);
 | |
|       Size        += StrSize (L"\\*");
 | |
|       TempFileName = AllocatePool (Size);
 | |
| 
 | |
|       StrCpyS (TempFileName, Size / sizeof (CHAR16), OldFileName);
 | |
| 
 | |
|       if (!PrivateFile->IsDirectoryPath) {
 | |
|         PrivateFile->LHandle = CreateFile (
 | |
|                                  TempFileName,
 | |
|                                  PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
 | |
|                                  FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                  NULL,
 | |
|                                  OPEN_EXISTING,
 | |
|                                  0,
 | |
|                                  NULL
 | |
|                                  );
 | |
|       } else {
 | |
|         PrivateFile->DirHandle = CreateFile (
 | |
|                                    TempFileName,
 | |
|                                    PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
 | |
|                                    FILE_SHARE_READ | FILE_SHARE_WRITE,
 | |
|                                    NULL,
 | |
|                                    OPEN_EXISTING,
 | |
|                                    FILE_FLAG_BACKUP_SEMANTICS,
 | |
|                                    NULL
 | |
|                                    );
 | |
| 
 | |
|         StrCatS (TempFileName, Size / sizeof (CHAR16), L"\\*");
 | |
|         PrivateFile->LHandle = FindFirstFile (TempFileName, &FindBuf);
 | |
|       }
 | |
| 
 | |
|       FreePool (TempFileName);
 | |
| 
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   //  Size change
 | |
|   //
 | |
|   if (SizeChangeFlag) {
 | |
|     if (PrivateFile->IsDirectoryPath) {
 | |
|       Status = EFI_UNSUPPORTED;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {
 | |
|       Status = EFI_ACCESS_DENIED;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = This->GetPosition (This, &CurPos);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = This->SetPosition (This, NewFileInfo->FileSize);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (SetEndOfFile (PrivateFile->LHandle) == 0) {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     Status = This->SetPosition (This, CurPos);
 | |
|     if (EFI_ERROR (Status)) {
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // Time change
 | |
|   //
 | |
|   if (TimeChangeFlag) {
 | |
|     NewCreationSystemTime.wYear         = NewFileInfo->CreateTime.Year;
 | |
|     NewCreationSystemTime.wMonth        = NewFileInfo->CreateTime.Month;
 | |
|     NewCreationSystemTime.wDay          = NewFileInfo->CreateTime.Day;
 | |
|     NewCreationSystemTime.wHour         = NewFileInfo->CreateTime.Hour;
 | |
|     NewCreationSystemTime.wMinute       = NewFileInfo->CreateTime.Minute;
 | |
|     NewCreationSystemTime.wSecond       = NewFileInfo->CreateTime.Second;
 | |
|     NewCreationSystemTime.wMilliseconds = 0;
 | |
| 
 | |
|     if (!SystemTimeToFileTime (
 | |
|            &NewCreationSystemTime,
 | |
|            &NewCreationFileTime
 | |
|            ))
 | |
|     {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (!LocalFileTimeToFileTime (
 | |
|            &NewCreationFileTime,
 | |
|            &NewCreationFileTime
 | |
|            ))
 | |
|     {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     NewLastAccessSystemTime.wYear         = NewFileInfo->LastAccessTime.Year;
 | |
|     NewLastAccessSystemTime.wMonth        = NewFileInfo->LastAccessTime.Month;
 | |
|     NewLastAccessSystemTime.wDay          = NewFileInfo->LastAccessTime.Day;
 | |
|     NewLastAccessSystemTime.wHour         = NewFileInfo->LastAccessTime.Hour;
 | |
|     NewLastAccessSystemTime.wMinute       = NewFileInfo->LastAccessTime.Minute;
 | |
|     NewLastAccessSystemTime.wSecond       = NewFileInfo->LastAccessTime.Second;
 | |
|     NewLastAccessSystemTime.wMilliseconds = 0;
 | |
| 
 | |
|     if (!SystemTimeToFileTime (
 | |
|            &NewLastAccessSystemTime,
 | |
|            &NewLastAccessFileTime
 | |
|            ))
 | |
|     {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (!LocalFileTimeToFileTime (
 | |
|            &NewLastAccessFileTime,
 | |
|            &NewLastAccessFileTime
 | |
|            ))
 | |
|     {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     NewLastWriteSystemTime.wYear         = NewFileInfo->ModificationTime.Year;
 | |
|     NewLastWriteSystemTime.wMonth        = NewFileInfo->ModificationTime.Month;
 | |
|     NewLastWriteSystemTime.wDay          = NewFileInfo->ModificationTime.Day;
 | |
|     NewLastWriteSystemTime.wHour         = NewFileInfo->ModificationTime.Hour;
 | |
|     NewLastWriteSystemTime.wMinute       = NewFileInfo->ModificationTime.Minute;
 | |
|     NewLastWriteSystemTime.wSecond       = NewFileInfo->ModificationTime.Second;
 | |
|     NewLastWriteSystemTime.wMilliseconds = 0;
 | |
| 
 | |
|     if (!SystemTimeToFileTime (
 | |
|            &NewLastWriteSystemTime,
 | |
|            &NewLastWriteFileTime
 | |
|            ))
 | |
|     {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (!LocalFileTimeToFileTime (
 | |
|            &NewLastWriteFileTime,
 | |
|            &NewLastWriteFileTime
 | |
|            ))
 | |
|     {
 | |
|       goto Done;
 | |
|     }
 | |
| 
 | |
|     if (!SetFileTime (
 | |
|            PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,
 | |
|            &NewCreationFileTime,
 | |
|            &NewLastAccessFileTime,
 | |
|            &NewLastWriteFileTime
 | |
|            ))
 | |
|     {
 | |
|       Status = EFI_DEVICE_ERROR;
 | |
|       goto Done;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //
 | |
|   // No matter about AttrChangeFlag, Attribute must be set.
 | |
|   // Because operation before may cause attribute change.
 | |
|   //
 | |
|   NewAttr = OldAttr;
 | |
| 
 | |
|   if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) {
 | |
|     NewAttr |= FILE_ATTRIBUTE_ARCHIVE;
 | |
|   } else {
 | |
|     NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE;
 | |
|   }
 | |
| 
 | |
|   if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) {
 | |
|     NewAttr |= FILE_ATTRIBUTE_HIDDEN;
 | |
|   } else {
 | |
|     NewAttr &= ~FILE_ATTRIBUTE_HIDDEN;
 | |
|   }
 | |
| 
 | |
|   if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) {
 | |
|     NewAttr |= FILE_ATTRIBUTE_SYSTEM;
 | |
|   } else {
 | |
|     NewAttr &= ~FILE_ATTRIBUTE_SYSTEM;
 | |
|   }
 | |
| 
 | |
|   if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {
 | |
|     NewAttr |= FILE_ATTRIBUTE_READONLY;
 | |
|   } else {
 | |
|     NewAttr &= ~FILE_ATTRIBUTE_READONLY;
 | |
|   }
 | |
| 
 | |
|   NtStatus = SetFileAttributes (NewFileName, NewAttr);
 | |
| 
 | |
|   if (!NtStatus) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Reopen;
 | |
|   }
 | |
| 
 | |
| Done:
 | |
|   if (OldFileInfo != NULL) {
 | |
|     FreePool (OldFileInfo);
 | |
|   }
 | |
| 
 | |
|   if (OldFileName != NULL) {
 | |
|     FreePool (OldFileName);
 | |
|   }
 | |
| 
 | |
|   if (NewFileName != NULL) {
 | |
|     FreePool (NewFileName);
 | |
|   }
 | |
| 
 | |
|   return Status;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Flush data back for the file handle.
 | |
| 
 | |
|   @param  This Protocol instance pointer.
 | |
| 
 | |
|   @retval EFI_SUCCESS          Data was written.
 | |
|   @retval EFI_UNSUPPORTED      Writes to Open directory are not supported.
 | |
|   @retval EFI_NO_MEDIA         The device has no media.
 | |
|   @retval EFI_DEVICE_ERROR     The device reported an error.
 | |
|   @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
 | |
|   @retval EFI_WRITE_PROTECTED  The device is write protected.
 | |
|   @retval EFI_ACCESS_DENIED    The file was open for read only.
 | |
|   @retval EFI_VOLUME_FULL      The volume is full.
 | |
| 
 | |
| **/
 | |
| EFI_STATUS
 | |
| WinNtFileFlush (
 | |
|   IN EFI_FILE_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   BY_HANDLE_FILE_INFORMATION  FileInfo;
 | |
|   WIN_NT_EFI_FILE_PRIVATE     *PrivateFile;
 | |
|   EFI_STATUS                  Status;
 | |
| 
 | |
|   PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
 | |
| 
 | |
|   if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
 | |
|     Status = EFI_DEVICE_ERROR;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->IsDirectoryPath) {
 | |
|     Status = EFI_SUCCESS;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   if (PrivateFile->IsOpenedByRead) {
 | |
|     Status = EFI_ACCESS_DENIED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo);
 | |
| 
 | |
|   if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
 | |
|     Status = EFI_ACCESS_DENIED;
 | |
|     goto Done;
 | |
|   }
 | |
| 
 | |
|   Status = FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
 | |
| 
 | |
| Done:
 | |
|   return Status;
 | |
|   //
 | |
|   // bugbug: - Use Windows error reporting.
 | |
|   //
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WinNtFileSystmeThunkOpen (
 | |
|   IN  EMU_IO_THUNK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *Private;
 | |
| 
 | |
|   Private = AllocateZeroPool (sizeof (*Private));
 | |
|   if (Private == NULL) {
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Private->FilePath = AllocateCopyPool (StrSize (This->ConfigString), This->ConfigString);
 | |
|   if (Private->FilePath == NULL) {
 | |
|     FreePool (Private);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Private->VolumeLabel = AllocateCopyPool (StrSize (L"EFI_EMULATED"), L"EFI_EMULATED");
 | |
|   if (Private->VolumeLabel == NULL) {
 | |
|     FreePool (Private->FilePath);
 | |
|     FreePool (Private);
 | |
|     return EFI_OUT_OF_RESOURCES;
 | |
|   }
 | |
| 
 | |
|   Private->Signature = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;
 | |
|   Private->Thunk     = This;
 | |
|   CopyMem (&Private->SimpleFileSystem, &gWinNtFileSystemProtocol, sizeof (Private->SimpleFileSystem));
 | |
| 
 | |
|   This->Interface = &Private->SimpleFileSystem;
 | |
|   This->Private   = Private;
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_STATUS
 | |
| WinNtFileSystmeThunkClose (
 | |
|   IN  EMU_IO_THUNK_PROTOCOL  *This
 | |
|   )
 | |
| {
 | |
|   WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE  *Private;
 | |
| 
 | |
|   Private = This->Private;
 | |
|   ASSERT (Private != NULL);
 | |
| 
 | |
|   if (Private->VolumeLabel != NULL) {
 | |
|     FreePool (Private->VolumeLabel);
 | |
|   }
 | |
| 
 | |
|   if (Private->FilePath != NULL) {
 | |
|     FreePool (Private->FilePath);
 | |
|   }
 | |
| 
 | |
|   FreePool (Private);
 | |
|   return EFI_SUCCESS;
 | |
| }
 | |
| 
 | |
| EFI_FILE_PROTOCOL  gWinNtFileProtocol = {
 | |
|   EFI_FILE_REVISION,
 | |
|   WinNtFileOpen,
 | |
|   WinNtFileClose,
 | |
|   WinNtFileDelete,
 | |
|   WinNtFileRead,
 | |
|   WinNtFileWrite,
 | |
|   WinNtFileGetPossition,
 | |
|   WinNtFileSetPossition,
 | |
|   WinNtFileGetInfo,
 | |
|   WinNtFileSetInfo,
 | |
|   WinNtFileFlush
 | |
| };
 | |
| 
 | |
| EFI_SIMPLE_FILE_SYSTEM_PROTOCOL  gWinNtFileSystemProtocol = {
 | |
|   EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION,
 | |
|   WinNtOpenVolume
 | |
| };
 | |
| 
 | |
| EMU_IO_THUNK_PROTOCOL  mWinNtFileSystemThunkIo = {
 | |
|   &gEfiSimpleFileSystemProtocolGuid,
 | |
|   NULL,
 | |
|   NULL,
 | |
|   0,
 | |
|   WinNtFileSystmeThunkOpen,
 | |
|   WinNtFileSystmeThunkClose,
 | |
|   NULL
 | |
| };
 |