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