2 Support OS native directory access.
4 Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 #define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 'f', 's')
23 EMU_IO_THUNK_PROTOCOL
*Thunk
;
24 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFileSystem
;
27 } WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
;
29 #define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \
31 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE, \
33 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \
37 #define WIN_NT_EFI_FILE_PRIVATE_SIGNATURE SIGNATURE_32 ('l', 'o', 'f', 's')
41 EMU_IO_THUNK_PROTOCOL
*Thunk
;
42 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFileSystem
;
43 EFI_FILE_PROTOCOL EfiFile
;
46 BOOLEAN IsRootDirectory
;
47 BOOLEAN IsDirectoryPath
;
48 BOOLEAN IsOpenedByRead
;
51 BOOLEAN IsValidFindBuf
;
52 WIN32_FIND_DATA FindBuf
;
53 } WIN_NT_EFI_FILE_PRIVATE
;
55 #define WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \
57 WIN_NT_EFI_FILE_PRIVATE, \
59 WIN_NT_EFI_FILE_PRIVATE_SIGNATURE \
62 extern EFI_FILE_PROTOCOL gWinNtFileProtocol
;
63 extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol
;
67 IN EFI_FILE_PROTOCOL
*This
,
68 IN EFI_GUID
*InformationType
,
69 IN OUT UINTN
*BufferSize
,
75 IN EFI_FILE_PROTOCOL
*This
,
76 IN EFI_GUID
*InformationType
,
92 Locate the first occurance of a character in a string.
96 Str - Pointer to NULL terminated unicode string.
97 Chr - Character to locate.
101 If Str is NULL, then NULL is returned.
102 If Chr is not contained in Str, then NULL is returned.
103 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
111 while (*Str
!= '\0' && *Str
!= Chr
) {
115 return (*Str
== Chr
) ? Str
: NULL
;
126 if (Buffer
== NULL
|| Length
== 0) {
130 if (*(UINT8
*) Buffer
!= 0) {
135 if (!CompareMem (Buffer
, (UINT8
*) Buffer
+ 1, Length
- 1)) {
151 if (StrLen (Str
) < Count
) {
156 for (Pointer
= Str
; *(Pointer
+ Count
); Pointer
++) {
157 *Pointer
= *(Pointer
+ Count
);
160 *Pointer
= *(Pointer
+ Count
);
164 Open the root directory on a volume.
166 @param This Protocol instance pointer.
167 @param Root Returns an Open file handle for the root directory
169 @retval EFI_SUCCESS The device was opened.
170 @retval EFI_UNSUPPORTED This volume does not support the file system.
171 @retval EFI_NO_MEDIA The device has no media.
172 @retval EFI_DEVICE_ERROR The device reported an error.
173 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
174 @retval EFI_ACCESS_DENIED The service denied access to the file.
175 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
180 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
181 OUT EFI_FILE_PROTOCOL
**Root
185 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
186 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
187 CHAR16
*TempFileName
;
190 if (This
== NULL
|| Root
== NULL
) {
191 return EFI_INVALID_PARAMETER
;
194 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
196 PrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
197 if (PrivateFile
== NULL
) {
198 Status
= EFI_OUT_OF_RESOURCES
;
202 PrivateFile
->FileName
= AllocatePool (StrSize (Private
->FilePath
));
203 if (PrivateFile
->FileName
== NULL
) {
204 Status
= EFI_OUT_OF_RESOURCES
;
208 PrivateFile
->FilePath
= AllocatePool (StrSize (Private
->FilePath
));
209 if (PrivateFile
->FilePath
== NULL
) {
210 Status
= EFI_OUT_OF_RESOURCES
;
214 StrCpy (PrivateFile
->FilePath
, Private
->FilePath
);
215 StrCpy (PrivateFile
->FileName
, PrivateFile
->FilePath
);
216 PrivateFile
->Signature
= WIN_NT_EFI_FILE_PRIVATE_SIGNATURE
;
217 PrivateFile
->Thunk
= Private
->Thunk
;
218 PrivateFile
->SimpleFileSystem
= This
;
219 PrivateFile
->IsRootDirectory
= TRUE
;
220 PrivateFile
->IsDirectoryPath
= TRUE
;
221 PrivateFile
->IsOpenedByRead
= TRUE
;
222 CopyMem (&PrivateFile
->EfiFile
, &gWinNtFileProtocol
, sizeof (gWinNtFileProtocol
));
223 PrivateFile
->IsValidFindBuf
= FALSE
;
228 PrivateFile
->DirHandle
= CreateFile (
229 PrivateFile
->FilePath
,
231 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
234 FILE_FLAG_BACKUP_SEMANTICS
,
238 if (PrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
239 Status
= EFI_NOT_FOUND
;
244 // Find the first file under it
246 Size
= StrSize (PrivateFile
->FilePath
);
247 Size
+= StrSize (L
"\\*");
248 TempFileName
= AllocatePool (Size
);
249 if (TempFileName
== NULL
) {
252 StrCpy (TempFileName
, PrivateFile
->FilePath
);
253 StrCat (TempFileName
, L
"\\*");
255 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &PrivateFile
->FindBuf
);
256 FreePool (TempFileName
);
258 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
259 PrivateFile
->IsValidFindBuf
= FALSE
;
261 PrivateFile
->IsValidFindBuf
= TRUE
;
263 *Root
= &PrivateFile
->EfiFile
;
265 Status
= EFI_SUCCESS
;
268 if (EFI_ERROR (Status
)) {
270 if (PrivateFile
->FileName
) {
271 FreePool (PrivateFile
->FileName
);
274 if (PrivateFile
->FilePath
) {
275 FreePool (PrivateFile
->FilePath
);
278 FreePool (PrivateFile
);
286 Count the number of Leading Dot in FileNameToken.
288 @param FileNameToken A string representing a token in the path name.
290 @return UINTN The number of leading dot in the name.
295 IN CONST CHAR16
* FileNameToken
301 while (*FileNameToken
== L
'.') {
311 IsFileNameTokenValid (
312 IN CONST CHAR16
* FileNameToken
316 if (StrStr (FileNameToken
, L
"/") != NULL
) {
318 // No L'/' in file name.
323 // If Token has all dot, the number should not exceed 2
325 Num
= CountLeadingDots (FileNameToken
);
327 if (Num
== StrLen (FileNameToken
)) {
329 // If the FileNameToken only contains a number of L'.'.
342 Return the first string token found in the indirect pointer a String named by FileName.
344 On input, FileName is a indirect pointer pointing to a String.
345 On output, FileName is a updated to point to the next character after the first
346 found L"\" or NULL if there is no L"\" found.
348 @param FileName A indirect pointer pointing to a FileName.
350 @return Token The first string token found before a L"\".
354 GetNextFileNameToken (
355 IN OUT CONST CHAR16
** FileName
361 ASSERT (**FileName
!= L
'\\');
362 ASSERT (**FileName
!= L
'\0');
364 SlashPos
= StrStr (*FileName
, L
"\\");
365 if (SlashPos
== NULL
) {
366 Token
= AllocateCopyPool (StrSize (*FileName
), *FileName
);
369 Offset
= SlashPos
- *FileName
;
370 Token
= AllocateZeroPool ((Offset
+ 1) * sizeof (CHAR16
));
371 StrnCpy (Token
, *FileName
, Offset
);
373 // Point *FileName to the next character after L'\'.
375 *FileName
= *FileName
+ Offset
+ 1;
377 // If *FileName is an empty string, then set *FileName to NULL
379 if (**FileName
== L
'\0') {
389 Check if a FileName contains only Valid Characters.
391 If FileName contains only a single L'\', return TRUE.
392 If FileName contains two adjacent L'\', return FALSE.
393 If FileName conatins L'/' , return FALSE.
394 If FielName contains more than two dots seperated with other FileName characters
395 by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
397 @param FileName The File Name String to check.
399 @return TRUE FileName only contains valid characters.
400 @return FALSE FileName contains at least one invalid character.
406 IN CONST CHAR16
*FileName
413 // If FileName is just L'\', then it is a valid pathname.
415 if (StrCmp (FileName
, L
"\\") == 0) {
419 // We don't support two or more adjacent L'\'.
421 if (StrStr (FileName
, L
"\\\\") != NULL
) {
426 // Is FileName has a leading L"\", skip to next character.
428 if (FileName
[0] == L
'\\') {
433 Token
= GetNextFileNameToken (&FileName
);
434 Valid
= IsFileNameTokenValid (Token
);
439 } while (FileName
!= NULL
);
446 Opens a new file relative to the source file's location.
448 @param This The protocol instance pointer.
449 @param NewHandle Returns File Handle for FileName.
450 @param FileName Null terminated string. "\", ".", and ".." are supported.
451 @param OpenMode Open mode for file.
452 @param Attributes Only used for EFI_FILE_MODE_CREATE.
454 @retval EFI_SUCCESS The device was opened.
455 @retval EFI_NOT_FOUND The specified file could not be found on the device.
456 @retval EFI_NO_MEDIA The device has no media.
457 @retval EFI_MEDIA_CHANGED The media has changed.
458 @retval EFI_DEVICE_ERROR The device reported an error.
459 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
460 @retval EFI_ACCESS_DENIED The service denied access to the file.
461 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
462 @retval EFI_VOLUME_FULL The volume is full.
467 IN EFI_FILE_PROTOCOL
*This
,
468 OUT EFI_FILE_PROTOCOL
**NewHandle
,
474 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
475 WIN_NT_EFI_FILE_PRIVATE
*NewPrivateFile
;
476 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
478 CHAR16
*RealFileName
;
479 CHAR16
*TempFileName
;
480 CHAR16
*ParseFileName
;
481 CHAR16
*GuardPointer
;
492 // Init local variables
494 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
495 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
496 NewPrivateFile
= NULL
;
499 // Allocate buffer for FileName as the passed in FileName may be read only
501 TempFileName
= AllocatePool (StrSize (FileName
));
502 if (TempFileName
== NULL
) {
503 return EFI_OUT_OF_RESOURCES
;
505 StrCpy (TempFileName
, FileName
);
506 FileName
= TempFileName
;
508 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
509 FileName
[StrLen (FileName
) - 1] = 0;
513 // If file name does not equal to "." or ".." and not trailed with "\..",
514 // then we trim the leading/trailing blanks and trailing dots
516 if (StrCmp (FileName
, L
".") != 0 && StrCmp (FileName
, L
"..") != 0 &&
517 ((StrLen (FileName
) >= 3) ? (StrCmp (&FileName
[StrLen (FileName
) - 3], L
"\\..") != 0) : TRUE
)) {
519 // Trim leading blanks
522 for (TempFileName
= FileName
;
523 *TempFileName
!= 0 && *TempFileName
== L
' ';
527 CutPrefix (FileName
, Count
);
529 // Trim trailing blanks
531 for (TempFileName
= FileName
+ StrLen (FileName
) - 1;
532 TempFileName
>= FileName
&& (*TempFileName
== L
' ');
536 *(TempFileName
+ 1) = 0;
540 // Attempt to open the file
542 NewPrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
543 if (NewPrivateFile
== NULL
) {
544 Status
= EFI_OUT_OF_RESOURCES
;
548 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (WIN_NT_EFI_FILE_PRIVATE
));
550 NewPrivateFile
->FilePath
= AllocatePool (StrSize (PrivateFile
->FileName
));
551 if (NewPrivateFile
->FilePath
== NULL
) {
552 Status
= EFI_OUT_OF_RESOURCES
;
556 if (PrivateFile
->IsDirectoryPath
) {
557 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FileName
);
559 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FilePath
);
562 Size
= StrSize (NewPrivateFile
->FilePath
);
563 Size
+= StrSize (L
"\\");
564 Size
+= StrSize (FileName
);
565 NewPrivateFile
->FileName
= AllocatePool (Size
);
566 if (NewPrivateFile
->FileName
== NULL
) {
567 Status
= EFI_OUT_OF_RESOURCES
;
571 if (*FileName
== L
'\\') {
572 StrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
573 StrCat (NewPrivateFile
->FileName
, L
"\\");
574 StrCat (NewPrivateFile
->FileName
, FileName
+ 1);
576 StrCpy (NewPrivateFile
->FileName
, NewPrivateFile
->FilePath
);
577 if (StrCmp (FileName
, L
"") != 0) {
579 // In case the filename becomes empty, especially after trimming dots and blanks
581 StrCat (NewPrivateFile
->FileName
, L
"\\");
582 StrCat (NewPrivateFile
->FileName
, FileName
);
586 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
587 Status
= EFI_NOT_FOUND
;
592 // Get rid of . and .., except leading . or ..
596 // GuardPointer protect simplefilesystem root path not be destroyed
598 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
602 while (!LoopFinish
) {
606 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
607 if (*ParseFileName
== L
'.' &&
608 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
609 *(ParseFileName
- 1) == L
'\\'
615 CutPrefix (ParseFileName
- 1, 2);
620 if (*ParseFileName
== L
'.' &&
621 *(ParseFileName
+ 1) == L
'.' &&
622 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
623 *(ParseFileName
- 1) == L
'\\'
629 while (ParseFileName
!= GuardPointer
) {
632 if (*ParseFileName
== L
'\\') {
638 // cut \.. and its left directory
640 CutPrefix (ParseFileName
, Count
);
647 RealFileName
= NewPrivateFile
->FileName
;
648 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
649 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
653 if (RealFileName
!= NewPrivateFile
->FileName
) {
654 TempChar
= *(RealFileName
- 1);
655 *(RealFileName
- 1) = 0;
658 FreePool (NewPrivateFile
->FilePath
);
659 NewPrivateFile
->FilePath
= NULL
;
660 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
661 if (NewPrivateFile
->FilePath
== NULL
) {
662 Status
= EFI_OUT_OF_RESOURCES
;
666 StrCpy (NewPrivateFile
->FilePath
, NewPrivateFile
->FileName
);
668 *(RealFileName
- 1) = TempChar
;
671 NewPrivateFile
->IsRootDirectory
= FALSE
;
674 // Test whether file or directory
676 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
677 if (Attributes
& EFI_FILE_DIRECTORY
) {
678 NewPrivateFile
->IsDirectoryPath
= TRUE
;
680 NewPrivateFile
->IsDirectoryPath
= FALSE
;
683 NewPrivateFile
->LHandle
= CreateFile (
684 NewPrivateFile
->FileName
,
686 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
693 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
694 NewPrivateFile
->IsDirectoryPath
= FALSE
;
695 CloseHandle (NewPrivateFile
->LHandle
);
697 NewPrivateFile
->IsDirectoryPath
= TRUE
;
700 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
703 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
704 NewPrivateFile
->IsOpenedByRead
= FALSE
;
706 NewPrivateFile
->IsOpenedByRead
= TRUE
;
709 Status
= EFI_SUCCESS
;
712 // deal with directory
714 if (NewPrivateFile
->IsDirectoryPath
) {
716 Size
= StrSize (NewPrivateFile
->FileName
);
717 Size
+= StrSize (L
"\\*");
718 TempFileName
= AllocatePool (Size
);
719 if (TempFileName
== NULL
) {
720 Status
= EFI_OUT_OF_RESOURCES
;
724 StrCpy (TempFileName
, NewPrivateFile
->FileName
);
726 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
728 // Create a directory
730 if (!CreateDirectory (TempFileName
, NULL
)) {
732 LastError
= GetLastError ();
733 if (LastError
!= ERROR_ALREADY_EXISTS
) {
734 FreePool (TempFileName
);
735 Status
= EFI_ACCESS_DENIED
;
741 NewPrivateFile
->DirHandle
= CreateFile (
743 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
744 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
747 FILE_FLAG_BACKUP_SEMANTICS
,
751 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
753 NewPrivateFile
->DirHandle
= CreateFile (
756 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
759 FILE_FLAG_BACKUP_SEMANTICS
,
763 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
764 CloseHandle (NewPrivateFile
->DirHandle
);
765 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
766 Status
= EFI_ACCESS_DENIED
;
768 Status
= EFI_NOT_FOUND
;
771 FreePool (TempFileName
);
776 // Find the first file under it
778 StrCat (TempFileName
, L
"\\*");
779 NewPrivateFile
->LHandle
= FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
780 FreePool (TempFileName
);
782 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
783 NewPrivateFile
->IsValidFindBuf
= FALSE
;
785 NewPrivateFile
->IsValidFindBuf
= TRUE
;
791 if (!NewPrivateFile
->IsOpenedByRead
) {
792 NewPrivateFile
->LHandle
= CreateFile (
793 NewPrivateFile
->FileName
,
794 GENERIC_READ
| GENERIC_WRITE
,
795 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
797 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
802 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
803 NewPrivateFile
->LHandle
= CreateFile (
804 NewPrivateFile
->FileName
,
806 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
813 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
814 Status
= EFI_NOT_FOUND
;
816 Status
= EFI_ACCESS_DENIED
;
817 CloseHandle (NewPrivateFile
->LHandle
);
818 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
822 NewPrivateFile
->LHandle
= CreateFile (
823 NewPrivateFile
->FileName
,
825 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
832 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
833 Status
= EFI_NOT_FOUND
;
838 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
845 Status
= WinNtFileGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
847 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
848 Status
= EFI_DEVICE_ERROR
;
852 Info
= AllocatePool (InfoSize
);
854 Status
= EFI_OUT_OF_RESOURCES
;
858 Status
= WinNtFileGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
860 if (EFI_ERROR (Status
)) {
865 Info
->Attribute
= Attributes
;
867 WinNtFileSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
874 if (EFI_ERROR (Status
)) {
875 if (NewPrivateFile
) {
876 if (NewPrivateFile
->FileName
) {
877 FreePool (NewPrivateFile
->FileName
);
880 if (NewPrivateFile
->FilePath
) {
881 FreePool (NewPrivateFile
->FilePath
);
884 FreePool (NewPrivateFile
);
887 *NewHandle
= &NewPrivateFile
->EfiFile
;
888 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
889 NewPrivateFile
->IsRootDirectory
= TRUE
;
899 Close the file handle
901 @param This Protocol instance pointer.
903 @retval EFI_SUCCESS The device was opened.
908 IN EFI_FILE_PROTOCOL
*This
911 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
913 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
915 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
916 if (PrivateFile
->IsDirectoryPath
) {
917 FindClose (PrivateFile
->LHandle
);
919 CloseHandle (PrivateFile
->LHandle
);
922 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
925 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
926 CloseHandle (PrivateFile
->DirHandle
);
927 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
930 if (PrivateFile
->FileName
) {
931 FreePool (PrivateFile
->FileName
);
934 if (PrivateFile
->FilePath
) {
935 FreePool (PrivateFile
->FilePath
);
938 FreePool (PrivateFile
);
946 Close and delete the file handle.
948 @param This Protocol instance pointer.
950 @retval EFI_SUCCESS The device was opened.
951 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
956 IN EFI_FILE_PROTOCOL
*This
960 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
962 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
964 Status
= EFI_WARN_DELETE_FAILURE
;
966 if (PrivateFile
->IsDirectoryPath
) {
967 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
968 FindClose (PrivateFile
->LHandle
);
971 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
972 CloseHandle (PrivateFile
->DirHandle
);
973 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
976 if (RemoveDirectory (PrivateFile
->FileName
)) {
977 Status
= EFI_SUCCESS
;
980 CloseHandle (PrivateFile
->LHandle
);
981 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
983 if (!PrivateFile
->IsOpenedByRead
) {
984 if (DeleteFile (PrivateFile
->FileName
)) {
985 Status
= EFI_SUCCESS
;
990 FreePool (PrivateFile
->FileName
);
991 FreePool (PrivateFile
->FilePath
);
992 FreePool (PrivateFile
);
998 WinNtSystemTimeToEfiTime (
999 IN SYSTEMTIME
*SystemTime
,
1000 IN TIME_ZONE_INFORMATION
*TimeZone
,
1005 Routine Description:
1007 TODO: Add function description
1011 SystemTime - TODO: add argument description
1012 TimeZone - TODO: add argument description
1013 Time - TODO: add argument description
1017 TODO: add return values
1021 Time
->Year
= (UINT16
)SystemTime
->wYear
;
1022 Time
->Month
= (UINT8
)SystemTime
->wMonth
;
1023 Time
->Day
= (UINT8
)SystemTime
->wDay
;
1024 Time
->Hour
= (UINT8
)SystemTime
->wHour
;
1025 Time
->Minute
= (UINT8
)SystemTime
->wMinute
;
1026 Time
->Second
= (UINT8
)SystemTime
->wSecond
;
1027 Time
->Nanosecond
= (UINT32
)SystemTime
->wMilliseconds
* 1000000;
1028 Time
->TimeZone
= (INT16
)TimeZone
->Bias
;
1030 if (TimeZone
->StandardDate
.wMonth
) {
1031 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1036 Convert the FileTime to EfiTime.
1038 @param PrivateFile Pointer to WIN_NT_EFI_FILE_PRIVATE.
1039 @param TimeZone Pointer to the current time zone.
1040 @param FileTime Pointer to file time.
1041 @param EfiTime Pointer to EFI time.
1044 WinNtFileTimeToEfiTime (
1045 IN CONST WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1046 IN TIME_ZONE_INFORMATION
*TimeZone
,
1047 IN CONST FILETIME
*FileTime
,
1048 OUT EFI_TIME
*EfiTime
1051 FILETIME TempFileTime
;
1052 SYSTEMTIME SystemTime
;
1054 FileTimeToLocalFileTime (FileTime
, &TempFileTime
);
1055 FileTimeToSystemTime (&TempFileTime
, &SystemTime
);
1056 WinNtSystemTimeToEfiTime (&SystemTime
, TimeZone
, EfiTime
);
1061 Read data from the file.
1063 @param This Protocol instance pointer.
1064 @param BufferSize On input size of buffer, on output amount of data in buffer.
1065 @param Buffer The buffer in which data is read.
1067 @retval EFI_SUCCESS Data was read.
1068 @retval EFI_NO_MEDIA The device has no media.
1069 @retval EFI_DEVICE_ERROR The device reported an error.
1070 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1071 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1076 IN EFI_FILE_PROTOCOL
*This
,
1077 IN OUT UINTN
*BufferSize
,
1081 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1087 EFI_FILE_INFO
*Info
;
1089 TIME_ZONE_INFORMATION TimeZone
;
1090 EFI_FILE_INFO
*FileInfo
;
1095 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1097 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1098 Status
= EFI_DEVICE_ERROR
;
1102 if (!PrivateFile
->IsDirectoryPath
) {
1104 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1105 Status
= EFI_DEVICE_ERROR
;
1109 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1110 FileInfo
= AllocatePool (FileInfoSize
);
1112 Status
= This
->GetInfo (
1119 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1120 FreePool (FileInfo
);
1121 FileInfo
= AllocatePool (FileInfoSize
);
1122 Status
= This
->GetInfo (
1130 if (EFI_ERROR (Status
)) {
1131 Status
= EFI_DEVICE_ERROR
;
1135 FileSize
= FileInfo
->FileSize
;
1137 FreePool (FileInfo
);
1139 if (Pos
>= FileSize
) {
1141 if (Pos
== FileSize
) {
1142 Status
= EFI_SUCCESS
;
1145 Status
= EFI_DEVICE_ERROR
;
1151 PrivateFile
->LHandle
,
1154 (LPDWORD
)BufferSize
,
1156 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1161 // Read on a directory. Perform a find next
1163 if (!PrivateFile
->IsValidFindBuf
) {
1165 Status
= EFI_SUCCESS
;
1169 Size
= SIZE_OF_EFI_FILE_INFO
;
1171 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1173 ResultSize
= Size
+ NameSize
;
1175 Status
= EFI_BUFFER_TOO_SMALL
;
1177 if (*BufferSize
>= ResultSize
) {
1178 Status
= EFI_SUCCESS
;
1181 ZeroMem (Info
, ResultSize
);
1183 Info
->Size
= ResultSize
;
1185 GetTimeZoneInformation (&TimeZone
);
1186 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftCreationTime
, &Info
->CreateTime
);
1187 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastAccessTime
, &Info
->LastAccessTime
);
1188 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastWriteTime
, &Info
->ModificationTime
);
1190 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1192 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1194 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1195 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1198 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1199 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1202 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1203 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1206 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1207 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1210 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1211 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1214 NameSize
= NameSize
/ sizeof (WCHAR
);
1216 pw
= (WCHAR
*)(((CHAR8
*)Buffer
) + Size
);
1218 for (Index
= 0; Index
< NameSize
; Index
++) {
1219 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1222 if (FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1223 PrivateFile
->IsValidFindBuf
= TRUE
;
1225 PrivateFile
->IsValidFindBuf
= FALSE
;
1229 *BufferSize
= ResultSize
;
1238 Write data to a file.
1240 @param This Protocol instance pointer.
1241 @param BufferSize On input size of buffer, on output amount of data in buffer.
1242 @param Buffer The buffer in which data to write.
1244 @retval EFI_SUCCESS Data was written.
1245 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
1246 @retval EFI_NO_MEDIA The device has no media.
1247 @retval EFI_DEVICE_ERROR The device reported an error.
1248 @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
1249 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1250 @retval EFI_WRITE_PROTECTED The device is write protected.
1251 @retval EFI_ACCESS_DENIED The file was open for read only.
1252 @retval EFI_VOLUME_FULL The volume is full.
1257 IN EFI_FILE_PROTOCOL
*This
,
1258 IN OUT UINTN
*BufferSize
,
1262 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1265 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1267 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1268 Status
= EFI_DEVICE_ERROR
;
1272 if (PrivateFile
->IsDirectoryPath
) {
1273 Status
= EFI_UNSUPPORTED
;
1277 if (PrivateFile
->IsOpenedByRead
) {
1278 Status
= EFI_ACCESS_DENIED
;
1282 Status
= WriteFile (
1283 PrivateFile
->LHandle
,
1286 (LPDWORD
)BufferSize
,
1288 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1294 // bugbug: need to access windows error reporting
1301 Set a files current position
1303 @param This Protocol instance pointer.
1304 @param Position Byte position from the start of the file.
1306 @retval EFI_SUCCESS Data was written.
1307 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1311 WinNtFileSetPossition (
1312 IN EFI_FILE_PROTOCOL
*This
,
1317 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1323 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1325 if (PrivateFile
->IsDirectoryPath
) {
1326 if (Position
!= 0) {
1327 Status
= EFI_UNSUPPORTED
;
1331 Size
= StrSize (PrivateFile
->FileName
);
1332 Size
+= StrSize (L
"\\*");
1333 FileName
= AllocatePool (Size
);
1334 if (FileName
== NULL
) {
1335 Status
= EFI_OUT_OF_RESOURCES
;
1339 StrCpy (FileName
, PrivateFile
->FileName
);
1340 StrCat (FileName
, L
"\\*");
1342 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1343 FindClose (PrivateFile
->LHandle
);
1346 PrivateFile
->LHandle
= FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1348 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1349 PrivateFile
->IsValidFindBuf
= FALSE
;
1351 PrivateFile
->IsValidFindBuf
= TRUE
;
1354 FreePool (FileName
);
1356 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1358 if (Position
== (UINT64
)-1) {
1359 PosLow
= SetFilePointer (PrivateFile
->LHandle
, (ULONG
)0, NULL
, FILE_END
);
1361 PosHigh
= (UINT32
)RShiftU64 (Position
, 32);
1363 PosLow
= SetFilePointer (PrivateFile
->LHandle
, (ULONG
)Position
, (PLONG
)&PosHigh
, FILE_BEGIN
);
1366 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1376 Get a file's current position
1378 @param This Protocol instance pointer.
1379 @param Position Byte position from the start of the file.
1381 @retval EFI_SUCCESS Data was written.
1382 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1386 WinNtFileGetPossition (
1387 IN EFI_FILE_PROTOCOL
*This
,
1388 OUT UINT64
*Position
1392 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1396 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1401 if (PrivateFile
->IsDirectoryPath
) {
1403 Status
= EFI_UNSUPPORTED
;
1409 *Position
= SetFilePointer (
1410 PrivateFile
->LHandle
,
1412 (PLONG
)&PositionHigh
,
1416 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1417 if (EFI_ERROR (Status
)) {
1421 PosHigh64
= PositionHigh
;
1422 *Position
+= LShiftU64 (PosHigh64
, 32);
1431 WinNtSimpleFileSystemFileInfo (
1432 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1433 IN OUT UINTN
*BufferSize
,
1438 Routine Description:
1440 TODO: Add function description
1444 PrivateFile - TODO: add argument description
1445 BufferSize - TODO: add argument description
1446 Buffer - TODO: add argument description
1450 TODO: add return values
1458 EFI_FILE_INFO
*Info
;
1459 BY_HANDLE_FILE_INFORMATION FileInfo
;
1460 CHAR16
*RealFileName
;
1461 CHAR16
*TempPointer
;
1462 TIME_ZONE_INFORMATION TimeZone
;
1464 Size
= SIZE_OF_EFI_FILE_INFO
;
1466 RealFileName
= PrivateFile
->FileName
;
1467 TempPointer
= RealFileName
;
1468 while (*TempPointer
) {
1469 if (*TempPointer
== '\\') {
1470 RealFileName
= TempPointer
+ 1;
1475 NameSize
= StrSize (RealFileName
);
1477 ResultSize
= Size
+ NameSize
;
1479 Status
= EFI_BUFFER_TOO_SMALL
;
1480 if (*BufferSize
>= ResultSize
) {
1481 Status
= EFI_SUCCESS
;
1484 ZeroMem (Info
, ResultSize
);
1486 Info
->Size
= ResultSize
;
1487 GetFileInformationByHandle (
1488 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
1491 Info
->FileSize
= FileInfo
.nFileSizeLow
;
1492 Info
->PhysicalSize
= Info
->FileSize
;
1494 GetTimeZoneInformation (&TimeZone
);
1495 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftCreationTime
, &Info
->CreateTime
);
1496 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastAccessTime
, &Info
->LastAccessTime
);
1497 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastWriteTime
, &Info
->ModificationTime
);
1499 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1500 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1503 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1504 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1507 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1508 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1511 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1512 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1515 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1516 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1519 if (PrivateFile
->IsDirectoryPath
) {
1520 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1523 if (PrivateFile
->IsRootDirectory
) {
1524 *((CHAR8
*)Buffer
+ Size
) = 0;
1526 CopyMem ((CHAR8
*)Buffer
+ Size
, RealFileName
, NameSize
);
1530 *BufferSize
= ResultSize
;
1535 Get information about a file.
1537 @param This Protocol instance pointer.
1538 @param InformationType Type of information to return in Buffer.
1539 @param BufferSize On input size of buffer, on output amount of data in buffer.
1540 @param Buffer The buffer to return data.
1542 @retval EFI_SUCCESS Data was returned.
1543 @retval EFI_UNSUPPORTED InformationType is not supported.
1544 @retval EFI_NO_MEDIA The device has no media.
1545 @retval EFI_DEVICE_ERROR The device reported an error.
1546 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1547 @retval EFI_WRITE_PROTECTED The device is write protected.
1548 @retval EFI_ACCESS_DENIED The file was open for read only.
1549 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1554 IN EFI_FILE_PROTOCOL
*This
,
1555 IN EFI_GUID
*InformationType
,
1556 IN OUT UINTN
*BufferSize
,
1561 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1562 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
1563 UINT32 SectorsPerCluster
;
1564 UINT32 BytesPerSector
;
1565 UINT32 FreeClusters
;
1566 UINT32 TotalClusters
;
1567 UINT32 BytesPerCluster
;
1569 BOOLEAN DriveNameFound
;
1572 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1574 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
1575 return EFI_INVALID_PARAMETER
;
1578 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1579 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1581 Status
= EFI_UNSUPPORTED
;
1583 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1584 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
1587 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1588 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1589 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1590 Status
= EFI_BUFFER_TOO_SMALL
;
1594 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*)Buffer
;
1595 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1596 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
1599 // Try to get the drive name
1601 DriveNameFound
= FALSE
;
1602 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
1603 if (DriveName
== NULL
) {
1604 Status
= EFI_OUT_OF_RESOURCES
;
1608 StrCpy (DriveName
, PrivateFile
->FilePath
);
1609 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
1613 if (DriveName
[Index
] == ':') {
1614 DriveName
[Index
+ 1] = '\\';
1615 DriveName
[Index
+ 2] = 0;
1616 DriveNameFound
= TRUE
;
1617 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
1618 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
1622 if (DriveName
[Index
] == '\\') {
1623 DriveNameFound
= TRUE
;
1624 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
1628 DriveName
[Index
] = '\\';
1629 DriveName
[Index
+ 1] = 0;
1634 // Try GetDiskFreeSpace first
1636 NtStatus
= GetDiskFreeSpace (
1637 DriveNameFound
? DriveName
: NULL
,
1638 (LPDWORD
)&SectorsPerCluster
,
1639 (LPDWORD
)&BytesPerSector
,
1640 (LPDWORD
)&FreeClusters
,
1641 (LPDWORD
)&TotalClusters
1644 FreePool (DriveName
);
1651 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
1652 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
1653 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
1654 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
1658 // try GetDiskFreeSpaceEx then
1660 FileSystemInfoBuffer
->BlockSize
= 0;
1661 NtStatus
= GetDiskFreeSpaceEx (
1662 PrivateFile
->FilePath
,
1663 (PULARGE_INTEGER
)(&FileSystemInfoBuffer
->FreeSpace
),
1664 (PULARGE_INTEGER
)(&FileSystemInfoBuffer
->VolumeSize
),
1668 Status
= EFI_DEVICE_ERROR
;
1673 StrCpy ((CHAR16
*)FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
1674 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1675 Status
= EFI_SUCCESS
;
1678 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1679 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1680 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1681 Status
= EFI_BUFFER_TOO_SMALL
;
1685 StrCpy ((CHAR16
*)Buffer
, PrivateRoot
->VolumeLabel
);
1686 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1687 Status
= EFI_SUCCESS
;
1696 Set information about a file
1698 @param File Protocol instance pointer.
1699 @param InformationType Type of information in Buffer.
1700 @param BufferSize Size of buffer.
1701 @param Buffer The data to write.
1703 @retval EFI_SUCCESS Data was returned.
1704 @retval EFI_UNSUPPORTED InformationType is not supported.
1705 @retval EFI_NO_MEDIA The device has no media.
1706 @retval EFI_DEVICE_ERROR The device reported an error.
1707 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1708 @retval EFI_WRITE_PROTECTED The device is write protected.
1709 @retval EFI_ACCESS_DENIED The file was open for read only.
1714 IN EFI_FILE_PROTOCOL
*This
,
1715 IN EFI_GUID
*InformationType
,
1716 IN UINTN BufferSize
,
1720 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1721 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1722 EFI_FILE_INFO
*OldFileInfo
;
1723 EFI_FILE_INFO
*NewFileInfo
;
1729 CHAR16
*OldFileName
;
1730 CHAR16
*NewFileName
;
1731 CHAR16
*TempFileName
;
1732 CHAR16
*CharPointer
;
1733 BOOLEAN AttrChangeFlag
;
1734 BOOLEAN NameChangeFlag
;
1735 BOOLEAN SizeChangeFlag
;
1736 BOOLEAN TimeChangeFlag
;
1738 SYSTEMTIME NewCreationSystemTime
;
1739 SYSTEMTIME NewLastAccessSystemTime
;
1740 SYSTEMTIME NewLastWriteSystemTime
;
1741 FILETIME NewCreationFileTime
;
1742 FILETIME NewLastAccessFileTime
;
1743 FILETIME NewLastWriteFileTime
;
1744 WIN32_FIND_DATA FindBuf
;
1745 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
1749 // Initialise locals.
1751 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1752 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1754 Status
= EFI_UNSUPPORTED
;
1755 OldFileInfo
= NewFileInfo
= NULL
;
1756 OldFileName
= NewFileName
= NULL
;
1757 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
1760 // Set file system information.
1762 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1763 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*)Buffer
;
1764 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (NewFileSystemInfo
->VolumeLabel
)) {
1765 Status
= EFI_BAD_BUFFER_SIZE
;
1770 FreePool (PrivateRoot
->VolumeLabel
);
1771 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
1772 if (PrivateRoot
->VolumeLabel
== NULL
) {
1773 Status
= EFI_OUT_OF_RESOURCES
;
1777 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
1779 Status
= EFI_SUCCESS
;
1784 // Set volume label information.
1786 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1787 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1788 Status
= EFI_BAD_BUFFER_SIZE
;
1792 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*)Buffer
);
1794 Status
= EFI_SUCCESS
;
1798 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1799 Status
= EFI_UNSUPPORTED
;
1803 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
1804 Status
= EFI_BAD_BUFFER_SIZE
;
1809 // Set file/directory information.
1813 // Check for invalid set file information parameters.
1815 NewFileInfo
= (EFI_FILE_INFO
*)Buffer
;
1817 if ((NewFileInfo
->Size
<= SIZE_OF_EFI_FILE_INFO
) ||
1818 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
1819 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
1821 Status
= EFI_INVALID_PARAMETER
;
1826 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
1827 // that would have an additional parameter that would be the size
1828 // of the string array just in case there are no NULL characters in
1829 // the string array.
1832 // Get current file information so we can determine what kind
1833 // of change request this is.
1836 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
1838 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1839 Status
= EFI_DEVICE_ERROR
;
1843 OldFileInfo
= AllocatePool (OldInfoSize
);
1844 if (OldFileInfo
== NULL
) {
1845 Status
= EFI_OUT_OF_RESOURCES
;
1849 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
1851 if (EFI_ERROR (Status
)) {
1855 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
1856 if (OldFileName
== NULL
) {
1857 Status
= EFI_OUT_OF_RESOURCES
;
1861 StrCpy (OldFileName
, PrivateFile
->FileName
);
1864 // Make full pathname from new filename and rootpath.
1866 if (NewFileInfo
->FileName
[0] == '\\') {
1867 Size
= StrSize (PrivateRoot
->FilePath
);
1868 Size
+= StrSize (L
"\\");
1869 Size
+= StrSize (NewFileInfo
->FileName
);
1870 NewFileName
= AllocatePool (Size
);
1871 if (NewFileName
== NULL
) {
1872 Status
= EFI_OUT_OF_RESOURCES
;
1876 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
1877 StrCat (NewFileName
, L
"\\");
1878 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
1880 Size
= StrSize (PrivateFile
->FilePath
);
1881 Size
+= StrSize (L
"\\");
1882 Size
+= StrSize (NewFileInfo
->FileName
);
1883 NewFileName
= AllocatePool (Size
);
1884 if (NewFileName
== NULL
) {
1885 Status
= EFI_OUT_OF_RESOURCES
;
1889 StrCpy (NewFileName
, PrivateFile
->FilePath
);
1890 StrCat (NewFileName
, L
"\\");
1891 StrCat (NewFileName
, NewFileInfo
->FileName
);
1895 // Is there an attribute change request?
1897 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
1898 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
1899 Status
= EFI_INVALID_PARAMETER
;
1903 AttrChangeFlag
= TRUE
;
1907 // Is there a name change request?
1908 // bugbug: - Need EfiStrCaseCmp()
1910 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
1911 NameChangeFlag
= TRUE
;
1915 // Is there a size change request?
1917 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
1918 SizeChangeFlag
= TRUE
;
1922 // Is there a time stamp change request?
1924 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
1925 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
1927 TimeChangeFlag
= TRUE
;
1928 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
1929 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
1931 TimeChangeFlag
= TRUE
;
1932 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
1933 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
1935 TimeChangeFlag
= TRUE
;
1939 // All done if there are no change requests being made.
1941 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
1942 Status
= EFI_SUCCESS
;
1947 // Set file or directory information.
1949 OldAttr
= GetFileAttributes (OldFileName
);
1954 if (NameChangeFlag
) {
1956 // Close the handles first
1958 if (PrivateFile
->IsOpenedByRead
) {
1959 Status
= EFI_ACCESS_DENIED
;
1963 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
1966 if (*CharPointer
!= 0) {
1967 Status
= EFI_ACCESS_DENIED
;
1971 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1972 if (PrivateFile
->IsDirectoryPath
) {
1973 FindClose (PrivateFile
->LHandle
);
1975 CloseHandle (PrivateFile
->LHandle
);
1976 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1980 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1981 CloseHandle (PrivateFile
->DirHandle
);
1982 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1985 NtStatus
= MoveFile (OldFileName
, NewFileName
);
1991 FreePool (PrivateFile
->FileName
);
1993 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
1994 if (PrivateFile
->FileName
== NULL
) {
1995 Status
= EFI_OUT_OF_RESOURCES
;
1999 StrCpy (PrivateFile
->FileName
, NewFileName
);
2001 Size
= StrSize (NewFileName
);
2002 Size
+= StrSize (L
"\\*");
2003 TempFileName
= AllocatePool (Size
);
2005 StrCpy (TempFileName
, NewFileName
);
2007 if (!PrivateFile
->IsDirectoryPath
) {
2008 PrivateFile
->LHandle
= CreateFile (
2010 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2011 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2018 FreePool (TempFileName
);
2021 // Flush buffers just in case
2023 if (FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2024 Status
= EFI_DEVICE_ERROR
;
2028 PrivateFile
->DirHandle
= CreateFile (
2030 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2031 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2034 FILE_FLAG_BACKUP_SEMANTICS
,
2038 StrCat (TempFileName
, L
"\\*");
2039 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &FindBuf
);
2041 FreePool (TempFileName
);
2044 Status
= EFI_ACCESS_DENIED
;
2047 NtStatus
= SetFileAttributes (OldFileName
, OldAttr
);
2053 Size
= StrSize (OldFileName
);
2054 Size
+= StrSize (L
"\\*");
2055 TempFileName
= AllocatePool (Size
);
2057 StrCpy (TempFileName
, OldFileName
);
2059 if (!PrivateFile
->IsDirectoryPath
) {
2060 PrivateFile
->LHandle
= CreateFile (
2062 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2063 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2070 PrivateFile
->DirHandle
= CreateFile (
2072 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2073 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2076 FILE_FLAG_BACKUP_SEMANTICS
,
2080 StrCat (TempFileName
, L
"\\*");
2081 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &FindBuf
);
2084 FreePool (TempFileName
);
2094 if (SizeChangeFlag
) {
2095 if (PrivateFile
->IsDirectoryPath
) {
2096 Status
= EFI_UNSUPPORTED
;
2100 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2101 Status
= EFI_ACCESS_DENIED
;
2105 Status
= This
->GetPosition (This
, &CurPos
);
2106 if (EFI_ERROR (Status
)) {
2110 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2111 if (EFI_ERROR (Status
)) {
2115 if (SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2116 Status
= EFI_DEVICE_ERROR
;
2120 Status
= This
->SetPosition (This
, CurPos
);
2121 if (EFI_ERROR (Status
)) {
2129 if (TimeChangeFlag
) {
2131 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2132 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2133 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2134 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2135 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2136 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2137 NewCreationSystemTime
.wMilliseconds
= 0;
2139 if (!SystemTimeToFileTime (
2140 &NewCreationSystemTime
,
2141 &NewCreationFileTime
2146 if (!LocalFileTimeToFileTime (
2147 &NewCreationFileTime
,
2148 &NewCreationFileTime
2153 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2154 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2155 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2156 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2157 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2158 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2159 NewLastAccessSystemTime
.wMilliseconds
= 0;
2161 if (!SystemTimeToFileTime (
2162 &NewLastAccessSystemTime
,
2163 &NewLastAccessFileTime
2168 if (!LocalFileTimeToFileTime (
2169 &NewLastAccessFileTime
,
2170 &NewLastAccessFileTime
2175 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2176 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2177 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2178 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2179 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2180 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2181 NewLastWriteSystemTime
.wMilliseconds
= 0;
2183 if (!SystemTimeToFileTime (
2184 &NewLastWriteSystemTime
,
2185 &NewLastWriteFileTime
2190 if (!LocalFileTimeToFileTime (
2191 &NewLastWriteFileTime
,
2192 &NewLastWriteFileTime
2198 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2199 &NewCreationFileTime
,
2200 &NewLastAccessFileTime
,
2201 &NewLastWriteFileTime
2203 Status
= EFI_DEVICE_ERROR
;
2210 // No matter about AttrChangeFlag, Attribute must be set.
2211 // Because operation before may cause attribute change.
2215 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2216 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2218 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2221 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2222 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2224 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2227 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2228 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2230 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2233 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2234 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2236 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2239 NtStatus
= SetFileAttributes (NewFileName
, NewAttr
);
2242 Status
= EFI_DEVICE_ERROR
;
2247 if (OldFileInfo
!= NULL
) {
2248 FreePool (OldFileInfo
);
2251 if (OldFileName
!= NULL
) {
2252 FreePool (OldFileName
);
2255 if (NewFileName
!= NULL
) {
2256 FreePool (NewFileName
);
2264 Flush data back for the file handle.
2266 @param This Protocol instance pointer.
2268 @retval EFI_SUCCESS Data was written.
2269 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
2270 @retval EFI_NO_MEDIA The device has no media.
2271 @retval EFI_DEVICE_ERROR The device reported an error.
2272 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2273 @retval EFI_WRITE_PROTECTED The device is write protected.
2274 @retval EFI_ACCESS_DENIED The file was open for read only.
2275 @retval EFI_VOLUME_FULL The volume is full.
2280 IN EFI_FILE_PROTOCOL
*This
2283 BY_HANDLE_FILE_INFORMATION FileInfo
;
2284 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2287 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2289 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2290 Status
= EFI_DEVICE_ERROR
;
2294 if (PrivateFile
->IsDirectoryPath
) {
2295 Status
= EFI_SUCCESS
;
2299 if (PrivateFile
->IsOpenedByRead
) {
2300 Status
= EFI_ACCESS_DENIED
;
2304 GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2306 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2307 Status
= EFI_ACCESS_DENIED
;
2311 Status
= FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2316 // bugbug: - Use Windows error reporting.
2324 WinNtFileSystmeThunkOpen (
2325 IN EMU_IO_THUNK_PROTOCOL
*This
2328 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
2330 Private
= AllocateZeroPool (sizeof (*Private
));
2331 if (Private
== NULL
) {
2332 return EFI_OUT_OF_RESOURCES
;
2335 Private
->FilePath
= AllocateCopyPool (StrSize (This
->ConfigString
), This
->ConfigString
);
2336 if (Private
->FilePath
== NULL
) {
2338 return EFI_OUT_OF_RESOURCES
;
2341 Private
->VolumeLabel
= AllocateCopyPool (StrSize (L
"EFI_EMULATED"), L
"EFI_EMULATED");
2342 if (Private
->VolumeLabel
== NULL
) {
2343 FreePool (Private
->FilePath
);
2345 return EFI_OUT_OF_RESOURCES
;
2348 Private
->Signature
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE
;
2349 Private
->Thunk
= This
;
2350 CopyMem (&Private
->SimpleFileSystem
, &gWinNtFileSystemProtocol
, sizeof (Private
->SimpleFileSystem
));
2352 This
->Interface
= &Private
->SimpleFileSystem
;
2353 This
->Private
= Private
;
2359 WinNtFileSystmeThunkClose (
2360 IN EMU_IO_THUNK_PROTOCOL
*This
2363 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
2365 Private
= This
->Private
;
2366 ASSERT (Private
!= NULL
);
2368 if (Private
->VolumeLabel
!= NULL
) {
2369 FreePool (Private
->VolumeLabel
);
2371 if (Private
->FilePath
!= NULL
) {
2372 FreePool (Private
->FilePath
);
2379 EFI_FILE_PROTOCOL gWinNtFileProtocol
= {
2386 WinNtFileGetPossition
,
2387 WinNtFileSetPossition
,
2393 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol
= {
2394 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
,
2399 EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo
= {
2400 &gEfiSimpleFileSystemProtocolGuid
,
2404 WinNtFileSystmeThunkOpen
,
2405 WinNtFileSystmeThunkClose
,