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