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