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