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 ".." and not trailed with "\..",
906 // then we trim the leading/trailing blanks and trailing dots
908 if (StrCmp (FileName
, L
".") != 0 && StrCmp (FileName
, L
"..") != 0 &&
909 ((StrLen (FileName
) >= 3) ? (StrCmp (&FileName
[StrLen (FileName
) - 3], L
"\\..") != 0) : TRUE
)) {
911 // Trim leading blanks
914 for (TempFileName
= FileName
;
915 *TempFileName
!= 0 && *TempFileName
== L
' ';
919 CutPrefix (FileName
, Count
);
921 // Trim trailing blanks
923 for (TempFileName
= FileName
+ StrLen (FileName
) - 1;
924 TempFileName
>= FileName
&& (*TempFileName
== L
' ');
928 *(TempFileName
+ 1) = 0;
932 // Attempt to open the file
934 NewPrivateFile
= AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE
));
935 if (NewPrivateFile
== NULL
) {
936 Status
= EFI_OUT_OF_RESOURCES
;
940 CopyMem (NewPrivateFile
, PrivateFile
, sizeof (WIN_NT_EFI_FILE_PRIVATE
));
942 NewPrivateFile
->FilePath
= AllocatePool (StrSize (PrivateFile
->FileName
));
943 if (NewPrivateFile
->FilePath
== NULL
) {
944 Status
= EFI_OUT_OF_RESOURCES
;
948 if (PrivateFile
->IsDirectoryPath
) {
949 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FileName
);
951 StrCpy (NewPrivateFile
->FilePath
, PrivateFile
->FilePath
);
954 NewPrivateFile
->FileName
= AllocatePool (StrSize (NewPrivateFile
->FilePath
) + StrSize (L
"\\") + StrSize (FileName
));
955 if (NewPrivateFile
->FileName
== NULL
) {
956 Status
= EFI_OUT_OF_RESOURCES
;
960 if (*FileName
== L
'\\') {
961 StrCpy (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
);
962 StrCat (NewPrivateFile
->FileName
, L
"\\");
963 StrCat (NewPrivateFile
->FileName
, FileName
+ 1);
965 StrCpy (NewPrivateFile
->FileName
, NewPrivateFile
->FilePath
);
966 if (StrCmp (FileName
, L
"") != 0) {
968 // In case the filename becomes empty, especially after trimming dots and blanks
970 StrCat (NewPrivateFile
->FileName
, L
"\\");
971 StrCat (NewPrivateFile
->FileName
, FileName
);
975 if (!IsFileNameValid (NewPrivateFile
->FileName
)) {
976 Status
= EFI_NOT_FOUND
;
981 // Get rid of . and .., except leading . or ..
985 // GuardPointer protect simplefilesystem root path not be destroyed
987 GuardPointer
= NewPrivateFile
->FileName
+ StrLen (PrivateRoot
->FilePath
);
991 while (!LoopFinish
) {
995 for (ParseFileName
= GuardPointer
; *ParseFileName
; ParseFileName
++) {
996 if (*ParseFileName
== L
'.' &&
997 (*(ParseFileName
+ 1) == 0 || *(ParseFileName
+ 1) == L
'\\') &&
998 *(ParseFileName
- 1) == L
'\\'
1004 CutPrefix (ParseFileName
- 1, 2);
1009 if (*ParseFileName
== L
'.' &&
1010 *(ParseFileName
+ 1) == L
'.' &&
1011 (*(ParseFileName
+ 2) == 0 || *(ParseFileName
+ 2) == L
'\\') &&
1012 *(ParseFileName
- 1) == L
'\\'
1018 while (ParseFileName
!= GuardPointer
) {
1021 if (*ParseFileName
== L
'\\') {
1027 // cut \.. and its left directory
1029 CutPrefix (ParseFileName
, Count
);
1036 if (StrCmp (NewPrivateFile
->FileName
, PrivateRoot
->FilePath
) == 0) {
1037 NewPrivateFile
->IsRootDirectory
= TRUE
;
1038 FreePool (NewPrivateFile
->FilePath
);
1039 FreePool (NewPrivateFile
->FileName
);
1040 FreePool (NewPrivateFile
);
1044 RealFileName
= NewPrivateFile
->FileName
;
1045 while (EfiStrChr (RealFileName
, L
'\\') != NULL
) {
1046 RealFileName
= EfiStrChr (RealFileName
, L
'\\') + 1;
1049 TempChar
= *(RealFileName
- 1);
1050 *(RealFileName
- 1) = 0;
1052 FreePool (NewPrivateFile
->FilePath
);
1053 NewPrivateFile
->FilePath
= NULL
;
1054 NewPrivateFile
->FilePath
= AllocatePool (StrSize (NewPrivateFile
->FileName
));
1055 if (NewPrivateFile
->FilePath
== NULL
) {
1056 Status
= EFI_OUT_OF_RESOURCES
;
1060 StrCpy (NewPrivateFile
->FilePath
, NewPrivateFile
->FileName
);
1062 *(RealFileName
- 1) = TempChar
;
1064 NewPrivateFile
->IsRootDirectory
= FALSE
;
1067 // Test whether file or directory
1069 if (OpenMode
& EFI_FILE_MODE_CREATE
) {
1070 if (Attributes
& EFI_FILE_DIRECTORY
) {
1071 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1073 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1076 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1077 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1078 NewPrivateFile
->FileName
,
1080 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1087 if (NewPrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1088 NewPrivateFile
->IsDirectoryPath
= FALSE
;
1089 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1091 NewPrivateFile
->IsDirectoryPath
= TRUE
;
1094 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1097 if (OpenMode
& EFI_FILE_MODE_WRITE
) {
1098 NewPrivateFile
->IsOpenedByRead
= FALSE
;
1100 NewPrivateFile
->IsOpenedByRead
= TRUE
;
1103 Status
= EFI_SUCCESS
;
1106 // deal with directory
1108 if (NewPrivateFile
->IsDirectoryPath
) {
1110 TempFileName
= AllocatePool (StrSize (NewPrivateFile
->FileName
) + StrSize (L
"\\*"));
1111 if (TempFileName
== NULL
) {
1112 Status
= EFI_OUT_OF_RESOURCES
;
1116 StrCpy (TempFileName
, NewPrivateFile
->FileName
);
1118 if ((OpenMode
& EFI_FILE_MODE_CREATE
)) {
1120 // Create a directory
1122 if (!NewPrivateFile
->WinNtThunk
->CreateDirectory (TempFileName
, NULL
)) {
1124 LastError
= PrivateFile
->WinNtThunk
->GetLastError ();
1125 if (LastError
!= ERROR_ALREADY_EXISTS
) {
1126 FreePool (TempFileName
);
1127 Status
= EFI_ACCESS_DENIED
;
1133 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1135 NewPrivateFile
->IsOpenedByRead
? GENERIC_READ
: (GENERIC_READ
| GENERIC_WRITE
),
1136 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1139 FILE_FLAG_BACKUP_SEMANTICS
,
1143 if (NewPrivateFile
->DirHandle
== INVALID_HANDLE_VALUE
) {
1145 NewPrivateFile
->DirHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1148 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1151 FILE_FLAG_BACKUP_SEMANTICS
,
1155 if (NewPrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1156 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->DirHandle
);
1157 NewPrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1158 Status
= EFI_ACCESS_DENIED
;
1160 Status
= EFI_NOT_FOUND
;
1167 // Find the first file under it
1169 StrCat (TempFileName
, L
"\\*");
1170 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &NewPrivateFile
->FindBuf
);
1172 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1173 NewPrivateFile
->IsValidFindBuf
= FALSE
;
1175 NewPrivateFile
->IsValidFindBuf
= TRUE
;
1181 if (!NewPrivateFile
->IsOpenedByRead
) {
1182 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1183 NewPrivateFile
->FileName
,
1184 GENERIC_READ
| GENERIC_WRITE
,
1185 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1187 (OpenMode
& EFI_FILE_MODE_CREATE
) ? OPEN_ALWAYS
: OPEN_EXISTING
,
1192 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1193 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1194 NewPrivateFile
->FileName
,
1196 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1203 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1204 Status
= EFI_NOT_FOUND
;
1206 Status
= EFI_ACCESS_DENIED
;
1207 NewPrivateFile
->WinNtThunk
->CloseHandle (NewPrivateFile
->LHandle
);
1208 NewPrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1212 NewPrivateFile
->LHandle
= NewPrivateFile
->WinNtThunk
->CreateFile (
1213 NewPrivateFile
->FileName
,
1215 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
1222 if (NewPrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1223 Status
= EFI_NOT_FOUND
;
1228 if ((OpenMode
& EFI_FILE_MODE_CREATE
) && Status
== EFI_SUCCESS
) {
1230 // Set the attribute
1235 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1237 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
1238 Status
= EFI_DEVICE_ERROR
;
1242 Info
= AllocatePool (InfoSize
);
1244 Status
= EFI_OUT_OF_RESOURCES
;
1248 Status
= WinNtSimpleFileSystemGetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, &InfoSize
, Info
);
1250 if (EFI_ERROR (Status
)) {
1254 Info
->Attribute
= Attributes
;
1256 WinNtSimpleFileSystemSetInfo (&NewPrivateFile
->EfiFile
, &gEfiFileInfoGuid
, InfoSize
, Info
);
1260 FreePool (FileName
);
1262 if (EFI_ERROR (Status
)) {
1263 if (NewPrivateFile
) {
1264 if (NewPrivateFile
->FileName
) {
1265 FreePool (NewPrivateFile
->FileName
);
1268 if (NewPrivateFile
->FilePath
) {
1269 FreePool (NewPrivateFile
->FilePath
);
1272 FreePool (NewPrivateFile
);
1275 *NewHandle
= &NewPrivateFile
->EfiFile
;
1283 WinNtSimpleFileSystemClose (
1288 Routine Description:
1290 Close the specified file handle.
1294 This - Pointer to a returned opened file handle.
1298 EFI_SUCCESS - The file handle has been closed.
1301 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1303 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1307 return EFI_INVALID_PARAMETER
;
1310 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1312 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1314 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1315 if (PrivateFile
->IsDirectoryPath
) {
1316 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1318 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1321 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1324 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1325 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1326 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1329 if (PrivateFile
->FileName
) {
1330 FreePool (PrivateFile
->FileName
);
1333 FreePool (PrivateFile
);
1335 gBS
->RestoreTPL (OldTpl
);
1342 WinNtSimpleFileSystemDelete (
1347 Routine Description:
1349 Close and delete a file.
1353 This - Pointer to a returned opened file handle.
1357 EFI_SUCCESS - The file handle was closed and deleted.
1359 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1362 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1365 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1369 return EFI_INVALID_PARAMETER
;
1372 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1374 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1376 Status
= EFI_WARN_DELETE_FAILURE
;
1378 if (PrivateFile
->IsDirectoryPath
) {
1379 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1380 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1383 if (PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
1384 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
1385 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
1388 if (PrivateFile
->WinNtThunk
->RemoveDirectory (PrivateFile
->FileName
)) {
1389 Status
= EFI_SUCCESS
;
1392 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
1393 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
1395 if (!PrivateFile
->IsOpenedByRead
) {
1396 if (PrivateFile
->WinNtThunk
->DeleteFile (PrivateFile
->FileName
)) {
1397 Status
= EFI_SUCCESS
;
1402 FreePool (PrivateFile
->FileName
);
1403 FreePool (PrivateFile
);
1405 gBS
->RestoreTPL (OldTpl
);
1411 WinNtSystemTimeToEfiTime (
1412 IN SYSTEMTIME
*SystemTime
,
1413 IN TIME_ZONE_INFORMATION
*TimeZone
,
1418 Routine Description:
1420 TODO: Add function description
1424 SystemTime - TODO: add argument description
1425 TimeZone - TODO: add argument description
1426 Time - TODO: add argument description
1430 TODO: add return values
1434 Time
->Year
= (UINT16
) SystemTime
->wYear
;
1435 Time
->Month
= (UINT8
) SystemTime
->wMonth
;
1436 Time
->Day
= (UINT8
) SystemTime
->wDay
;
1437 Time
->Hour
= (UINT8
) SystemTime
->wHour
;
1438 Time
->Minute
= (UINT8
) SystemTime
->wMinute
;
1439 Time
->Second
= (UINT8
) SystemTime
->wSecond
;
1440 Time
->Nanosecond
= (UINT32
) SystemTime
->wMilliseconds
* 1000000;
1441 Time
->TimeZone
= (INT16
) TimeZone
->Bias
;
1443 if (TimeZone
->StandardDate
.wMonth
) {
1444 Time
->Daylight
= EFI_TIME_ADJUST_DAYLIGHT
;
1450 WinNtSimpleFileSystemRead (
1452 IN OUT UINTN
*BufferSize
,
1457 Routine Description:
1459 Read data from a file.
1463 This - Pointer to a returned open file handle.
1465 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1467 Buffer - Pointer to the first byte of the read Buffer.
1471 EFI_SUCCESS - The data was read.
1473 EFI_NO_MEDIA - The device has no media.
1475 EFI_DEVICE_ERROR - The device reported an error.
1477 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1479 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1480 *BufferSize has been updated with the size needed to complete the request.
1483 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1485 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1491 SYSTEMTIME SystemTime
;
1492 EFI_FILE_INFO
*Info
;
1494 TIME_ZONE_INFORMATION TimeZone
;
1495 EFI_FILE_INFO
*FileInfo
;
1501 if (This
== NULL
|| BufferSize
== NULL
) {
1502 return EFI_INVALID_PARAMETER
;
1505 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1507 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1509 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1510 Status
= EFI_DEVICE_ERROR
;
1514 if (!PrivateFile
->IsDirectoryPath
) {
1516 if (This
->GetPosition (This
, &Pos
) != EFI_SUCCESS
) {
1517 Status
= EFI_DEVICE_ERROR
;
1521 FileInfoSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
;
1522 FileInfo
= AllocatePool (FileInfoSize
);
1524 Status
= This
->GetInfo (
1531 if (Status
== EFI_BUFFER_TOO_SMALL
) {
1532 FreePool (FileInfo
);
1533 FileInfo
= AllocatePool (FileInfoSize
);
1534 Status
= This
->GetInfo (
1542 if (EFI_ERROR (Status
)) {
1543 Status
= EFI_DEVICE_ERROR
;
1547 FileSize
= FileInfo
->FileSize
;
1549 FreePool (FileInfo
);
1551 if (Pos
>= FileSize
) {
1553 if (Pos
== FileSize
) {
1554 Status
= EFI_SUCCESS
;
1557 Status
= EFI_DEVICE_ERROR
;
1562 Status
= PrivateFile
->WinNtThunk
->ReadFile (
1563 PrivateFile
->LHandle
,
1568 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1573 // Read on a directory. Perform a find next
1575 if (!PrivateFile
->IsValidFindBuf
) {
1577 Status
= EFI_SUCCESS
;
1581 Size
= SIZE_OF_EFI_FILE_INFO
;
1583 NameSize
= StrSize (PrivateFile
->FindBuf
.cFileName
);
1585 ResultSize
= Size
+ NameSize
;
1587 Status
= EFI_BUFFER_TOO_SMALL
;
1589 if (*BufferSize
>= ResultSize
) {
1590 Status
= EFI_SUCCESS
;
1593 ZeroMem (Info
, ResultSize
);
1595 Info
->Size
= ResultSize
;
1597 PrivateFile
->WinNtThunk
->GetTimeZoneInformation (&TimeZone
);
1599 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1600 &PrivateFile
->FindBuf
.ftCreationTime
,
1601 &PrivateFile
->FindBuf
.ftCreationTime
1604 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftCreationTime
, &SystemTime
);
1606 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->CreateTime
);
1608 PrivateFile
->WinNtThunk
->FileTimeToLocalFileTime (
1609 &PrivateFile
->FindBuf
.ftLastWriteTime
,
1610 &PrivateFile
->FindBuf
.ftLastWriteTime
1613 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&PrivateFile
->FindBuf
.ftLastWriteTime
, &SystemTime
);
1615 WinNtSystemTimeToEfiTime (&SystemTime
, &TimeZone
, &Info
->ModificationTime
);
1617 Info
->FileSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1619 Info
->PhysicalSize
= PrivateFile
->FindBuf
.nFileSizeLow
;
1621 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1622 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1625 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1626 Info
->Attribute
|= EFI_FILE_HIDDEN
;
1629 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
1630 Info
->Attribute
|= EFI_FILE_SYSTEM
;
1633 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
1634 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
1637 if (PrivateFile
->FindBuf
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
1638 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
1641 NameSize
= NameSize
/ sizeof (WCHAR
);
1643 pw
= (WCHAR
*) (((CHAR8
*) Buffer
) + Size
);
1645 for (Index
= 0; Index
< NameSize
; Index
++) {
1646 pw
[Index
] = PrivateFile
->FindBuf
.cFileName
[Index
];
1649 if (PrivateFile
->WinNtThunk
->FindNextFile (PrivateFile
->LHandle
, &PrivateFile
->FindBuf
)) {
1650 PrivateFile
->IsValidFindBuf
= TRUE
;
1652 PrivateFile
->IsValidFindBuf
= FALSE
;
1656 *BufferSize
= ResultSize
;
1659 gBS
->RestoreTPL (OldTpl
);
1665 WinNtSimpleFileSystemWrite (
1667 IN OUT UINTN
*BufferSize
,
1672 Routine Description:
1674 Write data to a file.
1678 This - Pointer to an opened file handle.
1680 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1681 of data written to the file.
1683 Buffer - Pointer to the first by of data in the buffer to write to the file.
1687 EFI_SUCCESS - The data was written to the file.
1689 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1691 EFI_NO_MEDIA - The device has no media.
1693 EFI_DEVICE_ERROR - The device reported an error.
1695 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1697 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1699 EFI_ACCESS_DENIED - The file was opened read-only.
1701 EFI_VOLUME_FULL - The volume is full.
1704 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1706 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1710 if (This
== NULL
|| BufferSize
== NULL
|| Buffer
== NULL
) {
1711 return EFI_INVALID_PARAMETER
;
1714 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1716 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1718 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1719 Status
= EFI_DEVICE_ERROR
;
1723 if (PrivateFile
->IsDirectoryPath
) {
1724 Status
= EFI_UNSUPPORTED
;
1728 if (PrivateFile
->IsOpenedByRead
) {
1729 Status
= EFI_ACCESS_DENIED
;
1733 Status
= PrivateFile
->WinNtThunk
->WriteFile (
1734 PrivateFile
->LHandle
,
1739 ) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
1742 gBS
->RestoreTPL (OldTpl
);
1746 // bugbug: need to access windows error reporting
1752 WinNtSimpleFileSystemSetPosition (
1758 Routine Description:
1760 Set a file's current position.
1764 This - Pointer to an opened file handle.
1766 Position - The byte position from the start of the file to set.
1770 EFI_SUCCESS - The file position has been changed.
1772 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1775 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1778 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1785 return EFI_INVALID_PARAMETER
;
1788 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1790 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1792 if (PrivateFile
->IsDirectoryPath
) {
1793 if (Position
!= 0) {
1794 Status
= EFI_UNSUPPORTED
;
1798 FileName
= AllocatePool (StrSize (PrivateFile
->FileName
) + StrSize (L
"\\*"));
1799 if (FileName
== NULL
) {
1800 Status
= EFI_OUT_OF_RESOURCES
;
1804 StrCpy (FileName
, PrivateFile
->FileName
);
1805 StrCat (FileName
, L
"\\*");
1807 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
1808 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
1811 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (FileName
, &PrivateFile
->FindBuf
);
1813 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
1814 PrivateFile
->IsValidFindBuf
= FALSE
;
1816 PrivateFile
->IsValidFindBuf
= TRUE
;
1819 FreePool (FileName
);
1821 Status
= (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1823 if (Position
== (UINT64
) -1) {
1824 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) 0, NULL
, FILE_END
);
1826 PosHigh
= (UINT32
) RShiftU64 (Position
, 32);
1828 PosLow
= PrivateFile
->WinNtThunk
->SetFilePointer (PrivateFile
->LHandle
, (ULONG
) Position
, &PosHigh
, FILE_BEGIN
);
1831 Status
= (PosLow
== 0xFFFFFFFF) ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1835 gBS
->RestoreTPL (OldTpl
);
1841 WinNtSimpleFileSystemGetPosition (
1843 OUT UINT64
*Position
1847 Routine Description:
1849 Get a file's current position.
1853 This - Pointer to an opened file handle.
1855 Position - Pointer to storage for the current position.
1859 EFI_SUCCESS - The file position has been reported.
1861 EFI_UNSUPPORTED - Not valid for directories.
1864 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1867 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
1872 if (This
== NULL
|| Position
== NULL
) {
1873 return EFI_INVALID_PARAMETER
;
1876 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
1877 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
1882 if (PrivateFile
->IsDirectoryPath
) {
1884 Status
= EFI_UNSUPPORTED
;
1890 *Position
= PrivateFile
->WinNtThunk
->SetFilePointer (
1891 PrivateFile
->LHandle
,
1897 Status
= *Position
== 0xffffffff ? EFI_DEVICE_ERROR
: EFI_SUCCESS
;
1898 if (EFI_ERROR (Status
)) {
1902 PosHigh64
= PositionHigh
;
1903 *Position
+= LShiftU64 (PosHigh64
, 32);
1907 gBS
->RestoreTPL (OldTpl
);
1912 WinNtSimpleFileSystemFileInfo (
1913 IN WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
,
1914 IN OUT UINTN
*BufferSize
,
1919 Routine Description:
1921 TODO: Add function description
1925 PrivateFile - TODO: add argument description
1926 BufferSize - TODO: add argument description
1927 Buffer - TODO: add argument description
1931 TODO: add return values
1939 EFI_FILE_INFO
*Info
;
1940 BY_HANDLE_FILE_INFORMATION FileInfo
;
1941 SYSTEMTIME SystemTime
;
1942 CHAR16
*RealFileName
;
1943 CHAR16
*TempPointer
;
1944 EFI_FILE_INFO
*DirInfo
;
1947 EFI_STATUS DirStatus
;
1950 Size
= SIZE_OF_EFI_FILE_INFO
;
1951 NameSize
= StrSize (PrivateFile
->FileName
);
1952 ResultSize
= Size
+ NameSize
;
1954 Status
= EFI_BUFFER_TOO_SMALL
;
1955 if (*BufferSize
>= ResultSize
) {
1956 Status
= EFI_SUCCESS
;
1959 ZeroMem (Info
, ResultSize
);
1961 Info
->Size
= ResultSize
;
1962 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (
1963 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
1966 Info
->FileSize
= FileInfo
.nFileSizeLow
;
1967 Info
->PhysicalSize
= Info
->FileSize
;
1969 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftCreationTime
, &SystemTime
);
1970 Info
->CreateTime
.Year
= SystemTime
.wYear
;
1971 Info
->CreateTime
.Month
= (UINT8
) SystemTime
.wMonth
;
1972 Info
->CreateTime
.Day
= (UINT8
) SystemTime
.wDay
;
1973 Info
->CreateTime
.Hour
= (UINT8
) SystemTime
.wHour
;
1974 Info
->CreateTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
1975 Info
->CreateTime
.Second
= (UINT8
) SystemTime
.wSecond
;
1977 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastAccessTime
, &SystemTime
);
1978 Info
->LastAccessTime
.Year
= SystemTime
.wYear
;
1979 Info
->LastAccessTime
.Month
= (UINT8
) SystemTime
.wMonth
;
1980 Info
->LastAccessTime
.Day
= (UINT8
) SystemTime
.wDay
;
1981 Info
->LastAccessTime
.Hour
= (UINT8
) SystemTime
.wHour
;
1982 Info
->LastAccessTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
1983 Info
->LastAccessTime
.Second
= (UINT8
) SystemTime
.wSecond
;
1985 PrivateFile
->WinNtThunk
->FileTimeToSystemTime (&FileInfo
.ftLastWriteTime
, &SystemTime
);
1986 Info
->ModificationTime
.Year
= SystemTime
.wYear
;
1987 Info
->ModificationTime
.Month
= (UINT8
) SystemTime
.wMonth
;
1988 Info
->ModificationTime
.Day
= (UINT8
) SystemTime
.wDay
;
1989 Info
->ModificationTime
.Hour
= (UINT8
) SystemTime
.wHour
;
1990 Info
->ModificationTime
.Minute
= (UINT8
) SystemTime
.wMinute
;
1991 Info
->ModificationTime
.Second
= (UINT8
) SystemTime
.wSecond
;
1993 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_ARCHIVE
) {
1994 Info
->Attribute
|= EFI_FILE_ARCHIVE
;
1997 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_HIDDEN
) {
1998 Info
->Attribute
|= EFI_FILE_HIDDEN
;
2001 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2002 Info
->Attribute
|= EFI_FILE_READ_ONLY
;
2005 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_SYSTEM
) {
2006 Info
->Attribute
|= EFI_FILE_SYSTEM
;
2009 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_DIRECTORY
) {
2010 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2013 if (PrivateFile
->IsDirectoryPath
) {
2014 Info
->Attribute
|= EFI_FILE_DIRECTORY
;
2017 RealFileName
= PrivateFile
->FileName
;
2018 TempPointer
= RealFileName
;
2020 while (*TempPointer
) {
2021 if (*TempPointer
== '\\') {
2022 RealFileName
= TempPointer
+ 1;
2028 if (PrivateFile
->IsRootDirectory
) {
2029 *((CHAR8
*) Buffer
+ Size
) = 0;
2031 CopyMem ((CHAR8
*) Buffer
+ Size
, RealFileName
, NameSize
);
2034 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
2036 // The GetFileInformationByHandle.nFileSizeLow is bogus for dir so we
2037 // need to do the same thing the caller would do to get the right value
2039 ASSERT (PrivateFile
->EfiFile
.Read
!= NULL
);
2040 DirStatus
= PrivateFile
->EfiFile
.GetPosition (&PrivateFile
->EfiFile
, &Location
);
2041 if (EFI_ERROR (DirStatus
)) {
2045 PrivateFile
->EfiFile
.SetPosition (&PrivateFile
->EfiFile
, 0);
2050 DirStatus
= PrivateFile
->EfiFile
.Read (&PrivateFile
->EfiFile
, &ReadSize
, DirInfo
);
2051 if (DirStatus
== EFI_BUFFER_TOO_SMALL
) {
2052 DirInfo
= AllocatePool (ReadSize
);
2053 if (DirInfo
!= NULL
) {
2055 // Read each dir entry to figure out how big the directory is
2057 DirStatus
= PrivateFile
->EfiFile
.Read (&PrivateFile
->EfiFile
, &ReadSize
, DirInfo
);
2058 if (!EFI_ERROR (DirStatus
) && (ReadSize
!= 0)) {
2059 Info
->FileSize
+= ReadSize
;
2065 } while (!EFI_ERROR (DirStatus
) && (ReadSize
!= 0));
2068 // reset the file possition back to the previous location
2070 PrivateFile
->EfiFile
.SetPosition (&PrivateFile
->EfiFile
, Location
);
2074 *BufferSize
= ResultSize
;
2080 WinNtSimpleFileSystemGetInfo (
2082 IN EFI_GUID
*InformationType
,
2083 IN OUT UINTN
*BufferSize
,
2088 Routine Description:
2090 Return information about a file or volume.
2094 This - Pointer to an opened file handle.
2096 InformationType - GUID describing the type of information to be returned.
2098 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
2101 Buffer - Pointer to the first byte of the information buffer.
2105 EFI_SUCCESS - The requested information has been written into the buffer.
2107 EFI_UNSUPPORTED - The InformationType is not known.
2109 EFI_NO_MEDIA - The device has no media.
2111 EFI_DEVICE_ERROR - The device reported an error.
2113 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2115 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
2116 been updated with the size needed to complete the requested operation.
2119 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2122 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2123 EFI_FILE_SYSTEM_INFO
*FileSystemInfoBuffer
;
2124 UINT32 SectorsPerCluster
;
2125 UINT32 BytesPerSector
;
2126 UINT32 FreeClusters
;
2127 UINT32 TotalClusters
;
2128 UINT32 BytesPerCluster
;
2130 BOOLEAN DriveNameFound
;
2133 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2136 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== NULL
) {
2137 return EFI_INVALID_PARAMETER
;
2140 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2142 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2143 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2145 Status
= EFI_UNSUPPORTED
;
2147 if (CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2148 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, BufferSize
, Buffer
);
2151 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2152 if (*BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2153 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2154 Status
= EFI_BUFFER_TOO_SMALL
;
2158 FileSystemInfoBuffer
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2159 FileSystemInfoBuffer
->Size
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2160 FileSystemInfoBuffer
->ReadOnly
= FALSE
;
2163 // Try to get the drive name
2165 DriveNameFound
= FALSE
;
2166 DriveName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + 1);
2167 if (DriveName
== NULL
) {
2168 Status
= EFI_OUT_OF_RESOURCES
;
2172 StrCpy (DriveName
, PrivateFile
->FilePath
);
2173 for (Index
= 0; DriveName
[Index
] != 0 && DriveName
[Index
] != ':'; Index
++) {
2177 if (DriveName
[Index
] == ':') {
2178 DriveName
[Index
+ 1] = '\\';
2179 DriveName
[Index
+ 2] = 0;
2180 DriveNameFound
= TRUE
;
2181 } else if (DriveName
[0] == '\\' && DriveName
[1] == '\\') {
2182 for (Index
= 2; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2186 if (DriveName
[Index
] == '\\') {
2187 DriveNameFound
= TRUE
;
2188 for (Index
++; DriveName
[Index
] != 0 && DriveName
[Index
] != '\\'; Index
++) {
2192 DriveName
[Index
] = '\\';
2193 DriveName
[Index
+ 1] = 0;
2198 // Try GetDiskFreeSpace first
2200 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpace (
2201 DriveNameFound
? DriveName
: NULL
,
2208 FreePool (DriveName
);
2215 BytesPerCluster
= BytesPerSector
* SectorsPerCluster
;
2216 FileSystemInfoBuffer
->VolumeSize
= MultU64x32 (TotalClusters
, BytesPerCluster
);
2217 FileSystemInfoBuffer
->FreeSpace
= MultU64x32 (FreeClusters
, BytesPerCluster
);
2218 FileSystemInfoBuffer
->BlockSize
= BytesPerCluster
;
2222 // try GetDiskFreeSpaceEx then
2224 FileSystemInfoBuffer
->BlockSize
= 0;
2225 NtStatus
= PrivateFile
->WinNtThunk
->GetDiskFreeSpaceEx (
2226 PrivateFile
->FilePath
,
2227 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->FreeSpace
),
2228 (PULARGE_INTEGER
) (&FileSystemInfoBuffer
->VolumeSize
),
2232 Status
= EFI_DEVICE_ERROR
;
2237 StrCpy ((CHAR16
*) FileSystemInfoBuffer
->VolumeLabel
, PrivateRoot
->VolumeLabel
);
2238 *BufferSize
= SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
);
2239 Status
= EFI_SUCCESS
;
2242 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2243 if (*BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2244 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2245 Status
= EFI_BUFFER_TOO_SMALL
;
2249 StrCpy ((CHAR16
*) Buffer
, PrivateRoot
->VolumeLabel
);
2250 *BufferSize
= StrSize (PrivateRoot
->VolumeLabel
);
2251 Status
= EFI_SUCCESS
;
2255 gBS
->RestoreTPL (OldTpl
);
2261 WinNtSimpleFileSystemSetInfo (
2263 IN EFI_GUID
*InformationType
,
2264 IN UINTN BufferSize
,
2269 Routine Description:
2271 Set information about a file or volume.
2275 This - Pointer to an opened file handle.
2277 InformationType - GUID identifying the type of information to set.
2279 BufferSize - Number of bytes of data in the information buffer.
2281 Buffer - Pointer to the first byte of data in the information buffer.
2285 EFI_SUCCESS - The file or volume information has been updated.
2287 EFI_UNSUPPORTED - The information identifier is not recognised.
2289 EFI_NO_MEDIA - The device has no media.
2291 EFI_DEVICE_ERROR - The device reported an error.
2293 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2295 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2297 EFI_ACCESS_DENIED - The file was opened read-only.
2299 EFI_VOLUME_FULL - The volume is full.
2301 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2304 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2305 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2307 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE
*PrivateRoot
;
2308 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2309 EFI_FILE_INFO
*OldFileInfo
;
2310 EFI_FILE_INFO
*NewFileInfo
;
2316 CHAR16
*OldFileName
;
2317 CHAR16
*NewFileName
;
2318 CHAR16
*TempFileName
;
2319 CHAR16
*CharPointer
;
2320 BOOLEAN AttrChangeFlag
;
2321 BOOLEAN NameChangeFlag
;
2322 BOOLEAN SizeChangeFlag
;
2323 BOOLEAN TimeChangeFlag
;
2325 SYSTEMTIME NewCreationSystemTime
;
2326 SYSTEMTIME NewLastAccessSystemTime
;
2327 SYSTEMTIME NewLastWriteSystemTime
;
2328 FILETIME NewCreationFileTime
;
2329 FILETIME NewLastAccessFileTime
;
2330 FILETIME NewLastWriteFileTime
;
2331 WIN32_FIND_DATA FindBuf
;
2332 EFI_FILE_SYSTEM_INFO
*NewFileSystemInfo
;
2336 // Check for invalid parameters.
2338 if (This
== NULL
|| InformationType
== NULL
|| BufferSize
== 0 || Buffer
== NULL
) {
2339 return EFI_INVALID_PARAMETER
;
2342 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2345 // Initialise locals.
2347 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2348 PrivateRoot
= WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile
->SimpleFileSystem
);
2350 Status
= EFI_UNSUPPORTED
;
2351 OldFileInfo
= NewFileInfo
= NULL
;
2352 OldFileName
= NewFileName
= NULL
;
2353 AttrChangeFlag
= NameChangeFlag
= SizeChangeFlag
= TimeChangeFlag
= FALSE
;
2356 // Set file system information.
2358 if (CompareGuid (InformationType
, &gEfiFileSystemInfoGuid
)) {
2359 if (BufferSize
< SIZE_OF_EFI_FILE_SYSTEM_INFO
+ StrSize (PrivateRoot
->VolumeLabel
)) {
2360 Status
= EFI_BAD_BUFFER_SIZE
;
2364 NewFileSystemInfo
= (EFI_FILE_SYSTEM_INFO
*) Buffer
;
2366 FreePool (PrivateRoot
->VolumeLabel
);
2367 PrivateRoot
->VolumeLabel
= AllocatePool (StrSize (NewFileSystemInfo
->VolumeLabel
));
2368 if (PrivateRoot
->VolumeLabel
== NULL
) {
2369 Status
= EFI_OUT_OF_RESOURCES
;
2373 StrCpy (PrivateRoot
->VolumeLabel
, NewFileSystemInfo
->VolumeLabel
);
2375 Status
= EFI_SUCCESS
;
2380 // Set volume label information.
2382 if (CompareGuid (InformationType
, &gEfiFileSystemVolumeLabelInfoIdGuid
)) {
2383 if (BufferSize
< StrSize (PrivateRoot
->VolumeLabel
)) {
2384 Status
= EFI_BAD_BUFFER_SIZE
;
2388 StrCpy (PrivateRoot
->VolumeLabel
, (CHAR16
*) Buffer
);
2390 Status
= EFI_SUCCESS
;
2394 if (!CompareGuid (InformationType
, &gEfiFileInfoGuid
)) {
2395 Status
= EFI_UNSUPPORTED
;
2399 if (BufferSize
< SIZE_OF_EFI_FILE_INFO
) {
2400 Status
= EFI_BAD_BUFFER_SIZE
;
2405 // Set file/directory information.
2409 // Check for invalid set file information parameters.
2411 NewFileInfo
= (EFI_FILE_INFO
*) Buffer
;
2413 if (NewFileInfo
->Size
<= sizeof (EFI_FILE_INFO
) ||
2414 (NewFileInfo
->Attribute
&~(EFI_FILE_VALID_ATTR
)) ||
2415 (sizeof (UINTN
) == 4 && NewFileInfo
->Size
> 0xFFFFFFFF)
2417 Status
= EFI_INVALID_PARAMETER
;
2422 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2423 // that would have an additional parameter that would be the size
2424 // of the string array just in case there are no NULL characters in
2425 // the string array.
2428 // Get current file information so we can determine what kind
2429 // of change request this is.
2432 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, NULL
);
2434 if (Status
!= EFI_BUFFER_TOO_SMALL
) {
2435 Status
= EFI_DEVICE_ERROR
;
2439 OldFileInfo
= AllocatePool (OldInfoSize
);
2440 if (OldFileInfo
== NULL
) {
2441 Status
= EFI_OUT_OF_RESOURCES
;
2445 Status
= WinNtSimpleFileSystemFileInfo (PrivateFile
, &OldInfoSize
, OldFileInfo
);
2447 if (EFI_ERROR (Status
)) {
2451 OldFileName
= AllocatePool (StrSize (PrivateFile
->FileName
));
2452 if (OldFileName
== NULL
) {
2453 Status
= EFI_OUT_OF_RESOURCES
;
2457 StrCpy (OldFileName
, PrivateFile
->FileName
);
2460 // Make full pathname from new filename and rootpath.
2462 if (NewFileInfo
->FileName
[0] == '\\') {
2463 NewFileName
= AllocatePool (StrSize (PrivateRoot
->FilePath
) + StrSize (L
"\\") + StrSize (NewFileInfo
->FileName
));
2464 if (NewFileName
== NULL
) {
2465 Status
= EFI_OUT_OF_RESOURCES
;
2469 StrCpy (NewFileName
, PrivateRoot
->FilePath
);
2470 StrCat (NewFileName
, L
"\\");
2471 StrCat (NewFileName
, NewFileInfo
->FileName
+ 1);
2473 NewFileName
= AllocatePool (StrSize (PrivateFile
->FilePath
) + StrSize (L
"\\") + StrSize (NewFileInfo
->FileName
));
2474 if (NewFileName
== NULL
) {
2475 Status
= EFI_OUT_OF_RESOURCES
;
2479 StrCpy (NewFileName
, PrivateFile
->FilePath
);
2480 StrCat (NewFileName
, L
"\\");
2481 StrCat (NewFileName
, NewFileInfo
->FileName
);
2485 // Is there an attribute change request?
2487 if (NewFileInfo
->Attribute
!= OldFileInfo
->Attribute
) {
2488 if ((NewFileInfo
->Attribute
& EFI_FILE_DIRECTORY
) != (OldFileInfo
->Attribute
& EFI_FILE_DIRECTORY
)) {
2489 Status
= EFI_INVALID_PARAMETER
;
2493 AttrChangeFlag
= TRUE
;
2497 // Is there a name change request?
2498 // bugbug: - Need EfiStrCaseCmp()
2500 if (StrCmp (NewFileInfo
->FileName
, OldFileInfo
->FileName
)) {
2501 NameChangeFlag
= TRUE
;
2505 // Is there a size change request?
2507 if (NewFileInfo
->FileSize
!= OldFileInfo
->FileSize
) {
2508 SizeChangeFlag
= TRUE
;
2512 // Is there a time stamp change request?
2514 if (!IsZero (&NewFileInfo
->CreateTime
, sizeof (EFI_TIME
)) &&
2515 CompareMem (&NewFileInfo
->CreateTime
, &OldFileInfo
->CreateTime
, sizeof (EFI_TIME
))
2517 TimeChangeFlag
= TRUE
;
2518 } else if (!IsZero (&NewFileInfo
->LastAccessTime
, sizeof (EFI_TIME
)) &&
2519 CompareMem (&NewFileInfo
->LastAccessTime
, &OldFileInfo
->LastAccessTime
, sizeof (EFI_TIME
))
2521 TimeChangeFlag
= TRUE
;
2522 } else if (!IsZero (&NewFileInfo
->ModificationTime
, sizeof (EFI_TIME
)) &&
2523 CompareMem (&NewFileInfo
->ModificationTime
, &OldFileInfo
->ModificationTime
, sizeof (EFI_TIME
))
2525 TimeChangeFlag
= TRUE
;
2529 // All done if there are no change requests being made.
2531 if (!(AttrChangeFlag
|| NameChangeFlag
|| SizeChangeFlag
|| TimeChangeFlag
)) {
2532 Status
= EFI_SUCCESS
;
2537 // Set file or directory information.
2539 OldAttr
= PrivateFile
->WinNtThunk
->GetFileAttributes (OldFileName
);
2544 if (NameChangeFlag
) {
2546 // Close the handles first
2548 if (PrivateFile
->IsOpenedByRead
) {
2549 Status
= EFI_ACCESS_DENIED
;
2553 for (CharPointer
= NewFileName
; *CharPointer
!= 0 && *CharPointer
!= L
'/'; CharPointer
++) {
2556 if (*CharPointer
!= 0) {
2557 Status
= EFI_ACCESS_DENIED
;
2561 if (PrivateFile
->LHandle
!= INVALID_HANDLE_VALUE
) {
2562 if (PrivateFile
->IsDirectoryPath
) {
2563 PrivateFile
->WinNtThunk
->FindClose (PrivateFile
->LHandle
);
2565 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->LHandle
);
2566 PrivateFile
->LHandle
= INVALID_HANDLE_VALUE
;
2570 if (PrivateFile
->IsDirectoryPath
&& PrivateFile
->DirHandle
!= INVALID_HANDLE_VALUE
) {
2571 PrivateFile
->WinNtThunk
->CloseHandle (PrivateFile
->DirHandle
);
2572 PrivateFile
->DirHandle
= INVALID_HANDLE_VALUE
;
2575 NtStatus
= PrivateFile
->WinNtThunk
->MoveFile (OldFileName
, NewFileName
);
2581 FreePool (PrivateFile
->FileName
);
2583 PrivateFile
->FileName
= AllocatePool (StrSize (NewFileName
));
2584 if (PrivateFile
->FileName
== NULL
) {
2585 Status
= EFI_OUT_OF_RESOURCES
;
2589 StrCpy (PrivateFile
->FileName
, NewFileName
);
2591 TempFileName
= AllocatePool (StrSize (NewFileName
) + StrSize (L
"\\*"));
2593 StrCpy (TempFileName
, NewFileName
);
2595 if (!PrivateFile
->IsDirectoryPath
) {
2596 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2598 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2599 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2606 FreePool (TempFileName
);
2609 // Flush buffers just in case
2611 if (PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) == 0) {
2612 Status
= EFI_DEVICE_ERROR
;
2616 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2618 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2619 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2622 FILE_FLAG_BACKUP_SEMANTICS
,
2626 StrCat (TempFileName
, L
"\\*");
2627 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2629 FreePool (TempFileName
);
2633 Status
= EFI_DEVICE_ERROR
;
2635 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (OldFileName
, OldAttr
);
2641 TempFileName
= AllocatePool (StrSize (OldFileName
) + StrSize (L
"\\*"));
2643 StrCpy (TempFileName
, OldFileName
);
2645 if (!PrivateFile
->IsDirectoryPath
) {
2646 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2648 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2649 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2656 PrivateFile
->DirHandle
= PrivateFile
->WinNtThunk
->CreateFile (
2658 PrivateFile
->IsOpenedByRead
? GENERIC_READ
: GENERIC_READ
| GENERIC_WRITE
,
2659 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
2662 FILE_FLAG_BACKUP_SEMANTICS
,
2666 StrCat (TempFileName
, L
"\\*");
2667 PrivateFile
->LHandle
= PrivateFile
->WinNtThunk
->FindFirstFile (TempFileName
, &FindBuf
);
2670 FreePool (TempFileName
);
2680 if (SizeChangeFlag
) {
2681 if (PrivateFile
->IsDirectoryPath
) {
2682 Status
= EFI_UNSUPPORTED
;
2686 if (PrivateFile
->IsOpenedByRead
|| OldFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2687 Status
= EFI_ACCESS_DENIED
;
2691 Status
= This
->GetPosition (This
, &CurPos
);
2692 if (EFI_ERROR (Status
)) {
2696 Status
= This
->SetPosition (This
, NewFileInfo
->FileSize
);
2697 if (EFI_ERROR (Status
)) {
2701 if (PrivateFile
->WinNtThunk
->SetEndOfFile (PrivateFile
->LHandle
) == 0) {
2702 Status
= EFI_DEVICE_ERROR
;
2706 Status
= This
->SetPosition (This
, CurPos
);
2707 if (EFI_ERROR (Status
)) {
2715 if (TimeChangeFlag
) {
2717 NewCreationSystemTime
.wYear
= NewFileInfo
->CreateTime
.Year
;
2718 NewCreationSystemTime
.wMonth
= NewFileInfo
->CreateTime
.Month
;
2719 NewCreationSystemTime
.wDay
= NewFileInfo
->CreateTime
.Day
;
2720 NewCreationSystemTime
.wHour
= NewFileInfo
->CreateTime
.Hour
;
2721 NewCreationSystemTime
.wMinute
= NewFileInfo
->CreateTime
.Minute
;
2722 NewCreationSystemTime
.wSecond
= NewFileInfo
->CreateTime
.Second
;
2723 NewCreationSystemTime
.wMilliseconds
= 0;
2725 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2726 &NewCreationSystemTime
,
2727 &NewCreationFileTime
2732 NewLastAccessSystemTime
.wYear
= NewFileInfo
->LastAccessTime
.Year
;
2733 NewLastAccessSystemTime
.wMonth
= NewFileInfo
->LastAccessTime
.Month
;
2734 NewLastAccessSystemTime
.wDay
= NewFileInfo
->LastAccessTime
.Day
;
2735 NewLastAccessSystemTime
.wHour
= NewFileInfo
->LastAccessTime
.Hour
;
2736 NewLastAccessSystemTime
.wMinute
= NewFileInfo
->LastAccessTime
.Minute
;
2737 NewLastAccessSystemTime
.wSecond
= NewFileInfo
->LastAccessTime
.Second
;
2738 NewLastAccessSystemTime
.wMilliseconds
= 0;
2740 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2741 &NewLastAccessSystemTime
,
2742 &NewLastAccessFileTime
2747 NewLastWriteSystemTime
.wYear
= NewFileInfo
->ModificationTime
.Year
;
2748 NewLastWriteSystemTime
.wMonth
= NewFileInfo
->ModificationTime
.Month
;
2749 NewLastWriteSystemTime
.wDay
= NewFileInfo
->ModificationTime
.Day
;
2750 NewLastWriteSystemTime
.wHour
= NewFileInfo
->ModificationTime
.Hour
;
2751 NewLastWriteSystemTime
.wMinute
= NewFileInfo
->ModificationTime
.Minute
;
2752 NewLastWriteSystemTime
.wSecond
= NewFileInfo
->ModificationTime
.Second
;
2753 NewLastWriteSystemTime
.wMilliseconds
= 0;
2755 if (!PrivateFile
->WinNtThunk
->SystemTimeToFileTime (
2756 &NewLastWriteSystemTime
,
2757 &NewLastWriteFileTime
2762 if (!PrivateFile
->WinNtThunk
->SetFileTime (
2763 PrivateFile
->IsDirectoryPath
? PrivateFile
->DirHandle
: PrivateFile
->LHandle
,
2764 &NewCreationFileTime
,
2765 &NewLastAccessFileTime
,
2766 &NewLastWriteFileTime
2768 Status
= EFI_DEVICE_ERROR
;
2775 // No matter about AttrChangeFlag, Attribute must be set.
2776 // Because operation before may cause attribute change.
2780 if (NewFileInfo
->Attribute
& EFI_FILE_ARCHIVE
) {
2781 NewAttr
|= FILE_ATTRIBUTE_ARCHIVE
;
2783 NewAttr
&= ~FILE_ATTRIBUTE_ARCHIVE
;
2786 if (NewFileInfo
->Attribute
& EFI_FILE_HIDDEN
) {
2787 NewAttr
|= FILE_ATTRIBUTE_HIDDEN
;
2789 NewAttr
&= ~FILE_ATTRIBUTE_HIDDEN
;
2792 if (NewFileInfo
->Attribute
& EFI_FILE_SYSTEM
) {
2793 NewAttr
|= FILE_ATTRIBUTE_SYSTEM
;
2795 NewAttr
&= ~FILE_ATTRIBUTE_SYSTEM
;
2798 if (NewFileInfo
->Attribute
& EFI_FILE_READ_ONLY
) {
2799 NewAttr
|= FILE_ATTRIBUTE_READONLY
;
2801 NewAttr
&= ~FILE_ATTRIBUTE_READONLY
;
2804 NtStatus
= PrivateFile
->WinNtThunk
->SetFileAttributes (NewFileName
, NewAttr
);
2811 if (OldFileInfo
!= NULL
) {
2812 FreePool (OldFileInfo
);
2815 if (OldFileName
!= NULL
) {
2816 FreePool (OldFileName
);
2819 if (NewFileName
!= NULL
) {
2820 FreePool (NewFileName
);
2823 gBS
->RestoreTPL (OldTpl
);
2829 WinNtSimpleFileSystemFlush (
2834 Routine Description:
2836 Flush all modified data to the media.
2840 This - Pointer to an opened file handle.
2844 EFI_SUCCESS - The data has been flushed.
2846 EFI_NO_MEDIA - The device has no media.
2848 EFI_DEVICE_ERROR - The device reported an error.
2850 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2852 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2854 EFI_ACCESS_DENIED - The file was opened read-only.
2856 EFI_VOLUME_FULL - The volume is full.
2859 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2861 BY_HANDLE_FILE_INFORMATION FileInfo
;
2862 WIN_NT_EFI_FILE_PRIVATE
*PrivateFile
;
2867 return EFI_INVALID_PARAMETER
;
2870 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
2872 PrivateFile
= WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This
);
2874 if (PrivateFile
->LHandle
== INVALID_HANDLE_VALUE
) {
2875 Status
= EFI_DEVICE_ERROR
;
2879 if (PrivateFile
->IsDirectoryPath
) {
2880 Status
= EFI_SUCCESS
;
2884 if (PrivateFile
->IsOpenedByRead
) {
2885 Status
= EFI_ACCESS_DENIED
;
2889 PrivateFile
->WinNtThunk
->GetFileInformationByHandle (PrivateFile
->LHandle
, &FileInfo
);
2891 if (FileInfo
.dwFileAttributes
& FILE_ATTRIBUTE_READONLY
) {
2892 Status
= EFI_ACCESS_DENIED
;
2896 Status
= PrivateFile
->WinNtThunk
->FlushFileBuffers (PrivateFile
->LHandle
) ? EFI_SUCCESS
: EFI_DEVICE_ERROR
;
2899 gBS
->RestoreTPL (OldTpl
);
2902 // bugbug: - Use Windows error reporting.