3 Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
8 WinNtSimpleFileSystem.c
12 Produce Simple File System abstractions for directories on your PC using Win32 APIs.
13 The configuration of what devices to mount or emulate comes from NT
14 environment variables. The variables must be visible to the Microsoft*
15 Developer Studio for them to work.
17 * Other names and brands may be claimed as the property of others.
22 // The package level header files this module uses
27 // The protocols, PPI and GUID defintions for this module
29 #include <Guid/FileSystemVolumeLabelInfo.h>
30 #include <Protocol/WinNtIo.h>
31 #include <Protocol/ComponentName.h>
32 #include <Guid/FileInfo.h>
33 #include <Protocol/DriverBinding.h>
34 #include <Guid/FileSystemInfo.h>
35 #include <Protocol/SimpleFileSystem.h>
37 // The Library classes this module consumes
39 #include <Library/DebugLib.h>
40 #include <Library/BaseLib.h>
41 #include <Library/UefiDriverEntryPoint.h>
42 #include <Library/UefiLib.h>
43 #include <Library/BaseMemoryLib.h>
44 #include <Library/UefiBootServicesTableLib.h>
45 #include <Library/MemoryAllocationLib.h>
47 #include "WinNtSimpleFileSystem.h"
49 EFI_DRIVER_BINDING_PROTOCOL gWinNtSimpleFileSystemDriverBinding
= {
50 WinNtSimpleFileSystemDriverBindingSupported
,
51 WinNtSimpleFileSystemDriverBindingStart
,
52 WinNtSimpleFileSystemDriverBindingStop
,
59 The user Entry Point for module WinNtSimpleFileSystem. The user code starts with this function.
61 @param[in] ImageHandle The firmware allocated handle for the EFI image.
62 @param[in] SystemTable A pointer to the EFI System Table.
64 @retval EFI_SUCCESS The entry point is executed successfully.
65 @retval other Some error occurs when executing this entry point.
70 InitializeWinNtSimpleFileSystem(
71 IN EFI_HANDLE ImageHandle
,
72 IN EFI_SYSTEM_TABLE
*SystemTable
78 // Install driver model protocol(s).
80 Status
= EfiLibInstallDriverBindingComponentName2 (
83 &gWinNtSimpleFileSystemDriverBinding
,
85 &gWinNtSimpleFileSystemComponentName
,
86 &gWinNtSimpleFileSystemComponentName2
88 ASSERT_EFI_ERROR (Status
);
103 Locate the first occurance of a character in a string.
107 Str - Pointer to NULL terminated unicode string.
108 Chr - Character to locate.
112 If Str is NULL, then NULL is returned.
113 If Chr is not contained in Str, then NULL is returned.
114 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
122 while (*Str
!= '\0' && *Str
!= Chr
) {
126 return (*Str
== Chr
) ? Str
: NULL
;
138 TODO: Add function description
142 Buffer - TODO: add argument description
143 Length - TODO: add argument description
147 TODO: add return values
151 if (Buffer
== NULL
|| Length
== 0) {
155 if (*(UINT8
*) Buffer
!= 0) {
160 if (!CompareMem (Buffer
, (UINT8
*) Buffer
+ 1, Length
- 1)) {
177 TODO: Add function description
181 Str - TODO: add argument description
182 Count - TODO: add argument description
186 TODO: add return values
192 if (StrLen (Str
) < Count
) {
197 for (Pointer
= Str
; *(Pointer
+ Count
); Pointer
++) {
198 *Pointer
= *(Pointer
+ Count
);
200 *Pointer
= *(Pointer
+ Count
);
208 WinNtSimpleFileSystemDriverBindingSupported (
209 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
210 IN EFI_HANDLE ControllerHandle
,
211 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
217 Check to see if the driver supports a given controller.
221 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
223 ControllerHandle - EFI handle of the controller to test.
225 RemainingDevicePath - Pointer to remaining portion of a device path.
229 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver
232 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
233 the driver specified by This.
235 EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
236 a different driver or an application that requires exclusive access.
238 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the
239 driver specified by This.
244 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
247 // Open the IO Abstraction(s) needed to perform the supported test
249 Status
= gBS
->OpenProtocol (
251 &gEfiWinNtIoProtocolGuid
,
253 This
->DriverBindingHandle
,
255 EFI_OPEN_PROTOCOL_BY_DRIVER
257 if (EFI_ERROR (Status
)) {
262 // Make sure GUID is for a File System handle.
264 Status
= EFI_UNSUPPORTED
;
265 if (CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtFileSystemGuid
)) {
266 Status
= EFI_SUCCESS
;
270 // Close the I/O Abstraction(s) used to perform the supported test
274 &gEfiWinNtIoProtocolGuid
,
275 This
->DriverBindingHandle
,
284 WinNtSimpleFileSystemDriverBindingStart (
285 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
286 IN EFI_HANDLE ControllerHandle
,
287 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
293 Starts a device controller or a bus controller.
297 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
299 ControllerHandle - EFI handle of the controller to start.
301 RemainingDevicePath - Pointer to remaining portion of a device path.
305 EFI_SUCCESS - The device or bus controller has been started.
307 EFI_DEVICE_ERROR - The device could not be started due to a device failure.
309 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
314 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
315 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
320 // Open the IO Abstraction(s) needed
322 Status
= gBS
->OpenProtocol (
324 &gEfiWinNtIoProtocolGuid
,
326 This
->DriverBindingHandle
,
328 EFI_OPEN_PROTOCOL_BY_DRIVER
330 if (EFI_ERROR (Status
)) {
337 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtFileSystemGuid
)) {
338 Status
= EFI_UNSUPPORTED
;
342 Private
= AllocatePool (sizeof (WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
));
343 if (Private
== NULL
) {
344 Status
= EFI_OUT_OF_RESOURCES
;
349 Private
->Signature
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE
;
350 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
352 Private
->FilePath
= WinNtIo
->EnvString
;
354 Private
->VolumeLabel
= AllocatePool (StrSize (L
"EFI_EMULATED"));
355 if (Private
->VolumeLabel
== NULL
) {
356 Status
= EFI_OUT_OF_RESOURCES
;
360 StrCpy (Private
->VolumeLabel
, L
"EFI_EMULATED");
362 Private
->SimpleFileSystem
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
363 Private
->SimpleFileSystem
.OpenVolume
= WinNtSimpleFileSystemOpenVolume
;
365 Private
->WinNtThunk
->SetErrorMode (SEM_FAILCRITICALERRORS
);
367 Private
->ControllerNameTable
= NULL
;
371 gWinNtSimpleFileSystemComponentName
.SupportedLanguages
,
372 &Private
->ControllerNameTable
,
378 gWinNtSimpleFileSystemComponentName2
.SupportedLanguages
,
379 &Private
->ControllerNameTable
,
385 Status
= gBS
->InstallMultipleProtocolInterfaces (
387 &gEfiSimpleFileSystemProtocolGuid
,
388 &Private
->SimpleFileSystem
,
393 if (EFI_ERROR (Status
)) {
395 if (Private
!= NULL
) {
397 FreeUnicodeStringTable (Private
->ControllerNameTable
);
404 &gEfiWinNtIoProtocolGuid
,
405 This
->DriverBindingHandle
,
415 WinNtSimpleFileSystemDriverBindingStop (
416 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
417 IN EFI_HANDLE ControllerHandle
,
418 IN UINTN NumberOfChildren
,
419 IN EFI_HANDLE
*ChildHandleBuffer
425 TODO: Add function description
429 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
431 ControllerHandle - A handle to the device to be stopped.
433 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
435 ChildHandleBuffer - An array of child device handles to be freed.
439 EFI_SUCCESS - The device has been stopped.
441 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.
444 // TODO: EFI_UNSUPPORTED - add return value to function comment
447 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFileSystem
;
448 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
451 // Get our context back
453 Status
= gBS
->OpenProtocol (
455 &gEfiSimpleFileSystemProtocolGuid
,
456 (VOID
**) &SimpleFileSystem
,
457 This
->DriverBindingHandle
,
459 EFI_OPEN_PROTOCOL_GET_PROTOCOL
461 if (EFI_ERROR (Status
)) {
462 return EFI_UNSUPPORTED
;
465 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem
);
468 // Uninstall the Simple File System Protocol from ControllerHandle
470 Status
= gBS
->UninstallMultipleProtocolInterfaces (
472 &gEfiSimpleFileSystemProtocolGuid
,
473 &Private
->SimpleFileSystem
,
476 if (!EFI_ERROR (Status
)) {
477 Status
= gBS
->CloseProtocol (
479 &gEfiWinNtIoProtocolGuid
,
480 This
->DriverBindingHandle
,
485 if (!EFI_ERROR (Status
)) {
487 // Free our instance data
489 FreeUnicodeStringTable (Private
->ControllerNameTable
);
499 WinNtSimpleFileSystemOpenVolume (
500 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
501 OUT EFI_FILE_PROTOCOL
**Root
507 Open the root directory on a volume.
511 This - A pointer to the volume to open.
513 Root - A pointer to storage for the returned opened file handle of the root directory.
517 EFI_SUCCESS - The volume was opened.
519 EFI_UNSUPPORTED - The volume does not support the requested file system type.
521 EFI_NO_MEDIA - The device has no media.
523 EFI_DEVICE_ERROR - The device reported an error.
525 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
527 EFI_ACCESS_DENIED - The service denied access to the file.
529 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.
531 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
534 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
537 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
538 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
540 CHAR16
*TempFileName
;
543 if (This
== NULL
|| Root
== NULL
) {
544 return EFI_INVALID_PARAMETER
;
547 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
549 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
551 PrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
552 if (PrivateFile
== NULL
) {
553 Status
= EFI_OUT_OF_RESOURCES
;
557 PrivateFile
->FileName
= AllocatePool (StrSize (Private
->FilePath
));
558 if (PrivateFile
->FileName
== NULL
) {
559 Status
= EFI_OUT_OF_RESOURCES
;
563 PrivateFile
->FilePath
= AllocatePool (StrSize (Private
->FilePath
));
564 if (PrivateFile
->FilePath
== NULL
) {
565 Status
= EFI_OUT_OF_RESOURCES
;
569 StrCpy (PrivateFile
->FilePath
, Private
->FilePath
);
570 StrCpy (PrivateFile
->FileName
, PrivateFile
->FilePath
);
571 PrivateFile
->Signature
= WIN_NT_EFI_FILE_PRIVATE_SIGNATURE
;
572 PrivateFile
->WinNtThunk
= Private
->WinNtThunk
;
573 PrivateFile
->SimpleFileSystem
= This
;
574 PrivateFile
->IsRootDirectory
= TRUE
;
575 PrivateFile
->IsDirectoryPath
= TRUE
;
576 PrivateFile
->IsOpenedByRead
= TRUE
;
577 PrivateFile
->EfiFile
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
578 PrivateFile
->EfiFile
.Open
= WinNtSimpleFileSystemOpen
;
579 PrivateFile
->EfiFile
.Close
= WinNtSimpleFileSystemClose
;
580 PrivateFile
->EfiFile
.Delete
= WinNtSimpleFileSystemDelete
;
581 PrivateFile
->EfiFile
.Read
= WinNtSimpleFileSystemRead
;
582 PrivateFile
->EfiFile
.Write
= WinNtSimpleFileSystemWrite
;
583 PrivateFile
->EfiFile
.GetPosition
= WinNtSimpleFileSystemGetPosition
;
584 PrivateFile
->EfiFile
.SetPosition
= WinNtSimpleFileSystemSetPosition
;
585 PrivateFile
->EfiFile
.GetInfo
= WinNtSimpleFileSystemGetInfo
;
586 PrivateFile
->EfiFile
.SetInfo
= WinNtSimpleFileSystemSetInfo
;
587 PrivateFile
->EfiFile
.Flush
= WinNtSimpleFileSystemFlush
;
588 PrivateFile
->IsValidFindBuf
= FALSE
;
593 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
594 PrivateFile
->FilePath
,
596 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
599 FILE_FLAG_BACKUP_SEMANTICS
,
603 if (PrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
604 Status
= EFI_NOT_FOUND
;
609 // Find the first file under it
611 Size
= StrSize (PrivateFile
->FilePath
);
612 Size
+= StrSize (L
"\\*");
613 Status
= gBS
->AllocatePool (
616 (VOID
**)&TempFileName
618 if (EFI_ERROR (Status
)) {
621 StrCpy (TempFileName
, PrivateFile
->FilePath
);
622 StrCat (TempFileName
, L
"\\*");
624 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &PrivateFile
->FindBuf
);
625 FreePool (TempFileName
);
627 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
628 PrivateFile
->IsValidFindBuf
= FALSE
;
630 PrivateFile
->IsValidFindBuf
= TRUE
;
632 *Root
= &PrivateFile
->EfiFile
;
634 Status
= EFI_SUCCESS
;
637 if (EFI_ERROR (Status
)) {
639 if (PrivateFile
->FileName
) {
640 FreePool (PrivateFile
->FileName
);
643 if (PrivateFile
->FilePath
) {
644 FreePool (PrivateFile
->FilePath
);
647 FreePool (PrivateFile
);
651 gBS
->RestoreTPL (OldTpl
);
657 Count the number of Leading Dot in FileNameToken.
659 @param FileNameToken A string representing a token in the path name.
661 @return UINTN The number of leading dot in the name.
666 IN CONST CHAR16
* FileNameToken
672 while (*FileNameToken
== L
'.') {
681 IsFileNameTokenValid (
682 IN CONST CHAR16
* FileNameToken
686 if (StrStr (FileNameToken
, L
"/") != NULL
) {
688 // No L'/' in file name.
693 // If Token has all dot, the number should not exceed 2
695 Num
= CountLeadingDots (FileNameToken
);
697 if (Num
== StrLen (FileNameToken
)) {
699 // If the FileNameToken only contains a number of L'.'.
711 Return the first string token found in the indirect pointer a String named by FileName.
713 On input, FileName is a indirect pointer pointing to a String.
714 On output, FileName is a updated to point to the next character after the first
715 found L"\" or NULL if there is no L"\" found.
717 @param FileName A indirect pointer pointing to a FileName.
719 @return Token The first string token found before a L"\".
723 GetNextFileNameToken (
724 IN OUT CONST CHAR16
** FileName
730 ASSERT (**FileName
!= L
'\\');
731 ASSERT (**FileName
!= L
'\0');
733 SlashPos
= StrStr (*FileName
, L
"\\");
734 if (SlashPos
== NULL
) {
735 Token
= AllocateCopyPool (StrSize(*FileName
), *FileName
);
738 Offset
= SlashPos
- *FileName
;
739 Token
= AllocateZeroPool ((Offset
+ 1) * sizeof (CHAR16
));
740 StrnCpy (Token
, *FileName
, Offset
);
742 // Point *FileName to the next character after L'\'.
744 *FileName
= *FileName
+ Offset
+ 1;
746 // If *FileName is an empty string, then set *FileName to NULL
748 if (**FileName
== L
'\0') {
757 Check if a FileName contains only Valid Characters.
759 If FileName contains only a single L'\', return TRUE.
760 If FileName contains two adjacent L'\', return FALSE.
761 If FileName conatins L'/' , return FALSE.
762 If FielName contains more than two dots seperated with other FileName characters
763 by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
765 @param FileName The File Name String to check.
767 @return TRUE FileName only contains valid characters.
768 @return FALSE FileName contains at least one invalid character.
774 IN CONST CHAR16
*FileName
781 // If FileName is just L'\', then it is a valid pathname.
783 if (StrCmp (FileName
, L
"\\") == 0) {
787 // We don't support two or more adjacent L'\'.
789 if (StrStr (FileName
, L
"\\\\") != NULL
) {
794 // Is FileName has a leading L"\", skip to next character.
796 if (FileName
[0] == L
'\\') {
801 Token
= GetNextFileNameToken (&FileName
);
802 Valid
= IsFileNameTokenValid (Token
);
807 } while (FileName
!= NULL
);
814 WinNtSimpleFileSystemOpen (
815 IN EFI_FILE_PROTOCOL
*This
,
816 OUT EFI_FILE_PROTOCOL
**NewHandle
,
825 Open a file relative to the source file location.
829 This - A pointer to the source file location.
831 NewHandle - Pointer to storage for the new file handle.
833 FileName - Pointer to the file name to be opened.
835 OpenMode - File open mode information.
837 Attributes - File creation attributes.
841 EFI_SUCCESS - The file was opened.
843 EFI_NOT_FOUND - The file could not be found in the volume.
845 EFI_NO_MEDIA - The device has no media.
847 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
849 EFI_DEVICE_ERROR - The device reported an error.
851 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
853 EFI_WRITE_PROTECTED - The volume or file is write protected.
855 EFI_ACCESS_DENIED - The service denied access to the file.
857 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
859 EFI_VOLUME_FULL - There is not enough space left to create the new file.
862 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
863 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
864 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
865 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
867 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
868 WIN_NT_EFI_FILE_PRIVATE
*NewPrivateFile
;
869 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
871 CHAR16
*RealFileName
;
872 CHAR16
*TempFileName
;
873 CHAR16
*ParseFileName
;
874 CHAR16
*GuardPointer
;
884 // Check for obvious invalid parameters.
886 if (This
== NULL
|| NewHandle
== NULL
|| FileName
== NULL
) {
887 return EFI_INVALID_PARAMETER
;
891 case EFI_FILE_MODE_CREATE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
892 if (Attributes
&~EFI_FILE_VALID_ATTR
) {
893 return EFI_INVALID_PARAMETER
;
896 if (Attributes
& EFI_FILE_READ_ONLY
) {
897 return EFI_INVALID_PARAMETER
;
903 case EFI_FILE_MODE_READ
:
904 case EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
908 return EFI_INVALID_PARAMETER
;
912 // Init local variables
914 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
915 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
916 NewPrivateFile
= NULL
;
919 // Allocate buffer for FileName as the passed in FileName may be read only
921 TempFileName
= AllocatePool (StrSize (FileName
));
922 if (TempFileName
== NULL
) {
923 return EFI_OUT_OF_RESOURCES
;
925 StrCpy (TempFileName
, FileName
);
926 FileName
= TempFileName
;
928 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
929 FileName
[StrLen (FileName
) - 1] = 0;
933 // If file name does not equal to "." or ".." and not trailed with "\..",
934 // then we trim the leading/trailing blanks and trailing dots
936 if (StrCmp (FileName
, L
".") != 0 && StrCmp (FileName
, L
"..") != 0 &&
937 ((StrLen (FileName
) >= 3) ? (StrCmp (&FileName
[StrLen (FileName
) - 3], L
"\\..") != 0) : TRUE
)) {
939 // Trim leading blanks
942 for (TempFileName
= FileName
;
943 *TempFileName
!= 0 && *TempFileName
== L
' ';
947 CutPrefix (FileName
, Count
);
949 // Trim trailing blanks
951 for (TempFileName
= FileName
+ StrLen (FileName
) - 1;
952 TempFileName
>= FileName
&& (*TempFileName
== L
' ');
956 *(TempFileName
+ 1) = 0;
960 // Attempt to open the file
962 NewPrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
963 if (NewPrivateFile
== NULL
) {
964 Status
= EFI_OUT_OF_RESOURCES
;
968 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (WIN_NT_EFI_FILE_PRIVATE
));
970 NewPrivateFile
->FilePath
= AllocatePool (StrSize (PrivateFile
->FileName
));
971 if (NewPrivateFile
->FilePath
== NULL
) {
972 Status
= EFI_OUT_OF_RESOURCES
;
976 if (PrivateFile
->IsDirectoryPath
) {
977 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FileName
);
979 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FilePath
);
982 Size
= StrSize (NewPrivateFile
->FilePath
);
983 Size
+= StrSize (L
"\\");
984 Size
+= StrSize (FileName
);
985 NewPrivateFile
->FileName
= AllocatePool (Size
);
986 if (NewPrivateFile
->FileName
== NULL
) {
987 Status
= EFI_OUT_OF_RESOURCES
;
991 if (*FileName
== L
'\\') {
992 StrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
993 StrCat (NewPrivateFile
->FileName
, L
"\\");
994 StrCat (NewPrivateFile
->FileName
, FileName
+ 1);
996 StrCpy (NewPrivateFile
->FileName
, NewPrivateFile
->FilePath
);
997 if (StrCmp (FileName
, L
"") != 0) {
999 // In case the filename becomes empty, especially after trimming dots and blanks
1001 StrCat (NewPrivateFile
->FileName
, L
"\\");
1002 StrCat (NewPrivateFile
->FileName
, FileName
);
1006 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
1007 Status
= EFI_NOT_FOUND
;
1012 // Get rid of . and .., except leading . or ..
1016 // GuardPointer protect simplefilesystem root path not be destroyed
1018 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
1022 while (!LoopFinish
) {
1026 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
1027 if (*ParseFileName
== L
'.' &&
1028 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
1029 *(ParseFileName
- 1) == L
'\\'
1035 CutPrefix (ParseFileName
- 1, 2);
1040 if (*ParseFileName
== L
'.' &&
1041 *(ParseFileName
+ 1) == L
'.' &&
1042 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
1043 *(ParseFileName
- 1) == L
'\\'
1049 while (ParseFileName
!= GuardPointer
) {
1052 if (*ParseFileName
== L
'\\') {
1058 // cut \.. and its left directory
1060 CutPrefix (ParseFileName
, Count
);
1067 RealFileName
= NewPrivateFile
->FileName
;
1068 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
1069 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
1073 if (RealFileName
!= NewPrivateFile
->FileName
) {
1074 TempChar
= *(RealFileName
- 1);
1075 *(RealFileName
- 1) = 0;
1078 FreePool (NewPrivateFile
->FilePath
);
1079 NewPrivateFile
->FilePath
= NULL
;
1080 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
1081 if (NewPrivateFile
->FilePath
== NULL
) {
1082 Status
= EFI_OUT_OF_RESOURCES
;
1086 StrCpy (NewPrivateFile
->FilePath
, NewPrivateFile
->FileName
);
1087 if (TempChar
!= 0) {
1088 *(RealFileName
- 1) = TempChar
;
1091 NewPrivateFile
->IsRootDirectory
= FALSE
;
1094 // Test whether file or directory
1096 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
1097 if (Attributes
& EFI_FILE_DIRECTORY
) {
1098 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1100 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1103 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1104 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1105 NewPrivateFile
->FileName
,
1107 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1114 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1115 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1116 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1118 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1121 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1124 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
1125 NewPrivateFile
->IsOpenedByRead
= FALSE
;
1127 NewPrivateFile
->IsOpenedByRead
= TRUE
;
1130 Status
= EFI_SUCCESS
;
1133 // deal with directory
1135 if (NewPrivateFile
->IsDirectoryPath
) {
1137 Size
= StrSize (NewPrivateFile
->FileName
);
1138 Size
+= StrSize (L
"\\*");
1139 TempFileName
= AllocatePool (Size
);
1140 if (TempFileName
== NULL
) {
1141 Status
= EFI_OUT_OF_RESOURCES
;
1145 StrCpy (TempFileName
, NewPrivateFile
->FileName
);
1147 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
1149 // Create a directory
1151 if (!NewPrivateFile
->WinNtThunk
->CreateDirectory (TempFileName
, NULL
)) {
1153 LastError
= PrivateFile
->WinNtThunk
->GetLastError ();
1154 if (LastError
!= ERROR_ALREADY_EXISTS
) {
1155 FreePool (TempFileName
);
1156 Status
= EFI_ACCESS_DENIED
;
1162 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1164 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
1165 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1168 FILE_FLAG_BACKUP_SEMANTICS
,
1172 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
1174 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1177 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1180 FILE_FLAG_BACKUP_SEMANTICS
,
1184 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1185 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->DirHandle
);
1186 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1187 Status
= EFI_ACCESS_DENIED
;
1189 Status
= EFI_NOT_FOUND
;
1192 FreePool (TempFileName
);
1197 // Find the first file under it
1199 StrCat (TempFileName
, L
"\\*");
1200 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
1201 FreePool (TempFileName
);
1203 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1204 NewPrivateFile
->IsValidFindBuf
= FALSE
;
1206 NewPrivateFile
->IsValidFindBuf
= TRUE
;
1212 if (!NewPrivateFile
->IsOpenedByRead
) {
1213 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1214 NewPrivateFile
->FileName
,
1215 GENERIC_READ
| GENERIC_WRITE
,
1216 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1218 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
1223 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1224 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1225 NewPrivateFile
->FileName
,
1227 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1234 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1235 Status
= EFI_NOT_FOUND
;
1237 Status
= EFI_ACCESS_DENIED
;
1238 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1239 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1243 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1244 NewPrivateFile
->FileName
,
1246 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1253 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1254 Status
= EFI_NOT_FOUND
;
1259 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
1261 // Set the attribute
1266 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1268 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1269 Status
= EFI_DEVICE_ERROR
;
1273 Info
= AllocatePool (InfoSize
);
1275 Status
= EFI_OUT_OF_RESOURCES
;
1279 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1281 if (EFI_ERROR (Status
)) {
1286 Info
->Attribute
= Attributes
;
1288 WinNtSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
1293 FreePool (FileName
);
1295 if (EFI_ERROR (Status
)) {
1296 if (NewPrivateFile
) {
1297 if (NewPrivateFile
->FileName
) {
1298 FreePool (NewPrivateFile
->FileName
);
1301 if (NewPrivateFile
->FilePath
) {
1302 FreePool (NewPrivateFile
->FilePath
);
1305 FreePool (NewPrivateFile
);
1308 *NewHandle
= &NewPrivateFile
->EfiFile
;
1309 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
1310 NewPrivateFile
->IsRootDirectory
= TRUE
;
1319 WinNtSimpleFileSystemClose (
1320 IN EFI_FILE_PROTOCOL
*This
1324 Routine Description:
1326 Close the specified file handle.
1330 This - Pointer to a returned opened file handle.
1334 EFI_SUCCESS - The file handle has been closed.
1337 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1339 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1343 return EFI_INVALID_PARAMETER
;
1346 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1348 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1350 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1351 if (PrivateFile
->IsDirectoryPath
) {
1352 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1354 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1357 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1360 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1361 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1362 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1365 if (PrivateFile
->FileName
) {
1366 FreePool (PrivateFile
->FileName
);
1369 if (PrivateFile
->FilePath
) {
1370 FreePool (PrivateFile
->FilePath
);
1373 FreePool (PrivateFile
);
1375 gBS
->RestoreTPL (OldTpl
);
1382 WinNtSimpleFileSystemDelete (
1383 IN EFI_FILE_PROTOCOL
*This
1387 Routine Description:
1389 Close and delete a file.
1393 This - Pointer to a returned opened file handle.
1397 EFI_SUCCESS - The file handle was closed and deleted.
1399 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1402 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1405 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1409 return EFI_INVALID_PARAMETER
;
1412 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1414 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1416 Status
= EFI_WARN_DELETE_FAILURE
;
1418 if (PrivateFile
->IsDirectoryPath
) {
1419 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1420 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1423 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1424 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1425 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1428 if (PrivateFile
->WinNtThunk
->RemoveDirectory (PrivateFile
->FileName
)) {
1429 Status
= EFI_SUCCESS
;
1432 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1433 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1435 if (!PrivateFile
->IsOpenedByRead
) {
1436 if (PrivateFile
->WinNtThunk
->DeleteFile (PrivateFile
->FileName
)) {
1437 Status
= EFI_SUCCESS
;
1442 FreePool (PrivateFile
->FileName
);
1443 FreePool (PrivateFile
->FilePath
);
1444 FreePool (PrivateFile
);
1446 gBS
->RestoreTPL (OldTpl
);
1452 WinNtSystemTimeToEfiTime (
1453 IN SYSTEMTIME
*SystemTime
,
1454 IN TIME_ZONE_INFORMATION
*TimeZone
,
1459 Routine Description:
1461 TODO: Add function description
1465 SystemTime - TODO: add argument description
1466 TimeZone - TODO: add argument description
1467 Time - TODO: add argument description
1471 TODO: add return values
1475 Time
->Year
= (UINT16
) SystemTime
->wYear
;
1476 Time
->Month
= (UINT8
) SystemTime
->wMonth
;
1477 Time
->Day
= (UINT8
) SystemTime
->wDay
;
1478 Time
->Hour
= (UINT8
) SystemTime
->wHour
;
1479 Time
->Minute
= (UINT8
) SystemTime
->wMinute
;
1480 Time
->Second
= (UINT8
) SystemTime
->wSecond
;
1481 Time
->Nanosecond
= (UINT32
) SystemTime
->wMilliseconds
* 1000000;
1482 Time
->TimeZone
= (INT16
) TimeZone
->Bias
;
1484 if (TimeZone
->StandardDate
.wMonth
) {
1485 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1490 Convert the FileTime to EfiTime.
1492 @param PrivateFile Pointer to WIN_NT_EFI_FILE_PRIVATE.
1493 @param TimeZone Pointer to the current time zone.
1494 @param FileTime Pointer to file time.
1495 @param EfiTime Pointer to EFI time.
1498 WinNtFileTimeToEfiTime (
1499 IN CONST WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1500 IN TIME_ZONE_INFORMATION
*TimeZone
,
1501 IN CONST FILETIME
*FileTime
,
1502 OUT EFI_TIME
*EfiTime
1505 FILETIME TempFileTime
;
1506 SYSTEMTIME SystemTime
;
1508 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (FileTime
, &TempFileTime
);
1509 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&TempFileTime
, &SystemTime
);
1510 WinNtSystemTimeToEfiTime (&SystemTime
, TimeZone
, EfiTime
);
1515 WinNtSimpleFileSystemRead (
1516 IN EFI_FILE_PROTOCOL
*This
,
1517 IN OUT UINTN
*BufferSize
,
1522 Routine Description:
1524 Read data from a file.
1528 This - Pointer to a returned open file handle.
1530 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1532 Buffer - Pointer to the first byte of the read Buffer.
1536 EFI_SUCCESS - The data was read.
1538 EFI_NO_MEDIA - The device has no media.
1540 EFI_DEVICE_ERROR - The device reported an error.
1542 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1544 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1545 *BufferSize has been updated with the size needed to complete the request.
1548 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1550 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1556 EFI_FILE_INFO
*Info
;
1558 TIME_ZONE_INFORMATION TimeZone
;
1559 EFI_FILE_INFO
*FileInfo
;
1565 if (This
== NULL
|| BufferSize
== NULL
) {
1566 return EFI_INVALID_PARAMETER
;
1569 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1571 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1573 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1574 Status
= EFI_DEVICE_ERROR
;
1578 if (!PrivateFile
->IsDirectoryPath
) {
1580 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1581 Status
= EFI_DEVICE_ERROR
;
1585 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1586 FileInfo
= AllocatePool (FileInfoSize
);
1588 Status
= This
->GetInfo (
1595 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1596 FreePool (FileInfo
);
1597 FileInfo
= AllocatePool (FileInfoSize
);
1598 Status
= This
->GetInfo (
1606 if (EFI_ERROR (Status
)) {
1607 Status
= EFI_DEVICE_ERROR
;
1611 FileSize
= FileInfo
->FileSize
;
1613 FreePool (FileInfo
);
1615 if (Pos
>= FileSize
) {
1617 if (Pos
== FileSize
) {
1618 Status
= EFI_SUCCESS
;
1621 Status
= EFI_DEVICE_ERROR
;
1626 Status
= PrivateFile
->WinNtThunk
->ReadFile (
1627 PrivateFile
->LHandle
,
1630 (LPDWORD
)BufferSize
,
1632 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1637 // Read on a directory. Perform a find next
1639 if (!PrivateFile
->IsValidFindBuf
) {
1641 Status
= EFI_SUCCESS
;
1645 Size
= SIZE_OF_EFI_FILE_INFO
;
1647 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1649 ResultSize
= Size
+ NameSize
;
1651 Status
= EFI_BUFFER_TOO_SMALL
;
1653 if (*BufferSize
>= ResultSize
) {
1654 Status
= EFI_SUCCESS
;
1657 ZeroMem (Info
, ResultSize
);
1659 Info
->Size
= ResultSize
;
1661 PrivateFile
->WinNtThunk
->GetTimeZoneInformation (&TimeZone
);
1662 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftCreationTime
, &Info
->CreateTime
);
1663 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastAccessTime
, &Info
->LastAccessTime
);
1664 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &PrivateFile
->FindBuf
.ftLastWriteTime
, &Info
->ModificationTime
);
1666 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1668 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1670 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1671 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1674 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1675 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1678 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1679 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1682 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1683 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1686 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1687 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1690 NameSize
= NameSize
/ sizeof (WCHAR
);
1692 pw
= (WCHAR
*) (((CHAR8
*) Buffer
) + Size
);
1694 for (Index
= 0; Index
< NameSize
; Index
++) {
1695 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1698 if (PrivateFile
->WinNtThunk
->FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1699 PrivateFile
->IsValidFindBuf
= TRUE
;
1701 PrivateFile
->IsValidFindBuf
= FALSE
;
1705 *BufferSize
= ResultSize
;
1708 gBS
->RestoreTPL (OldTpl
);
1714 WinNtSimpleFileSystemWrite (
1715 IN EFI_FILE_PROTOCOL
*This
,
1716 IN OUT UINTN
*BufferSize
,
1721 Routine Description:
1723 Write data to a file.
1727 This - Pointer to an opened file handle.
1729 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1730 of data written to the file.
1732 Buffer - Pointer to the first by of data in the buffer to write to the file.
1736 EFI_SUCCESS - The data was written to the file.
1738 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1740 EFI_NO_MEDIA - The device has no media.
1742 EFI_DEVICE_ERROR - The device reported an error.
1744 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1746 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1748 EFI_ACCESS_DENIED - The file was opened read-only.
1750 EFI_VOLUME_FULL - The volume is full.
1753 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1755 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1759 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1760 return EFI_INVALID_PARAMETER
;
1763 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1765 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1767 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1768 Status
= EFI_DEVICE_ERROR
;
1772 if (PrivateFile
->IsDirectoryPath
) {
1773 Status
= EFI_UNSUPPORTED
;
1777 if (PrivateFile
->IsOpenedByRead
) {
1778 Status
= EFI_ACCESS_DENIED
;
1782 Status
= PrivateFile
->WinNtThunk
->WriteFile (
1783 PrivateFile
->LHandle
,
1786 (LPDWORD
)BufferSize
,
1788 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1791 gBS
->RestoreTPL (OldTpl
);
1795 // bugbug: need to access windows error reporting
1801 WinNtSimpleFileSystemSetPosition (
1802 IN EFI_FILE_PROTOCOL
*This
,
1807 Routine Description:
1809 Set a file's current position.
1813 This - Pointer to an opened file handle.
1815 Position - The byte position from the start of the file to set.
1819 EFI_SUCCESS - The file position has been changed.
1821 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1824 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1827 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1835 return EFI_INVALID_PARAMETER
;
1838 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1840 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1842 if (PrivateFile
->IsDirectoryPath
) {
1843 if (Position
!= 0) {
1844 Status
= EFI_UNSUPPORTED
;
1848 Size
= StrSize (PrivateFile
->FileName
);
1849 Size
+= StrSize (L
"\\*");
1850 FileName
= AllocatePool (Size
);
1851 if (FileName
== NULL
) {
1852 Status
= EFI_OUT_OF_RESOURCES
;
1856 StrCpy (FileName
, PrivateFile
->FileName
);
1857 StrCat (FileName
, L
"\\*");
1859 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1860 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1863 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1865 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1866 PrivateFile
->IsValidFindBuf
= FALSE
;
1868 PrivateFile
->IsValidFindBuf
= TRUE
;
1871 FreePool (FileName
);
1873 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1875 if (Position
== (UINT64
) -1) {
1876 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) 0, NULL
, FILE_END
);
1878 PosHigh
= (UINT32
) RShiftU64 (Position
, 32);
1880 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) Position
, (PLONG
)&PosHigh
, FILE_BEGIN
);
1883 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1887 gBS
->RestoreTPL (OldTpl
);
1893 WinNtSimpleFileSystemGetPosition (
1894 IN EFI_FILE_PROTOCOL
*This
,
1895 OUT UINT64
*Position
1899 Routine Description:
1901 Get a file's current position.
1905 This - Pointer to an opened file handle.
1907 Position - Pointer to storage for the current position.
1911 EFI_SUCCESS - The file position has been reported.
1913 EFI_UNSUPPORTED - Not valid for directories.
1916 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1919 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1924 if (This
== NULL
|| Position
== NULL
) {
1925 return EFI_INVALID_PARAMETER
;
1928 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1929 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1934 if (PrivateFile
->IsDirectoryPath
) {
1936 Status
= EFI_UNSUPPORTED
;
1942 *Position
= PrivateFile
->WinNtThunk
->SetFilePointer (
1943 PrivateFile
->LHandle
,
1945 (PLONG
)&PositionHigh
,
1949 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1950 if (EFI_ERROR (Status
)) {
1954 PosHigh64
= PositionHigh
;
1955 *Position
+= LShiftU64 (PosHigh64
, 32);
1959 gBS
->RestoreTPL (OldTpl
);
1964 WinNtSimpleFileSystemFileInfo (
1965 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1966 IN OUT UINTN
*BufferSize
,
1971 Routine Description:
1973 TODO: Add function description
1977 PrivateFile - TODO: add argument description
1978 BufferSize - TODO: add argument description
1979 Buffer - TODO: add argument description
1983 TODO: add return values
1991 EFI_FILE_INFO
*Info
;
1992 BY_HANDLE_FILE_INFORMATION FileInfo
;
1993 CHAR16
*RealFileName
;
1994 CHAR16
*TempPointer
;
1995 TIME_ZONE_INFORMATION TimeZone
;
1997 Size
= SIZE_OF_EFI_FILE_INFO
;
1999 RealFileName
= PrivateFile
->FileName
;
2000 TempPointer
= RealFileName
;
2001 while (*TempPointer
) {
2002 if (*TempPointer
== '\\') {
2003 RealFileName
= TempPointer
+ 1;
2008 NameSize
= StrSize (RealFileName
);
2010 ResultSize
= Size
+ NameSize
;
2012 Status
= EFI_BUFFER_TOO_SMALL
;
2013 if (*BufferSize
>= ResultSize
) {
2014 Status
= EFI_SUCCESS
;
2017 ZeroMem (Info
, ResultSize
);
2019 Info
->Size
= ResultSize
;
2020 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (
2021 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2024 Info
->FileSize
= FileInfo
.nFileSizeLow
;
2025 Info
->PhysicalSize
= Info
->FileSize
;
2027 PrivateFile
->WinNtThunk
->GetTimeZoneInformation (&TimeZone
);
2028 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftCreationTime
, &Info
->CreateTime
);
2029 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastAccessTime
, &Info
->LastAccessTime
);
2030 WinNtFileTimeToEfiTime (PrivateFile
, &TimeZone
, &FileInfo
.ftLastWriteTime
, &Info
->ModificationTime
);
2032 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
2033 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
2036 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
2037 Info
->Attribute
|= EFI_FILE_HIDDEN
;
2040 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2041 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
2044 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
2045 Info
->Attribute
|= EFI_FILE_SYSTEM
;
2048 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2049 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2052 if (PrivateFile
->IsDirectoryPath
) {
2053 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2056 if (PrivateFile
->IsRootDirectory
) {
2057 *((CHAR8
*) Buffer
+ Size
) = 0;
2059 CopyMem ((CHAR8
*) Buffer
+ Size
, RealFileName
, NameSize
);
2063 *BufferSize
= ResultSize
;
2069 WinNtSimpleFileSystemGetInfo (
2070 IN EFI_FILE_PROTOCOL
*This
,
2071 IN EFI_GUID
*InformationType
,
2072 IN OUT UINTN
*BufferSize
,
2077 Routine Description:
2079 Return information about a file or volume.
2083 This - Pointer to an opened file handle.
2085 InformationType - GUID describing the type of information to be returned.
2087 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
2090 Buffer - Pointer to the first byte of the information buffer.
2094 EFI_SUCCESS - The requested information has been written into the buffer.
2096 EFI_UNSUPPORTED - The InformationType is not known.
2098 EFI_NO_MEDIA - The device has no media.
2100 EFI_DEVICE_ERROR - The device reported an error.
2102 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2104 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
2105 been updated with the size needed to complete the requested operation.
2108 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2111 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2112 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
2113 UINT32 SectorsPerCluster
;
2114 UINT32 BytesPerSector
;
2115 UINT32 FreeClusters
;
2116 UINT32 TotalClusters
;
2117 UINT32 BytesPerCluster
;
2119 BOOLEAN DriveNameFound
;
2122 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2125 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
2126 return EFI_INVALID_PARAMETER
;
2129 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2131 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2132 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2134 Status
= EFI_UNSUPPORTED
;
2136 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2137 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
2140 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2141 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2142 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2143 Status
= EFI_BUFFER_TOO_SMALL
;
2147 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2148 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2149 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
2152 // Try to get the drive name
2154 DriveNameFound
= FALSE
;
2155 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
2156 if (DriveName
== NULL
) {
2157 Status
= EFI_OUT_OF_RESOURCES
;
2161 StrCpy (DriveName
, PrivateFile
->FilePath
);
2162 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
2166 if (DriveName
[Index
] == ':') {
2167 DriveName
[Index
+ 1] = '\\';
2168 DriveName
[Index
+ 2] = 0;
2169 DriveNameFound
= TRUE
;
2170 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
2171 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2175 if (DriveName
[Index
] == '\\') {
2176 DriveNameFound
= TRUE
;
2177 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2181 DriveName
[Index
] = '\\';
2182 DriveName
[Index
+ 1] = 0;
2187 // Try GetDiskFreeSpace first
2189 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpace (
2190 DriveNameFound
? DriveName
: NULL
,
2191 (LPDWORD
)&SectorsPerCluster
,
2192 (LPDWORD
)&BytesPerSector
,
2193 (LPDWORD
)&FreeClusters
,
2194 (LPDWORD
)&TotalClusters
2197 FreePool (DriveName
);
2204 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
2205 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
2206 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
2207 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
2211 // try GetDiskFreeSpaceEx then
2213 FileSystemInfoBuffer
->BlockSize
= 0;
2214 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpaceEx (
2215 PrivateFile
->FilePath
,
2216 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->FreeSpace
),
2217 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->VolumeSize
),
2221 Status
= EFI_DEVICE_ERROR
;
2226 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
2227 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2228 Status
= EFI_SUCCESS
;
2231 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2232 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2233 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2234 Status
= EFI_BUFFER_TOO_SMALL
;
2238 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
2239 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2240 Status
= EFI_SUCCESS
;
2244 gBS
->RestoreTPL (OldTpl
);
2250 WinNtSimpleFileSystemSetInfo (
2251 IN EFI_FILE_PROTOCOL
*This
,
2252 IN EFI_GUID
*InformationType
,
2253 IN UINTN BufferSize
,
2258 Routine Description:
2260 Set information about a file or volume.
2264 This - Pointer to an opened file handle.
2266 InformationType - GUID identifying the type of information to set.
2268 BufferSize - Number of bytes of data in the information buffer.
2270 Buffer - Pointer to the first byte of data in the information buffer.
2274 EFI_SUCCESS - The file or volume information has been updated.
2276 EFI_UNSUPPORTED - The information identifier is not recognised.
2278 EFI_NO_MEDIA - The device has no media.
2280 EFI_DEVICE_ERROR - The device reported an error.
2282 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2284 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2286 EFI_ACCESS_DENIED - The file was opened read-only.
2288 EFI_VOLUME_FULL - The volume is full.
2290 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2293 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2294 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2296 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2297 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2298 EFI_FILE_INFO
*OldFileInfo
;
2299 EFI_FILE_INFO
*NewFileInfo
;
2305 CHAR16
*OldFileName
;
2306 CHAR16
*NewFileName
;
2307 CHAR16
*TempFileName
;
2308 CHAR16
*CharPointer
;
2309 BOOLEAN AttrChangeFlag
;
2310 BOOLEAN NameChangeFlag
;
2311 BOOLEAN SizeChangeFlag
;
2312 BOOLEAN TimeChangeFlag
;
2314 SYSTEMTIME NewCreationSystemTime
;
2315 SYSTEMTIME NewLastAccessSystemTime
;
2316 SYSTEMTIME NewLastWriteSystemTime
;
2317 FILETIME NewCreationFileTime
;
2318 FILETIME NewLastAccessFileTime
;
2319 FILETIME NewLastWriteFileTime
;
2320 WIN32_FIND_DATA FindBuf
;
2321 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
2326 // Check for invalid parameters.
2328 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
2329 return EFI_INVALID_PARAMETER
;
2332 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2335 // Initialise locals.
2337 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2338 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2340 Status
= EFI_UNSUPPORTED
;
2341 OldFileInfo
= NewFileInfo
= NULL
;
2342 OldFileName
= NewFileName
= NULL
;
2343 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
2346 // Set file system information.
2348 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2349 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2350 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (NewFileSystemInfo
->VolumeLabel
)) {
2351 Status
= EFI_BAD_BUFFER_SIZE
;
2356 FreePool (PrivateRoot
->VolumeLabel
);
2357 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
2358 if (PrivateRoot
->VolumeLabel
== NULL
) {
2359 Status
= EFI_OUT_OF_RESOURCES
;
2363 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
2365 Status
= EFI_SUCCESS
;
2370 // Set volume label information.
2372 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2373 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2374 Status
= EFI_BAD_BUFFER_SIZE
;
2378 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
2380 Status
= EFI_SUCCESS
;
2384 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2385 Status
= EFI_UNSUPPORTED
;
2389 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
2390 Status
= EFI_BAD_BUFFER_SIZE
;
2395 // Set file/directory information.
2399 // Check for invalid set file information parameters.
2401 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
2403 if ((NewFileInfo
->Size
<= SIZE_OF_EFI_FILE_INFO
) ||
2404 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
2405 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
2407 Status
= EFI_INVALID_PARAMETER
;
2412 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2413 // that would have an additional parameter that would be the size
2414 // of the string array just in case there are no NULL characters in
2415 // the string array.
2418 // Get current file information so we can determine what kind
2419 // of change request this is.
2422 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
2424 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2425 Status
= EFI_DEVICE_ERROR
;
2429 OldFileInfo
= AllocatePool (OldInfoSize
);
2430 if (OldFileInfo
== NULL
) {
2431 Status
= EFI_OUT_OF_RESOURCES
;
2435 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
2437 if (EFI_ERROR (Status
)) {
2441 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
2442 if (OldFileName
== NULL
) {
2443 Status
= EFI_OUT_OF_RESOURCES
;
2447 StrCpy (OldFileName
, PrivateFile
->FileName
);
2450 // Make full pathname from new filename and rootpath.
2452 if (NewFileInfo
->FileName
[0] == '\\') {
2453 Size
= StrSize (PrivateRoot
->FilePath
);
2454 Size
+= StrSize (L
"\\");
2455 Size
+= StrSize (NewFileInfo
->FileName
);
2456 NewFileName
= AllocatePool (Size
);
2457 if (NewFileName
== NULL
) {
2458 Status
= EFI_OUT_OF_RESOURCES
;
2462 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
2463 StrCat (NewFileName
, L
"\\");
2464 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
2466 Size
= StrSize (PrivateFile
->FilePath
);
2467 Size
+= StrSize (L
"\\");
2468 Size
+= StrSize (NewFileInfo
->FileName
);
2469 NewFileName
= AllocatePool (Size
);
2470 if (NewFileName
== NULL
) {
2471 Status
= EFI_OUT_OF_RESOURCES
;
2475 StrCpy (NewFileName
, PrivateFile
->FilePath
);
2476 StrCat (NewFileName
, L
"\\");
2477 StrCat (NewFileName
, NewFileInfo
->FileName
);
2481 // Is there an attribute change request?
2483 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
2484 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
2485 Status
= EFI_INVALID_PARAMETER
;
2489 AttrChangeFlag
= TRUE
;
2493 // Is there a name change request?
2494 // bugbug: - Need EfiStrCaseCmp()
2496 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
2497 NameChangeFlag
= TRUE
;
2501 // Is there a size change request?
2503 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
2504 SizeChangeFlag
= TRUE
;
2508 // Is there a time stamp change request?
2510 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
2511 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
2513 TimeChangeFlag
= TRUE
;
2514 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
2515 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
2517 TimeChangeFlag
= TRUE
;
2518 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
2519 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
2521 TimeChangeFlag
= TRUE
;
2525 // All done if there are no change requests being made.
2527 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
2528 Status
= EFI_SUCCESS
;
2533 // Set file or directory information.
2535 OldAttr
= PrivateFile
->WinNtThunk
->GetFileAttributes (OldFileName
);
2540 if (NameChangeFlag
) {
2542 // Close the handles first
2544 if (PrivateFile
->IsOpenedByRead
) {
2545 Status
= EFI_ACCESS_DENIED
;
2549 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
2552 if (*CharPointer
!= 0) {
2553 Status
= EFI_ACCESS_DENIED
;
2557 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
2558 if (PrivateFile
->IsDirectoryPath
) {
2559 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
2561 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
2562 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
2566 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
2567 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
2568 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
2571 NtStatus
= PrivateFile
->WinNtThunk
->MoveFile (OldFileName
, NewFileName
);
2577 FreePool (PrivateFile
->FileName
);
2579 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
2580 if (PrivateFile
->FileName
== NULL
) {
2581 Status
= EFI_OUT_OF_RESOURCES
;
2585 StrCpy (PrivateFile
->FileName
, NewFileName
);
2587 Size
= StrSize (NewFileName
);
2588 Size
+= StrSize (L
"\\*");
2589 TempFileName
= AllocatePool (Size
);
2591 StrCpy (TempFileName
, NewFileName
);
2593 if (!PrivateFile
->IsDirectoryPath
) {
2594 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2596 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2597 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2604 FreePool (TempFileName
);
2607 // Flush buffers just in case
2609 if (PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2610 Status
= EFI_DEVICE_ERROR
;
2614 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2616 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2617 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2620 FILE_FLAG_BACKUP_SEMANTICS
,
2624 StrCat (TempFileName
, L
"\\*");
2625 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2627 FreePool (TempFileName
);
2630 Status
= EFI_ACCESS_DENIED
;
2633 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (OldFileName
, OldAttr
);
2639 Size
= StrSize (OldFileName
);
2640 Size
+= StrSize (L
"\\*");
2641 TempFileName
= AllocatePool (Size
);
2643 StrCpy (TempFileName
, OldFileName
);
2645 if (!PrivateFile
->IsDirectoryPath
) {
2646 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2648 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2649 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2656 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2658 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2659 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2662 FILE_FLAG_BACKUP_SEMANTICS
,
2666 StrCat (TempFileName
, L
"\\*");
2667 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2670 FreePool (TempFileName
);
2680 if (SizeChangeFlag
) {
2681 if (PrivateFile
->IsDirectoryPath
) {
2682 Status
= EFI_UNSUPPORTED
;
2686 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2687 Status
= EFI_ACCESS_DENIED
;
2691 Status
= This
->GetPosition (This
, &CurPos
);
2692 if (EFI_ERROR (Status
)) {
2696 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2697 if (EFI_ERROR (Status
)) {
2701 if (PrivateFile
->WinNtThunk
->SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2702 Status
= EFI_DEVICE_ERROR
;
2706 Status
= This
->SetPosition (This
, CurPos
);
2707 if (EFI_ERROR (Status
)) {
2715 if (TimeChangeFlag
) {
2717 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2718 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2719 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2720 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2721 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2722 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2723 NewCreationSystemTime
.wMilliseconds
= 0;
2725 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2726 &NewCreationSystemTime
,
2727 &NewCreationFileTime
2732 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2733 &NewCreationFileTime
,
2734 &NewCreationFileTime
2739 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2740 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2741 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2742 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2743 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2744 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2745 NewLastAccessSystemTime
.wMilliseconds
= 0;
2747 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2748 &NewLastAccessSystemTime
,
2749 &NewLastAccessFileTime
2754 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2755 &NewLastAccessFileTime
,
2756 &NewLastAccessFileTime
2761 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2762 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2763 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2764 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2765 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2766 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2767 NewLastWriteSystemTime
.wMilliseconds
= 0;
2769 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2770 &NewLastWriteSystemTime
,
2771 &NewLastWriteFileTime
2776 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2777 &NewLastWriteFileTime
,
2778 &NewLastWriteFileTime
2783 if (!PrivateFile
->WinNtThunk
->SetFileTime (
2784 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2785 &NewCreationFileTime
,
2786 &NewLastAccessFileTime
,
2787 &NewLastWriteFileTime
2789 Status
= EFI_DEVICE_ERROR
;
2796 // No matter about AttrChangeFlag, Attribute must be set.
2797 // Because operation before may cause attribute change.
2801 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2802 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2804 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2807 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2808 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2810 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2813 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2814 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2816 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2819 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2820 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2822 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2825 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (NewFileName
, NewAttr
);
2828 Status
= EFI_DEVICE_ERROR
;
2833 if (OldFileInfo
!= NULL
) {
2834 FreePool (OldFileInfo
);
2837 if (OldFileName
!= NULL
) {
2838 FreePool (OldFileName
);
2841 if (NewFileName
!= NULL
) {
2842 FreePool (NewFileName
);
2845 gBS
->RestoreTPL (OldTpl
);
2851 WinNtSimpleFileSystemFlush (
2852 IN EFI_FILE_PROTOCOL
*This
2856 Routine Description:
2858 Flush all modified data to the media.
2862 This - Pointer to an opened file handle.
2866 EFI_SUCCESS - The data has been flushed.
2868 EFI_NO_MEDIA - The device has no media.
2870 EFI_DEVICE_ERROR - The device reported an error.
2872 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2874 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2876 EFI_ACCESS_DENIED - The file was opened read-only.
2878 EFI_VOLUME_FULL - The volume is full.
2881 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2883 BY_HANDLE_FILE_INFORMATION FileInfo
;
2884 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2889 return EFI_INVALID_PARAMETER
;
2892 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2894 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2896 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2897 Status
= EFI_DEVICE_ERROR
;
2901 if (PrivateFile
->IsDirectoryPath
) {
2902 Status
= EFI_SUCCESS
;
2906 if (PrivateFile
->IsOpenedByRead
) {
2907 Status
= EFI_ACCESS_DENIED
;
2911 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2913 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2914 Status
= EFI_ACCESS_DENIED
;
2918 Status
= PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2921 gBS
->RestoreTPL (OldTpl
);
2924 // bugbug: - Use Windows error reporting.