3 Copyright (c) 2006 - 2008, 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
;
547 if (This
== NULL
|| Root
== NULL
) {
548 return EFI_INVALID_PARAMETER
;
551 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
553 Private
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This
);
555 PrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
556 if (PrivateFile
== NULL
) {
557 Status
= EFI_OUT_OF_RESOURCES
;
561 PrivateFile
->FileName
= AllocatePool (StrSize (Private
->FilePath
));
562 if (PrivateFile
->FileName
== NULL
) {
563 Status
= EFI_OUT_OF_RESOURCES
;
567 PrivateFile
->FilePath
= AllocatePool (StrSize (Private
->FilePath
));
568 if (PrivateFile
->FilePath
== NULL
) {
569 Status
= EFI_OUT_OF_RESOURCES
;
573 StrCpy (PrivateFile
->FilePath
, Private
->FilePath
);
574 StrCpy (PrivateFile
->FileName
, PrivateFile
->FilePath
);
575 PrivateFile
->Signature
= WIN_NT_EFI_FILE_PRIVATE_SIGNATURE
;
576 PrivateFile
->WinNtThunk
= Private
->WinNtThunk
;
577 PrivateFile
->SimpleFileSystem
= This
;
578 PrivateFile
->IsRootDirectory
= TRUE
;
579 PrivateFile
->IsDirectoryPath
= TRUE
;
580 PrivateFile
->IsOpenedByRead
= TRUE
;
581 PrivateFile
->EfiFile
.Revision
= EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION
;
582 PrivateFile
->EfiFile
.Open
= WinNtSimpleFileSystemOpen
;
583 PrivateFile
->EfiFile
.Close
= WinNtSimpleFileSystemClose
;
584 PrivateFile
->EfiFile
.Delete
= WinNtSimpleFileSystemDelete
;
585 PrivateFile
->EfiFile
.Read
= WinNtSimpleFileSystemRead
;
586 PrivateFile
->EfiFile
.Write
= WinNtSimpleFileSystemWrite
;
587 PrivateFile
->EfiFile
.GetPosition
= WinNtSimpleFileSystemGetPosition
;
588 PrivateFile
->EfiFile
.SetPosition
= WinNtSimpleFileSystemSetPosition
;
589 PrivateFile
->EfiFile
.GetInfo
= WinNtSimpleFileSystemGetInfo
;
590 PrivateFile
->EfiFile
.SetInfo
= WinNtSimpleFileSystemSetInfo
;
591 PrivateFile
->EfiFile
.Flush
= WinNtSimpleFileSystemFlush
;
592 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
593 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
594 PrivateFile
->IsValidFindBuf
= FALSE
;
596 *Root
= &PrivateFile
->EfiFile
;
598 Status
= EFI_SUCCESS
;
601 if (EFI_ERROR (Status
)) {
603 if (PrivateFile
->FileName
) {
604 FreePool (PrivateFile
->FileName
);
607 if (PrivateFile
->FilePath
) {
608 FreePool (PrivateFile
->FilePath
);
611 FreePool (PrivateFile
);
615 gBS
->RestoreTPL (OldTpl
);
621 Count the number of Leading Dot in FileNameToken.
623 @param FileNameToken A string representing a token in the path name.
625 @return UINTN The number of leading dot in the name.
630 IN CONST CHAR16
* FileNameToken
636 while (*FileNameToken
== L
'.') {
645 IsFileNameTokenValid (
646 IN CONST CHAR16
* FileNameToken
650 if (StrStr (FileNameToken
, L
"/") != NULL
) {
652 // No L'/' in file name.
657 // If Token has all dot, the number should not exceed 2
659 Num
= CountLeadingDots (FileNameToken
);
661 if (Num
== StrLen (FileNameToken
)) {
663 // If the FileNameToken only contains a number of L'.'.
675 Return the first string token found in the indirect pointer a String named by FileName.
677 On input, FileName is a indirect pointer pointing to a String.
678 On output, FileName is a updated to point to the next character after the first
679 found L"\" or NULL if there is no L"\" found.
681 @param FileName A indirect pointer pointing to a FileName.
683 @return Token The first string token found before a L"\".
687 GetNextFileNameToken (
688 IN OUT CONST CHAR16
** FileName
694 ASSERT (**FileName
!= L
'\\');
695 ASSERT (**FileName
!= L
'\0');
697 SlashPos
= StrStr (*FileName
, L
"\\");
698 if (SlashPos
== NULL
) {
699 Token
= AllocateCopyPool (StrSize(*FileName
), *FileName
);
702 Offset
= SlashPos
- *FileName
;
703 Token
= AllocateZeroPool ((Offset
+ 1) * sizeof (CHAR16
));
704 StrnCpy (Token
, *FileName
, Offset
);
706 // Point *FileName to the next character after L'\'.
708 *FileName
= *FileName
+ Offset
+ 1;
715 Check if a FileName contains only Valid Characters.
717 If FileName contains only a single L'\', return TRUE.
718 If FileName contains two adjacent L'\', return FALSE.
719 If FileName conatins L'/' , return FALSE.
720 If FielName contains more than two dots seperated with other FileName characters
721 by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
723 @param FileName The File Name String to check.
725 @return TRUE FileName only contains valid characters.
726 @return FALSE FileName contains at least one invalid character.
732 IN CONST CHAR16
*FileName
739 // If FileName is just L'\', then it is a valid pathname.
741 if (StrCmp (FileName
, L
"\\") == 0) {
745 // We don't support two or more adjacent L'\'.
747 if (StrStr (FileName
, L
"\\\\") != NULL
) {
752 // Is FileName has a leading L"\", skip to next character.
754 if (FileName
[0] == L
'\\') {
759 Token
= GetNextFileNameToken (&FileName
);
760 Valid
= IsFileNameTokenValid (Token
);
765 } while (FileName
!= NULL
);
772 WinNtSimpleFileSystemOpen (
774 OUT EFI_FILE
**NewHandle
,
783 Open a file relative to the source file location.
787 This - A pointer to the seource file location.
789 NewHandle - Pointer to storage for the new file handle.
791 FileName - Pointer to the file name to be opened.
793 OpenMode - File open mode information.
795 Attributes - File creation attributes.
799 EFI_SUCCESS - The file was opened.
801 EFI_NOT_FOUND - The file could not be found in the volume.
803 EFI_NO_MEDIA - The device has no media.
805 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
807 EFI_DEVICE_ERROR - The device reported an error.
809 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
811 EFI_WRITE_PROTECTED - The volume or file is write protected.
813 EFI_ACCESS_DENIED - The service denied access to the file.
815 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
817 EFI_VOLUME_FULL - There is not enough space left to create the new file.
820 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
821 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
822 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
823 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
826 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
827 WIN_NT_EFI_FILE_PRIVATE
*NewPrivateFile
;
828 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
830 CHAR16
*RealFileName
;
831 CHAR16
*TempFileName
;
832 CHAR16
*ParseFileName
;
833 CHAR16
*GuardPointer
;
842 // Check for obvious invalid parameters.
844 if (This
== NULL
|| NewHandle
== NULL
|| FileName
== NULL
) {
845 return EFI_INVALID_PARAMETER
;
849 case EFI_FILE_MODE_CREATE
| EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
850 if (Attributes
&~EFI_FILE_VALID_ATTR
) {
851 return EFI_INVALID_PARAMETER
;
854 if (Attributes
& EFI_FILE_READ_ONLY
) {
855 return EFI_INVALID_PARAMETER
;
861 case EFI_FILE_MODE_READ
:
862 case EFI_FILE_MODE_READ
| EFI_FILE_MODE_WRITE
:
866 return EFI_INVALID_PARAMETER
;
870 // Init local variables
872 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
873 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
874 NewPrivateFile
= NULL
;
877 // Allocate buffer for FileName as the passed in FileName may be read only
879 TempFileName
= AllocatePool (StrSize (FileName
));
880 if (TempFileName
== NULL
) {
881 return EFI_OUT_OF_RESOURCES
;
883 StrCpy (TempFileName
, FileName
);
884 FileName
= TempFileName
;
887 // BUGBUG: assume an open of root
888 // if current location, return current data
890 if (StrCmp (FileName
, L
"\\") == 0 || (StrCmp (FileName
, L
".") == 0 && PrivateFile
->IsRootDirectory
)) {
892 // BUGBUG: assume an open root
895 Status
= WinNtSimpleFileSystemOpenVolume (PrivateFile
->SimpleFileSystem
, &Root
);
896 NewPrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root
);
900 if (FileName
[StrLen (FileName
) - 1] == L
'\\') {
901 FileName
[StrLen (FileName
) - 1] = 0;
905 // If file name does not equal to "." or "..",
906 // then we trim the leading/trailing blanks and trailing dots
908 if (StrCmp (FileName
, L
".") != 0 && StrCmp (FileName
, L
"..") != 0) {
910 // Trim leading blanks
913 for (TempFileName
= FileName
;
914 *TempFileName
!= 0 && *TempFileName
== L
' ';
918 CutPrefix (FileName
, Count
);
920 // Trim trailing blanks
922 for (TempFileName
= FileName
+ StrLen (FileName
) - 1;
923 TempFileName
>= FileName
&& (*TempFileName
== L
' ');
927 *(TempFileName
+ 1) = 0;
931 // Attempt to open the file
933 NewPrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
934 if (NewPrivateFile
== NULL
) {
935 Status
= EFI_OUT_OF_RESOURCES
;
939 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (WIN_NT_EFI_FILE_PRIVATE
));
941 NewPrivateFile
->FilePath
= AllocatePool (StrSize (PrivateFile
->FileName
));
942 if (NewPrivateFile
->FilePath
== NULL
) {
943 Status
= EFI_OUT_OF_RESOURCES
;
947 if (PrivateFile
->IsDirectoryPath
) {
948 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FileName
);
950 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FilePath
);
953 NewPrivateFile
->FileName
= AllocatePool (StrSize (NewPrivateFile
->FilePath
) + StrSize (L
"\\") + StrSize (FileName
));
954 if (NewPrivateFile
->FileName
== NULL
) {
955 Status
= EFI_OUT_OF_RESOURCES
;
959 if (*FileName
== L
'\\') {
960 StrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
961 StrCat (NewPrivateFile
->FileName
, L
"\\");
962 StrCat (NewPrivateFile
->FileName
, FileName
+ 1);
964 StrCpy (NewPrivateFile
->FileName
, NewPrivateFile
->FilePath
);
965 if (StrCmp (FileName
, L
"") != 0) {
967 // In case the filename becomes empty, especially after trimming dots and blanks
969 StrCat (NewPrivateFile
->FileName
, L
"\\");
970 StrCat (NewPrivateFile
->FileName
, FileName
);
974 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
975 Status
= EFI_NOT_FOUND
;
980 // Get rid of . and .., except leading . or ..
984 // GuardPointer protect simplefilesystem root path not be destroyed
986 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
990 while (!LoopFinish
) {
994 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
995 if (*ParseFileName
== L
'.' &&
996 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
997 *(ParseFileName
- 1) == L
'\\'
1003 CutPrefix (ParseFileName
- 1, 2);
1008 if (*ParseFileName
== L
'.' &&
1009 *(ParseFileName
+ 1) == L
'.' &&
1010 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
1011 *(ParseFileName
- 1) == L
'\\'
1017 while (ParseFileName
!= GuardPointer
) {
1020 if (*ParseFileName
== L
'\\') {
1026 // cut \.. and its left directory
1028 CutPrefix (ParseFileName
, Count
);
1035 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
1036 NewPrivateFile
->IsRootDirectory
= TRUE
;
1037 FreePool (NewPrivateFile
->FilePath
);
1038 FreePool (NewPrivateFile
->FileName
);
1039 FreePool (NewPrivateFile
);
1043 RealFileName
= NewPrivateFile
->FileName
;
1044 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
1045 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
1048 TempChar
= *(RealFileName
- 1);
1049 *(RealFileName
- 1) = 0;
1051 FreePool (NewPrivateFile
->FilePath
);
1052 NewPrivateFile
->FilePath
= NULL
;
1053 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
1054 if (NewPrivateFile
->FilePath
== NULL
) {
1055 Status
= EFI_OUT_OF_RESOURCES
;
1059 StrCpy (NewPrivateFile
->FilePath
, NewPrivateFile
->FileName
);
1061 *(RealFileName
- 1) = TempChar
;
1063 NewPrivateFile
->IsRootDirectory
= FALSE
;
1066 // Test whether file or directory
1068 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
1069 if (Attributes
& EFI_FILE_DIRECTORY
) {
1070 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1072 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1075 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1076 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1077 NewPrivateFile
->FileName
,
1079 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1086 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1087 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1088 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1090 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1093 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1096 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
1097 NewPrivateFile
->IsOpenedByRead
= FALSE
;
1099 NewPrivateFile
->IsOpenedByRead
= TRUE
;
1102 Status
= EFI_SUCCESS
;
1105 // deal with directory
1107 if (NewPrivateFile
->IsDirectoryPath
) {
1109 TempFileName
= AllocatePool (StrSize (NewPrivateFile
->FileName
) + StrSize (L
"\\*"));
1110 if (TempFileName
== NULL
) {
1111 Status
= EFI_OUT_OF_RESOURCES
;
1115 StrCpy (TempFileName
, NewPrivateFile
->FileName
);
1117 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
1119 // Create a directory
1121 if (!NewPrivateFile
->WinNtThunk
->CreateDirectory (TempFileName
, NULL
)) {
1123 LastError
= PrivateFile
->WinNtThunk
->GetLastError ();
1124 if (LastError
!= ERROR_ALREADY_EXISTS
) {
1125 FreePool (TempFileName
);
1126 Status
= EFI_ACCESS_DENIED
;
1132 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1134 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
1135 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1138 FILE_FLAG_BACKUP_SEMANTICS
,
1142 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
1144 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1147 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1150 FILE_FLAG_BACKUP_SEMANTICS
,
1154 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1155 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->DirHandle
);
1156 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1157 Status
= EFI_ACCESS_DENIED
;
1159 Status
= EFI_NOT_FOUND
;
1166 // Find the first file under it
1168 StrCat (TempFileName
, L
"\\*");
1169 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
1171 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1172 NewPrivateFile
->IsValidFindBuf
= FALSE
;
1174 NewPrivateFile
->IsValidFindBuf
= TRUE
;
1180 if (!NewPrivateFile
->IsOpenedByRead
) {
1181 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1182 NewPrivateFile
->FileName
,
1183 GENERIC_READ
| GENERIC_WRITE
,
1184 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1186 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
1191 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1192 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1193 NewPrivateFile
->FileName
,
1195 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1202 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1203 Status
= EFI_NOT_FOUND
;
1205 Status
= EFI_ACCESS_DENIED
;
1206 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1207 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1211 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1212 NewPrivateFile
->FileName
,
1214 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1221 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1222 Status
= EFI_NOT_FOUND
;
1227 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
1229 // Set the attribute
1234 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1236 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1237 Status
= EFI_DEVICE_ERROR
;
1241 Info
= AllocatePool (InfoSize
);
1243 Status
= EFI_OUT_OF_RESOURCES
;
1247 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1249 if (EFI_ERROR (Status
)) {
1253 Info
->Attribute
= Attributes
;
1255 WinNtSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
1259 FreePool (FileName
);
1261 if (EFI_ERROR (Status
)) {
1262 if (NewPrivateFile
) {
1263 if (NewPrivateFile
->FileName
) {
1264 FreePool (NewPrivateFile
->FileName
);
1267 if (NewPrivateFile
->FilePath
) {
1268 FreePool (NewPrivateFile
->FilePath
);
1271 FreePool (NewPrivateFile
);
1274 *NewHandle
= &NewPrivateFile
->EfiFile
;
1282 WinNtSimpleFileSystemClose (
1287 Routine Description:
1289 Close the specified file handle.
1293 This - Pointer to a returned opened file handle.
1297 EFI_SUCCESS - The file handle has been closed.
1300 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1302 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1306 return EFI_INVALID_PARAMETER
;
1309 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1311 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1313 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1314 if (PrivateFile
->IsDirectoryPath
) {
1315 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1317 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1320 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1323 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1324 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1325 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1328 if (PrivateFile
->FileName
) {
1329 FreePool (PrivateFile
->FileName
);
1332 FreePool (PrivateFile
);
1334 gBS
->RestoreTPL (OldTpl
);
1341 WinNtSimpleFileSystemDelete (
1346 Routine Description:
1348 Close and delete a file.
1352 This - Pointer to a returned opened file handle.
1356 EFI_SUCCESS - The file handle was closed and deleted.
1358 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1361 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1364 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1368 return EFI_INVALID_PARAMETER
;
1371 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1373 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1375 Status
= EFI_WARN_DELETE_FAILURE
;
1377 if (PrivateFile
->IsDirectoryPath
) {
1378 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1379 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1382 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1383 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1384 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1387 if (PrivateFile
->WinNtThunk
->RemoveDirectory (PrivateFile
->FileName
)) {
1388 Status
= EFI_SUCCESS
;
1391 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1392 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1394 if (!PrivateFile
->IsOpenedByRead
) {
1395 if (PrivateFile
->WinNtThunk
->DeleteFile (PrivateFile
->FileName
)) {
1396 Status
= EFI_SUCCESS
;
1401 FreePool (PrivateFile
->FileName
);
1402 FreePool (PrivateFile
);
1404 gBS
->RestoreTPL (OldTpl
);
1410 WinNtSystemTimeToEfiTime (
1411 IN SYSTEMTIME
*SystemTime
,
1412 IN TIME_ZONE_INFORMATION
*TimeZone
,
1417 Routine Description:
1419 TODO: Add function description
1423 SystemTime - TODO: add argument description
1424 TimeZone - TODO: add argument description
1425 Time - TODO: add argument description
1429 TODO: add return values
1433 Time
->Year
= (UINT16
) SystemTime
->wYear
;
1434 Time
->Month
= (UINT8
) SystemTime
->wMonth
;
1435 Time
->Day
= (UINT8
) SystemTime
->wDay
;
1436 Time
->Hour
= (UINT8
) SystemTime
->wHour
;
1437 Time
->Minute
= (UINT8
) SystemTime
->wMinute
;
1438 Time
->Second
= (UINT8
) SystemTime
->wSecond
;
1439 Time
->Nanosecond
= (UINT32
) SystemTime
->wMilliseconds
* 1000000;
1440 Time
->TimeZone
= (INT16
) TimeZone
->Bias
;
1442 if (TimeZone
->StandardDate
.wMonth
) {
1443 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1449 WinNtSimpleFileSystemRead (
1451 IN OUT UINTN
*BufferSize
,
1456 Routine Description:
1458 Read data from a file.
1462 This - Pointer to a returned open file handle.
1464 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1466 Buffer - Pointer to the first byte of the read Buffer.
1470 EFI_SUCCESS - The data was read.
1472 EFI_NO_MEDIA - The device has no media.
1474 EFI_DEVICE_ERROR - The device reported an error.
1476 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1478 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1479 *BufferSize has been updated with the size needed to complete the request.
1482 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1484 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1490 SYSTEMTIME SystemTime
;
1491 EFI_FILE_INFO
*Info
;
1493 TIME_ZONE_INFORMATION TimeZone
;
1494 EFI_FILE_INFO
*FileInfo
;
1500 if (This
== NULL
|| BufferSize
== NULL
) {
1501 return EFI_INVALID_PARAMETER
;
1504 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1506 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1508 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1509 Status
= EFI_DEVICE_ERROR
;
1513 if (!PrivateFile
->IsDirectoryPath
) {
1515 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1516 Status
= EFI_DEVICE_ERROR
;
1520 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1521 FileInfo
= AllocatePool (FileInfoSize
);
1523 Status
= This
->GetInfo (
1530 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1531 FreePool (FileInfo
);
1532 FileInfo
= AllocatePool (FileInfoSize
);
1533 Status
= This
->GetInfo (
1541 if (EFI_ERROR (Status
)) {
1542 Status
= EFI_DEVICE_ERROR
;
1546 FileSize
= FileInfo
->FileSize
;
1548 FreePool (FileInfo
);
1550 if (Pos
>= FileSize
) {
1552 if (Pos
== FileSize
) {
1553 Status
= EFI_SUCCESS
;
1556 Status
= EFI_DEVICE_ERROR
;
1561 Status
= PrivateFile
->WinNtThunk
->ReadFile (
1562 PrivateFile
->LHandle
,
1567 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1572 // Read on a directory. Perform a find next
1574 if (!PrivateFile
->IsValidFindBuf
) {
1576 Status
= EFI_SUCCESS
;
1580 Size
= SIZE_OF_EFI_FILE_INFO
;
1582 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1584 ResultSize
= Size
+ NameSize
;
1586 Status
= EFI_BUFFER_TOO_SMALL
;
1588 if (*BufferSize
>= ResultSize
) {
1589 Status
= EFI_SUCCESS
;
1592 ZeroMem (Info
, ResultSize
);
1594 Info
->Size
= ResultSize
;
1596 PrivateFile
->WinNtThunk
->GetTimeZoneInformation (&TimeZone
);
1598 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1599 &PrivateFile
->FindBuf
.ftCreationTime
,
1600 &PrivateFile
->FindBuf
.ftCreationTime
1603 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftCreationTime
, &SystemTime
);
1605 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->CreateTime
);
1607 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1608 &PrivateFile
->FindBuf
.ftLastWriteTime
,
1609 &PrivateFile
->FindBuf
.ftLastWriteTime
1612 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftLastWriteTime
, &SystemTime
);
1614 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->ModificationTime
);
1616 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1618 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1620 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1621 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1624 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1625 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1628 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1629 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1632 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1633 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1636 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1637 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1640 NameSize
= NameSize
/ sizeof (WCHAR
);
1642 pw
= (WCHAR
*) (((CHAR8
*) Buffer
) + Size
);
1644 for (Index
= 0; Index
< NameSize
; Index
++) {
1645 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1648 if (PrivateFile
->WinNtThunk
->FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1649 PrivateFile
->IsValidFindBuf
= TRUE
;
1651 PrivateFile
->IsValidFindBuf
= FALSE
;
1655 *BufferSize
= ResultSize
;
1658 gBS
->RestoreTPL (OldTpl
);
1664 WinNtSimpleFileSystemWrite (
1666 IN OUT UINTN
*BufferSize
,
1671 Routine Description:
1673 Write data to a file.
1677 This - Pointer to an opened file handle.
1679 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1680 of data written to the file.
1682 Buffer - Pointer to the first by of data in the buffer to write to the file.
1686 EFI_SUCCESS - The data was written to the file.
1688 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1690 EFI_NO_MEDIA - The device has no media.
1692 EFI_DEVICE_ERROR - The device reported an error.
1694 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1696 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1698 EFI_ACCESS_DENIED - The file was opened read-only.
1700 EFI_VOLUME_FULL - The volume is full.
1703 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1705 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1709 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1710 return EFI_INVALID_PARAMETER
;
1713 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1715 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1717 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1718 Status
= EFI_DEVICE_ERROR
;
1722 if (PrivateFile
->IsDirectoryPath
) {
1723 Status
= EFI_UNSUPPORTED
;
1727 if (PrivateFile
->IsOpenedByRead
) {
1728 Status
= EFI_ACCESS_DENIED
;
1732 Status
= PrivateFile
->WinNtThunk
->WriteFile (
1733 PrivateFile
->LHandle
,
1738 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1741 gBS
->RestoreTPL (OldTpl
);
1745 // bugbug: need to access windows error reporting
1751 WinNtSimpleFileSystemSetPosition (
1757 Routine Description:
1759 Set a file's current position.
1763 This - Pointer to an opened file handle.
1765 Position - The byte position from the start of the file to set.
1769 EFI_SUCCESS - The file position has been changed.
1771 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1774 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1777 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1784 return EFI_INVALID_PARAMETER
;
1787 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1789 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1791 if (PrivateFile
->IsDirectoryPath
) {
1792 if (Position
!= 0) {
1793 Status
= EFI_UNSUPPORTED
;
1797 FileName
= AllocatePool (StrSize (PrivateFile
->FileName
) + StrSize (L
"\\*"));
1798 if (FileName
== NULL
) {
1799 Status
= EFI_OUT_OF_RESOURCES
;
1803 StrCpy (FileName
, PrivateFile
->FileName
);
1804 StrCat (FileName
, L
"\\*");
1806 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1807 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1810 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1812 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1813 PrivateFile
->IsValidFindBuf
= FALSE
;
1815 PrivateFile
->IsValidFindBuf
= TRUE
;
1818 FreePool (FileName
);
1820 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1822 if (Position
== (UINT64
) -1) {
1823 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) 0, NULL
, FILE_END
);
1825 PosHigh
= (UINT32
) RShiftU64 (Position
, 32);
1827 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) Position
, &PosHigh
, FILE_BEGIN
);
1830 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1834 gBS
->RestoreTPL (OldTpl
);
1840 WinNtSimpleFileSystemGetPosition (
1842 OUT UINT64
*Position
1846 Routine Description:
1848 Get a file's current position.
1852 This - Pointer to an opened file handle.
1854 Position - Pointer to storage for the current position.
1858 EFI_SUCCESS - The file position has been reported.
1860 EFI_UNSUPPORTED - Not valid for directories.
1863 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1866 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1871 if (This
== NULL
|| Position
== NULL
) {
1872 return EFI_INVALID_PARAMETER
;
1875 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1876 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1881 if (PrivateFile
->IsDirectoryPath
) {
1883 Status
= EFI_UNSUPPORTED
;
1889 *Position
= PrivateFile
->WinNtThunk
->SetFilePointer (
1890 PrivateFile
->LHandle
,
1896 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1897 if (EFI_ERROR (Status
)) {
1901 PosHigh64
= PositionHigh
;
1902 *Position
+= LShiftU64 (PosHigh64
, 32);
1906 gBS
->RestoreTPL (OldTpl
);
1911 WinNtSimpleFileSystemFileInfo (
1912 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1913 IN OUT UINTN
*BufferSize
,
1918 Routine Description:
1920 TODO: Add function description
1924 PrivateFile - TODO: add argument description
1925 BufferSize - TODO: add argument description
1926 Buffer - TODO: add argument description
1930 TODO: add return values
1938 EFI_FILE_INFO
*Info
;
1939 BY_HANDLE_FILE_INFORMATION FileInfo
;
1940 SYSTEMTIME SystemTime
;
1941 CHAR16
*RealFileName
;
1942 CHAR16
*TempPointer
;
1943 EFI_FILE_INFO
*DirInfo
;
1946 EFI_STATUS DirStatus
;
1949 Size
= SIZE_OF_EFI_FILE_INFO
;
1950 NameSize
= StrSize (PrivateFile
->FileName
);
1951 ResultSize
= Size
+ NameSize
;
1953 Status
= EFI_BUFFER_TOO_SMALL
;
1954 if (*BufferSize
>= ResultSize
) {
1955 Status
= EFI_SUCCESS
;
1958 ZeroMem (Info
, ResultSize
);
1960 Info
->Size
= ResultSize
;
1961 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (
1962 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
1965 Info
->FileSize
= FileInfo
.nFileSizeLow
;
1966 Info
->PhysicalSize
= Info
->FileSize
;
1968 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftCreationTime
, &SystemTime
);
1969 Info
->CreateTime
.Year
= SystemTime
.wYear
;
1970 Info
->CreateTime
.Month
= (UINT8
) SystemTime
.wMonth
;
1971 Info
->CreateTime
.Day
= (UINT8
) SystemTime
.wDay
;
1972 Info
->CreateTime
.Hour
= (UINT8
) SystemTime
.wHour
;
1973 Info
->CreateTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
1974 Info
->CreateTime
.Second
= (UINT8
) SystemTime
.wSecond
;
1976 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastAccessTime
, &SystemTime
);
1977 Info
->LastAccessTime
.Year
= SystemTime
.wYear
;
1978 Info
->LastAccessTime
.Month
= (UINT8
) SystemTime
.wMonth
;
1979 Info
->LastAccessTime
.Day
= (UINT8
) SystemTime
.wDay
;
1980 Info
->LastAccessTime
.Hour
= (UINT8
) SystemTime
.wHour
;
1981 Info
->LastAccessTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
1982 Info
->LastAccessTime
.Second
= (UINT8
) SystemTime
.wSecond
;
1984 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastWriteTime
, &SystemTime
);
1985 Info
->ModificationTime
.Year
= SystemTime
.wYear
;
1986 Info
->ModificationTime
.Month
= (UINT8
) SystemTime
.wMonth
;
1987 Info
->ModificationTime
.Day
= (UINT8
) SystemTime
.wDay
;
1988 Info
->ModificationTime
.Hour
= (UINT8
) SystemTime
.wHour
;
1989 Info
->ModificationTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
1990 Info
->ModificationTime
.Second
= (UINT8
) SystemTime
.wSecond
;
1992 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1993 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1996 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1997 Info
->Attribute
|= EFI_FILE_HIDDEN
;
2000 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2001 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
2004 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
2005 Info
->Attribute
|= EFI_FILE_SYSTEM
;
2008 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2009 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2012 if (PrivateFile
->IsDirectoryPath
) {
2013 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2016 RealFileName
= PrivateFile
->FileName
;
2017 TempPointer
= RealFileName
;
2019 while (*TempPointer
) {
2020 if (*TempPointer
== '\\') {
2021 RealFileName
= TempPointer
+ 1;
2027 if (PrivateFile
->IsRootDirectory
) {
2028 *((CHAR8
*) Buffer
+ Size
) = 0;
2030 CopyMem ((CHAR8
*) Buffer
+ Size
, RealFileName
, NameSize
);
2033 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
2035 // The GetFileInformationByHandle.nFileSizeLow is bogus for dir so we
2036 // need to do the same thing the caller would do to get the right value
2038 ASSERT (PrivateFile
->EfiFile
.Read
!= NULL
);
2039 DirStatus
= PrivateFile
->EfiFile
.GetPosition (&PrivateFile
->EfiFile
, &Location
);
2040 if (EFI_ERROR (DirStatus
)) {
2044 PrivateFile
->EfiFile
.SetPosition (&PrivateFile
->EfiFile
, 0);
2049 DirStatus
= PrivateFile
->EfiFile
.Read (&PrivateFile
->EfiFile
, &ReadSize
, DirInfo
);
2050 if (DirStatus
== EFI_BUFFER_TOO_SMALL
) {
2051 DirInfo
= AllocatePool (ReadSize
);
2052 if (DirInfo
!= NULL
) {
2054 // Read each dir entry to figure out how big the directory is
2056 DirStatus
= PrivateFile
->EfiFile
.Read (&PrivateFile
->EfiFile
, &ReadSize
, DirInfo
);
2057 if (!EFI_ERROR (DirStatus
) && (ReadSize
!= 0)) {
2058 Info
->FileSize
+= ReadSize
;
2064 } while (!EFI_ERROR (DirStatus
) && (ReadSize
!= 0));
2067 // reset the file possition back to the previous location
2069 PrivateFile
->EfiFile
.SetPosition (&PrivateFile
->EfiFile
, Location
);
2073 *BufferSize
= ResultSize
;
2079 WinNtSimpleFileSystemGetInfo (
2081 IN EFI_GUID
*InformationType
,
2082 IN OUT UINTN
*BufferSize
,
2087 Routine Description:
2089 Return information about a file or volume.
2093 This - Pointer to an opened file handle.
2095 InformationType - GUID describing the type of information to be returned.
2097 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
2100 Buffer - Pointer to the first byte of the information buffer.
2104 EFI_SUCCESS - The requested information has been written into the buffer.
2106 EFI_UNSUPPORTED - The InformationType is not known.
2108 EFI_NO_MEDIA - The device has no media.
2110 EFI_DEVICE_ERROR - The device reported an error.
2112 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2114 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
2115 been updated with the size needed to complete the requested operation.
2118 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2121 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2122 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
2123 UINT32 SectorsPerCluster
;
2124 UINT32 BytesPerSector
;
2125 UINT32 FreeClusters
;
2126 UINT32 TotalClusters
;
2127 UINT32 BytesPerCluster
;
2129 BOOLEAN DriveNameFound
;
2132 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2135 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
2136 return EFI_INVALID_PARAMETER
;
2139 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2141 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2142 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2144 Status
= EFI_UNSUPPORTED
;
2146 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2147 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
2150 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2151 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2152 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2153 Status
= EFI_BUFFER_TOO_SMALL
;
2157 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2158 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2159 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
2162 // Try to get the drive name
2164 DriveNameFound
= FALSE
;
2165 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
2166 if (DriveName
== NULL
) {
2167 Status
= EFI_OUT_OF_RESOURCES
;
2171 StrCpy (DriveName
, PrivateFile
->FilePath
);
2172 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
2176 if (DriveName
[Index
] == ':') {
2177 DriveName
[Index
+ 1] = '\\';
2178 DriveName
[Index
+ 2] = 0;
2179 DriveNameFound
= TRUE
;
2180 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
2181 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2185 if (DriveName
[Index
] == '\\') {
2186 DriveNameFound
= TRUE
;
2187 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2191 DriveName
[Index
] = '\\';
2192 DriveName
[Index
+ 1] = 0;
2197 // Try GetDiskFreeSpace first
2199 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpace (
2200 DriveNameFound
? DriveName
: NULL
,
2207 FreePool (DriveName
);
2214 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
2215 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
2216 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
2217 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
2221 // try GetDiskFreeSpaceEx then
2223 FileSystemInfoBuffer
->BlockSize
= 0;
2224 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpaceEx (
2225 PrivateFile
->FilePath
,
2226 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->FreeSpace
),
2227 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->VolumeSize
),
2231 Status
= EFI_DEVICE_ERROR
;
2236 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
2237 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2238 Status
= EFI_SUCCESS
;
2241 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2242 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2243 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2244 Status
= EFI_BUFFER_TOO_SMALL
;
2248 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
2249 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2250 Status
= EFI_SUCCESS
;
2254 gBS
->RestoreTPL (OldTpl
);
2260 WinNtSimpleFileSystemSetInfo (
2262 IN EFI_GUID
*InformationType
,
2263 IN UINTN BufferSize
,
2268 Routine Description:
2270 Set information about a file or volume.
2274 This - Pointer to an opened file handle.
2276 InformationType - GUID identifying the type of information to set.
2278 BufferSize - Number of bytes of data in the information buffer.
2280 Buffer - Pointer to the first byte of data in the information buffer.
2284 EFI_SUCCESS - The file or volume information has been updated.
2286 EFI_UNSUPPORTED - The information identifier is not recognised.
2288 EFI_NO_MEDIA - The device has no media.
2290 EFI_DEVICE_ERROR - The device reported an error.
2292 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2294 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2296 EFI_ACCESS_DENIED - The file was opened read-only.
2298 EFI_VOLUME_FULL - The volume is full.
2300 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2303 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2304 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2306 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2307 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2308 EFI_FILE_INFO
*OldFileInfo
;
2309 EFI_FILE_INFO
*NewFileInfo
;
2315 CHAR16
*OldFileName
;
2316 CHAR16
*NewFileName
;
2317 CHAR16
*TempFileName
;
2318 CHAR16
*CharPointer
;
2319 BOOLEAN AttrChangeFlag
;
2320 BOOLEAN NameChangeFlag
;
2321 BOOLEAN SizeChangeFlag
;
2322 BOOLEAN TimeChangeFlag
;
2324 SYSTEMTIME NewCreationSystemTime
;
2325 SYSTEMTIME NewLastAccessSystemTime
;
2326 SYSTEMTIME NewLastWriteSystemTime
;
2327 FILETIME NewCreationFileTime
;
2328 FILETIME NewLastAccessFileTime
;
2329 FILETIME NewLastWriteFileTime
;
2330 WIN32_FIND_DATA FindBuf
;
2331 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
2335 // Check for invalid parameters.
2337 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
2338 return EFI_INVALID_PARAMETER
;
2341 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2344 // Initialise locals.
2346 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2347 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2349 Status
= EFI_UNSUPPORTED
;
2350 OldFileInfo
= NewFileInfo
= NULL
;
2351 OldFileName
= NewFileName
= NULL
;
2352 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
2355 // Set file system information.
2357 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2358 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2359 Status
= EFI_BAD_BUFFER_SIZE
;
2363 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2365 FreePool (PrivateRoot
->VolumeLabel
);
2366 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
2367 if (PrivateRoot
->VolumeLabel
== NULL
) {
2368 Status
= EFI_OUT_OF_RESOURCES
;
2372 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
2374 Status
= EFI_SUCCESS
;
2379 // Set volume label information.
2381 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2382 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2383 Status
= EFI_BAD_BUFFER_SIZE
;
2387 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
2389 Status
= EFI_SUCCESS
;
2393 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2394 Status
= EFI_UNSUPPORTED
;
2398 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
2399 Status
= EFI_BAD_BUFFER_SIZE
;
2404 // Set file/directory information.
2408 // Check for invalid set file information parameters.
2410 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
2412 if (NewFileInfo
->Size
<= sizeof (EFI_FILE_INFO
) ||
2413 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
2414 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
2416 Status
= EFI_INVALID_PARAMETER
;
2421 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2422 // that would have an additional parameter that would be the size
2423 // of the string array just in case there are no NULL characters in
2424 // the string array.
2427 // Get current file information so we can determine what kind
2428 // of change request this is.
2431 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
2433 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2434 Status
= EFI_DEVICE_ERROR
;
2438 OldFileInfo
= AllocatePool (OldInfoSize
);
2439 if (OldFileInfo
== NULL
) {
2440 Status
= EFI_OUT_OF_RESOURCES
;
2444 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
2446 if (EFI_ERROR (Status
)) {
2450 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
2451 if (OldFileName
== NULL
) {
2452 Status
= EFI_OUT_OF_RESOURCES
;
2456 StrCpy (OldFileName
, PrivateFile
->FileName
);
2459 // Make full pathname from new filename and rootpath.
2461 if (NewFileInfo
->FileName
[0] == '\\') {
2462 NewFileName
= AllocatePool (StrSize (PrivateRoot
->FilePath
) + StrSize (L
"\\") + StrSize (NewFileInfo
->FileName
));
2463 if (NewFileName
== NULL
) {
2464 Status
= EFI_OUT_OF_RESOURCES
;
2468 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
2469 StrCat (NewFileName
, L
"\\");
2470 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
2472 NewFileName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + StrSize (L
"\\") + StrSize (NewFileInfo
->FileName
));
2473 if (NewFileName
== NULL
) {
2474 Status
= EFI_OUT_OF_RESOURCES
;
2478 StrCpy (NewFileName
, PrivateFile
->FilePath
);
2479 StrCat (NewFileName
, L
"\\");
2480 StrCat (NewFileName
, NewFileInfo
->FileName
);
2484 // Is there an attribute change request?
2486 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
2487 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
2488 Status
= EFI_INVALID_PARAMETER
;
2492 AttrChangeFlag
= TRUE
;
2496 // Is there a name change request?
2497 // bugbug: - Need EfiStrCaseCmp()
2499 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
2500 NameChangeFlag
= TRUE
;
2504 // Is there a size change request?
2506 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
2507 SizeChangeFlag
= TRUE
;
2511 // Is there a time stamp change request?
2513 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
2514 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
2516 TimeChangeFlag
= TRUE
;
2517 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
2518 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
2520 TimeChangeFlag
= TRUE
;
2521 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
2522 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
2524 TimeChangeFlag
= TRUE
;
2528 // All done if there are no change requests being made.
2530 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
2531 Status
= EFI_SUCCESS
;
2536 // Set file or directory information.
2538 OldAttr
= PrivateFile
->WinNtThunk
->GetFileAttributes (OldFileName
);
2543 if (NameChangeFlag
) {
2545 // Close the handles first
2547 if (PrivateFile
->IsOpenedByRead
) {
2548 Status
= EFI_ACCESS_DENIED
;
2552 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
2555 if (*CharPointer
!= 0) {
2556 Status
= EFI_ACCESS_DENIED
;
2560 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
2561 if (PrivateFile
->IsDirectoryPath
) {
2562 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
2564 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
2565 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
2569 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
2570 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
2571 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
2574 NtStatus
= PrivateFile
->WinNtThunk
->MoveFile (OldFileName
, NewFileName
);
2580 FreePool (PrivateFile
->FileName
);
2582 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
2583 if (PrivateFile
->FileName
== NULL
) {
2584 Status
= EFI_OUT_OF_RESOURCES
;
2588 StrCpy (PrivateFile
->FileName
, NewFileName
);
2590 TempFileName
= AllocatePool (StrSize (NewFileName
) + StrSize (L
"\\*"));
2592 StrCpy (TempFileName
, NewFileName
);
2594 if (!PrivateFile
->IsDirectoryPath
) {
2595 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2597 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2598 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2605 FreePool (TempFileName
);
2608 // Flush buffers just in case
2610 if (PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2611 Status
= EFI_DEVICE_ERROR
;
2615 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2617 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2618 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2621 FILE_FLAG_BACKUP_SEMANTICS
,
2625 StrCat (TempFileName
, L
"\\*");
2626 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2628 FreePool (TempFileName
);
2632 Status
= EFI_DEVICE_ERROR
;
2634 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (OldFileName
, OldAttr
);
2640 TempFileName
= AllocatePool (StrSize (OldFileName
) + StrSize (L
"\\*"));
2642 StrCpy (TempFileName
, OldFileName
);
2644 if (!PrivateFile
->IsDirectoryPath
) {
2645 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2647 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2648 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2655 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2657 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2658 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2661 FILE_FLAG_BACKUP_SEMANTICS
,
2665 StrCat (TempFileName
, L
"\\*");
2666 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2669 FreePool (TempFileName
);
2679 if (SizeChangeFlag
) {
2680 if (PrivateFile
->IsDirectoryPath
) {
2681 Status
= EFI_UNSUPPORTED
;
2685 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2686 Status
= EFI_ACCESS_DENIED
;
2690 Status
= This
->GetPosition (This
, &CurPos
);
2691 if (EFI_ERROR (Status
)) {
2695 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2696 if (EFI_ERROR (Status
)) {
2700 if (PrivateFile
->WinNtThunk
->SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2701 Status
= EFI_DEVICE_ERROR
;
2705 Status
= This
->SetPosition (This
, CurPos
);
2706 if (EFI_ERROR (Status
)) {
2714 if (TimeChangeFlag
) {
2716 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2717 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2718 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2719 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2720 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2721 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2722 NewCreationSystemTime
.wMilliseconds
= 0;
2724 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2725 &NewCreationSystemTime
,
2726 &NewCreationFileTime
2731 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2732 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2733 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2734 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2735 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2736 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2737 NewLastAccessSystemTime
.wMilliseconds
= 0;
2739 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2740 &NewLastAccessSystemTime
,
2741 &NewLastAccessFileTime
2746 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2747 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2748 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2749 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2750 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2751 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2752 NewLastWriteSystemTime
.wMilliseconds
= 0;
2754 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2755 &NewLastWriteSystemTime
,
2756 &NewLastWriteFileTime
2761 if (!PrivateFile
->WinNtThunk
->SetFileTime (
2762 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2763 &NewCreationFileTime
,
2764 &NewLastAccessFileTime
,
2765 &NewLastWriteFileTime
2767 Status
= EFI_DEVICE_ERROR
;
2774 // No matter about AttrChangeFlag, Attribute must be set.
2775 // Because operation before may cause attribute change.
2779 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2780 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2782 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2785 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2786 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2788 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2791 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2792 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2794 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2797 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2798 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2800 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2803 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (NewFileName
, NewAttr
);
2810 if (OldFileInfo
!= NULL
) {
2811 FreePool (OldFileInfo
);
2814 if (OldFileName
!= NULL
) {
2815 FreePool (OldFileName
);
2818 if (NewFileName
!= NULL
) {
2819 FreePool (NewFileName
);
2822 gBS
->RestoreTPL (OldTpl
);
2828 WinNtSimpleFileSystemFlush (
2833 Routine Description:
2835 Flush all modified data to the media.
2839 This - Pointer to an opened file handle.
2843 EFI_SUCCESS - The data has been flushed.
2845 EFI_NO_MEDIA - The device has no media.
2847 EFI_DEVICE_ERROR - The device reported an error.
2849 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2851 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2853 EFI_ACCESS_DENIED - The file was opened read-only.
2855 EFI_VOLUME_FULL - The volume is full.
2858 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2860 BY_HANDLE_FILE_INFORMATION FileInfo
;
2861 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2866 return EFI_INVALID_PARAMETER
;
2869 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2871 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2873 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2874 Status
= EFI_DEVICE_ERROR
;
2878 if (PrivateFile
->IsDirectoryPath
) {
2879 Status
= EFI_SUCCESS
;
2883 if (PrivateFile
->IsOpenedByRead
) {
2884 Status
= EFI_ACCESS_DENIED
;
2888 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2890 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2891 Status
= EFI_ACCESS_DENIED
;
2895 Status
= PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2898 gBS
->RestoreTPL (OldTpl
);
2901 // bugbug: - Use Windows error reporting.