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