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