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