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