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