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