2 Support OS native directory access.
4 Copyright (c) 2006 - 2018, 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 StrCpy (PrivateFile
->FilePath
, Private
->FilePath
);
209 StrCpy (PrivateFile
->FileName
, PrivateFile
->FilePath
);
210 PrivateFile
->Signature
= WIN_NT_EFI_FILE_PRIVATE_SIGNATURE
;
211 PrivateFile
->Thunk
= Private
->Thunk
;
212 PrivateFile
->SimpleFileSystem
= This
;
213 PrivateFile
->IsRootDirectory
= TRUE
;
214 PrivateFile
->IsDirectoryPath
= TRUE
;
215 PrivateFile
->IsOpenedByRead
= TRUE
;
216 CopyMem (&PrivateFile
->EfiFile
, &gWinNtFileProtocol
, sizeof (gWinNtFileProtocol
));
217 PrivateFile
->IsValidFindBuf
= FALSE
;
222 PrivateFile
->DirHandle
= CreateFile (
223 PrivateFile
->FilePath
,
225 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
228 FILE_FLAG_BACKUP_SEMANTICS
,
232 if (PrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
233 Status
= EFI_NOT_FOUND
;
238 // Find the first file under it
240 Size
= StrSize (PrivateFile
->FilePath
);
241 Size
+= StrSize (L
"\\*");
242 TempFileName
= AllocatePool (Size
);
243 if (TempFileName
== NULL
) {
246 StrCpy (TempFileName
, PrivateFile
->FilePath
);
247 StrCat (TempFileName
, L
"\\*");
249 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &PrivateFile
->FindBuf
);
250 FreePool (TempFileName
);
252 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
253 PrivateFile
->IsValidFindBuf
= FALSE
;
255 PrivateFile
->IsValidFindBuf
= TRUE
;
257 *Root
= &PrivateFile
->EfiFile
;
259 Status
= EFI_SUCCESS
;
262 if (EFI_ERROR (Status
)) {
264 if (PrivateFile
->FileName
) {
265 FreePool (PrivateFile
->FileName
);
268 if (PrivateFile
->FilePath
) {
269 FreePool (PrivateFile
->FilePath
);
272 FreePool (PrivateFile
);
280 Count the number of Leading Dot in FileNameToken.
282 @param FileNameToken A string representing a token in the path name.
284 @return UINTN The number of leading dot in the name.
289 IN CONST CHAR16
* FileNameToken
295 while (*FileNameToken
== L
'.') {
305 IsFileNameTokenValid (
306 IN CONST CHAR16
* FileNameToken
310 if (StrStr (FileNameToken
, L
"/") != NULL
) {
312 // No L'/' in file name.
317 // If Token has all dot, the number should not exceed 2
319 Num
= CountLeadingDots (FileNameToken
);
321 if (Num
== StrLen (FileNameToken
)) {
323 // If the FileNameToken only contains a number of L'.'.
336 Return the first string token found in the indirect pointer a String named by FileName.
338 On input, FileName is a indirect pointer pointing to a String.
339 On output, FileName is a updated to point to the next character after the first
340 found L"\" or NULL if there is no L"\" found.
342 @param FileName A indirect pointer pointing to a FileName.
344 @return Token The first string token found before a L"\".
348 GetNextFileNameToken (
349 IN OUT CONST CHAR16
** FileName
355 ASSERT (**FileName
!= L
'\\');
356 ASSERT (**FileName
!= L
'\0');
358 SlashPos
= StrStr (*FileName
, L
"\\");
359 if (SlashPos
== NULL
) {
360 Token
= AllocateCopyPool (StrSize (*FileName
), *FileName
);
363 Offset
= SlashPos
- *FileName
;
364 Token
= AllocateZeroPool ((Offset
+ 1) * sizeof (CHAR16
));
365 StrnCpy (Token
, *FileName
, Offset
);
367 // Point *FileName to the next character after L'\'.
369 *FileName
= *FileName
+ Offset
+ 1;
371 // If *FileName is an empty string, then set *FileName to NULL
373 if (**FileName
== L
'\0') {
383 Check if a FileName contains only Valid Characters.
385 If FileName contains only a single L'\', return TRUE.
386 If FileName contains two adjacent L'\', return FALSE.
387 If FileName conatins L'/' , return FALSE.
388 If FielName contains more than two dots seperated with other FileName characters
389 by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
391 @param FileName The File Name String to check.
393 @return TRUE FileName only contains valid characters.
394 @return FALSE FileName contains at least one invalid character.
400 IN CONST CHAR16
*FileName
407 // If FileName is just L'\', then it is a valid pathname.
409 if (StrCmp (FileName
, L
"\\") == 0) {
413 // We don't support two or more adjacent L'\'.
415 if (StrStr (FileName
, L
"\\\\") != NULL
) {
420 // Is FileName has a leading L"\", skip to next character.
422 if (FileName
[0] == L
'\\') {
427 Token
= GetNextFileNameToken (&FileName
);
428 Valid
= IsFileNameTokenValid (Token
);
433 } while (FileName
!= NULL
);
440 Opens a new file relative to the source file's location.
442 @param This The protocol instance pointer.
443 @param NewHandle Returns File Handle for FileName.
444 @param FileName Null terminated string. "\", ".", and ".." are supported.
445 @param OpenMode Open mode for file.
446 @param Attributes Only used for EFI_FILE_MODE_CREATE.
448 @retval EFI_SUCCESS The device was opened.
449 @retval EFI_NOT_FOUND The specified file could not be found on the device.
450 @retval EFI_NO_MEDIA The device has no media.
451 @retval EFI_MEDIA_CHANGED The media has changed.
452 @retval EFI_DEVICE_ERROR The device reported an error.
453 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
454 @retval EFI_ACCESS_DENIED The service denied access to the file.
455 @retval EFI_OUT_OF_RESOURCES The volume was not opened due to lack of resources.
456 @retval EFI_VOLUME_FULL The volume is full.
461 IN EFI_FILE_PROTOCOL
*This
,
462 OUT EFI_FILE_PROTOCOL
**NewHandle
,
468 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
469 WIN_NT_EFI_FILE_PRIVATE
*NewPrivateFile
;
470 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
472 CHAR16
*RealFileName
;
473 CHAR16
*TempFileName
;
474 CHAR16
*ParseFileName
;
475 CHAR16
*GuardPointer
;
486 // Init local variables
488 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
489 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
490 NewPrivateFile
= NULL
;
493 // Allocate buffer for FileName as the passed in FileName may be read only
495 TempFileName
= AllocatePool (StrSize (FileName
));
496 if (TempFileName
== NULL
) {
497 return EFI_OUT_OF_RESOURCES
;
499 StrCpy (TempFileName
, FileName
);
500 FileName
= TempFileName
;
502 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
503 FileName
[StrLen (FileName
) - 1] = 0;
507 // If file name does not equal to "." or ".." and not trailed with "\..",
508 // then we trim the leading/trailing blanks and trailing dots
510 if (StrCmp (FileName
, L
".") != 0 && StrCmp (FileName
, L
"..") != 0 &&
511 ((StrLen (FileName
) >= 3) ? (StrCmp (&FileName
[StrLen (FileName
) - 3], L
"\\..") != 0) : TRUE
)) {
513 // Trim leading blanks
516 for (TempFileName
= FileName
;
517 *TempFileName
!= 0 && *TempFileName
== L
' ';
521 CutPrefix (FileName
, Count
);
523 // Trim trailing blanks
525 for (TempFileName
= FileName
+ StrLen (FileName
) - 1;
526 TempFileName
>= FileName
&& (*TempFileName
== L
' ');
530 *(TempFileName
+ 1) = 0;
534 // Attempt to open the file
536 NewPrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
537 if (NewPrivateFile
== NULL
) {
538 Status
= EFI_OUT_OF_RESOURCES
;
542 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (WIN_NT_EFI_FILE_PRIVATE
));
544 NewPrivateFile
->FilePath
= AllocatePool (StrSize (PrivateFile
->FileName
));
545 if (NewPrivateFile
->FilePath
== NULL
) {
546 Status
= EFI_OUT_OF_RESOURCES
;
550 if (PrivateFile
->IsDirectoryPath
) {
551 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FileName
);
553 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FilePath
);
556 Size
= StrSize (NewPrivateFile
->FilePath
);
557 Size
+= StrSize (L
"\\");
558 Size
+= StrSize (FileName
);
559 NewPrivateFile
->FileName
= AllocatePool (Size
);
560 if (NewPrivateFile
->FileName
== NULL
) {
561 Status
= EFI_OUT_OF_RESOURCES
;
565 if (*FileName
== L
'\\') {
566 StrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
567 StrCat (NewPrivateFile
->FileName
, L
"\\");
568 StrCat (NewPrivateFile
->FileName
, FileName
+ 1);
570 StrCpy (NewPrivateFile
->FileName
, NewPrivateFile
->FilePath
);
571 if (StrCmp (FileName
, L
"") != 0) {
573 // In case the filename becomes empty, especially after trimming dots and blanks
575 StrCat (NewPrivateFile
->FileName
, L
"\\");
576 StrCat (NewPrivateFile
->FileName
, FileName
);
580 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
581 Status
= EFI_NOT_FOUND
;
586 // Get rid of . and .., except leading . or ..
590 // GuardPointer protect simplefilesystem root path not be destroyed
592 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
596 while (!LoopFinish
) {
600 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
601 if (*ParseFileName
== L
'.' &&
602 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
603 *(ParseFileName
- 1) == L
'\\'
609 CutPrefix (ParseFileName
- 1, 2);
614 if (*ParseFileName
== L
'.' &&
615 *(ParseFileName
+ 1) == L
'.' &&
616 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
617 *(ParseFileName
- 1) == L
'\\'
623 while (ParseFileName
!= GuardPointer
) {
626 if (*ParseFileName
== L
'\\') {
632 // cut \.. and its left directory
634 CutPrefix (ParseFileName
, Count
);
641 RealFileName
= NewPrivateFile
->FileName
;
642 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
643 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
647 if (RealFileName
!= NewPrivateFile
->FileName
) {
648 TempChar
= *(RealFileName
- 1);
649 *(RealFileName
- 1) = 0;
652 FreePool (NewPrivateFile
->FilePath
);
653 NewPrivateFile
->FilePath
= NULL
;
654 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
655 if (NewPrivateFile
->FilePath
== NULL
) {
656 Status
= EFI_OUT_OF_RESOURCES
;
660 StrCpy (NewPrivateFile
->FilePath
, NewPrivateFile
->FileName
);
662 *(RealFileName
- 1) = TempChar
;
665 NewPrivateFile
->IsRootDirectory
= FALSE
;
668 // Test whether file or directory
670 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
671 if (Attributes
& EFI_FILE_DIRECTORY
) {
672 NewPrivateFile
->IsDirectoryPath
= TRUE
;
674 NewPrivateFile
->IsDirectoryPath
= FALSE
;
677 NewPrivateFile
->LHandle
= CreateFile (
678 NewPrivateFile
->FileName
,
680 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
687 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
688 NewPrivateFile
->IsDirectoryPath
= FALSE
;
689 CloseHandle (NewPrivateFile
->LHandle
);
691 NewPrivateFile
->IsDirectoryPath
= TRUE
;
694 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
697 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
698 NewPrivateFile
->IsOpenedByRead
= FALSE
;
700 NewPrivateFile
->IsOpenedByRead
= TRUE
;
703 Status
= EFI_SUCCESS
;
706 // deal with directory
708 if (NewPrivateFile
->IsDirectoryPath
) {
710 Size
= StrSize (NewPrivateFile
->FileName
);
711 Size
+= StrSize (L
"\\*");
712 TempFileName
= AllocatePool (Size
);
713 if (TempFileName
== NULL
) {
714 Status
= EFI_OUT_OF_RESOURCES
;
718 StrCpy (TempFileName
, NewPrivateFile
->FileName
);
720 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
722 // Create a directory
724 if (!CreateDirectory (TempFileName
, NULL
)) {
726 LastError
= GetLastError ();
727 if (LastError
!= ERROR_ALREADY_EXISTS
) {
728 FreePool (TempFileName
);
729 Status
= EFI_ACCESS_DENIED
;
735 NewPrivateFile
->DirHandle
= CreateFile (
737 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
738 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
741 FILE_FLAG_BACKUP_SEMANTICS
,
745 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
747 NewPrivateFile
->DirHandle
= CreateFile (
750 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
753 FILE_FLAG_BACKUP_SEMANTICS
,
757 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
758 CloseHandle (NewPrivateFile
->DirHandle
);
759 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
760 Status
= EFI_ACCESS_DENIED
;
762 Status
= EFI_NOT_FOUND
;
765 FreePool (TempFileName
);
770 // Find the first file under it
772 StrCat (TempFileName
, L
"\\*");
773 NewPrivateFile
->LHandle
= FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
774 FreePool (TempFileName
);
776 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
777 NewPrivateFile
->IsValidFindBuf
= FALSE
;
779 NewPrivateFile
->IsValidFindBuf
= TRUE
;
785 if (!NewPrivateFile
->IsOpenedByRead
) {
786 NewPrivateFile
->LHandle
= CreateFile (
787 NewPrivateFile
->FileName
,
788 GENERIC_READ
| GENERIC_WRITE
,
789 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
791 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
796 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
797 NewPrivateFile
->LHandle
= CreateFile (
798 NewPrivateFile
->FileName
,
800 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
807 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
808 Status
= EFI_NOT_FOUND
;
810 Status
= EFI_ACCESS_DENIED
;
811 CloseHandle (NewPrivateFile
->LHandle
);
812 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
816 NewPrivateFile
->LHandle
= CreateFile (
817 NewPrivateFile
->FileName
,
819 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
826 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
827 Status
= EFI_NOT_FOUND
;
832 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
839 Status
= WinNtFileGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
841 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
842 Status
= EFI_DEVICE_ERROR
;
846 Info
= AllocatePool (InfoSize
);
848 Status
= EFI_OUT_OF_RESOURCES
;
852 Status
= WinNtFileGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
854 if (EFI_ERROR (Status
)) {
859 Info
->Attribute
= Attributes
;
861 WinNtFileSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
868 if (EFI_ERROR (Status
)) {
869 if (NewPrivateFile
) {
870 if (NewPrivateFile
->FileName
) {
871 FreePool (NewPrivateFile
->FileName
);
874 if (NewPrivateFile
->FilePath
) {
875 FreePool (NewPrivateFile
->FilePath
);
878 FreePool (NewPrivateFile
);
881 *NewHandle
= &NewPrivateFile
->EfiFile
;
882 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
883 NewPrivateFile
->IsRootDirectory
= TRUE
;
893 Close the file handle
895 @param This Protocol instance pointer.
897 @retval EFI_SUCCESS The device was opened.
902 IN EFI_FILE_PROTOCOL
*This
905 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
907 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
909 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
910 if (PrivateFile
->IsDirectoryPath
) {
911 FindClose (PrivateFile
->LHandle
);
913 CloseHandle (PrivateFile
->LHandle
);
916 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
919 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
920 CloseHandle (PrivateFile
->DirHandle
);
921 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
924 if (PrivateFile
->FileName
) {
925 FreePool (PrivateFile
->FileName
);
928 if (PrivateFile
->FilePath
) {
929 FreePool (PrivateFile
->FilePath
);
932 FreePool (PrivateFile
);
940 Close and delete the file handle.
942 @param This Protocol instance pointer.
944 @retval EFI_SUCCESS The device was opened.
945 @retval EFI_WARN_DELETE_FAILURE The handle was closed but the file was not deleted.
950 IN EFI_FILE_PROTOCOL
*This
954 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
956 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
958 Status
= EFI_WARN_DELETE_FAILURE
;
960 if (PrivateFile
->IsDirectoryPath
) {
961 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
962 FindClose (PrivateFile
->LHandle
);
965 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
966 CloseHandle (PrivateFile
->DirHandle
);
967 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
970 if (RemoveDirectory (PrivateFile
->FileName
)) {
971 Status
= EFI_SUCCESS
;
974 CloseHandle (PrivateFile
->LHandle
);
975 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
977 if (!PrivateFile
->IsOpenedByRead
) {
978 if (DeleteFile (PrivateFile
->FileName
)) {
979 Status
= EFI_SUCCESS
;
984 FreePool (PrivateFile
->FileName
);
985 FreePool (PrivateFile
->FilePath
);
986 FreePool (PrivateFile
);
992 WinNtSystemTimeToEfiTime (
993 IN SYSTEMTIME
*SystemTime
,
994 IN TIME_ZONE_INFORMATION
*TimeZone
,
1001 TODO: Add function description
1005 SystemTime - TODO: add argument description
1006 TimeZone - TODO: add argument description
1007 Time - TODO: add argument description
1011 TODO: add return values
1015 Time
->Year
= (UINT16
)SystemTime
->wYear
;
1016 Time
->Month
= (UINT8
)SystemTime
->wMonth
;
1017 Time
->Day
= (UINT8
)SystemTime
->wDay
;
1018 Time
->Hour
= (UINT8
)SystemTime
->wHour
;
1019 Time
->Minute
= (UINT8
)SystemTime
->wMinute
;
1020 Time
->Second
= (UINT8
)SystemTime
->wSecond
;
1021 Time
->Nanosecond
= (UINT32
)SystemTime
->wMilliseconds
* 1000000;
1022 Time
->TimeZone
= (INT16
)TimeZone
->Bias
;
1024 if (TimeZone
->StandardDate
.wMonth
) {
1025 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1030 Convert the FileTime to EfiTime.
1032 @param PrivateFile Pointer to WIN_NT_EFI_FILE_PRIVATE.
1033 @param TimeZone Pointer to the current time zone.
1034 @param FileTime Pointer to file time.
1035 @param EfiTime Pointer to EFI time.
1038 WinNtFileTimeToEfiTime (
1039 IN CONST WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1040 IN TIME_ZONE_INFORMATION
*TimeZone
,
1041 IN CONST FILETIME
*FileTime
,
1042 OUT EFI_TIME
*EfiTime
1045 FILETIME TempFileTime
;
1046 SYSTEMTIME SystemTime
;
1048 FileTimeToLocalFileTime (FileTime
, &TempFileTime
);
1049 FileTimeToSystemTime (&TempFileTime
, &SystemTime
);
1050 WinNtSystemTimeToEfiTime (&SystemTime
, TimeZone
, EfiTime
);
1055 Read data from the file.
1057 @param This Protocol instance pointer.
1058 @param BufferSize On input size of buffer, on output amount of data in buffer.
1059 @param Buffer The buffer in which data is read.
1061 @retval EFI_SUCCESS Data was read.
1062 @retval EFI_NO_MEDIA The device has no media.
1063 @retval EFI_DEVICE_ERROR The device reported an error.
1064 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1065 @retval EFI_BUFFER_TO_SMALL BufferSize is too small. BufferSize contains required size.
1070 IN EFI_FILE_PROTOCOL
*This
,
1071 IN OUT UINTN
*BufferSize
,
1075 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1081 EFI_FILE_INFO
*Info
;
1083 TIME_ZONE_INFORMATION TimeZone
;
1084 EFI_FILE_INFO
*FileInfo
;
1089 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1091 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1092 Status
= EFI_DEVICE_ERROR
;
1096 if (!PrivateFile
->IsDirectoryPath
) {
1098 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1099 Status
= EFI_DEVICE_ERROR
;
1103 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1104 FileInfo
= AllocatePool (FileInfoSize
);
1106 Status
= This
->GetInfo (
1113 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1114 FreePool (FileInfo
);
1115 FileInfo
= AllocatePool (FileInfoSize
);
1116 Status
= This
->GetInfo (
1124 if (EFI_ERROR (Status
)) {
1125 Status
= EFI_DEVICE_ERROR
;
1129 FileSize
= FileInfo
->FileSize
;
1131 FreePool (FileInfo
);
1133 if (Pos
>= FileSize
) {
1135 if (Pos
== FileSize
) {
1136 Status
= EFI_SUCCESS
;
1139 Status
= EFI_DEVICE_ERROR
;
1145 PrivateFile
->LHandle
,
1148 (LPDWORD
)BufferSize
,
1150 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1155 // Read on a directory. Perform a find next
1157 if (!PrivateFile
->IsValidFindBuf
) {
1159 Status
= EFI_SUCCESS
;
1163 Size
= SIZE_OF_EFI_FILE_INFO
;
1165 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1167 ResultSize
= Size
+ NameSize
;
1169 Status
= EFI_BUFFER_TOO_SMALL
;
1171 if (*BufferSize
>= ResultSize
) {
1172 Status
= EFI_SUCCESS
;
1175 ZeroMem (Info
, ResultSize
);
1177 Info
->Size
= ResultSize
;
1179 GetTimeZoneInformation (&TimeZone
);
1180 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftCreationTime
, &Info
->CreateTime
);
1181 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastAccessTime
, &Info
->LastAccessTime
);
1182 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastWriteTime
, &Info
->ModificationTime
);
1184 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1186 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1188 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1189 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1192 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1193 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1196 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1197 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1200 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1201 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1204 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1205 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1208 NameSize
= NameSize
/ sizeof (WCHAR
);
1210 pw
= (WCHAR
*)(((CHAR8
*)Buffer
) + Size
);
1212 for (Index
= 0; Index
< NameSize
; Index
++) {
1213 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1216 if (FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1217 PrivateFile
->IsValidFindBuf
= TRUE
;
1219 PrivateFile
->IsValidFindBuf
= FALSE
;
1223 *BufferSize
= ResultSize
;
1232 Write data to a file.
1234 @param This Protocol instance pointer.
1235 @param BufferSize On input size of buffer, on output amount of data in buffer.
1236 @param Buffer The buffer in which data to write.
1238 @retval EFI_SUCCESS Data was written.
1239 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
1240 @retval EFI_NO_MEDIA The device has no media.
1241 @retval EFI_DEVICE_ERROR The device reported an error.
1242 @retval EFI_DEVICE_ERROR An attempt was made to write to a deleted file.
1243 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1244 @retval EFI_WRITE_PROTECTED The device is write protected.
1245 @retval EFI_ACCESS_DENIED The file was open for read only.
1246 @retval EFI_VOLUME_FULL The volume is full.
1251 IN EFI_FILE_PROTOCOL
*This
,
1252 IN OUT UINTN
*BufferSize
,
1256 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1259 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1261 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1262 Status
= EFI_DEVICE_ERROR
;
1266 if (PrivateFile
->IsDirectoryPath
) {
1267 Status
= EFI_UNSUPPORTED
;
1271 if (PrivateFile
->IsOpenedByRead
) {
1272 Status
= EFI_ACCESS_DENIED
;
1276 Status
= WriteFile (
1277 PrivateFile
->LHandle
,
1280 (LPDWORD
)BufferSize
,
1282 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1288 // bugbug: need to access windows error reporting
1295 Set a files current position
1297 @param This Protocol instance pointer.
1298 @param Position Byte position from the start of the file.
1300 @retval EFI_SUCCESS Data was written.
1301 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open.
1305 WinNtFileSetPossition (
1306 IN EFI_FILE_PROTOCOL
*This
,
1311 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1317 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1319 if (PrivateFile
->IsDirectoryPath
) {
1320 if (Position
!= 0) {
1321 Status
= EFI_UNSUPPORTED
;
1325 Size
= StrSize (PrivateFile
->FileName
);
1326 Size
+= StrSize (L
"\\*");
1327 FileName
= AllocatePool (Size
);
1328 if (FileName
== NULL
) {
1329 Status
= EFI_OUT_OF_RESOURCES
;
1333 StrCpy (FileName
, PrivateFile
->FileName
);
1334 StrCat (FileName
, L
"\\*");
1336 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1337 FindClose (PrivateFile
->LHandle
);
1340 PrivateFile
->LHandle
= FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1342 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1343 PrivateFile
->IsValidFindBuf
= FALSE
;
1345 PrivateFile
->IsValidFindBuf
= TRUE
;
1348 FreePool (FileName
);
1350 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1352 if (Position
== (UINT64
)-1) {
1353 PosLow
= SetFilePointer (PrivateFile
->LHandle
, (ULONG
)0, NULL
, FILE_END
);
1355 PosHigh
= (UINT32
)RShiftU64 (Position
, 32);
1357 PosLow
= SetFilePointer (PrivateFile
->LHandle
, (ULONG
)Position
, (PLONG
)&PosHigh
, FILE_BEGIN
);
1360 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1370 Get a file's current position
1372 @param This Protocol instance pointer.
1373 @param Position Byte position from the start of the file.
1375 @retval EFI_SUCCESS Data was written.
1376 @retval EFI_UNSUPPORTED Seek request for non-zero is not valid on open..
1380 WinNtFileGetPossition (
1381 IN EFI_FILE_PROTOCOL
*This
,
1382 OUT UINT64
*Position
1386 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1390 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1395 if (PrivateFile
->IsDirectoryPath
) {
1397 Status
= EFI_UNSUPPORTED
;
1403 *Position
= SetFilePointer (
1404 PrivateFile
->LHandle
,
1406 (PLONG
)&PositionHigh
,
1410 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1411 if (EFI_ERROR (Status
)) {
1415 PosHigh64
= PositionHigh
;
1416 *Position
+= LShiftU64 (PosHigh64
, 32);
1425 WinNtSimpleFileSystemFileInfo (
1426 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1427 IN OUT UINTN
*BufferSize
,
1432 Routine Description:
1434 TODO: Add function description
1438 PrivateFile - TODO: add argument description
1439 BufferSize - TODO: add argument description
1440 Buffer - TODO: add argument description
1444 TODO: add return values
1452 EFI_FILE_INFO
*Info
;
1453 BY_HANDLE_FILE_INFORMATION FileInfo
;
1454 CHAR16
*RealFileName
;
1455 CHAR16
*TempPointer
;
1456 TIME_ZONE_INFORMATION TimeZone
;
1458 Size
= SIZE_OF_EFI_FILE_INFO
;
1460 RealFileName
= PrivateFile
->FileName
;
1461 TempPointer
= RealFileName
;
1462 while (*TempPointer
) {
1463 if (*TempPointer
== '\\') {
1464 RealFileName
= TempPointer
+ 1;
1469 NameSize
= StrSize (RealFileName
);
1471 ResultSize
= Size
+ NameSize
;
1473 Status
= EFI_BUFFER_TOO_SMALL
;
1474 if (*BufferSize
>= ResultSize
) {
1475 Status
= EFI_SUCCESS
;
1478 ZeroMem (Info
, ResultSize
);
1480 Info
->Size
= ResultSize
;
1481 GetFileInformationByHandle (
1482 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
1485 Info
->FileSize
= FileInfo
.nFileSizeLow
;
1486 Info
->PhysicalSize
= Info
->FileSize
;
1488 GetTimeZoneInformation (&TimeZone
);
1489 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftCreationTime
, &Info
->CreateTime
);
1490 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastAccessTime
, &Info
->LastAccessTime
);
1491 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastWriteTime
, &Info
->ModificationTime
);
1493 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1494 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1497 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1498 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1501 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1502 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1505 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1506 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1509 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1510 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1513 if (PrivateFile
->IsDirectoryPath
) {
1514 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1517 if (PrivateFile
->IsRootDirectory
) {
1518 *((CHAR8
*)Buffer
+ Size
) = 0;
1520 CopyMem ((CHAR8
*)Buffer
+ Size
, RealFileName
, NameSize
);
1524 *BufferSize
= ResultSize
;
1529 Get information about a file.
1531 @param This Protocol instance pointer.
1532 @param InformationType Type of information to return in Buffer.
1533 @param BufferSize On input size of buffer, on output amount of data in buffer.
1534 @param Buffer The buffer to return data.
1536 @retval EFI_SUCCESS Data was returned.
1537 @retval EFI_UNSUPPORTED InformationType is not supported.
1538 @retval EFI_NO_MEDIA The device has no media.
1539 @retval EFI_DEVICE_ERROR The device reported an error.
1540 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1541 @retval EFI_WRITE_PROTECTED The device is write protected.
1542 @retval EFI_ACCESS_DENIED The file was open for read only.
1543 @retval EFI_BUFFER_TOO_SMALL Buffer was too small; required size returned in BufferSize.
1548 IN EFI_FILE_PROTOCOL
*This
,
1549 IN EFI_GUID
*InformationType
,
1550 IN OUT UINTN
*BufferSize
,
1555 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1556 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
1557 UINT32 SectorsPerCluster
;
1558 UINT32 BytesPerSector
;
1559 UINT32 FreeClusters
;
1560 UINT32 TotalClusters
;
1561 UINT32 BytesPerCluster
;
1563 BOOLEAN DriveNameFound
;
1566 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1568 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
1569 return EFI_INVALID_PARAMETER
;
1572 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1573 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1575 Status
= EFI_UNSUPPORTED
;
1577 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1578 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
1581 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1582 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
1583 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1584 Status
= EFI_BUFFER_TOO_SMALL
;
1588 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*)Buffer
;
1589 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1590 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
1593 // Try to get the drive name
1595 DriveNameFound
= FALSE
;
1596 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
1597 if (DriveName
== NULL
) {
1598 Status
= EFI_OUT_OF_RESOURCES
;
1602 StrCpy (DriveName
, PrivateFile
->FilePath
);
1603 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
1607 if (DriveName
[Index
] == ':') {
1608 DriveName
[Index
+ 1] = '\\';
1609 DriveName
[Index
+ 2] = 0;
1610 DriveNameFound
= TRUE
;
1611 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
1612 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
1616 if (DriveName
[Index
] == '\\') {
1617 DriveNameFound
= TRUE
;
1618 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
1622 DriveName
[Index
] = '\\';
1623 DriveName
[Index
+ 1] = 0;
1628 // Try GetDiskFreeSpace first
1630 NtStatus
= GetDiskFreeSpace (
1631 DriveNameFound
? DriveName
: NULL
,
1632 (LPDWORD
)&SectorsPerCluster
,
1633 (LPDWORD
)&BytesPerSector
,
1634 (LPDWORD
)&FreeClusters
,
1635 (LPDWORD
)&TotalClusters
1638 FreePool (DriveName
);
1645 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
1646 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
1647 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
1648 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
1652 // try GetDiskFreeSpaceEx then
1654 FileSystemInfoBuffer
->BlockSize
= 0;
1655 NtStatus
= GetDiskFreeSpaceEx (
1656 PrivateFile
->FilePath
,
1657 (PULARGE_INTEGER
)(&FileSystemInfoBuffer
->FreeSpace
),
1658 (PULARGE_INTEGER
)(&FileSystemInfoBuffer
->VolumeSize
),
1662 Status
= EFI_DEVICE_ERROR
;
1667 StrCpy ((CHAR16
*)FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
1668 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
1669 Status
= EFI_SUCCESS
;
1672 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1673 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1674 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1675 Status
= EFI_BUFFER_TOO_SMALL
;
1679 StrCpy ((CHAR16
*)Buffer
, PrivateRoot
->VolumeLabel
);
1680 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
1681 Status
= EFI_SUCCESS
;
1690 Set information about a file
1692 @param File Protocol instance pointer.
1693 @param InformationType Type of information in Buffer.
1694 @param BufferSize Size of buffer.
1695 @param Buffer The data to write.
1697 @retval EFI_SUCCESS Data was returned.
1698 @retval EFI_UNSUPPORTED InformationType is not supported.
1699 @retval EFI_NO_MEDIA The device has no media.
1700 @retval EFI_DEVICE_ERROR The device reported an error.
1701 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
1702 @retval EFI_WRITE_PROTECTED The device is write protected.
1703 @retval EFI_ACCESS_DENIED The file was open for read only.
1708 IN EFI_FILE_PROTOCOL
*This
,
1709 IN EFI_GUID
*InformationType
,
1710 IN UINTN BufferSize
,
1714 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
1715 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1716 EFI_FILE_INFO
*OldFileInfo
;
1717 EFI_FILE_INFO
*NewFileInfo
;
1723 CHAR16
*OldFileName
;
1724 CHAR16
*NewFileName
;
1725 CHAR16
*TempFileName
;
1726 CHAR16
*CharPointer
;
1727 BOOLEAN AttrChangeFlag
;
1728 BOOLEAN NameChangeFlag
;
1729 BOOLEAN SizeChangeFlag
;
1730 BOOLEAN TimeChangeFlag
;
1732 SYSTEMTIME NewCreationSystemTime
;
1733 SYSTEMTIME NewLastAccessSystemTime
;
1734 SYSTEMTIME NewLastWriteSystemTime
;
1735 FILETIME NewCreationFileTime
;
1736 FILETIME NewLastAccessFileTime
;
1737 FILETIME NewLastWriteFileTime
;
1738 WIN32_FIND_DATA FindBuf
;
1739 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
1743 // Initialise locals.
1745 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1746 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
1748 Status
= EFI_UNSUPPORTED
;
1749 OldFileInfo
= NewFileInfo
= NULL
;
1750 OldFileName
= NewFileName
= NULL
;
1751 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
1754 // Set file system information.
1756 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
1757 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*)Buffer
;
1758 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (NewFileSystemInfo
->VolumeLabel
)) {
1759 Status
= EFI_BAD_BUFFER_SIZE
;
1764 FreePool (PrivateRoot
->VolumeLabel
);
1765 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
1766 if (PrivateRoot
->VolumeLabel
== NULL
) {
1767 Status
= EFI_OUT_OF_RESOURCES
;
1771 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
1773 Status
= EFI_SUCCESS
;
1778 // Set volume label information.
1780 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
1781 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
1782 Status
= EFI_BAD_BUFFER_SIZE
;
1786 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*)Buffer
);
1788 Status
= EFI_SUCCESS
;
1792 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
1793 Status
= EFI_UNSUPPORTED
;
1797 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
1798 Status
= EFI_BAD_BUFFER_SIZE
;
1803 // Set file/directory information.
1807 // Check for invalid set file information parameters.
1809 NewFileInfo
= (EFI_FILE_INFO
*)Buffer
;
1811 if ((NewFileInfo
->Size
<= SIZE_OF_EFI_FILE_INFO
) ||
1812 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
1813 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
1815 Status
= EFI_INVALID_PARAMETER
;
1820 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
1821 // that would have an additional parameter that would be the size
1822 // of the string array just in case there are no NULL characters in
1823 // the string array.
1826 // Get current file information so we can determine what kind
1827 // of change request this is.
1830 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
1832 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1833 Status
= EFI_DEVICE_ERROR
;
1837 OldFileInfo
= AllocatePool (OldInfoSize
);
1838 if (OldFileInfo
== NULL
) {
1839 Status
= EFI_OUT_OF_RESOURCES
;
1843 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
1845 if (EFI_ERROR (Status
)) {
1849 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
1850 if (OldFileName
== NULL
) {
1851 Status
= EFI_OUT_OF_RESOURCES
;
1855 StrCpy (OldFileName
, PrivateFile
->FileName
);
1858 // Make full pathname from new filename and rootpath.
1860 if (NewFileInfo
->FileName
[0] == '\\') {
1861 Size
= StrSize (PrivateRoot
->FilePath
);
1862 Size
+= StrSize (L
"\\");
1863 Size
+= StrSize (NewFileInfo
->FileName
);
1864 NewFileName
= AllocatePool (Size
);
1865 if (NewFileName
== NULL
) {
1866 Status
= EFI_OUT_OF_RESOURCES
;
1870 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
1871 StrCat (NewFileName
, L
"\\");
1872 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
1874 Size
= StrSize (PrivateFile
->FilePath
);
1875 Size
+= StrSize (L
"\\");
1876 Size
+= StrSize (NewFileInfo
->FileName
);
1877 NewFileName
= AllocatePool (Size
);
1878 if (NewFileName
== NULL
) {
1879 Status
= EFI_OUT_OF_RESOURCES
;
1883 StrCpy (NewFileName
, PrivateFile
->FilePath
);
1884 StrCat (NewFileName
, L
"\\");
1885 StrCat (NewFileName
, NewFileInfo
->FileName
);
1889 // Is there an attribute change request?
1891 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
1892 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
1893 Status
= EFI_INVALID_PARAMETER
;
1897 AttrChangeFlag
= TRUE
;
1901 // Is there a name change request?
1902 // bugbug: - Need EfiStrCaseCmp()
1904 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
1905 NameChangeFlag
= TRUE
;
1909 // Is there a size change request?
1911 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
1912 SizeChangeFlag
= TRUE
;
1916 // Is there a time stamp change request?
1918 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
1919 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
1921 TimeChangeFlag
= TRUE
;
1922 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
1923 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
1925 TimeChangeFlag
= TRUE
;
1926 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
1927 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
1929 TimeChangeFlag
= TRUE
;
1933 // All done if there are no change requests being made.
1935 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
1936 Status
= EFI_SUCCESS
;
1941 // Set file or directory information.
1943 OldAttr
= GetFileAttributes (OldFileName
);
1948 if (NameChangeFlag
) {
1950 // Close the handles first
1952 if (PrivateFile
->IsOpenedByRead
) {
1953 Status
= EFI_ACCESS_DENIED
;
1957 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
1960 if (*CharPointer
!= 0) {
1961 Status
= EFI_ACCESS_DENIED
;
1965 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1966 if (PrivateFile
->IsDirectoryPath
) {
1967 FindClose (PrivateFile
->LHandle
);
1969 CloseHandle (PrivateFile
->LHandle
);
1970 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1974 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1975 CloseHandle (PrivateFile
->DirHandle
);
1976 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1979 NtStatus
= MoveFile (OldFileName
, NewFileName
);
1985 FreePool (PrivateFile
->FileName
);
1987 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
1988 if (PrivateFile
->FileName
== NULL
) {
1989 Status
= EFI_OUT_OF_RESOURCES
;
1993 StrCpy (PrivateFile
->FileName
, NewFileName
);
1995 Size
= StrSize (NewFileName
);
1996 Size
+= StrSize (L
"\\*");
1997 TempFileName
= AllocatePool (Size
);
1999 StrCpy (TempFileName
, NewFileName
);
2001 if (!PrivateFile
->IsDirectoryPath
) {
2002 PrivateFile
->LHandle
= CreateFile (
2004 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2005 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2012 FreePool (TempFileName
);
2015 // Flush buffers just in case
2017 if (FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2018 Status
= EFI_DEVICE_ERROR
;
2022 PrivateFile
->DirHandle
= CreateFile (
2024 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2025 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2028 FILE_FLAG_BACKUP_SEMANTICS
,
2032 StrCat (TempFileName
, L
"\\*");
2033 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &FindBuf
);
2035 FreePool (TempFileName
);
2038 Status
= EFI_ACCESS_DENIED
;
2041 NtStatus
= SetFileAttributes (OldFileName
, OldAttr
);
2047 Size
= StrSize (OldFileName
);
2048 Size
+= StrSize (L
"\\*");
2049 TempFileName
= AllocatePool (Size
);
2051 StrCpy (TempFileName
, OldFileName
);
2053 if (!PrivateFile
->IsDirectoryPath
) {
2054 PrivateFile
->LHandle
= CreateFile (
2056 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2057 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
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 StrCat (TempFileName
, L
"\\*");
2075 PrivateFile
->LHandle
= FindFirstFile (TempFileName
, &FindBuf
);
2078 FreePool (TempFileName
);
2088 if (SizeChangeFlag
) {
2089 if (PrivateFile
->IsDirectoryPath
) {
2090 Status
= EFI_UNSUPPORTED
;
2094 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2095 Status
= EFI_ACCESS_DENIED
;
2099 Status
= This
->GetPosition (This
, &CurPos
);
2100 if (EFI_ERROR (Status
)) {
2104 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2105 if (EFI_ERROR (Status
)) {
2109 if (SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2110 Status
= EFI_DEVICE_ERROR
;
2114 Status
= This
->SetPosition (This
, CurPos
);
2115 if (EFI_ERROR (Status
)) {
2123 if (TimeChangeFlag
) {
2125 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2126 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2127 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2128 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2129 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2130 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2131 NewCreationSystemTime
.wMilliseconds
= 0;
2133 if (!SystemTimeToFileTime (
2134 &NewCreationSystemTime
,
2135 &NewCreationFileTime
2140 if (!LocalFileTimeToFileTime (
2141 &NewCreationFileTime
,
2142 &NewCreationFileTime
2147 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2148 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2149 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2150 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2151 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2152 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2153 NewLastAccessSystemTime
.wMilliseconds
= 0;
2155 if (!SystemTimeToFileTime (
2156 &NewLastAccessSystemTime
,
2157 &NewLastAccessFileTime
2162 if (!LocalFileTimeToFileTime (
2163 &NewLastAccessFileTime
,
2164 &NewLastAccessFileTime
2169 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2170 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2171 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2172 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2173 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2174 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2175 NewLastWriteSystemTime
.wMilliseconds
= 0;
2177 if (!SystemTimeToFileTime (
2178 &NewLastWriteSystemTime
,
2179 &NewLastWriteFileTime
2184 if (!LocalFileTimeToFileTime (
2185 &NewLastWriteFileTime
,
2186 &NewLastWriteFileTime
2192 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2193 &NewCreationFileTime
,
2194 &NewLastAccessFileTime
,
2195 &NewLastWriteFileTime
2197 Status
= EFI_DEVICE_ERROR
;
2204 // No matter about AttrChangeFlag, Attribute must be set.
2205 // Because operation before may cause attribute change.
2209 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2210 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2212 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2215 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2216 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2218 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2221 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2222 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2224 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2227 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2228 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2230 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2233 NtStatus
= SetFileAttributes (NewFileName
, NewAttr
);
2236 Status
= EFI_DEVICE_ERROR
;
2241 if (OldFileInfo
!= NULL
) {
2242 FreePool (OldFileInfo
);
2245 if (OldFileName
!= NULL
) {
2246 FreePool (OldFileName
);
2249 if (NewFileName
!= NULL
) {
2250 FreePool (NewFileName
);
2258 Flush data back for the file handle.
2260 @param This Protocol instance pointer.
2262 @retval EFI_SUCCESS Data was written.
2263 @retval EFI_UNSUPPORTED Writes to Open directory are not supported.
2264 @retval EFI_NO_MEDIA The device has no media.
2265 @retval EFI_DEVICE_ERROR The device reported an error.
2266 @retval EFI_VOLUME_CORRUPTED The file system structures are corrupted.
2267 @retval EFI_WRITE_PROTECTED The device is write protected.
2268 @retval EFI_ACCESS_DENIED The file was open for read only.
2269 @retval EFI_VOLUME_FULL The volume is full.
2274 IN EFI_FILE_PROTOCOL
*This
2277 BY_HANDLE_FILE_INFORMATION FileInfo
;
2278 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2281 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2283 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2284 Status
= EFI_DEVICE_ERROR
;
2288 if (PrivateFile
->IsDirectoryPath
) {
2289 Status
= EFI_SUCCESS
;
2293 if (PrivateFile
->IsOpenedByRead
) {
2294 Status
= EFI_ACCESS_DENIED
;
2298 GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2300 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2301 Status
= EFI_ACCESS_DENIED
;
2305 Status
= FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2310 // bugbug: - Use Windows error reporting.
2318 WinNtFileSystmeThunkOpen (
2319 IN EMU_IO_THUNK_PROTOCOL
*This
2322 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
2324 Private
= AllocateZeroPool (sizeof (*Private
));
2325 if (Private
== NULL
) {
2326 return EFI_OUT_OF_RESOURCES
;
2329 Private
->FilePath
= AllocateCopyPool (StrSize (This
->ConfigString
), This
->ConfigString
);
2330 if (Private
->FilePath
== NULL
) {
2332 return EFI_OUT_OF_RESOURCES
;
2335 Private
->VolumeLabel
= AllocateCopyPool (StrSize (L
"EFI_EMULATED"), L
"EFI_EMULATED");
2336 if (Private
->VolumeLabel
== NULL
) {
2337 FreePool (Private
->FilePath
);
2339 return EFI_OUT_OF_RESOURCES
;
2342 Private
->Signature
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE
;
2343 Private
->Thunk
= This
;
2344 CopyMem (&Private
->SimpleFileSystem
, &gWinNtFileSystemProtocol
, sizeof (Private
->SimpleFileSystem
));
2346 This
->Interface
= &Private
->SimpleFileSystem
;
2347 This
->Private
= Private
;
2353 WinNtFileSystmeThunkClose (
2354 IN EMU_IO_THUNK_PROTOCOL
*This
2357 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
2359 Private
= This
->Private
;
2360 ASSERT (Private
!= NULL
);
2362 if (Private
->VolumeLabel
!= NULL
) {
2363 FreePool (Private
->VolumeLabel
);
2365 if (Private
->FilePath
!= NULL
) {
2366 FreePool (Private
->FilePath
);
2373 EFI_FILE_PROTOCOL gWinNtFileProtocol
= {
2380 WinNtFileGetPossition
,
2381 WinNtFileSetPossition
,
2387 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL gWinNtFileSystemProtocol
= {
2388 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
,
2393 EMU_IO_THUNK_PROTOCOL mWinNtFileSystemThunkIo
= {
2394 &gEfiSimpleFileSystemProtocolGuid
,
2398 WinNtFileSystmeThunkOpen
,
2399 WinNtFileSystmeThunkClose
,