]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/WinNtSimpleFileSystemDxe/WinNtSimpleFileSystem.c
fixed one bug causing "sct -u" failure when running at twice or more times.
[mirror_edk2.git] / Nt32Pkg / WinNtSimpleFileSystemDxe / WinNtSimpleFileSystem.c
CommitLineData
6ae81428 1/**@file\r
068eac81 2\r
9485089d 3Copyright (c) 2006 - 2009, 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
63941829 258 (VOID **) &WinNtIo,\r
068eac81 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
63941829 331 (VOID **) &WinNtIo,\r
068eac81 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
63941829 462 (VOID **) &SimpleFileSystem,\r
068eac81 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
a00ec39b 840 UINTN Size;\r
068eac81 841\r
842 //\r
843 // Check for obvious invalid parameters.\r
844 //\r
845 if (This == NULL || NewHandle == NULL || FileName == NULL) {\r
846 return EFI_INVALID_PARAMETER;\r
847 }\r
848\r
849 switch (OpenMode) {\r
850 case EFI_FILE_MODE_CREATE | EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
851 if (Attributes &~EFI_FILE_VALID_ATTR) {\r
852 return EFI_INVALID_PARAMETER;\r
853 }\r
854\r
855 if (Attributes & EFI_FILE_READ_ONLY) {\r
856 return EFI_INVALID_PARAMETER;\r
857 }\r
858\r
859 //\r
860 // fall through\r
861 //\r
862 case EFI_FILE_MODE_READ:\r
863 case EFI_FILE_MODE_READ | EFI_FILE_MODE_WRITE:\r
864 break;\r
865\r
866 default:\r
867 return EFI_INVALID_PARAMETER;\r
868 }\r
869\r
870 //\r
871 // Init local variables\r
872 //\r
873 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
874 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
875 NewPrivateFile = NULL;\r
876\r
877 //\r
878 // Allocate buffer for FileName as the passed in FileName may be read only\r
879 //\r
880 TempFileName = AllocatePool (StrSize (FileName));\r
881 if (TempFileName == NULL) {\r
882 return EFI_OUT_OF_RESOURCES;\r
883 }\r
884 StrCpy (TempFileName, FileName);\r
885 FileName = TempFileName;\r
886\r
887 //\r
888 // BUGBUG: assume an open of root\r
889 // if current location, return current data\r
890 //\r
891 if (StrCmp (FileName, L"\\") == 0 || (StrCmp (FileName, L".") == 0 && PrivateFile->IsRootDirectory)) {\r
892 //\r
893 // BUGBUG: assume an open root\r
894 //\r
895OpenRoot:\r
896 Status = WinNtSimpleFileSystemOpenVolume (PrivateFile->SimpleFileSystem, &Root);\r
897 NewPrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (Root);\r
898 goto Done;\r
899 }\r
900\r
901 if (FileName[StrLen (FileName) - 1] == L'\\') {\r
902 FileName[StrLen (FileName) - 1] = 0;\r
903 }\r
904\r
905 //\r
6a729dca 906 // If file name does not equal to "." or ".." and not trailed with "\..",\r
068eac81 907 // then we trim the leading/trailing blanks and trailing dots\r
908 //\r
6a729dca 909 if (StrCmp (FileName, L".") != 0 && StrCmp (FileName, L"..") != 0 && \r
910 ((StrLen (FileName) >= 3) ? (StrCmp (&FileName[StrLen (FileName) - 3], L"\\..") != 0) : TRUE)) {\r
068eac81 911 //\r
912 // Trim leading blanks\r
913 //\r
914 Count = 0;\r
915 for (TempFileName = FileName;\r
916 *TempFileName != 0 && *TempFileName == L' ';\r
917 TempFileName++) {\r
918 Count++;\r
919 }\r
920 CutPrefix (FileName, Count);\r
921 //\r
4d384084 922 // Trim trailing blanks\r
068eac81 923 //\r
924 for (TempFileName = FileName + StrLen (FileName) - 1;\r
4d384084 925 TempFileName >= FileName && (*TempFileName == L' ');\r
068eac81 926 TempFileName--) {\r
927 ;\r
928 }\r
929 *(TempFileName + 1) = 0;\r
930 }\r
931\r
932 //\r
933 // Attempt to open the file\r
934 //\r
935 NewPrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));\r
936 if (NewPrivateFile == NULL) {\r
937 Status = EFI_OUT_OF_RESOURCES;\r
938 goto Done;\r
939 }\r
940\r
941 CopyMem (NewPrivateFile, PrivateFile, sizeof (WIN_NT_EFI_FILE_PRIVATE));\r
942\r
943 NewPrivateFile->FilePath = AllocatePool (StrSize (PrivateFile->FileName));\r
944 if (NewPrivateFile->FilePath == NULL) {\r
945 Status = EFI_OUT_OF_RESOURCES;\r
946 goto Done;\r
947 }\r
948\r
949 if (PrivateFile->IsDirectoryPath) {\r
950 StrCpy (NewPrivateFile->FilePath, PrivateFile->FileName);\r
951 } else {\r
952 StrCpy (NewPrivateFile->FilePath, PrivateFile->FilePath);\r
953 }\r
954\r
a00ec39b 955 Size = StrSize (NewPrivateFile->FilePath);\r
956 Size += StrSize (L"\\");\r
957 Size += StrSize (FileName);\r
958 NewPrivateFile->FileName = AllocatePool (Size);\r
068eac81 959 if (NewPrivateFile->FileName == NULL) {\r
960 Status = EFI_OUT_OF_RESOURCES;\r
961 goto Done;\r
962 }\r
963\r
964 if (*FileName == L'\\') {\r
965 StrCpy (NewPrivateFile->FileName, PrivateRoot->FilePath);\r
966 StrCat (NewPrivateFile->FileName, L"\\");\r
967 StrCat (NewPrivateFile->FileName, FileName + 1);\r
968 } else {\r
969 StrCpy (NewPrivateFile->FileName, NewPrivateFile->FilePath);\r
970 if (StrCmp (FileName, L"") != 0) {\r
971 //\r
972 // In case the filename becomes empty, especially after trimming dots and blanks\r
973 //\r
974 StrCat (NewPrivateFile->FileName, L"\\");\r
975 StrCat (NewPrivateFile->FileName, FileName);\r
976 }\r
977 }\r
978\r
4d384084 979 if (!IsFileNameValid (NewPrivateFile->FileName)) {\r
980 Status = EFI_NOT_FOUND;\r
981 goto Done;\r
982 }\r
983\r
068eac81 984 //\r
985 // Get rid of . and .., except leading . or ..\r
986 //\r
987\r
988 //\r
989 // GuardPointer protect simplefilesystem root path not be destroyed\r
990 //\r
991 GuardPointer = NewPrivateFile->FileName + StrLen (PrivateRoot->FilePath);\r
992\r
993 LoopFinish = FALSE;\r
994\r
995 while (!LoopFinish) {\r
996\r
997 LoopFinish = TRUE;\r
998\r
999 for (ParseFileName = GuardPointer; *ParseFileName; ParseFileName++) {\r
1000 if (*ParseFileName == L'.' &&\r
1001 (*(ParseFileName + 1) == 0 || *(ParseFileName + 1) == L'\\') &&\r
1002 *(ParseFileName - 1) == L'\\'\r
1003 ) {\r
1004\r
1005 //\r
1006 // cut \.\r
1007 //\r
1008 CutPrefix (ParseFileName - 1, 2);\r
1009 LoopFinish = FALSE;\r
1010 break;\r
1011 }\r
1012\r
1013 if (*ParseFileName == L'.' &&\r
1014 *(ParseFileName + 1) == L'.' &&\r
1015 (*(ParseFileName + 2) == 0 || *(ParseFileName + 2) == L'\\') &&\r
1016 *(ParseFileName - 1) == L'\\'\r
1017 ) {\r
1018\r
1019 ParseFileName--;\r
1020 Count = 3;\r
1021\r
1022 while (ParseFileName != GuardPointer) {\r
1023 ParseFileName--;\r
1024 Count++;\r
1025 if (*ParseFileName == L'\\') {\r
1026 break;\r
1027 }\r
1028 }\r
1029\r
1030 //\r
1031 // cut \.. and its left directory\r
1032 //\r
1033 CutPrefix (ParseFileName, Count);\r
1034 LoopFinish = FALSE;\r
1035 break;\r
1036 }\r
1037 }\r
1038 }\r
1039\r
1040 if (StrCmp (NewPrivateFile->FileName, PrivateRoot->FilePath) == 0) {\r
1041 NewPrivateFile->IsRootDirectory = TRUE;\r
1042 FreePool (NewPrivateFile->FilePath);\r
1043 FreePool (NewPrivateFile->FileName);\r
1044 FreePool (NewPrivateFile);\r
1045 goto OpenRoot;\r
1046 }\r
1047\r
1048 RealFileName = NewPrivateFile->FileName;\r
1049 while (EfiStrChr (RealFileName, L'\\') != NULL) {\r
1050 RealFileName = EfiStrChr (RealFileName, L'\\') + 1;\r
1051 }\r
1052\r
1053 TempChar = *(RealFileName - 1);\r
1054 *(RealFileName - 1) = 0;\r
1055\r
1056 FreePool (NewPrivateFile->FilePath);\r
1057 NewPrivateFile->FilePath = NULL;\r
1058 NewPrivateFile->FilePath = AllocatePool (StrSize (NewPrivateFile->FileName));\r
1059 if (NewPrivateFile->FilePath == NULL) {\r
1060 Status = EFI_OUT_OF_RESOURCES;\r
1061 goto Done;\r
1062 }\r
1063\r
1064 StrCpy (NewPrivateFile->FilePath, NewPrivateFile->FileName);\r
1065\r
1066 *(RealFileName - 1) = TempChar;\r
1067\r
1068 NewPrivateFile->IsRootDirectory = FALSE;\r
1069\r
1070 //\r
1071 // Test whether file or directory\r
1072 //\r
1073 if (OpenMode & EFI_FILE_MODE_CREATE) {\r
1074 if (Attributes & EFI_FILE_DIRECTORY) {\r
1075 NewPrivateFile->IsDirectoryPath = TRUE;\r
1076 } else {\r
1077 NewPrivateFile->IsDirectoryPath = FALSE;\r
1078 }\r
1079 } else {\r
1080 NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
1081 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (\r
1082 NewPrivateFile->FileName,\r
1083 GENERIC_READ,\r
1084 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
1085 NULL,\r
1086 OPEN_EXISTING,\r
1087 0,\r
1088 NULL\r
1089 );\r
1090\r
1091 if (NewPrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
1092 NewPrivateFile->IsDirectoryPath = FALSE;\r
1093 NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->LHandle);\r
1094 } else {\r
1095 NewPrivateFile->IsDirectoryPath = TRUE;\r
1096 }\r
1097\r
1098 NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
1099 }\r
1100\r
1101 if (OpenMode & EFI_FILE_MODE_WRITE) {\r
1102 NewPrivateFile->IsOpenedByRead = FALSE;\r
1103 } else {\r
1104 NewPrivateFile->IsOpenedByRead = TRUE;\r
1105 }\r
1106\r
1107 Status = EFI_SUCCESS;\r
1108\r
1109 //\r
1110 // deal with directory\r
1111 //\r
1112 if (NewPrivateFile->IsDirectoryPath) {\r
1113\r
a00ec39b 1114 Size = StrSize (NewPrivateFile->FileName);\r
1115 Size += StrSize (L"\\*");\r
1116 TempFileName = AllocatePool (Size);\r
068eac81 1117 if (TempFileName == NULL) {\r
1118 Status = EFI_OUT_OF_RESOURCES;\r
1119 goto Done;\r
1120 }\r
1121\r
1122 StrCpy (TempFileName, NewPrivateFile->FileName);\r
1123\r
1124 if ((OpenMode & EFI_FILE_MODE_CREATE)) {\r
1125 //\r
1126 // Create a directory\r
1127 //\r
1128 if (!NewPrivateFile->WinNtThunk->CreateDirectory (TempFileName, NULL)) {\r
1129\r
1130 LastError = PrivateFile->WinNtThunk->GetLastError ();\r
1131 if (LastError != ERROR_ALREADY_EXISTS) {\r
1132 FreePool (TempFileName);\r
1133 Status = EFI_ACCESS_DENIED;\r
1134 goto Done;\r
1135 }\r
1136 }\r
1137 }\r
1138\r
1139 NewPrivateFile->DirHandle = NewPrivateFile->WinNtThunk->CreateFile (\r
1140 TempFileName,\r
1141 NewPrivateFile->IsOpenedByRead ? GENERIC_READ : (GENERIC_READ | GENERIC_WRITE),\r
1142 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
1143 NULL,\r
1144 OPEN_EXISTING,\r
1145 FILE_FLAG_BACKUP_SEMANTICS,\r
1146 NULL\r
1147 );\r
1148\r
1149 if (NewPrivateFile->DirHandle == INVALID_HANDLE_VALUE) {\r
1150\r
1151 NewPrivateFile->DirHandle = NewPrivateFile->WinNtThunk->CreateFile (\r
1152 TempFileName,\r
1153 GENERIC_READ,\r
1154 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
1155 NULL,\r
1156 OPEN_EXISTING,\r
1157 FILE_FLAG_BACKUP_SEMANTICS,\r
1158 NULL\r
1159 );\r
1160\r
1161 if (NewPrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
1162 NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->DirHandle);\r
1163 NewPrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
1164 Status = EFI_ACCESS_DENIED;\r
1165 } else {\r
1166 Status = EFI_NOT_FOUND;\r
1167 }\r
1168\r
1169 goto Done;\r
1170 }\r
1171\r
1172 //\r
1173 // Find the first file under it\r
1174 //\r
1175 StrCat (TempFileName, L"\\*");\r
1176 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->FindFirstFile (TempFileName, &NewPrivateFile->FindBuf);\r
1177\r
1178 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1179 NewPrivateFile->IsValidFindBuf = FALSE;\r
1180 } else {\r
1181 NewPrivateFile->IsValidFindBuf = TRUE;\r
1182 }\r
1183 } else {\r
1184 //\r
1185 // deal with file\r
1186 //\r
1187 if (!NewPrivateFile->IsOpenedByRead) {\r
1188 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (\r
1189 NewPrivateFile->FileName,\r
1190 GENERIC_READ | GENERIC_WRITE,\r
1191 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
1192 NULL,\r
1193 (OpenMode & EFI_FILE_MODE_CREATE) ? OPEN_ALWAYS : OPEN_EXISTING,\r
1194 0,\r
1195 NULL\r
1196 );\r
1197\r
1198 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1199 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (\r
1200 NewPrivateFile->FileName,\r
1201 GENERIC_READ,\r
1202 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
1203 NULL,\r
1204 OPEN_EXISTING,\r
1205 0,\r
1206 NULL\r
1207 );\r
1208\r
1209 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1210 Status = EFI_NOT_FOUND;\r
1211 } else {\r
1212 Status = EFI_ACCESS_DENIED;\r
1213 NewPrivateFile->WinNtThunk->CloseHandle (NewPrivateFile->LHandle);\r
1214 NewPrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
1215 }\r
1216 }\r
1217 } else {\r
1218 NewPrivateFile->LHandle = NewPrivateFile->WinNtThunk->CreateFile (\r
1219 NewPrivateFile->FileName,\r
1220 GENERIC_READ,\r
1221 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
1222 NULL,\r
1223 OPEN_EXISTING,\r
1224 0,\r
1225 NULL\r
1226 );\r
1227\r
1228 if (NewPrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1229 Status = EFI_NOT_FOUND;\r
1230 }\r
1231 }\r
1232 }\r
1233\r
1234 if ((OpenMode & EFI_FILE_MODE_CREATE) && Status == EFI_SUCCESS) {\r
1235 //\r
1236 // Set the attribute\r
1237 //\r
1238 InfoSize = 0;\r
1239 Info = NULL;\r
1240\r
1241 Status = WinNtSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
1242\r
1243 if (Status != EFI_BUFFER_TOO_SMALL) {\r
1244 Status = EFI_DEVICE_ERROR;\r
1245 goto Done;\r
1246 }\r
1247\r
1248 Info = AllocatePool (InfoSize);\r
1249 if (Info == NULL) {\r
1250 Status = EFI_OUT_OF_RESOURCES;\r
1251 goto Done;\r
1252 }\r
1253\r
1254 Status = WinNtSimpleFileSystemGetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, &InfoSize, Info);\r
1255\r
1256 if (EFI_ERROR (Status)) {\r
1257 goto Done;\r
1258 }\r
1259\r
1260 Info->Attribute = Attributes;\r
1261\r
1262 WinNtSimpleFileSystemSetInfo (&NewPrivateFile->EfiFile, &gEfiFileInfoGuid, InfoSize, Info);\r
1263 }\r
1264\r
6a729dca 1265Done:\r
068eac81 1266 FreePool (FileName);\r
1267\r
1268 if (EFI_ERROR (Status)) {\r
1269 if (NewPrivateFile) {\r
1270 if (NewPrivateFile->FileName) {\r
1271 FreePool (NewPrivateFile->FileName);\r
1272 }\r
1273\r
1274 if (NewPrivateFile->FilePath) {\r
1275 FreePool (NewPrivateFile->FilePath);\r
1276 }\r
1277\r
1278 FreePool (NewPrivateFile);\r
1279 }\r
1280 } else {\r
1281 *NewHandle = &NewPrivateFile->EfiFile;\r
1282 }\r
1283\r
1284 return Status;\r
1285}\r
1286\r
1287EFI_STATUS\r
1288EFIAPI\r
1289WinNtSimpleFileSystemClose (\r
1290 IN EFI_FILE *This\r
1291 )\r
1292/*++\r
1293\r
1294Routine Description:\r
1295\r
1296 Close the specified file handle.\r
1297\r
1298Arguments:\r
1299\r
1300 This - Pointer to a returned opened file handle.\r
1301\r
1302Returns:\r
1303\r
1304 EFI_SUCCESS - The file handle has been closed.\r
1305\r
1306--*/\r
1307// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1308{\r
1309 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1310 EFI_TPL OldTpl;\r
1311\r
1312 if (This == NULL) {\r
1313 return EFI_INVALID_PARAMETER;\r
1314 }\r
1315\r
1316 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1317\r
1318 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1319\r
1320 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
1321 if (PrivateFile->IsDirectoryPath) {\r
1322 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);\r
1323 } else {\r
1324 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);\r
1325 }\r
1326\r
1327 PrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
1328 }\r
1329\r
1330 if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
1331 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);\r
1332 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
1333 }\r
1334\r
1335 if (PrivateFile->FileName) {\r
1336 FreePool (PrivateFile->FileName);\r
1337 }\r
1338\r
1339 FreePool (PrivateFile);\r
1340\r
1341 gBS->RestoreTPL (OldTpl);\r
1342\r
1343 return EFI_SUCCESS;\r
1344}\r
1345\r
1346EFI_STATUS\r
1347EFIAPI\r
1348WinNtSimpleFileSystemDelete (\r
1349 IN EFI_FILE *This\r
1350 )\r
1351/*++\r
1352\r
1353Routine Description:\r
1354\r
1355 Close and delete a file.\r
1356\r
1357Arguments:\r
1358\r
1359 This - Pointer to a returned opened file handle.\r
1360\r
1361Returns:\r
1362\r
1363 EFI_SUCCESS - The file handle was closed and deleted.\r
1364\r
1365 EFI_WARN_DELETE_FAILURE - The handle was closed but could not be deleted.\r
1366\r
1367--*/\r
1368// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1369{\r
1370 EFI_STATUS Status;\r
1371 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1372 EFI_TPL OldTpl;\r
1373\r
1374 if (This == NULL) {\r
1375 return EFI_INVALID_PARAMETER;\r
1376 }\r
1377\r
1378 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1379\r
1380 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1381\r
1382 Status = EFI_WARN_DELETE_FAILURE;\r
1383\r
1384 if (PrivateFile->IsDirectoryPath) {\r
1385 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
1386 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);\r
1387 }\r
1388\r
1389 if (PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
1390 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);\r
1391 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
1392 }\r
1393\r
1394 if (PrivateFile->WinNtThunk->RemoveDirectory (PrivateFile->FileName)) {\r
1395 Status = EFI_SUCCESS;\r
1396 }\r
1397 } else {\r
1398 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);\r
1399 PrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
1400\r
1401 if (!PrivateFile->IsOpenedByRead) {\r
1402 if (PrivateFile->WinNtThunk->DeleteFile (PrivateFile->FileName)) {\r
1403 Status = EFI_SUCCESS;\r
1404 }\r
1405 }\r
1406 }\r
1407\r
1408 FreePool (PrivateFile->FileName);\r
1409 FreePool (PrivateFile);\r
1410\r
1411 gBS->RestoreTPL (OldTpl);\r
1412\r
1413 return Status;\r
1414}\r
1415\r
068eac81 1416VOID\r
1417WinNtSystemTimeToEfiTime (\r
1418 IN SYSTEMTIME *SystemTime,\r
1419 IN TIME_ZONE_INFORMATION *TimeZone,\r
1420 OUT EFI_TIME *Time\r
1421 )\r
1422/*++\r
1423\r
1424Routine Description:\r
1425\r
1426 TODO: Add function description\r
1427\r
1428Arguments:\r
1429\r
1430 SystemTime - TODO: add argument description\r
1431 TimeZone - TODO: add argument description\r
1432 Time - TODO: add argument description\r
1433\r
1434Returns:\r
1435\r
1436 TODO: add return values\r
1437\r
1438--*/\r
1439{\r
1440 Time->Year = (UINT16) SystemTime->wYear;\r
1441 Time->Month = (UINT8) SystemTime->wMonth;\r
1442 Time->Day = (UINT8) SystemTime->wDay;\r
1443 Time->Hour = (UINT8) SystemTime->wHour;\r
1444 Time->Minute = (UINT8) SystemTime->wMinute;\r
1445 Time->Second = (UINT8) SystemTime->wSecond;\r
1446 Time->Nanosecond = (UINT32) SystemTime->wMilliseconds * 1000000;\r
1447 Time->TimeZone = (INT16) TimeZone->Bias;\r
1448\r
1449 if (TimeZone->StandardDate.wMonth) {\r
1450 Time->Daylight = EFI_TIME_ADJUST_DAYLIGHT;\r
1451 }\r
1452}\r
1453\r
1454EFI_STATUS\r
1455EFIAPI\r
1456WinNtSimpleFileSystemRead (\r
1457 IN EFI_FILE *This,\r
1458 IN OUT UINTN *BufferSize,\r
1459 OUT VOID *Buffer\r
1460 )\r
1461/*++\r
1462\r
1463Routine Description:\r
1464\r
1465 Read data from a file.\r
1466\r
1467Arguments:\r
1468\r
1469 This - Pointer to a returned open file handle.\r
1470\r
1471 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.\r
1472\r
1473 Buffer - Pointer to the first byte of the read Buffer.\r
1474\r
1475Returns:\r
1476\r
1477 EFI_SUCCESS - The data was read.\r
1478\r
1479 EFI_NO_MEDIA - The device has no media.\r
1480\r
1481 EFI_DEVICE_ERROR - The device reported an error.\r
1482\r
1483 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
1484\r
1485 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.\r
1486 *BufferSize has been updated with the size needed to complete the request.\r
1487\r
1488--*/\r
1489// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1490{\r
1491 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1492 EFI_STATUS Status;\r
1493 UINTN Size;\r
1494 UINTN NameSize;\r
1495 UINTN ResultSize;\r
1496 UINTN Index;\r
1497 SYSTEMTIME SystemTime;\r
1498 EFI_FILE_INFO *Info;\r
1499 WCHAR *pw;\r
1500 TIME_ZONE_INFORMATION TimeZone;\r
1501 EFI_FILE_INFO *FileInfo;\r
1502 UINT64 Pos;\r
1503 UINT64 FileSize;\r
1504 UINTN FileInfoSize;\r
1505 EFI_TPL OldTpl;\r
1506\r
1507 if (This == NULL || BufferSize == NULL) {\r
1508 return EFI_INVALID_PARAMETER;\r
1509 }\r
1510\r
1511 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1512\r
1513 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1514\r
1515 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1516 Status = EFI_DEVICE_ERROR;\r
1517 goto Done;\r
1518 }\r
1519\r
1520 if (!PrivateFile->IsDirectoryPath) {\r
1521\r
1522 if (This->GetPosition (This, &Pos) != EFI_SUCCESS) {\r
1523 Status = EFI_DEVICE_ERROR;\r
1524 goto Done;\r
1525 }\r
1526\r
1527 FileInfoSize = SIZE_OF_EFI_FILE_SYSTEM_INFO;\r
1528 FileInfo = AllocatePool (FileInfoSize);\r
1529\r
1530 Status = This->GetInfo (\r
1531 This,\r
1532 &gEfiFileInfoGuid,\r
1533 &FileInfoSize,\r
1534 FileInfo\r
1535 );\r
1536\r
1537 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1538 FreePool (FileInfo);\r
1539 FileInfo = AllocatePool (FileInfoSize);\r
1540 Status = This->GetInfo (\r
1541 This,\r
1542 &gEfiFileInfoGuid,\r
1543 &FileInfoSize,\r
1544 FileInfo\r
1545 );\r
1546 }\r
1547\r
1548 if (EFI_ERROR (Status)) {\r
1549 Status = EFI_DEVICE_ERROR;\r
1550 goto Done;\r
1551 }\r
1552\r
1553 FileSize = FileInfo->FileSize;\r
1554\r
1555 FreePool (FileInfo);\r
1556\r
1557 if (Pos >= FileSize) {\r
1558 *BufferSize = 0;\r
1559 if (Pos == FileSize) {\r
1560 Status = EFI_SUCCESS;\r
1561 goto Done;\r
1562 } else {\r
1563 Status = EFI_DEVICE_ERROR;\r
1564 goto Done;\r
1565 }\r
1566 }\r
1567\r
1568 Status = PrivateFile->WinNtThunk->ReadFile (\r
a00ec39b 1569 PrivateFile->LHandle,\r
1570 Buffer,\r
1571 *BufferSize,\r
1572 (LPDWORD)BufferSize,\r
1573 NULL\r
1574 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
068eac81 1575 goto Done;\r
1576 }\r
1577\r
1578 //\r
1579 // Read on a directory. Perform a find next\r
1580 //\r
1581 if (!PrivateFile->IsValidFindBuf) {\r
1582 *BufferSize = 0;\r
1583 Status = EFI_SUCCESS;\r
1584 goto Done;\r
1585 }\r
1586\r
1587 Size = SIZE_OF_EFI_FILE_INFO;\r
1588\r
1589 NameSize = StrSize (PrivateFile->FindBuf.cFileName);\r
1590\r
1591 ResultSize = Size + NameSize;\r
1592\r
1593 Status = EFI_BUFFER_TOO_SMALL;\r
1594\r
1595 if (*BufferSize >= ResultSize) {\r
1596 Status = EFI_SUCCESS;\r
1597\r
1598 Info = Buffer;\r
1599 ZeroMem (Info, ResultSize);\r
1600\r
1601 Info->Size = ResultSize;\r
1602\r
1603 PrivateFile->WinNtThunk->GetTimeZoneInformation (&TimeZone);\r
1604\r
1605 PrivateFile->WinNtThunk->FileTimeToLocalFileTime (\r
1606 &PrivateFile->FindBuf.ftCreationTime,\r
1607 &PrivateFile->FindBuf.ftCreationTime\r
1608 );\r
1609\r
1610 PrivateFile->WinNtThunk->FileTimeToSystemTime (&PrivateFile->FindBuf.ftCreationTime, &SystemTime);\r
1611\r
1612 WinNtSystemTimeToEfiTime (&SystemTime, &TimeZone, &Info->CreateTime);\r
1613\r
1614 PrivateFile->WinNtThunk->FileTimeToLocalFileTime (\r
1615 &PrivateFile->FindBuf.ftLastWriteTime,\r
1616 &PrivateFile->FindBuf.ftLastWriteTime\r
1617 );\r
1618\r
1619 PrivateFile->WinNtThunk->FileTimeToSystemTime (&PrivateFile->FindBuf.ftLastWriteTime, &SystemTime);\r
1620\r
1621 WinNtSystemTimeToEfiTime (&SystemTime, &TimeZone, &Info->ModificationTime);\r
1622\r
1623 Info->FileSize = PrivateFile->FindBuf.nFileSizeLow;\r
1624\r
1625 Info->PhysicalSize = PrivateFile->FindBuf.nFileSizeLow;\r
1626\r
1627 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {\r
1628 Info->Attribute |= EFI_FILE_ARCHIVE;\r
1629 }\r
1630\r
1631 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {\r
1632 Info->Attribute |= EFI_FILE_HIDDEN;\r
1633 }\r
1634\r
1635 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {\r
1636 Info->Attribute |= EFI_FILE_SYSTEM;\r
1637 }\r
1638\r
1639 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
1640 Info->Attribute |= EFI_FILE_READ_ONLY;\r
1641 }\r
1642\r
1643 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\r
1644 Info->Attribute |= EFI_FILE_DIRECTORY;\r
1645 }\r
1646\r
1647 NameSize = NameSize / sizeof (WCHAR);\r
1648\r
1649 pw = (WCHAR *) (((CHAR8 *) Buffer) + Size);\r
1650\r
1651 for (Index = 0; Index < NameSize; Index++) {\r
1652 pw[Index] = PrivateFile->FindBuf.cFileName[Index];\r
1653 }\r
1654\r
1655 if (PrivateFile->WinNtThunk->FindNextFile (PrivateFile->LHandle, &PrivateFile->FindBuf)) {\r
1656 PrivateFile->IsValidFindBuf = TRUE;\r
1657 } else {\r
1658 PrivateFile->IsValidFindBuf = FALSE;\r
1659 }\r
1660 }\r
1661\r
1662 *BufferSize = ResultSize;\r
1663\r
1664Done:\r
1665 gBS->RestoreTPL (OldTpl);\r
1666 return Status;\r
1667}\r
1668\r
1669EFI_STATUS\r
1670EFIAPI\r
1671WinNtSimpleFileSystemWrite (\r
1672 IN EFI_FILE *This,\r
1673 IN OUT UINTN *BufferSize,\r
1674 IN VOID *Buffer\r
1675 )\r
1676/*++\r
1677\r
1678Routine Description:\r
1679\r
1680 Write data to a file.\r
1681\r
1682Arguments:\r
1683\r
1684 This - Pointer to an opened file handle.\r
1685\r
1686 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes\r
1687 of data written to the file.\r
1688\r
1689 Buffer - Pointer to the first by of data in the buffer to write to the file.\r
1690\r
1691Returns:\r
1692\r
1693 EFI_SUCCESS - The data was written to the file.\r
1694\r
1695 EFI_UNSUPPORTED - Writes to an open directory are not supported.\r
1696\r
1697 EFI_NO_MEDIA - The device has no media.\r
1698\r
1699 EFI_DEVICE_ERROR - The device reported an error.\r
1700\r
1701 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1702\r
1703 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1704\r
1705 EFI_ACCESS_DENIED - The file was opened read-only.\r
1706\r
1707 EFI_VOLUME_FULL - The volume is full.\r
1708\r
1709--*/\r
1710// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1711{\r
1712 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1713 EFI_STATUS Status;\r
1714 EFI_TPL OldTpl;\r
1715\r
1716 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1717 return EFI_INVALID_PARAMETER;\r
1718 }\r
1719\r
1720 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1721\r
1722 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1723\r
1724 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1725 Status = EFI_DEVICE_ERROR;\r
1726 goto Done;\r
1727 }\r
1728\r
1729 if (PrivateFile->IsDirectoryPath) {\r
1730 Status = EFI_UNSUPPORTED;\r
1731 goto Done;\r
1732 }\r
1733\r
1734 if (PrivateFile->IsOpenedByRead) {\r
1735 Status = EFI_ACCESS_DENIED;\r
1736 goto Done;\r
1737 }\r
1738\r
1739 Status = PrivateFile->WinNtThunk->WriteFile (\r
a00ec39b 1740 PrivateFile->LHandle,\r
1741 Buffer,\r
1742 *BufferSize,\r
1743 (LPDWORD)BufferSize,\r
1744 NULL\r
1745 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
068eac81 1746\r
1747Done:\r
1748 gBS->RestoreTPL (OldTpl);\r
1749 return Status;\r
1750\r
1751 //\r
1752 // bugbug: need to access windows error reporting\r
1753 //\r
1754}\r
1755\r
1756EFI_STATUS\r
1757EFIAPI\r
1758WinNtSimpleFileSystemSetPosition (\r
1759 IN EFI_FILE *This,\r
1760 IN UINT64 Position\r
1761 )\r
1762/*++\r
1763\r
1764Routine Description:\r
1765\r
1766 Set a file's current position.\r
1767\r
1768Arguments:\r
1769\r
1770 This - Pointer to an opened file handle.\r
1771\r
1772 Position - The byte position from the start of the file to set.\r
1773\r
1774Returns:\r
1775\r
1776 EFI_SUCCESS - The file position has been changed.\r
1777\r
1778 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.\r
1779\r
1780--*/\r
1781// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1782{\r
1783 EFI_STATUS Status;\r
1784 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1785 UINT32 PosLow;\r
1786 UINT32 PosHigh;\r
1787 CHAR16 *FileName;\r
1788 EFI_TPL OldTpl;\r
a00ec39b 1789 UINTN Size;\r
068eac81 1790\r
1791 if (This == NULL) {\r
1792 return EFI_INVALID_PARAMETER;\r
1793 }\r
1794\r
1795 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1796\r
1797 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1798\r
1799 if (PrivateFile->IsDirectoryPath) {\r
1800 if (Position != 0) {\r
1801 Status = EFI_UNSUPPORTED;\r
1802 goto Done;\r
1803 }\r
1804\r
a00ec39b 1805 Size = StrSize (PrivateFile->FileName);\r
1806 Size += StrSize (L"\\*");\r
1807 FileName = AllocatePool (Size);\r
068eac81 1808 if (FileName == NULL) {\r
1809 Status = EFI_OUT_OF_RESOURCES;\r
1810 goto Done;\r
1811 }\r
1812\r
1813 StrCpy (FileName, PrivateFile->FileName);\r
1814 StrCat (FileName, L"\\*");\r
1815\r
1816 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
1817 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);\r
1818 }\r
1819\r
1820 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (FileName, &PrivateFile->FindBuf);\r
1821\r
1822 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1823 PrivateFile->IsValidFindBuf = FALSE;\r
1824 } else {\r
1825 PrivateFile->IsValidFindBuf = TRUE;\r
1826 }\r
1827\r
1828 FreePool (FileName);\r
1829\r
1830 Status = (PrivateFile->LHandle == INVALID_HANDLE_VALUE) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1831 } else {\r
1832 if (Position == (UINT64) -1) {\r
1833 PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) 0, NULL, FILE_END);\r
1834 } else {\r
1835 PosHigh = (UINT32) RShiftU64 (Position, 32);\r
1836\r
a00ec39b 1837 PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) Position, (PLONG)&PosHigh, FILE_BEGIN);\r
068eac81 1838 }\r
1839\r
1840 Status = (PosLow == 0xFFFFFFFF) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1841 }\r
1842\r
1843Done:\r
1844 gBS->RestoreTPL (OldTpl);\r
1845 return Status;\r
1846}\r
1847\r
1848EFI_STATUS\r
1849EFIAPI\r
1850WinNtSimpleFileSystemGetPosition (\r
1851 IN EFI_FILE *This,\r
1852 OUT UINT64 *Position\r
1853 )\r
1854/*++\r
1855\r
1856Routine Description:\r
1857\r
1858 Get a file's current position.\r
1859\r
1860Arguments:\r
1861\r
1862 This - Pointer to an opened file handle.\r
1863\r
1864 Position - Pointer to storage for the current position.\r
1865\r
1866Returns:\r
1867\r
1868 EFI_SUCCESS - The file position has been reported.\r
1869\r
1870 EFI_UNSUPPORTED - Not valid for directories.\r
1871\r
1872--*/\r
1873// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1874{\r
1875 EFI_STATUS Status;\r
1876 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1877 INT32 PositionHigh;\r
1878 UINT64 PosHigh64;\r
1879 EFI_TPL OldTpl;\r
1880\r
1881 if (This == NULL || Position == NULL) {\r
1882 return EFI_INVALID_PARAMETER;\r
1883 }\r
1884\r
1885 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1886 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1887\r
1888 PositionHigh = 0;\r
1889 PosHigh64 = 0;\r
1890\r
1891 if (PrivateFile->IsDirectoryPath) {\r
1892\r
1893 Status = EFI_UNSUPPORTED;\r
1894 goto Done;\r
1895\r
1896 } else {\r
1897\r
1898 PositionHigh = 0;\r
1899 *Position = PrivateFile->WinNtThunk->SetFilePointer (\r
a00ec39b 1900 PrivateFile->LHandle,\r
1901 0,\r
1902 (PLONG)&PositionHigh,\r
1903 FILE_CURRENT\r
1904 );\r
068eac81 1905\r
1906 Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1907 if (EFI_ERROR (Status)) {\r
1908 goto Done;\r
1909 }\r
1910\r
1911 PosHigh64 = PositionHigh;\r
1912 *Position += LShiftU64 (PosHigh64, 32);\r
1913 }\r
1914\r
1915Done:\r
1916 gBS->RestoreTPL (OldTpl);\r
1917 return Status;\r
1918}\r
1919\r
068eac81 1920EFI_STATUS\r
1921WinNtSimpleFileSystemFileInfo (\r
1922 IN WIN_NT_EFI_FILE_PRIVATE *PrivateFile,\r
1923 IN OUT UINTN *BufferSize,\r
1924 OUT VOID *Buffer\r
1925 )\r
1926/*++\r
1927\r
1928Routine Description:\r
1929\r
1930 TODO: Add function description\r
1931\r
1932Arguments:\r
1933\r
1934 PrivateFile - TODO: add argument description\r
1935 BufferSize - TODO: add argument description\r
1936 Buffer - TODO: add argument description\r
1937\r
1938Returns:\r
1939\r
1940 TODO: add return values\r
1941\r
1942--*/\r
1943{\r
1944 EFI_STATUS Status;\r
1945 UINTN Size;\r
1946 UINTN NameSize;\r
1947 UINTN ResultSize;\r
1948 EFI_FILE_INFO *Info;\r
1949 BY_HANDLE_FILE_INFORMATION FileInfo;\r
1950 SYSTEMTIME SystemTime;\r
1951 CHAR16 *RealFileName;\r
1952 CHAR16 *TempPointer;\r
1953 EFI_FILE_INFO *DirInfo;\r
1954 UINTN ReadSize;\r
1955 UINT64 Location;\r
1956 EFI_STATUS DirStatus;\r
1957\r
1958\r
1959 Size = SIZE_OF_EFI_FILE_INFO;\r
1960 NameSize = StrSize (PrivateFile->FileName);\r
1961 ResultSize = Size + NameSize;\r
1962\r
1963 Status = EFI_BUFFER_TOO_SMALL;\r
1964 if (*BufferSize >= ResultSize) {\r
1965 Status = EFI_SUCCESS;\r
1966\r
1967 Info = Buffer;\r
1968 ZeroMem (Info, ResultSize);\r
1969\r
1970 Info->Size = ResultSize;\r
1971 PrivateFile->WinNtThunk->GetFileInformationByHandle (\r
1972 PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,\r
1973 &FileInfo\r
1974 );\r
1975 Info->FileSize = FileInfo.nFileSizeLow;\r
1976 Info->PhysicalSize = Info->FileSize;\r
1977\r
1978 PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftCreationTime, &SystemTime);\r
1979 Info->CreateTime.Year = SystemTime.wYear;\r
1980 Info->CreateTime.Month = (UINT8) SystemTime.wMonth;\r
1981 Info->CreateTime.Day = (UINT8) SystemTime.wDay;\r
1982 Info->CreateTime.Hour = (UINT8) SystemTime.wHour;\r
1983 Info->CreateTime.Minute = (UINT8) SystemTime.wMinute;\r
1984 Info->CreateTime.Second = (UINT8) SystemTime.wSecond;\r
1985\r
1986 PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftLastAccessTime, &SystemTime);\r
1987 Info->LastAccessTime.Year = SystemTime.wYear;\r
1988 Info->LastAccessTime.Month = (UINT8) SystemTime.wMonth;\r
1989 Info->LastAccessTime.Day = (UINT8) SystemTime.wDay;\r
1990 Info->LastAccessTime.Hour = (UINT8) SystemTime.wHour;\r
1991 Info->LastAccessTime.Minute = (UINT8) SystemTime.wMinute;\r
1992 Info->LastAccessTime.Second = (UINT8) SystemTime.wSecond;\r
1993\r
1994 PrivateFile->WinNtThunk->FileTimeToSystemTime (&FileInfo.ftLastWriteTime, &SystemTime);\r
1995 Info->ModificationTime.Year = SystemTime.wYear;\r
1996 Info->ModificationTime.Month = (UINT8) SystemTime.wMonth;\r
1997 Info->ModificationTime.Day = (UINT8) SystemTime.wDay;\r
1998 Info->ModificationTime.Hour = (UINT8) SystemTime.wHour;\r
1999 Info->ModificationTime.Minute = (UINT8) SystemTime.wMinute;\r
2000 Info->ModificationTime.Second = (UINT8) SystemTime.wSecond;\r
2001\r
2002 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {\r
2003 Info->Attribute |= EFI_FILE_ARCHIVE;\r
2004 }\r
2005\r
2006 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {\r
2007 Info->Attribute |= EFI_FILE_HIDDEN;\r
2008 }\r
2009\r
2010 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
2011 Info->Attribute |= EFI_FILE_READ_ONLY;\r
2012 }\r
2013\r
2014 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {\r
2015 Info->Attribute |= EFI_FILE_SYSTEM;\r
2016 }\r
2017\r
2018 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\r
2019 Info->Attribute |= EFI_FILE_DIRECTORY;\r
2020 }\r
2021\r
2022 if (PrivateFile->IsDirectoryPath) {\r
2023 Info->Attribute |= EFI_FILE_DIRECTORY;\r
2024 }\r
2025\r
2026 RealFileName = PrivateFile->FileName;\r
2027 TempPointer = RealFileName;\r
2028\r
2029 while (*TempPointer) {\r
2030 if (*TempPointer == '\\') {\r
2031 RealFileName = TempPointer + 1;\r
2032 }\r
2033\r
2034 TempPointer++;\r
2035 }\r
2036\r
2037 if (PrivateFile->IsRootDirectory) {\r
2038 *((CHAR8 *) Buffer + Size) = 0;\r
2039 } else {\r
2040 CopyMem ((CHAR8 *) Buffer + Size, RealFileName, NameSize);\r
2041 }\r
2042\r
2043 if (Info->Attribute & EFI_FILE_DIRECTORY) {\r
2044 //\r
2045 // The GetFileInformationByHandle.nFileSizeLow is bogus for dir so we \r
2046 // need to do the same thing the caller would do to get the right value\r
2047 //\r
2048 ASSERT (PrivateFile->EfiFile.Read != NULL);\r
2049 DirStatus = PrivateFile->EfiFile.GetPosition (&PrivateFile->EfiFile, &Location);\r
2050 if (EFI_ERROR (DirStatus)) {\r
2051 Location = 0;\r
2052 }\r
2053\r
2054 PrivateFile->EfiFile.SetPosition (&PrivateFile->EfiFile, 0);\r
2055 Info->FileSize = 0; \r
2056 do {\r
2057 ReadSize = 0;\r
2058 DirInfo = NULL;\r
2059 DirStatus = PrivateFile->EfiFile.Read (&PrivateFile->EfiFile, &ReadSize, DirInfo);\r
2060 if (DirStatus == EFI_BUFFER_TOO_SMALL) {\r
2061 DirInfo = AllocatePool (ReadSize);\r
2062 if (DirInfo != NULL) {\r
2063 //\r
2064 // Read each dir entry to figure out how big the directory is\r
2065 //\r
2066 DirStatus = PrivateFile->EfiFile.Read (&PrivateFile->EfiFile, &ReadSize, DirInfo);\r
2067 if (!EFI_ERROR (DirStatus) && (ReadSize != 0)) {\r
2068 Info->FileSize += ReadSize;\r
2069 }\r
2070 FreePool (DirInfo);\r
2071 }\r
2072 }\r
2073 \r
2074 } while (!EFI_ERROR (DirStatus) && (ReadSize != 0));\r
2075\r
2076 //\r
2077 // reset the file possition back to the previous location\r
2078 //\r
2079 PrivateFile->EfiFile.SetPosition (&PrivateFile->EfiFile, Location);\r
2080 }\r
2081 }\r
2082\r
2083 *BufferSize = ResultSize;\r
2084 return Status;\r
2085}\r
2086\r
2087EFI_STATUS\r
2088EFIAPI\r
2089WinNtSimpleFileSystemGetInfo (\r
2090 IN EFI_FILE *This,\r
2091 IN EFI_GUID *InformationType,\r
2092 IN OUT UINTN *BufferSize,\r
2093 OUT VOID *Buffer\r
2094 )\r
2095/*++\r
2096\r
2097Routine Description:\r
2098\r
2099 Return information about a file or volume.\r
2100\r
2101Arguments:\r
2102\r
2103 This - Pointer to an opened file handle.\r
2104\r
2105 InformationType - GUID describing the type of information to be returned.\r
2106\r
2107 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the\r
2108 information buffer.\r
2109\r
2110 Buffer - Pointer to the first byte of the information buffer.\r
2111\r
2112Returns:\r
2113\r
2114 EFI_SUCCESS - The requested information has been written into the buffer.\r
2115\r
2116 EFI_UNSUPPORTED - The InformationType is not known.\r
2117\r
2118 EFI_NO_MEDIA - The device has no media.\r
2119\r
2120 EFI_DEVICE_ERROR - The device reported an error.\r
2121\r
2122 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
2123\r
2124 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has\r
2125 been updated with the size needed to complete the requested operation.\r
2126\r
2127--*/\r
2128// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2129{\r
2130 EFI_STATUS Status;\r
2131 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
2132 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;\r
2133 UINT32 SectorsPerCluster;\r
2134 UINT32 BytesPerSector;\r
2135 UINT32 FreeClusters;\r
2136 UINT32 TotalClusters;\r
2137 UINT32 BytesPerCluster;\r
2138 CHAR16 *DriveName;\r
2139 BOOLEAN DriveNameFound;\r
2140 BOOL NtStatus;\r
2141 UINTN Index;\r
2142 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
2143 EFI_TPL OldTpl;\r
2144\r
2145 if (This == NULL || InformationType == NULL || BufferSize == NULL) {\r
2146 return EFI_INVALID_PARAMETER;\r
2147 }\r
2148\r
2149 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
2150\r
2151 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2152 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
2153\r
2154 Status = EFI_UNSUPPORTED;\r
2155\r
2156 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
2157 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);\r
2158 }\r
2159\r
2160 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
2161 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
2162 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
2163 Status = EFI_BUFFER_TOO_SMALL;\r
2164 goto Done;\r
2165 }\r
2166\r
2167 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
2168 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
2169 FileSystemInfoBuffer->ReadOnly = FALSE;\r
2170\r
2171 //\r
2172 // Try to get the drive name\r
2173 //\r
2174 DriveNameFound = FALSE;\r
2175 DriveName = AllocatePool (StrSize (PrivateFile->FilePath) + 1);\r
2176 if (DriveName == NULL) {\r
2177 Status = EFI_OUT_OF_RESOURCES;\r
2178 goto Done;\r
2179 }\r
2180\r
2181 StrCpy (DriveName, PrivateFile->FilePath);\r
2182 for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) {\r
2183 ;\r
2184 }\r
2185\r
2186 if (DriveName[Index] == ':') {\r
2187 DriveName[Index + 1] = '\\';\r
2188 DriveName[Index + 2] = 0;\r
2189 DriveNameFound = TRUE;\r
2190 } else if (DriveName[0] == '\\' && DriveName[1] == '\\') {\r
2191 for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {\r
2192 ;\r
2193 }\r
2194\r
2195 if (DriveName[Index] == '\\') {\r
2196 DriveNameFound = TRUE;\r
2197 for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {\r
2198 ;\r
2199 }\r
2200\r
2201 DriveName[Index] = '\\';\r
2202 DriveName[Index + 1] = 0;\r
2203 }\r
2204 }\r
2205\r
2206 //\r
2207 // Try GetDiskFreeSpace first\r
2208 //\r
2209 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpace (\r
2210 DriveNameFound ? DriveName : NULL,\r
a00ec39b 2211 (LPDWORD)&SectorsPerCluster,\r
2212 (LPDWORD)&BytesPerSector,\r
2213 (LPDWORD)&FreeClusters,\r
2214 (LPDWORD)&TotalClusters\r
068eac81 2215 );\r
2216 if (DriveName) {\r
2217 FreePool (DriveName);\r
2218 }\r
2219\r
2220 if (NtStatus) {\r
2221 //\r
2222 // Succeeded\r
2223 //\r
2224 BytesPerCluster = BytesPerSector * SectorsPerCluster;\r
2225 FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster);\r
2226 FileSystemInfoBuffer->FreeSpace = MultU64x32 (FreeClusters, BytesPerCluster);\r
2227 FileSystemInfoBuffer->BlockSize = BytesPerCluster;\r
2228\r
2229 } else {\r
2230 //\r
2231 // try GetDiskFreeSpaceEx then\r
2232 //\r
2233 FileSystemInfoBuffer->BlockSize = 0;\r
2234 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpaceEx (\r
2235 PrivateFile->FilePath,\r
2236 (PULARGE_INTEGER) (&FileSystemInfoBuffer->FreeSpace),\r
2237 (PULARGE_INTEGER) (&FileSystemInfoBuffer->VolumeSize),\r
2238 NULL\r
2239 );\r
2240 if (!NtStatus) {\r
2241 Status = EFI_DEVICE_ERROR;\r
2242 goto Done;\r
2243 }\r
2244 }\r
2245\r
2246 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);\r
2247 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
2248 Status = EFI_SUCCESS;\r
2249 }\r
2250\r
2251 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
2252 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
2253 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
2254 Status = EFI_BUFFER_TOO_SMALL;\r
2255 goto Done;\r
2256 }\r
2257\r
2258 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);\r
2259 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
2260 Status = EFI_SUCCESS;\r
2261 }\r
2262\r
2263Done:\r
2264 gBS->RestoreTPL (OldTpl);\r
2265 return Status;\r
2266}\r
2267\r
2268EFI_STATUS\r
2269EFIAPI\r
2270WinNtSimpleFileSystemSetInfo (\r
2271 IN EFI_FILE *This,\r
2272 IN EFI_GUID *InformationType,\r
2273 IN UINTN BufferSize,\r
2274 IN VOID *Buffer\r
2275 )\r
2276/*++\r
2277\r
2278Routine Description:\r
2279\r
2280 Set information about a file or volume.\r
2281\r
2282Arguments:\r
2283\r
2284 This - Pointer to an opened file handle.\r
2285\r
2286 InformationType - GUID identifying the type of information to set.\r
2287\r
2288 BufferSize - Number of bytes of data in the information buffer.\r
2289\r
2290 Buffer - Pointer to the first byte of data in the information buffer.\r
2291\r
2292Returns:\r
2293\r
2294 EFI_SUCCESS - The file or volume information has been updated.\r
2295\r
2296 EFI_UNSUPPORTED - The information identifier is not recognised.\r
2297\r
2298 EFI_NO_MEDIA - The device has no media.\r
2299\r
2300 EFI_DEVICE_ERROR - The device reported an error.\r
2301\r
2302 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
2303\r
2304 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
2305\r
2306 EFI_ACCESS_DENIED - The file was opened read-only.\r
2307\r
2308 EFI_VOLUME_FULL - The volume is full.\r
2309\r
2310 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.\r
2311\r
2312--*/\r
2313// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2314// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2315{\r
2316 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
2317 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
2318 EFI_FILE_INFO *OldFileInfo;\r
2319 EFI_FILE_INFO *NewFileInfo;\r
2320 EFI_STATUS Status;\r
2321 UINTN OldInfoSize;\r
2322 INTN NtStatus;\r
2323 UINT32 NewAttr;\r
2324 UINT32 OldAttr;\r
2325 CHAR16 *OldFileName;\r
2326 CHAR16 *NewFileName;\r
2327 CHAR16 *TempFileName;\r
2328 CHAR16 *CharPointer;\r
2329 BOOLEAN AttrChangeFlag;\r
2330 BOOLEAN NameChangeFlag;\r
2331 BOOLEAN SizeChangeFlag;\r
2332 BOOLEAN TimeChangeFlag;\r
2333 UINT64 CurPos;\r
2334 SYSTEMTIME NewCreationSystemTime;\r
2335 SYSTEMTIME NewLastAccessSystemTime;\r
2336 SYSTEMTIME NewLastWriteSystemTime;\r
2337 FILETIME NewCreationFileTime;\r
2338 FILETIME NewLastAccessFileTime;\r
2339 FILETIME NewLastWriteFileTime;\r
2340 WIN32_FIND_DATA FindBuf;\r
2341 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;\r
2342 EFI_TPL OldTpl;\r
a00ec39b 2343 UINTN Size;\r
068eac81 2344\r
2345 //\r
2346 // Check for invalid parameters.\r
2347 //\r
2348 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {\r
2349 return EFI_INVALID_PARAMETER;\r
2350 }\r
2351\r
2352 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
2353\r
2354 //\r
2355 // Initialise locals.\r
2356 //\r
2357 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2358 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
2359\r
2360 Status = EFI_UNSUPPORTED;\r
2361 OldFileInfo = NewFileInfo = NULL;\r
2362 OldFileName = NewFileName = NULL;\r
2363 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;\r
2364\r
2365 //\r
2366 // Set file system information.\r
2367 //\r
2368 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
2369 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
2370 Status = EFI_BAD_BUFFER_SIZE;\r
2371 goto Done;\r
2372 }\r
2373\r
2374 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
2375\r
2376 FreePool (PrivateRoot->VolumeLabel);\r
2377 PrivateRoot->VolumeLabel = AllocatePool (StrSize (NewFileSystemInfo->VolumeLabel));\r
2378 if (PrivateRoot->VolumeLabel == NULL) {\r
2379 Status = EFI_OUT_OF_RESOURCES;\r
2380 goto Done;\r
2381 }\r
2382\r
2383 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);\r
2384\r
2385 Status = EFI_SUCCESS;\r
2386 goto Done;\r
2387 }\r
2388\r
2389 //\r
2390 // Set volume label information.\r
2391 //\r
2392 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
2393 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
2394 Status = EFI_BAD_BUFFER_SIZE;\r
2395 goto Done;\r
2396 }\r
2397\r
2398 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);\r
2399\r
2400 Status = EFI_SUCCESS;\r
2401 goto Done;\r
2402 }\r
2403\r
2404 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
2405 Status = EFI_UNSUPPORTED;\r
2406 goto Done;\r
2407 }\r
2408\r
2409 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {\r
2410 Status = EFI_BAD_BUFFER_SIZE;\r
2411 goto Done;\r
2412 }\r
2413\r
2414 //\r
2415 // Set file/directory information.\r
2416 //\r
2417\r
2418 //\r
2419 // Check for invalid set file information parameters.\r
2420 //\r
2421 NewFileInfo = (EFI_FILE_INFO *) Buffer;\r
2422\r
2423 if (NewFileInfo->Size <= sizeof (EFI_FILE_INFO) ||\r
2424 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||\r
2425 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)\r
2426 ) {\r
2427 Status = EFI_INVALID_PARAMETER;\r
2428 goto Done;\r
2429 }\r
2430\r
2431 //\r
2432 // bugbug: - This is not safe. We need something like EfiStrMaxSize()\r
2433 // that would have an additional parameter that would be the size\r
2434 // of the string array just in case there are no NULL characters in\r
2435 // the string array.\r
2436 //\r
2437 //\r
2438 // Get current file information so we can determine what kind\r
2439 // of change request this is.\r
2440 //\r
2441 OldInfoSize = 0;\r
2442 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL);\r
2443\r
2444 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2445 Status = EFI_DEVICE_ERROR;\r
2446 goto Done;\r
2447 }\r
2448\r
2449 OldFileInfo = AllocatePool (OldInfoSize);\r
2450 if (OldFileInfo == NULL) {\r
2451 Status = EFI_OUT_OF_RESOURCES;\r
2452 goto Done;\r
2453 }\r
2454\r
2455 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo);\r
2456\r
2457 if (EFI_ERROR (Status)) {\r
2458 goto Done;\r
2459 }\r
2460\r
2461 OldFileName = AllocatePool (StrSize (PrivateFile->FileName));\r
2462 if (OldFileName == NULL) {\r
2463 Status = EFI_OUT_OF_RESOURCES;\r
2464 goto Done;\r
2465 }\r
2466\r
2467 StrCpy (OldFileName, PrivateFile->FileName);\r
2468\r
2469 //\r
2470 // Make full pathname from new filename and rootpath.\r
2471 //\r
a00ec39b 2472 if (NewFileInfo->FileName[0] == '\\') {\r
9485089d 2473 Size = StrSize (PrivateRoot->FilePath);\r
2474 Size += StrSize (L"\\");\r
2475 Size += StrSize (NewFileInfo->FileName);\r
2476 NewFileName = AllocatePool (Size);\r
2477 if (NewFileName == NULL) {\r
2478 Status = EFI_OUT_OF_RESOURCES;\r
2479 goto Done;\r
2480 }\r
2481\r
2482 StrCpy (NewFileName, PrivateRoot->FilePath);\r
2483 StrCat (NewFileName, L"\\");\r
068eac81 2484 StrCat (NewFileName, NewFileInfo->FileName + 1);\r
2485 } else {\r
9485089d 2486 Size = StrSize (PrivateFile->FilePath);\r
2487 Size += StrSize (L"\\");\r
2488 Size += StrSize (NewFileInfo->FileName);\r
2489 NewFileName = AllocatePool (Size);\r
2490 if (NewFileName == NULL) {\r
2491 Status = EFI_OUT_OF_RESOURCES;\r
2492 goto Done;\r
2493 }\r
2494\r
2495 StrCpy (NewFileName, PrivateFile->FilePath);\r
2496 StrCat (NewFileName, L"\\");\r
068eac81 2497 StrCat (NewFileName, NewFileInfo->FileName);\r
2498 }\r
2499\r
2500 //\r
2501 // Is there an attribute change request?\r
2502 //\r
2503 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {\r
2504 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
2505 Status = EFI_INVALID_PARAMETER;\r
2506 goto Done;\r
2507 }\r
2508\r
2509 AttrChangeFlag = TRUE;\r
2510 }\r
2511\r
2512 //\r
2513 // Is there a name change request?\r
2514 // bugbug: - Need EfiStrCaseCmp()\r
2515 //\r
2516 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {\r
2517 NameChangeFlag = TRUE;\r
2518 }\r
2519\r
2520 //\r
2521 // Is there a size change request?\r
2522 //\r
2523 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {\r
2524 SizeChangeFlag = TRUE;\r
2525 }\r
2526\r
2527 //\r
2528 // Is there a time stamp change request?\r
2529 //\r
2530 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&\r
2531 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))\r
2532 ) {\r
2533 TimeChangeFlag = TRUE;\r
2534 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&\r
2535 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))\r
2536 ) {\r
2537 TimeChangeFlag = TRUE;\r
2538 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&\r
2539 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))\r
2540 ) {\r
2541 TimeChangeFlag = TRUE;\r
2542 }\r
2543\r
2544 //\r
2545 // All done if there are no change requests being made.\r
2546 //\r
2547 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {\r
2548 Status = EFI_SUCCESS;\r
2549 goto Done;\r
2550 }\r
2551\r
2552 //\r
2553 // Set file or directory information.\r
2554 //\r
2555 OldAttr = PrivateFile->WinNtThunk->GetFileAttributes (OldFileName);\r
2556\r
2557 //\r
2558 // Name change.\r
2559 //\r
2560 if (NameChangeFlag) {\r
2561 //\r
2562 // Close the handles first\r
2563 //\r
2564 if (PrivateFile->IsOpenedByRead) {\r
2565 Status = EFI_ACCESS_DENIED;\r
2566 goto Done;\r
2567 }\r
2568\r
2569 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {\r
2570 }\r
2571\r
2572 if (*CharPointer != 0) {\r
2573 Status = EFI_ACCESS_DENIED;\r
2574 goto Done;\r
2575 }\r
2576\r
2577 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
2578 if (PrivateFile->IsDirectoryPath) {\r
2579 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);\r
2580 } else {\r
2581 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);\r
2582 PrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
2583 }\r
2584 }\r
2585\r
2586 if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
2587 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);\r
2588 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
2589 }\r
2590\r
2591 NtStatus = PrivateFile->WinNtThunk->MoveFile (OldFileName, NewFileName);\r
2592\r
2593 if (NtStatus) {\r
2594 //\r
2595 // modify file name\r
2596 //\r
2597 FreePool (PrivateFile->FileName);\r
2598\r
2599 PrivateFile->FileName = AllocatePool (StrSize (NewFileName));\r
2600 if (PrivateFile->FileName == NULL) {\r
2601 Status = EFI_OUT_OF_RESOURCES;\r
2602 goto Done;\r
2603 }\r
2604\r
2605 StrCpy (PrivateFile->FileName, NewFileName);\r
2606\r
a00ec39b 2607 Size = StrSize (NewFileName);\r
2608 Size += StrSize (L"\\*");\r
2609 TempFileName = AllocatePool (Size);\r
068eac81 2610\r
2611 StrCpy (TempFileName, NewFileName);\r
2612\r
2613 if (!PrivateFile->IsDirectoryPath) {\r
2614 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (\r
2615 TempFileName,\r
2616 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2617 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2618 NULL,\r
2619 OPEN_EXISTING,\r
2620 0,\r
2621 NULL\r
2622 );\r
2623\r
2624 FreePool (TempFileName);\r
2625\r
2626 //\r
2627 // Flush buffers just in case\r
2628 //\r
2629 if (PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) == 0) {\r
2630 Status = EFI_DEVICE_ERROR;\r
2631 goto Done;\r
2632 }\r
2633 } else {\r
2634 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (\r
2635 TempFileName,\r
2636 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2637 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2638 NULL,\r
2639 OPEN_EXISTING,\r
2640 FILE_FLAG_BACKUP_SEMANTICS,\r
2641 NULL\r
2642 );\r
2643\r
2644 StrCat (TempFileName, L"\\*");\r
2645 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);\r
2646\r
2647 FreePool (TempFileName);\r
2648 }\r
2649 } else {\r
2650Reopen: ;\r
2651 Status = EFI_DEVICE_ERROR;\r
2652\r
2653 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (OldFileName, OldAttr);\r
2654\r
2655 if (!NtStatus) {\r
2656 goto Done;\r
2657 }\r
2658\r
a00ec39b 2659 Size = StrSize (OldFileName);\r
2660 Size += StrSize (L"\\*");\r
2661 TempFileName = AllocatePool (Size);\r
068eac81 2662\r
2663 StrCpy (TempFileName, OldFileName);\r
2664\r
2665 if (!PrivateFile->IsDirectoryPath) {\r
2666 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (\r
2667 TempFileName,\r
2668 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2669 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2670 NULL,\r
2671 OPEN_EXISTING,\r
2672 0,\r
2673 NULL\r
2674 );\r
2675 } else {\r
2676 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (\r
2677 TempFileName,\r
2678 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2679 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2680 NULL,\r
2681 OPEN_EXISTING,\r
2682 FILE_FLAG_BACKUP_SEMANTICS,\r
2683 NULL\r
2684 );\r
2685\r
2686 StrCat (TempFileName, L"\\*");\r
2687 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);\r
2688 }\r
2689\r
2690 FreePool (TempFileName);\r
2691\r
2692 goto Done;\r
2693\r
2694 }\r
2695 }\r
2696\r
2697 //\r
2698 // Size change\r
2699 //\r
2700 if (SizeChangeFlag) {\r
2701 if (PrivateFile->IsDirectoryPath) {\r
2702 Status = EFI_UNSUPPORTED;\r
2703 goto Done;\r
2704 }\r
2705\r
2706 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2707 Status = EFI_ACCESS_DENIED;\r
2708 goto Done;\r
2709 }\r
2710\r
2711 Status = This->GetPosition (This, &CurPos);\r
2712 if (EFI_ERROR (Status)) {\r
2713 goto Done;\r
2714 }\r
2715\r
2716 Status = This->SetPosition (This, NewFileInfo->FileSize);\r
2717 if (EFI_ERROR (Status)) {\r
2718 goto Done;\r
2719 }\r
2720\r
2721 if (PrivateFile->WinNtThunk->SetEndOfFile (PrivateFile->LHandle) == 0) {\r
2722 Status = EFI_DEVICE_ERROR;\r
2723 goto Done;\r
2724 }\r
2725\r
2726 Status = This->SetPosition (This, CurPos);\r
2727 if (EFI_ERROR (Status)) {\r
2728 goto Done;\r
2729 }\r
2730 }\r
2731\r
2732 //\r
2733 // Time change\r
2734 //\r
2735 if (TimeChangeFlag) {\r
2736\r
2737 NewCreationSystemTime.wYear = NewFileInfo->CreateTime.Year;\r
2738 NewCreationSystemTime.wMonth = NewFileInfo->CreateTime.Month;\r
2739 NewCreationSystemTime.wDay = NewFileInfo->CreateTime.Day;\r
2740 NewCreationSystemTime.wHour = NewFileInfo->CreateTime.Hour;\r
2741 NewCreationSystemTime.wMinute = NewFileInfo->CreateTime.Minute;\r
2742 NewCreationSystemTime.wSecond = NewFileInfo->CreateTime.Second;\r
2743 NewCreationSystemTime.wMilliseconds = 0;\r
2744\r
2745 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (\r
2746 &NewCreationSystemTime,\r
2747 &NewCreationFileTime\r
2748 )) {\r
2749 goto Done;\r
2750 }\r
2751\r
2752 NewLastAccessSystemTime.wYear = NewFileInfo->LastAccessTime.Year;\r
2753 NewLastAccessSystemTime.wMonth = NewFileInfo->LastAccessTime.Month;\r
2754 NewLastAccessSystemTime.wDay = NewFileInfo->LastAccessTime.Day;\r
2755 NewLastAccessSystemTime.wHour = NewFileInfo->LastAccessTime.Hour;\r
2756 NewLastAccessSystemTime.wMinute = NewFileInfo->LastAccessTime.Minute;\r
2757 NewLastAccessSystemTime.wSecond = NewFileInfo->LastAccessTime.Second;\r
2758 NewLastAccessSystemTime.wMilliseconds = 0;\r
2759\r
2760 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (\r
2761 &NewLastAccessSystemTime,\r
2762 &NewLastAccessFileTime\r
2763 )) {\r
2764 goto Done;\r
2765 }\r
2766\r
2767 NewLastWriteSystemTime.wYear = NewFileInfo->ModificationTime.Year;\r
2768 NewLastWriteSystemTime.wMonth = NewFileInfo->ModificationTime.Month;\r
2769 NewLastWriteSystemTime.wDay = NewFileInfo->ModificationTime.Day;\r
2770 NewLastWriteSystemTime.wHour = NewFileInfo->ModificationTime.Hour;\r
2771 NewLastWriteSystemTime.wMinute = NewFileInfo->ModificationTime.Minute;\r
2772 NewLastWriteSystemTime.wSecond = NewFileInfo->ModificationTime.Second;\r
2773 NewLastWriteSystemTime.wMilliseconds = 0;\r
2774\r
2775 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (\r
2776 &NewLastWriteSystemTime,\r
2777 &NewLastWriteFileTime\r
2778 )) {\r
2779 goto Done;\r
2780 }\r
2781\r
2782 if (!PrivateFile->WinNtThunk->SetFileTime (\r
2783 PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,\r
2784 &NewCreationFileTime,\r
2785 &NewLastAccessFileTime,\r
2786 &NewLastWriteFileTime\r
2787 )) {\r
2788 Status = EFI_DEVICE_ERROR;\r
2789 goto Done;\r
2790 }\r
2791\r
2792 }\r
2793\r
2794 //\r
2795 // No matter about AttrChangeFlag, Attribute must be set.\r
2796 // Because operation before may cause attribute change.\r
2797 //\r
2798 NewAttr = OldAttr;\r
2799\r
2800 if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) {\r
2801 NewAttr |= FILE_ATTRIBUTE_ARCHIVE;\r
2802 } else {\r
2803 NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE;\r
2804 }\r
2805\r
2806 if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) {\r
2807 NewAttr |= FILE_ATTRIBUTE_HIDDEN;\r
2808 } else {\r
2809 NewAttr &= ~FILE_ATTRIBUTE_HIDDEN;\r
2810 }\r
2811\r
2812 if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) {\r
2813 NewAttr |= FILE_ATTRIBUTE_SYSTEM;\r
2814 } else {\r
2815 NewAttr &= ~FILE_ATTRIBUTE_SYSTEM;\r
2816 }\r
2817\r
2818 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2819 NewAttr |= FILE_ATTRIBUTE_READONLY;\r
2820 } else {\r
2821 NewAttr &= ~FILE_ATTRIBUTE_READONLY;\r
2822 }\r
2823\r
2824 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (NewFileName, NewAttr);\r
2825\r
2826 if (!NtStatus) {\r
2827 goto Reopen;\r
2828 }\r
2829\r
2830Done:\r
2831 if (OldFileInfo != NULL) {\r
2832 FreePool (OldFileInfo);\r
2833 }\r
2834\r
2835 if (OldFileName != NULL) {\r
2836 FreePool (OldFileName);\r
2837 }\r
2838\r
2839 if (NewFileName != NULL) {\r
2840 FreePool (NewFileName);\r
2841 }\r
2842\r
2843 gBS->RestoreTPL (OldTpl);\r
2844 return Status;\r
2845}\r
2846\r
2847EFI_STATUS\r
2848EFIAPI\r
2849WinNtSimpleFileSystemFlush (\r
2850 IN EFI_FILE *This\r
2851 )\r
2852/*++\r
2853\r
2854Routine Description:\r
2855\r
2856 Flush all modified data to the media.\r
2857\r
2858Arguments:\r
2859\r
2860 This - Pointer to an opened file handle.\r
2861\r
2862Returns:\r
2863\r
2864 EFI_SUCCESS - The data has been flushed.\r
2865\r
2866 EFI_NO_MEDIA - The device has no media.\r
2867\r
2868 EFI_DEVICE_ERROR - The device reported an error.\r
2869\r
2870 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.\r
2871\r
2872 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
2873\r
2874 EFI_ACCESS_DENIED - The file was opened read-only.\r
2875\r
2876 EFI_VOLUME_FULL - The volume is full.\r
2877\r
2878--*/\r
2879// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2880{\r
2881 BY_HANDLE_FILE_INFORMATION FileInfo;\r
2882 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
2883 EFI_STATUS Status;\r
2884 EFI_TPL OldTpl;\r
2885\r
2886 if (This == NULL) {\r
2887 return EFI_INVALID_PARAMETER;\r
2888 }\r
2889\r
2890 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
2891\r
2892 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2893\r
2894 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
2895 Status = EFI_DEVICE_ERROR;\r
2896 goto Done;\r
2897 }\r
2898\r
2899 if (PrivateFile->IsDirectoryPath) {\r
2900 Status = EFI_SUCCESS;\r
2901 goto Done;\r
2902 }\r
2903\r
2904 if (PrivateFile->IsOpenedByRead) {\r
2905 Status = EFI_ACCESS_DENIED;\r
2906 goto Done;\r
2907 }\r
2908\r
2909 PrivateFile->WinNtThunk->GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo);\r
2910\r
2911 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
2912 Status = EFI_ACCESS_DENIED;\r
2913 goto Done;\r
2914 }\r
2915\r
2916 Status = PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
2917\r
2918Done:\r
2919 gBS->RestoreTPL (OldTpl);\r
2920 return Status;\r
2921 //\r
2922 // bugbug: - Use Windows error reporting.\r
2923 //\r
2924}\r
2925\r
2926\r