3 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
4 This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
14 WinNtSimpleFileSystem.c
18 Produce Simple File System abstractions for directories on your PC using Win32 APIs.
19 The configuration of what devices to mount or emulate comes from NT
20 environment variables. The variables must be visible to the Microsoft*
21 Developer Studio for them to work.
23 * Other names and brands may be claimed as the property of others.
28 // The package level header files this module uses
33 // The protocols, PPI and GUID defintions for this module
35 #include <Guid/FileSystemVolumeLabelInfo.h>
36 #include <Protocol/WinNtIo.h>
37 #include <Protocol/ComponentName.h>
38 #include <Guid/FileInfo.h>
39 #include <Protocol/DriverBinding.h>
40 #include <Guid/FileSystemInfo.h>
41 #include <Protocol/SimpleFileSystem.h>
43 // The Library classes this module consumes
45 #include <Library/DebugLib.h>
46 #include <Library/BaseLib.h>
47 #include <Library/UefiDriverEntryPoint.h>
48 #include <Library/UefiLib.h>
49 #include <Library/BaseMemoryLib.h>
50 #include <Library/UefiBootServicesTableLib.h>
51 #include <Library/MemoryAllocationLib.h>
53 #include "WinNtSimpleFileSystem.h"
55 EFI_DRIVER_BINDING_PROTOCOL gWinNtSimpleFileSystemDriverBinding
= {
56 WinNtSimpleFileSystemDriverBindingSupported
,
57 WinNtSimpleFileSystemDriverBindingStart
,
58 WinNtSimpleFileSystemDriverBindingStop
,
65 The user Entry Point for module WinNtSimpleFileSystem. The user code starts with this function.
67 @param[in] ImageHandle The firmware allocated handle for the EFI image.
68 @param[in] SystemTable A pointer to the EFI System Table.
70 @retval EFI_SUCCESS The entry point is executed successfully.
71 @retval other Some error occurs when executing this entry point.
76 InitializeWinNtSimpleFileSystem(
77 IN EFI_HANDLE ImageHandle
,
78 IN EFI_SYSTEM_TABLE
*SystemTable
84 // Install driver model protocol(s).
86 Status
= EfiLibInstallDriverBindingComponentName2 (
89 &gWinNtSimpleFileSystemDriverBinding
,
91 &gWinNtSimpleFileSystemComponentName
,
92 &gWinNtSimpleFileSystemComponentName2
94 ASSERT_EFI_ERROR (Status
);
109 Locate the first occurance of a character in a string.
113 Str - Pointer to NULL terminated unicode string.
114 Chr - Character to locate.
118 If Str is NULL, then NULL is returned.
119 If Chr is not contained in Str, then NULL is returned.
120 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.
128 while (*Str
!= '\0' && *Str
!= Chr
) {
132 return (*Str
== Chr
) ? Str
: NULL
;
144 TODO: Add function description
148 Buffer - TODO: add argument description
149 Length - TODO: add argument description
153 TODO: add return values
157 if (Buffer
== NULL
|| Length
== 0) {
161 if (*(UINT8
*) Buffer
!= 0) {
166 if (!CompareMem (Buffer
, (UINT8
*) Buffer
+ 1, Length
- 1)) {
183 TODO: Add function description
187 Str - TODO: add argument description
188 Count - TODO: add argument description
192 TODO: add return values
198 if (StrLen (Str
) < Count
) {
203 for (Pointer
= Str
; *(Pointer
+ Count
); Pointer
++) {
204 *Pointer
= *(Pointer
+ Count
);
206 *Pointer
= *(Pointer
+ Count
);
214 WinNtSimpleFileSystemDriverBindingSupported (
215 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
216 IN EFI_HANDLE ControllerHandle
,
217 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
223 Check to see if the driver supports a given controller.
227 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
229 ControllerHandle - EFI handle of the controller to test.
231 RemainingDevicePath - Pointer to remaining portion of a device path.
235 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver
238 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
239 the driver specified by This.
241 EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
242 a different driver or an application that requires exclusive access.
244 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the
245 driver specified by This.
250 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
253 // Open the IO Abstraction(s) needed to perform the supported test
255 Status
= gBS
->OpenProtocol (
257 &gEfiWinNtIoProtocolGuid
,
259 This
->DriverBindingHandle
,
261 EFI_OPEN_PROTOCOL_BY_DRIVER
263 if (EFI_ERROR (Status
)) {
268 // Make sure GUID is for a File System handle.
270 Status
= EFI_UNSUPPORTED
;
271 if (CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtFileSystemGuid
)) {
272 Status
= EFI_SUCCESS
;
276 // Close the I/O Abstraction(s) used to perform the supported test
280 &gEfiWinNtIoProtocolGuid
,
281 This
->DriverBindingHandle
,
290 WinNtSimpleFileSystemDriverBindingStart (
291 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
292 IN EFI_HANDLE ControllerHandle
,
293 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
299 Starts a device controller or a bus controller.
303 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
305 ControllerHandle - EFI handle of the controller to start.
307 RemainingDevicePath - Pointer to remaining portion of a device path.
311 EFI_SUCCESS - The device or bus controller has been started.
313 EFI_DEVICE_ERROR - The device could not be started due to a device failure.
315 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
320 EFI_WIN_NT_IO_PROTOCOL
*WinNtIo
;
321 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
326 // Open the IO Abstraction(s) needed
328 Status
= gBS
->OpenProtocol (
330 &gEfiWinNtIoProtocolGuid
,
332 This
->DriverBindingHandle
,
334 EFI_OPEN_PROTOCOL_BY_DRIVER
336 if (EFI_ERROR (Status
)) {
343 if (!CompareGuid (WinNtIo
->TypeGuid
, &gEfiWinNtFileSystemGuid
)) {
344 Status
= EFI_UNSUPPORTED
;
348 Private
= AllocatePool (sizeof (WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
));
349 if (Private
== NULL
) {
350 Status
= EFI_OUT_OF_RESOURCES
;
355 Private
->Signature
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE
;
356 Private
->WinNtThunk
= WinNtIo
->WinNtThunk
;
358 Private
->FilePath
= WinNtIo
->EnvString
;
360 Private
->VolumeLabel
= AllocatePool (StrSize (L
"EFI_EMULATED"));
361 if (Private
->VolumeLabel
== NULL
) {
362 Status
= EFI_OUT_OF_RESOURCES
;
366 StrCpy (Private
->VolumeLabel
, L
"EFI_EMULATED");
368 Private
->SimpleFileSystem
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
369 Private
->SimpleFileSystem
.OpenVolume
= WinNtSimpleFileSystemOpenVolume
;
371 Private
->WinNtThunk
->SetErrorMode (SEM_FAILCRITICALERRORS
);
373 Private
->ControllerNameTable
= NULL
;
377 gWinNtSimpleFileSystemComponentName
.SupportedLanguages
,
378 &Private
->ControllerNameTable
,
384 gWinNtSimpleFileSystemComponentName2
.SupportedLanguages
,
385 &Private
->ControllerNameTable
,
391 Status
= gBS
->InstallMultipleProtocolInterfaces (
393 &gEfiSimpleFileSystemProtocolGuid
,
394 &Private
->SimpleFileSystem
,
399 if (EFI_ERROR (Status
)) {
401 if (Private
!= NULL
) {
403 FreeUnicodeStringTable (Private
->ControllerNameTable
);
410 &gEfiWinNtIoProtocolGuid
,
411 This
->DriverBindingHandle
,
421 WinNtSimpleFileSystemDriverBindingStop (
422 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
423 IN EFI_HANDLE ControllerHandle
,
424 IN UINTN NumberOfChildren
,
425 IN EFI_HANDLE
*ChildHandleBuffer
431 TODO: Add function description
435 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
437 ControllerHandle - A handle to the device to be stopped.
439 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
441 ChildHandleBuffer - An array of child device handles to be freed.
445 EFI_SUCCESS - The device has been stopped.
447 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.
450 // TODO: EFI_UNSUPPORTED - add return value to function comment
453 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*SimpleFileSystem
;
454 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
457 // Get our context back
459 Status
= gBS
->OpenProtocol (
461 &gEfiSimpleFileSystemProtocolGuid
,
462 (VOID
**) &SimpleFileSystem
,
463 This
->DriverBindingHandle
,
465 EFI_OPEN_PROTOCOL_GET_PROTOCOL
467 if (EFI_ERROR (Status
)) {
468 return EFI_UNSUPPORTED
;
471 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem
);
474 // Uninstall the Simple File System Protocol from ControllerHandle
476 Status
= gBS
->UninstallMultipleProtocolInterfaces (
478 &gEfiSimpleFileSystemProtocolGuid
,
479 &Private
->SimpleFileSystem
,
482 if (!EFI_ERROR (Status
)) {
483 Status
= gBS
->CloseProtocol (
485 &gEfiWinNtIoProtocolGuid
,
486 This
->DriverBindingHandle
,
491 if (!EFI_ERROR (Status
)) {
493 // Free our instance data
495 FreeUnicodeStringTable (Private
->ControllerNameTable
);
505 WinNtSimpleFileSystemOpenVolume (
506 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL
*This
,
507 OUT EFI_FILE_PROTOCOL
**Root
513 Open the root directory on a volume.
517 This - A pointer to the volume to open.
519 Root - A pointer to storage for the returned opened file handle of the root directory.
523 EFI_SUCCESS - The volume was opened.
525 EFI_UNSUPPORTED - The volume does not support the requested file system type.
527 EFI_NO_MEDIA - The device has no media.
529 EFI_DEVICE_ERROR - The device reported an error.
531 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
533 EFI_ACCESS_DENIED - The service denied access to the file.
535 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.
537 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
540 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
543 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*Private
;
544 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
546 CHAR16
*TempFileName
;
549 if (This
== NULL
|| Root
== NULL
) {
550 return EFI_INVALID_PARAMETER
;
553 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
555 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
557 PrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
558 if (PrivateFile
== NULL
) {
559 Status
= EFI_OUT_OF_RESOURCES
;
563 PrivateFile
->FileName
= AllocatePool (StrSize (Private
->FilePath
));
564 if (PrivateFile
->FileName
== NULL
) {
565 Status
= EFI_OUT_OF_RESOURCES
;
569 PrivateFile
->FilePath
= AllocatePool (StrSize (Private
->FilePath
));
570 if (PrivateFile
->FilePath
== NULL
) {
571 Status
= EFI_OUT_OF_RESOURCES
;
575 StrCpy (PrivateFile
->FilePath
, Private
->FilePath
);
576 StrCpy (PrivateFile
->FileName
, PrivateFile
->FilePath
);
577 PrivateFile
->Signature
= WIN_NT_EFI_FILE_PRIVATE_SIGNATURE
;
578 PrivateFile
->WinNtThunk
= Private
->WinNtThunk
;
579 PrivateFile
->SimpleFileSystem
= This
;
580 PrivateFile
->IsRootDirectory
= TRUE
;
581 PrivateFile
->IsDirectoryPath
= TRUE
;
582 PrivateFile
->IsOpenedByRead
= TRUE
;
583 PrivateFile
->EfiFile
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
584 PrivateFile
->EfiFile
.Open
= WinNtSimpleFileSystemOpen
;
585 PrivateFile
->EfiFile
.Close
= WinNtSimpleFileSystemClose
;
586 PrivateFile
->EfiFile
.Delete
= WinNtSimpleFileSystemDelete
;
587 PrivateFile
->EfiFile
.Read
= WinNtSimpleFileSystemRead
;
588 PrivateFile
->EfiFile
.Write
= WinNtSimpleFileSystemWrite
;
589 PrivateFile
->EfiFile
.GetPosition
= WinNtSimpleFileSystemGetPosition
;
590 PrivateFile
->EfiFile
.SetPosition
= WinNtSimpleFileSystemSetPosition
;
591 PrivateFile
->EfiFile
.GetInfo
= WinNtSimpleFileSystemGetInfo
;
592 PrivateFile
->EfiFile
.SetInfo
= WinNtSimpleFileSystemSetInfo
;
593 PrivateFile
->EfiFile
.Flush
= WinNtSimpleFileSystemFlush
;
594 PrivateFile
->IsValidFindBuf
= FALSE
;
599 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
600 PrivateFile
->FilePath
,
602 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
605 FILE_FLAG_BACKUP_SEMANTICS
,
609 if (PrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
610 Status
= EFI_NOT_FOUND
;
615 // Find the first file under it
617 Size
= StrSize (PrivateFile
->FilePath
);
618 Size
+= StrSize (L
"\\*");
619 Status
= gBS
->AllocatePool (
622 (VOID
**)&TempFileName
624 if (EFI_ERROR (Status
)) {
627 StrCpy (TempFileName
, PrivateFile
->FilePath
);
628 StrCat (TempFileName
, L
"\\*");
630 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &PrivateFile
->FindBuf
);
631 FreePool (TempFileName
);
633 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
634 PrivateFile
->IsValidFindBuf
= FALSE
;
636 PrivateFile
->IsValidFindBuf
= TRUE
;
638 *Root
= &PrivateFile
->EfiFile
;
640 Status
= EFI_SUCCESS
;
643 if (EFI_ERROR (Status
)) {
645 if (PrivateFile
->FileName
) {
646 FreePool (PrivateFile
->FileName
);
649 if (PrivateFile
->FilePath
) {
650 FreePool (PrivateFile
->FilePath
);
653 FreePool (PrivateFile
);
657 gBS
->RestoreTPL (OldTpl
);
663 Count the number of Leading Dot in FileNameToken.
665 @param FileNameToken A string representing a token in the path name.
667 @return UINTN The number of leading dot in the name.
672 IN CONST CHAR16
* FileNameToken
678 while (*FileNameToken
== L
'.') {
687 IsFileNameTokenValid (
688 IN CONST CHAR16
* FileNameToken
692 if (StrStr (FileNameToken
, L
"/") != NULL
) {
694 // No L'/' in file name.
699 // If Token has all dot, the number should not exceed 2
701 Num
= CountLeadingDots (FileNameToken
);
703 if (Num
== StrLen (FileNameToken
)) {
705 // If the FileNameToken only contains a number of L'.'.
717 Return the first string token found in the indirect pointer a String named by FileName.
719 On input, FileName is a indirect pointer pointing to a String.
720 On output, FileName is a updated to point to the next character after the first
721 found L"\" or NULL if there is no L"\" found.
723 @param FileName A indirect pointer pointing to a FileName.
725 @return Token The first string token found before a L"\".
729 GetNextFileNameToken (
730 IN OUT CONST CHAR16
** FileName
736 ASSERT (**FileName
!= L
'\\');
737 ASSERT (**FileName
!= L
'\0');
739 SlashPos
= StrStr (*FileName
, L
"\\");
740 if (SlashPos
== NULL
) {
741 Token
= AllocateCopyPool (StrSize(*FileName
), *FileName
);
744 Offset
= SlashPos
- *FileName
;
745 Token
= AllocateZeroPool ((Offset
+ 1) * sizeof (CHAR16
));
746 StrnCpy (Token
, *FileName
, Offset
);
748 // Point *FileName to the next character after L'\'.
750 *FileName
= *FileName
+ Offset
+ 1;
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
;
1491 WinNtSimpleFileSystemRead (
1492 IN EFI_FILE_PROTOCOL
*This
,
1493 IN OUT UINTN
*BufferSize
,
1498 Routine Description:
1500 Read data from a file.
1504 This - Pointer to a returned open file handle.
1506 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1508 Buffer - Pointer to the first byte of the read Buffer.
1512 EFI_SUCCESS - The data was read.
1514 EFI_NO_MEDIA - The device has no media.
1516 EFI_DEVICE_ERROR - The device reported an error.
1518 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1520 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1521 *BufferSize has been updated with the size needed to complete the request.
1524 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1526 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1532 SYSTEMTIME SystemTime
;
1533 EFI_FILE_INFO
*Info
;
1535 TIME_ZONE_INFORMATION TimeZone
;
1536 EFI_FILE_INFO
*FileInfo
;
1542 if (This
== NULL
|| BufferSize
== NULL
) {
1543 return EFI_INVALID_PARAMETER
;
1546 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1548 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1550 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1551 Status
= EFI_DEVICE_ERROR
;
1555 if (!PrivateFile
->IsDirectoryPath
) {
1557 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1558 Status
= EFI_DEVICE_ERROR
;
1562 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1563 FileInfo
= AllocatePool (FileInfoSize
);
1565 Status
= This
->GetInfo (
1572 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1573 FreePool (FileInfo
);
1574 FileInfo
= AllocatePool (FileInfoSize
);
1575 Status
= This
->GetInfo (
1583 if (EFI_ERROR (Status
)) {
1584 Status
= EFI_DEVICE_ERROR
;
1588 FileSize
= FileInfo
->FileSize
;
1590 FreePool (FileInfo
);
1592 if (Pos
>= FileSize
) {
1594 if (Pos
== FileSize
) {
1595 Status
= EFI_SUCCESS
;
1598 Status
= EFI_DEVICE_ERROR
;
1603 Status
= PrivateFile
->WinNtThunk
->ReadFile (
1604 PrivateFile
->LHandle
,
1607 (LPDWORD
)BufferSize
,
1609 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1614 // Read on a directory. Perform a find next
1616 if (!PrivateFile
->IsValidFindBuf
) {
1618 Status
= EFI_SUCCESS
;
1622 Size
= SIZE_OF_EFI_FILE_INFO
;
1624 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1626 ResultSize
= Size
+ NameSize
;
1628 Status
= EFI_BUFFER_TOO_SMALL
;
1630 if (*BufferSize
>= ResultSize
) {
1631 Status
= EFI_SUCCESS
;
1634 ZeroMem (Info
, ResultSize
);
1636 Info
->Size
= ResultSize
;
1638 PrivateFile
->WinNtThunk
->GetTimeZoneInformation (&TimeZone
);
1640 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1641 &PrivateFile
->FindBuf
.ftCreationTime
,
1642 &PrivateFile
->FindBuf
.ftCreationTime
1645 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftCreationTime
, &SystemTime
);
1647 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->CreateTime
);
1649 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1650 &PrivateFile
->FindBuf
.ftLastWriteTime
,
1651 &PrivateFile
->FindBuf
.ftLastWriteTime
1654 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftLastWriteTime
, &SystemTime
);
1656 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->ModificationTime
);
1658 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1660 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1662 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1663 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1666 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1667 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1670 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1671 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1674 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1675 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1678 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1679 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1682 NameSize
= NameSize
/ sizeof (WCHAR
);
1684 pw
= (WCHAR
*) (((CHAR8
*) Buffer
) + Size
);
1686 for (Index
= 0; Index
< NameSize
; Index
++) {
1687 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1690 if (PrivateFile
->WinNtThunk
->FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1691 PrivateFile
->IsValidFindBuf
= TRUE
;
1693 PrivateFile
->IsValidFindBuf
= FALSE
;
1697 *BufferSize
= ResultSize
;
1700 gBS
->RestoreTPL (OldTpl
);
1706 WinNtSimpleFileSystemWrite (
1707 IN EFI_FILE_PROTOCOL
*This
,
1708 IN OUT UINTN
*BufferSize
,
1713 Routine Description:
1715 Write data to a file.
1719 This - Pointer to an opened file handle.
1721 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1722 of data written to the file.
1724 Buffer - Pointer to the first by of data in the buffer to write to the file.
1728 EFI_SUCCESS - The data was written to the file.
1730 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1732 EFI_NO_MEDIA - The device has no media.
1734 EFI_DEVICE_ERROR - The device reported an error.
1736 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1738 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1740 EFI_ACCESS_DENIED - The file was opened read-only.
1742 EFI_VOLUME_FULL - The volume is full.
1745 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1747 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1751 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1752 return EFI_INVALID_PARAMETER
;
1755 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1757 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1759 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1760 Status
= EFI_DEVICE_ERROR
;
1764 if (PrivateFile
->IsDirectoryPath
) {
1765 Status
= EFI_UNSUPPORTED
;
1769 if (PrivateFile
->IsOpenedByRead
) {
1770 Status
= EFI_ACCESS_DENIED
;
1774 Status
= PrivateFile
->WinNtThunk
->WriteFile (
1775 PrivateFile
->LHandle
,
1778 (LPDWORD
)BufferSize
,
1780 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1783 gBS
->RestoreTPL (OldTpl
);
1787 // bugbug: need to access windows error reporting
1793 WinNtSimpleFileSystemSetPosition (
1794 IN EFI_FILE_PROTOCOL
*This
,
1799 Routine Description:
1801 Set a file's current position.
1805 This - Pointer to an opened file handle.
1807 Position - The byte position from the start of the file to set.
1811 EFI_SUCCESS - The file position has been changed.
1813 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1816 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1819 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1827 return EFI_INVALID_PARAMETER
;
1830 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1832 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1834 if (PrivateFile
->IsDirectoryPath
) {
1835 if (Position
!= 0) {
1836 Status
= EFI_UNSUPPORTED
;
1840 Size
= StrSize (PrivateFile
->FileName
);
1841 Size
+= StrSize (L
"\\*");
1842 FileName
= AllocatePool (Size
);
1843 if (FileName
== NULL
) {
1844 Status
= EFI_OUT_OF_RESOURCES
;
1848 StrCpy (FileName
, PrivateFile
->FileName
);
1849 StrCat (FileName
, L
"\\*");
1851 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1852 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1855 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1857 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1858 PrivateFile
->IsValidFindBuf
= FALSE
;
1860 PrivateFile
->IsValidFindBuf
= TRUE
;
1863 FreePool (FileName
);
1865 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1867 if (Position
== (UINT64
) -1) {
1868 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) 0, NULL
, FILE_END
);
1870 PosHigh
= (UINT32
) RShiftU64 (Position
, 32);
1872 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) Position
, (PLONG
)&PosHigh
, FILE_BEGIN
);
1875 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1879 gBS
->RestoreTPL (OldTpl
);
1885 WinNtSimpleFileSystemGetPosition (
1886 IN EFI_FILE_PROTOCOL
*This
,
1887 OUT UINT64
*Position
1891 Routine Description:
1893 Get a file's current position.
1897 This - Pointer to an opened file handle.
1899 Position - Pointer to storage for the current position.
1903 EFI_SUCCESS - The file position has been reported.
1905 EFI_UNSUPPORTED - Not valid for directories.
1908 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1911 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1916 if (This
== NULL
|| Position
== NULL
) {
1917 return EFI_INVALID_PARAMETER
;
1920 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1921 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1926 if (PrivateFile
->IsDirectoryPath
) {
1928 Status
= EFI_UNSUPPORTED
;
1934 *Position
= PrivateFile
->WinNtThunk
->SetFilePointer (
1935 PrivateFile
->LHandle
,
1937 (PLONG
)&PositionHigh
,
1941 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1942 if (EFI_ERROR (Status
)) {
1946 PosHigh64
= PositionHigh
;
1947 *Position
+= LShiftU64 (PosHigh64
, 32);
1951 gBS
->RestoreTPL (OldTpl
);
1956 WinNtSimpleFileSystemFileInfo (
1957 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1958 IN OUT UINTN
*BufferSize
,
1963 Routine Description:
1965 TODO: Add function description
1969 PrivateFile - TODO: add argument description
1970 BufferSize - TODO: add argument description
1971 Buffer - TODO: add argument description
1975 TODO: add return values
1983 EFI_FILE_INFO
*Info
;
1984 BY_HANDLE_FILE_INFORMATION FileInfo
;
1985 SYSTEMTIME SystemTime
;
1986 CHAR16
*RealFileName
;
1987 CHAR16
*TempPointer
;
1989 Size
= SIZE_OF_EFI_FILE_INFO
;
1991 RealFileName
= PrivateFile
->FileName
;
1992 TempPointer
= RealFileName
;
1993 while (*TempPointer
) {
1994 if (*TempPointer
== '\\') {
1995 RealFileName
= TempPointer
+ 1;
2000 NameSize
= StrSize (RealFileName
);
2002 ResultSize
= Size
+ NameSize
;
2004 Status
= EFI_BUFFER_TOO_SMALL
;
2005 if (*BufferSize
>= ResultSize
) {
2006 Status
= EFI_SUCCESS
;
2009 ZeroMem (Info
, ResultSize
);
2011 Info
->Size
= ResultSize
;
2012 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (
2013 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2016 Info
->FileSize
= FileInfo
.nFileSizeLow
;
2017 Info
->PhysicalSize
= Info
->FileSize
;
2019 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime(&FileInfo
.ftCreationTime
, &FileInfo
.ftCreationTime
);
2020 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftCreationTime
, &SystemTime
);
2021 Info
->CreateTime
.Year
= SystemTime
.wYear
;
2022 Info
->CreateTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2023 Info
->CreateTime
.Day
= (UINT8
) SystemTime
.wDay
;
2024 Info
->CreateTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2025 Info
->CreateTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2026 Info
->CreateTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2028 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime(&FileInfo
.ftLastAccessTime
, &FileInfo
.ftLastAccessTime
);
2029 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastAccessTime
, &SystemTime
);
2030 Info
->LastAccessTime
.Year
= SystemTime
.wYear
;
2031 Info
->LastAccessTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2032 Info
->LastAccessTime
.Day
= (UINT8
) SystemTime
.wDay
;
2033 Info
->LastAccessTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2034 Info
->LastAccessTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2035 Info
->LastAccessTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2037 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime(&FileInfo
.ftLastWriteTime
, &FileInfo
.ftLastWriteTime
);
2038 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastWriteTime
, &SystemTime
);
2039 Info
->ModificationTime
.Year
= SystemTime
.wYear
;
2040 Info
->ModificationTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2041 Info
->ModificationTime
.Day
= (UINT8
) SystemTime
.wDay
;
2042 Info
->ModificationTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2043 Info
->ModificationTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2044 Info
->ModificationTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2046 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
2047 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
2050 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
2051 Info
->Attribute
|= EFI_FILE_HIDDEN
;
2054 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2055 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
2058 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
2059 Info
->Attribute
|= EFI_FILE_SYSTEM
;
2062 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2063 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2066 if (PrivateFile
->IsDirectoryPath
) {
2067 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2070 if (PrivateFile
->IsRootDirectory
) {
2071 *((CHAR8
*) Buffer
+ Size
) = 0;
2073 CopyMem ((CHAR8
*) Buffer
+ Size
, RealFileName
, NameSize
);
2077 *BufferSize
= ResultSize
;
2083 WinNtSimpleFileSystemGetInfo (
2084 IN EFI_FILE_PROTOCOL
*This
,
2085 IN EFI_GUID
*InformationType
,
2086 IN OUT UINTN
*BufferSize
,
2091 Routine Description:
2093 Return information about a file or volume.
2097 This - Pointer to an opened file handle.
2099 InformationType - GUID describing the type of information to be returned.
2101 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
2104 Buffer - Pointer to the first byte of the information buffer.
2108 EFI_SUCCESS - The requested information has been written into the buffer.
2110 EFI_UNSUPPORTED - The InformationType is not known.
2112 EFI_NO_MEDIA - The device has no media.
2114 EFI_DEVICE_ERROR - The device reported an error.
2116 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2118 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
2119 been updated with the size needed to complete the requested operation.
2122 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2125 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2126 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
2127 UINT32 SectorsPerCluster
;
2128 UINT32 BytesPerSector
;
2129 UINT32 FreeClusters
;
2130 UINT32 TotalClusters
;
2131 UINT32 BytesPerCluster
;
2133 BOOLEAN DriveNameFound
;
2136 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2139 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
2140 return EFI_INVALID_PARAMETER
;
2143 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2145 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2146 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2148 Status
= EFI_UNSUPPORTED
;
2150 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2151 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
2154 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2155 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2156 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2157 Status
= EFI_BUFFER_TOO_SMALL
;
2161 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2162 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2163 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
2166 // Try to get the drive name
2168 DriveNameFound
= FALSE
;
2169 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
2170 if (DriveName
== NULL
) {
2171 Status
= EFI_OUT_OF_RESOURCES
;
2175 StrCpy (DriveName
, PrivateFile
->FilePath
);
2176 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
2180 if (DriveName
[Index
] == ':') {
2181 DriveName
[Index
+ 1] = '\\';
2182 DriveName
[Index
+ 2] = 0;
2183 DriveNameFound
= TRUE
;
2184 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
2185 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2189 if (DriveName
[Index
] == '\\') {
2190 DriveNameFound
= TRUE
;
2191 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2195 DriveName
[Index
] = '\\';
2196 DriveName
[Index
+ 1] = 0;
2201 // Try GetDiskFreeSpace first
2203 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpace (
2204 DriveNameFound
? DriveName
: NULL
,
2205 (LPDWORD
)&SectorsPerCluster
,
2206 (LPDWORD
)&BytesPerSector
,
2207 (LPDWORD
)&FreeClusters
,
2208 (LPDWORD
)&TotalClusters
2211 FreePool (DriveName
);
2218 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
2219 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
2220 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
2221 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
2225 // try GetDiskFreeSpaceEx then
2227 FileSystemInfoBuffer
->BlockSize
= 0;
2228 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpaceEx (
2229 PrivateFile
->FilePath
,
2230 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->FreeSpace
),
2231 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->VolumeSize
),
2235 Status
= EFI_DEVICE_ERROR
;
2240 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
2241 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2242 Status
= EFI_SUCCESS
;
2245 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2246 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2247 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2248 Status
= EFI_BUFFER_TOO_SMALL
;
2252 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
2253 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2254 Status
= EFI_SUCCESS
;
2258 gBS
->RestoreTPL (OldTpl
);
2264 WinNtSimpleFileSystemSetInfo (
2265 IN EFI_FILE_PROTOCOL
*This
,
2266 IN EFI_GUID
*InformationType
,
2267 IN UINTN BufferSize
,
2272 Routine Description:
2274 Set information about a file or volume.
2278 This - Pointer to an opened file handle.
2280 InformationType - GUID identifying the type of information to set.
2282 BufferSize - Number of bytes of data in the information buffer.
2284 Buffer - Pointer to the first byte of data in the information buffer.
2288 EFI_SUCCESS - The file or volume information has been updated.
2290 EFI_UNSUPPORTED - The information identifier is not recognised.
2292 EFI_NO_MEDIA - The device has no media.
2294 EFI_DEVICE_ERROR - The device reported an error.
2296 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2298 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2300 EFI_ACCESS_DENIED - The file was opened read-only.
2302 EFI_VOLUME_FULL - The volume is full.
2304 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2307 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2308 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2310 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2311 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2312 EFI_FILE_INFO
*OldFileInfo
;
2313 EFI_FILE_INFO
*NewFileInfo
;
2319 CHAR16
*OldFileName
;
2320 CHAR16
*NewFileName
;
2321 CHAR16
*TempFileName
;
2322 CHAR16
*CharPointer
;
2323 BOOLEAN AttrChangeFlag
;
2324 BOOLEAN NameChangeFlag
;
2325 BOOLEAN SizeChangeFlag
;
2326 BOOLEAN TimeChangeFlag
;
2328 SYSTEMTIME NewCreationSystemTime
;
2329 SYSTEMTIME NewLastAccessSystemTime
;
2330 SYSTEMTIME NewLastWriteSystemTime
;
2331 FILETIME NewCreationFileTime
;
2332 FILETIME NewLastAccessFileTime
;
2333 FILETIME NewLastWriteFileTime
;
2334 WIN32_FIND_DATA FindBuf
;
2335 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
2340 // Check for invalid parameters.
2342 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
2343 return EFI_INVALID_PARAMETER
;
2346 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2349 // Initialise locals.
2351 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2352 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2354 Status
= EFI_UNSUPPORTED
;
2355 OldFileInfo
= NewFileInfo
= NULL
;
2356 OldFileName
= NewFileName
= NULL
;
2357 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
2360 // Set file system information.
2362 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2363 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2364 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (NewFileSystemInfo
->VolumeLabel
)) {
2365 Status
= EFI_BAD_BUFFER_SIZE
;
2370 FreePool (PrivateRoot
->VolumeLabel
);
2371 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
2372 if (PrivateRoot
->VolumeLabel
== NULL
) {
2373 Status
= EFI_OUT_OF_RESOURCES
;
2377 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
2379 Status
= EFI_SUCCESS
;
2384 // Set volume label information.
2386 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2387 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2388 Status
= EFI_BAD_BUFFER_SIZE
;
2392 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
2394 Status
= EFI_SUCCESS
;
2398 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2399 Status
= EFI_UNSUPPORTED
;
2403 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
2404 Status
= EFI_BAD_BUFFER_SIZE
;
2409 // Set file/directory information.
2413 // Check for invalid set file information parameters.
2415 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
2417 if ((NewFileInfo
->Size
<= SIZE_OF_EFI_FILE_INFO
) ||
2418 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
2419 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
2421 Status
= EFI_INVALID_PARAMETER
;
2426 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2427 // that would have an additional parameter that would be the size
2428 // of the string array just in case there are no NULL characters in
2429 // the string array.
2432 // Get current file information so we can determine what kind
2433 // of change request this is.
2436 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
2438 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2439 Status
= EFI_DEVICE_ERROR
;
2443 OldFileInfo
= AllocatePool (OldInfoSize
);
2444 if (OldFileInfo
== NULL
) {
2445 Status
= EFI_OUT_OF_RESOURCES
;
2449 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
2451 if (EFI_ERROR (Status
)) {
2455 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
2456 if (OldFileName
== NULL
) {
2457 Status
= EFI_OUT_OF_RESOURCES
;
2461 StrCpy (OldFileName
, PrivateFile
->FileName
);
2464 // Make full pathname from new filename and rootpath.
2466 if (NewFileInfo
->FileName
[0] == '\\') {
2467 Size
= StrSize (PrivateRoot
->FilePath
);
2468 Size
+= StrSize (L
"\\");
2469 Size
+= StrSize (NewFileInfo
->FileName
);
2470 NewFileName
= AllocatePool (Size
);
2471 if (NewFileName
== NULL
) {
2472 Status
= EFI_OUT_OF_RESOURCES
;
2476 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
2477 StrCat (NewFileName
, L
"\\");
2478 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
2480 Size
= StrSize (PrivateFile
->FilePath
);
2481 Size
+= StrSize (L
"\\");
2482 Size
+= StrSize (NewFileInfo
->FileName
);
2483 NewFileName
= AllocatePool (Size
);
2484 if (NewFileName
== NULL
) {
2485 Status
= EFI_OUT_OF_RESOURCES
;
2489 StrCpy (NewFileName
, PrivateFile
->FilePath
);
2490 StrCat (NewFileName
, L
"\\");
2491 StrCat (NewFileName
, NewFileInfo
->FileName
);
2495 // Is there an attribute change request?
2497 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
2498 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
2499 Status
= EFI_INVALID_PARAMETER
;
2503 AttrChangeFlag
= TRUE
;
2507 // Is there a name change request?
2508 // bugbug: - Need EfiStrCaseCmp()
2510 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
2511 NameChangeFlag
= TRUE
;
2515 // Is there a size change request?
2517 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
2518 SizeChangeFlag
= TRUE
;
2522 // Is there a time stamp change request?
2524 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
2525 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
2527 TimeChangeFlag
= TRUE
;
2528 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
2529 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
2531 TimeChangeFlag
= TRUE
;
2532 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
2533 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
2535 TimeChangeFlag
= TRUE
;
2539 // All done if there are no change requests being made.
2541 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
2542 Status
= EFI_SUCCESS
;
2547 // Set file or directory information.
2549 OldAttr
= PrivateFile
->WinNtThunk
->GetFileAttributes (OldFileName
);
2554 if (NameChangeFlag
) {
2556 // Close the handles first
2558 if (PrivateFile
->IsOpenedByRead
) {
2559 Status
= EFI_ACCESS_DENIED
;
2563 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
2566 if (*CharPointer
!= 0) {
2567 Status
= EFI_ACCESS_DENIED
;
2571 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
2572 if (PrivateFile
->IsDirectoryPath
) {
2573 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
2575 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
2576 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
2580 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
2581 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
2582 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
2585 NtStatus
= PrivateFile
->WinNtThunk
->MoveFile (OldFileName
, NewFileName
);
2591 FreePool (PrivateFile
->FileName
);
2593 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
2594 if (PrivateFile
->FileName
== NULL
) {
2595 Status
= EFI_OUT_OF_RESOURCES
;
2599 StrCpy (PrivateFile
->FileName
, NewFileName
);
2601 Size
= StrSize (NewFileName
);
2602 Size
+= StrSize (L
"\\*");
2603 TempFileName
= AllocatePool (Size
);
2605 StrCpy (TempFileName
, NewFileName
);
2607 if (!PrivateFile
->IsDirectoryPath
) {
2608 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2610 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2611 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2618 FreePool (TempFileName
);
2621 // Flush buffers just in case
2623 if (PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2624 Status
= EFI_DEVICE_ERROR
;
2628 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2630 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2631 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2634 FILE_FLAG_BACKUP_SEMANTICS
,
2638 StrCat (TempFileName
, L
"\\*");
2639 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2641 FreePool (TempFileName
);
2644 Status
= EFI_ACCESS_DENIED
;
2647 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (OldFileName
, OldAttr
);
2653 Size
= StrSize (OldFileName
);
2654 Size
+= StrSize (L
"\\*");
2655 TempFileName
= AllocatePool (Size
);
2657 StrCpy (TempFileName
, OldFileName
);
2659 if (!PrivateFile
->IsDirectoryPath
) {
2660 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2662 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2663 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2670 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2672 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2673 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2676 FILE_FLAG_BACKUP_SEMANTICS
,
2680 StrCat (TempFileName
, L
"\\*");
2681 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2684 FreePool (TempFileName
);
2694 if (SizeChangeFlag
) {
2695 if (PrivateFile
->IsDirectoryPath
) {
2696 Status
= EFI_UNSUPPORTED
;
2700 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2701 Status
= EFI_ACCESS_DENIED
;
2705 Status
= This
->GetPosition (This
, &CurPos
);
2706 if (EFI_ERROR (Status
)) {
2710 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2711 if (EFI_ERROR (Status
)) {
2715 if (PrivateFile
->WinNtThunk
->SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2716 Status
= EFI_DEVICE_ERROR
;
2720 Status
= This
->SetPosition (This
, CurPos
);
2721 if (EFI_ERROR (Status
)) {
2729 if (TimeChangeFlag
) {
2731 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2732 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2733 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2734 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2735 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2736 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2737 NewCreationSystemTime
.wMilliseconds
= 0;
2739 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2740 &NewCreationSystemTime
,
2741 &NewCreationFileTime
2746 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2747 &NewCreationFileTime
,
2748 &NewCreationFileTime
2753 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2754 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2755 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2756 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2757 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2758 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2759 NewLastAccessSystemTime
.wMilliseconds
= 0;
2761 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2762 &NewLastAccessSystemTime
,
2763 &NewLastAccessFileTime
2768 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2769 &NewLastAccessFileTime
,
2770 &NewLastAccessFileTime
2775 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2776 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2777 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2778 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2779 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2780 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2781 NewLastWriteSystemTime
.wMilliseconds
= 0;
2783 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2784 &NewLastWriteSystemTime
,
2785 &NewLastWriteFileTime
2790 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2791 &NewLastWriteFileTime
,
2792 &NewLastWriteFileTime
2797 if (!PrivateFile
->WinNtThunk
->SetFileTime (
2798 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2799 &NewCreationFileTime
,
2800 &NewLastAccessFileTime
,
2801 &NewLastWriteFileTime
2803 Status
= EFI_DEVICE_ERROR
;
2810 // No matter about AttrChangeFlag, Attribute must be set.
2811 // Because operation before may cause attribute change.
2815 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2816 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2818 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2821 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2822 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2824 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2827 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2828 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2830 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2833 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2834 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2836 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2839 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (NewFileName
, NewAttr
);
2842 Status
= EFI_DEVICE_ERROR
;
2847 if (OldFileInfo
!= NULL
) {
2848 FreePool (OldFileInfo
);
2851 if (OldFileName
!= NULL
) {
2852 FreePool (OldFileName
);
2855 if (NewFileName
!= NULL
) {
2856 FreePool (NewFileName
);
2859 gBS
->RestoreTPL (OldTpl
);
2865 WinNtSimpleFileSystemFlush (
2866 IN EFI_FILE_PROTOCOL
*This
2870 Routine Description:
2872 Flush all modified data to the media.
2876 This - Pointer to an opened file handle.
2880 EFI_SUCCESS - The data has been flushed.
2882 EFI_NO_MEDIA - The device has no media.
2884 EFI_DEVICE_ERROR - The device reported an error.
2886 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2888 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2890 EFI_ACCESS_DENIED - The file was opened read-only.
2892 EFI_VOLUME_FULL - The volume is full.
2895 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2897 BY_HANDLE_FILE_INFORMATION FileInfo
;
2898 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2903 return EFI_INVALID_PARAMETER
;
2906 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2908 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2910 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2911 Status
= EFI_DEVICE_ERROR
;
2915 if (PrivateFile
->IsDirectoryPath
) {
2916 Status
= EFI_SUCCESS
;
2920 if (PrivateFile
->IsOpenedByRead
) {
2921 Status
= EFI_ACCESS_DENIED
;
2925 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2927 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2928 Status
= EFI_ACCESS_DENIED
;
2932 Status
= PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2935 gBS
->RestoreTPL (OldTpl
);
2938 // bugbug: - Use Windows error reporting.