2 Support OS native directory access.
4 Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
13 #define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE SIGNATURE_32 ('N', 'T', 'f', 's')
17 EMU_IO_THUNK_PROTOCOL
*Thunk
;
18 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL SimpleFileSystem
;
21 } WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
;
23 #define WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS(a) \
25 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE, \
27 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE \
31 #define WIN_NT_EFI_FILE_PRIVATE_SIGNATURE SIGNATURE_32 ('l', 'o', 'f', 's')
35 EMU_IO_THUNK_PROTOCOL
*Thunk
;
36 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFileSystem
;
37 EFI_FILE_PROTOCOL EfiFile
;
40 BOOLEAN IsRootDirectory
;
41 BOOLEAN IsDirectoryPath
;
42 BOOLEAN IsOpenedByRead
;
45 BOOLEAN IsValidFindBuf
;
46 WIN32_FIND_DATA FindBuf
;
47 } WIN_NT_EFI_FILE_PRIVATE
;
49 #define WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS(a) \
51 WIN_NT_EFI_FILE_PRIVATE, \
53 WIN_NT_EFI_FILE_PRIVATE_SIGNATURE \
56 extern EFI_FILE_PROTOCOL gWinNtFileProtocol
;
57 extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol
;
61 IN EFI_FILE_PROTOCOL
*This
,
62 IN EFI_GUID
*InformationType
,
63 IN OUT UINTN
*BufferSize
,
69 IN EFI_FILE_PROTOCOL
*This
,
70 IN EFI_GUID
*InformationType
,
86 Locate the first occurance of a character in a string.
90 Str - Pointer to NULL terminated unicode string.
91 Chr - Character to locate.
95 If Str is NULL, then NULL is returned.
96 If Chr is not contained in Str, then NULL is returned.
97 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
105 while (*Str
!= '\0' && *Str
!= Chr
) {
109 return (*Str
== Chr
) ? Str
: NULL
;
120 if (Buffer
== NULL
|| Length
== 0) {
124 if (*(UINT8
*) Buffer
!= 0) {
129 if (!CompareMem (Buffer
, (UINT8
*) Buffer
+ 1, Length
- 1)) {
145 if (StrLen (Str
) < Count
) {
150 for (Pointer
= Str
; *(Pointer
+ Count
); Pointer
++) {
151 *Pointer
= *(Pointer
+ Count
);
154 *Pointer
= *(Pointer
+ Count
);
158 Open the root directory on a volume.
160 @param This Protocol instance pointer.
161 @param Root Returns an Open file handle for the root directory
163 @retval EFI_SUCCESS The device was opened.
164 @retval EFI_UNSUPPORTED This volume does not support the file system.
165 @retval EFI_NO_MEDIA The device has no media.
166 @retval EFI_DEVICE_ERROR The device reported an error.
167 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
168 @retval EFI_ACCESS_DENIED The service denied access to the file.
169 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
174 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
175 OUT EFI_FILE_PROTOCOL
**Root
179 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
180 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
181 CHAR16
*TempFileName
;
184 if (This
== NULL
|| Root
== NULL
) {
185 return EFI_INVALID_PARAMETER
;
188 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
190 PrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
191 if (PrivateFile
== NULL
) {
192 Status
= EFI_OUT_OF_RESOURCES
;
196 PrivateFile
->FileName
= AllocatePool (StrSize (Private
->FilePath
));
197 if (PrivateFile
->FileName
== NULL
) {
198 Status
= EFI_OUT_OF_RESOURCES
;
202 PrivateFile
->FilePath
= AllocatePool (StrSize (Private
->FilePath
));
203 if (PrivateFile
->FilePath
== NULL
) {
204 Status
= EFI_OUT_OF_RESOURCES
;
208 StrCpyS (PrivateFile
->FilePath
,
209 StrSize (Private
->FilePath
) / sizeof (CHAR16
),
212 StrCpyS (PrivateFile
->FileName
,
213 StrSize (Private
->FilePath
) / sizeof (CHAR16
),
214 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 StrCpyS (TempFileName
, Size
/ sizeof (CHAR16
), PrivateFile
->FilePath
);
253 StrCatS (TempFileName
, Size
/ sizeof (CHAR16
), 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 StrnCpyS (Token
, Offset
+ 1, *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 StrCpyS (TempFileName
, StrSize (FileName
) / sizeof (CHAR16
), 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
) {
558 NewPrivateFile
->FilePath
,
559 StrSize (PrivateFile
->FileName
) / sizeof (CHAR16
),
560 PrivateFile
->FileName
564 NewPrivateFile
->FilePath
,
565 StrSize (PrivateFile
->FileName
) / sizeof (CHAR16
),
566 PrivateFile
->FilePath
570 Size
= StrSize (NewPrivateFile
->FilePath
);
571 Size
+= StrSize (L
"\\");
572 Size
+= StrSize (FileName
);
573 NewPrivateFile
->FileName
= AllocatePool (Size
);
574 if (NewPrivateFile
->FileName
== NULL
) {
575 Status
= EFI_OUT_OF_RESOURCES
;
579 if (*FileName
== L
'\\') {
580 StrCpyS (NewPrivateFile
->FileName
, Size
/ sizeof (CHAR16
), PrivateRoot
->FilePath
);
581 StrCatS (NewPrivateFile
->FileName
, Size
/ sizeof (CHAR16
), L
"\\");
582 StrCatS (NewPrivateFile
->FileName
, Size
/ sizeof (CHAR16
), FileName
+ 1);
584 StrCpyS (NewPrivateFile
->FileName
, Size
/ sizeof (CHAR16
), NewPrivateFile
->FilePath
);
585 if (StrCmp (FileName
, L
"") != 0) {
587 // In case the filename becomes empty, especially after trimming dots and blanks
589 StrCatS (NewPrivateFile
->FileName
, Size
/ sizeof (CHAR16
), L
"\\");
590 StrCatS (NewPrivateFile
->FileName
, Size
/ sizeof (CHAR16
), FileName
);
594 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
595 Status
= EFI_NOT_FOUND
;
600 // Get rid of . and .., except leading . or ..
604 // GuardPointer protect simplefilesystem root path not be destroyed
606 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
610 while (!LoopFinish
) {
614 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
615 if (*ParseFileName
== L
'.' &&
616 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
617 *(ParseFileName
- 1) == L
'\\'
623 CutPrefix (ParseFileName
- 1, 2);
628 if (*ParseFileName
== L
'.' &&
629 *(ParseFileName
+ 1) == L
'.' &&
630 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
631 *(ParseFileName
- 1) == L
'\\'
637 while (ParseFileName
!= GuardPointer
) {
640 if (*ParseFileName
== L
'\\') {
646 // cut \.. and its left directory
648 CutPrefix (ParseFileName
, Count
);
655 RealFileName
= NewPrivateFile
->FileName
;
656 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
657 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
661 if (RealFileName
!= NewPrivateFile
->FileName
) {
662 TempChar
= *(RealFileName
- 1);
663 *(RealFileName
- 1) = 0;
666 FreePool (NewPrivateFile
->FilePath
);
667 NewPrivateFile
->FilePath
= NULL
;
668 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
669 if (NewPrivateFile
->FilePath
== NULL
) {
670 Status
= EFI_OUT_OF_RESOURCES
;
675 NewPrivateFile
->FilePath
,
676 StrSize (NewPrivateFile
->FileName
) / sizeof (CHAR16
),
677 NewPrivateFile
->FileName
680 *(RealFileName
- 1) = TempChar
;
683 NewPrivateFile
->IsRootDirectory
= FALSE
;
686 // Test whether file or directory
688 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
689 if (Attributes
& EFI_FILE_DIRECTORY
) {
690 NewPrivateFile
->IsDirectoryPath
= TRUE
;
692 NewPrivateFile
->IsDirectoryPath
= FALSE
;
695 NewPrivateFile
->LHandle
= CreateFile (
696 NewPrivateFile
->FileName
,
698 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
705 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
706 NewPrivateFile
->IsDirectoryPath
= FALSE
;
707 CloseHandle (NewPrivateFile
->LHandle
);
709 NewPrivateFile
->IsDirectoryPath
= TRUE
;
712 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
715 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
716 NewPrivateFile
->IsOpenedByRead
= FALSE
;
718 NewPrivateFile
->IsOpenedByRead
= TRUE
;
721 Status
= EFI_SUCCESS
;
724 // deal with directory
726 if (NewPrivateFile
->IsDirectoryPath
) {
728 Size
= StrSize (NewPrivateFile
->FileName
);
729 Size
+= StrSize (L
"\\*");
730 TempFileName
= AllocatePool (Size
);
731 if (TempFileName
== NULL
) {
732 Status
= EFI_OUT_OF_RESOURCES
;
736 StrCpyS (TempFileName
, Size
/ sizeof (CHAR16
), NewPrivateFile
->FileName
);
738 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
740 // Create a directory
742 if (!CreateDirectory (TempFileName
, NULL
)) {
744 LastError
= GetLastError ();
745 if (LastError
!= ERROR_ALREADY_EXISTS
) {
746 FreePool (TempFileName
);
747 Status
= EFI_ACCESS_DENIED
;
753 NewPrivateFile
->DirHandle
= CreateFile (
755 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
756 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
759 FILE_FLAG_BACKUP_SEMANTICS
,
763 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
765 NewPrivateFile
->DirHandle
= CreateFile (
768 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
771 FILE_FLAG_BACKUP_SEMANTICS
,
775 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
776 CloseHandle (NewPrivateFile
->DirHandle
);
777 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
778 Status
= EFI_ACCESS_DENIED
;
780 Status
= EFI_NOT_FOUND
;
783 FreePool (TempFileName
);
788 // Find the first file under it
790 StrCatS (TempFileName
, Size
/ sizeof (CHAR16
), L
"\\*");
791 NewPrivateFile
->LHandle
= FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
792 FreePool (TempFileName
);
794 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
795 NewPrivateFile
->IsValidFindBuf
= FALSE
;
797 NewPrivateFile
->IsValidFindBuf
= TRUE
;
803 if (!NewPrivateFile
->IsOpenedByRead
) {
804 NewPrivateFile
->LHandle
= CreateFile (
805 NewPrivateFile
->FileName
,
806 GENERIC_READ
| GENERIC_WRITE
,
807 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
809 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
814 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
815 NewPrivateFile
->LHandle
= CreateFile (
816 NewPrivateFile
->FileName
,
818 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
825 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
826 Status
= EFI_NOT_FOUND
;
828 Status
= EFI_ACCESS_DENIED
;
829 CloseHandle (NewPrivateFile
->LHandle
);
830 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
834 NewPrivateFile
->LHandle
= CreateFile (
835 NewPrivateFile
->FileName
,
837 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
844 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
845 Status
= EFI_NOT_FOUND
;
850 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
857 Status
= WinNtFileGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
859 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
860 Status
= EFI_DEVICE_ERROR
;
864 Info
= AllocatePool (InfoSize
);
866 Status
= EFI_OUT_OF_RESOURCES
;
870 Status
= WinNtFileGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
872 if (EFI_ERROR (Status
)) {
877 Info
->Attribute
= Attributes
;
879 WinNtFileSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
886 if (EFI_ERROR (Status
)) {
887 if (NewPrivateFile
) {
888 if (NewPrivateFile
->FileName
) {
889 FreePool (NewPrivateFile
->FileName
);
892 if (NewPrivateFile
->FilePath
) {
893 FreePool (NewPrivateFile
->FilePath
);
896 FreePool (NewPrivateFile
);
899 *NewHandle
= &NewPrivateFile
->EfiFile
;
900 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
901 NewPrivateFile
->IsRootDirectory
= TRUE
;
911 Close the file handle
913 @param This Protocol instance pointer.
915 @retval EFI_SUCCESS The device was opened.
920 IN EFI_FILE_PROTOCOL
*This
923 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
925 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
927 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
928 if (PrivateFile
->IsDirectoryPath
) {
929 FindClose (PrivateFile
->LHandle
);
931 CloseHandle (PrivateFile
->LHandle
);
934 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
937 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
938 CloseHandle (PrivateFile
->DirHandle
);
939 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
942 if (PrivateFile
->FileName
) {
943 FreePool (PrivateFile
->FileName
);
946 if (PrivateFile
->FilePath
) {
947 FreePool (PrivateFile
->FilePath
);
950 FreePool (PrivateFile
);
958 Close and delete the file handle.
960 @param This Protocol instance pointer.
962 @retval EFI_SUCCESS The device was opened.
963 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
968 IN EFI_FILE_PROTOCOL
*This
972 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
974 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
976 Status
= EFI_WARN_DELETE_FAILURE
;
978 if (PrivateFile
->IsDirectoryPath
) {
979 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
980 FindClose (PrivateFile
->LHandle
);
983 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
984 CloseHandle (PrivateFile
->DirHandle
);
985 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
988 if (RemoveDirectory (PrivateFile
->FileName
)) {
989 Status
= EFI_SUCCESS
;
992 CloseHandle (PrivateFile
->LHandle
);
993 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
995 if (!PrivateFile
->IsOpenedByRead
) {
996 if (DeleteFile (PrivateFile
->FileName
)) {
997 Status
= EFI_SUCCESS
;
1002 FreePool (PrivateFile
->FileName
);
1003 FreePool (PrivateFile
->FilePath
);
1004 FreePool (PrivateFile
);
1010 WinNtSystemTimeToEfiTime (
1011 IN SYSTEMTIME
*SystemTime
,
1012 IN TIME_ZONE_INFORMATION
*TimeZone
,
1017 Routine Description:
1019 TODO: Add function description
1023 SystemTime - TODO: add argument description
1024 TimeZone - TODO: add argument description
1025 Time - TODO: add argument description
1029 TODO: add return values
1033 Time
->Year
= (UINT16
)SystemTime
->wYear
;
1034 Time
->Month
= (UINT8
)SystemTime
->wMonth
;
1035 Time
->Day
= (UINT8
)SystemTime
->wDay
;
1036 Time
->Hour
= (UINT8
)SystemTime
->wHour
;
1037 Time
->Minute
= (UINT8
)SystemTime
->wMinute
;
1038 Time
->Second
= (UINT8
)SystemTime
->wSecond
;
1039 Time
->Nanosecond
= (UINT32
)SystemTime
->wMilliseconds
* 1000000;
1040 Time
->TimeZone
= (INT16
)TimeZone
->Bias
;
1042 if (TimeZone
->StandardDate
.wMonth
) {
1043 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1048 Convert the FileTime to EfiTime.
1050 @param PrivateFile Pointer to WIN_NT_EFI_FILE_PRIVATE.
1051 @param TimeZone Pointer to the current time zone.
1052 @param FileTime Pointer to file time.
1053 @param EfiTime Pointer to EFI time.
1056 WinNtFileTimeToEfiTime (
1057 IN CONST WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1058 IN TIME_ZONE_INFORMATION
*TimeZone
,
1059 IN CONST FILETIME
*FileTime
,
1060 OUT EFI_TIME
*EfiTime
1063 FILETIME TempFileTime
;
1064 SYSTEMTIME SystemTime
;
1066 FileTimeToLocalFileTime (FileTime
, &TempFileTime
);
1067 FileTimeToSystemTime (&TempFileTime
, &SystemTime
);
1068 WinNtSystemTimeToEfiTime (&SystemTime
, TimeZone
, EfiTime
);
1073 Read data from the file.
1075 @param This Protocol instance pointer.
1076 @param BufferSize On input size of buffer, on output amount of data in buffer.
1077 @param Buffer The buffer in which data is read.
1079 @retval EFI_SUCCESS Data was read.
1080 @retval EFI_NO_MEDIA The device has no media.
1081 @retval EFI_DEVICE_ERROR The device reported an error.
1082 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1083 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1088 IN EFI_FILE_PROTOCOL
*This
,
1089 IN OUT UINTN
*BufferSize
,
1093 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1099 EFI_FILE_INFO
*Info
;
1101 TIME_ZONE_INFORMATION TimeZone
;
1102 EFI_FILE_INFO
*FileInfo
;
1107 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1109 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1110 Status
= EFI_DEVICE_ERROR
;
1114 if (!PrivateFile
->IsDirectoryPath
) {
1116 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1117 Status
= EFI_DEVICE_ERROR
;
1121 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1122 FileInfo
= AllocatePool (FileInfoSize
);
1124 Status
= This
->GetInfo (
1131 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1132 FreePool (FileInfo
);
1133 FileInfo
= AllocatePool (FileInfoSize
);
1134 Status
= This
->GetInfo (
1142 if (EFI_ERROR (Status
)) {
1143 Status
= EFI_DEVICE_ERROR
;
1147 FileSize
= FileInfo
->FileSize
;
1149 FreePool (FileInfo
);
1151 if (Pos
>= FileSize
) {
1153 if (Pos
== FileSize
) {
1154 Status
= EFI_SUCCESS
;
1157 Status
= EFI_DEVICE_ERROR
;
1163 PrivateFile
->LHandle
,
1166 (LPDWORD
)BufferSize
,
1168 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1173 // Read on a directory. Perform a find next
1175 if (!PrivateFile
->IsValidFindBuf
) {
1177 Status
= EFI_SUCCESS
;
1181 Size
= SIZE_OF_EFI_FILE_INFO
;
1183 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1185 ResultSize
= Size
+ NameSize
;
1187 Status
= EFI_BUFFER_TOO_SMALL
;
1189 if (*BufferSize
>= ResultSize
) {
1190 Status
= EFI_SUCCESS
;
1193 ZeroMem (Info
, ResultSize
);
1195 Info
->Size
= ResultSize
;
1197 GetTimeZoneInformation (&TimeZone
);
1198 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftCreationTime
, &Info
->CreateTime
);
1199 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastAccessTime
, &Info
->LastAccessTime
);
1200 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastWriteTime
, &Info
->ModificationTime
);
1202 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1204 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1206 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1207 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1210 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1211 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1214 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1215 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1218 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1219 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1222 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1223 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1226 NameSize
= NameSize
/ sizeof (WCHAR
);
1228 pw
= (WCHAR
*)(((CHAR8
*)Buffer
) + Size
);
1230 for (Index
= 0; Index
< NameSize
; Index
++) {
1231 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1234 if (FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1235 PrivateFile
->IsValidFindBuf
= TRUE
;
1237 PrivateFile
->IsValidFindBuf
= FALSE
;
1241 *BufferSize
= ResultSize
;
1250 Write data to a file.
1252 @param This Protocol instance pointer.
1253 @param BufferSize On input size of buffer, on output amount of data in buffer.
1254 @param Buffer The buffer in which data to write.
1256 @retval EFI_SUCCESS Data was written.
1257 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
1258 @retval EFI_NO_MEDIA The device has no media.
1259 @retval EFI_DEVICE_ERROR The device reported an error.
1260 @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
1261 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1262 @retval EFI_WRITE_PROTECTED The device is write protected.
1263 @retval EFI_ACCESS_DENIED The file was open for read only.
1264 @retval EFI_VOLUME_FULL The volume is full.
1269 IN EFI_FILE_PROTOCOL
*This
,
1270 IN OUT UINTN
*BufferSize
,
1274 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1277 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1279 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1280 Status
= EFI_DEVICE_ERROR
;
1284 if (PrivateFile
->IsDirectoryPath
) {
1285 Status
= EFI_UNSUPPORTED
;
1289 if (PrivateFile
->IsOpenedByRead
) {
1290 Status
= EFI_ACCESS_DENIED
;
1294 Status
= WriteFile (
1295 PrivateFile
->LHandle
,
1298 (LPDWORD
)BufferSize
,
1300 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1306 // bugbug: need to access windows error reporting
1313 Set a files current position
1315 @param This Protocol instance pointer.
1316 @param Position Byte position from the start of the file.
1318 @retval EFI_SUCCESS Data was written.
1319 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1323 WinNtFileSetPossition (
1324 IN EFI_FILE_PROTOCOL
*This
,
1329 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1335 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1337 if (PrivateFile
->IsDirectoryPath
) {
1338 if (Position
!= 0) {
1339 Status
= EFI_UNSUPPORTED
;
1343 Size
= StrSize (PrivateFile
->FileName
);
1344 Size
+= StrSize (L
"\\*");
1345 FileName
= AllocatePool (Size
);
1346 if (FileName
== NULL
) {
1347 Status
= EFI_OUT_OF_RESOURCES
;
1351 StrCpyS (FileName
, Size
/ sizeof (CHAR16
), PrivateFile
->FileName
);
1352 StrCatS (FileName
, Size
/ sizeof (CHAR16
), L
"\\*");
1354 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1355 FindClose (PrivateFile
->LHandle
);
1358 PrivateFile
->LHandle
= FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1360 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1361 PrivateFile
->IsValidFindBuf
= FALSE
;
1363 PrivateFile
->IsValidFindBuf
= TRUE
;
1366 FreePool (FileName
);
1368 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1370 if (Position
== (UINT64
)-1) {
1371 PosLow
= SetFilePointer (PrivateFile
->LHandle
, (ULONG
)0, NULL
, FILE_END
);
1373 PosHigh
= (UINT32
)RShiftU64 (Position
, 32);
1375 PosLow
= SetFilePointer (PrivateFile
->LHandle
, (ULONG
)Position
, (PLONG
)&PosHigh
, FILE_BEGIN
);
1378 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1388 Get a file's current position
1390 @param This Protocol instance pointer.
1391 @param Position Byte position from the start of the file.
1393 @retval EFI_SUCCESS Data was written.
1394 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1398 WinNtFileGetPossition (
1399 IN EFI_FILE_PROTOCOL
*This
,
1400 OUT UINT64
*Position
1404 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1408 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1413 if (PrivateFile
->IsDirectoryPath
) {
1415 Status
= EFI_UNSUPPORTED
;
1421 *Position
= SetFilePointer (
1422 PrivateFile
->LHandle
,
1424 (PLONG
)&PositionHigh
,
1428 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1429 if (EFI_ERROR (Status
)) {
1433 PosHigh64
= PositionHigh
;
1434 *Position
+= LShiftU64 (PosHigh64
, 32);
1443 WinNtSimpleFileSystemFileInfo (
1444 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1445 IN OUT UINTN
*BufferSize
,
1450 Routine Description:
1452 TODO: Add function description
1456 PrivateFile - TODO: add argument description
1457 BufferSize - TODO: add argument description
1458 Buffer - TODO: add argument description
1462 TODO: add return values
1470 EFI_FILE_INFO
*Info
;
1471 BY_HANDLE_FILE_INFORMATION FileInfo
;
1472 CHAR16
*RealFileName
;
1473 CHAR16
*TempPointer
;
1474 TIME_ZONE_INFORMATION TimeZone
;
1476 Size
= SIZE_OF_EFI_FILE_INFO
;
1478 RealFileName
= PrivateFile
->FileName
;
1479 TempPointer
= RealFileName
;
1480 while (*TempPointer
) {
1481 if (*TempPointer
== '\\') {
1482 RealFileName
= TempPointer
+ 1;
1487 NameSize
= StrSize (RealFileName
);
1489 ResultSize
= Size
+ NameSize
;
1491 Status
= EFI_BUFFER_TOO_SMALL
;
1492 if (*BufferSize
>= ResultSize
) {
1493 Status
= EFI_SUCCESS
;
1496 ZeroMem (Info
, ResultSize
);
1498 Info
->Size
= ResultSize
;
1499 GetFileInformationByHandle (
1500 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
1503 Info
->FileSize
= FileInfo
.nFileSizeLow
;
1504 Info
->PhysicalSize
= Info
->FileSize
;
1506 GetTimeZoneInformation (&TimeZone
);
1507 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftCreationTime
, &Info
->CreateTime
);
1508 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastAccessTime
, &Info
->LastAccessTime
);
1509 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastWriteTime
, &Info
->ModificationTime
);
1511 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1512 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1515 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1516 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1519 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1520 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1523 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1524 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1527 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1528 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1531 if (PrivateFile
->IsDirectoryPath
) {
1532 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1535 if (PrivateFile
->IsRootDirectory
) {
1536 *((CHAR8
*)Buffer
+ Size
) = 0;
1538 CopyMem ((CHAR8
*)Buffer
+ Size
, RealFileName
, NameSize
);
1542 *BufferSize
= ResultSize
;
1547 Get information about a file.
1549 @param This Protocol instance pointer.
1550 @param InformationType Type of information to return in Buffer.
1551 @param BufferSize On input size of buffer, on output amount of data in buffer.
1552 @param Buffer The buffer to return data.
1554 @retval EFI_SUCCESS Data was returned.
1555 @retval EFI_UNSUPPORTED InformationType is not supported.
1556 @retval EFI_NO_MEDIA The device has no media.
1557 @retval EFI_DEVICE_ERROR The device reported an error.
1558 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1559 @retval EFI_WRITE_PROTECTED The device is write protected.
1560 @retval EFI_ACCESS_DENIED The file was open for read only.
1561 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1566 IN EFI_FILE_PROTOCOL
*This
,
1567 IN EFI_GUID
*InformationType
,
1568 IN OUT UINTN
*BufferSize
,
1573 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1574 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
1575 UINT32 SectorsPerCluster
;
1576 UINT32 BytesPerSector
;
1577 UINT32 FreeClusters
;
1578 UINT32 TotalClusters
;
1579 UINT32 BytesPerCluster
;
1581 BOOLEAN DriveNameFound
;
1584 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1586 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
1587 return EFI_INVALID_PARAMETER
;
1590 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1591 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1593 Status
= EFI_UNSUPPORTED
;
1595 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1596 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
1599 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1600 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1601 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1602 Status
= EFI_BUFFER_TOO_SMALL
;
1606 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*)Buffer
;
1607 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1608 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
1611 // Try to get the drive name
1613 DriveNameFound
= FALSE
;
1614 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
1615 if (DriveName
== NULL
) {
1616 Status
= EFI_OUT_OF_RESOURCES
;
1622 (StrSize (PrivateFile
->FilePath
) + 1) / sizeof (CHAR16
),
1623 PrivateFile
->FilePath
1625 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
1629 if (DriveName
[Index
] == ':') {
1630 DriveName
[Index
+ 1] = '\\';
1631 DriveName
[Index
+ 2] = 0;
1632 DriveNameFound
= TRUE
;
1633 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
1634 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
1638 if (DriveName
[Index
] == '\\') {
1639 DriveNameFound
= TRUE
;
1640 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
1644 DriveName
[Index
] = '\\';
1645 DriveName
[Index
+ 1] = 0;
1650 // Try GetDiskFreeSpace first
1652 NtStatus
= GetDiskFreeSpace (
1653 DriveNameFound
? DriveName
: NULL
,
1654 (LPDWORD
)&SectorsPerCluster
,
1655 (LPDWORD
)&BytesPerSector
,
1656 (LPDWORD
)&FreeClusters
,
1657 (LPDWORD
)&TotalClusters
1660 FreePool (DriveName
);
1667 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
1668 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
1669 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
1670 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
1674 // try GetDiskFreeSpaceEx then
1676 FileSystemInfoBuffer
->BlockSize
= 0;
1677 NtStatus
= GetDiskFreeSpaceEx (
1678 PrivateFile
->FilePath
,
1679 (PULARGE_INTEGER
)(&FileSystemInfoBuffer
->FreeSpace
),
1680 (PULARGE_INTEGER
)(&FileSystemInfoBuffer
->VolumeSize
),
1684 Status
= EFI_DEVICE_ERROR
;
1690 (CHAR16
*)FileSystemInfoBuffer
->VolumeLabel
,
1691 (*BufferSize
- SIZE_OF_EFI_FILE_SYSTEM_INFO
) / sizeof (CHAR16
),
1692 PrivateRoot
->VolumeLabel
1694 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1695 Status
= EFI_SUCCESS
;
1698 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1699 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1700 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1701 Status
= EFI_BUFFER_TOO_SMALL
;
1707 *BufferSize
/ sizeof (CHAR16
),
1708 PrivateRoot
->VolumeLabel
1710 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1711 Status
= EFI_SUCCESS
;
1720 Set information about a file
1722 @param File Protocol instance pointer.
1723 @param InformationType Type of information in Buffer.
1724 @param BufferSize Size of buffer.
1725 @param Buffer The data to write.
1727 @retval EFI_SUCCESS Data was returned.
1728 @retval EFI_UNSUPPORTED InformationType is not supported.
1729 @retval EFI_NO_MEDIA The device has no media.
1730 @retval EFI_DEVICE_ERROR The device reported an error.
1731 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1732 @retval EFI_WRITE_PROTECTED The device is write protected.
1733 @retval EFI_ACCESS_DENIED The file was open for read only.
1738 IN EFI_FILE_PROTOCOL
*This
,
1739 IN EFI_GUID
*InformationType
,
1740 IN UINTN BufferSize
,
1744 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1745 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1746 EFI_FILE_INFO
*OldFileInfo
;
1747 EFI_FILE_INFO
*NewFileInfo
;
1753 CHAR16
*OldFileName
;
1754 CHAR16
*NewFileName
;
1755 CHAR16
*TempFileName
;
1756 CHAR16
*CharPointer
;
1757 BOOLEAN AttrChangeFlag
;
1758 BOOLEAN NameChangeFlag
;
1759 BOOLEAN SizeChangeFlag
;
1760 BOOLEAN TimeChangeFlag
;
1762 SYSTEMTIME NewCreationSystemTime
;
1763 SYSTEMTIME NewLastAccessSystemTime
;
1764 SYSTEMTIME NewLastWriteSystemTime
;
1765 FILETIME NewCreationFileTime
;
1766 FILETIME NewLastAccessFileTime
;
1767 FILETIME NewLastWriteFileTime
;
1768 WIN32_FIND_DATA FindBuf
;
1769 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
1773 // Initialise locals.
1775 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1776 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1778 Status
= EFI_UNSUPPORTED
;
1779 OldFileInfo
= NewFileInfo
= NULL
;
1780 OldFileName
= NewFileName
= NULL
;
1781 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
1784 // Set file system information.
1786 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1787 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*)Buffer
;
1788 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (NewFileSystemInfo
->VolumeLabel
)) {
1789 Status
= EFI_BAD_BUFFER_SIZE
;
1794 FreePool (PrivateRoot
->VolumeLabel
);
1795 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
1796 if (PrivateRoot
->VolumeLabel
== NULL
) {
1797 Status
= EFI_OUT_OF_RESOURCES
;
1802 PrivateRoot
->VolumeLabel
,
1803 StrSize (NewFileSystemInfo
->VolumeLabel
) / sizeof (CHAR16
),
1804 NewFileSystemInfo
->VolumeLabel
1807 Status
= EFI_SUCCESS
;
1812 // Set volume label information.
1814 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1815 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1816 Status
= EFI_BAD_BUFFER_SIZE
;
1821 PrivateRoot
->VolumeLabel
,
1822 StrSize (PrivateRoot
->VolumeLabel
) / sizeof (CHAR16
),
1826 Status
= EFI_SUCCESS
;
1830 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1831 Status
= EFI_UNSUPPORTED
;
1835 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
1836 Status
= EFI_BAD_BUFFER_SIZE
;
1841 // Set file/directory information.
1845 // Check for invalid set file information parameters.
1847 NewFileInfo
= (EFI_FILE_INFO
*)Buffer
;
1849 if ((NewFileInfo
->Size
<= SIZE_OF_EFI_FILE_INFO
) ||
1850 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
1851 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
1853 Status
= EFI_INVALID_PARAMETER
;
1858 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
1859 // that would have an additional parameter that would be the size
1860 // of the string array just in case there are no NULL characters in
1861 // the string array.
1864 // Get current file information so we can determine what kind
1865 // of change request this is.
1868 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
1870 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1871 Status
= EFI_DEVICE_ERROR
;
1875 OldFileInfo
= AllocatePool (OldInfoSize
);
1876 if (OldFileInfo
== NULL
) {
1877 Status
= EFI_OUT_OF_RESOURCES
;
1881 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
1883 if (EFI_ERROR (Status
)) {
1887 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
1888 if (OldFileName
== NULL
) {
1889 Status
= EFI_OUT_OF_RESOURCES
;
1895 StrSize (PrivateFile
->FileName
) / sizeof (CHAR16
),
1896 PrivateFile
->FileName
1900 // Make full pathname from new filename and rootpath.
1902 if (NewFileInfo
->FileName
[0] == '\\') {
1903 Size
= StrSize (PrivateRoot
->FilePath
);
1904 Size
+= StrSize (L
"\\");
1905 Size
+= StrSize (NewFileInfo
->FileName
);
1906 NewFileName
= AllocatePool (Size
);
1907 if (NewFileName
== NULL
) {
1908 Status
= EFI_OUT_OF_RESOURCES
;
1912 StrCpyS (NewFileName
, Size
/ sizeof (CHAR16
), PrivateRoot
->FilePath
);
1913 StrCatS (NewFileName
, Size
/ sizeof (CHAR16
), L
"\\");
1914 StrCatS (NewFileName
, Size
/ sizeof (CHAR16
), NewFileInfo
->FileName
+ 1);
1916 Size
= StrSize (PrivateFile
->FilePath
);
1917 Size
+= StrSize (L
"\\");
1918 Size
+= StrSize (NewFileInfo
->FileName
);
1919 NewFileName
= AllocatePool (Size
);
1920 if (NewFileName
== NULL
) {
1921 Status
= EFI_OUT_OF_RESOURCES
;
1925 StrCpyS (NewFileName
, Size
/ sizeof (CHAR16
), PrivateFile
->FilePath
);
1926 StrCatS (NewFileName
, Size
/ sizeof (CHAR16
), L
"\\");
1927 StrCatS (NewFileName
, Size
/ sizeof (CHAR16
), NewFileInfo
->FileName
);
1931 // Is there an attribute change request?
1933 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
1934 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
1935 Status
= EFI_INVALID_PARAMETER
;
1939 AttrChangeFlag
= TRUE
;
1943 // Is there a name change request?
1944 // bugbug: - Need EfiStrCaseCmp()
1946 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
1947 NameChangeFlag
= TRUE
;
1951 // Is there a size change request?
1953 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
1954 SizeChangeFlag
= TRUE
;
1958 // Is there a time stamp change request?
1960 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
1961 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
1963 TimeChangeFlag
= TRUE
;
1964 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
1965 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
1967 TimeChangeFlag
= TRUE
;
1968 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
1969 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
1971 TimeChangeFlag
= TRUE
;
1975 // All done if there are no change requests being made.
1977 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
1978 Status
= EFI_SUCCESS
;
1983 // Set file or directory information.
1985 OldAttr
= GetFileAttributes (OldFileName
);
1990 if (NameChangeFlag
) {
1992 // Close the handles first
1994 if (PrivateFile
->IsOpenedByRead
) {
1995 Status
= EFI_ACCESS_DENIED
;
1999 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
2002 if (*CharPointer
!= 0) {
2003 Status
= EFI_ACCESS_DENIED
;
2007 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
2008 if (PrivateFile
->IsDirectoryPath
) {
2009 FindClose (PrivateFile
->LHandle
);
2011 CloseHandle (PrivateFile
->LHandle
);
2012 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
2016 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
2017 CloseHandle (PrivateFile
->DirHandle
);
2018 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
2021 NtStatus
= MoveFile (OldFileName
, NewFileName
);
2027 FreePool (PrivateFile
->FileName
);
2029 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
2030 if (PrivateFile
->FileName
== NULL
) {
2031 Status
= EFI_OUT_OF_RESOURCES
;
2035 StrCpyS (PrivateFile
->FileName
, StrSize (NewFileName
) / sizeof (CHAR16
), NewFileName
);
2037 Size
= StrSize (NewFileName
);
2038 Size
+= StrSize (L
"\\*");
2039 TempFileName
= AllocatePool (Size
);
2041 StrCpyS (TempFileName
, Size
/ sizeof (CHAR16
), NewFileName
);
2043 if (!PrivateFile
->IsDirectoryPath
) {
2044 PrivateFile
->LHandle
= CreateFile (
2046 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2047 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2054 FreePool (TempFileName
);
2057 // Flush buffers just in case
2059 if (FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2060 Status
= EFI_DEVICE_ERROR
;
2064 PrivateFile
->DirHandle
= CreateFile (
2066 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2067 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2070 FILE_FLAG_BACKUP_SEMANTICS
,
2074 StrCatS (TempFileName
, Size
/ sizeof (CHAR16
), L
"\\*");
2075 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &FindBuf
);
2077 FreePool (TempFileName
);
2080 Status
= EFI_ACCESS_DENIED
;
2083 NtStatus
= SetFileAttributes (OldFileName
, OldAttr
);
2089 Size
= StrSize (OldFileName
);
2090 Size
+= StrSize (L
"\\*");
2091 TempFileName
= AllocatePool (Size
);
2093 StrCpyS (TempFileName
, Size
/ sizeof (CHAR16
), OldFileName
);
2095 if (!PrivateFile
->IsDirectoryPath
) {
2096 PrivateFile
->LHandle
= CreateFile (
2098 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2099 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2106 PrivateFile
->DirHandle
= CreateFile (
2108 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2109 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2112 FILE_FLAG_BACKUP_SEMANTICS
,
2116 StrCatS (TempFileName
, Size
/ sizeof (CHAR16
), L
"\\*");
2117 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &FindBuf
);
2120 FreePool (TempFileName
);
2130 if (SizeChangeFlag
) {
2131 if (PrivateFile
->IsDirectoryPath
) {
2132 Status
= EFI_UNSUPPORTED
;
2136 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2137 Status
= EFI_ACCESS_DENIED
;
2141 Status
= This
->GetPosition (This
, &CurPos
);
2142 if (EFI_ERROR (Status
)) {
2146 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2147 if (EFI_ERROR (Status
)) {
2151 if (SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2152 Status
= EFI_DEVICE_ERROR
;
2156 Status
= This
->SetPosition (This
, CurPos
);
2157 if (EFI_ERROR (Status
)) {
2165 if (TimeChangeFlag
) {
2167 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2168 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2169 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2170 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2171 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2172 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2173 NewCreationSystemTime
.wMilliseconds
= 0;
2175 if (!SystemTimeToFileTime (
2176 &NewCreationSystemTime
,
2177 &NewCreationFileTime
2182 if (!LocalFileTimeToFileTime (
2183 &NewCreationFileTime
,
2184 &NewCreationFileTime
2189 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2190 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2191 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2192 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2193 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2194 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2195 NewLastAccessSystemTime
.wMilliseconds
= 0;
2197 if (!SystemTimeToFileTime (
2198 &NewLastAccessSystemTime
,
2199 &NewLastAccessFileTime
2204 if (!LocalFileTimeToFileTime (
2205 &NewLastAccessFileTime
,
2206 &NewLastAccessFileTime
2211 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2212 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2213 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2214 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2215 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2216 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2217 NewLastWriteSystemTime
.wMilliseconds
= 0;
2219 if (!SystemTimeToFileTime (
2220 &NewLastWriteSystemTime
,
2221 &NewLastWriteFileTime
2226 if (!LocalFileTimeToFileTime (
2227 &NewLastWriteFileTime
,
2228 &NewLastWriteFileTime
2234 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2235 &NewCreationFileTime
,
2236 &NewLastAccessFileTime
,
2237 &NewLastWriteFileTime
2239 Status
= EFI_DEVICE_ERROR
;
2246 // No matter about AttrChangeFlag, Attribute must be set.
2247 // Because operation before may cause attribute change.
2251 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2252 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2254 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2257 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2258 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2260 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2263 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2264 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2266 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2269 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2270 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2272 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2275 NtStatus
= SetFileAttributes (NewFileName
, NewAttr
);
2278 Status
= EFI_DEVICE_ERROR
;
2283 if (OldFileInfo
!= NULL
) {
2284 FreePool (OldFileInfo
);
2287 if (OldFileName
!= NULL
) {
2288 FreePool (OldFileName
);
2291 if (NewFileName
!= NULL
) {
2292 FreePool (NewFileName
);
2300 Flush data back for the file handle.
2302 @param This Protocol instance pointer.
2304 @retval EFI_SUCCESS Data was written.
2305 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
2306 @retval EFI_NO_MEDIA The device has no media.
2307 @retval EFI_DEVICE_ERROR The device reported an error.
2308 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2309 @retval EFI_WRITE_PROTECTED The device is write protected.
2310 @retval EFI_ACCESS_DENIED The file was open for read only.
2311 @retval EFI_VOLUME_FULL The volume is full.
2316 IN EFI_FILE_PROTOCOL
*This
2319 BY_HANDLE_FILE_INFORMATION FileInfo
;
2320 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2323 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2325 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2326 Status
= EFI_DEVICE_ERROR
;
2330 if (PrivateFile
->IsDirectoryPath
) {
2331 Status
= EFI_SUCCESS
;
2335 if (PrivateFile
->IsOpenedByRead
) {
2336 Status
= EFI_ACCESS_DENIED
;
2340 GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2342 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2343 Status
= EFI_ACCESS_DENIED
;
2347 Status
= FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2352 // bugbug: - Use Windows error reporting.
2360 WinNtFileSystmeThunkOpen (
2361 IN EMU_IO_THUNK_PROTOCOL
*This
2364 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
2366 Private
= AllocateZeroPool (sizeof (*Private
));
2367 if (Private
== NULL
) {
2368 return EFI_OUT_OF_RESOURCES
;
2371 Private
->FilePath
= AllocateCopyPool (StrSize (This
->ConfigString
), This
->ConfigString
);
2372 if (Private
->FilePath
== NULL
) {
2374 return EFI_OUT_OF_RESOURCES
;
2377 Private
->VolumeLabel
= AllocateCopyPool (StrSize (L
"EFI_EMULATED"), L
"EFI_EMULATED");
2378 if (Private
->VolumeLabel
== NULL
) {
2379 FreePool (Private
->FilePath
);
2381 return EFI_OUT_OF_RESOURCES
;
2384 Private
->Signature
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE
;
2385 Private
->Thunk
= This
;
2386 CopyMem (&Private
->SimpleFileSystem
, &gWinNtFileSystemProtocol
, sizeof (Private
->SimpleFileSystem
));
2388 This
->Interface
= &Private
->SimpleFileSystem
;
2389 This
->Private
= Private
;
2395 WinNtFileSystmeThunkClose (
2396 IN EMU_IO_THUNK_PROTOCOL
*This
2399 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
2401 Private
= This
->Private
;
2402 ASSERT (Private
!= NULL
);
2404 if (Private
->VolumeLabel
!= NULL
) {
2405 FreePool (Private
->VolumeLabel
);
2407 if (Private
->FilePath
!= NULL
) {
2408 FreePool (Private
->FilePath
);
2415 EFI_FILE_PROTOCOL gWinNtFileProtocol
= {
2422 WinNtFileGetPossition
,
2423 WinNtFileSetPossition
,
2429 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol
= {
2430 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
,
2435 EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo
= {
2436 &gEfiSimpleFileSystemProtocolGuid
,
2440 WinNtFileSystmeThunkOpen
,
2441 WinNtFileSystmeThunkClose
,