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