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