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