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