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