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