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