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