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