blob: 1c300b6930f2568262d2eb628978b36bb4fcb562 [file] [log] [blame]
Vishal Bhoj82c80712015-12-15 21:13:33 +05301/**@file
2
3Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
4This program and the accompanying materials
5are licensed and made available under the terms and conditions of the BSD License
6which accompanies this distribution. The full text of the license may be found at
7http://opensource.org/licenses/bsd-license.php
8
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
11
12Module Name:
13
14 WinNtSimpleFileSystem.c
15
16Abstract:
17
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.
22
23 * Other names and brands may be claimed as the property of others.
24
25**/
26
27//
28// The package level header files this module uses
29//
30#include <Uefi.h>
31#include <WinNtDxe.h>
32//
33// The protocols, PPI and GUID defintions for this module
34//
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>
42//
43// The Library classes this module consumes
44//
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>
52
53#include "WinNtSimpleFileSystem.h"
54
55EFI_DRIVER_BINDING_PROTOCOL gWinNtSimpleFileSystemDriverBinding = {
56 WinNtSimpleFileSystemDriverBindingSupported,
57 WinNtSimpleFileSystemDriverBindingStart,
58 WinNtSimpleFileSystemDriverBindingStop,
59 0xa,
60 NULL,
61 NULL
62};
63
64/**
65 The user Entry Point for module WinNtSimpleFileSystem. The user code starts with this function.
66
67 @param[in] ImageHandle The firmware allocated handle for the EFI image.
68 @param[in] SystemTable A pointer to the EFI System Table.
69
70 @retval EFI_SUCCESS The entry point is executed successfully.
71 @retval other Some error occurs when executing this entry point.
72
73**/
74EFI_STATUS
75EFIAPI
76InitializeWinNtSimpleFileSystem(
77 IN EFI_HANDLE ImageHandle,
78 IN EFI_SYSTEM_TABLE *SystemTable
79 )
80{
81 EFI_STATUS Status;
82
83 //
84 // Install driver model protocol(s).
85 //
86 Status = EfiLibInstallDriverBindingComponentName2 (
87 ImageHandle,
88 SystemTable,
89 &gWinNtSimpleFileSystemDriverBinding,
90 ImageHandle,
91 &gWinNtSimpleFileSystemComponentName,
92 &gWinNtSimpleFileSystemComponentName2
93 );
94 ASSERT_EFI_ERROR (Status);
95
96
97 return Status;
98}
99
100CHAR16 *
101EfiStrChr (
102 IN CHAR16 *Str,
103 IN CHAR16 Chr
104 )
105/*++
106
107Routine Description:
108
109 Locate the first occurance of a character in a string.
110
111Arguments:
112
113 Str - Pointer to NULL terminated unicode string.
114 Chr - Character to locate.
115
116Returns:
117
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.
121
122--*/
123{
124 if (Str == NULL) {
125 return Str;
126 }
127
128 while (*Str != '\0' && *Str != Chr) {
129 ++Str;
130 }
131
132 return (*Str == Chr) ? Str : NULL;
133}
134
135BOOLEAN
136IsZero (
137 IN VOID *Buffer,
138 IN UINTN Length
139 )
140/*++
141
142Routine Description:
143
144 TODO: Add function description
145
146Arguments:
147
148 Buffer - TODO: add argument description
149 Length - TODO: add argument description
150
151Returns:
152
153 TODO: add return values
154
155--*/
156{
157 if (Buffer == NULL || Length == 0) {
158 return FALSE;
159 }
160
161 if (*(UINT8 *) Buffer != 0) {
162 return FALSE;
163 }
164
165 if (Length > 1) {
166 if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) {
167 return FALSE;
168 }
169 }
170
171 return TRUE;
172}
173
174VOID
175CutPrefix (
176 IN CHAR16 *Str,
177 IN UINTN Count
178 )
179/*++
180
181Routine Description:
182
183 TODO: Add function description
184
185Arguments:
186
187 Str - TODO: add argument description
188 Count - TODO: add argument description
189
190Returns:
191
192 TODO: add return values
193
194--*/
195{
196 CHAR16 *Pointer;
197
198 if (StrLen (Str) < Count) {
199 ASSERT (0);
200 }
201
202 if (Count != 0) {
203 for (Pointer = Str; *(Pointer + Count); Pointer++) {
204 *Pointer = *(Pointer + Count);
205 }
206 *Pointer = *(Pointer + Count);
207 }
208}
209
210
211
212EFI_STATUS
213EFIAPI
214WinNtSimpleFileSystemDriverBindingSupported (
215 IN EFI_DRIVER_BINDING_PROTOCOL *This,
216 IN EFI_HANDLE ControllerHandle,
217 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
218 )
219/*++
220
221Routine Description:
222
223 Check to see if the driver supports a given controller.
224
225Arguments:
226
227 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
228
229 ControllerHandle - EFI handle of the controller to test.
230
231 RemainingDevicePath - Pointer to remaining portion of a device path.
232
233Returns:
234
235 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver
236 specified by This.
237
238 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by
239 the driver specified by This.
240
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.
243
244 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the
245 driver specified by This.
246
247--*/
248{
249 EFI_STATUS Status;
250 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
251
252 //
253 // Open the IO Abstraction(s) needed to perform the supported test
254 //
255 Status = gBS->OpenProtocol (
256 ControllerHandle,
257 &gEfiWinNtIoProtocolGuid,
258 (VOID **) &WinNtIo,
259 This->DriverBindingHandle,
260 ControllerHandle,
261 EFI_OPEN_PROTOCOL_BY_DRIVER
262 );
263 if (EFI_ERROR (Status)) {
264 return Status;
265 }
266
267 //
268 // Make sure GUID is for a File System handle.
269 //
270 Status = EFI_UNSUPPORTED;
271 if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtFileSystemGuid)) {
272 Status = EFI_SUCCESS;
273 }
274
275 //
276 // Close the I/O Abstraction(s) used to perform the supported test
277 //
278 gBS->CloseProtocol (
279 ControllerHandle,
280 &gEfiWinNtIoProtocolGuid,
281 This->DriverBindingHandle,
282 ControllerHandle
283 );
284
285 return Status;
286}
287
288EFI_STATUS
289EFIAPI
290WinNtSimpleFileSystemDriverBindingStart (
291 IN EFI_DRIVER_BINDING_PROTOCOL *This,
292 IN EFI_HANDLE ControllerHandle,
293 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
294 )
295/*++
296
297Routine Description:
298
299 Starts a device controller or a bus controller.
300
301Arguments:
302
303 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
304
305 ControllerHandle - EFI handle of the controller to start.
306
307 RemainingDevicePath - Pointer to remaining portion of a device path.
308
309Returns:
310
311 EFI_SUCCESS - The device or bus controller has been started.
312
313 EFI_DEVICE_ERROR - The device could not be started due to a device failure.
314
315 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.
316
317--*/
318{
319 EFI_STATUS Status;
320 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;
321 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
322
323 Private = NULL;
324
325 //
326 // Open the IO Abstraction(s) needed
327 //
328 Status = gBS->OpenProtocol (
329 ControllerHandle,
330 &gEfiWinNtIoProtocolGuid,
331 (VOID **) &WinNtIo,
332 This->DriverBindingHandle,
333 ControllerHandle,
334 EFI_OPEN_PROTOCOL_BY_DRIVER
335 );
336 if (EFI_ERROR (Status)) {
337 return Status;
338 }
339
340 //
341 // Validate GUID
342 //
343 if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtFileSystemGuid)) {
344 Status = EFI_UNSUPPORTED;
345 goto Done;
346 }
347
348 Private = AllocatePool (sizeof (WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE));
349 if (Private == NULL) {
350 Status = EFI_OUT_OF_RESOURCES;
351
352 goto Done;
353 }
354
355 Private->Signature = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;
356 Private->WinNtThunk = WinNtIo->WinNtThunk;
357
358 Private->FilePath = WinNtIo->EnvString;
359
360 Private->VolumeLabel = AllocatePool (StrSize (L"EFI_EMULATED"));
361 if (Private->VolumeLabel == NULL) {
362 Status = EFI_OUT_OF_RESOURCES;
363 goto Done;
364 }
365
366 StrCpy (Private->VolumeLabel, L"EFI_EMULATED");
367
368 Private->SimpleFileSystem.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
369 Private->SimpleFileSystem.OpenVolume = WinNtSimpleFileSystemOpenVolume;
370
371 Private->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS);
372
373 Private->ControllerNameTable = NULL;
374
375 AddUnicodeString2 (
376 "eng",
377 gWinNtSimpleFileSystemComponentName.SupportedLanguages,
378 &Private->ControllerNameTable,
379 WinNtIo->EnvString,
380 TRUE
381 );
382 AddUnicodeString2 (
383 "en",
384 gWinNtSimpleFileSystemComponentName2.SupportedLanguages,
385 &Private->ControllerNameTable,
386 WinNtIo->EnvString,
387 FALSE
388 );
389
390
391 Status = gBS->InstallMultipleProtocolInterfaces (
392 &ControllerHandle,
393 &gEfiSimpleFileSystemProtocolGuid,
394 &Private->SimpleFileSystem,
395 NULL
396 );
397
398Done:
399 if (EFI_ERROR (Status)) {
400
401 if (Private != NULL) {
402
403 FreeUnicodeStringTable (Private->ControllerNameTable);
404
405 FreePool (Private);
406 }
407
408 gBS->CloseProtocol (
409 ControllerHandle,
410 &gEfiWinNtIoProtocolGuid,
411 This->DriverBindingHandle,
412 ControllerHandle
413 );
414 }
415
416 return Status;
417}
418
419EFI_STATUS
420EFIAPI
421WinNtSimpleFileSystemDriverBindingStop (
422 IN EFI_DRIVER_BINDING_PROTOCOL *This,
423 IN EFI_HANDLE ControllerHandle,
424 IN UINTN NumberOfChildren,
425 IN EFI_HANDLE *ChildHandleBuffer
426 )
427/*++
428
429Routine Description:
430
431 TODO: Add function description
432
433Arguments:
434
435 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.
436
437 ControllerHandle - A handle to the device to be stopped.
438
439 NumberOfChildren - The number of child device handles in ChildHandleBuffer.
440
441 ChildHandleBuffer - An array of child device handles to be freed.
442
443Returns:
444
445 EFI_SUCCESS - The device has been stopped.
446
447 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.
448
449--*/
450// TODO: EFI_UNSUPPORTED - add return value to function comment
451{
452 EFI_STATUS Status;
453 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;
454 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
455
456 //
457 // Get our context back
458 //
459 Status = gBS->OpenProtocol (
460 ControllerHandle,
461 &gEfiSimpleFileSystemProtocolGuid,
462 (VOID **) &SimpleFileSystem,
463 This->DriverBindingHandle,
464 ControllerHandle,
465 EFI_OPEN_PROTOCOL_GET_PROTOCOL
466 );
467 if (EFI_ERROR (Status)) {
468 return EFI_UNSUPPORTED;
469 }
470
471 Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem);
472
473 //
474 // Uninstall the Simple File System Protocol from ControllerHandle
475 //
476 Status = gBS->UninstallMultipleProtocolInterfaces (
477 ControllerHandle,
478 &gEfiSimpleFileSystemProtocolGuid,
479 &Private->SimpleFileSystem,
480 NULL
481 );
482 if (!EFI_ERROR (Status)) {
483 Status = gBS->CloseProtocol (
484 ControllerHandle,
485 &gEfiWinNtIoProtocolGuid,
486 This->DriverBindingHandle,
487 ControllerHandle
488 );
489 }
490
491 if (!EFI_ERROR (Status)) {
492 //
493 // Free our instance data
494 //
495 FreeUnicodeStringTable (Private->ControllerNameTable);
496
497 FreePool (Private);
498 }
499
500 return Status;
501}
502
503EFI_STATUS
504EFIAPI
505WinNtSimpleFileSystemOpenVolume (
506 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,
507 OUT EFI_FILE_PROTOCOL **Root
508 )
509/*++
510
511Routine Description:
512
513 Open the root directory on a volume.
514
515Arguments:
516
517 This - A pointer to the volume to open.
518
519 Root - A pointer to storage for the returned opened file handle of the root directory.
520
521Returns:
522
523 EFI_SUCCESS - The volume was opened.
524
525 EFI_UNSUPPORTED - The volume does not support the requested file system type.
526
527 EFI_NO_MEDIA - The device has no media.
528
529 EFI_DEVICE_ERROR - The device reported an error.
530
531 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
532
533 EFI_ACCESS_DENIED - The service denied access to the file.
534
535 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.
536
537 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
538
539--*/
540// TODO: EFI_INVALID_PARAMETER - add return value to function comment
541{
542 EFI_STATUS Status;
543 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;
544 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
545 EFI_TPL OldTpl;
546 CHAR16 *TempFileName;
547 UINTN Size;
548
549 if (This == NULL || Root == NULL) {
550 return EFI_INVALID_PARAMETER;
551 }
552
553 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
554
555 Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);
556
557 PrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));
558 if (PrivateFile == NULL) {
559 Status = EFI_OUT_OF_RESOURCES;
560 goto Done;
561 }
562
563 PrivateFile->FileName = AllocatePool (StrSize (Private->FilePath));
564 if (PrivateFile->FileName == NULL) {
565 Status = EFI_OUT_OF_RESOURCES;
566 goto Done;
567 }
568
569 PrivateFile->FilePath = AllocatePool (StrSize (Private->FilePath));
570 if (PrivateFile->FilePath == NULL) {
571 Status = EFI_OUT_OF_RESOURCES;
572 goto Done;
573 }
574
575 StrCpy (PrivateFile->FilePath, Private->FilePath);
576 StrCpy (PrivateFile->FileName, PrivateFile->FilePath);
577 PrivateFile->Signature = WIN_NT_EFI_FILE_PRIVATE_SIGNATURE;
578 PrivateFile->WinNtThunk = Private->WinNtThunk;
579 PrivateFile->SimpleFileSystem = This;
580 PrivateFile->IsRootDirectory = TRUE;
581 PrivateFile->IsDirectoryPath = TRUE;
582 PrivateFile->IsOpenedByRead = TRUE;
583 PrivateFile->EfiFile.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;
584 PrivateFile->EfiFile.Open = WinNtSimpleFileSystemOpen;
585 PrivateFile->EfiFile.Close = WinNtSimpleFileSystemClose;
586 PrivateFile->EfiFile.Delete = WinNtSimpleFileSystemDelete;
587 PrivateFile->EfiFile.Read = WinNtSimpleFileSystemRead;
588 PrivateFile->EfiFile.Write = WinNtSimpleFileSystemWrite;
589 PrivateFile->EfiFile.GetPosition = WinNtSimpleFileSystemGetPosition;
590 PrivateFile->EfiFile.SetPosition = WinNtSimpleFileSystemSetPosition;
591 PrivateFile->EfiFile.GetInfo = WinNtSimpleFileSystemGetInfo;
592 PrivateFile->EfiFile.SetInfo = WinNtSimpleFileSystemSetInfo;
593 PrivateFile->EfiFile.Flush = WinNtSimpleFileSystemFlush;
594 PrivateFile->IsValidFindBuf = FALSE;
595
596 //
597 // Set DirHandle
598 //
599 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (
600 PrivateFile->FilePath,
601 GENERIC_READ,
602 FILE_SHARE_READ | FILE_SHARE_WRITE,
603 NULL,
604 OPEN_EXISTING,
605 FILE_FLAG_BACKUP_SEMANTICS,
606 NULL
607 );
608
609 if (PrivateFile->DirHandle == INVALID_HANDLE_VALUE) {
610 Status = EFI_NOT_FOUND;
611 goto Done;
612 }
613
614 //
615 // Find the first file under it
616 //
617 Size = StrSize (PrivateFile->FilePath);
618 Size += StrSize (L"\\*");
619 Status = gBS->AllocatePool (
620 EfiBootServicesData,
621 Size,
622 (VOID **)&TempFileName
623 );
624 if (EFI_ERROR (Status)) {
625 goto Done;
626 }
627 StrCpy (TempFileName, PrivateFile->FilePath);
628 StrCat (TempFileName, L"\\*");
629
630 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &PrivateFile->FindBuf);
631
632 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
633 PrivateFile->IsValidFindBuf = FALSE;
634 } else {
635 PrivateFile->IsValidFindBuf = TRUE;
636 }
637 *Root = &PrivateFile->EfiFile;
638
639 Status = EFI_SUCCESS;
640
641Done:
642 if (EFI_ERROR (Status)) {
643 if (PrivateFile) {
644 if (PrivateFile->FileName) {
645 FreePool (PrivateFile->FileName);
646 }
647
648 if (PrivateFile->FilePath) {
649 FreePool (PrivateFile->FilePath);
650 }
651
652 FreePool (PrivateFile);
653 }
654 }
655
656 gBS->RestoreTPL (OldTpl);
657
658 return Status;
659}
660
661/**
662 Count the number of Leading Dot in FileNameToken.
663
664 @param FileNameToken A string representing a token in the path name.
665
666 @return UINTN The number of leading dot in the name.
667
668**/
669UINTN
670CountLeadingDots (
671 IN CONST CHAR16 * FileNameToken
672 )
673{
674 UINTN Num;
675
676 Num = 0;
677 while (*FileNameToken == L'.') {
678 Num++;
679 FileNameToken++;
680 }
681
682 return Num;
683}
684
685BOOLEAN
686IsFileNameTokenValid (
687 IN CONST CHAR16 * FileNameToken
688 )
689{
690 UINTN Num;
691 if (StrStr (FileNameToken, L"/") != NULL) {
692 //
693 // No L'/' in file name.
694 //
695 return FALSE;
696 } else {
697 //
698 // If Token has all dot, the number should not exceed 2
699 //
700 Num = CountLeadingDots (FileNameToken);
701
702 if (Num == StrLen (FileNameToken)) {
703 //
704 // If the FileNameToken only contains a number of L'.'.
705 //
706 if (Num > 2) {
707 return FALSE;
708 }
709 }
710 }
711
712 return TRUE;
713}
714
715/**
716 Return the first string token found in the indirect pointer a String named by FileName.
717
718 On input, FileName is a indirect pointer pointing to a String.
719 On output, FileName is a updated to point to the next character after the first
720 found L"\" or NULL if there is no L"\" found.
721
722 @param FileName A indirect pointer pointing to a FileName.
723
724 @return Token The first string token found before a L"\".
725
726**/
727CHAR16 *
728GetNextFileNameToken (
729 IN OUT CONST CHAR16 ** FileName
730 )
731{
732 CHAR16 *SlashPos;
733 CHAR16 *Token;
734 UINTN Offset;
735 ASSERT (**FileName != L'\\');
736 ASSERT (**FileName != L'\0');
737
738 SlashPos = StrStr (*FileName, L"\\");
739 if (SlashPos == NULL) {
740 Token = AllocateCopyPool (StrSize(*FileName), *FileName);
741 *FileName = NULL;
742 } else {
743 Offset = SlashPos - *FileName;
744 Token = AllocateZeroPool ((Offset + 1) * sizeof (CHAR16));
745 StrnCpy (Token, *FileName, Offset);
746 //
747 // Point *FileName to the next character after L'\'.
748 //
749 *FileName = *FileName + Offset + 1;
750 }
751
752 return Token;
753}
754
755/**
756 Check if a FileName contains only Valid Characters.
757
758 If FileName contains only a single L'\', return TRUE.
759 If FileName contains two adjacent L'\', return FALSE.
760 If FileName conatins L'/' , return FALSE.
761 If FielName contains more than two dots seperated with other FileName characters
762 by L'\', return FALSE. For example, L'.\...\filename.txt' is invalid path name. But L'..TwoDots\filename.txt' is valid path name.
763
764 @param FileName The File Name String to check.
765
766 @return TRUE FileName only contains valid characters.
767 @return FALSE FileName contains at least one invalid character.
768
769**/
770
771BOOLEAN
772IsFileNameValid (
773 IN CONST CHAR16 *FileName
774 )
775{
776 CHAR16 *Token;
777 BOOLEAN Valid;
778
779 //
780 // If FileName is just L'\', then it is a valid pathname.
781 //
782 if (StrCmp (FileName, L"\\") == 0) {
783 return TRUE;
784 }
785 //
786 // We don't support two or more adjacent L'\'.
787 //
788 if (StrStr (FileName, L"\\\\") != NULL) {
789 return FALSE;
790 }
791
792 //
793 // Is FileName has a leading L"\", skip to next character.
794 //
795 if (FileName [0] == L'\\') {
796 FileName++;
797 }
798
799 do {
800 Token = GetNextFileNameToken (&FileName);
801 Valid = IsFileNameTokenValid (Token);
802 FreePool (Token);
803
804 if (!Valid)
805 return FALSE;
806 } while (FileName != NULL);
807
808 return TRUE;
809}
810
811EFI_STATUS
812EFIAPI
813WinNtSimpleFileSystemOpen (
814 IN EFI_FILE_PROTOCOL *This,
815 OUT EFI_FILE_PROTOCOL **NewHandle,
816 IN CHAR16 *FileName,
817 IN UINT64 OpenMode,
818 IN UINT64 Attributes
819 )
820/*++
821
822Routine Description:
823
824 Open a file relative to the source file location.
825
826Arguments:
827
828 This - A pointer to the source file location.
829
830 NewHandle - Pointer to storage for the new file handle.
831
832 FileName - Pointer to the file name to be opened.
833
834 OpenMode - File open mode information.
835
836 Attributes - File creation attributes.
837
838Returns:
839
840 EFI_SUCCESS - The file was opened.
841
842 EFI_NOT_FOUND - The file could not be found in the volume.
843
844 EFI_NO_MEDIA - The device has no media.
845
846 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.
847
848 EFI_DEVICE_ERROR - The device reported an error.
849
850 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
851
852 EFI_WRITE_PROTECTED - The volume or file is write protected.
853
854 EFI_ACCESS_DENIED - The service denied access to the file.
855
856 EFI_OUT_OF_RESOURCES - Not enough resources were available to open the file.
857
858 EFI_VOLUME_FULL - There is not enough space left to create the new file.
859
860--*/
861// TODO: EFI_INVALID_PARAMETER - add return value to function comment
862// TODO: EFI_INVALID_PARAMETER - add return value to function comment
863// TODO: EFI_INVALID_PARAMETER - add return value to function comment
864// TODO: EFI_INVALID_PARAMETER - add return value to function comment
865{
866 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
867 WIN_NT_EFI_FILE_PRIVATE *NewPrivateFile;
868 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
869 EFI_STATUS Status;
870 CHAR16 *RealFileName;
871 CHAR16 *TempFileName;
872 CHAR16 *ParseFileName;
873 CHAR16 *GuardPointer;
874 CHAR16 TempChar;
875 DWORD LastError;
876 UINTN Count;
877 BOOLEAN LoopFinish;
878 UINTN InfoSize;
879 EFI_FILE_INFO *Info;
880 UINTN Size;
881
882 //
883 // Check for obvious invalid parameters.
884 //
885 if (This == NULL || NewHandle == NULL || FileName == NULL) {
886 return EFI_INVALID_PARAMETER;
887 }
888
889 switch (OpenMode) {
890 case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
891 if (Attributes &~EFI_FILE_VALID_ATTR) {
892 return EFI_INVALID_PARAMETER;
893 }
894
895 if (Attributes & EFI_FILE_READ_ONLY) {
896 return EFI_INVALID_PARAMETER;
897 }
898
899 //
900 // fall through
901 //
902 case EFI_FILE_MODE_READ:
903 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:
904 break;
905
906 default:
907 return EFI_INVALID_PARAMETER;
908 }
909
910 //
911 // Init local variables
912 //
913 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
914 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
915 NewPrivateFile = NULL;
916
917 //
918 // Allocate buffer for FileName as the passed in FileName may be read only
919 //
920 TempFileName = AllocatePool (StrSize (FileName));
921 if (TempFileName == NULL) {
922 return EFI_OUT_OF_RESOURCES;
923 }
924 StrCpy (TempFileName, FileName);
925 FileName = TempFileName;
926
927 if (FileName[StrLen (FileName) - 1] == L'\\') {
928 FileName[StrLen (FileName) - 1] = 0;
929 }
930
931 //
932 // If file name does not equal to "." or ".." and not trailed with "\..",
933 // then we trim the leading/trailing blanks and trailing dots
934 //
935 if (StrCmp (FileName, L".") != 0 && StrCmp (FileName, L"..") != 0 &&
936 ((StrLen (FileName) >= 3) ? (StrCmp (&FileName[StrLen (FileName) - 3], L"\\..") != 0) : TRUE)) {
937 //
938 // Trim leading blanks
939 //
940 Count = 0;
941 for (TempFileName = FileName;
942 *TempFileName != 0 && *TempFileName == L' ';
943 TempFileName++) {
944 Count++;
945 }
946 CutPrefix (FileName, Count);
947 //
948 // Trim trailing blanks
949 //
950 for (TempFileName = FileName + StrLen (FileName) - 1;
951 TempFileName >= FileName && (*TempFileName == L' ');
952 TempFileName--) {
953 ;
954 }
955 *(TempFileName + 1) = 0;
956 }
957
958 //
959 // Attempt to open the file
960 //
961 NewPrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));
962 if (NewPrivateFile == NULL) {
963 Status = EFI_OUT_OF_RESOURCES;
964 goto Done;
965 }
966
967 CopyMem (NewPrivateFile, PrivateFile, sizeof (WIN_NT_EFI_FILE_PRIVATE));
968
969 NewPrivateFile->FilePath = AllocatePool (StrSize (PrivateFile->FileName));
970 if (NewPrivateFile->FilePath == NULL) {
971 Status = EFI_OUT_OF_RESOURCES;
972 goto Done;
973 }
974
975 if (PrivateFile->IsDirectoryPath) {
976 StrCpy (NewPrivateFile->FilePath, PrivateFile->FileName);
977 } else {
978 StrCpy (NewPrivateFile->FilePath, PrivateFile->FilePath);
979 }
980
981 Size = StrSize (NewPrivateFile->FilePath);
982 Size += StrSize (L"\\");
983 Size += StrSize (FileName);
984 NewPrivateFile->FileName = AllocatePool (Size);
985 if (NewPrivateFile->FileName == NULL) {
986 Status = EFI_OUT_OF_RESOURCES;
987 goto Done;
988 }
989
990 if (*FileName == L'\\') {
991 StrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);
992 StrCat (NewPrivateFile->FileName, L"\\");
993 StrCat (NewPrivateFile->FileName, FileName + 1);
994 } else {
995 StrCpy (NewPrivateFile->FileName, NewPrivateFile->FilePath);
996 if (StrCmp (FileName, L"") != 0) {
997 //
998 // In case the filename becomes empty, especially after trimming dots and blanks
999 //
1000 StrCat (NewPrivateFile->FileName, L"\\");
1001 StrCat (NewPrivateFile->FileName, FileName);
1002 }
1003 }
1004
1005 if (!IsFileNameValid (NewPrivateFile->FileName)) {
1006 Status = EFI_NOT_FOUND;
1007 goto Done;
1008 }
1009
1010 //
1011 // Get rid of . and .., except leading . or ..
1012 //
1013
1014 //
1015 // GuardPointer protect simplefilesystem root path not be destroyed
1016 //
1017 GuardPointer = NewPrivateFile->FileName + StrLen (PrivateRoot->FilePath);
1018
1019 LoopFinish = FALSE;
1020
1021 while (!LoopFinish) {
1022
1023 LoopFinish = TRUE;
1024
1025 for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {
1026 if (*ParseFileName == L'.' &&
1027 (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == L'\\') &&
1028 *(ParseFileName - 1) == L'\\'
1029 ) {
1030
1031 //
1032 // cut \.
1033 //
1034 CutPrefix (ParseFileName - 1, 2);
1035 LoopFinish = FALSE;
1036 break;
1037 }
1038
1039 if (*ParseFileName == L'.' &&
1040 *(ParseFileName + 1) == L'.' &&
1041 (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == L'\\') &&
1042 *(ParseFileName - 1) == L'\\'
1043 ) {
1044
1045 ParseFileName--;
1046 Count = 3;
1047
1048 while (ParseFileName != GuardPointer) {
1049 ParseFileName--;
1050 Count++;
1051 if (*ParseFileName == L'\\') {
1052 break;
1053 }
1054 }
1055
1056 //
1057 // cut \.. and its left directory
1058 //
1059 CutPrefix (ParseFileName, Count);
1060 LoopFinish = FALSE;
1061 break;
1062 }
1063 }
1064 }
1065
1066 RealFileName = NewPrivateFile->FileName;
1067 while (EfiStrChr (RealFileName, L'\\') != NULL) {
1068 RealFileName = EfiStrChr (RealFileName, L'\\') + 1;
1069 }
1070
1071 TempChar = 0;
1072 if (RealFileName != NewPrivateFile->FileName) {
1073 TempChar = *(RealFileName - 1);
1074 *(RealFileName - 1) = 0;
1075 }
1076
1077 FreePool (NewPrivateFile->FilePath);
1078 NewPrivateFile->FilePath = NULL;
1079 NewPrivateFile->FilePath = AllocatePool (StrSize (NewPrivateFile->FileName));
1080 if (NewPrivateFile->FilePath == NULL) {
1081 Status = EFI_OUT_OF_RESOURCES;
1082 goto Done;
1083 }
1084
1085 StrCpy (NewPrivateFile->FilePath, NewPrivateFile->FileName);
1086 if (TempChar != 0) {
1087 *(RealFileName - 1) = TempChar;
1088 }
1089
1090 NewPrivateFile->IsRootDirectory = FALSE;
1091
1092 //
1093 // Test whether file or directory
1094 //
1095 if (OpenMode & EFI_FILE_MODE_CREATE) {
1096 if (Attributes & EFI_FILE_DIRECTORY) {
1097 NewPrivateFile->IsDirectoryPath = TRUE;
1098 } else {
1099 NewPrivateFile->IsDirectoryPath = FALSE;
1100 }
1101 } else {
1102 NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;
1103 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (
1104 NewPrivateFile->FileName,
1105 GENERIC_READ,
1106 FILE_SHARE_READ | FILE_SHARE_WRITE,
1107 NULL,
1108 OPEN_EXISTING,
1109 0,
1110 NULL
1111 );
1112
1113 if (NewPrivateFile->LHandle != INVALID_HANDLE_VALUE) {
1114 NewPrivateFile->IsDirectoryPath = FALSE;
1115 NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->LHandle);
1116 } else {
1117 NewPrivateFile->IsDirectoryPath = TRUE;
1118 }
1119
1120 NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;
1121 }
1122
1123 if (OpenMode & EFI_FILE_MODE_WRITE) {
1124 NewPrivateFile->IsOpenedByRead = FALSE;
1125 } else {
1126 NewPrivateFile->IsOpenedByRead = TRUE;
1127 }
1128
1129 Status = EFI_SUCCESS;
1130
1131 //
1132 // deal with directory
1133 //
1134 if (NewPrivateFile->IsDirectoryPath) {
1135
1136 Size = StrSize (NewPrivateFile->FileName);
1137 Size += StrSize (L"\\*");
1138 TempFileName = AllocatePool (Size);
1139 if (TempFileName == NULL) {
1140 Status = EFI_OUT_OF_RESOURCES;
1141 goto Done;
1142 }
1143
1144 StrCpy (TempFileName, NewPrivateFile->FileName);
1145
1146 if ((OpenMode & EFI_FILE_MODE_CREATE)) {
1147 //
1148 // Create a directory
1149 //
1150 if (!NewPrivateFile->WinNtThunk->CreateDirectory (TempFileName, NULL)) {
1151
1152 LastError = PrivateFile->WinNtThunk->GetLastError ();
1153 if (LastError != ERROR_ALREADY_EXISTS) {
1154 FreePool (TempFileName);
1155 Status = EFI_ACCESS_DENIED;
1156 goto Done;
1157 }
1158 }
1159 }
1160
1161 NewPrivateFile->DirHandle = NewPrivateFile->WinNtThunk->CreateFile (
1162 TempFileName,
1163 NewPrivateFile->IsOpenedByRead ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),
1164 FILE_SHARE_READ | FILE_SHARE_WRITE,
1165 NULL,
1166 OPEN_EXISTING,
1167 FILE_FLAG_BACKUP_SEMANTICS,
1168 NULL
1169 );
1170
1171 if (NewPrivateFile->DirHandle == INVALID_HANDLE_VALUE) {
1172
1173 NewPrivateFile->DirHandle = NewPrivateFile->WinNtThunk->CreateFile (
1174 TempFileName,
1175 GENERIC_READ,
1176 FILE_SHARE_READ | FILE_SHARE_WRITE,
1177 NULL,
1178 OPEN_EXISTING,
1179 FILE_FLAG_BACKUP_SEMANTICS,
1180 NULL
1181 );
1182
1183 if (NewPrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
1184 NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->DirHandle);
1185 NewPrivateFile->DirHandle = INVALID_HANDLE_VALUE;
1186 Status = EFI_ACCESS_DENIED;
1187 } else {
1188 Status = EFI_NOT_FOUND;
1189 }
1190
1191 goto Done;
1192 }
1193
1194 //
1195 // Find the first file under it
1196 //
1197 StrCat (TempFileName, L"\\*");
1198 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->FindFirstFile (TempFileName, &NewPrivateFile->FindBuf);
1199
1200 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
1201 NewPrivateFile->IsValidFindBuf = FALSE;
1202 } else {
1203 NewPrivateFile->IsValidFindBuf = TRUE;
1204 }
1205 } else {
1206 //
1207 // deal with file
1208 //
1209 if (!NewPrivateFile->IsOpenedByRead) {
1210 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (
1211 NewPrivateFile->FileName,
1212 GENERIC_READ | GENERIC_WRITE,
1213 FILE_SHARE_READ | FILE_SHARE_WRITE,
1214 NULL,
1215 (OpenMode & EFI_FILE_MODE_CREATE) ? OPEN_ALWAYS : OPEN_EXISTING,
1216 0,
1217 NULL
1218 );
1219
1220 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
1221 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (
1222 NewPrivateFile->FileName,
1223 GENERIC_READ,
1224 FILE_SHARE_READ | FILE_SHARE_WRITE,
1225 NULL,
1226 OPEN_EXISTING,
1227 0,
1228 NULL
1229 );
1230
1231 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
1232 Status = EFI_NOT_FOUND;
1233 } else {
1234 Status = EFI_ACCESS_DENIED;
1235 NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->LHandle);
1236 NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;
1237 }
1238 }
1239 } else {
1240 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (
1241 NewPrivateFile->FileName,
1242 GENERIC_READ,
1243 FILE_SHARE_READ | FILE_SHARE_WRITE,
1244 NULL,
1245 OPEN_EXISTING,
1246 0,
1247 NULL
1248 );
1249
1250 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {
1251 Status = EFI_NOT_FOUND;
1252 }
1253 }
1254 }
1255
1256 if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {
1257 //
1258 // Set the attribute
1259 //
1260 InfoSize = 0;
1261 Info = NULL;
1262
1263 Status = WinNtSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
1264
1265 if (Status != EFI_BUFFER_TOO_SMALL) {
1266 Status = EFI_DEVICE_ERROR;
1267 goto Done;
1268 }
1269
1270 Info = AllocatePool (InfoSize);
1271 if (Info == NULL) {
1272 Status = EFI_OUT_OF_RESOURCES;
1273 goto Done;
1274 }
1275
1276 Status = WinNtSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);
1277
1278 if (EFI_ERROR (Status)) {
1279 goto Done;
1280 }
1281
1282 Info->Attribute = Attributes;
1283
1284 WinNtSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);
1285 }
1286
1287Done:
1288 FreePool (FileName);
1289
1290 if (EFI_ERROR (Status)) {
1291 if (NewPrivateFile) {
1292 if (NewPrivateFile->FileName) {
1293 FreePool (NewPrivateFile->FileName);
1294 }
1295
1296 if (NewPrivateFile->FilePath) {
1297 FreePool (NewPrivateFile->FilePath);
1298 }
1299
1300 FreePool (NewPrivateFile);
1301 }
1302 } else {
1303 *NewHandle = &NewPrivateFile->EfiFile;
1304 if (StrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {
1305 NewPrivateFile->IsRootDirectory = TRUE;
1306 }
1307 }
1308
1309 return Status;
1310}
1311
1312EFI_STATUS
1313EFIAPI
1314WinNtSimpleFileSystemClose (
1315 IN EFI_FILE_PROTOCOL *This
1316 )
1317/*++
1318
1319Routine Description:
1320
1321 Close the specified file handle.
1322
1323Arguments:
1324
1325 This - Pointer to a returned opened file handle.
1326
1327Returns:
1328
1329 EFI_SUCCESS - The file handle has been closed.
1330
1331--*/
1332// TODO: EFI_INVALID_PARAMETER - add return value to function comment
1333{
1334 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
1335 EFI_TPL OldTpl;
1336
1337 if (This == NULL) {
1338 return EFI_INVALID_PARAMETER;
1339 }
1340
1341 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1342
1343 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1344
1345 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
1346 if (PrivateFile->IsDirectoryPath) {
1347 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);
1348 } else {
1349 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);
1350 }
1351
1352 PrivateFile->LHandle = INVALID_HANDLE_VALUE;
1353 }
1354
1355 if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
1356 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);
1357 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
1358 }
1359
1360 if (PrivateFile->FileName) {
1361 FreePool (PrivateFile->FileName);
1362 }
1363
1364 FreePool (PrivateFile);
1365
1366 gBS->RestoreTPL (OldTpl);
1367
1368 return EFI_SUCCESS;
1369}
1370
1371EFI_STATUS
1372EFIAPI
1373WinNtSimpleFileSystemDelete (
1374 IN EFI_FILE_PROTOCOL *This
1375 )
1376/*++
1377
1378Routine Description:
1379
1380 Close and delete a file.
1381
1382Arguments:
1383
1384 This - Pointer to a returned opened file handle.
1385
1386Returns:
1387
1388 EFI_SUCCESS - The file handle was closed and deleted.
1389
1390 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.
1391
1392--*/
1393// TODO: EFI_INVALID_PARAMETER - add return value to function comment
1394{
1395 EFI_STATUS Status;
1396 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
1397 EFI_TPL OldTpl;
1398
1399 if (This == NULL) {
1400 return EFI_INVALID_PARAMETER;
1401 }
1402
1403 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1404
1405 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1406
1407 Status = EFI_WARN_DELETE_FAILURE;
1408
1409 if (PrivateFile->IsDirectoryPath) {
1410 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
1411 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);
1412 }
1413
1414 if (PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
1415 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);
1416 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
1417 }
1418
1419 if (PrivateFile->WinNtThunk->RemoveDirectory (PrivateFile->FileName)) {
1420 Status = EFI_SUCCESS;
1421 }
1422 } else {
1423 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);
1424 PrivateFile->LHandle = INVALID_HANDLE_VALUE;
1425
1426 if (!PrivateFile->IsOpenedByRead) {
1427 if (PrivateFile->WinNtThunk->DeleteFile (PrivateFile->FileName)) {
1428 Status = EFI_SUCCESS;
1429 }
1430 }
1431 }
1432
1433 FreePool (PrivateFile->FileName);
1434 FreePool (PrivateFile);
1435
1436 gBS->RestoreTPL (OldTpl);
1437
1438 return Status;
1439}
1440
1441VOID
1442WinNtSystemTimeToEfiTime (
1443 IN SYSTEMTIME *SystemTime,
1444 IN TIME_ZONE_INFORMATION *TimeZone,
1445 OUT EFI_TIME *Time
1446 )
1447/*++
1448
1449Routine Description:
1450
1451 TODO: Add function description
1452
1453Arguments:
1454
1455 SystemTime - TODO: add argument description
1456 TimeZone - TODO: add argument description
1457 Time - TODO: add argument description
1458
1459Returns:
1460
1461 TODO: add return values
1462
1463--*/
1464{
1465 Time->Year = (UINT16) SystemTime->wYear;
1466 Time->Month = (UINT8) SystemTime->wMonth;
1467 Time->Day = (UINT8) SystemTime->wDay;
1468 Time->Hour = (UINT8) SystemTime->wHour;
1469 Time->Minute = (UINT8) SystemTime->wMinute;
1470 Time->Second = (UINT8) SystemTime->wSecond;
1471 Time->Nanosecond = (UINT32) SystemTime->wMilliseconds * 1000000;
1472 Time->TimeZone = (INT16) TimeZone->Bias;
1473
1474 if (TimeZone->StandardDate.wMonth) {
1475 Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;
1476 }
1477}
1478
1479EFI_STATUS
1480EFIAPI
1481WinNtSimpleFileSystemRead (
1482 IN EFI_FILE_PROTOCOL *This,
1483 IN OUT UINTN *BufferSize,
1484 OUT VOID *Buffer
1485 )
1486/*++
1487
1488Routine Description:
1489
1490 Read data from a file.
1491
1492Arguments:
1493
1494 This - Pointer to a returned open file handle.
1495
1496 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.
1497
1498 Buffer - Pointer to the first byte of the read Buffer.
1499
1500Returns:
1501
1502 EFI_SUCCESS - The data was read.
1503
1504 EFI_NO_MEDIA - The device has no media.
1505
1506 EFI_DEVICE_ERROR - The device reported an error.
1507
1508 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.
1509
1510 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.
1511 *BufferSize has been updated with the size needed to complete the request.
1512
1513--*/
1514// TODO: EFI_INVALID_PARAMETER - add return value to function comment
1515{
1516 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
1517 EFI_STATUS Status;
1518 UINTN Size;
1519 UINTN NameSize;
1520 UINTN ResultSize;
1521 UINTN Index;
1522 SYSTEMTIME SystemTime;
1523 EFI_FILE_INFO *Info;
1524 WCHAR *pw;
1525 TIME_ZONE_INFORMATION TimeZone;
1526 EFI_FILE_INFO *FileInfo;
1527 UINT64 Pos;
1528 UINT64 FileSize;
1529 UINTN FileInfoSize;
1530 EFI_TPL OldTpl;
1531
1532 if (This == NULL || BufferSize == NULL) {
1533 return EFI_INVALID_PARAMETER;
1534 }
1535
1536 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1537
1538 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1539
1540 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
1541 Status = EFI_DEVICE_ERROR;
1542 goto Done;
1543 }
1544
1545 if (!PrivateFile->IsDirectoryPath) {
1546
1547 if (This->GetPosition (This, &Pos) != EFI_SUCCESS) {
1548 Status = EFI_DEVICE_ERROR;
1549 goto Done;
1550 }
1551
1552 FileInfoSize = SIZE_OF_EFI_FILE_SYSTEM_INFO;
1553 FileInfo = AllocatePool (FileInfoSize);
1554
1555 Status = This->GetInfo (
1556 This,
1557 &gEfiFileInfoGuid,
1558 &FileInfoSize,
1559 FileInfo
1560 );
1561
1562 if (Status == EFI_BUFFER_TOO_SMALL) {
1563 FreePool (FileInfo);
1564 FileInfo = AllocatePool (FileInfoSize);
1565 Status = This->GetInfo (
1566 This,
1567 &gEfiFileInfoGuid,
1568 &FileInfoSize,
1569 FileInfo
1570 );
1571 }
1572
1573 if (EFI_ERROR (Status)) {
1574 Status = EFI_DEVICE_ERROR;
1575 goto Done;
1576 }
1577
1578 FileSize = FileInfo->FileSize;
1579
1580 FreePool (FileInfo);
1581
1582 if (Pos >= FileSize) {
1583 *BufferSize = 0;
1584 if (Pos == FileSize) {
1585 Status = EFI_SUCCESS;
1586 goto Done;
1587 } else {
1588 Status = EFI_DEVICE_ERROR;
1589 goto Done;
1590 }
1591 }
1592
1593 Status = PrivateFile->WinNtThunk->ReadFile (
1594 PrivateFile->LHandle,
1595 Buffer,
1596 (DWORD)*BufferSize,
1597 (LPDWORD)BufferSize,
1598 NULL
1599 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
1600 goto Done;
1601 }
1602
1603 //
1604 // Read on a directory. Perform a find next
1605 //
1606 if (!PrivateFile->IsValidFindBuf) {
1607 *BufferSize = 0;
1608 Status = EFI_SUCCESS;
1609 goto Done;
1610 }
1611
1612 Size = SIZE_OF_EFI_FILE_INFO;
1613
1614 NameSize = StrSize (PrivateFile->FindBuf.cFileName);
1615
1616 ResultSize = Size + NameSize;
1617
1618 Status = EFI_BUFFER_TOO_SMALL;
1619
1620 if (*BufferSize >= ResultSize) {
1621 Status = EFI_SUCCESS;
1622
1623 Info = Buffer;
1624 ZeroMem (Info, ResultSize);
1625
1626 Info->Size = ResultSize;
1627
1628 PrivateFile->WinNtThunk->GetTimeZoneInformation (&TimeZone);
1629
1630 PrivateFile->WinNtThunk->FileTimeToLocalFileTime (
1631 &PrivateFile->FindBuf.ftCreationTime,
1632 &PrivateFile->FindBuf.ftCreationTime
1633 );
1634
1635 PrivateFile->WinNtThunk->FileTimeToSystemTime (&PrivateFile->FindBuf.ftCreationTime, &SystemTime);
1636
1637 WinNtSystemTimeToEfiTime (&SystemTime, &TimeZone, &Info->CreateTime);
1638
1639 PrivateFile->WinNtThunk->FileTimeToLocalFileTime (
1640 &PrivateFile->FindBuf.ftLastWriteTime,
1641 &PrivateFile->FindBuf.ftLastWriteTime
1642 );
1643
1644 PrivateFile->WinNtThunk->FileTimeToSystemTime (&PrivateFile->FindBuf.ftLastWriteTime, &SystemTime);
1645
1646 WinNtSystemTimeToEfiTime (&SystemTime, &TimeZone, &Info->ModificationTime);
1647
1648 Info->FileSize = PrivateFile->FindBuf.nFileSizeLow;
1649
1650 Info->PhysicalSize = PrivateFile->FindBuf.nFileSizeLow;
1651
1652 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
1653 Info->Attribute |= EFI_FILE_ARCHIVE;
1654 }
1655
1656 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
1657 Info->Attribute |= EFI_FILE_HIDDEN;
1658 }
1659
1660 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
1661 Info->Attribute |= EFI_FILE_SYSTEM;
1662 }
1663
1664 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
1665 Info->Attribute |= EFI_FILE_READ_ONLY;
1666 }
1667
1668 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
1669 Info->Attribute |= EFI_FILE_DIRECTORY;
1670 }
1671
1672 NameSize = NameSize / sizeof (WCHAR);
1673
1674 pw = (WCHAR *) (((CHAR8 *) Buffer) + Size);
1675
1676 for (Index = 0; Index < NameSize; Index++) {
1677 pw[Index] = PrivateFile->FindBuf.cFileName[Index];
1678 }
1679
1680 if (PrivateFile->WinNtThunk->FindNextFile (PrivateFile->LHandle, &PrivateFile->FindBuf)) {
1681 PrivateFile->IsValidFindBuf = TRUE;
1682 } else {
1683 PrivateFile->IsValidFindBuf = FALSE;
1684 }
1685 }
1686
1687 *BufferSize = ResultSize;
1688
1689Done:
1690 gBS->RestoreTPL (OldTpl);
1691 return Status;
1692}
1693
1694EFI_STATUS
1695EFIAPI
1696WinNtSimpleFileSystemWrite (
1697 IN EFI_FILE_PROTOCOL *This,
1698 IN OUT UINTN *BufferSize,
1699 IN VOID *Buffer
1700 )
1701/*++
1702
1703Routine Description:
1704
1705 Write data to a file.
1706
1707Arguments:
1708
1709 This - Pointer to an opened file handle.
1710
1711 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes
1712 of data written to the file.
1713
1714 Buffer - Pointer to the first by of data in the buffer to write to the file.
1715
1716Returns:
1717
1718 EFI_SUCCESS - The data was written to the file.
1719
1720 EFI_UNSUPPORTED - Writes to an open directory are not supported.
1721
1722 EFI_NO_MEDIA - The device has no media.
1723
1724 EFI_DEVICE_ERROR - The device reported an error.
1725
1726 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1727
1728 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
1729
1730 EFI_ACCESS_DENIED - The file was opened read-only.
1731
1732 EFI_VOLUME_FULL - The volume is full.
1733
1734--*/
1735// TODO: EFI_INVALID_PARAMETER - add return value to function comment
1736{
1737 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
1738 EFI_STATUS Status;
1739 EFI_TPL OldTpl;
1740
1741 if (This == NULL || BufferSize == NULL || Buffer == NULL) {
1742 return EFI_INVALID_PARAMETER;
1743 }
1744
1745 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1746
1747 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1748
1749 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
1750 Status = EFI_DEVICE_ERROR;
1751 goto Done;
1752 }
1753
1754 if (PrivateFile->IsDirectoryPath) {
1755 Status = EFI_UNSUPPORTED;
1756 goto Done;
1757 }
1758
1759 if (PrivateFile->IsOpenedByRead) {
1760 Status = EFI_ACCESS_DENIED;
1761 goto Done;
1762 }
1763
1764 Status = PrivateFile->WinNtThunk->WriteFile (
1765 PrivateFile->LHandle,
1766 Buffer,
1767 (DWORD)*BufferSize,
1768 (LPDWORD)BufferSize,
1769 NULL
1770 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
1771
1772Done:
1773 gBS->RestoreTPL (OldTpl);
1774 return Status;
1775
1776 //
1777 // bugbug: need to access windows error reporting
1778 //
1779}
1780
1781EFI_STATUS
1782EFIAPI
1783WinNtSimpleFileSystemSetPosition (
1784 IN EFI_FILE_PROTOCOL *This,
1785 IN UINT64 Position
1786 )
1787/*++
1788
1789Routine Description:
1790
1791 Set a file's current position.
1792
1793Arguments:
1794
1795 This - Pointer to an opened file handle.
1796
1797 Position - The byte position from the start of the file to set.
1798
1799Returns:
1800
1801 EFI_SUCCESS - The file position has been changed.
1802
1803 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.
1804
1805--*/
1806// TODO: EFI_INVALID_PARAMETER - add return value to function comment
1807{
1808 EFI_STATUS Status;
1809 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
1810 UINT32 PosLow;
1811 UINT32 PosHigh;
1812 CHAR16 *FileName;
1813 EFI_TPL OldTpl;
1814 UINTN Size;
1815
1816 if (This == NULL) {
1817 return EFI_INVALID_PARAMETER;
1818 }
1819
1820 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1821
1822 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1823
1824 if (PrivateFile->IsDirectoryPath) {
1825 if (Position != 0) {
1826 Status = EFI_UNSUPPORTED;
1827 goto Done;
1828 }
1829
1830 Size = StrSize (PrivateFile->FileName);
1831 Size += StrSize (L"\\*");
1832 FileName = AllocatePool (Size);
1833 if (FileName == NULL) {
1834 Status = EFI_OUT_OF_RESOURCES;
1835 goto Done;
1836 }
1837
1838 StrCpy (FileName, PrivateFile->FileName);
1839 StrCat (FileName, L"\\*");
1840
1841 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
1842 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);
1843 }
1844
1845 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (FileName, &PrivateFile->FindBuf);
1846
1847 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
1848 PrivateFile->IsValidFindBuf = FALSE;
1849 } else {
1850 PrivateFile->IsValidFindBuf = TRUE;
1851 }
1852
1853 FreePool (FileName);
1854
1855 Status = (PrivateFile->LHandle == INVALID_HANDLE_VALUE) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
1856 } else {
1857 if (Position == (UINT64) -1) {
1858 PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) 0, NULL, FILE_END);
1859 } else {
1860 PosHigh = (UINT32) RShiftU64 (Position, 32);
1861
1862 PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) Position, (PLONG)&PosHigh, FILE_BEGIN);
1863 }
1864
1865 Status = (PosLow == 0xFFFFFFFF) ? EFI_DEVICE_ERROR : EFI_SUCCESS;
1866 }
1867
1868Done:
1869 gBS->RestoreTPL (OldTpl);
1870 return Status;
1871}
1872
1873EFI_STATUS
1874EFIAPI
1875WinNtSimpleFileSystemGetPosition (
1876 IN EFI_FILE_PROTOCOL *This,
1877 OUT UINT64 *Position
1878 )
1879/*++
1880
1881Routine Description:
1882
1883 Get a file's current position.
1884
1885Arguments:
1886
1887 This - Pointer to an opened file handle.
1888
1889 Position - Pointer to storage for the current position.
1890
1891Returns:
1892
1893 EFI_SUCCESS - The file position has been reported.
1894
1895 EFI_UNSUPPORTED - Not valid for directories.
1896
1897--*/
1898// TODO: EFI_INVALID_PARAMETER - add return value to function comment
1899{
1900 EFI_STATUS Status;
1901 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
1902 INT32 PositionHigh;
1903 UINT64 PosHigh64;
1904 EFI_TPL OldTpl;
1905
1906 if (This == NULL || Position == NULL) {
1907 return EFI_INVALID_PARAMETER;
1908 }
1909
1910 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
1911 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1912
1913 PositionHigh = 0;
1914 PosHigh64 = 0;
1915
1916 if (PrivateFile->IsDirectoryPath) {
1917
1918 Status = EFI_UNSUPPORTED;
1919 goto Done;
1920
1921 } else {
1922
1923 PositionHigh = 0;
1924 *Position = PrivateFile->WinNtThunk->SetFilePointer (
1925 PrivateFile->LHandle,
1926 0,
1927 (PLONG)&PositionHigh,
1928 FILE_CURRENT
1929 );
1930
1931 Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS;
1932 if (EFI_ERROR (Status)) {
1933 goto Done;
1934 }
1935
1936 PosHigh64 = PositionHigh;
1937 *Position += LShiftU64 (PosHigh64, 32);
1938 }
1939
1940Done:
1941 gBS->RestoreTPL (OldTpl);
1942 return Status;
1943}
1944
1945EFI_STATUS
1946WinNtSimpleFileSystemFileInfo (
1947 IN WIN_NT_EFI_FILE_PRIVATE *PrivateFile,
1948 IN OUT UINTN *BufferSize,
1949 OUT VOID *Buffer
1950 )
1951/*++
1952
1953Routine Description:
1954
1955 TODO: Add function description
1956
1957Arguments:
1958
1959 PrivateFile - TODO: add argument description
1960 BufferSize - TODO: add argument description
1961 Buffer - TODO: add argument description
1962
1963Returns:
1964
1965 TODO: add return values
1966
1967--*/
1968{
1969 EFI_STATUS Status;
1970 UINTN Size;
1971 UINTN NameSize;
1972 UINTN ResultSize;
1973 EFI_FILE_INFO *Info;
1974 BY_HANDLE_FILE_INFORMATION FileInfo;
1975 SYSTEMTIME SystemTime;
1976 CHAR16 *RealFileName;
1977 CHAR16 *TempPointer;
1978
1979 Size = SIZE_OF_EFI_FILE_INFO;
1980 NameSize = StrSize (PrivateFile->FileName);
1981 ResultSize = Size + NameSize;
1982
1983 Status = EFI_BUFFER_TOO_SMALL;
1984 if (*BufferSize >= ResultSize) {
1985 Status = EFI_SUCCESS;
1986
1987 Info = Buffer;
1988 ZeroMem (Info, ResultSize);
1989
1990 Info->Size = ResultSize;
1991 PrivateFile->WinNtThunk->GetFileInformationByHandle (
1992 PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,
1993 &FileInfo
1994 );
1995 Info->FileSize = FileInfo.nFileSizeLow;
1996 Info->PhysicalSize = Info->FileSize;
1997
1998 PrivateFile->WinNtThunk->FileTimeToLocalFileTime(&FileInfo.ftCreationTime, &FileInfo.ftCreationTime);
1999 PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftCreationTime, &SystemTime);
2000 Info->CreateTime.Year = SystemTime.wYear;
2001 Info->CreateTime.Month = (UINT8) SystemTime.wMonth;
2002 Info->CreateTime.Day = (UINT8) SystemTime.wDay;
2003 Info->CreateTime.Hour = (UINT8) SystemTime.wHour;
2004 Info->CreateTime.Minute = (UINT8) SystemTime.wMinute;
2005 Info->CreateTime.Second = (UINT8) SystemTime.wSecond;
2006
2007 PrivateFile->WinNtThunk->FileTimeToLocalFileTime(&FileInfo.ftLastAccessTime, &FileInfo.ftLastAccessTime);
2008 PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftLastAccessTime, &SystemTime);
2009 Info->LastAccessTime.Year = SystemTime.wYear;
2010 Info->LastAccessTime.Month = (UINT8) SystemTime.wMonth;
2011 Info->LastAccessTime.Day = (UINT8) SystemTime.wDay;
2012 Info->LastAccessTime.Hour = (UINT8) SystemTime.wHour;
2013 Info->LastAccessTime.Minute = (UINT8) SystemTime.wMinute;
2014 Info->LastAccessTime.Second = (UINT8) SystemTime.wSecond;
2015
2016 PrivateFile->WinNtThunk->FileTimeToLocalFileTime(&FileInfo.ftLastWriteTime, &FileInfo.ftLastWriteTime);
2017 PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftLastWriteTime, &SystemTime);
2018 Info->ModificationTime.Year = SystemTime.wYear;
2019 Info->ModificationTime.Month = (UINT8) SystemTime.wMonth;
2020 Info->ModificationTime.Day = (UINT8) SystemTime.wDay;
2021 Info->ModificationTime.Hour = (UINT8) SystemTime.wHour;
2022 Info->ModificationTime.Minute = (UINT8) SystemTime.wMinute;
2023 Info->ModificationTime.Second = (UINT8) SystemTime.wSecond;
2024
2025 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {
2026 Info->Attribute |= EFI_FILE_ARCHIVE;
2027 }
2028
2029 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {
2030 Info->Attribute |= EFI_FILE_HIDDEN;
2031 }
2032
2033 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
2034 Info->Attribute |= EFI_FILE_READ_ONLY;
2035 }
2036
2037 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {
2038 Info->Attribute |= EFI_FILE_SYSTEM;
2039 }
2040
2041 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
2042 Info->Attribute |= EFI_FILE_DIRECTORY;
2043 }
2044
2045 if (PrivateFile->IsDirectoryPath) {
2046 Info->Attribute |= EFI_FILE_DIRECTORY;
2047 }
2048
2049 RealFileName = PrivateFile->FileName;
2050 TempPointer = RealFileName;
2051
2052 while (*TempPointer) {
2053 if (*TempPointer == '\\') {
2054 RealFileName = TempPointer + 1;
2055 }
2056
2057 TempPointer++;
2058 }
2059
2060 if (PrivateFile->IsRootDirectory) {
2061 *((CHAR8 *) Buffer + Size) = 0;
2062 } else {
2063 CopyMem ((CHAR8 *) Buffer + Size, RealFileName, NameSize);
2064 }
2065 }
2066
2067 *BufferSize = ResultSize;
2068 return Status;
2069}
2070
2071EFI_STATUS
2072EFIAPI
2073WinNtSimpleFileSystemGetInfo (
2074 IN EFI_FILE_PROTOCOL *This,
2075 IN EFI_GUID *InformationType,
2076 IN OUT UINTN *BufferSize,
2077 OUT VOID *Buffer
2078 )
2079/*++
2080
2081Routine Description:
2082
2083 Return information about a file or volume.
2084
2085Arguments:
2086
2087 This - Pointer to an opened file handle.
2088
2089 InformationType - GUID describing the type of information to be returned.
2090
2091 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
2092 information buffer.
2093
2094 Buffer - Pointer to the first byte of the information buffer.
2095
2096Returns:
2097
2098 EFI_SUCCESS - The requested information has been written into the buffer.
2099
2100 EFI_UNSUPPORTED - The InformationType is not known.
2101
2102 EFI_NO_MEDIA - The device has no media.
2103
2104 EFI_DEVICE_ERROR - The device reported an error.
2105
2106 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2107
2108 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
2109 been updated with the size needed to complete the requested operation.
2110
2111--*/
2112// TODO: EFI_INVALID_PARAMETER - add return value to function comment
2113{
2114 EFI_STATUS Status;
2115 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
2116 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;
2117 UINT32 SectorsPerCluster;
2118 UINT32 BytesPerSector;
2119 UINT32 FreeClusters;
2120 UINT32 TotalClusters;
2121 UINT32 BytesPerCluster;
2122 CHAR16 *DriveName;
2123 BOOLEAN DriveNameFound;
2124 BOOL NtStatus;
2125 UINTN Index;
2126 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
2127 EFI_TPL OldTpl;
2128
2129 if (This == NULL || InformationType == NULL || BufferSize == NULL) {
2130 return EFI_INVALID_PARAMETER;
2131 }
2132
2133 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
2134
2135 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
2136 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
2137
2138 Status = EFI_UNSUPPORTED;
2139
2140 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
2141 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);
2142 }
2143
2144 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
2145 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
2146 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
2147 Status = EFI_BUFFER_TOO_SMALL;
2148 goto Done;
2149 }
2150
2151 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;
2152 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
2153 FileSystemInfoBuffer->ReadOnly = FALSE;
2154
2155 //
2156 // Try to get the drive name
2157 //
2158 DriveNameFound = FALSE;
2159 DriveName = AllocatePool (StrSize (PrivateFile->FilePath) + 1);
2160 if (DriveName == NULL) {
2161 Status = EFI_OUT_OF_RESOURCES;
2162 goto Done;
2163 }
2164
2165 StrCpy (DriveName, PrivateFile->FilePath);
2166 for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) {
2167 ;
2168 }
2169
2170 if (DriveName[Index] == ':') {
2171 DriveName[Index + 1] = '\\';
2172 DriveName[Index + 2] = 0;
2173 DriveNameFound = TRUE;
2174 } else if (DriveName[0] == '\\' && DriveName[1] == '\\') {
2175 for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
2176 ;
2177 }
2178
2179 if (DriveName[Index] == '\\') {
2180 DriveNameFound = TRUE;
2181 for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
2182 ;
2183 }
2184
2185 DriveName[Index] = '\\';
2186 DriveName[Index + 1] = 0;
2187 }
2188 }
2189
2190 //
2191 // Try GetDiskFreeSpace first
2192 //
2193 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpace (
2194 DriveNameFound ? DriveName : NULL,
2195 (LPDWORD)&SectorsPerCluster,
2196 (LPDWORD)&BytesPerSector,
2197 (LPDWORD)&FreeClusters,
2198 (LPDWORD)&TotalClusters
2199 );
2200 if (DriveName) {
2201 FreePool (DriveName);
2202 }
2203
2204 if (NtStatus) {
2205 //
2206 // Succeeded
2207 //
2208 BytesPerCluster = BytesPerSector * SectorsPerCluster;
2209 FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster);
2210 FileSystemInfoBuffer->FreeSpace = MultU64x32 (FreeClusters, BytesPerCluster);
2211 FileSystemInfoBuffer->BlockSize = BytesPerCluster;
2212
2213 } else {
2214 //
2215 // try GetDiskFreeSpaceEx then
2216 //
2217 FileSystemInfoBuffer->BlockSize = 0;
2218 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpaceEx (
2219 PrivateFile->FilePath,
2220 (PULARGE_INTEGER) (&FileSystemInfoBuffer->FreeSpace),
2221 (PULARGE_INTEGER) (&FileSystemInfoBuffer->VolumeSize),
2222 NULL
2223 );
2224 if (!NtStatus) {
2225 Status = EFI_DEVICE_ERROR;
2226 goto Done;
2227 }
2228 }
2229
2230 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);
2231 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
2232 Status = EFI_SUCCESS;
2233 }
2234
2235 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
2236 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
2237 *BufferSize = StrSize (PrivateRoot->VolumeLabel);
2238 Status = EFI_BUFFER_TOO_SMALL;
2239 goto Done;
2240 }
2241
2242 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);
2243 *BufferSize = StrSize (PrivateRoot->VolumeLabel);
2244 Status = EFI_SUCCESS;
2245 }
2246
2247Done:
2248 gBS->RestoreTPL (OldTpl);
2249 return Status;
2250}
2251
2252EFI_STATUS
2253EFIAPI
2254WinNtSimpleFileSystemSetInfo (
2255 IN EFI_FILE_PROTOCOL*This,
2256 IN EFI_GUID *InformationType,
2257 IN UINTN BufferSize,
2258 IN VOID *Buffer
2259 )
2260/*++
2261
2262Routine Description:
2263
2264 Set information about a file or volume.
2265
2266Arguments:
2267
2268 This - Pointer to an opened file handle.
2269
2270 InformationType - GUID identifying the type of information to set.
2271
2272 BufferSize - Number of bytes of data in the information buffer.
2273
2274 Buffer - Pointer to the first byte of data in the information buffer.
2275
2276Returns:
2277
2278 EFI_SUCCESS - The file or volume information has been updated.
2279
2280 EFI_UNSUPPORTED - The information identifier is not recognised.
2281
2282 EFI_NO_MEDIA - The device has no media.
2283
2284 EFI_DEVICE_ERROR - The device reported an error.
2285
2286 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2287
2288 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2289
2290 EFI_ACCESS_DENIED - The file was opened read-only.
2291
2292 EFI_VOLUME_FULL - The volume is full.
2293
2294 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2295
2296--*/
2297// TODO: EFI_INVALID_PARAMETER - add return value to function comment
2298// TODO: EFI_INVALID_PARAMETER - add return value to function comment
2299{
2300 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
2301 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
2302 EFI_FILE_INFO *OldFileInfo;
2303 EFI_FILE_INFO *NewFileInfo;
2304 EFI_STATUS Status;
2305 UINTN OldInfoSize;
2306 INTN NtStatus;
2307 UINT32 NewAttr;
2308 UINT32 OldAttr;
2309 CHAR16 *OldFileName;
2310 CHAR16 *NewFileName;
2311 CHAR16 *TempFileName;
2312 CHAR16 *CharPointer;
2313 BOOLEAN AttrChangeFlag;
2314 BOOLEAN NameChangeFlag;
2315 BOOLEAN SizeChangeFlag;
2316 BOOLEAN TimeChangeFlag;
2317 UINT64 CurPos;
2318 SYSTEMTIME NewCreationSystemTime;
2319 SYSTEMTIME NewLastAccessSystemTime;
2320 SYSTEMTIME NewLastWriteSystemTime;
2321 FILETIME NewCreationFileTime;
2322 FILETIME NewLastAccessFileTime;
2323 FILETIME NewLastWriteFileTime;
2324 WIN32_FIND_DATA FindBuf;
2325 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;
2326 EFI_TPL OldTpl;
2327 UINTN Size;
2328
2329 //
2330 // Check for invalid parameters.
2331 //
2332 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {
2333 return EFI_INVALID_PARAMETER;
2334 }
2335
2336 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
2337
2338 //
2339 // Initialise locals.
2340 //
2341 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
2342 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
2343
2344 Status = EFI_UNSUPPORTED;
2345 OldFileInfo = NewFileInfo = NULL;
2346 OldFileName = NewFileName = NULL;
2347 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;
2348
2349 //
2350 // Set file system information.
2351 //
2352 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
2353 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;
2354 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (NewFileSystemInfo->VolumeLabel)) {
2355 Status = EFI_BAD_BUFFER_SIZE;
2356 goto Done;
2357 }
2358
2359
2360 FreePool (PrivateRoot->VolumeLabel);
2361 PrivateRoot->VolumeLabel = AllocatePool (StrSize (NewFileSystemInfo->VolumeLabel));
2362 if (PrivateRoot->VolumeLabel == NULL) {
2363 Status = EFI_OUT_OF_RESOURCES;
2364 goto Done;
2365 }
2366
2367 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);
2368
2369 Status = EFI_SUCCESS;
2370 goto Done;
2371 }
2372
2373 //
2374 // Set volume label information.
2375 //
2376 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
2377 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
2378 Status = EFI_BAD_BUFFER_SIZE;
2379 goto Done;
2380 }
2381
2382 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);
2383
2384 Status = EFI_SUCCESS;
2385 goto Done;
2386 }
2387
2388 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {
2389 Status = EFI_UNSUPPORTED;
2390 goto Done;
2391 }
2392
2393 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {
2394 Status = EFI_BAD_BUFFER_SIZE;
2395 goto Done;
2396 }
2397
2398 //
2399 // Set file/directory information.
2400 //
2401
2402 //
2403 // Check for invalid set file information parameters.
2404 //
2405 NewFileInfo = (EFI_FILE_INFO *) Buffer;
2406
2407 if ((NewFileInfo->Size <= SIZE_OF_EFI_FILE_INFO) ||
2408 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||
2409 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)
2410 ) {
2411 Status = EFI_INVALID_PARAMETER;
2412 goto Done;
2413 }
2414
2415 //
2416 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2417 // that would have an additional parameter that would be the size
2418 // of the string array just in case there are no NULL characters in
2419 // the string array.
2420 //
2421 //
2422 // Get current file information so we can determine what kind
2423 // of change request this is.
2424 //
2425 OldInfoSize = 0;
2426 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL);
2427
2428 if (Status != EFI_BUFFER_TOO_SMALL) {
2429 Status = EFI_DEVICE_ERROR;
2430 goto Done;
2431 }
2432
2433 OldFileInfo = AllocatePool (OldInfoSize);
2434 if (OldFileInfo == NULL) {
2435 Status = EFI_OUT_OF_RESOURCES;
2436 goto Done;
2437 }
2438
2439 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo);
2440
2441 if (EFI_ERROR (Status)) {
2442 goto Done;
2443 }
2444
2445 OldFileName = AllocatePool (StrSize (PrivateFile->FileName));
2446 if (OldFileName == NULL) {
2447 Status = EFI_OUT_OF_RESOURCES;
2448 goto Done;
2449 }
2450
2451 StrCpy (OldFileName, PrivateFile->FileName);
2452
2453 //
2454 // Make full pathname from new filename and rootpath.
2455 //
2456 if (NewFileInfo->FileName[0] == '\\') {
2457 Size = StrSize (PrivateRoot->FilePath);
2458 Size += StrSize (L"\\");
2459 Size += StrSize (NewFileInfo->FileName);
2460 NewFileName = AllocatePool (Size);
2461 if (NewFileName == NULL) {
2462 Status = EFI_OUT_OF_RESOURCES;
2463 goto Done;
2464 }
2465
2466 StrCpy (NewFileName, PrivateRoot->FilePath);
2467 StrCat (NewFileName, L"\\");
2468 StrCat (NewFileName, NewFileInfo->FileName + 1);
2469 } else {
2470 Size = StrSize (PrivateFile->FilePath);
2471 Size += StrSize (L"\\");
2472 Size += StrSize (NewFileInfo->FileName);
2473 NewFileName = AllocatePool (Size);
2474 if (NewFileName == NULL) {
2475 Status = EFI_OUT_OF_RESOURCES;
2476 goto Done;
2477 }
2478
2479 StrCpy (NewFileName, PrivateFile->FilePath);
2480 StrCat (NewFileName, L"\\");
2481 StrCat (NewFileName, NewFileInfo->FileName);
2482 }
2483
2484 //
2485 // Is there an attribute change request?
2486 //
2487 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {
2488 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
2489 Status = EFI_INVALID_PARAMETER;
2490 goto Done;
2491 }
2492
2493 AttrChangeFlag = TRUE;
2494 }
2495
2496 //
2497 // Is there a name change request?
2498 // bugbug: - Need EfiStrCaseCmp()
2499 //
2500 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {
2501 NameChangeFlag = TRUE;
2502 }
2503
2504 //
2505 // Is there a size change request?
2506 //
2507 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {
2508 SizeChangeFlag = TRUE;
2509 }
2510
2511 //
2512 // Is there a time stamp change request?
2513 //
2514 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&
2515 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))
2516 ) {
2517 TimeChangeFlag = TRUE;
2518 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&
2519 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))
2520 ) {
2521 TimeChangeFlag = TRUE;
2522 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&
2523 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))
2524 ) {
2525 TimeChangeFlag = TRUE;
2526 }
2527
2528 //
2529 // All done if there are no change requests being made.
2530 //
2531 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {
2532 Status = EFI_SUCCESS;
2533 goto Done;
2534 }
2535
2536 //
2537 // Set file or directory information.
2538 //
2539 OldAttr = PrivateFile->WinNtThunk->GetFileAttributes (OldFileName);
2540
2541 //
2542 // Name change.
2543 //
2544 if (NameChangeFlag) {
2545 //
2546 // Close the handles first
2547 //
2548 if (PrivateFile->IsOpenedByRead) {
2549 Status = EFI_ACCESS_DENIED;
2550 goto Done;
2551 }
2552
2553 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {
2554 }
2555
2556 if (*CharPointer != 0) {
2557 Status = EFI_ACCESS_DENIED;
2558 goto Done;
2559 }
2560
2561 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
2562 if (PrivateFile->IsDirectoryPath) {
2563 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);
2564 } else {
2565 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);
2566 PrivateFile->LHandle = INVALID_HANDLE_VALUE;
2567 }
2568 }
2569
2570 if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
2571 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);
2572 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
2573 }
2574
2575 NtStatus = PrivateFile->WinNtThunk->MoveFile (OldFileName, NewFileName);
2576
2577 if (NtStatus) {
2578 //
2579 // modify file name
2580 //
2581 FreePool (PrivateFile->FileName);
2582
2583 PrivateFile->FileName = AllocatePool (StrSize (NewFileName));
2584 if (PrivateFile->FileName == NULL) {
2585 Status = EFI_OUT_OF_RESOURCES;
2586 goto Done;
2587 }
2588
2589 StrCpy (PrivateFile->FileName, NewFileName);
2590
2591 Size = StrSize (NewFileName);
2592 Size += StrSize (L"\\*");
2593 TempFileName = AllocatePool (Size);
2594
2595 StrCpy (TempFileName, NewFileName);
2596
2597 if (!PrivateFile->IsDirectoryPath) {
2598 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (
2599 TempFileName,
2600 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2601 FILE_SHARE_READ | FILE_SHARE_WRITE,
2602 NULL,
2603 OPEN_EXISTING,
2604 0,
2605 NULL
2606 );
2607
2608 FreePool (TempFileName);
2609
2610 //
2611 // Flush buffers just in case
2612 //
2613 if (PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) == 0) {
2614 Status = EFI_DEVICE_ERROR;
2615 goto Done;
2616 }
2617 } else {
2618 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (
2619 TempFileName,
2620 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2621 FILE_SHARE_READ | FILE_SHARE_WRITE,
2622 NULL,
2623 OPEN_EXISTING,
2624 FILE_FLAG_BACKUP_SEMANTICS,
2625 NULL
2626 );
2627
2628 StrCat (TempFileName, L"\\*");
2629 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);
2630
2631 FreePool (TempFileName);
2632 }
2633 } else {
2634 Status = EFI_ACCESS_DENIED;
2635Reopen: ;
2636
2637 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (OldFileName, OldAttr);
2638
2639 if (!NtStatus) {
2640 goto Done;
2641 }
2642
2643 Size = StrSize (OldFileName);
2644 Size += StrSize (L"\\*");
2645 TempFileName = AllocatePool (Size);
2646
2647 StrCpy (TempFileName, OldFileName);
2648
2649 if (!PrivateFile->IsDirectoryPath) {
2650 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (
2651 TempFileName,
2652 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2653 FILE_SHARE_READ | FILE_SHARE_WRITE,
2654 NULL,
2655 OPEN_EXISTING,
2656 0,
2657 NULL
2658 );
2659 } else {
2660 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (
2661 TempFileName,
2662 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2663 FILE_SHARE_READ | FILE_SHARE_WRITE,
2664 NULL,
2665 OPEN_EXISTING,
2666 FILE_FLAG_BACKUP_SEMANTICS,
2667 NULL
2668 );
2669
2670 StrCat (TempFileName, L"\\*");
2671 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);
2672 }
2673
2674 FreePool (TempFileName);
2675
2676 goto Done;
2677
2678 }
2679 }
2680
2681 //
2682 // Size change
2683 //
2684 if (SizeChangeFlag) {
2685 if (PrivateFile->IsDirectoryPath) {
2686 Status = EFI_UNSUPPORTED;
2687 goto Done;
2688 }
2689
2690 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2691 Status = EFI_ACCESS_DENIED;
2692 goto Done;
2693 }
2694
2695 Status = This->GetPosition (This, &CurPos);
2696 if (EFI_ERROR (Status)) {
2697 goto Done;
2698 }
2699
2700 Status = This->SetPosition (This, NewFileInfo->FileSize);
2701 if (EFI_ERROR (Status)) {
2702 goto Done;
2703 }
2704
2705 if (PrivateFile->WinNtThunk->SetEndOfFile (PrivateFile->LHandle) == 0) {
2706 Status = EFI_DEVICE_ERROR;
2707 goto Done;
2708 }
2709
2710 Status = This->SetPosition (This, CurPos);
2711 if (EFI_ERROR (Status)) {
2712 goto Done;
2713 }
2714 }
2715
2716 //
2717 // Time change
2718 //
2719 if (TimeChangeFlag) {
2720
2721 NewCreationSystemTime.wYear = NewFileInfo->CreateTime.Year;
2722 NewCreationSystemTime.wMonth = NewFileInfo->CreateTime.Month;
2723 NewCreationSystemTime.wDay = NewFileInfo->CreateTime.Day;
2724 NewCreationSystemTime.wHour = NewFileInfo->CreateTime.Hour;
2725 NewCreationSystemTime.wMinute = NewFileInfo->CreateTime.Minute;
2726 NewCreationSystemTime.wSecond = NewFileInfo->CreateTime.Second;
2727 NewCreationSystemTime.wMilliseconds = 0;
2728
2729 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (
2730 &NewCreationSystemTime,
2731 &NewCreationFileTime
2732 )) {
2733 goto Done;
2734 }
2735
2736 if (!PrivateFile->WinNtThunk->LocalFileTimeToFileTime (
2737 &NewCreationFileTime,
2738 &NewCreationFileTime
2739 )) {
2740 goto Done;
2741 }
2742
2743 NewLastAccessSystemTime.wYear = NewFileInfo->LastAccessTime.Year;
2744 NewLastAccessSystemTime.wMonth = NewFileInfo->LastAccessTime.Month;
2745 NewLastAccessSystemTime.wDay = NewFileInfo->LastAccessTime.Day;
2746 NewLastAccessSystemTime.wHour = NewFileInfo->LastAccessTime.Hour;
2747 NewLastAccessSystemTime.wMinute = NewFileInfo->LastAccessTime.Minute;
2748 NewLastAccessSystemTime.wSecond = NewFileInfo->LastAccessTime.Second;
2749 NewLastAccessSystemTime.wMilliseconds = 0;
2750
2751 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (
2752 &NewLastAccessSystemTime,
2753 &NewLastAccessFileTime
2754 )) {
2755 goto Done;
2756 }
2757
2758 if (!PrivateFile->WinNtThunk->LocalFileTimeToFileTime (
2759 &NewLastAccessFileTime,
2760 &NewLastAccessFileTime
2761 )) {
2762 goto Done;
2763 }
2764
2765 NewLastWriteSystemTime.wYear = NewFileInfo->ModificationTime.Year;
2766 NewLastWriteSystemTime.wMonth = NewFileInfo->ModificationTime.Month;
2767 NewLastWriteSystemTime.wDay = NewFileInfo->ModificationTime.Day;
2768 NewLastWriteSystemTime.wHour = NewFileInfo->ModificationTime.Hour;
2769 NewLastWriteSystemTime.wMinute = NewFileInfo->ModificationTime.Minute;
2770 NewLastWriteSystemTime.wSecond = NewFileInfo->ModificationTime.Second;
2771 NewLastWriteSystemTime.wMilliseconds = 0;
2772
2773 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (
2774 &NewLastWriteSystemTime,
2775 &NewLastWriteFileTime
2776 )) {
2777 goto Done;
2778 }
2779
2780 if (!PrivateFile->WinNtThunk->LocalFileTimeToFileTime (
2781 &NewLastWriteFileTime,
2782 &NewLastWriteFileTime
2783 )) {
2784 goto Done;
2785 }
2786
2787 if (!PrivateFile->WinNtThunk->SetFileTime (
2788 PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,
2789 &NewCreationFileTime,
2790 &NewLastAccessFileTime,
2791 &NewLastWriteFileTime
2792 )) {
2793 Status = EFI_DEVICE_ERROR;
2794 goto Done;
2795 }
2796
2797 }
2798
2799 //
2800 // No matter about AttrChangeFlag, Attribute must be set.
2801 // Because operation before may cause attribute change.
2802 //
2803 NewAttr = OldAttr;
2804
2805 if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) {
2806 NewAttr |= FILE_ATTRIBUTE_ARCHIVE;
2807 } else {
2808 NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE;
2809 }
2810
2811 if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) {
2812 NewAttr |= FILE_ATTRIBUTE_HIDDEN;
2813 } else {
2814 NewAttr &= ~FILE_ATTRIBUTE_HIDDEN;
2815 }
2816
2817 if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) {
2818 NewAttr |= FILE_ATTRIBUTE_SYSTEM;
2819 } else {
2820 NewAttr &= ~FILE_ATTRIBUTE_SYSTEM;
2821 }
2822
2823 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2824 NewAttr |= FILE_ATTRIBUTE_READONLY;
2825 } else {
2826 NewAttr &= ~FILE_ATTRIBUTE_READONLY;
2827 }
2828
2829 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (NewFileName, NewAttr);
2830
2831 if (!NtStatus) {
2832 Status = EFI_DEVICE_ERROR;
2833 goto Reopen;
2834 }
2835
2836Done:
2837 if (OldFileInfo != NULL) {
2838 FreePool (OldFileInfo);
2839 }
2840
2841 if (OldFileName != NULL) {
2842 FreePool (OldFileName);
2843 }
2844
2845 if (NewFileName != NULL) {
2846 FreePool (NewFileName);
2847 }
2848
2849 gBS->RestoreTPL (OldTpl);
2850 return Status;
2851}
2852
2853EFI_STATUS
2854EFIAPI
2855WinNtSimpleFileSystemFlush (
2856 IN EFI_FILE_PROTOCOL *This
2857 )
2858/*++
2859
2860Routine Description:
2861
2862 Flush all modified data to the media.
2863
2864Arguments:
2865
2866 This - Pointer to an opened file handle.
2867
2868Returns:
2869
2870 EFI_SUCCESS - The data has been flushed.
2871
2872 EFI_NO_MEDIA - The device has no media.
2873
2874 EFI_DEVICE_ERROR - The device reported an error.
2875
2876 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2877
2878 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2879
2880 EFI_ACCESS_DENIED - The file was opened read-only.
2881
2882 EFI_VOLUME_FULL - The volume is full.
2883
2884--*/
2885// TODO: EFI_INVALID_PARAMETER - add return value to function comment
2886{
2887 BY_HANDLE_FILE_INFORMATION FileInfo;
2888 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
2889 EFI_STATUS Status;
2890 EFI_TPL OldTpl;
2891
2892 if (This == NULL) {
2893 return EFI_INVALID_PARAMETER;
2894 }
2895
2896 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
2897
2898 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
2899
2900 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
2901 Status = EFI_DEVICE_ERROR;
2902 goto Done;
2903 }
2904
2905 if (PrivateFile->IsDirectoryPath) {
2906 Status = EFI_SUCCESS;
2907 goto Done;
2908 }
2909
2910 if (PrivateFile->IsOpenedByRead) {
2911 Status = EFI_ACCESS_DENIED;
2912 goto Done;
2913 }
2914
2915 PrivateFile->WinNtThunk->GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo);
2916
2917 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
2918 Status = EFI_ACCESS_DENIED;
2919 goto Done;
2920 }
2921
2922 Status = PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
2923
2924Done:
2925 gBS->RestoreTPL (OldTpl);
2926 return Status;
2927 //
2928 // bugbug: - Use Windows error reporting.
2929 //
2930}
2931
2932