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