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