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