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