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