3 Copyright (c) 2006 - 2009, Intel Corporation
4 All rights reserved. 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
,
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
;
548 if (This
== NULL
|| Root
== NULL
) {
549 return EFI_INVALID_PARAMETER
;
552 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
554 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
556 PrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
557 if (PrivateFile
== NULL
) {
558 Status
= EFI_OUT_OF_RESOURCES
;
562 PrivateFile
->FileName
= AllocatePool (StrSize (Private
->FilePath
));
563 if (PrivateFile
->FileName
== NULL
) {
564 Status
= EFI_OUT_OF_RESOURCES
;
568 PrivateFile
->FilePath
= AllocatePool (StrSize (Private
->FilePath
));
569 if (PrivateFile
->FilePath
== NULL
) {
570 Status
= EFI_OUT_OF_RESOURCES
;
574 StrCpy (PrivateFile
->FilePath
, Private
->FilePath
);
575 StrCpy (PrivateFile
->FileName
, PrivateFile
->FilePath
);
576 PrivateFile
->Signature
= WIN_NT_EFI_FILE_PRIVATE_SIGNATURE
;
577 PrivateFile
->WinNtThunk
= Private
->WinNtThunk
;
578 PrivateFile
->SimpleFileSystem
= This
;
579 PrivateFile
->IsRootDirectory
= TRUE
;
580 PrivateFile
->IsDirectoryPath
= TRUE
;
581 PrivateFile
->IsOpenedByRead
= TRUE
;
582 PrivateFile
->EfiFile
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
583 PrivateFile
->EfiFile
.Open
= WinNtSimpleFileSystemOpen
;
584 PrivateFile
->EfiFile
.Close
= WinNtSimpleFileSystemClose
;
585 PrivateFile
->EfiFile
.Delete
= WinNtSimpleFileSystemDelete
;
586 PrivateFile
->EfiFile
.Read
= WinNtSimpleFileSystemRead
;
587 PrivateFile
->EfiFile
.Write
= WinNtSimpleFileSystemWrite
;
588 PrivateFile
->EfiFile
.GetPosition
= WinNtSimpleFileSystemGetPosition
;
589 PrivateFile
->EfiFile
.SetPosition
= WinNtSimpleFileSystemSetPosition
;
590 PrivateFile
->EfiFile
.GetInfo
= WinNtSimpleFileSystemGetInfo
;
591 PrivateFile
->EfiFile
.SetInfo
= WinNtSimpleFileSystemSetInfo
;
592 PrivateFile
->EfiFile
.Flush
= WinNtSimpleFileSystemFlush
;
593 PrivateFile
->IsValidFindBuf
= FALSE
;
598 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
599 PrivateFile
->FilePath
,
601 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
604 FILE_FLAG_BACKUP_SEMANTICS
,
608 if (PrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
609 Status
= EFI_NOT_FOUND
;
614 // Find the first file under it
616 Status
= gBS
->AllocatePool (
618 StrSize (PrivateFile
->FilePath
) + StrSize (L
"\\*"),
621 if (EFI_ERROR (Status
)) {
624 StrCpy (TempFileName
, PrivateFile
->FilePath
);
625 StrCat (TempFileName
, L
"\\*");
627 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &PrivateFile
->FindBuf
);
629 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
630 PrivateFile
->IsValidFindBuf
= FALSE
;
632 PrivateFile
->IsValidFindBuf
= TRUE
;
634 *Root
= &PrivateFile
->EfiFile
;
636 Status
= EFI_SUCCESS
;
639 if (EFI_ERROR (Status
)) {
641 if (PrivateFile
->FileName
) {
642 FreePool (PrivateFile
->FileName
);
645 if (PrivateFile
->FilePath
) {
646 FreePool (PrivateFile
->FilePath
);
649 FreePool (PrivateFile
);
653 gBS
->RestoreTPL (OldTpl
);
659 Count the number of Leading Dot in FileNameToken.
661 @param FileNameToken A string representing a token in the path name.
663 @return UINTN The number of leading dot in the name.
668 IN CONST CHAR16
* FileNameToken
674 while (*FileNameToken
== L
'.') {
683 IsFileNameTokenValid (
684 IN CONST CHAR16
* FileNameToken
688 if (StrStr (FileNameToken
, L
"/") != NULL
) {
690 // No L'/' in file name.
695 // If Token has all dot, the number should not exceed 2
697 Num
= CountLeadingDots (FileNameToken
);
699 if (Num
== StrLen (FileNameToken
)) {
701 // If the FileNameToken only contains a number of L'.'.
713 Return the first string token found in the indirect pointer a String named by FileName.
715 On input, FileName is a indirect pointer pointing to a String.
716 On output, FileName is a updated to point to the next character after the first
717 found L"\" or NULL if there is no L"\" found.
719 @param FileName A indirect pointer pointing to a FileName.
721 @return Token The first string token found before a L"\".
725 GetNextFileNameToken (
726 IN OUT CONST CHAR16
** FileName
732 ASSERT (**FileName
!= L
'\\');
733 ASSERT (**FileName
!= L
'\0');
735 SlashPos
= StrStr (*FileName
, L
"\\");
736 if (SlashPos
== NULL
) {
737 Token
= AllocateCopyPool (StrSize(*FileName
), *FileName
);
740 Offset
= SlashPos
- *FileName
;
741 Token
= AllocateZeroPool ((Offset
+ 1) * sizeof (CHAR16
));
742 StrnCpy (Token
, *FileName
, Offset
);
744 // Point *FileName to the next character after L'\'.
746 *FileName
= *FileName
+ Offset
+ 1;
753 Check if a FileName contains only Valid Characters.
755 If FileName contains only a single L'\', return TRUE.
756 If FileName contains two adjacent L'\', return FALSE.
757 If FileName conatins L'/' , return FALSE.
758 If FielName contains more than two dots seperated with other FileName characters
759 by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
761 @param FileName The File Name String to check.
763 @return TRUE FileName only contains valid characters.
764 @return FALSE FileName contains at least one invalid character.
770 IN CONST CHAR16
*FileName
777 // If FileName is just L'\', then it is a valid pathname.
779 if (StrCmp (FileName
, L
"\\") == 0) {
783 // We don't support two or more adjacent L'\'.
785 if (StrStr (FileName
, L
"\\\\") != NULL
) {
790 // Is FileName has a leading L"\", skip to next character.
792 if (FileName
[0] == L
'\\') {
797 Token
= GetNextFileNameToken (&FileName
);
798 Valid
= IsFileNameTokenValid (Token
);
803 } while (FileName
!= NULL
);
810 WinNtSimpleFileSystemOpen (
812 OUT EFI_FILE
**NewHandle
,
821 Open a file relative to the source file location.
825 This - A pointer to the seource file location.
827 NewHandle - Pointer to storage for the new file handle.
829 FileName - Pointer to the file name to be opened.
831 OpenMode - File open mode information.
833 Attributes - File creation attributes.
837 EFI_SUCCESS - The file was opened.
839 EFI_NOT_FOUND - The file could not be found in the volume.
841 EFI_NO_MEDIA - The device has no media.
843 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
845 EFI_DEVICE_ERROR - The device reported an error.
847 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
849 EFI_WRITE_PROTECTED - The volume or file is write protected.
851 EFI_ACCESS_DENIED - The service denied access to the file.
853 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
855 EFI_VOLUME_FULL - There is not enough space left to create the new file.
858 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
859 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
860 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
861 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
863 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
864 WIN_NT_EFI_FILE_PRIVATE
*NewPrivateFile
;
865 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
867 CHAR16
*RealFileName
;
868 CHAR16
*TempFileName
;
869 CHAR16
*ParseFileName
;
870 CHAR16
*GuardPointer
;
880 // Check for obvious invalid parameters.
882 if (This
== NULL
|| NewHandle
== NULL
|| FileName
== NULL
) {
883 return EFI_INVALID_PARAMETER
;
887 case EFI_FILE_MODE_CREATE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
888 if (Attributes
&~EFI_FILE_VALID_ATTR
) {
889 return EFI_INVALID_PARAMETER
;
892 if (Attributes
& EFI_FILE_READ_ONLY
) {
893 return EFI_INVALID_PARAMETER
;
899 case EFI_FILE_MODE_READ
:
900 case EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
904 return EFI_INVALID_PARAMETER
;
908 // Init local variables
910 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
911 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
912 NewPrivateFile
= NULL
;
915 // Allocate buffer for FileName as the passed in FileName may be read only
917 TempFileName
= AllocatePool (StrSize (FileName
));
918 if (TempFileName
== NULL
) {
919 return EFI_OUT_OF_RESOURCES
;
921 StrCpy (TempFileName
, FileName
);
922 FileName
= TempFileName
;
924 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
925 FileName
[StrLen (FileName
) - 1] = 0;
929 // If file name does not equal to "." or ".." and not trailed with "\..",
930 // then we trim the leading/trailing blanks and trailing dots
932 if (StrCmp (FileName
, L
".") != 0 && StrCmp (FileName
, L
"..") != 0 &&
933 ((StrLen (FileName
) >= 3) ? (StrCmp (&FileName
[StrLen (FileName
) - 3], L
"\\..") != 0) : TRUE
)) {
935 // Trim leading blanks
938 for (TempFileName
= FileName
;
939 *TempFileName
!= 0 && *TempFileName
== L
' ';
943 CutPrefix (FileName
, Count
);
945 // Trim trailing blanks
947 for (TempFileName
= FileName
+ StrLen (FileName
) - 1;
948 TempFileName
>= FileName
&& (*TempFileName
== L
' ');
952 *(TempFileName
+ 1) = 0;
956 // Attempt to open the file
958 NewPrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
959 if (NewPrivateFile
== NULL
) {
960 Status
= EFI_OUT_OF_RESOURCES
;
964 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (WIN_NT_EFI_FILE_PRIVATE
));
966 NewPrivateFile
->FilePath
= AllocatePool (StrSize (PrivateFile
->FileName
));
967 if (NewPrivateFile
->FilePath
== NULL
) {
968 Status
= EFI_OUT_OF_RESOURCES
;
972 if (PrivateFile
->IsDirectoryPath
) {
973 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FileName
);
975 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FilePath
);
978 Size
= StrSize (NewPrivateFile
->FilePath
);
979 Size
+= StrSize (L
"\\");
980 Size
+= StrSize (FileName
);
981 NewPrivateFile
->FileName
= AllocatePool (Size
);
982 if (NewPrivateFile
->FileName
== NULL
) {
983 Status
= EFI_OUT_OF_RESOURCES
;
987 if (*FileName
== L
'\\') {
988 StrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
989 StrCat (NewPrivateFile
->FileName
, L
"\\");
990 StrCat (NewPrivateFile
->FileName
, FileName
+ 1);
992 StrCpy (NewPrivateFile
->FileName
, NewPrivateFile
->FilePath
);
993 if (StrCmp (FileName
, L
"") != 0) {
995 // In case the filename becomes empty, especially after trimming dots and blanks
997 StrCat (NewPrivateFile
->FileName
, L
"\\");
998 StrCat (NewPrivateFile
->FileName
, FileName
);
1002 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
1003 Status
= EFI_NOT_FOUND
;
1008 // Get rid of . and .., except leading . or ..
1012 // GuardPointer protect simplefilesystem root path not be destroyed
1014 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
1018 while (!LoopFinish
) {
1022 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
1023 if (*ParseFileName
== L
'.' &&
1024 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
1025 *(ParseFileName
- 1) == L
'\\'
1031 CutPrefix (ParseFileName
- 1, 2);
1036 if (*ParseFileName
== L
'.' &&
1037 *(ParseFileName
+ 1) == L
'.' &&
1038 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
1039 *(ParseFileName
- 1) == L
'\\'
1045 while (ParseFileName
!= GuardPointer
) {
1048 if (*ParseFileName
== L
'\\') {
1054 // cut \.. and its left directory
1056 CutPrefix (ParseFileName
, Count
);
1063 RealFileName
= NewPrivateFile
->FileName
;
1064 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
1065 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
1069 if (RealFileName
!= NewPrivateFile
->FileName
) {
1070 TempChar
= *(RealFileName
- 1);
1071 *(RealFileName
- 1) = 0;
1074 FreePool (NewPrivateFile
->FilePath
);
1075 NewPrivateFile
->FilePath
= NULL
;
1076 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
1077 if (NewPrivateFile
->FilePath
== NULL
) {
1078 Status
= EFI_OUT_OF_RESOURCES
;
1082 StrCpy (NewPrivateFile
->FilePath
, NewPrivateFile
->FileName
);
1083 if (TempChar
!= 0) {
1084 *(RealFileName
- 1) = TempChar
;
1087 NewPrivateFile
->IsRootDirectory
= FALSE
;
1090 // Test whether file or directory
1092 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
1093 if (Attributes
& EFI_FILE_DIRECTORY
) {
1094 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1096 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1099 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1100 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1101 NewPrivateFile
->FileName
,
1103 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1110 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1111 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1112 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1114 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1117 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1120 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
1121 NewPrivateFile
->IsOpenedByRead
= FALSE
;
1123 NewPrivateFile
->IsOpenedByRead
= TRUE
;
1126 Status
= EFI_SUCCESS
;
1129 // deal with directory
1131 if (NewPrivateFile
->IsDirectoryPath
) {
1133 Size
= StrSize (NewPrivateFile
->FileName
);
1134 Size
+= StrSize (L
"\\*");
1135 TempFileName
= AllocatePool (Size
);
1136 if (TempFileName
== NULL
) {
1137 Status
= EFI_OUT_OF_RESOURCES
;
1141 StrCpy (TempFileName
, NewPrivateFile
->FileName
);
1143 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
1145 // Create a directory
1147 if (!NewPrivateFile
->WinNtThunk
->CreateDirectory (TempFileName
, NULL
)) {
1149 LastError
= PrivateFile
->WinNtThunk
->GetLastError ();
1150 if (LastError
!= ERROR_ALREADY_EXISTS
) {
1151 FreePool (TempFileName
);
1152 Status
= EFI_ACCESS_DENIED
;
1158 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1160 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
1161 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1164 FILE_FLAG_BACKUP_SEMANTICS
,
1168 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
1170 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1173 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1176 FILE_FLAG_BACKUP_SEMANTICS
,
1180 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1181 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->DirHandle
);
1182 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1183 Status
= EFI_ACCESS_DENIED
;
1185 Status
= EFI_NOT_FOUND
;
1192 // Find the first file under it
1194 StrCat (TempFileName
, L
"\\*");
1195 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
1197 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1198 NewPrivateFile
->IsValidFindBuf
= FALSE
;
1200 NewPrivateFile
->IsValidFindBuf
= TRUE
;
1206 if (!NewPrivateFile
->IsOpenedByRead
) {
1207 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1208 NewPrivateFile
->FileName
,
1209 GENERIC_READ
| GENERIC_WRITE
,
1210 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1212 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
1217 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1218 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1219 NewPrivateFile
->FileName
,
1221 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1228 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1229 Status
= EFI_NOT_FOUND
;
1231 Status
= EFI_ACCESS_DENIED
;
1232 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1233 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1237 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1238 NewPrivateFile
->FileName
,
1240 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1247 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1248 Status
= EFI_NOT_FOUND
;
1253 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
1255 // Set the attribute
1260 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1262 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1263 Status
= EFI_DEVICE_ERROR
;
1267 Info
= AllocatePool (InfoSize
);
1269 Status
= EFI_OUT_OF_RESOURCES
;
1273 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1275 if (EFI_ERROR (Status
)) {
1279 Info
->Attribute
= Attributes
;
1281 WinNtSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
1285 FreePool (FileName
);
1287 if (EFI_ERROR (Status
)) {
1288 if (NewPrivateFile
) {
1289 if (NewPrivateFile
->FileName
) {
1290 FreePool (NewPrivateFile
->FileName
);
1293 if (NewPrivateFile
->FilePath
) {
1294 FreePool (NewPrivateFile
->FilePath
);
1297 FreePool (NewPrivateFile
);
1300 *NewHandle
= &NewPrivateFile
->EfiFile
;
1301 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
1302 NewPrivateFile
->IsRootDirectory
= TRUE
;
1311 WinNtSimpleFileSystemClose (
1316 Routine Description:
1318 Close the specified file handle.
1322 This - Pointer to a returned opened file handle.
1326 EFI_SUCCESS - The file handle has been closed.
1329 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1331 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1335 return EFI_INVALID_PARAMETER
;
1338 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1340 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1342 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1343 if (PrivateFile
->IsDirectoryPath
) {
1344 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1346 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1349 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1352 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1353 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1354 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1357 if (PrivateFile
->FileName
) {
1358 FreePool (PrivateFile
->FileName
);
1361 FreePool (PrivateFile
);
1363 gBS
->RestoreTPL (OldTpl
);
1370 WinNtSimpleFileSystemDelete (
1375 Routine Description:
1377 Close and delete a file.
1381 This - Pointer to a returned opened file handle.
1385 EFI_SUCCESS - The file handle was closed and deleted.
1387 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1390 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1393 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1397 return EFI_INVALID_PARAMETER
;
1400 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1402 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1404 Status
= EFI_WARN_DELETE_FAILURE
;
1406 if (PrivateFile
->IsDirectoryPath
) {
1407 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1408 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1411 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1412 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1413 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1416 if (PrivateFile
->WinNtThunk
->RemoveDirectory (PrivateFile
->FileName
)) {
1417 Status
= EFI_SUCCESS
;
1420 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1421 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1423 if (!PrivateFile
->IsOpenedByRead
) {
1424 if (PrivateFile
->WinNtThunk
->DeleteFile (PrivateFile
->FileName
)) {
1425 Status
= EFI_SUCCESS
;
1430 FreePool (PrivateFile
->FileName
);
1431 FreePool (PrivateFile
);
1433 gBS
->RestoreTPL (OldTpl
);
1439 WinNtSystemTimeToEfiTime (
1440 IN SYSTEMTIME
*SystemTime
,
1441 IN TIME_ZONE_INFORMATION
*TimeZone
,
1446 Routine Description:
1448 TODO: Add function description
1452 SystemTime - TODO: add argument description
1453 TimeZone - TODO: add argument description
1454 Time - TODO: add argument description
1458 TODO: add return values
1462 Time
->Year
= (UINT16
) SystemTime
->wYear
;
1463 Time
->Month
= (UINT8
) SystemTime
->wMonth
;
1464 Time
->Day
= (UINT8
) SystemTime
->wDay
;
1465 Time
->Hour
= (UINT8
) SystemTime
->wHour
;
1466 Time
->Minute
= (UINT8
) SystemTime
->wMinute
;
1467 Time
->Second
= (UINT8
) SystemTime
->wSecond
;
1468 Time
->Nanosecond
= (UINT32
) SystemTime
->wMilliseconds
* 1000000;
1469 Time
->TimeZone
= (INT16
) TimeZone
->Bias
;
1471 if (TimeZone
->StandardDate
.wMonth
) {
1472 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1478 WinNtSimpleFileSystemRead (
1480 IN OUT UINTN
*BufferSize
,
1485 Routine Description:
1487 Read data from a file.
1491 This - Pointer to a returned open file handle.
1493 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1495 Buffer - Pointer to the first byte of the read Buffer.
1499 EFI_SUCCESS - The data was read.
1501 EFI_NO_MEDIA - The device has no media.
1503 EFI_DEVICE_ERROR - The device reported an error.
1505 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1507 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1508 *BufferSize has been updated with the size needed to complete the request.
1511 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1513 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1519 SYSTEMTIME SystemTime
;
1520 EFI_FILE_INFO
*Info
;
1522 TIME_ZONE_INFORMATION TimeZone
;
1523 EFI_FILE_INFO
*FileInfo
;
1529 if (This
== NULL
|| BufferSize
== NULL
) {
1530 return EFI_INVALID_PARAMETER
;
1533 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1535 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1537 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1538 Status
= EFI_DEVICE_ERROR
;
1542 if (!PrivateFile
->IsDirectoryPath
) {
1544 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1545 Status
= EFI_DEVICE_ERROR
;
1549 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1550 FileInfo
= AllocatePool (FileInfoSize
);
1552 Status
= This
->GetInfo (
1559 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1560 FreePool (FileInfo
);
1561 FileInfo
= AllocatePool (FileInfoSize
);
1562 Status
= This
->GetInfo (
1570 if (EFI_ERROR (Status
)) {
1571 Status
= EFI_DEVICE_ERROR
;
1575 FileSize
= FileInfo
->FileSize
;
1577 FreePool (FileInfo
);
1579 if (Pos
>= FileSize
) {
1581 if (Pos
== FileSize
) {
1582 Status
= EFI_SUCCESS
;
1585 Status
= EFI_DEVICE_ERROR
;
1590 Status
= PrivateFile
->WinNtThunk
->ReadFile (
1591 PrivateFile
->LHandle
,
1594 (LPDWORD
)BufferSize
,
1596 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1601 // Read on a directory. Perform a find next
1603 if (!PrivateFile
->IsValidFindBuf
) {
1605 Status
= EFI_SUCCESS
;
1609 Size
= SIZE_OF_EFI_FILE_INFO
;
1611 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1613 ResultSize
= Size
+ NameSize
;
1615 Status
= EFI_BUFFER_TOO_SMALL
;
1617 if (*BufferSize
>= ResultSize
) {
1618 Status
= EFI_SUCCESS
;
1621 ZeroMem (Info
, ResultSize
);
1623 Info
->Size
= ResultSize
;
1625 PrivateFile
->WinNtThunk
->GetTimeZoneInformation (&TimeZone
);
1627 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1628 &PrivateFile
->FindBuf
.ftCreationTime
,
1629 &PrivateFile
->FindBuf
.ftCreationTime
1632 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftCreationTime
, &SystemTime
);
1634 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->CreateTime
);
1636 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1637 &PrivateFile
->FindBuf
.ftLastWriteTime
,
1638 &PrivateFile
->FindBuf
.ftLastWriteTime
1641 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftLastWriteTime
, &SystemTime
);
1643 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->ModificationTime
);
1645 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1647 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1649 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1650 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1653 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1654 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1657 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1658 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1661 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1662 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1665 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1666 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1669 NameSize
= NameSize
/ sizeof (WCHAR
);
1671 pw
= (WCHAR
*) (((CHAR8
*) Buffer
) + Size
);
1673 for (Index
= 0; Index
< NameSize
; Index
++) {
1674 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1677 if (PrivateFile
->WinNtThunk
->FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1678 PrivateFile
->IsValidFindBuf
= TRUE
;
1680 PrivateFile
->IsValidFindBuf
= FALSE
;
1684 *BufferSize
= ResultSize
;
1687 gBS
->RestoreTPL (OldTpl
);
1693 WinNtSimpleFileSystemWrite (
1695 IN OUT UINTN
*BufferSize
,
1700 Routine Description:
1702 Write data to a file.
1706 This - Pointer to an opened file handle.
1708 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1709 of data written to the file.
1711 Buffer - Pointer to the first by of data in the buffer to write to the file.
1715 EFI_SUCCESS - The data was written to the file.
1717 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1719 EFI_NO_MEDIA - The device has no media.
1721 EFI_DEVICE_ERROR - The device reported an error.
1723 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1725 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1727 EFI_ACCESS_DENIED - The file was opened read-only.
1729 EFI_VOLUME_FULL - The volume is full.
1732 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1734 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1738 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1739 return EFI_INVALID_PARAMETER
;
1742 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1744 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1746 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1747 Status
= EFI_DEVICE_ERROR
;
1751 if (PrivateFile
->IsDirectoryPath
) {
1752 Status
= EFI_UNSUPPORTED
;
1756 if (PrivateFile
->IsOpenedByRead
) {
1757 Status
= EFI_ACCESS_DENIED
;
1761 Status
= PrivateFile
->WinNtThunk
->WriteFile (
1762 PrivateFile
->LHandle
,
1765 (LPDWORD
)BufferSize
,
1767 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1770 gBS
->RestoreTPL (OldTpl
);
1774 // bugbug: need to access windows error reporting
1780 WinNtSimpleFileSystemSetPosition (
1786 Routine Description:
1788 Set a file's current position.
1792 This - Pointer to an opened file handle.
1794 Position - The byte position from the start of the file to set.
1798 EFI_SUCCESS - The file position has been changed.
1800 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1803 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1806 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1814 return EFI_INVALID_PARAMETER
;
1817 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1819 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1821 if (PrivateFile
->IsDirectoryPath
) {
1822 if (Position
!= 0) {
1823 Status
= EFI_UNSUPPORTED
;
1827 Size
= StrSize (PrivateFile
->FileName
);
1828 Size
+= StrSize (L
"\\*");
1829 FileName
= AllocatePool (Size
);
1830 if (FileName
== NULL
) {
1831 Status
= EFI_OUT_OF_RESOURCES
;
1835 StrCpy (FileName
, PrivateFile
->FileName
);
1836 StrCat (FileName
, L
"\\*");
1838 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1839 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1842 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1844 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1845 PrivateFile
->IsValidFindBuf
= FALSE
;
1847 PrivateFile
->IsValidFindBuf
= TRUE
;
1850 FreePool (FileName
);
1852 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1854 if (Position
== (UINT64
) -1) {
1855 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) 0, NULL
, FILE_END
);
1857 PosHigh
= (UINT32
) RShiftU64 (Position
, 32);
1859 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) Position
, (PLONG
)&PosHigh
, FILE_BEGIN
);
1862 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1866 gBS
->RestoreTPL (OldTpl
);
1872 WinNtSimpleFileSystemGetPosition (
1874 OUT UINT64
*Position
1878 Routine Description:
1880 Get a file's current position.
1884 This - Pointer to an opened file handle.
1886 Position - Pointer to storage for the current position.
1890 EFI_SUCCESS - The file position has been reported.
1892 EFI_UNSUPPORTED - Not valid for directories.
1895 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1898 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1903 if (This
== NULL
|| Position
== NULL
) {
1904 return EFI_INVALID_PARAMETER
;
1907 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1908 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1913 if (PrivateFile
->IsDirectoryPath
) {
1915 Status
= EFI_UNSUPPORTED
;
1921 *Position
= PrivateFile
->WinNtThunk
->SetFilePointer (
1922 PrivateFile
->LHandle
,
1924 (PLONG
)&PositionHigh
,
1928 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1929 if (EFI_ERROR (Status
)) {
1933 PosHigh64
= PositionHigh
;
1934 *Position
+= LShiftU64 (PosHigh64
, 32);
1938 gBS
->RestoreTPL (OldTpl
);
1943 WinNtSimpleFileSystemFileInfo (
1944 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1945 IN OUT UINTN
*BufferSize
,
1950 Routine Description:
1952 TODO: Add function description
1956 PrivateFile - TODO: add argument description
1957 BufferSize - TODO: add argument description
1958 Buffer - TODO: add argument description
1962 TODO: add return values
1970 EFI_FILE_INFO
*Info
;
1971 BY_HANDLE_FILE_INFORMATION FileInfo
;
1972 SYSTEMTIME SystemTime
;
1973 CHAR16
*RealFileName
;
1974 CHAR16
*TempPointer
;
1975 EFI_FILE_INFO
*DirInfo
;
1978 EFI_STATUS DirStatus
;
1981 Size
= SIZE_OF_EFI_FILE_INFO
;
1982 NameSize
= StrSize (PrivateFile
->FileName
);
1983 ResultSize
= Size
+ NameSize
;
1985 Status
= EFI_BUFFER_TOO_SMALL
;
1986 if (*BufferSize
>= ResultSize
) {
1987 Status
= EFI_SUCCESS
;
1990 ZeroMem (Info
, ResultSize
);
1992 Info
->Size
= ResultSize
;
1993 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (
1994 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
1997 Info
->FileSize
= FileInfo
.nFileSizeLow
;
1998 Info
->PhysicalSize
= Info
->FileSize
;
2000 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftCreationTime
, &SystemTime
);
2001 Info
->CreateTime
.Year
= SystemTime
.wYear
;
2002 Info
->CreateTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2003 Info
->CreateTime
.Day
= (UINT8
) SystemTime
.wDay
;
2004 Info
->CreateTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2005 Info
->CreateTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2006 Info
->CreateTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2008 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastAccessTime
, &SystemTime
);
2009 Info
->LastAccessTime
.Year
= SystemTime
.wYear
;
2010 Info
->LastAccessTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2011 Info
->LastAccessTime
.Day
= (UINT8
) SystemTime
.wDay
;
2012 Info
->LastAccessTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2013 Info
->LastAccessTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2014 Info
->LastAccessTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2016 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastWriteTime
, &SystemTime
);
2017 Info
->ModificationTime
.Year
= SystemTime
.wYear
;
2018 Info
->ModificationTime
.Month
= (UINT8
) SystemTime
.wMonth
;
2019 Info
->ModificationTime
.Day
= (UINT8
) SystemTime
.wDay
;
2020 Info
->ModificationTime
.Hour
= (UINT8
) SystemTime
.wHour
;
2021 Info
->ModificationTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
2022 Info
->ModificationTime
.Second
= (UINT8
) SystemTime
.wSecond
;
2024 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
2025 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
2028 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
2029 Info
->Attribute
|= EFI_FILE_HIDDEN
;
2032 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2033 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
2036 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
2037 Info
->Attribute
|= EFI_FILE_SYSTEM
;
2040 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2041 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2044 if (PrivateFile
->IsDirectoryPath
) {
2045 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2048 RealFileName
= PrivateFile
->FileName
;
2049 TempPointer
= RealFileName
;
2051 while (*TempPointer
) {
2052 if (*TempPointer
== '\\') {
2053 RealFileName
= TempPointer
+ 1;
2059 if (PrivateFile
->IsRootDirectory
) {
2060 *((CHAR8
*) Buffer
+ Size
) = 0;
2062 CopyMem ((CHAR8
*) Buffer
+ Size
, RealFileName
, NameSize
);
2065 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
2067 // The GetFileInformationByHandle.nFileSizeLow is bogus for dir so we
2068 // need to do the same thing the caller would do to get the right value
2070 ASSERT (PrivateFile
->EfiFile
.Read
!= NULL
);
2071 DirStatus
= PrivateFile
->EfiFile
.GetPosition (&PrivateFile
->EfiFile
, &Location
);
2072 if (EFI_ERROR (DirStatus
)) {
2076 PrivateFile
->EfiFile
.SetPosition (&PrivateFile
->EfiFile
, 0);
2081 DirStatus
= PrivateFile
->EfiFile
.Read (&PrivateFile
->EfiFile
, &ReadSize
, DirInfo
);
2082 if (DirStatus
== EFI_BUFFER_TOO_SMALL
) {
2083 DirInfo
= AllocatePool (ReadSize
);
2084 if (DirInfo
!= NULL
) {
2086 // Read each dir entry to figure out how big the directory is
2088 DirStatus
= PrivateFile
->EfiFile
.Read (&PrivateFile
->EfiFile
, &ReadSize
, DirInfo
);
2089 if (!EFI_ERROR (DirStatus
) && (ReadSize
!= 0)) {
2090 Info
->FileSize
+= ReadSize
;
2096 } while (!EFI_ERROR (DirStatus
) && (ReadSize
!= 0));
2099 // reset the file possition back to the previous location
2101 PrivateFile
->EfiFile
.SetPosition (&PrivateFile
->EfiFile
, Location
);
2105 *BufferSize
= ResultSize
;
2111 WinNtSimpleFileSystemGetInfo (
2113 IN EFI_GUID
*InformationType
,
2114 IN OUT UINTN
*BufferSize
,
2119 Routine Description:
2121 Return information about a file or volume.
2125 This - Pointer to an opened file handle.
2127 InformationType - GUID describing the type of information to be returned.
2129 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
2132 Buffer - Pointer to the first byte of the information buffer.
2136 EFI_SUCCESS - The requested information has been written into the buffer.
2138 EFI_UNSUPPORTED - The InformationType is not known.
2140 EFI_NO_MEDIA - The device has no media.
2142 EFI_DEVICE_ERROR - The device reported an error.
2144 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2146 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
2147 been updated with the size needed to complete the requested operation.
2150 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2153 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2154 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
2155 UINT32 SectorsPerCluster
;
2156 UINT32 BytesPerSector
;
2157 UINT32 FreeClusters
;
2158 UINT32 TotalClusters
;
2159 UINT32 BytesPerCluster
;
2161 BOOLEAN DriveNameFound
;
2164 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2167 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
2168 return EFI_INVALID_PARAMETER
;
2171 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2173 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2174 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2176 Status
= EFI_UNSUPPORTED
;
2178 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2179 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
2182 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2183 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2184 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2185 Status
= EFI_BUFFER_TOO_SMALL
;
2189 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2190 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2191 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
2194 // Try to get the drive name
2196 DriveNameFound
= FALSE
;
2197 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
2198 if (DriveName
== NULL
) {
2199 Status
= EFI_OUT_OF_RESOURCES
;
2203 StrCpy (DriveName
, PrivateFile
->FilePath
);
2204 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
2208 if (DriveName
[Index
] == ':') {
2209 DriveName
[Index
+ 1] = '\\';
2210 DriveName
[Index
+ 2] = 0;
2211 DriveNameFound
= TRUE
;
2212 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
2213 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2217 if (DriveName
[Index
] == '\\') {
2218 DriveNameFound
= TRUE
;
2219 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2223 DriveName
[Index
] = '\\';
2224 DriveName
[Index
+ 1] = 0;
2229 // Try GetDiskFreeSpace first
2231 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpace (
2232 DriveNameFound
? DriveName
: NULL
,
2233 (LPDWORD
)&SectorsPerCluster
,
2234 (LPDWORD
)&BytesPerSector
,
2235 (LPDWORD
)&FreeClusters
,
2236 (LPDWORD
)&TotalClusters
2239 FreePool (DriveName
);
2246 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
2247 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
2248 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
2249 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
2253 // try GetDiskFreeSpaceEx then
2255 FileSystemInfoBuffer
->BlockSize
= 0;
2256 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpaceEx (
2257 PrivateFile
->FilePath
,
2258 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->FreeSpace
),
2259 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->VolumeSize
),
2263 Status
= EFI_DEVICE_ERROR
;
2268 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
2269 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2270 Status
= EFI_SUCCESS
;
2273 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2274 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2275 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2276 Status
= EFI_BUFFER_TOO_SMALL
;
2280 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
2281 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2282 Status
= EFI_SUCCESS
;
2286 gBS
->RestoreTPL (OldTpl
);
2292 WinNtSimpleFileSystemSetInfo (
2294 IN EFI_GUID
*InformationType
,
2295 IN UINTN BufferSize
,
2300 Routine Description:
2302 Set information about a file or volume.
2306 This - Pointer to an opened file handle.
2308 InformationType - GUID identifying the type of information to set.
2310 BufferSize - Number of bytes of data in the information buffer.
2312 Buffer - Pointer to the first byte of data in the information buffer.
2316 EFI_SUCCESS - The file or volume information has been updated.
2318 EFI_UNSUPPORTED - The information identifier is not recognised.
2320 EFI_NO_MEDIA - The device has no media.
2322 EFI_DEVICE_ERROR - The device reported an error.
2324 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2326 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2328 EFI_ACCESS_DENIED - The file was opened read-only.
2330 EFI_VOLUME_FULL - The volume is full.
2332 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2335 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2336 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2338 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2339 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2340 EFI_FILE_INFO
*OldFileInfo
;
2341 EFI_FILE_INFO
*NewFileInfo
;
2347 CHAR16
*OldFileName
;
2348 CHAR16
*NewFileName
;
2349 CHAR16
*TempFileName
;
2350 CHAR16
*CharPointer
;
2351 BOOLEAN AttrChangeFlag
;
2352 BOOLEAN NameChangeFlag
;
2353 BOOLEAN SizeChangeFlag
;
2354 BOOLEAN TimeChangeFlag
;
2356 SYSTEMTIME NewCreationSystemTime
;
2357 SYSTEMTIME NewLastAccessSystemTime
;
2358 SYSTEMTIME NewLastWriteSystemTime
;
2359 FILETIME NewCreationFileTime
;
2360 FILETIME NewLastAccessFileTime
;
2361 FILETIME NewLastWriteFileTime
;
2362 WIN32_FIND_DATA FindBuf
;
2363 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
2368 // Check for invalid parameters.
2370 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
2371 return EFI_INVALID_PARAMETER
;
2374 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2377 // Initialise locals.
2379 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2380 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2382 Status
= EFI_UNSUPPORTED
;
2383 OldFileInfo
= NewFileInfo
= NULL
;
2384 OldFileName
= NewFileName
= NULL
;
2385 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
2388 // Set file system information.
2390 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2391 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2392 Status
= EFI_BAD_BUFFER_SIZE
;
2396 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2398 FreePool (PrivateRoot
->VolumeLabel
);
2399 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
2400 if (PrivateRoot
->VolumeLabel
== NULL
) {
2401 Status
= EFI_OUT_OF_RESOURCES
;
2405 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
2407 Status
= EFI_SUCCESS
;
2412 // Set volume label information.
2414 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2415 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2416 Status
= EFI_BAD_BUFFER_SIZE
;
2420 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
2422 Status
= EFI_SUCCESS
;
2426 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2427 Status
= EFI_UNSUPPORTED
;
2431 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
2432 Status
= EFI_BAD_BUFFER_SIZE
;
2437 // Set file/directory information.
2441 // Check for invalid set file information parameters.
2443 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
2445 if (NewFileInfo
->Size
<= sizeof (EFI_FILE_INFO
) ||
2446 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
2447 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
2449 Status
= EFI_INVALID_PARAMETER
;
2454 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2455 // that would have an additional parameter that would be the size
2456 // of the string array just in case there are no NULL characters in
2457 // the string array.
2460 // Get current file information so we can determine what kind
2461 // of change request this is.
2464 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
2466 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2467 Status
= EFI_DEVICE_ERROR
;
2471 OldFileInfo
= AllocatePool (OldInfoSize
);
2472 if (OldFileInfo
== NULL
) {
2473 Status
= EFI_OUT_OF_RESOURCES
;
2477 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
2479 if (EFI_ERROR (Status
)) {
2483 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
2484 if (OldFileName
== NULL
) {
2485 Status
= EFI_OUT_OF_RESOURCES
;
2489 StrCpy (OldFileName
, PrivateFile
->FileName
);
2492 // Make full pathname from new filename and rootpath.
2494 if (NewFileInfo
->FileName
[0] == '\\') {
2495 Size
= StrSize (PrivateRoot
->FilePath
);
2496 Size
+= StrSize (L
"\\");
2497 Size
+= StrSize (NewFileInfo
->FileName
);
2498 NewFileName
= AllocatePool (Size
);
2499 if (NewFileName
== NULL
) {
2500 Status
= EFI_OUT_OF_RESOURCES
;
2504 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
2505 StrCat (NewFileName
, L
"\\");
2506 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
2508 Size
= StrSize (PrivateFile
->FilePath
);
2509 Size
+= StrSize (L
"\\");
2510 Size
+= StrSize (NewFileInfo
->FileName
);
2511 NewFileName
= AllocatePool (Size
);
2512 if (NewFileName
== NULL
) {
2513 Status
= EFI_OUT_OF_RESOURCES
;
2517 StrCpy (NewFileName
, PrivateFile
->FilePath
);
2518 StrCat (NewFileName
, L
"\\");
2519 StrCat (NewFileName
, NewFileInfo
->FileName
);
2523 // Is there an attribute change request?
2525 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
2526 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
2527 Status
= EFI_INVALID_PARAMETER
;
2531 AttrChangeFlag
= TRUE
;
2535 // Is there a name change request?
2536 // bugbug: - Need EfiStrCaseCmp()
2538 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
2539 NameChangeFlag
= TRUE
;
2543 // Is there a size change request?
2545 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
2546 SizeChangeFlag
= TRUE
;
2550 // Is there a time stamp change request?
2552 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
2553 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
2555 TimeChangeFlag
= TRUE
;
2556 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
2557 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
2559 TimeChangeFlag
= TRUE
;
2560 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
2561 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
2563 TimeChangeFlag
= TRUE
;
2567 // All done if there are no change requests being made.
2569 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
2570 Status
= EFI_SUCCESS
;
2575 // Set file or directory information.
2577 OldAttr
= PrivateFile
->WinNtThunk
->GetFileAttributes (OldFileName
);
2582 if (NameChangeFlag
) {
2584 // Close the handles first
2586 if (PrivateFile
->IsOpenedByRead
) {
2587 Status
= EFI_ACCESS_DENIED
;
2591 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
2594 if (*CharPointer
!= 0) {
2595 Status
= EFI_ACCESS_DENIED
;
2599 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
2600 if (PrivateFile
->IsDirectoryPath
) {
2601 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
2603 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
2604 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
2608 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
2609 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
2610 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
2613 NtStatus
= PrivateFile
->WinNtThunk
->MoveFile (OldFileName
, NewFileName
);
2619 FreePool (PrivateFile
->FileName
);
2621 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
2622 if (PrivateFile
->FileName
== NULL
) {
2623 Status
= EFI_OUT_OF_RESOURCES
;
2627 StrCpy (PrivateFile
->FileName
, NewFileName
);
2629 Size
= StrSize (NewFileName
);
2630 Size
+= StrSize (L
"\\*");
2631 TempFileName
= AllocatePool (Size
);
2633 StrCpy (TempFileName
, NewFileName
);
2635 if (!PrivateFile
->IsDirectoryPath
) {
2636 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2638 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2639 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2646 FreePool (TempFileName
);
2649 // Flush buffers just in case
2651 if (PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2652 Status
= EFI_DEVICE_ERROR
;
2656 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2658 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2659 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2662 FILE_FLAG_BACKUP_SEMANTICS
,
2666 StrCat (TempFileName
, L
"\\*");
2667 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2669 FreePool (TempFileName
);
2673 Status
= EFI_DEVICE_ERROR
;
2675 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (OldFileName
, OldAttr
);
2681 Size
= StrSize (OldFileName
);
2682 Size
+= StrSize (L
"\\*");
2683 TempFileName
= AllocatePool (Size
);
2685 StrCpy (TempFileName
, OldFileName
);
2687 if (!PrivateFile
->IsDirectoryPath
) {
2688 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2690 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2691 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2698 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2700 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2701 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2704 FILE_FLAG_BACKUP_SEMANTICS
,
2708 StrCat (TempFileName
, L
"\\*");
2709 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2712 FreePool (TempFileName
);
2722 if (SizeChangeFlag
) {
2723 if (PrivateFile
->IsDirectoryPath
) {
2724 Status
= EFI_UNSUPPORTED
;
2728 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2729 Status
= EFI_ACCESS_DENIED
;
2733 Status
= This
->GetPosition (This
, &CurPos
);
2734 if (EFI_ERROR (Status
)) {
2738 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2739 if (EFI_ERROR (Status
)) {
2743 if (PrivateFile
->WinNtThunk
->SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2744 Status
= EFI_DEVICE_ERROR
;
2748 Status
= This
->SetPosition (This
, CurPos
);
2749 if (EFI_ERROR (Status
)) {
2757 if (TimeChangeFlag
) {
2759 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2760 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2761 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2762 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2763 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2764 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2765 NewCreationSystemTime
.wMilliseconds
= 0;
2767 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2768 &NewCreationSystemTime
,
2769 &NewCreationFileTime
2774 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2775 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2776 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2777 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2778 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2779 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2780 NewLastAccessSystemTime
.wMilliseconds
= 0;
2782 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2783 &NewLastAccessSystemTime
,
2784 &NewLastAccessFileTime
2789 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2790 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2791 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2792 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2793 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2794 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2795 NewLastWriteSystemTime
.wMilliseconds
= 0;
2797 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2798 &NewLastWriteSystemTime
,
2799 &NewLastWriteFileTime
2804 if (!PrivateFile
->WinNtThunk
->SetFileTime (
2805 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2806 &NewCreationFileTime
,
2807 &NewLastAccessFileTime
,
2808 &NewLastWriteFileTime
2810 Status
= EFI_DEVICE_ERROR
;
2817 // No matter about AttrChangeFlag, Attribute must be set.
2818 // Because operation before may cause attribute change.
2822 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2823 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2825 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2828 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2829 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2831 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2834 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2835 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2837 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2840 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2841 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2843 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2846 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (NewFileName
, NewAttr
);
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 (
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.