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