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