Fixed bug in NT32 file system driver. The FileInfo->FileSize returned for a directory...
[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) {
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 EFI_FILE_INFO *DirInfo;
1721 UINTN ReadSize;
1722 UINT64 Location;
1723 EFI_STATUS DirStatus;
1724
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 if (Info->Attribute & EFI_FILE_DIRECTORY) {
1811 //
1812 // The GetFileInformationByHandle.nFileSizeLow is bogus for dir so we
1813 // need to do the same thing the caller would do to get the right value
1814 //
1815 ASSERT (PrivateFile->EfiFile.Read != NULL);
1816 DirStatus = PrivateFile->EfiFile.GetPosition (&PrivateFile->EfiFile, &Location);
1817 if (EFI_ERROR (DirStatus)) {
1818 Location = 0;
1819 }
1820
1821 PrivateFile->EfiFile.SetPosition (&PrivateFile->EfiFile, 0);
1822 Info->FileSize = 0;
1823 do {
1824 ReadSize = 0;
1825 DirInfo = NULL;
1826 DirStatus = PrivateFile->EfiFile.Read (&PrivateFile->EfiFile, &ReadSize, DirInfo);
1827 if (DirStatus == EFI_BUFFER_TOO_SMALL) {
1828 DirInfo = AllocatePool (ReadSize);
1829 if (DirInfo != NULL) {
1830 //
1831 // Read each dir entry to figure out how big the directory is
1832 //
1833 DirStatus = PrivateFile->EfiFile.Read (&PrivateFile->EfiFile, &ReadSize, DirInfo);
1834 if (!EFI_ERROR (DirStatus) && (ReadSize != 0)) {
1835 Info->FileSize += ReadSize;
1836 }
1837 FreePool (DirInfo);
1838 }
1839 }
1840
1841 } while (!EFI_ERROR (DirStatus) && (ReadSize != 0));
1842
1843 //
1844 // reset the file possition back to the previous location
1845 //
1846 PrivateFile->EfiFile.SetPosition (&PrivateFile->EfiFile, Location);
1847 }
1848 }
1849
1850 *BufferSize = ResultSize;
1851 return Status;
1852 }
1853
1854 EFI_STATUS
1855 EFIAPI
1856 WinNtSimpleFileSystemGetInfo (
1857 IN EFI_FILE *This,
1858 IN EFI_GUID *InformationType,
1859 IN OUT UINTN *BufferSize,
1860 OUT VOID *Buffer
1861 )
1862 /*++
1863
1864 Routine Description:
1865
1866 Return information about a file or volume.
1867
1868 Arguments:
1869
1870 This - Pointer to an opened file handle.
1871
1872 InformationType - GUID describing the type of information to be returned.
1873
1874 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the
1875 information buffer.
1876
1877 Buffer - Pointer to the first byte of the information buffer.
1878
1879 Returns:
1880
1881 EFI_SUCCESS - The requested information has been written into the buffer.
1882
1883 EFI_UNSUPPORTED - The InformationType is not known.
1884
1885 EFI_NO_MEDIA - The device has no media.
1886
1887 EFI_DEVICE_ERROR - The device reported an error.
1888
1889 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
1890
1891 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has
1892 been updated with the size needed to complete the requested operation.
1893
1894 --*/
1895 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
1896 {
1897 EFI_STATUS Status;
1898 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
1899 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;
1900 UINT32 SectorsPerCluster;
1901 UINT32 BytesPerSector;
1902 UINT32 FreeClusters;
1903 UINT32 TotalClusters;
1904 UINT32 BytesPerCluster;
1905 CHAR16 *DriveName;
1906 BOOLEAN DriveNameFound;
1907 BOOL NtStatus;
1908 UINTN Index;
1909 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
1910 EFI_TPL OldTpl;
1911
1912 if (This == NULL || InformationType == NULL || BufferSize == NULL) {
1913 return EFI_INVALID_PARAMETER;
1914 }
1915
1916 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
1917
1918 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
1919 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
1920
1921 Status = EFI_UNSUPPORTED;
1922
1923 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {
1924 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);
1925 }
1926
1927 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
1928 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
1929 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
1930 Status = EFI_BUFFER_TOO_SMALL;
1931 goto Done;
1932 }
1933
1934 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;
1935 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
1936 FileSystemInfoBuffer->ReadOnly = FALSE;
1937
1938 //
1939 // Try to get the drive name
1940 //
1941 DriveNameFound = FALSE;
1942 DriveName = AllocatePool (StrSize (PrivateFile->FilePath) + 1);
1943 if (DriveName == NULL) {
1944 Status = EFI_OUT_OF_RESOURCES;
1945 goto Done;
1946 }
1947
1948 StrCpy (DriveName, PrivateFile->FilePath);
1949 for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) {
1950 ;
1951 }
1952
1953 if (DriveName[Index] == ':') {
1954 DriveName[Index + 1] = '\\';
1955 DriveName[Index + 2] = 0;
1956 DriveNameFound = TRUE;
1957 } else if (DriveName[0] == '\\' && DriveName[1] == '\\') {
1958 for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
1959 ;
1960 }
1961
1962 if (DriveName[Index] == '\\') {
1963 DriveNameFound = TRUE;
1964 for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {
1965 ;
1966 }
1967
1968 DriveName[Index] = '\\';
1969 DriveName[Index + 1] = 0;
1970 }
1971 }
1972
1973 //
1974 // Try GetDiskFreeSpace first
1975 //
1976 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpace (
1977 DriveNameFound ? DriveName : NULL,
1978 &SectorsPerCluster,
1979 &BytesPerSector,
1980 &FreeClusters,
1981 &TotalClusters
1982 );
1983 if (DriveName) {
1984 FreePool (DriveName);
1985 }
1986
1987 if (NtStatus) {
1988 //
1989 // Succeeded
1990 //
1991 BytesPerCluster = BytesPerSector * SectorsPerCluster;
1992 FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster);
1993 FileSystemInfoBuffer->FreeSpace = MultU64x32 (FreeClusters, BytesPerCluster);
1994 FileSystemInfoBuffer->BlockSize = BytesPerCluster;
1995
1996 } else {
1997 //
1998 // try GetDiskFreeSpaceEx then
1999 //
2000 FileSystemInfoBuffer->BlockSize = 0;
2001 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpaceEx (
2002 PrivateFile->FilePath,
2003 (PULARGE_INTEGER) (&FileSystemInfoBuffer->FreeSpace),
2004 (PULARGE_INTEGER) (&FileSystemInfoBuffer->VolumeSize),
2005 NULL
2006 );
2007 if (!NtStatus) {
2008 Status = EFI_DEVICE_ERROR;
2009 goto Done;
2010 }
2011 }
2012
2013 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);
2014 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);
2015 Status = EFI_SUCCESS;
2016 }
2017
2018 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
2019 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
2020 *BufferSize = StrSize (PrivateRoot->VolumeLabel);
2021 Status = EFI_BUFFER_TOO_SMALL;
2022 goto Done;
2023 }
2024
2025 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);
2026 *BufferSize = StrSize (PrivateRoot->VolumeLabel);
2027 Status = EFI_SUCCESS;
2028 }
2029
2030 Done:
2031 gBS->RestoreTPL (OldTpl);
2032 return Status;
2033 }
2034
2035 EFI_STATUS
2036 EFIAPI
2037 WinNtSimpleFileSystemSetInfo (
2038 IN EFI_FILE *This,
2039 IN EFI_GUID *InformationType,
2040 IN UINTN BufferSize,
2041 IN VOID *Buffer
2042 )
2043 /*++
2044
2045 Routine Description:
2046
2047 Set information about a file or volume.
2048
2049 Arguments:
2050
2051 This - Pointer to an opened file handle.
2052
2053 InformationType - GUID identifying the type of information to set.
2054
2055 BufferSize - Number of bytes of data in the information buffer.
2056
2057 Buffer - Pointer to the first byte of data in the information buffer.
2058
2059 Returns:
2060
2061 EFI_SUCCESS - The file or volume information has been updated.
2062
2063 EFI_UNSUPPORTED - The information identifier is not recognised.
2064
2065 EFI_NO_MEDIA - The device has no media.
2066
2067 EFI_DEVICE_ERROR - The device reported an error.
2068
2069 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.
2070
2071 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2072
2073 EFI_ACCESS_DENIED - The file was opened read-only.
2074
2075 EFI_VOLUME_FULL - The volume is full.
2076
2077 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.
2078
2079 --*/
2080 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2081 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2082 {
2083 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;
2084 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
2085 EFI_FILE_INFO *OldFileInfo;
2086 EFI_FILE_INFO *NewFileInfo;
2087 EFI_STATUS Status;
2088 UINTN OldInfoSize;
2089 INTN NtStatus;
2090 UINT32 NewAttr;
2091 UINT32 OldAttr;
2092 CHAR16 *OldFileName;
2093 CHAR16 *NewFileName;
2094 CHAR16 *TempFileName;
2095 CHAR16 *CharPointer;
2096 BOOLEAN AttrChangeFlag;
2097 BOOLEAN NameChangeFlag;
2098 BOOLEAN SizeChangeFlag;
2099 BOOLEAN TimeChangeFlag;
2100 UINT64 CurPos;
2101 SYSTEMTIME NewCreationSystemTime;
2102 SYSTEMTIME NewLastAccessSystemTime;
2103 SYSTEMTIME NewLastWriteSystemTime;
2104 FILETIME NewCreationFileTime;
2105 FILETIME NewLastAccessFileTime;
2106 FILETIME NewLastWriteFileTime;
2107 WIN32_FIND_DATA FindBuf;
2108 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;
2109 EFI_TPL OldTpl;
2110
2111 //
2112 // Check for invalid parameters.
2113 //
2114 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {
2115 return EFI_INVALID_PARAMETER;
2116 }
2117
2118 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
2119
2120 //
2121 // Initialise locals.
2122 //
2123 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
2124 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);
2125
2126 Status = EFI_UNSUPPORTED;
2127 OldFileInfo = NewFileInfo = NULL;
2128 OldFileName = NewFileName = NULL;
2129 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;
2130
2131 //
2132 // Set file system information.
2133 //
2134 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {
2135 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {
2136 Status = EFI_BAD_BUFFER_SIZE;
2137 goto Done;
2138 }
2139
2140 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;
2141
2142 FreePool (PrivateRoot->VolumeLabel);
2143 PrivateRoot->VolumeLabel = AllocatePool (StrSize (NewFileSystemInfo->VolumeLabel));
2144 if (PrivateRoot->VolumeLabel == NULL) {
2145 Status = EFI_OUT_OF_RESOURCES;
2146 goto Done;
2147 }
2148
2149 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);
2150
2151 Status = EFI_SUCCESS;
2152 goto Done;
2153 }
2154
2155 //
2156 // Set volume label information.
2157 //
2158 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {
2159 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {
2160 Status = EFI_BAD_BUFFER_SIZE;
2161 goto Done;
2162 }
2163
2164 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);
2165
2166 Status = EFI_SUCCESS;
2167 goto Done;
2168 }
2169
2170 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {
2171 Status = EFI_UNSUPPORTED;
2172 goto Done;
2173 }
2174
2175 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {
2176 Status = EFI_BAD_BUFFER_SIZE;
2177 goto Done;
2178 }
2179
2180 //
2181 // Set file/directory information.
2182 //
2183
2184 //
2185 // Check for invalid set file information parameters.
2186 //
2187 NewFileInfo = (EFI_FILE_INFO *) Buffer;
2188
2189 if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) ||
2190 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||
2191 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)
2192 ) {
2193 Status = EFI_INVALID_PARAMETER;
2194 goto Done;
2195 }
2196
2197 //
2198 // bugbug: - This is not safe. We need something like EfiStrMaxSize()
2199 // that would have an additional parameter that would be the size
2200 // of the string array just in case there are no NULL characters in
2201 // the string array.
2202 //
2203 //
2204 // Get current file information so we can determine what kind
2205 // of change request this is.
2206 //
2207 OldInfoSize = 0;
2208 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL);
2209
2210 if (Status != EFI_BUFFER_TOO_SMALL) {
2211 Status = EFI_DEVICE_ERROR;
2212 goto Done;
2213 }
2214
2215 OldFileInfo = AllocatePool (OldInfoSize);
2216 if (OldFileInfo == NULL) {
2217 Status = EFI_OUT_OF_RESOURCES;
2218 goto Done;
2219 }
2220
2221 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo);
2222
2223 if (EFI_ERROR (Status)) {
2224 goto Done;
2225 }
2226
2227 OldFileName = AllocatePool (StrSize (PrivateFile->FileName));
2228 if (OldFileName == NULL) {
2229 Status = EFI_OUT_OF_RESOURCES;
2230 goto Done;
2231 }
2232
2233 StrCpy (OldFileName, PrivateFile->FileName);
2234
2235 //
2236 // Make full pathname from new filename and rootpath.
2237 //
2238 if (NewFileInfo->FileName[0] == '\\') {
2239 NewFileName = AllocatePool (StrSize (PrivateRoot->FilePath) + StrSize (L"\\") + StrSize (NewFileInfo->FileName));
2240 if (NewFileName == NULL) {
2241 Status = EFI_OUT_OF_RESOURCES;
2242 goto Done;
2243 }
2244
2245 StrCpy (NewFileName, PrivateRoot->FilePath);
2246 StrCat (NewFileName, L"\\");
2247 StrCat (NewFileName, NewFileInfo->FileName + 1);
2248 } else {
2249 NewFileName = AllocatePool (StrSize (PrivateFile->FilePath) + StrSize (L"\\") + StrSize (NewFileInfo->FileName));
2250 if (NewFileName == NULL) {
2251 Status = EFI_OUT_OF_RESOURCES;
2252 goto Done;
2253 }
2254
2255 StrCpy (NewFileName, PrivateFile->FilePath);
2256 StrCat (NewFileName, L"\\");
2257 StrCat (NewFileName, NewFileInfo->FileName);
2258 }
2259
2260 //
2261 // Is there an attribute change request?
2262 //
2263 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {
2264 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {
2265 Status = EFI_INVALID_PARAMETER;
2266 goto Done;
2267 }
2268
2269 AttrChangeFlag = TRUE;
2270 }
2271
2272 //
2273 // Is there a name change request?
2274 // bugbug: - Need EfiStrCaseCmp()
2275 //
2276 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {
2277 NameChangeFlag = TRUE;
2278 }
2279
2280 //
2281 // Is there a size change request?
2282 //
2283 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {
2284 SizeChangeFlag = TRUE;
2285 }
2286
2287 //
2288 // Is there a time stamp change request?
2289 //
2290 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&
2291 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))
2292 ) {
2293 TimeChangeFlag = TRUE;
2294 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&
2295 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))
2296 ) {
2297 TimeChangeFlag = TRUE;
2298 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&
2299 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))
2300 ) {
2301 TimeChangeFlag = TRUE;
2302 }
2303
2304 //
2305 // All done if there are no change requests being made.
2306 //
2307 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {
2308 Status = EFI_SUCCESS;
2309 goto Done;
2310 }
2311
2312 //
2313 // Set file or directory information.
2314 //
2315 OldAttr = PrivateFile->WinNtThunk->GetFileAttributes (OldFileName);
2316
2317 //
2318 // Name change.
2319 //
2320 if (NameChangeFlag) {
2321 //
2322 // Close the handles first
2323 //
2324 if (PrivateFile->IsOpenedByRead) {
2325 Status = EFI_ACCESS_DENIED;
2326 goto Done;
2327 }
2328
2329 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {
2330 }
2331
2332 if (*CharPointer != 0) {
2333 Status = EFI_ACCESS_DENIED;
2334 goto Done;
2335 }
2336
2337 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {
2338 if (PrivateFile->IsDirectoryPath) {
2339 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);
2340 } else {
2341 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);
2342 PrivateFile->LHandle = INVALID_HANDLE_VALUE;
2343 }
2344 }
2345
2346 if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {
2347 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);
2348 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;
2349 }
2350
2351 NtStatus = PrivateFile->WinNtThunk->MoveFile (OldFileName, NewFileName);
2352
2353 if (NtStatus) {
2354 //
2355 // modify file name
2356 //
2357 FreePool (PrivateFile->FileName);
2358
2359 PrivateFile->FileName = AllocatePool (StrSize (NewFileName));
2360 if (PrivateFile->FileName == NULL) {
2361 Status = EFI_OUT_OF_RESOURCES;
2362 goto Done;
2363 }
2364
2365 StrCpy (PrivateFile->FileName, NewFileName);
2366
2367 TempFileName = AllocatePool (StrSize (NewFileName) + StrSize (L"\\*"));
2368
2369 StrCpy (TempFileName, NewFileName);
2370
2371 if (!PrivateFile->IsDirectoryPath) {
2372 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (
2373 TempFileName,
2374 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2375 FILE_SHARE_READ | FILE_SHARE_WRITE,
2376 NULL,
2377 OPEN_EXISTING,
2378 0,
2379 NULL
2380 );
2381
2382 FreePool (TempFileName);
2383
2384 //
2385 // Flush buffers just in case
2386 //
2387 if (PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) == 0) {
2388 Status = EFI_DEVICE_ERROR;
2389 goto Done;
2390 }
2391 } else {
2392 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (
2393 TempFileName,
2394 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2395 FILE_SHARE_READ | FILE_SHARE_WRITE,
2396 NULL,
2397 OPEN_EXISTING,
2398 FILE_FLAG_BACKUP_SEMANTICS,
2399 NULL
2400 );
2401
2402 StrCat (TempFileName, L"\\*");
2403 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);
2404
2405 FreePool (TempFileName);
2406 }
2407 } else {
2408 Reopen: ;
2409 Status = EFI_DEVICE_ERROR;
2410
2411 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (OldFileName, OldAttr);
2412
2413 if (!NtStatus) {
2414 goto Done;
2415 }
2416
2417 TempFileName = AllocatePool (StrSize (OldFileName) + StrSize (L"\\*"));
2418
2419 StrCpy (TempFileName, OldFileName);
2420
2421 if (!PrivateFile->IsDirectoryPath) {
2422 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (
2423 TempFileName,
2424 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2425 FILE_SHARE_READ | FILE_SHARE_WRITE,
2426 NULL,
2427 OPEN_EXISTING,
2428 0,
2429 NULL
2430 );
2431 } else {
2432 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (
2433 TempFileName,
2434 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,
2435 FILE_SHARE_READ | FILE_SHARE_WRITE,
2436 NULL,
2437 OPEN_EXISTING,
2438 FILE_FLAG_BACKUP_SEMANTICS,
2439 NULL
2440 );
2441
2442 StrCat (TempFileName, L"\\*");
2443 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);
2444 }
2445
2446 FreePool (TempFileName);
2447
2448 goto Done;
2449
2450 }
2451 }
2452
2453 //
2454 // Size change
2455 //
2456 if (SizeChangeFlag) {
2457 if (PrivateFile->IsDirectoryPath) {
2458 Status = EFI_UNSUPPORTED;
2459 goto Done;
2460 }
2461
2462 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2463 Status = EFI_ACCESS_DENIED;
2464 goto Done;
2465 }
2466
2467 Status = This->GetPosition (This, &CurPos);
2468 if (EFI_ERROR (Status)) {
2469 goto Done;
2470 }
2471
2472 Status = This->SetPosition (This, NewFileInfo->FileSize);
2473 if (EFI_ERROR (Status)) {
2474 goto Done;
2475 }
2476
2477 if (PrivateFile->WinNtThunk->SetEndOfFile (PrivateFile->LHandle) == 0) {
2478 Status = EFI_DEVICE_ERROR;
2479 goto Done;
2480 }
2481
2482 Status = This->SetPosition (This, CurPos);
2483 if (EFI_ERROR (Status)) {
2484 goto Done;
2485 }
2486 }
2487
2488 //
2489 // Time change
2490 //
2491 if (TimeChangeFlag) {
2492
2493 NewCreationSystemTime.wYear = NewFileInfo->CreateTime.Year;
2494 NewCreationSystemTime.wMonth = NewFileInfo->CreateTime.Month;
2495 NewCreationSystemTime.wDay = NewFileInfo->CreateTime.Day;
2496 NewCreationSystemTime.wHour = NewFileInfo->CreateTime.Hour;
2497 NewCreationSystemTime.wMinute = NewFileInfo->CreateTime.Minute;
2498 NewCreationSystemTime.wSecond = NewFileInfo->CreateTime.Second;
2499 NewCreationSystemTime.wMilliseconds = 0;
2500
2501 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (
2502 &NewCreationSystemTime,
2503 &NewCreationFileTime
2504 )) {
2505 goto Done;
2506 }
2507
2508 NewLastAccessSystemTime.wYear = NewFileInfo->LastAccessTime.Year;
2509 NewLastAccessSystemTime.wMonth = NewFileInfo->LastAccessTime.Month;
2510 NewLastAccessSystemTime.wDay = NewFileInfo->LastAccessTime.Day;
2511 NewLastAccessSystemTime.wHour = NewFileInfo->LastAccessTime.Hour;
2512 NewLastAccessSystemTime.wMinute = NewFileInfo->LastAccessTime.Minute;
2513 NewLastAccessSystemTime.wSecond = NewFileInfo->LastAccessTime.Second;
2514 NewLastAccessSystemTime.wMilliseconds = 0;
2515
2516 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (
2517 &NewLastAccessSystemTime,
2518 &NewLastAccessFileTime
2519 )) {
2520 goto Done;
2521 }
2522
2523 NewLastWriteSystemTime.wYear = NewFileInfo->ModificationTime.Year;
2524 NewLastWriteSystemTime.wMonth = NewFileInfo->ModificationTime.Month;
2525 NewLastWriteSystemTime.wDay = NewFileInfo->ModificationTime.Day;
2526 NewLastWriteSystemTime.wHour = NewFileInfo->ModificationTime.Hour;
2527 NewLastWriteSystemTime.wMinute = NewFileInfo->ModificationTime.Minute;
2528 NewLastWriteSystemTime.wSecond = NewFileInfo->ModificationTime.Second;
2529 NewLastWriteSystemTime.wMilliseconds = 0;
2530
2531 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (
2532 &NewLastWriteSystemTime,
2533 &NewLastWriteFileTime
2534 )) {
2535 goto Done;
2536 }
2537
2538 if (!PrivateFile->WinNtThunk->SetFileTime (
2539 PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,
2540 &NewCreationFileTime,
2541 &NewLastAccessFileTime,
2542 &NewLastWriteFileTime
2543 )) {
2544 Status = EFI_DEVICE_ERROR;
2545 goto Done;
2546 }
2547
2548 }
2549
2550 //
2551 // No matter about AttrChangeFlag, Attribute must be set.
2552 // Because operation before may cause attribute change.
2553 //
2554 NewAttr = OldAttr;
2555
2556 if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) {
2557 NewAttr |= FILE_ATTRIBUTE_ARCHIVE;
2558 } else {
2559 NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE;
2560 }
2561
2562 if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) {
2563 NewAttr |= FILE_ATTRIBUTE_HIDDEN;
2564 } else {
2565 NewAttr &= ~FILE_ATTRIBUTE_HIDDEN;
2566 }
2567
2568 if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) {
2569 NewAttr |= FILE_ATTRIBUTE_SYSTEM;
2570 } else {
2571 NewAttr &= ~FILE_ATTRIBUTE_SYSTEM;
2572 }
2573
2574 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {
2575 NewAttr |= FILE_ATTRIBUTE_READONLY;
2576 } else {
2577 NewAttr &= ~FILE_ATTRIBUTE_READONLY;
2578 }
2579
2580 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (NewFileName, NewAttr);
2581
2582 if (!NtStatus) {
2583 goto Reopen;
2584 }
2585
2586 Done:
2587 if (OldFileInfo != NULL) {
2588 FreePool (OldFileInfo);
2589 }
2590
2591 if (OldFileName != NULL) {
2592 FreePool (OldFileName);
2593 }
2594
2595 if (NewFileName != NULL) {
2596 FreePool (NewFileName);
2597 }
2598
2599 gBS->RestoreTPL (OldTpl);
2600 return Status;
2601 }
2602
2603 EFI_STATUS
2604 EFIAPI
2605 WinNtSimpleFileSystemFlush (
2606 IN EFI_FILE *This
2607 )
2608 /*++
2609
2610 Routine Description:
2611
2612 Flush all modified data to the media.
2613
2614 Arguments:
2615
2616 This - Pointer to an opened file handle.
2617
2618 Returns:
2619
2620 EFI_SUCCESS - The data has been flushed.
2621
2622 EFI_NO_MEDIA - The device has no media.
2623
2624 EFI_DEVICE_ERROR - The device reported an error.
2625
2626 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.
2627
2628 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.
2629
2630 EFI_ACCESS_DENIED - The file was opened read-only.
2631
2632 EFI_VOLUME_FULL - The volume is full.
2633
2634 --*/
2635 // TODO: EFI_INVALID_PARAMETER - add return value to function comment
2636 {
2637 BY_HANDLE_FILE_INFORMATION FileInfo;
2638 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;
2639 EFI_STATUS Status;
2640 EFI_TPL OldTpl;
2641
2642 if (This == NULL) {
2643 return EFI_INVALID_PARAMETER;
2644 }
2645
2646 OldTpl = gBS->RaiseTPL (EFI_TPL_CALLBACK);
2647
2648 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);
2649
2650 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {
2651 Status = EFI_DEVICE_ERROR;
2652 goto Done;
2653 }
2654
2655 if (PrivateFile->IsDirectoryPath) {
2656 Status = EFI_SUCCESS;
2657 goto Done;
2658 }
2659
2660 if (PrivateFile->IsOpenedByRead) {
2661 Status = EFI_ACCESS_DENIED;
2662 goto Done;
2663 }
2664
2665 PrivateFile->WinNtThunk->GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo);
2666
2667 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {
2668 Status = EFI_ACCESS_DENIED;
2669 goto Done;
2670 }
2671
2672 Status = PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR;
2673
2674 Done:
2675 gBS->RestoreTPL (OldTpl);
2676 return Status;
2677 //
2678 // bugbug: - Use Windows error reporting.
2679 //
2680 }
2681
2682