3 Copyright (c) 2006 - 2017, 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;
752 // If *FileName is an empty string, then set *FileName to NULL
754 if (**FileName
== L
'\0') {
763 Check if a FileName contains only Valid Characters.
765 If FileName contains only a single L'\', return TRUE.
766 If FileName contains two adjacent L'\', return FALSE.
767 If FileName conatins L'/' , return FALSE.
768 If FielName contains more than two dots seperated with other FileName characters
769 by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
771 @param FileName The File Name String to check.
773 @return TRUE FileName only contains valid characters.
774 @return FALSE FileName contains at least one invalid character.
780 IN CONST CHAR16
*FileName
787 // If FileName is just L'\', then it is a valid pathname.
789 if (StrCmp (FileName
, L
"\\") == 0) {
793 // We don't support two or more adjacent L'\'.
795 if (StrStr (FileName
, L
"\\\\") != NULL
) {
800 // Is FileName has a leading L"\", skip to next character.
802 if (FileName
[0] == L
'\\') {
807 Token
= GetNextFileNameToken (&FileName
);
808 Valid
= IsFileNameTokenValid (Token
);
813 } while (FileName
!= NULL
);
820 WinNtSimpleFileSystemOpen (
821 IN EFI_FILE_PROTOCOL
*This
,
822 OUT EFI_FILE_PROTOCOL
**NewHandle
,
831 Open a file relative to the source file location.
835 This - A pointer to the source file location.
837 NewHandle - Pointer to storage for the new file handle.
839 FileName - Pointer to the file name to be opened.
841 OpenMode - File open mode information.
843 Attributes - File creation attributes.
847 EFI_SUCCESS - The file was opened.
849 EFI_NOT_FOUND - The file could not be found in the volume.
851 EFI_NO_MEDIA - The device has no media.
853 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
855 EFI_DEVICE_ERROR - The device reported an error.
857 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
859 EFI_WRITE_PROTECTED - The volume or file is write protected.
861 EFI_ACCESS_DENIED - The service denied access to the file.
863 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
865 EFI_VOLUME_FULL - There is not enough space left to create the new file.
868 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
869 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
870 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
871 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
873 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
874 WIN_NT_EFI_FILE_PRIVATE
*NewPrivateFile
;
875 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
877 CHAR16
*RealFileName
;
878 CHAR16
*TempFileName
;
879 CHAR16
*ParseFileName
;
880 CHAR16
*GuardPointer
;
890 // Check for obvious invalid parameters.
892 if (This
== NULL
|| NewHandle
== NULL
|| FileName
== NULL
) {
893 return EFI_INVALID_PARAMETER
;
897 case EFI_FILE_MODE_CREATE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
898 if (Attributes
&~EFI_FILE_VALID_ATTR
) {
899 return EFI_INVALID_PARAMETER
;
902 if (Attributes
& EFI_FILE_READ_ONLY
) {
903 return EFI_INVALID_PARAMETER
;
909 case EFI_FILE_MODE_READ
:
910 case EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
914 return EFI_INVALID_PARAMETER
;
918 // Init local variables
920 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
921 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
922 NewPrivateFile
= NULL
;
925 // Allocate buffer for FileName as the passed in FileName may be read only
927 TempFileName
= AllocatePool (StrSize (FileName
));
928 if (TempFileName
== NULL
) {
929 return EFI_OUT_OF_RESOURCES
;
931 StrCpy (TempFileName
, FileName
);
932 FileName
= TempFileName
;
934 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
935 FileName
[StrLen (FileName
) - 1] = 0;
939 // If file name does not equal to "." or ".." and not trailed with "\..",
940 // then we trim the leading/trailing blanks and trailing dots
942 if (StrCmp (FileName
, L
".") != 0 && StrCmp (FileName
, L
"..") != 0 &&
943 ((StrLen (FileName
) >= 3) ? (StrCmp (&FileName
[StrLen (FileName
) - 3], L
"\\..") != 0) : TRUE
)) {
945 // Trim leading blanks
948 for (TempFileName
= FileName
;
949 *TempFileName
!= 0 && *TempFileName
== L
' ';
953 CutPrefix (FileName
, Count
);
955 // Trim trailing blanks
957 for (TempFileName
= FileName
+ StrLen (FileName
) - 1;
958 TempFileName
>= FileName
&& (*TempFileName
== L
' ');
962 *(TempFileName
+ 1) = 0;
966 // Attempt to open the file
968 NewPrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
969 if (NewPrivateFile
== NULL
) {
970 Status
= EFI_OUT_OF_RESOURCES
;
974 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (WIN_NT_EFI_FILE_PRIVATE
));
976 NewPrivateFile
->FilePath
= AllocatePool (StrSize (PrivateFile
->FileName
));
977 if (NewPrivateFile
->FilePath
== NULL
) {
978 Status
= EFI_OUT_OF_RESOURCES
;
982 if (PrivateFile
->IsDirectoryPath
) {
983 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FileName
);
985 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FilePath
);
988 Size
= StrSize (NewPrivateFile
->FilePath
);
989 Size
+= StrSize (L
"\\");
990 Size
+= StrSize (FileName
);
991 NewPrivateFile
->FileName
= AllocatePool (Size
);
992 if (NewPrivateFile
->FileName
== NULL
) {
993 Status
= EFI_OUT_OF_RESOURCES
;
997 if (*FileName
== L
'\\') {
998 StrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
999 StrCat (NewPrivateFile
->FileName
, L
"\\");
1000 StrCat (NewPrivateFile
->FileName
, FileName
+ 1);
1002 StrCpy (NewPrivateFile
->FileName
, NewPrivateFile
->FilePath
);
1003 if (StrCmp (FileName
, L
"") != 0) {
1005 // In case the filename becomes empty, especially after trimming dots and blanks
1007 StrCat (NewPrivateFile
->FileName
, L
"\\");
1008 StrCat (NewPrivateFile
->FileName
, FileName
);
1012 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
1013 Status
= EFI_NOT_FOUND
;
1018 // Get rid of . and .., except leading . or ..
1022 // GuardPointer protect simplefilesystem root path not be destroyed
1024 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
1028 while (!LoopFinish
) {
1032 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
1033 if (*ParseFileName
== L
'.' &&
1034 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
1035 *(ParseFileName
- 1) == L
'\\'
1041 CutPrefix (ParseFileName
- 1, 2);
1046 if (*ParseFileName
== L
'.' &&
1047 *(ParseFileName
+ 1) == L
'.' &&
1048 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
1049 *(ParseFileName
- 1) == L
'\\'
1055 while (ParseFileName
!= GuardPointer
) {
1058 if (*ParseFileName
== L
'\\') {
1064 // cut \.. and its left directory
1066 CutPrefix (ParseFileName
, Count
);
1073 RealFileName
= NewPrivateFile
->FileName
;
1074 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
1075 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
1079 if (RealFileName
!= NewPrivateFile
->FileName
) {
1080 TempChar
= *(RealFileName
- 1);
1081 *(RealFileName
- 1) = 0;
1084 FreePool (NewPrivateFile
->FilePath
);
1085 NewPrivateFile
->FilePath
= NULL
;
1086 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
1087 if (NewPrivateFile
->FilePath
== NULL
) {
1088 Status
= EFI_OUT_OF_RESOURCES
;
1092 StrCpy (NewPrivateFile
->FilePath
, NewPrivateFile
->FileName
);
1093 if (TempChar
!= 0) {
1094 *(RealFileName
- 1) = TempChar
;
1097 NewPrivateFile
->IsRootDirectory
= FALSE
;
1100 // Test whether file or directory
1102 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
1103 if (Attributes
& EFI_FILE_DIRECTORY
) {
1104 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1106 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1109 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1110 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1111 NewPrivateFile
->FileName
,
1113 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1120 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1121 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1122 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1124 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1127 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1130 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
1131 NewPrivateFile
->IsOpenedByRead
= FALSE
;
1133 NewPrivateFile
->IsOpenedByRead
= TRUE
;
1136 Status
= EFI_SUCCESS
;
1139 // deal with directory
1141 if (NewPrivateFile
->IsDirectoryPath
) {
1143 Size
= StrSize (NewPrivateFile
->FileName
);
1144 Size
+= StrSize (L
"\\*");
1145 TempFileName
= AllocatePool (Size
);
1146 if (TempFileName
== NULL
) {
1147 Status
= EFI_OUT_OF_RESOURCES
;
1151 StrCpy (TempFileName
, NewPrivateFile
->FileName
);
1153 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
1155 // Create a directory
1157 if (!NewPrivateFile
->WinNtThunk
->CreateDirectory (TempFileName
, NULL
)) {
1159 LastError
= PrivateFile
->WinNtThunk
->GetLastError ();
1160 if (LastError
!= ERROR_ALREADY_EXISTS
) {
1161 FreePool (TempFileName
);
1162 Status
= EFI_ACCESS_DENIED
;
1168 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1170 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
1171 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1174 FILE_FLAG_BACKUP_SEMANTICS
,
1178 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
1180 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1183 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1186 FILE_FLAG_BACKUP_SEMANTICS
,
1190 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1191 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->DirHandle
);
1192 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1193 Status
= EFI_ACCESS_DENIED
;
1195 Status
= EFI_NOT_FOUND
;
1198 FreePool (TempFileName
);
1203 // Find the first file under it
1205 StrCat (TempFileName
, L
"\\*");
1206 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
1207 FreePool (TempFileName
);
1209 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1210 NewPrivateFile
->IsValidFindBuf
= FALSE
;
1212 NewPrivateFile
->IsValidFindBuf
= TRUE
;
1218 if (!NewPrivateFile
->IsOpenedByRead
) {
1219 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1220 NewPrivateFile
->FileName
,
1221 GENERIC_READ
| GENERIC_WRITE
,
1222 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1224 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
1229 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1230 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1231 NewPrivateFile
->FileName
,
1233 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1240 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1241 Status
= EFI_NOT_FOUND
;
1243 Status
= EFI_ACCESS_DENIED
;
1244 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1245 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1249 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1250 NewPrivateFile
->FileName
,
1252 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1259 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1260 Status
= EFI_NOT_FOUND
;
1265 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
1267 // Set the attribute
1272 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1274 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1275 Status
= EFI_DEVICE_ERROR
;
1279 Info
= AllocatePool (InfoSize
);
1281 Status
= EFI_OUT_OF_RESOURCES
;
1285 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1287 if (EFI_ERROR (Status
)) {
1292 Info
->Attribute
= Attributes
;
1294 WinNtSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
1299 FreePool (FileName
);
1301 if (EFI_ERROR (Status
)) {
1302 if (NewPrivateFile
) {
1303 if (NewPrivateFile
->FileName
) {
1304 FreePool (NewPrivateFile
->FileName
);
1307 if (NewPrivateFile
->FilePath
) {
1308 FreePool (NewPrivateFile
->FilePath
);
1311 FreePool (NewPrivateFile
);
1314 *NewHandle
= &NewPrivateFile
->EfiFile
;
1315 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
1316 NewPrivateFile
->IsRootDirectory
= TRUE
;
1325 WinNtSimpleFileSystemClose (
1326 IN EFI_FILE_PROTOCOL
*This
1330 Routine Description:
1332 Close the specified file handle.
1336 This - Pointer to a returned opened file handle.
1340 EFI_SUCCESS - The file handle has been closed.
1343 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1345 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1349 return EFI_INVALID_PARAMETER
;
1352 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1354 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1356 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1357 if (PrivateFile
->IsDirectoryPath
) {
1358 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1360 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1363 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1366 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1367 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1368 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1371 if (PrivateFile
->FileName
) {
1372 FreePool (PrivateFile
->FileName
);
1375 if (PrivateFile
->FilePath
) {
1376 FreePool (PrivateFile
->FilePath
);
1379 FreePool (PrivateFile
);
1381 gBS
->RestoreTPL (OldTpl
);
1388 WinNtSimpleFileSystemDelete (
1389 IN EFI_FILE_PROTOCOL
*This
1393 Routine Description:
1395 Close and delete a file.
1399 This - Pointer to a returned opened file handle.
1403 EFI_SUCCESS - The file handle was closed and deleted.
1405 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1408 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1411 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1415 return EFI_INVALID_PARAMETER
;
1418 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1420 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1422 Status
= EFI_WARN_DELETE_FAILURE
;
1424 if (PrivateFile
->IsDirectoryPath
) {
1425 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1426 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1429 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1430 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1431 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1434 if (PrivateFile
->WinNtThunk
->RemoveDirectory (PrivateFile
->FileName
)) {
1435 Status
= EFI_SUCCESS
;
1438 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1439 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1441 if (!PrivateFile
->IsOpenedByRead
) {
1442 if (PrivateFile
->WinNtThunk
->DeleteFile (PrivateFile
->FileName
)) {
1443 Status
= EFI_SUCCESS
;
1448 FreePool (PrivateFile
->FileName
);
1449 FreePool (PrivateFile
->FilePath
);
1450 FreePool (PrivateFile
);
1452 gBS
->RestoreTPL (OldTpl
);
1458 WinNtSystemTimeToEfiTime (
1459 IN SYSTEMTIME
*SystemTime
,
1460 IN TIME_ZONE_INFORMATION
*TimeZone
,
1465 Routine Description:
1467 TODO: Add function description
1471 SystemTime - TODO: add argument description
1472 TimeZone - TODO: add argument description
1473 Time - TODO: add argument description
1477 TODO: add return values
1481 Time
->Year
= (UINT16
) SystemTime
->wYear
;
1482 Time
->Month
= (UINT8
) SystemTime
->wMonth
;
1483 Time
->Day
= (UINT8
) SystemTime
->wDay
;
1484 Time
->Hour
= (UINT8
) SystemTime
->wHour
;
1485 Time
->Minute
= (UINT8
) SystemTime
->wMinute
;
1486 Time
->Second
= (UINT8
) SystemTime
->wSecond
;
1487 Time
->Nanosecond
= (UINT32
) SystemTime
->wMilliseconds
* 1000000;
1488 Time
->TimeZone
= (INT16
) TimeZone
->Bias
;
1490 if (TimeZone
->StandardDate
.wMonth
) {
1491 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1497 WinNtSimpleFileSystemRead (
1498 IN EFI_FILE_PROTOCOL
*This
,
1499 IN OUT UINTN
*BufferSize
,
1504 Routine Description:
1506 Read data from a file.
1510 This - Pointer to a returned open file handle.
1512 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1514 Buffer - Pointer to the first byte of the read Buffer.
1518 EFI_SUCCESS - The data was read.
1520 EFI_NO_MEDIA - The device has no media.
1522 EFI_DEVICE_ERROR - The device reported an error.
1524 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1526 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1527 *BufferSize has been updated with the size needed to complete the request.
1530 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1532 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1538 SYSTEMTIME SystemTime
;
1539 EFI_FILE_INFO
*Info
;
1541 TIME_ZONE_INFORMATION TimeZone
;
1542 EFI_FILE_INFO
*FileInfo
;
1548 if (This
== NULL
|| BufferSize
== NULL
) {
1549 return EFI_INVALID_PARAMETER
;
1552 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1554 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1556 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1557 Status
= EFI_DEVICE_ERROR
;
1561 if (!PrivateFile
->IsDirectoryPath
) {
1563 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1564 Status
= EFI_DEVICE_ERROR
;
1568 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1569 FileInfo
= AllocatePool (FileInfoSize
);
1571 Status
= This
->GetInfo (
1578 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1579 FreePool (FileInfo
);
1580 FileInfo
= AllocatePool (FileInfoSize
);
1581 Status
= This
->GetInfo (
1589 if (EFI_ERROR (Status
)) {
1590 Status
= EFI_DEVICE_ERROR
;
1594 FileSize
= FileInfo
->FileSize
;
1596 FreePool (FileInfo
);
1598 if (Pos
>= FileSize
) {
1600 if (Pos
== FileSize
) {
1601 Status
= EFI_SUCCESS
;
1604 Status
= EFI_DEVICE_ERROR
;
1609 Status
= PrivateFile
->WinNtThunk
->ReadFile (
1610 PrivateFile
->LHandle
,
1613 (LPDWORD
)BufferSize
,
1615 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1620 // Read on a directory. Perform a find next
1622 if (!PrivateFile
->IsValidFindBuf
) {
1624 Status
= EFI_SUCCESS
;
1628 Size
= SIZE_OF_EFI_FILE_INFO
;
1630 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1632 ResultSize
= Size
+ NameSize
;
1634 Status
= EFI_BUFFER_TOO_SMALL
;
1636 if (*BufferSize
>= ResultSize
) {
1637 Status
= EFI_SUCCESS
;
1640 ZeroMem (Info
, ResultSize
);
1642 Info
->Size
= ResultSize
;
1644 PrivateFile
->WinNtThunk
->GetTimeZoneInformation (&TimeZone
);
1646 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1647 &PrivateFile
->FindBuf
.ftCreationTime
,
1648 &PrivateFile
->FindBuf
.ftCreationTime
1651 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftCreationTime
, &SystemTime
);
1653 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->CreateTime
);
1655 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1656 &PrivateFile
->FindBuf
.ftLastWriteTime
,
1657 &PrivateFile
->FindBuf
.ftLastWriteTime
1660 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftLastWriteTime
, &SystemTime
);
1662 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->ModificationTime
);
1664 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1666 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1668 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1669 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1672 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1673 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1676 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1677 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1680 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1681 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1684 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1685 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1688 NameSize
= NameSize
/ sizeof (WCHAR
);
1690 pw
= (WCHAR
*) (((CHAR8
*) Buffer
) + Size
);
1692 for (Index
= 0; Index
< NameSize
; Index
++) {
1693 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1696 if (PrivateFile
->WinNtThunk
->FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1697 PrivateFile
->IsValidFindBuf
= TRUE
;
1699 PrivateFile
->IsValidFindBuf
= FALSE
;
1703 *BufferSize
= ResultSize
;
1706 gBS
->RestoreTPL (OldTpl
);
1712 WinNtSimpleFileSystemWrite (
1713 IN EFI_FILE_PROTOCOL
*This
,
1714 IN OUT UINTN
*BufferSize
,
1719 Routine Description:
1721 Write data to a file.
1725 This - Pointer to an opened file handle.
1727 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1728 of data written to the file.
1730 Buffer - Pointer to the first by of data in the buffer to write to the file.
1734 EFI_SUCCESS - The data was written to the file.
1736 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1738 EFI_NO_MEDIA - The device has no media.
1740 EFI_DEVICE_ERROR - The device reported an error.
1742 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1744 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1746 EFI_ACCESS_DENIED - The file was opened read-only.
1748 EFI_VOLUME_FULL - The volume is full.
1751 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1753 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1757 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1758 return EFI_INVALID_PARAMETER
;
1761 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1763 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1765 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1766 Status
= EFI_DEVICE_ERROR
;
1770 if (PrivateFile
->IsDirectoryPath
) {
1771 Status
= EFI_UNSUPPORTED
;
1775 if (PrivateFile
->IsOpenedByRead
) {
1776 Status
= EFI_ACCESS_DENIED
;
1780 Status
= PrivateFile
->WinNtThunk
->WriteFile (
1781 PrivateFile
->LHandle
,
1784 (LPDWORD
)BufferSize
,
1786 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1789 gBS
->RestoreTPL (OldTpl
);
1793 // bugbug: need to access windows error reporting
1799 WinNtSimpleFileSystemSetPosition (
1800 IN EFI_FILE_PROTOCOL
*This
,
1805 Routine Description:
1807 Set a file's current position.
1811 This - Pointer to an opened file handle.
1813 Position - The byte position from the start of the file to set.
1817 EFI_SUCCESS - The file position has been changed.
1819 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1822 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1825 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1833 return EFI_INVALID_PARAMETER
;
1836 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1838 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1840 if (PrivateFile
->IsDirectoryPath
) {
1841 if (Position
!= 0) {
1842 Status
= EFI_UNSUPPORTED
;
1846 Size
= StrSize (PrivateFile
->FileName
);
1847 Size
+= StrSize (L
"\\*");
1848 FileName
= AllocatePool (Size
);
1849 if (FileName
== NULL
) {
1850 Status
= EFI_OUT_OF_RESOURCES
;
1854 StrCpy (FileName
, PrivateFile
->FileName
);
1855 StrCat (FileName
, L
"\\*");
1857 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1858 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1861 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1863 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1864 PrivateFile
->IsValidFindBuf
= FALSE
;
1866 PrivateFile
->IsValidFindBuf
= TRUE
;
1869 FreePool (FileName
);
1871 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1873 if (Position
== (UINT64
) -1) {
1874 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) 0, NULL
, FILE_END
);
1876 PosHigh
= (UINT32
) RShiftU64 (Position
, 32);
1878 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) Position
, (PLONG
)&PosHigh
, FILE_BEGIN
);
1881 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1885 gBS
->RestoreTPL (OldTpl
);
1891 WinNtSimpleFileSystemGetPosition (
1892 IN EFI_FILE_PROTOCOL
*This
,
1893 OUT UINT64
*Position
1897 Routine Description:
1899 Get a file's current position.
1903 This - Pointer to an opened file handle.
1905 Position - Pointer to storage for the current position.
1909 EFI_SUCCESS - The file position has been reported.
1911 EFI_UNSUPPORTED - Not valid for directories.
1914 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1917 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1922 if (This
== NULL
|| Position
== NULL
) {
1923 return EFI_INVALID_PARAMETER
;
1926 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1927 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1932 if (PrivateFile
->IsDirectoryPath
) {
1934 Status
= EFI_UNSUPPORTED
;
1940 *Position
= PrivateFile
->WinNtThunk
->SetFilePointer (
1941 PrivateFile
->LHandle
,
1943 (PLONG
)&PositionHigh
,
1947 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1948 if (EFI_ERROR (Status
)) {
1952 PosHigh64
= PositionHigh
;
1953 *Position
+= LShiftU64 (PosHigh64
, 32);
1957 gBS
->RestoreTPL (OldTpl
);
1962 WinNtSimpleFileSystemFileInfo (
1963 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1964 IN OUT UINTN
*BufferSize
,
1969 Routine Description:
1971 TODO: Add function description
1975 PrivateFile - TODO: add argument description
1976 BufferSize - TODO: add argument description
1977 Buffer - TODO: add argument description
1981 TODO: add return values
1989 EFI_FILE_INFO
*Info
;
1990 BY_HANDLE_FILE_INFORMATION FileInfo
;
1991 SYSTEMTIME SystemTime
;
1992 CHAR16
*RealFileName
;
1993 CHAR16
*TempPointer
;
1995 Size
= SIZE_OF_EFI_FILE_INFO
;
1997 RealFileName
= PrivateFile
->FileName
;
1998 TempPointer
= RealFileName
;
1999 while (*TempPointer
) {
2000 if (*TempPointer
== '\\') {
2001 RealFileName
= TempPointer
+ 1;
2006 NameSize
= StrSize (RealFileName
);
2008 ResultSize
= Size
+ NameSize
;
2010 Status
= EFI_BUFFER_TOO_SMALL
;
2011 if (*BufferSize
>= ResultSize
) {
2012 Status
= EFI_SUCCESS
;
2015 ZeroMem (Info
, ResultSize
);
2017 Info
->Size
= ResultSize
;
2018 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (
2019 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2022 Info
->FileSize
= FileInfo
.nFileSizeLow
;
2023 Info
->PhysicalSize
= Info
->FileSize
;
2025 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime(&FileInfo
.ftCreationTime
, &FileInfo
.ftCreationTime
);
2026 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftCreationTime
, &SystemTime
);
2027 Info
->CreateTime
.Year
= SystemTime
.wYear
;
2028 Info
->CreateTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2029 Info
->CreateTime
.Day
= (UINT8
) SystemTime
.wDay
;
2030 Info
->CreateTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2031 Info
->CreateTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2032 Info
->CreateTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2034 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime(&FileInfo
.ftLastAccessTime
, &FileInfo
.ftLastAccessTime
);
2035 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastAccessTime
, &SystemTime
);
2036 Info
->LastAccessTime
.Year
= SystemTime
.wYear
;
2037 Info
->LastAccessTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2038 Info
->LastAccessTime
.Day
= (UINT8
) SystemTime
.wDay
;
2039 Info
->LastAccessTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2040 Info
->LastAccessTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2041 Info
->LastAccessTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2043 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime(&FileInfo
.ftLastWriteTime
, &FileInfo
.ftLastWriteTime
);
2044 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastWriteTime
, &SystemTime
);
2045 Info
->ModificationTime
.Year
= SystemTime
.wYear
;
2046 Info
->ModificationTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2047 Info
->ModificationTime
.Day
= (UINT8
) SystemTime
.wDay
;
2048 Info
->ModificationTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2049 Info
->ModificationTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2050 Info
->ModificationTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2052 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
2053 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
2056 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
2057 Info
->Attribute
|= EFI_FILE_HIDDEN
;
2060 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2061 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
2064 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
2065 Info
->Attribute
|= EFI_FILE_SYSTEM
;
2068 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2069 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2072 if (PrivateFile
->IsDirectoryPath
) {
2073 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2076 if (PrivateFile
->IsRootDirectory
) {
2077 *((CHAR8
*) Buffer
+ Size
) = 0;
2079 CopyMem ((CHAR8
*) Buffer
+ Size
, RealFileName
, NameSize
);
2083 *BufferSize
= ResultSize
;
2089 WinNtSimpleFileSystemGetInfo (
2090 IN EFI_FILE_PROTOCOL
*This
,
2091 IN EFI_GUID
*InformationType
,
2092 IN OUT UINTN
*BufferSize
,
2097 Routine Description:
2099 Return information about a file or volume.
2103 This - Pointer to an opened file handle.
2105 InformationType - GUID describing the type of information to be returned.
2107 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
2110 Buffer - Pointer to the first byte of the information buffer.
2114 EFI_SUCCESS - The requested information has been written into the buffer.
2116 EFI_UNSUPPORTED - The InformationType is not known.
2118 EFI_NO_MEDIA - The device has no media.
2120 EFI_DEVICE_ERROR - The device reported an error.
2122 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2124 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
2125 been updated with the size needed to complete the requested operation.
2128 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2131 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2132 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
2133 UINT32 SectorsPerCluster
;
2134 UINT32 BytesPerSector
;
2135 UINT32 FreeClusters
;
2136 UINT32 TotalClusters
;
2137 UINT32 BytesPerCluster
;
2139 BOOLEAN DriveNameFound
;
2142 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2145 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
2146 return EFI_INVALID_PARAMETER
;
2149 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2151 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2152 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2154 Status
= EFI_UNSUPPORTED
;
2156 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2157 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
2160 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2161 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2162 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2163 Status
= EFI_BUFFER_TOO_SMALL
;
2167 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2168 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2169 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
2172 // Try to get the drive name
2174 DriveNameFound
= FALSE
;
2175 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
2176 if (DriveName
== NULL
) {
2177 Status
= EFI_OUT_OF_RESOURCES
;
2181 StrCpy (DriveName
, PrivateFile
->FilePath
);
2182 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
2186 if (DriveName
[Index
] == ':') {
2187 DriveName
[Index
+ 1] = '\\';
2188 DriveName
[Index
+ 2] = 0;
2189 DriveNameFound
= TRUE
;
2190 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
2191 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2195 if (DriveName
[Index
] == '\\') {
2196 DriveNameFound
= TRUE
;
2197 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2201 DriveName
[Index
] = '\\';
2202 DriveName
[Index
+ 1] = 0;
2207 // Try GetDiskFreeSpace first
2209 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpace (
2210 DriveNameFound
? DriveName
: NULL
,
2211 (LPDWORD
)&SectorsPerCluster
,
2212 (LPDWORD
)&BytesPerSector
,
2213 (LPDWORD
)&FreeClusters
,
2214 (LPDWORD
)&TotalClusters
2217 FreePool (DriveName
);
2224 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
2225 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
2226 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
2227 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
2231 // try GetDiskFreeSpaceEx then
2233 FileSystemInfoBuffer
->BlockSize
= 0;
2234 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpaceEx (
2235 PrivateFile
->FilePath
,
2236 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->FreeSpace
),
2237 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->VolumeSize
),
2241 Status
= EFI_DEVICE_ERROR
;
2246 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
2247 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2248 Status
= EFI_SUCCESS
;
2251 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2252 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2253 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2254 Status
= EFI_BUFFER_TOO_SMALL
;
2258 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
2259 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2260 Status
= EFI_SUCCESS
;
2264 gBS
->RestoreTPL (OldTpl
);
2270 WinNtSimpleFileSystemSetInfo (
2271 IN EFI_FILE_PROTOCOL
*This
,
2272 IN EFI_GUID
*InformationType
,
2273 IN UINTN BufferSize
,
2278 Routine Description:
2280 Set information about a file or volume.
2284 This - Pointer to an opened file handle.
2286 InformationType - GUID identifying the type of information to set.
2288 BufferSize - Number of bytes of data in the information buffer.
2290 Buffer - Pointer to the first byte of data in the information buffer.
2294 EFI_SUCCESS - The file or volume information has been updated.
2296 EFI_UNSUPPORTED - The information identifier is not recognised.
2298 EFI_NO_MEDIA - The device has no media.
2300 EFI_DEVICE_ERROR - The device reported an error.
2302 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2304 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2306 EFI_ACCESS_DENIED - The file was opened read-only.
2308 EFI_VOLUME_FULL - The volume is full.
2310 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2313 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2314 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2316 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2317 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2318 EFI_FILE_INFO
*OldFileInfo
;
2319 EFI_FILE_INFO
*NewFileInfo
;
2325 CHAR16
*OldFileName
;
2326 CHAR16
*NewFileName
;
2327 CHAR16
*TempFileName
;
2328 CHAR16
*CharPointer
;
2329 BOOLEAN AttrChangeFlag
;
2330 BOOLEAN NameChangeFlag
;
2331 BOOLEAN SizeChangeFlag
;
2332 BOOLEAN TimeChangeFlag
;
2334 SYSTEMTIME NewCreationSystemTime
;
2335 SYSTEMTIME NewLastAccessSystemTime
;
2336 SYSTEMTIME NewLastWriteSystemTime
;
2337 FILETIME NewCreationFileTime
;
2338 FILETIME NewLastAccessFileTime
;
2339 FILETIME NewLastWriteFileTime
;
2340 WIN32_FIND_DATA FindBuf
;
2341 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
2346 // Check for invalid parameters.
2348 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
2349 return EFI_INVALID_PARAMETER
;
2352 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2355 // Initialise locals.
2357 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2358 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2360 Status
= EFI_UNSUPPORTED
;
2361 OldFileInfo
= NewFileInfo
= NULL
;
2362 OldFileName
= NewFileName
= NULL
;
2363 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
2366 // Set file system information.
2368 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2369 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2370 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (NewFileSystemInfo
->VolumeLabel
)) {
2371 Status
= EFI_BAD_BUFFER_SIZE
;
2376 FreePool (PrivateRoot
->VolumeLabel
);
2377 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
2378 if (PrivateRoot
->VolumeLabel
== NULL
) {
2379 Status
= EFI_OUT_OF_RESOURCES
;
2383 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
2385 Status
= EFI_SUCCESS
;
2390 // Set volume label information.
2392 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2393 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2394 Status
= EFI_BAD_BUFFER_SIZE
;
2398 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
2400 Status
= EFI_SUCCESS
;
2404 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2405 Status
= EFI_UNSUPPORTED
;
2409 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
2410 Status
= EFI_BAD_BUFFER_SIZE
;
2415 // Set file/directory information.
2419 // Check for invalid set file information parameters.
2421 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
2423 if ((NewFileInfo
->Size
<= SIZE_OF_EFI_FILE_INFO
) ||
2424 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
2425 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
2427 Status
= EFI_INVALID_PARAMETER
;
2432 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2433 // that would have an additional parameter that would be the size
2434 // of the string array just in case there are no NULL characters in
2435 // the string array.
2438 // Get current file information so we can determine what kind
2439 // of change request this is.
2442 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
2444 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2445 Status
= EFI_DEVICE_ERROR
;
2449 OldFileInfo
= AllocatePool (OldInfoSize
);
2450 if (OldFileInfo
== NULL
) {
2451 Status
= EFI_OUT_OF_RESOURCES
;
2455 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
2457 if (EFI_ERROR (Status
)) {
2461 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
2462 if (OldFileName
== NULL
) {
2463 Status
= EFI_OUT_OF_RESOURCES
;
2467 StrCpy (OldFileName
, PrivateFile
->FileName
);
2470 // Make full pathname from new filename and rootpath.
2472 if (NewFileInfo
->FileName
[0] == '\\') {
2473 Size
= StrSize (PrivateRoot
->FilePath
);
2474 Size
+= StrSize (L
"\\");
2475 Size
+= StrSize (NewFileInfo
->FileName
);
2476 NewFileName
= AllocatePool (Size
);
2477 if (NewFileName
== NULL
) {
2478 Status
= EFI_OUT_OF_RESOURCES
;
2482 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
2483 StrCat (NewFileName
, L
"\\");
2484 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
2486 Size
= StrSize (PrivateFile
->FilePath
);
2487 Size
+= StrSize (L
"\\");
2488 Size
+= StrSize (NewFileInfo
->FileName
);
2489 NewFileName
= AllocatePool (Size
);
2490 if (NewFileName
== NULL
) {
2491 Status
= EFI_OUT_OF_RESOURCES
;
2495 StrCpy (NewFileName
, PrivateFile
->FilePath
);
2496 StrCat (NewFileName
, L
"\\");
2497 StrCat (NewFileName
, NewFileInfo
->FileName
);
2501 // Is there an attribute change request?
2503 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
2504 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
2505 Status
= EFI_INVALID_PARAMETER
;
2509 AttrChangeFlag
= TRUE
;
2513 // Is there a name change request?
2514 // bugbug: - Need EfiStrCaseCmp()
2516 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
2517 NameChangeFlag
= TRUE
;
2521 // Is there a size change request?
2523 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
2524 SizeChangeFlag
= TRUE
;
2528 // Is there a time stamp change request?
2530 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
2531 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
2533 TimeChangeFlag
= TRUE
;
2534 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
2535 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
2537 TimeChangeFlag
= TRUE
;
2538 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
2539 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
2541 TimeChangeFlag
= TRUE
;
2545 // All done if there are no change requests being made.
2547 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
2548 Status
= EFI_SUCCESS
;
2553 // Set file or directory information.
2555 OldAttr
= PrivateFile
->WinNtThunk
->GetFileAttributes (OldFileName
);
2560 if (NameChangeFlag
) {
2562 // Close the handles first
2564 if (PrivateFile
->IsOpenedByRead
) {
2565 Status
= EFI_ACCESS_DENIED
;
2569 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
2572 if (*CharPointer
!= 0) {
2573 Status
= EFI_ACCESS_DENIED
;
2577 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
2578 if (PrivateFile
->IsDirectoryPath
) {
2579 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
2581 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
2582 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
2586 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
2587 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
2588 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
2591 NtStatus
= PrivateFile
->WinNtThunk
->MoveFile (OldFileName
, NewFileName
);
2597 FreePool (PrivateFile
->FileName
);
2599 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
2600 if (PrivateFile
->FileName
== NULL
) {
2601 Status
= EFI_OUT_OF_RESOURCES
;
2605 StrCpy (PrivateFile
->FileName
, NewFileName
);
2607 Size
= StrSize (NewFileName
);
2608 Size
+= StrSize (L
"\\*");
2609 TempFileName
= AllocatePool (Size
);
2611 StrCpy (TempFileName
, NewFileName
);
2613 if (!PrivateFile
->IsDirectoryPath
) {
2614 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2616 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2617 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2624 FreePool (TempFileName
);
2627 // Flush buffers just in case
2629 if (PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2630 Status
= EFI_DEVICE_ERROR
;
2634 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2636 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2637 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2640 FILE_FLAG_BACKUP_SEMANTICS
,
2644 StrCat (TempFileName
, L
"\\*");
2645 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2647 FreePool (TempFileName
);
2650 Status
= EFI_ACCESS_DENIED
;
2653 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (OldFileName
, OldAttr
);
2659 Size
= StrSize (OldFileName
);
2660 Size
+= StrSize (L
"\\*");
2661 TempFileName
= AllocatePool (Size
);
2663 StrCpy (TempFileName
, OldFileName
);
2665 if (!PrivateFile
->IsDirectoryPath
) {
2666 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2668 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2669 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2676 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2678 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2679 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2682 FILE_FLAG_BACKUP_SEMANTICS
,
2686 StrCat (TempFileName
, L
"\\*");
2687 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2690 FreePool (TempFileName
);
2700 if (SizeChangeFlag
) {
2701 if (PrivateFile
->IsDirectoryPath
) {
2702 Status
= EFI_UNSUPPORTED
;
2706 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2707 Status
= EFI_ACCESS_DENIED
;
2711 Status
= This
->GetPosition (This
, &CurPos
);
2712 if (EFI_ERROR (Status
)) {
2716 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2717 if (EFI_ERROR (Status
)) {
2721 if (PrivateFile
->WinNtThunk
->SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2722 Status
= EFI_DEVICE_ERROR
;
2726 Status
= This
->SetPosition (This
, CurPos
);
2727 if (EFI_ERROR (Status
)) {
2735 if (TimeChangeFlag
) {
2737 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2738 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2739 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2740 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2741 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2742 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2743 NewCreationSystemTime
.wMilliseconds
= 0;
2745 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2746 &NewCreationSystemTime
,
2747 &NewCreationFileTime
2752 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2753 &NewCreationFileTime
,
2754 &NewCreationFileTime
2759 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2760 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2761 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2762 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2763 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2764 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2765 NewLastAccessSystemTime
.wMilliseconds
= 0;
2767 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2768 &NewLastAccessSystemTime
,
2769 &NewLastAccessFileTime
2774 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2775 &NewLastAccessFileTime
,
2776 &NewLastAccessFileTime
2781 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2782 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2783 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2784 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2785 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2786 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2787 NewLastWriteSystemTime
.wMilliseconds
= 0;
2789 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2790 &NewLastWriteSystemTime
,
2791 &NewLastWriteFileTime
2796 if (!PrivateFile
->WinNtThunk
->LocalFileTimeToFileTime (
2797 &NewLastWriteFileTime
,
2798 &NewLastWriteFileTime
2803 if (!PrivateFile
->WinNtThunk
->SetFileTime (
2804 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2805 &NewCreationFileTime
,
2806 &NewLastAccessFileTime
,
2807 &NewLastWriteFileTime
2809 Status
= EFI_DEVICE_ERROR
;
2816 // No matter about AttrChangeFlag, Attribute must be set.
2817 // Because operation before may cause attribute change.
2821 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2822 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2824 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2827 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2828 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2830 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2833 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2834 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2836 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2839 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2840 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2842 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2845 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (NewFileName
, NewAttr
);
2848 Status
= EFI_DEVICE_ERROR
;
2853 if (OldFileInfo
!= NULL
) {
2854 FreePool (OldFileInfo
);
2857 if (OldFileName
!= NULL
) {
2858 FreePool (OldFileName
);
2861 if (NewFileName
!= NULL
) {
2862 FreePool (NewFileName
);
2865 gBS
->RestoreTPL (OldTpl
);
2871 WinNtSimpleFileSystemFlush (
2872 IN EFI_FILE_PROTOCOL
*This
2876 Routine Description:
2878 Flush all modified data to the media.
2882 This - Pointer to an opened file handle.
2886 EFI_SUCCESS - The data has been flushed.
2888 EFI_NO_MEDIA - The device has no media.
2890 EFI_DEVICE_ERROR - The device reported an error.
2892 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2894 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2896 EFI_ACCESS_DENIED - The file was opened read-only.
2898 EFI_VOLUME_FULL - The volume is full.
2901 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2903 BY_HANDLE_FILE_INFORMATION FileInfo
;
2904 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2909 return EFI_INVALID_PARAMETER
;
2912 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2914 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2916 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2917 Status
= EFI_DEVICE_ERROR
;
2921 if (PrivateFile
->IsDirectoryPath
) {
2922 Status
= EFI_SUCCESS
;
2926 if (PrivateFile
->IsOpenedByRead
) {
2927 Status
= EFI_ACCESS_DENIED
;
2931 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2933 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2934 Status
= EFI_ACCESS_DENIED
;
2938 Status
= PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2941 gBS
->RestoreTPL (OldTpl
);
2944 // bugbug: - Use Windows error reporting.