]> git.proxmox.com Git - mirror_edk2.git/blame - Nt32Pkg/WinNtSimpleFileSystemDxe/WinNtSimpleFileSystem.c
Nt32Pkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / Nt32Pkg / WinNtSimpleFileSystemDxe / WinNtSimpleFileSystem.c
CommitLineData
6ae81428 1/**@file\r
068eac81 2\r
462a3eba 3Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.<BR>\r
9d2eedba 4SPDX-License-Identifier: BSD-2-Clause-Patent\r
068eac81 5\r
6Module Name:\r
7\r
8 WinNtSimpleFileSystem.c\r
9\r
10Abstract:\r
11\r
12 Produce Simple File System abstractions for directories on your PC using Win32 APIs.\r
13 The configuration of what devices to mount or emulate comes from NT\r
14 environment variables. The variables must be visible to the Microsoft*\r
15 Developer Studio for them to work.\r
16\r
17 * Other names and brands may be claimed as the property of others.\r
18\r
6ae81428 19**/\r
068eac81 20\r
21//\r
22// The package level header files this module uses\r
23//\r
24#include <Uefi.h>\r
25#include <WinNtDxe.h>\r
26//\r
27// The protocols, PPI and GUID defintions for this module\r
28//\r
29#include <Guid/FileSystemVolumeLabelInfo.h>\r
30#include <Protocol/WinNtIo.h>\r
31#include <Protocol/ComponentName.h>\r
32#include <Guid/FileInfo.h>\r
33#include <Protocol/DriverBinding.h>\r
34#include <Guid/FileSystemInfo.h>\r
35#include <Protocol/SimpleFileSystem.h>\r
36//\r
37// The Library classes this module consumes\r
38//\r
39#include <Library/DebugLib.h>\r
40#include <Library/BaseLib.h>\r
41#include <Library/UefiDriverEntryPoint.h>\r
42#include <Library/UefiLib.h>\r
43#include <Library/BaseMemoryLib.h>\r
44#include <Library/UefiBootServicesTableLib.h>\r
45#include <Library/MemoryAllocationLib.h>\r
46\r
47#include "WinNtSimpleFileSystem.h"\r
48\r
49EFI_DRIVER_BINDING_PROTOCOL gWinNtSimpleFileSystemDriverBinding = {\r
50 WinNtSimpleFileSystemDriverBindingSupported,\r
51 WinNtSimpleFileSystemDriverBindingStart,\r
52 WinNtSimpleFileSystemDriverBindingStop,\r
53 0xa,\r
54 NULL,\r
55 NULL\r
56};\r
57\r
58/**\r
59 The user Entry Point for module WinNtSimpleFileSystem. The user code starts with this function.\r
60\r
61 @param[in] ImageHandle The firmware allocated handle for the EFI image. \r
62 @param[in] SystemTable A pointer to the EFI System Table.\r
63 \r
64 @retval EFI_SUCCESS The entry point is executed successfully.\r
65 @retval other Some error occurs when executing this entry point.\r
66\r
67**/\r
68EFI_STATUS\r
69EFIAPI\r
70InitializeWinNtSimpleFileSystem(\r
71 IN EFI_HANDLE ImageHandle,\r
72 IN EFI_SYSTEM_TABLE *SystemTable\r
73 )\r
74{\r
75 EFI_STATUS Status;\r
76\r
77 //\r
78 // Install driver model protocol(s).\r
79 //\r
6c28f118 80 Status = EfiLibInstallDriverBindingComponentName2 (\r
068eac81 81 ImageHandle,\r
82 SystemTable,\r
83 &gWinNtSimpleFileSystemDriverBinding,\r
84 ImageHandle,\r
85 &gWinNtSimpleFileSystemComponentName,\r
6c28f118 86 &gWinNtSimpleFileSystemComponentName2\r
068eac81 87 );\r
88 ASSERT_EFI_ERROR (Status);\r
89\r
90\r
91 return Status;\r
92}\r
93\r
94CHAR16 *\r
95EfiStrChr (\r
96 IN CHAR16 *Str,\r
97 IN CHAR16 Chr\r
98 )\r
99/*++\r
100\r
101Routine Description:\r
102\r
103 Locate the first occurance of a character in a string.\r
104\r
105Arguments:\r
106\r
107 Str - Pointer to NULL terminated unicode string.\r
108 Chr - Character to locate.\r
109\r
110Returns:\r
111\r
112 If Str is NULL, then NULL is returned.\r
113 If Chr is not contained in Str, then NULL is returned.\r
114 If Chr is contained in Str, then a pointer to the first occurance of Chr in Str is returned.\r
115\r
116--*/\r
117{\r
118 if (Str == NULL) {\r
119 return Str;\r
120 }\r
121\r
122 while (*Str != '\0' && *Str != Chr) {\r
123 ++Str;\r
124 }\r
125\r
126 return (*Str == Chr) ? Str : NULL;\r
127}\r
128\r
129BOOLEAN\r
130IsZero (\r
131 IN VOID *Buffer,\r
132 IN UINTN Length\r
133 )\r
134/*++\r
135\r
136Routine Description:\r
137\r
138 TODO: Add function description\r
139\r
140Arguments:\r
141\r
142 Buffer - TODO: add argument description\r
143 Length - TODO: add argument description\r
144\r
145Returns:\r
146\r
147 TODO: add return values\r
148\r
149--*/\r
150{\r
151 if (Buffer == NULL || Length == 0) {\r
152 return FALSE;\r
153 }\r
154\r
155 if (*(UINT8 *) Buffer != 0) {\r
156 return FALSE;\r
157 }\r
158\r
159 if (Length > 1) {\r
160 if (!CompareMem (Buffer, (UINT8 *) Buffer + 1, Length - 1)) {\r
161 return FALSE;\r
162 }\r
163 }\r
164\r
165 return TRUE;\r
166}\r
167\r
168VOID\r
169CutPrefix (\r
170 IN CHAR16 *Str,\r
171 IN UINTN Count\r
172 )\r
173/*++\r
174\r
175Routine Description:\r
176\r
177 TODO: Add function description\r
178\r
179Arguments:\r
180\r
181 Str - TODO: add argument description\r
182 Count - TODO: add argument description\r
183\r
184Returns:\r
185\r
186 TODO: add return values\r
187\r
188--*/\r
189{\r
190 CHAR16 *Pointer;\r
191\r
192 if (StrLen (Str) < Count) {\r
193 ASSERT (0);\r
194 }\r
195\r
196 if (Count != 0) {\r
197 for (Pointer = Str; *(Pointer + Count); Pointer++) {\r
198 *Pointer = *(Pointer + Count);\r
199 }\r
200 *Pointer = *(Pointer + Count);\r
201 }\r
202}\r
203\r
204\r
205\r
206EFI_STATUS\r
207EFIAPI\r
208WinNtSimpleFileSystemDriverBindingSupported (\r
209 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
210 IN EFI_HANDLE ControllerHandle,\r
211 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
212 )\r
213/*++\r
214\r
215Routine Description:\r
216\r
217 Check to see if the driver supports a given controller.\r
218\r
219Arguments:\r
220\r
221 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
222\r
223 ControllerHandle - EFI handle of the controller to test.\r
224\r
225 RemainingDevicePath - Pointer to remaining portion of a device path.\r
226\r
227Returns:\r
228\r
229 EFI_SUCCESS - The device specified by ControllerHandle and RemainingDevicePath is supported by the driver\r
230 specified by This.\r
231\r
232 EFI_ALREADY_STARTED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by\r
233 the driver specified by This.\r
234\r
235 EFI_ACCESS_DENIED - The device specified by ControllerHandle and RemainingDevicePath is already being managed by\r
236 a different driver or an application that requires exclusive access.\r
237\r
238 EFI_UNSUPPORTED - The device specified by ControllerHandle and RemainingDevicePath is not supported by the\r
239 driver specified by This.\r
240\r
241--*/\r
242{\r
243 EFI_STATUS Status;\r
244 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
245\r
246 //\r
247 // Open the IO Abstraction(s) needed to perform the supported test\r
248 //\r
249 Status = gBS->OpenProtocol (\r
250 ControllerHandle,\r
251 &gEfiWinNtIoProtocolGuid,\r
63941829 252 (VOID **) &WinNtIo,\r
068eac81 253 This->DriverBindingHandle,\r
254 ControllerHandle,\r
255 EFI_OPEN_PROTOCOL_BY_DRIVER\r
256 );\r
257 if (EFI_ERROR (Status)) {\r
258 return Status;\r
259 }\r
260\r
261 //\r
262 // Make sure GUID is for a File System handle.\r
263 //\r
264 Status = EFI_UNSUPPORTED;\r
265 if (CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtFileSystemGuid)) {\r
266 Status = EFI_SUCCESS;\r
267 }\r
268\r
269 //\r
270 // Close the I/O Abstraction(s) used to perform the supported test\r
271 //\r
272 gBS->CloseProtocol (\r
273 ControllerHandle,\r
274 &gEfiWinNtIoProtocolGuid,\r
275 This->DriverBindingHandle,\r
276 ControllerHandle\r
277 );\r
278\r
279 return Status;\r
280}\r
281\r
282EFI_STATUS\r
283EFIAPI\r
284WinNtSimpleFileSystemDriverBindingStart (\r
285 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
286 IN EFI_HANDLE ControllerHandle,\r
287 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
288 )\r
289/*++\r
290\r
291Routine Description:\r
292\r
293 Starts a device controller or a bus controller.\r
294\r
295Arguments:\r
296\r
297 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
298\r
299 ControllerHandle - EFI handle of the controller to start.\r
300\r
301 RemainingDevicePath - Pointer to remaining portion of a device path.\r
302\r
303Returns:\r
304\r
305 EFI_SUCCESS - The device or bus controller has been started.\r
306\r
307 EFI_DEVICE_ERROR - The device could not be started due to a device failure.\r
308\r
309 EFI_OUT_OF_RESOURCES - The request could not be completed due to lack of resources.\r
310\r
311--*/\r
312{\r
313 EFI_STATUS Status;\r
314 EFI_WIN_NT_IO_PROTOCOL *WinNtIo;\r
315 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
316\r
317 Private = NULL;\r
318\r
319 //\r
320 // Open the IO Abstraction(s) needed\r
321 //\r
322 Status = gBS->OpenProtocol (\r
323 ControllerHandle,\r
324 &gEfiWinNtIoProtocolGuid,\r
63941829 325 (VOID **) &WinNtIo,\r
068eac81 326 This->DriverBindingHandle,\r
327 ControllerHandle,\r
328 EFI_OPEN_PROTOCOL_BY_DRIVER\r
329 );\r
330 if (EFI_ERROR (Status)) {\r
331 return Status;\r
332 }\r
333\r
334 //\r
335 // Validate GUID\r
336 //\r
337 if (!CompareGuid (WinNtIo->TypeGuid, &gEfiWinNtFileSystemGuid)) {\r
338 Status = EFI_UNSUPPORTED;\r
339 goto Done;\r
340 }\r
341\r
342 Private = AllocatePool (sizeof (WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE));\r
343 if (Private == NULL) {\r
344 Status = EFI_OUT_OF_RESOURCES;\r
345\r
346 goto Done;\r
347 }\r
348\r
349 Private->Signature = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_SIGNATURE;\r
350 Private->WinNtThunk = WinNtIo->WinNtThunk;\r
351\r
352 Private->FilePath = WinNtIo->EnvString;\r
353\r
354 Private->VolumeLabel = AllocatePool (StrSize (L"EFI_EMULATED"));\r
355 if (Private->VolumeLabel == NULL) {\r
356 Status = EFI_OUT_OF_RESOURCES;\r
357 goto Done;\r
358 }\r
359\r
360 StrCpy (Private->VolumeLabel, L"EFI_EMULATED");\r
361\r
362 Private->SimpleFileSystem.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;\r
363 Private->SimpleFileSystem.OpenVolume = WinNtSimpleFileSystemOpenVolume;\r
364\r
365 Private->WinNtThunk->SetErrorMode (SEM_FAILCRITICALERRORS);\r
366\r
367 Private->ControllerNameTable = NULL;\r
368\r
6c28f118 369 AddUnicodeString2 (\r
068eac81 370 "eng",\r
371 gWinNtSimpleFileSystemComponentName.SupportedLanguages,\r
372 &Private->ControllerNameTable,\r
6c28f118 373 WinNtIo->EnvString,\r
374 TRUE\r
068eac81 375 );\r
6c28f118 376 AddUnicodeString2 (\r
377 "en",\r
378 gWinNtSimpleFileSystemComponentName2.SupportedLanguages,\r
379 &Private->ControllerNameTable,\r
380 WinNtIo->EnvString,\r
381 FALSE\r
382 );\r
383\r
068eac81 384\r
385 Status = gBS->InstallMultipleProtocolInterfaces (\r
386 &ControllerHandle,\r
387 &gEfiSimpleFileSystemProtocolGuid,\r
388 &Private->SimpleFileSystem,\r
389 NULL\r
390 );\r
391\r
392Done:\r
393 if (EFI_ERROR (Status)) {\r
394\r
395 if (Private != NULL) {\r
396\r
397 FreeUnicodeStringTable (Private->ControllerNameTable);\r
398\r
399 FreePool (Private);\r
400 }\r
401\r
402 gBS->CloseProtocol (\r
403 ControllerHandle,\r
404 &gEfiWinNtIoProtocolGuid,\r
405 This->DriverBindingHandle,\r
406 ControllerHandle\r
407 );\r
408 }\r
409\r
410 return Status;\r
411}\r
412\r
413EFI_STATUS\r
414EFIAPI\r
415WinNtSimpleFileSystemDriverBindingStop (\r
416 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
417 IN EFI_HANDLE ControllerHandle,\r
418 IN UINTN NumberOfChildren,\r
419 IN EFI_HANDLE *ChildHandleBuffer\r
420 )\r
421/*++\r
422\r
423Routine Description:\r
424\r
425 TODO: Add function description\r
426\r
427Arguments:\r
428\r
429 This - A pointer to an instance of the EFI_DRIVER_BINDING_PROTOCOL.\r
430\r
431 ControllerHandle - A handle to the device to be stopped.\r
432\r
433 NumberOfChildren - The number of child device handles in ChildHandleBuffer.\r
434\r
435 ChildHandleBuffer - An array of child device handles to be freed.\r
436\r
437Returns:\r
438\r
439 EFI_SUCCESS - The device has been stopped.\r
440\r
441 EFI_DEVICE_ERROR - The device could not be stopped due to a device failure.\r
442\r
443--*/\r
444// TODO: EFI_UNSUPPORTED - add return value to function comment\r
445{\r
446 EFI_STATUS Status;\r
447 EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SimpleFileSystem;\r
448 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
449\r
450 //\r
451 // Get our context back\r
452 //\r
453 Status = gBS->OpenProtocol (\r
454 ControllerHandle,\r
455 &gEfiSimpleFileSystemProtocolGuid,\r
63941829 456 (VOID **) &SimpleFileSystem,\r
068eac81 457 This->DriverBindingHandle,\r
458 ControllerHandle,\r
459 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
460 );\r
461 if (EFI_ERROR (Status)) {\r
462 return EFI_UNSUPPORTED;\r
463 }\r
464\r
465 Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (SimpleFileSystem);\r
466\r
467 //\r
468 // Uninstall the Simple File System Protocol from ControllerHandle\r
469 //\r
470 Status = gBS->UninstallMultipleProtocolInterfaces (\r
471 ControllerHandle,\r
472 &gEfiSimpleFileSystemProtocolGuid,\r
473 &Private->SimpleFileSystem,\r
474 NULL\r
475 );\r
476 if (!EFI_ERROR (Status)) {\r
477 Status = gBS->CloseProtocol (\r
478 ControllerHandle,\r
479 &gEfiWinNtIoProtocolGuid,\r
480 This->DriverBindingHandle,\r
481 ControllerHandle\r
482 );\r
483 }\r
484\r
485 if (!EFI_ERROR (Status)) {\r
486 //\r
487 // Free our instance data\r
488 //\r
489 FreeUnicodeStringTable (Private->ControllerNameTable);\r
490\r
491 FreePool (Private);\r
492 }\r
493\r
494 return Status;\r
495}\r
496\r
497EFI_STATUS\r
498EFIAPI\r
499WinNtSimpleFileSystemOpenVolume (\r
500 IN EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *This,\r
c0cf06d6 501 OUT EFI_FILE_PROTOCOL **Root\r
068eac81 502 )\r
503/*++\r
504\r
505Routine Description:\r
506\r
507 Open the root directory on a volume.\r
508\r
509Arguments:\r
510\r
511 This - A pointer to the volume to open.\r
512\r
513 Root - A pointer to storage for the returned opened file handle of the root directory.\r
514\r
515Returns:\r
516\r
517 EFI_SUCCESS - The volume was opened.\r
518\r
519 EFI_UNSUPPORTED - The volume does not support the requested file system type.\r
520\r
521 EFI_NO_MEDIA - The device has no media.\r
522\r
523 EFI_DEVICE_ERROR - The device reported an error.\r
524\r
525 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
526\r
527 EFI_ACCESS_DENIED - The service denied access to the file.\r
528\r
529 EFI_OUT_OF_RESOURCES - The file volume could not be opened due to lack of resources.\r
530\r
531 EFI_MEDIA_CHANGED - The device has new media or the media is no longer supported.\r
532\r
533--*/\r
534// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
535{\r
536 EFI_STATUS Status;\r
537 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *Private;\r
538 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
539 EFI_TPL OldTpl;\r
2bda59e4 540 CHAR16 *TempFileName;\r
5b368e7d 541 UINTN Size;\r
068eac81 542\r
543 if (This == NULL || Root == NULL) {\r
544 return EFI_INVALID_PARAMETER;\r
545 }\r
546\r
547 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
548\r
549 Private = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (This);\r
550\r
551 PrivateFile = AllocatePool (sizeof (WIN_NT_EFI_FILE_PRIVATE));\r
552 if (PrivateFile == NULL) {\r
553 Status = EFI_OUT_OF_RESOURCES;\r
554 goto Done;\r
555 }\r
556\r
557 PrivateFile->FileName = AllocatePool (StrSize (Private->FilePath));\r
558 if (PrivateFile->FileName == NULL) {\r
559 Status = EFI_OUT_OF_RESOURCES;\r
560 goto Done;\r
561 }\r
562\r
563 PrivateFile->FilePath = AllocatePool (StrSize (Private->FilePath));\r
564 if (PrivateFile->FilePath == NULL) {\r
565 Status = EFI_OUT_OF_RESOURCES;\r
566 goto Done;\r
567 }\r
568\r
569 StrCpy (PrivateFile->FilePath, Private->FilePath);\r
570 StrCpy (PrivateFile->FileName, PrivateFile->FilePath);\r
571 PrivateFile->Signature = WIN_NT_EFI_FILE_PRIVATE_SIGNATURE;\r
572 PrivateFile->WinNtThunk = Private->WinNtThunk;\r
573 PrivateFile->SimpleFileSystem = This;\r
574 PrivateFile->IsRootDirectory = TRUE;\r
575 PrivateFile->IsDirectoryPath = TRUE;\r
576 PrivateFile->IsOpenedByRead = TRUE;\r
577 PrivateFile->EfiFile.Revision = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_REVISION;\r
578 PrivateFile->EfiFile.Open = WinNtSimpleFileSystemOpen;\r
579 PrivateFile->EfiFile.Close = WinNtSimpleFileSystemClose;\r
580 PrivateFile->EfiFile.Delete = WinNtSimpleFileSystemDelete;\r
581 PrivateFile->EfiFile.Read = WinNtSimpleFileSystemRead;\r
582 PrivateFile->EfiFile.Write = WinNtSimpleFileSystemWrite;\r
583 PrivateFile->EfiFile.GetPosition = WinNtSimpleFileSystemGetPosition;\r
584 PrivateFile->EfiFile.SetPosition = WinNtSimpleFileSystemSetPosition;\r
585 PrivateFile->EfiFile.GetInfo = WinNtSimpleFileSystemGetInfo;\r
586 PrivateFile->EfiFile.SetInfo = WinNtSimpleFileSystemSetInfo;\r
587 PrivateFile->EfiFile.Flush = WinNtSimpleFileSystemFlush;\r
068eac81 588 PrivateFile->IsValidFindBuf = FALSE;\r
589\r
2bda59e4 590 //\r
591 // Set DirHandle\r
592 //\r
593 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (\r
594 PrivateFile->FilePath,\r
595 GENERIC_READ,\r
596 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
597 NULL,\r
598 OPEN_EXISTING,\r
599 FILE_FLAG_BACKUP_SEMANTICS,\r
600 NULL\r
601 );\r
602\r
603 if (PrivateFile->DirHandle == INVALID_HANDLE_VALUE) {\r
604 Status = EFI_NOT_FOUND;\r
605 goto Done;\r
606 }\r
607\r
608 //\r
609 // Find the first file under it\r
610 //\r
5b368e7d 611 Size = StrSize (PrivateFile->FilePath);\r
612 Size += StrSize (L"\\*");\r
2bda59e4 613 Status = gBS->AllocatePool (\r
614 EfiBootServicesData,\r
5b368e7d 615 Size,\r
616 (VOID **)&TempFileName\r
2bda59e4 617 );\r
618 if (EFI_ERROR (Status)) {\r
619 goto Done;\r
620 }\r
621 StrCpy (TempFileName, PrivateFile->FilePath);\r
622 StrCat (TempFileName, L"\\*");\r
623\r
624 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &PrivateFile->FindBuf);\r
521465d2 625 FreePool (TempFileName);\r
2bda59e4 626\r
627 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
628 PrivateFile->IsValidFindBuf = FALSE;\r
629 } else {\r
630 PrivateFile->IsValidFindBuf = TRUE;\r
631 }\r
068eac81 632 *Root = &PrivateFile->EfiFile;\r
633\r
634 Status = EFI_SUCCESS;\r
635\r
636Done:\r
637 if (EFI_ERROR (Status)) {\r
638 if (PrivateFile) {\r
639 if (PrivateFile->FileName) {\r
640 FreePool (PrivateFile->FileName);\r
641 }\r
642\r
643 if (PrivateFile->FilePath) {\r
644 FreePool (PrivateFile->FilePath);\r
645 }\r
646\r
647 FreePool (PrivateFile);\r
648 }\r
649 }\r
650\r
651 gBS->RestoreTPL (OldTpl);\r
652\r
653 return Status;\r
654}\r
655\r
4d384084 656/**\r
657 Count the number of Leading Dot in FileNameToken.\r
658\r
659 @param FileNameToken A string representing a token in the path name.\r
660\r
661 @return UINTN The number of leading dot in the name.\r
662\r
663**/\r
664UINTN\r
665CountLeadingDots (\r
666 IN CONST CHAR16 * FileNameToken\r
667 )\r
668{\r
669 UINTN Num;\r
670\r
671 Num = 0;\r
672 while (*FileNameToken == L'.') {\r
673 Num++;\r
674 FileNameToken++;\r
675 }\r
676 \r
677 return Num;\r
678}\r
679\r
680BOOLEAN \r
681IsFileNameTokenValid (\r
682 IN CONST CHAR16 * FileNameToken\r
683 )\r
684{\r
685 UINTN Num;\r
686 if (StrStr (FileNameToken, L"/") != NULL) {\r
687 //\r
688 // No L'/' in file name.\r
689 //\r
690 return FALSE;\r
691 } else {\r
692 //\r
693 // If Token has all dot, the number should not exceed 2\r
694 //\r
695 Num = CountLeadingDots (FileNameToken);\r
696\r
697 if (Num == StrLen (FileNameToken)) {\r
698 //\r
699 // If the FileNameToken only contains a number of L'.'.\r
700 //\r
701 if (Num > 2) {\r
702 return FALSE;\r
703 }\r
704 }\r
705 }\r
706\r
707 return TRUE;\r
708}\r
709\r
710/**\r
711 Return the first string token found in the indirect pointer a String named by FileName.\r
712\r
713 On input, FileName is a indirect pointer pointing to a String.\r
714 On output, FileName is a updated to point to the next character after the first\r
715 found L"\" or NULL if there is no L"\" found.\r
716\r
717 @param FileName A indirect pointer pointing to a FileName.\r
718\r
719 @return Token The first string token found before a L"\".\r
720\r
721**/\r
722CHAR16 *\r
723GetNextFileNameToken (\r
724 IN OUT CONST CHAR16 ** FileName \r
725 )\r
726{\r
727 CHAR16 *SlashPos;\r
728 CHAR16 *Token;\r
729 UINTN Offset;\r
730 ASSERT (**FileName != L'\\');\r
731 ASSERT (**FileName != L'\0');\r
732\r
733 SlashPos = StrStr (*FileName, L"\\");\r
734 if (SlashPos == NULL) {\r
735 Token = AllocateCopyPool (StrSize(*FileName), *FileName);\r
736 *FileName = NULL;\r
737 } else {\r
738 Offset = SlashPos - *FileName;\r
739 Token = AllocateZeroPool ((Offset + 1) * sizeof (CHAR16));\r
740 StrnCpy (Token, *FileName, Offset);\r
741 //\r
742 // Point *FileName to the next character after L'\'.\r
743 //\r
744 *FileName = *FileName + Offset + 1;\r
462a3eba
MK
745 //\r
746 // If *FileName is an empty string, then set *FileName to NULL\r
747 //\r
748 if (**FileName == L'\0') {\r
749 *FileName = NULL;\r
750 }\r
4d384084 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
c46aecea
LH
1489/**\r
1490 Convert the FileTime to EfiTime.\r
1491\r
1492 @param PrivateFile Pointer to WIN_NT_EFI_FILE_PRIVATE.\r
1493 @param TimeZone Pointer to the current time zone.\r
1494 @param FileTime Pointer to file time.\r
1495 @param EfiTime Pointer to EFI time.\r
1496**/\r
1497VOID\r
1498WinNtFileTimeToEfiTime ( \r
1499 IN CONST WIN_NT_EFI_FILE_PRIVATE *PrivateFile,\r
1500 IN TIME_ZONE_INFORMATION *TimeZone,\r
1501 IN CONST FILETIME *FileTime,\r
1502 OUT EFI_TIME *EfiTime\r
1503 )\r
1504{\r
1505 FILETIME TempFileTime;\r
1506 SYSTEMTIME SystemTime;\r
1507\r
1508 PrivateFile->WinNtThunk->FileTimeToLocalFileTime (FileTime, &TempFileTime);\r
1509 PrivateFile->WinNtThunk->FileTimeToSystemTime (&TempFileTime, &SystemTime);\r
1510 WinNtSystemTimeToEfiTime (&SystemTime, TimeZone, EfiTime);\r
1511}\r
1512\r
068eac81 1513EFI_STATUS\r
1514EFIAPI\r
1515WinNtSimpleFileSystemRead (\r
c0cf06d6 1516 IN EFI_FILE_PROTOCOL *This,\r
1517 IN OUT UINTN *BufferSize,\r
1518 OUT VOID *Buffer\r
068eac81 1519 )\r
1520/*++\r
1521\r
1522Routine Description:\r
1523\r
1524 Read data from a file.\r
1525\r
1526Arguments:\r
1527\r
1528 This - Pointer to a returned open file handle.\r
1529\r
1530 BufferSize - On input, the size of the Buffer. On output, the number of bytes stored in the Buffer.\r
1531\r
1532 Buffer - Pointer to the first byte of the read Buffer.\r
1533\r
1534Returns:\r
1535\r
1536 EFI_SUCCESS - The data was read.\r
1537\r
1538 EFI_NO_MEDIA - The device has no media.\r
1539\r
1540 EFI_DEVICE_ERROR - The device reported an error.\r
1541\r
1542 EFI_VOLUME_CORRUPTED - The file system structures are corrupted.\r
1543\r
1544 EFI_BUFFER_TOO_SMALL - The supplied buffer size was too small to store the current directory entry.\r
1545 *BufferSize has been updated with the size needed to complete the request.\r
1546\r
1547--*/\r
1548// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1549{\r
1550 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1551 EFI_STATUS Status;\r
1552 UINTN Size;\r
1553 UINTN NameSize;\r
1554 UINTN ResultSize;\r
1555 UINTN Index;\r
068eac81 1556 EFI_FILE_INFO *Info;\r
1557 WCHAR *pw;\r
1558 TIME_ZONE_INFORMATION TimeZone;\r
1559 EFI_FILE_INFO *FileInfo;\r
1560 UINT64 Pos;\r
1561 UINT64 FileSize;\r
1562 UINTN FileInfoSize;\r
1563 EFI_TPL OldTpl;\r
1564\r
1565 if (This == NULL || BufferSize == NULL) {\r
1566 return EFI_INVALID_PARAMETER;\r
1567 }\r
1568\r
1569 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1570\r
1571 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1572\r
1573 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1574 Status = EFI_DEVICE_ERROR;\r
1575 goto Done;\r
1576 }\r
1577\r
1578 if (!PrivateFile->IsDirectoryPath) {\r
1579\r
1580 if (This->GetPosition (This, &Pos) != EFI_SUCCESS) {\r
1581 Status = EFI_DEVICE_ERROR;\r
1582 goto Done;\r
1583 }\r
1584\r
1585 FileInfoSize = SIZE_OF_EFI_FILE_SYSTEM_INFO;\r
1586 FileInfo = AllocatePool (FileInfoSize);\r
1587\r
1588 Status = This->GetInfo (\r
1589 This,\r
1590 &gEfiFileInfoGuid,\r
1591 &FileInfoSize,\r
1592 FileInfo\r
1593 );\r
1594\r
1595 if (Status == EFI_BUFFER_TOO_SMALL) {\r
1596 FreePool (FileInfo);\r
1597 FileInfo = AllocatePool (FileInfoSize);\r
1598 Status = This->GetInfo (\r
1599 This,\r
1600 &gEfiFileInfoGuid,\r
1601 &FileInfoSize,\r
1602 FileInfo\r
1603 );\r
1604 }\r
1605\r
1606 if (EFI_ERROR (Status)) {\r
1607 Status = EFI_DEVICE_ERROR;\r
1608 goto Done;\r
1609 }\r
1610\r
1611 FileSize = FileInfo->FileSize;\r
1612\r
1613 FreePool (FileInfo);\r
1614\r
1615 if (Pos >= FileSize) {\r
1616 *BufferSize = 0;\r
1617 if (Pos == FileSize) {\r
1618 Status = EFI_SUCCESS;\r
1619 goto Done;\r
1620 } else {\r
1621 Status = EFI_DEVICE_ERROR;\r
1622 goto Done;\r
1623 }\r
1624 }\r
1625\r
1626 Status = PrivateFile->WinNtThunk->ReadFile (\r
a00ec39b 1627 PrivateFile->LHandle,\r
1628 Buffer,\r
f66a43b2 1629 (DWORD)*BufferSize,\r
a00ec39b 1630 (LPDWORD)BufferSize,\r
1631 NULL\r
1632 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
068eac81 1633 goto Done;\r
1634 }\r
1635\r
1636 //\r
1637 // Read on a directory. Perform a find next\r
1638 //\r
1639 if (!PrivateFile->IsValidFindBuf) {\r
1640 *BufferSize = 0;\r
1641 Status = EFI_SUCCESS;\r
1642 goto Done;\r
1643 }\r
1644\r
1645 Size = SIZE_OF_EFI_FILE_INFO;\r
1646\r
1647 NameSize = StrSize (PrivateFile->FindBuf.cFileName);\r
1648\r
1649 ResultSize = Size + NameSize;\r
1650\r
1651 Status = EFI_BUFFER_TOO_SMALL;\r
1652\r
1653 if (*BufferSize >= ResultSize) {\r
1654 Status = EFI_SUCCESS;\r
1655\r
1656 Info = Buffer;\r
1657 ZeroMem (Info, ResultSize);\r
1658\r
1659 Info->Size = ResultSize;\r
1660\r
1661 PrivateFile->WinNtThunk->GetTimeZoneInformation (&TimeZone);\r
c46aecea
LH
1662 WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftCreationTime, &Info->CreateTime);\r
1663 WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastAccessTime, &Info->LastAccessTime);\r
1664 WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &PrivateFile->FindBuf.ftLastWriteTime, &Info->ModificationTime);\r
068eac81 1665\r
1666 Info->FileSize = PrivateFile->FindBuf.nFileSizeLow;\r
1667\r
1668 Info->PhysicalSize = PrivateFile->FindBuf.nFileSizeLow;\r
1669\r
1670 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {\r
1671 Info->Attribute |= EFI_FILE_ARCHIVE;\r
1672 }\r
1673\r
1674 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {\r
1675 Info->Attribute |= EFI_FILE_HIDDEN;\r
1676 }\r
1677\r
1678 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {\r
1679 Info->Attribute |= EFI_FILE_SYSTEM;\r
1680 }\r
1681\r
1682 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
1683 Info->Attribute |= EFI_FILE_READ_ONLY;\r
1684 }\r
1685\r
1686 if (PrivateFile->FindBuf.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\r
1687 Info->Attribute |= EFI_FILE_DIRECTORY;\r
1688 }\r
1689\r
1690 NameSize = NameSize / sizeof (WCHAR);\r
1691\r
1692 pw = (WCHAR *) (((CHAR8 *) Buffer) + Size);\r
1693\r
1694 for (Index = 0; Index < NameSize; Index++) {\r
1695 pw[Index] = PrivateFile->FindBuf.cFileName[Index];\r
1696 }\r
1697\r
1698 if (PrivateFile->WinNtThunk->FindNextFile (PrivateFile->LHandle, &PrivateFile->FindBuf)) {\r
1699 PrivateFile->IsValidFindBuf = TRUE;\r
1700 } else {\r
1701 PrivateFile->IsValidFindBuf = FALSE;\r
1702 }\r
1703 }\r
1704\r
1705 *BufferSize = ResultSize;\r
1706\r
1707Done:\r
1708 gBS->RestoreTPL (OldTpl);\r
1709 return Status;\r
1710}\r
1711\r
1712EFI_STATUS\r
1713EFIAPI\r
1714WinNtSimpleFileSystemWrite (\r
c0cf06d6 1715 IN EFI_FILE_PROTOCOL *This,\r
1716 IN OUT UINTN *BufferSize,\r
1717 IN VOID *Buffer\r
068eac81 1718 )\r
1719/*++\r
1720\r
1721Routine Description:\r
1722\r
1723 Write data to a file.\r
1724\r
1725Arguments:\r
1726\r
1727 This - Pointer to an opened file handle.\r
1728\r
1729 BufferSize - On input, the number of bytes in the Buffer to write to the file. On output, the number of bytes\r
1730 of data written to the file.\r
1731\r
1732 Buffer - Pointer to the first by of data in the buffer to write to the file.\r
1733\r
1734Returns:\r
1735\r
1736 EFI_SUCCESS - The data was written to the file.\r
1737\r
1738 EFI_UNSUPPORTED - Writes to an open directory are not supported.\r
1739\r
1740 EFI_NO_MEDIA - The device has no media.\r
1741\r
1742 EFI_DEVICE_ERROR - The device reported an error.\r
1743\r
1744 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
1745\r
1746 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
1747\r
1748 EFI_ACCESS_DENIED - The file was opened read-only.\r
1749\r
1750 EFI_VOLUME_FULL - The volume is full.\r
1751\r
1752--*/\r
1753// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1754{\r
1755 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1756 EFI_STATUS Status;\r
1757 EFI_TPL OldTpl;\r
1758\r
1759 if (This == NULL || BufferSize == NULL || Buffer == NULL) {\r
1760 return EFI_INVALID_PARAMETER;\r
1761 }\r
1762\r
1763 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1764\r
1765 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1766\r
1767 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1768 Status = EFI_DEVICE_ERROR;\r
1769 goto Done;\r
1770 }\r
1771\r
1772 if (PrivateFile->IsDirectoryPath) {\r
1773 Status = EFI_UNSUPPORTED;\r
1774 goto Done;\r
1775 }\r
1776\r
1777 if (PrivateFile->IsOpenedByRead) {\r
1778 Status = EFI_ACCESS_DENIED;\r
1779 goto Done;\r
1780 }\r
1781\r
1782 Status = PrivateFile->WinNtThunk->WriteFile (\r
a00ec39b 1783 PrivateFile->LHandle,\r
1784 Buffer,\r
f66a43b2 1785 (DWORD)*BufferSize,\r
a00ec39b 1786 (LPDWORD)BufferSize,\r
1787 NULL\r
1788 ) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
068eac81 1789\r
1790Done:\r
1791 gBS->RestoreTPL (OldTpl);\r
1792 return Status;\r
1793\r
1794 //\r
1795 // bugbug: need to access windows error reporting\r
1796 //\r
1797}\r
1798\r
1799EFI_STATUS\r
1800EFIAPI\r
1801WinNtSimpleFileSystemSetPosition (\r
c0cf06d6 1802 IN EFI_FILE_PROTOCOL *This,\r
1803 IN UINT64 Position\r
068eac81 1804 )\r
1805/*++\r
1806\r
1807Routine Description:\r
1808\r
1809 Set a file's current position.\r
1810\r
1811Arguments:\r
1812\r
1813 This - Pointer to an opened file handle.\r
1814\r
1815 Position - The byte position from the start of the file to set.\r
1816\r
1817Returns:\r
1818\r
1819 EFI_SUCCESS - The file position has been changed.\r
1820\r
1821 EFI_UNSUPPORTED - The seek request for non-zero is not supported for directories.\r
1822\r
1823--*/\r
1824// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1825{\r
1826 EFI_STATUS Status;\r
1827 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1828 UINT32 PosLow;\r
1829 UINT32 PosHigh;\r
1830 CHAR16 *FileName;\r
1831 EFI_TPL OldTpl;\r
a00ec39b 1832 UINTN Size;\r
068eac81 1833\r
1834 if (This == NULL) {\r
1835 return EFI_INVALID_PARAMETER;\r
1836 }\r
1837\r
1838 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1839\r
1840 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1841\r
1842 if (PrivateFile->IsDirectoryPath) {\r
1843 if (Position != 0) {\r
1844 Status = EFI_UNSUPPORTED;\r
1845 goto Done;\r
1846 }\r
1847\r
a00ec39b 1848 Size = StrSize (PrivateFile->FileName);\r
1849 Size += StrSize (L"\\*");\r
1850 FileName = AllocatePool (Size);\r
068eac81 1851 if (FileName == NULL) {\r
1852 Status = EFI_OUT_OF_RESOURCES;\r
1853 goto Done;\r
1854 }\r
1855\r
1856 StrCpy (FileName, PrivateFile->FileName);\r
1857 StrCat (FileName, L"\\*");\r
1858\r
1859 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
1860 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);\r
1861 }\r
1862\r
1863 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (FileName, &PrivateFile->FindBuf);\r
1864\r
1865 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
1866 PrivateFile->IsValidFindBuf = FALSE;\r
1867 } else {\r
1868 PrivateFile->IsValidFindBuf = TRUE;\r
1869 }\r
1870\r
1871 FreePool (FileName);\r
1872\r
1873 Status = (PrivateFile->LHandle == INVALID_HANDLE_VALUE) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1874 } else {\r
1875 if (Position == (UINT64) -1) {\r
1876 PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) 0, NULL, FILE_END);\r
1877 } else {\r
1878 PosHigh = (UINT32) RShiftU64 (Position, 32);\r
1879\r
a00ec39b 1880 PosLow = PrivateFile->WinNtThunk->SetFilePointer (PrivateFile->LHandle, (ULONG) Position, (PLONG)&PosHigh, FILE_BEGIN);\r
068eac81 1881 }\r
1882\r
1883 Status = (PosLow == 0xFFFFFFFF) ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1884 }\r
1885\r
1886Done:\r
1887 gBS->RestoreTPL (OldTpl);\r
1888 return Status;\r
1889}\r
1890\r
1891EFI_STATUS\r
1892EFIAPI\r
1893WinNtSimpleFileSystemGetPosition (\r
c0cf06d6 1894 IN EFI_FILE_PROTOCOL *This,\r
1895 OUT UINT64 *Position\r
068eac81 1896 )\r
1897/*++\r
1898\r
1899Routine Description:\r
1900\r
1901 Get a file's current position.\r
1902\r
1903Arguments:\r
1904\r
1905 This - Pointer to an opened file handle.\r
1906\r
1907 Position - Pointer to storage for the current position.\r
1908\r
1909Returns:\r
1910\r
1911 EFI_SUCCESS - The file position has been reported.\r
1912\r
1913 EFI_UNSUPPORTED - Not valid for directories.\r
1914\r
1915--*/\r
1916// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
1917{\r
1918 EFI_STATUS Status;\r
1919 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
1920 INT32 PositionHigh;\r
1921 UINT64 PosHigh64;\r
1922 EFI_TPL OldTpl;\r
1923\r
1924 if (This == NULL || Position == NULL) {\r
1925 return EFI_INVALID_PARAMETER;\r
1926 }\r
1927\r
1928 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
1929 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
1930\r
1931 PositionHigh = 0;\r
1932 PosHigh64 = 0;\r
1933\r
1934 if (PrivateFile->IsDirectoryPath) {\r
1935\r
1936 Status = EFI_UNSUPPORTED;\r
1937 goto Done;\r
1938\r
1939 } else {\r
1940\r
1941 PositionHigh = 0;\r
1942 *Position = PrivateFile->WinNtThunk->SetFilePointer (\r
a00ec39b 1943 PrivateFile->LHandle,\r
1944 0,\r
1945 (PLONG)&PositionHigh,\r
1946 FILE_CURRENT\r
1947 );\r
068eac81 1948\r
1949 Status = *Position == 0xffffffff ? EFI_DEVICE_ERROR : EFI_SUCCESS;\r
1950 if (EFI_ERROR (Status)) {\r
1951 goto Done;\r
1952 }\r
1953\r
1954 PosHigh64 = PositionHigh;\r
1955 *Position += LShiftU64 (PosHigh64, 32);\r
1956 }\r
1957\r
1958Done:\r
1959 gBS->RestoreTPL (OldTpl);\r
1960 return Status;\r
1961}\r
1962\r
068eac81 1963EFI_STATUS\r
1964WinNtSimpleFileSystemFileInfo (\r
1965 IN WIN_NT_EFI_FILE_PRIVATE *PrivateFile,\r
1966 IN OUT UINTN *BufferSize,\r
1967 OUT VOID *Buffer\r
1968 )\r
1969/*++\r
1970\r
1971Routine Description:\r
1972\r
1973 TODO: Add function description\r
1974\r
1975Arguments:\r
1976\r
1977 PrivateFile - TODO: add argument description\r
1978 BufferSize - TODO: add argument description\r
1979 Buffer - TODO: add argument description\r
1980\r
1981Returns:\r
1982\r
1983 TODO: add return values\r
1984\r
1985--*/\r
1986{\r
1987 EFI_STATUS Status;\r
1988 UINTN Size;\r
1989 UINTN NameSize;\r
1990 UINTN ResultSize;\r
1991 EFI_FILE_INFO *Info;\r
1992 BY_HANDLE_FILE_INFORMATION FileInfo;\r
068eac81 1993 CHAR16 *RealFileName;\r
1994 CHAR16 *TempPointer;\r
c46aecea 1995 TIME_ZONE_INFORMATION TimeZone;\r
068eac81 1996\r
1997 Size = SIZE_OF_EFI_FILE_INFO;\r
3643e8e7
ED
1998\r
1999 RealFileName = PrivateFile->FileName;\r
2000 TempPointer = RealFileName;\r
2001 while (*TempPointer) {\r
2002 if (*TempPointer == '\\') {\r
2003 RealFileName = TempPointer + 1;\r
2004 }\r
2005\r
2006 TempPointer++;\r
2007 }\r
2008 NameSize = StrSize (RealFileName);\r
2009\r
2010 ResultSize = Size + NameSize; \r
068eac81 2011\r
2012 Status = EFI_BUFFER_TOO_SMALL;\r
2013 if (*BufferSize >= ResultSize) {\r
2014 Status = EFI_SUCCESS;\r
2015\r
2016 Info = Buffer;\r
2017 ZeroMem (Info, ResultSize);\r
2018\r
2019 Info->Size = ResultSize;\r
2020 PrivateFile->WinNtThunk->GetFileInformationByHandle (\r
2021 PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,\r
2022 &FileInfo\r
2023 );\r
2024 Info->FileSize = FileInfo.nFileSizeLow;\r
2025 Info->PhysicalSize = Info->FileSize;\r
2026\r
c46aecea
LH
2027 PrivateFile->WinNtThunk->GetTimeZoneInformation (&TimeZone);\r
2028 WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftCreationTime, &Info->CreateTime);\r
2029 WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastAccessTime, &Info->LastAccessTime);\r
2030 WinNtFileTimeToEfiTime (PrivateFile, &TimeZone, &FileInfo.ftLastWriteTime, &Info->ModificationTime);\r
068eac81 2031\r
2032 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_ARCHIVE) {\r
2033 Info->Attribute |= EFI_FILE_ARCHIVE;\r
2034 }\r
2035\r
2036 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN) {\r
2037 Info->Attribute |= EFI_FILE_HIDDEN;\r
2038 }\r
2039\r
2040 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
2041 Info->Attribute |= EFI_FILE_READ_ONLY;\r
2042 }\r
2043\r
2044 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_SYSTEM) {\r
2045 Info->Attribute |= EFI_FILE_SYSTEM;\r
2046 }\r
2047\r
2048 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {\r
2049 Info->Attribute |= EFI_FILE_DIRECTORY;\r
2050 }\r
2051\r
2052 if (PrivateFile->IsDirectoryPath) {\r
2053 Info->Attribute |= EFI_FILE_DIRECTORY;\r
2054 }\r
2055\r
068eac81 2056 if (PrivateFile->IsRootDirectory) {\r
2057 *((CHAR8 *) Buffer + Size) = 0;\r
2058 } else {\r
2059 CopyMem ((CHAR8 *) Buffer + Size, RealFileName, NameSize);\r
2060 }\r
068eac81 2061 }\r
2062\r
2063 *BufferSize = ResultSize;\r
2064 return Status;\r
2065}\r
2066\r
2067EFI_STATUS\r
2068EFIAPI\r
2069WinNtSimpleFileSystemGetInfo (\r
c0cf06d6 2070 IN EFI_FILE_PROTOCOL *This,\r
2071 IN EFI_GUID *InformationType,\r
2072 IN OUT UINTN *BufferSize,\r
2073 OUT VOID *Buffer\r
068eac81 2074 )\r
2075/*++\r
2076\r
2077Routine Description:\r
2078\r
2079 Return information about a file or volume.\r
2080\r
2081Arguments:\r
2082\r
2083 This - Pointer to an opened file handle.\r
2084\r
2085 InformationType - GUID describing the type of information to be returned.\r
2086\r
2087 BufferSize - On input, the size of the information buffer. On output, the number of bytes written to the\r
2088 information buffer.\r
2089\r
2090 Buffer - Pointer to the first byte of the information buffer.\r
2091\r
2092Returns:\r
2093\r
2094 EFI_SUCCESS - The requested information has been written into the buffer.\r
2095\r
2096 EFI_UNSUPPORTED - The InformationType is not known.\r
2097\r
2098 EFI_NO_MEDIA - The device has no media.\r
2099\r
2100 EFI_DEVICE_ERROR - The device reported an error.\r
2101\r
2102 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
2103\r
2104 EFI_BUFFER_TOO_SMALL - The buffer size was too small to contain the requested information. The buffer size has\r
2105 been updated with the size needed to complete the requested operation.\r
2106\r
2107--*/\r
2108// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2109{\r
2110 EFI_STATUS Status;\r
2111 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
2112 EFI_FILE_SYSTEM_INFO *FileSystemInfoBuffer;\r
2113 UINT32 SectorsPerCluster;\r
2114 UINT32 BytesPerSector;\r
2115 UINT32 FreeClusters;\r
2116 UINT32 TotalClusters;\r
2117 UINT32 BytesPerCluster;\r
2118 CHAR16 *DriveName;\r
2119 BOOLEAN DriveNameFound;\r
2120 BOOL NtStatus;\r
2121 UINTN Index;\r
2122 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
2123 EFI_TPL OldTpl;\r
2124\r
2125 if (This == NULL || InformationType == NULL || BufferSize == NULL) {\r
2126 return EFI_INVALID_PARAMETER;\r
2127 }\r
2128\r
2129 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
2130\r
2131 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2132 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
2133\r
2134 Status = EFI_UNSUPPORTED;\r
2135\r
2136 if (CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
2137 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, BufferSize, Buffer);\r
2138 }\r
2139\r
2140 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
2141 if (*BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel)) {\r
2142 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
2143 Status = EFI_BUFFER_TOO_SMALL;\r
2144 goto Done;\r
2145 }\r
2146\r
2147 FileSystemInfoBuffer = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
2148 FileSystemInfoBuffer->Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
2149 FileSystemInfoBuffer->ReadOnly = FALSE;\r
2150\r
2151 //\r
2152 // Try to get the drive name\r
2153 //\r
2154 DriveNameFound = FALSE;\r
2155 DriveName = AllocatePool (StrSize (PrivateFile->FilePath) + 1);\r
2156 if (DriveName == NULL) {\r
2157 Status = EFI_OUT_OF_RESOURCES;\r
2158 goto Done;\r
2159 }\r
2160\r
2161 StrCpy (DriveName, PrivateFile->FilePath);\r
2162 for (Index = 0; DriveName[Index] != 0 && DriveName[Index] != ':'; Index++) {\r
2163 ;\r
2164 }\r
2165\r
2166 if (DriveName[Index] == ':') {\r
2167 DriveName[Index + 1] = '\\';\r
2168 DriveName[Index + 2] = 0;\r
2169 DriveNameFound = TRUE;\r
2170 } else if (DriveName[0] == '\\' && DriveName[1] == '\\') {\r
2171 for (Index = 2; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {\r
2172 ;\r
2173 }\r
2174\r
2175 if (DriveName[Index] == '\\') {\r
2176 DriveNameFound = TRUE;\r
2177 for (Index++; DriveName[Index] != 0 && DriveName[Index] != '\\'; Index++) {\r
2178 ;\r
2179 }\r
2180\r
2181 DriveName[Index] = '\\';\r
2182 DriveName[Index + 1] = 0;\r
2183 }\r
2184 }\r
2185\r
2186 //\r
2187 // Try GetDiskFreeSpace first\r
2188 //\r
2189 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpace (\r
2190 DriveNameFound ? DriveName : NULL,\r
a00ec39b 2191 (LPDWORD)&SectorsPerCluster,\r
2192 (LPDWORD)&BytesPerSector,\r
2193 (LPDWORD)&FreeClusters,\r
2194 (LPDWORD)&TotalClusters\r
068eac81 2195 );\r
2196 if (DriveName) {\r
2197 FreePool (DriveName);\r
2198 }\r
2199\r
2200 if (NtStatus) {\r
2201 //\r
2202 // Succeeded\r
2203 //\r
2204 BytesPerCluster = BytesPerSector * SectorsPerCluster;\r
2205 FileSystemInfoBuffer->VolumeSize = MultU64x32 (TotalClusters, BytesPerCluster);\r
2206 FileSystemInfoBuffer->FreeSpace = MultU64x32 (FreeClusters, BytesPerCluster);\r
2207 FileSystemInfoBuffer->BlockSize = BytesPerCluster;\r
2208\r
2209 } else {\r
2210 //\r
2211 // try GetDiskFreeSpaceEx then\r
2212 //\r
2213 FileSystemInfoBuffer->BlockSize = 0;\r
2214 NtStatus = PrivateFile->WinNtThunk->GetDiskFreeSpaceEx (\r
2215 PrivateFile->FilePath,\r
2216 (PULARGE_INTEGER) (&FileSystemInfoBuffer->FreeSpace),\r
2217 (PULARGE_INTEGER) (&FileSystemInfoBuffer->VolumeSize),\r
2218 NULL\r
2219 );\r
2220 if (!NtStatus) {\r
2221 Status = EFI_DEVICE_ERROR;\r
2222 goto Done;\r
2223 }\r
2224 }\r
2225\r
2226 StrCpy ((CHAR16 *) FileSystemInfoBuffer->VolumeLabel, PrivateRoot->VolumeLabel);\r
2227 *BufferSize = SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (PrivateRoot->VolumeLabel);\r
2228 Status = EFI_SUCCESS;\r
2229 }\r
2230\r
2231 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
2232 if (*BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
2233 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
2234 Status = EFI_BUFFER_TOO_SMALL;\r
2235 goto Done;\r
2236 }\r
2237\r
2238 StrCpy ((CHAR16 *) Buffer, PrivateRoot->VolumeLabel);\r
2239 *BufferSize = StrSize (PrivateRoot->VolumeLabel);\r
2240 Status = EFI_SUCCESS;\r
2241 }\r
2242\r
2243Done:\r
2244 gBS->RestoreTPL (OldTpl);\r
2245 return Status;\r
2246}\r
2247\r
2248EFI_STATUS\r
2249EFIAPI\r
2250WinNtSimpleFileSystemSetInfo (\r
c0cf06d6 2251 IN EFI_FILE_PROTOCOL*This,\r
068eac81 2252 IN EFI_GUID *InformationType,\r
2253 IN UINTN BufferSize,\r
2254 IN VOID *Buffer\r
2255 )\r
2256/*++\r
2257\r
2258Routine Description:\r
2259\r
2260 Set information about a file or volume.\r
2261\r
2262Arguments:\r
2263\r
2264 This - Pointer to an opened file handle.\r
2265\r
2266 InformationType - GUID identifying the type of information to set.\r
2267\r
2268 BufferSize - Number of bytes of data in the information buffer.\r
2269\r
2270 Buffer - Pointer to the first byte of data in the information buffer.\r
2271\r
2272Returns:\r
2273\r
2274 EFI_SUCCESS - The file or volume information has been updated.\r
2275\r
2276 EFI_UNSUPPORTED - The information identifier is not recognised.\r
2277\r
2278 EFI_NO_MEDIA - The device has no media.\r
2279\r
2280 EFI_DEVICE_ERROR - The device reported an error.\r
2281\r
2282 EFI_VOLUME_CORRUPTED - The file system structures are corrupt.\r
2283\r
2284 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
2285\r
2286 EFI_ACCESS_DENIED - The file was opened read-only.\r
2287\r
2288 EFI_VOLUME_FULL - The volume is full.\r
2289\r
2290 EFI_BAD_BUFFER_SIZE - The buffer size is smaller than the type indicated by InformationType.\r
2291\r
2292--*/\r
2293// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2294// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2295{\r
2296 WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE *PrivateRoot;\r
2297 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
2298 EFI_FILE_INFO *OldFileInfo;\r
2299 EFI_FILE_INFO *NewFileInfo;\r
2300 EFI_STATUS Status;\r
2301 UINTN OldInfoSize;\r
2302 INTN NtStatus;\r
2303 UINT32 NewAttr;\r
2304 UINT32 OldAttr;\r
2305 CHAR16 *OldFileName;\r
2306 CHAR16 *NewFileName;\r
2307 CHAR16 *TempFileName;\r
2308 CHAR16 *CharPointer;\r
2309 BOOLEAN AttrChangeFlag;\r
2310 BOOLEAN NameChangeFlag;\r
2311 BOOLEAN SizeChangeFlag;\r
2312 BOOLEAN TimeChangeFlag;\r
2313 UINT64 CurPos;\r
2314 SYSTEMTIME NewCreationSystemTime;\r
2315 SYSTEMTIME NewLastAccessSystemTime;\r
2316 SYSTEMTIME NewLastWriteSystemTime;\r
2317 FILETIME NewCreationFileTime;\r
2318 FILETIME NewLastAccessFileTime;\r
2319 FILETIME NewLastWriteFileTime;\r
2320 WIN32_FIND_DATA FindBuf;\r
2321 EFI_FILE_SYSTEM_INFO *NewFileSystemInfo;\r
2322 EFI_TPL OldTpl;\r
a00ec39b 2323 UINTN Size;\r
068eac81 2324\r
2325 //\r
2326 // Check for invalid parameters.\r
2327 //\r
2328 if (This == NULL || InformationType == NULL || BufferSize == 0 || Buffer == NULL) {\r
2329 return EFI_INVALID_PARAMETER;\r
2330 }\r
2331\r
2332 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
2333\r
2334 //\r
2335 // Initialise locals.\r
2336 //\r
2337 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2338 PrivateRoot = WIN_NT_SIMPLE_FILE_SYSTEM_PRIVATE_DATA_FROM_THIS (PrivateFile->SimpleFileSystem);\r
2339\r
2340 Status = EFI_UNSUPPORTED;\r
2341 OldFileInfo = NewFileInfo = NULL;\r
2342 OldFileName = NewFileName = NULL;\r
2343 AttrChangeFlag = NameChangeFlag = SizeChangeFlag = TimeChangeFlag = FALSE;\r
2344\r
2345 //\r
2346 // Set file system information.\r
2347 //\r
2348 if (CompareGuid (InformationType, &gEfiFileSystemInfoGuid)) {\r
b80022da 2349 NewFileSystemInfo = (EFI_FILE_SYSTEM_INFO *) Buffer;\r
2350 if (BufferSize < SIZE_OF_EFI_FILE_SYSTEM_INFO + StrSize (NewFileSystemInfo->VolumeLabel)) {\r
068eac81 2351 Status = EFI_BAD_BUFFER_SIZE;\r
2352 goto Done;\r
2353 }\r
2354\r
068eac81 2355\r
2356 FreePool (PrivateRoot->VolumeLabel);\r
2357 PrivateRoot->VolumeLabel = AllocatePool (StrSize (NewFileSystemInfo->VolumeLabel));\r
2358 if (PrivateRoot->VolumeLabel == NULL) {\r
2359 Status = EFI_OUT_OF_RESOURCES;\r
2360 goto Done;\r
2361 }\r
2362\r
2363 StrCpy (PrivateRoot->VolumeLabel, NewFileSystemInfo->VolumeLabel);\r
2364\r
2365 Status = EFI_SUCCESS;\r
2366 goto Done;\r
2367 }\r
2368\r
2369 //\r
2370 // Set volume label information.\r
2371 //\r
2372 if (CompareGuid (InformationType, &gEfiFileSystemVolumeLabelInfoIdGuid)) {\r
2373 if (BufferSize < StrSize (PrivateRoot->VolumeLabel)) {\r
2374 Status = EFI_BAD_BUFFER_SIZE;\r
2375 goto Done;\r
2376 }\r
2377\r
2378 StrCpy (PrivateRoot->VolumeLabel, (CHAR16 *) Buffer);\r
2379\r
2380 Status = EFI_SUCCESS;\r
2381 goto Done;\r
2382 }\r
2383\r
2384 if (!CompareGuid (InformationType, &gEfiFileInfoGuid)) {\r
2385 Status = EFI_UNSUPPORTED;\r
2386 goto Done;\r
2387 }\r
2388\r
2389 if (BufferSize < SIZE_OF_EFI_FILE_INFO) {\r
2390 Status = EFI_BAD_BUFFER_SIZE;\r
2391 goto Done;\r
2392 }\r
2393\r
2394 //\r
2395 // Set file/directory information.\r
2396 //\r
2397\r
2398 //\r
2399 // Check for invalid set file information parameters.\r
2400 //\r
2401 NewFileInfo = (EFI_FILE_INFO *) Buffer;\r
2402\r
82b76043 2403 if ((NewFileInfo->Size <= SIZE_OF_EFI_FILE_INFO) ||\r
068eac81 2404 (NewFileInfo->Attribute &~(EFI_FILE_VALID_ATTR)) ||\r
2405 (sizeof (UINTN) == 4 && NewFileInfo->Size > 0xFFFFFFFF)\r
2406 ) {\r
2407 Status = EFI_INVALID_PARAMETER;\r
2408 goto Done;\r
2409 }\r
2410\r
2411 //\r
2412 // bugbug: - This is not safe. We need something like EfiStrMaxSize()\r
2413 // that would have an additional parameter that would be the size\r
2414 // of the string array just in case there are no NULL characters in\r
2415 // the string array.\r
2416 //\r
2417 //\r
2418 // Get current file information so we can determine what kind\r
2419 // of change request this is.\r
2420 //\r
2421 OldInfoSize = 0;\r
2422 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, NULL);\r
2423\r
2424 if (Status != EFI_BUFFER_TOO_SMALL) {\r
2425 Status = EFI_DEVICE_ERROR;\r
2426 goto Done;\r
2427 }\r
2428\r
2429 OldFileInfo = AllocatePool (OldInfoSize);\r
2430 if (OldFileInfo == NULL) {\r
2431 Status = EFI_OUT_OF_RESOURCES;\r
2432 goto Done;\r
2433 }\r
2434\r
2435 Status = WinNtSimpleFileSystemFileInfo (PrivateFile, &OldInfoSize, OldFileInfo);\r
2436\r
2437 if (EFI_ERROR (Status)) {\r
2438 goto Done;\r
2439 }\r
2440\r
2441 OldFileName = AllocatePool (StrSize (PrivateFile->FileName));\r
2442 if (OldFileName == NULL) {\r
2443 Status = EFI_OUT_OF_RESOURCES;\r
2444 goto Done;\r
2445 }\r
2446\r
2447 StrCpy (OldFileName, PrivateFile->FileName);\r
2448\r
2449 //\r
2450 // Make full pathname from new filename and rootpath.\r
2451 //\r
a00ec39b 2452 if (NewFileInfo->FileName[0] == '\\') {\r
9485089d 2453 Size = StrSize (PrivateRoot->FilePath);\r
2454 Size += StrSize (L"\\");\r
2455 Size += StrSize (NewFileInfo->FileName);\r
2456 NewFileName = AllocatePool (Size);\r
2457 if (NewFileName == NULL) {\r
2458 Status = EFI_OUT_OF_RESOURCES;\r
2459 goto Done;\r
2460 }\r
2461\r
2462 StrCpy (NewFileName, PrivateRoot->FilePath);\r
2463 StrCat (NewFileName, L"\\");\r
068eac81 2464 StrCat (NewFileName, NewFileInfo->FileName + 1);\r
2465 } else {\r
9485089d 2466 Size = StrSize (PrivateFile->FilePath);\r
2467 Size += StrSize (L"\\");\r
2468 Size += StrSize (NewFileInfo->FileName);\r
2469 NewFileName = AllocatePool (Size);\r
2470 if (NewFileName == NULL) {\r
2471 Status = EFI_OUT_OF_RESOURCES;\r
2472 goto Done;\r
2473 }\r
2474\r
2475 StrCpy (NewFileName, PrivateFile->FilePath);\r
2476 StrCat (NewFileName, L"\\");\r
068eac81 2477 StrCat (NewFileName, NewFileInfo->FileName);\r
2478 }\r
2479\r
2480 //\r
2481 // Is there an attribute change request?\r
2482 //\r
2483 if (NewFileInfo->Attribute != OldFileInfo->Attribute) {\r
2484 if ((NewFileInfo->Attribute & EFI_FILE_DIRECTORY) != (OldFileInfo->Attribute & EFI_FILE_DIRECTORY)) {\r
2485 Status = EFI_INVALID_PARAMETER;\r
2486 goto Done;\r
2487 }\r
2488\r
2489 AttrChangeFlag = TRUE;\r
2490 }\r
2491\r
2492 //\r
2493 // Is there a name change request?\r
2494 // bugbug: - Need EfiStrCaseCmp()\r
2495 //\r
2496 if (StrCmp (NewFileInfo->FileName, OldFileInfo->FileName)) {\r
2497 NameChangeFlag = TRUE;\r
2498 }\r
2499\r
2500 //\r
2501 // Is there a size change request?\r
2502 //\r
2503 if (NewFileInfo->FileSize != OldFileInfo->FileSize) {\r
2504 SizeChangeFlag = TRUE;\r
2505 }\r
2506\r
2507 //\r
2508 // Is there a time stamp change request?\r
2509 //\r
2510 if (!IsZero (&NewFileInfo->CreateTime, sizeof (EFI_TIME)) &&\r
2511 CompareMem (&NewFileInfo->CreateTime, &OldFileInfo->CreateTime, sizeof (EFI_TIME))\r
2512 ) {\r
2513 TimeChangeFlag = TRUE;\r
2514 } else if (!IsZero (&NewFileInfo->LastAccessTime, sizeof (EFI_TIME)) &&\r
2515 CompareMem (&NewFileInfo->LastAccessTime, &OldFileInfo->LastAccessTime, sizeof (EFI_TIME))\r
2516 ) {\r
2517 TimeChangeFlag = TRUE;\r
2518 } else if (!IsZero (&NewFileInfo->ModificationTime, sizeof (EFI_TIME)) &&\r
2519 CompareMem (&NewFileInfo->ModificationTime, &OldFileInfo->ModificationTime, sizeof (EFI_TIME))\r
2520 ) {\r
2521 TimeChangeFlag = TRUE;\r
2522 }\r
2523\r
2524 //\r
2525 // All done if there are no change requests being made.\r
2526 //\r
2527 if (!(AttrChangeFlag || NameChangeFlag || SizeChangeFlag || TimeChangeFlag)) {\r
2528 Status = EFI_SUCCESS;\r
2529 goto Done;\r
2530 }\r
2531\r
2532 //\r
2533 // Set file or directory information.\r
2534 //\r
2535 OldAttr = PrivateFile->WinNtThunk->GetFileAttributes (OldFileName);\r
2536\r
2537 //\r
2538 // Name change.\r
2539 //\r
2540 if (NameChangeFlag) {\r
2541 //\r
2542 // Close the handles first\r
2543 //\r
2544 if (PrivateFile->IsOpenedByRead) {\r
2545 Status = EFI_ACCESS_DENIED;\r
2546 goto Done;\r
2547 }\r
2548\r
2549 for (CharPointer = NewFileName; *CharPointer != 0 && *CharPointer != L'/'; CharPointer++) {\r
2550 }\r
2551\r
2552 if (*CharPointer != 0) {\r
2553 Status = EFI_ACCESS_DENIED;\r
2554 goto Done;\r
2555 }\r
2556\r
2557 if (PrivateFile->LHandle != INVALID_HANDLE_VALUE) {\r
2558 if (PrivateFile->IsDirectoryPath) {\r
2559 PrivateFile->WinNtThunk->FindClose (PrivateFile->LHandle);\r
2560 } else {\r
2561 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->LHandle);\r
2562 PrivateFile->LHandle = INVALID_HANDLE_VALUE;\r
2563 }\r
2564 }\r
2565\r
2566 if (PrivateFile->IsDirectoryPath && PrivateFile->DirHandle != INVALID_HANDLE_VALUE) {\r
2567 PrivateFile->WinNtThunk->CloseHandle (PrivateFile->DirHandle);\r
2568 PrivateFile->DirHandle = INVALID_HANDLE_VALUE;\r
2569 }\r
2570\r
2571 NtStatus = PrivateFile->WinNtThunk->MoveFile (OldFileName, NewFileName);\r
2572\r
2573 if (NtStatus) {\r
2574 //\r
2575 // modify file name\r
2576 //\r
2577 FreePool (PrivateFile->FileName);\r
2578\r
2579 PrivateFile->FileName = AllocatePool (StrSize (NewFileName));\r
2580 if (PrivateFile->FileName == NULL) {\r
2581 Status = EFI_OUT_OF_RESOURCES;\r
2582 goto Done;\r
2583 }\r
2584\r
2585 StrCpy (PrivateFile->FileName, NewFileName);\r
2586\r
a00ec39b 2587 Size = StrSize (NewFileName);\r
2588 Size += StrSize (L"\\*");\r
2589 TempFileName = AllocatePool (Size);\r
068eac81 2590\r
2591 StrCpy (TempFileName, NewFileName);\r
2592\r
2593 if (!PrivateFile->IsDirectoryPath) {\r
2594 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (\r
2595 TempFileName,\r
2596 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2597 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2598 NULL,\r
2599 OPEN_EXISTING,\r
2600 0,\r
2601 NULL\r
2602 );\r
2603\r
2604 FreePool (TempFileName);\r
2605\r
2606 //\r
2607 // Flush buffers just in case\r
2608 //\r
2609 if (PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) == 0) {\r
2610 Status = EFI_DEVICE_ERROR;\r
2611 goto Done;\r
2612 }\r
2613 } else {\r
2614 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (\r
2615 TempFileName,\r
2616 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2617 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2618 NULL,\r
2619 OPEN_EXISTING,\r
2620 FILE_FLAG_BACKUP_SEMANTICS,\r
2621 NULL\r
2622 );\r
2623\r
2624 StrCat (TempFileName, L"\\*");\r
2625 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);\r
2626\r
2627 FreePool (TempFileName);\r
2628 }\r
2629 } else {\r
41e9426b 2630 Status = EFI_ACCESS_DENIED;\r
068eac81 2631Reopen: ;\r
068eac81 2632\r
2633 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (OldFileName, OldAttr);\r
2634\r
2635 if (!NtStatus) {\r
2636 goto Done;\r
2637 }\r
2638\r
a00ec39b 2639 Size = StrSize (OldFileName);\r
2640 Size += StrSize (L"\\*");\r
2641 TempFileName = AllocatePool (Size);\r
068eac81 2642\r
2643 StrCpy (TempFileName, OldFileName);\r
2644\r
2645 if (!PrivateFile->IsDirectoryPath) {\r
2646 PrivateFile->LHandle = PrivateFile->WinNtThunk->CreateFile (\r
2647 TempFileName,\r
2648 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2649 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2650 NULL,\r
2651 OPEN_EXISTING,\r
2652 0,\r
2653 NULL\r
2654 );\r
2655 } else {\r
2656 PrivateFile->DirHandle = PrivateFile->WinNtThunk->CreateFile (\r
2657 TempFileName,\r
2658 PrivateFile->IsOpenedByRead ? GENERIC_READ : GENERIC_READ | GENERIC_WRITE,\r
2659 FILE_SHARE_READ | FILE_SHARE_WRITE,\r
2660 NULL,\r
2661 OPEN_EXISTING,\r
2662 FILE_FLAG_BACKUP_SEMANTICS,\r
2663 NULL\r
2664 );\r
2665\r
2666 StrCat (TempFileName, L"\\*");\r
2667 PrivateFile->LHandle = PrivateFile->WinNtThunk->FindFirstFile (TempFileName, &FindBuf);\r
2668 }\r
2669\r
2670 FreePool (TempFileName);\r
2671\r
2672 goto Done;\r
2673\r
2674 }\r
2675 }\r
2676\r
2677 //\r
2678 // Size change\r
2679 //\r
2680 if (SizeChangeFlag) {\r
2681 if (PrivateFile->IsDirectoryPath) {\r
2682 Status = EFI_UNSUPPORTED;\r
2683 goto Done;\r
2684 }\r
2685\r
2686 if (PrivateFile->IsOpenedByRead || OldFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2687 Status = EFI_ACCESS_DENIED;\r
2688 goto Done;\r
2689 }\r
2690\r
2691 Status = This->GetPosition (This, &CurPos);\r
2692 if (EFI_ERROR (Status)) {\r
2693 goto Done;\r
2694 }\r
2695\r
2696 Status = This->SetPosition (This, NewFileInfo->FileSize);\r
2697 if (EFI_ERROR (Status)) {\r
2698 goto Done;\r
2699 }\r
2700\r
2701 if (PrivateFile->WinNtThunk->SetEndOfFile (PrivateFile->LHandle) == 0) {\r
2702 Status = EFI_DEVICE_ERROR;\r
2703 goto Done;\r
2704 }\r
2705\r
2706 Status = This->SetPosition (This, CurPos);\r
2707 if (EFI_ERROR (Status)) {\r
2708 goto Done;\r
2709 }\r
2710 }\r
2711\r
2712 //\r
2713 // Time change\r
2714 //\r
2715 if (TimeChangeFlag) {\r
2716\r
2717 NewCreationSystemTime.wYear = NewFileInfo->CreateTime.Year;\r
2718 NewCreationSystemTime.wMonth = NewFileInfo->CreateTime.Month;\r
2719 NewCreationSystemTime.wDay = NewFileInfo->CreateTime.Day;\r
2720 NewCreationSystemTime.wHour = NewFileInfo->CreateTime.Hour;\r
2721 NewCreationSystemTime.wMinute = NewFileInfo->CreateTime.Minute;\r
2722 NewCreationSystemTime.wSecond = NewFileInfo->CreateTime.Second;\r
2723 NewCreationSystemTime.wMilliseconds = 0;\r
2724\r
2725 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (\r
2726 &NewCreationSystemTime,\r
2727 &NewCreationFileTime\r
2728 )) {\r
2729 goto Done;\r
2730 }\r
2731\r
f515069c
ED
2732 if (!PrivateFile->WinNtThunk->LocalFileTimeToFileTime (\r
2733 &NewCreationFileTime,\r
2734 &NewCreationFileTime\r
2735 )) {\r
2736 goto Done;\r
2737 }\r
2738\r
068eac81 2739 NewLastAccessSystemTime.wYear = NewFileInfo->LastAccessTime.Year;\r
2740 NewLastAccessSystemTime.wMonth = NewFileInfo->LastAccessTime.Month;\r
2741 NewLastAccessSystemTime.wDay = NewFileInfo->LastAccessTime.Day;\r
2742 NewLastAccessSystemTime.wHour = NewFileInfo->LastAccessTime.Hour;\r
2743 NewLastAccessSystemTime.wMinute = NewFileInfo->LastAccessTime.Minute;\r
2744 NewLastAccessSystemTime.wSecond = NewFileInfo->LastAccessTime.Second;\r
2745 NewLastAccessSystemTime.wMilliseconds = 0;\r
2746\r
2747 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (\r
2748 &NewLastAccessSystemTime,\r
2749 &NewLastAccessFileTime\r
2750 )) {\r
2751 goto Done;\r
2752 }\r
2753\r
f515069c
ED
2754 if (!PrivateFile->WinNtThunk->LocalFileTimeToFileTime (\r
2755 &NewLastAccessFileTime,\r
2756 &NewLastAccessFileTime\r
2757 )) {\r
2758 goto Done;\r
2759 }\r
2760\r
068eac81 2761 NewLastWriteSystemTime.wYear = NewFileInfo->ModificationTime.Year;\r
2762 NewLastWriteSystemTime.wMonth = NewFileInfo->ModificationTime.Month;\r
2763 NewLastWriteSystemTime.wDay = NewFileInfo->ModificationTime.Day;\r
2764 NewLastWriteSystemTime.wHour = NewFileInfo->ModificationTime.Hour;\r
2765 NewLastWriteSystemTime.wMinute = NewFileInfo->ModificationTime.Minute;\r
2766 NewLastWriteSystemTime.wSecond = NewFileInfo->ModificationTime.Second;\r
2767 NewLastWriteSystemTime.wMilliseconds = 0;\r
2768\r
2769 if (!PrivateFile->WinNtThunk->SystemTimeToFileTime (\r
2770 &NewLastWriteSystemTime,\r
2771 &NewLastWriteFileTime\r
2772 )) {\r
2773 goto Done;\r
2774 }\r
2775\r
f515069c
ED
2776 if (!PrivateFile->WinNtThunk->LocalFileTimeToFileTime (\r
2777 &NewLastWriteFileTime,\r
2778 &NewLastWriteFileTime\r
2779 )) {\r
2780 goto Done;\r
2781 }\r
2782\r
068eac81 2783 if (!PrivateFile->WinNtThunk->SetFileTime (\r
2784 PrivateFile->IsDirectoryPath ? PrivateFile->DirHandle : PrivateFile->LHandle,\r
2785 &NewCreationFileTime,\r
2786 &NewLastAccessFileTime,\r
2787 &NewLastWriteFileTime\r
2788 )) {\r
2789 Status = EFI_DEVICE_ERROR;\r
2790 goto Done;\r
2791 }\r
2792\r
2793 }\r
2794\r
2795 //\r
2796 // No matter about AttrChangeFlag, Attribute must be set.\r
2797 // Because operation before may cause attribute change.\r
2798 //\r
2799 NewAttr = OldAttr;\r
2800\r
2801 if (NewFileInfo->Attribute & EFI_FILE_ARCHIVE) {\r
2802 NewAttr |= FILE_ATTRIBUTE_ARCHIVE;\r
2803 } else {\r
2804 NewAttr &= ~FILE_ATTRIBUTE_ARCHIVE;\r
2805 }\r
2806\r
2807 if (NewFileInfo->Attribute & EFI_FILE_HIDDEN) {\r
2808 NewAttr |= FILE_ATTRIBUTE_HIDDEN;\r
2809 } else {\r
2810 NewAttr &= ~FILE_ATTRIBUTE_HIDDEN;\r
2811 }\r
2812\r
2813 if (NewFileInfo->Attribute & EFI_FILE_SYSTEM) {\r
2814 NewAttr |= FILE_ATTRIBUTE_SYSTEM;\r
2815 } else {\r
2816 NewAttr &= ~FILE_ATTRIBUTE_SYSTEM;\r
2817 }\r
2818\r
2819 if (NewFileInfo->Attribute & EFI_FILE_READ_ONLY) {\r
2820 NewAttr |= FILE_ATTRIBUTE_READONLY;\r
2821 } else {\r
2822 NewAttr &= ~FILE_ATTRIBUTE_READONLY;\r
2823 }\r
2824\r
2825 NtStatus = PrivateFile->WinNtThunk->SetFileAttributes (NewFileName, NewAttr);\r
2826\r
2827 if (!NtStatus) {\r
41e9426b 2828 Status = EFI_DEVICE_ERROR;\r
068eac81 2829 goto Reopen;\r
2830 }\r
2831\r
2832Done:\r
2833 if (OldFileInfo != NULL) {\r
2834 FreePool (OldFileInfo);\r
2835 }\r
2836\r
2837 if (OldFileName != NULL) {\r
2838 FreePool (OldFileName);\r
2839 }\r
2840\r
2841 if (NewFileName != NULL) {\r
2842 FreePool (NewFileName);\r
2843 }\r
2844\r
2845 gBS->RestoreTPL (OldTpl);\r
2846 return Status;\r
2847}\r
2848\r
2849EFI_STATUS\r
2850EFIAPI\r
2851WinNtSimpleFileSystemFlush (\r
c0cf06d6 2852 IN EFI_FILE_PROTOCOL *This\r
068eac81 2853 )\r
2854/*++\r
2855\r
2856Routine Description:\r
2857\r
2858 Flush all modified data to the media.\r
2859\r
2860Arguments:\r
2861\r
2862 This - Pointer to an opened file handle.\r
2863\r
2864Returns:\r
2865\r
2866 EFI_SUCCESS - The data has been flushed.\r
2867\r
2868 EFI_NO_MEDIA - The device has no media.\r
2869\r
2870 EFI_DEVICE_ERROR - The device reported an error.\r
2871\r
2872 EFI_VOLUME_CORRUPTED - The file system structures have been corrupted.\r
2873\r
2874 EFI_WRITE_PROTECTED - The file, directory, volume, or device is write protected.\r
2875\r
2876 EFI_ACCESS_DENIED - The file was opened read-only.\r
2877\r
2878 EFI_VOLUME_FULL - The volume is full.\r
2879\r
2880--*/\r
2881// TODO: EFI_INVALID_PARAMETER - add return value to function comment\r
2882{\r
2883 BY_HANDLE_FILE_INFORMATION FileInfo;\r
2884 WIN_NT_EFI_FILE_PRIVATE *PrivateFile;\r
2885 EFI_STATUS Status;\r
2886 EFI_TPL OldTpl;\r
2887\r
2888 if (This == NULL) {\r
2889 return EFI_INVALID_PARAMETER;\r
2890 }\r
2891\r
2892 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
2893\r
2894 PrivateFile = WIN_NT_EFI_FILE_PRIVATE_DATA_FROM_THIS (This);\r
2895\r
2896 if (PrivateFile->LHandle == INVALID_HANDLE_VALUE) {\r
2897 Status = EFI_DEVICE_ERROR;\r
2898 goto Done;\r
2899 }\r
2900\r
2901 if (PrivateFile->IsDirectoryPath) {\r
2902 Status = EFI_SUCCESS;\r
2903 goto Done;\r
2904 }\r
2905\r
2906 if (PrivateFile->IsOpenedByRead) {\r
2907 Status = EFI_ACCESS_DENIED;\r
2908 goto Done;\r
2909 }\r
2910\r
2911 PrivateFile->WinNtThunk->GetFileInformationByHandle (PrivateFile->LHandle, &FileInfo);\r
2912\r
2913 if (FileInfo.dwFileAttributes & FILE_ATTRIBUTE_READONLY) {\r
2914 Status = EFI_ACCESS_DENIED;\r
2915 goto Done;\r
2916 }\r
2917\r
2918 Status = PrivateFile->WinNtThunk->FlushFileBuffers (PrivateFile->LHandle) ? EFI_SUCCESS : EFI_DEVICE_ERROR;\r
2919\r
2920Done:\r
2921 gBS->RestoreTPL (OldTpl);\r
2922 return Status;\r
2923 //\r
2924 // bugbug: - Use Windows error reporting.\r
2925 //\r
2926}\r
2927\r
2928\r