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