ReactOS 0.4.16-dev-2284-g3529151
ntfs.c
Go to the documentation of this file.
1/*
2 * FreeLoader NTFS support
3 * Copyright (C) 2004 Filip Navara <xnavara@volny.cz>
4 * Copyright (C) 2009-2010 Hervé Poussineau
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 */
20
21/*
22 * Limitations:
23 * - No support for compressed files.
24 * - May crash on corrupted filesystem.
25 */
26
27#ifndef _M_ARM
28#include <freeldr.h>
29
30#include <debug.h>
32
33#define TAG_NTFS_CONTEXT 'CftN'
34#define TAG_NTFS_LIST 'LftN'
35#define TAG_NTFS_MFT 'MftN'
36#define TAG_NTFS_INDEX_REC 'IftN'
37#define TAG_NTFS_BITMAP 'BftN'
38#define TAG_NTFS_FILE 'FftN'
39#define TAG_NTFS_VOLUME 'VftN'
40#define TAG_NTFS_DATA 'DftN'
41
42#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION 8
43
44typedef struct _NTFS_VOLUME_INFO
45{
51 /* FIXME: MFTContext is never freed. */
56
58
60{
61 if (AttrRecord->IsNonResident)
62 return AttrRecord->NonResident.DataSize;
63 else
64 return AttrRecord->Resident.ValueLength;
65}
66
67static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
68{
69 UCHAR DataRunOffsetSize;
70 UCHAR DataRunLengthSize;
71 CHAR i;
72
73 DataRunOffsetSize = (*DataRun >> 4) & 0xF;
74 DataRunLengthSize = *DataRun & 0xF;
75 *DataRunOffset = 0;
76 *DataRunLength = 0;
77 DataRun++;
78 for (i = 0; i < DataRunLengthSize; i++)
79 {
80 *DataRunLength += ((ULONG64)*DataRun) << (i * 8);
81 DataRun++;
82 }
83
84 /* NTFS 3+ sparse files */
85 if (DataRunOffsetSize == 0)
86 {
87 *DataRunOffset = -1;
88 }
89 else
90 {
91 for (i = 0; i < DataRunOffsetSize - 1; i++)
92 {
93 *DataRunOffset += ((ULONG64)*DataRun) << (i * 8);
94 DataRun++;
95 }
96 /* The last byte contains sign so we must process it different way. */
97 *DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset;
98 }
99
100 TRACE("DataRunOffsetSize: %x\n", DataRunOffsetSize);
101 TRACE("DataRunLengthSize: %x\n", DataRunLengthSize);
102 TRACE("DataRunOffset: %x\n", *DataRunOffset);
103 TRACE("DataRunLength: %x\n", *DataRunLength);
104
105 return DataRun;
106}
107
109{
111
114 RtlCopyMemory(&Context->Record, AttrRecord, AttrRecord->Length);
115 if (AttrRecord->IsNonResident)
116 {
117 LONGLONG DataRunOffset;
118 ULONGLONG DataRunLength;
119
120 Context->CacheRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset;
121 Context->CacheRunOffset = 0;
122 Context->CacheRun = NtfsDecodeRun(Context->CacheRun, &DataRunOffset, &DataRunLength);
123 Context->CacheRunLength = DataRunLength;
124 if (DataRunOffset != -1)
125 {
126 /* Normal run. */
127 Context->CacheRunStartLCN =
128 Context->CacheRunLastLCN = DataRunOffset;
129 }
130 else
131 {
132 /* Sparse run. */
133 Context->CacheRunStartLCN = -1;
134 Context->CacheRunLastLCN = 0;
135 }
136 Context->CacheRunCurrentOffset = 0;
137 }
138
139 return Context;
140}
141
143{
145}
146
148{
150 ULONG Count;
153
154 TRACE("NtfsDiskRead - Offset: %I64u Length: %I64u\n", Offset, Length);
155
156 //
157 // I. Read partial first sector if needed
158 //
159 if (Offset % Volume->BootSector.BytesPerSector)
160 {
161 Position.QuadPart = Offset & ~(Volume->BootSector.BytesPerSector - 1);
162 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
163 if (Status != ESUCCESS)
164 return FALSE;
165 Status = ArcRead(Volume->DeviceId, Volume->TemporarySector, Volume->BootSector.BytesPerSector, &Count);
166 if (Status != ESUCCESS || Count != Volume->BootSector.BytesPerSector)
167 return FALSE;
168 ReadLength = (USHORT)min(Length, Volume->BootSector.BytesPerSector - (Offset % Volume->BootSector.BytesPerSector));
169
170 //
171 // Copy interesting data
172 //
174 &Volume->TemporarySector[Offset % Volume->BootSector.BytesPerSector],
175 ReadLength);
176
177 //
178 // Move to unfilled buffer part
179 //
183 }
184
185 //
186 // II. Read all complete blocks
187 //
188 if (Length >= Volume->BootSector.BytesPerSector)
189 {
190 Position.QuadPart = Offset;
191 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
192 if (Status != ESUCCESS)
193 return FALSE;
194 ReadLength = Length & ~(Volume->BootSector.BytesPerSector - 1);
195 Status = ArcRead(Volume->DeviceId, Buffer, ReadLength, &Count);
196 if (Status != ESUCCESS || Count != ReadLength)
197 return FALSE;
198
199 //
200 // Move to unfilled buffer part
201 //
205 }
206
207 //
208 // III. Read the rest of data
209 //
210 if (Length)
211 {
212 Position.QuadPart = Offset;
213 Status = ArcSeek(Volume->DeviceId, &Position, SeekAbsolute);
214 if (Status != ESUCCESS)
215 return FALSE;
216 Status = ArcRead(Volume->DeviceId, Buffer, (ULONG)Length, &Count);
217 if (Status != ESUCCESS || Count != Length)
218 return FALSE;
219 }
220
221 return TRUE;
222}
223
225{
226 ULONGLONG LastLCN;
227 PUCHAR DataRun;
228 LONGLONG DataRunOffset;
229 ULONGLONG DataRunLength;
230 LONGLONG DataRunStartLCN;
231 ULONGLONG CurrentOffset;
233 ULONG AlreadyRead;
234
235 if (!Context->Record.IsNonResident)
236 {
237 if (Offset > Context->Record.Resident.ValueLength)
238 return 0;
239 if (Offset + Length > Context->Record.Resident.ValueLength)
240 Length = (ULONG)(Context->Record.Resident.ValueLength - Offset);
241 RtlCopyMemory(Buffer, (PCHAR)&Context->Record + Context->Record.Resident.ValueOffset + Offset, Length);
242 return Length;
243 }
244
245 /*
246 * Non-resident attribute
247 */
248
249 /*
250 * I. Find the corresponding start data run.
251 */
252
253 AlreadyRead = 0;
254
255 // FIXME: Cache seems to be non-working. Disable it for now
256 //if(Context->CacheRunOffset <= Offset && Offset < Context->CacheRunOffset + Context->CacheRunLength * Volume->ClusterSize)
257 if (0)
258 {
259 DataRun = Context->CacheRun;
260 LastLCN = Context->CacheRunLastLCN;
261 DataRunStartLCN = Context->CacheRunStartLCN;
262 DataRunLength = Context->CacheRunLength;
263 CurrentOffset = Context->CacheRunCurrentOffset;
264 }
265 else
266 {
267 LastLCN = 0;
268 DataRun = (PUCHAR)&Context->Record + Context->Record.NonResident.MappingPairsOffset;
269 CurrentOffset = 0;
270
271 while (1)
272 {
273 DataRun = NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
274 if (DataRunOffset != -1)
275 {
276 /* Normal data run. */
277 DataRunStartLCN = LastLCN + DataRunOffset;
278 LastLCN = DataRunStartLCN;
279 }
280 else
281 {
282 /* Sparse data run. */
283 DataRunStartLCN = -1;
284 }
285
286 if (Offset >= CurrentOffset &&
287 Offset < CurrentOffset + (DataRunLength * Volume->ClusterSize))
288 {
289 break;
290 }
291
292 if (*DataRun == 0)
293 {
294 return AlreadyRead;
295 }
296
297 CurrentOffset += DataRunLength * Volume->ClusterSize;
298 }
299 }
300
301 /*
302 * II. Go through the run list and read the data
303 */
304
305 ReadLength = (ULONG)min(DataRunLength * Volume->ClusterSize - (Offset - CurrentOffset), Length);
306 if (DataRunStartLCN == -1)
308 if (DataRunStartLCN == -1 || NtfsDiskRead(Volume, DataRunStartLCN * Volume->ClusterSize + Offset - CurrentOffset, ReadLength, Buffer))
309 {
312 AlreadyRead += ReadLength;
313
314 if (ReadLength == DataRunLength * Volume->ClusterSize - (Offset - CurrentOffset))
315 {
316 CurrentOffset += DataRunLength * Volume->ClusterSize;
317 DataRun = NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
318 if (DataRunOffset != (ULONGLONG)-1)
319 {
320 DataRunStartLCN = LastLCN + DataRunOffset;
321 LastLCN = DataRunStartLCN;
322 }
323 else
324 DataRunStartLCN = -1;
325 }
326
327 while (Length > 0)
328 {
329 ReadLength = (ULONG)min(DataRunLength * Volume->ClusterSize, Length);
330 if (DataRunStartLCN == -1)
332 else if (!NtfsDiskRead(Volume, DataRunStartLCN * Volume->ClusterSize, ReadLength, Buffer))
333 break;
334
337 AlreadyRead += ReadLength;
338
339 /* We finished this request, but there still data in this data run. */
340 if (Length == 0 && ReadLength != DataRunLength * Volume->ClusterSize)
341 break;
342
343 /*
344 * Go to next run in the list.
345 */
346
347 if (*DataRun == 0)
348 break;
349 CurrentOffset += DataRunLength * Volume->ClusterSize;
350 DataRun = NtfsDecodeRun(DataRun, &DataRunOffset, &DataRunLength);
351 if (DataRunOffset != -1)
352 {
353 /* Normal data run. */
354 DataRunStartLCN = LastLCN + DataRunOffset;
355 LastLCN = DataRunStartLCN;
356 }
357 else
358 {
359 /* Sparse data run. */
360 DataRunStartLCN = -1;
361 }
362 } /* while */
363
364 } /* if Disk */
365
366 Context->CacheRun = DataRun;
367 Context->CacheRunOffset = Offset + AlreadyRead;
368 Context->CacheRunStartLCN = DataRunStartLCN;
369 Context->CacheRunLength = DataRunLength;
370 Context->CacheRunLastLCN = LastLCN;
371 Context->CacheRunCurrentOffset = CurrentOffset;
372
373 return AlreadyRead;
374}
375
378 ULONGLONG CurrentMftIndex,
379 PNTFS_ATTR_RECORD AttrRecord,
380 PNTFS_ATTR_RECORD AttrRecordEnd,
381 ULONG Type,
382 const WCHAR *Name,
383 ULONG NameLength,
384 ULONG RecursionLimit,
387
390 ULONGLONG ParentMftIndex,
391 PNTFS_ATTR_LIST_ATTR AttrListRecord,
392 PNTFS_ATTR_LIST_ATTR AttrListRecordEnd,
393 ULONG Type,
394 const WCHAR *Name,
395 ULONG NameLength,
396 ULONG RecursionLimit)
397{
398 ULONGLONG PrevMftIndex = -1;
400 PNTFS_MFT_RECORD MftRecord;
401 if (RecursionLimit < 1)
402 return NULL;
403
404 MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
405 if (!MftRecord)
406 return NULL;
407
408 while (AttrListRecord < AttrListRecordEnd)
409 {
410 ULONGLONG MftIndex = AttrListRecord->BaseFileRef & NTFS_MFT_MASK;
411 ULONG AttrType = AttrListRecord->Type;
412 ULONG AttrId = AttrListRecord->AttrId;
413
414 if (AttrType == NTFS_ATTR_TYPE_END)
415 break;
416
417 TRACE("RecursionLimit = %u, AttrType = 0x%x, MftIndex = %I64u\n", RecursionLimit, AttrType, MftIndex);
418
419 if (MftIndex == ParentMftIndex)
420 {
421 TRACE("Skipping unnecessary recursion level!\n");
422 goto skip;
423 }
424
425 if (AttrType == Type &&
426 AttrListRecord->NameLength == NameLength)
427 {
428 PWCHAR AttrListName;
429
430 AttrListName = (PWCHAR)((PCHAR)AttrListRecord + AttrListRecord->NameOffset);
431 if (RtlEqualMemory(AttrListName, Name, NameLength * sizeof(WCHAR)))
432 {
433 PNTFS_ATTR_RECORD AttrRecord;
434 PNTFS_ATTR_RECORD AttrRecordEnd;
435
436 if (PrevMftIndex != MftIndex)
437 {
438 PrevMftIndex = MftIndex;
439 if (!NtfsReadMftRecord(Volume, MftIndex, MftRecord))
440 goto skip;
441 }
442
443 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
444 AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
445
447 AttrRecord, AttrRecordEnd,
448 Type, Name, NameLength,
449 RecursionLimit - 1, AttrId);
450 if (Context)
451 break;
452 }
453 }
454
455skip:
456 if (AttrListRecord->RecLength == 0)
457 break;
458 AttrListRecord = (PNTFS_ATTR_LIST_ATTR)((PCHAR)AttrListRecord + AttrListRecord->RecLength);
459 }
460
461 if (MftRecord)
462 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
463
464 return Context;
465}
466
469 ULONGLONG CurrentMftIndex,
470 PNTFS_ATTR_RECORD AttrRecord,
471 PNTFS_ATTR_RECORD AttrRecordEnd,
472 ULONG Type,
473 const WCHAR *Name,
474 ULONG NameLength,
475 ULONG RecursionLimit,
477{
479 PNTFS_ATTR_CONTEXT ListContext = NULL;
480 PVOID ListBuffer = NULL;
481 ULONGLONG ListSize = 0;
482 if (RecursionLimit < 1)
483 return NULL;
484
485 while (AttrRecord < AttrRecordEnd)
486 {
487 ULONG AttrType = AttrRecord->Type;
488 ULONG AttrInstance = AttrRecord->Instance;
489
490 if (AttrType == NTFS_ATTR_TYPE_END)
491 break;
492
493 TRACE("RecursionLimit = %u, AttrType = 0x%x\n", RecursionLimit, AttrType);
494
495 if (ListContext)
496 NtfsReleaseAttributeContext(ListContext);
497 if (ListBuffer)
498 FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
499
500 ListContext = ListBuffer = NULL;
501
502 /* Limit the $ATTRIBUTE_LIST recursion or else infinity loop */
503 if (AttrType != Type && AttrType == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && RecursionLimit >= 2)
504 {
505 PNTFS_ATTR_LIST_ATTR ListAttrRecord;
506 PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd;
507
508 ListContext = NtfsPrepareAttributeContext(AttrRecord);
509
510 ListSize = NtfsGetAttributeSize(&ListContext->Record);
511 if (ListSize <= 0xFFFFFFFF)
512 ListBuffer = FrLdrTempAlloc((ULONG)ListSize, TAG_NTFS_LIST);
513 else
514 ListBuffer = NULL;
515
516 if (!ListBuffer)
517 {
518 TRACE("Failed to allocate memory: %x\n", (ULONG)ListSize);
519 goto skip;
520 }
521
522 ListAttrRecord = (PNTFS_ATTR_LIST_ATTR)ListBuffer;
523 ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR)((PCHAR)ListBuffer + ListSize);
524
525 if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
526 {
527 Context = NtfsFindAttributeHelperList(Volume, CurrentMftIndex,
528 ListAttrRecord, ListAttrRecordEnd,
529 Type, Name, NameLength,
530 RecursionLimit - 1);
531
532 if (Context != NULL)
533 break;
534 }
535 }
536
537 if (AttrType == Type &&
538 AttrRecord->NameLength == NameLength &&
539 /* HACK for ntfs3 driver on linux! Because the ntfs3 likes to generate invalid
540 * attribute size when mft record increases and I don't know how I will handle this */
541 NtfsGetAttributeSize(AttrRecord) != 0 &&
542 (Instance == (ULONG)-1 || AttrInstance == Instance))
543 {
544 PWCHAR AttrName;
545
546 AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
547 if (RtlEqualMemory(AttrName, Name, NameLength * sizeof(WCHAR)))
548 {
549 /* Found it, fill up the context and return */
551 break;
552 }
553 }
554
555skip:
556 if (AttrRecord->Length == 0)
557 break;
558 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
559 }
560
561 if (ListContext)
562 NtfsReleaseAttributeContext(ListContext);
563 if (ListBuffer)
564 FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
565
566 return Context;
567}
568
570{
571 PNTFS_ATTR_RECORD AttrRecord;
572 PNTFS_ATTR_RECORD AttrRecordEnd;
573 ULONG NameLength;
574
575 AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
576 AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
577 for (NameLength = 0; Name[NameLength] != 0; NameLength++)
578 ;
579
580 return NtfsFindAttributeHelper(Volume, MftIndex, AttrRecord, AttrRecordEnd, Type, Name, NameLength, NTFS_MAX_ATTRIBUTE_LIST_RECURSION, -1);
581}
582
584{
585 USHORT *USA;
586 USHORT USANumber;
587 USHORT USACount;
588 USHORT *Block;
589
590 USA = (USHORT*)((PCHAR)Record + Record->USAOffset);
591 USANumber = *(USA++);
592 USACount = Record->USACount - 1; /* Exclude the USA Number. */
593 Block = (USHORT*)((PCHAR)Record + Volume->BootSector.BytesPerSector - 2);
594
595 while (USACount)
596 {
597 if (*Block != USANumber)
598 return FALSE;
599 *Block = *(USA++);
600 Block = (USHORT*)((PCHAR)Block + Volume->BootSector.BytesPerSector);
601 USACount--;
602 }
603
604 return TRUE;
605}
606
608{
610
611 BytesRead = NtfsReadAttribute(Volume, Volume->MFTContext, MFTIndex * Volume->MftRecordSize, (PCHAR)Buffer, Volume->MftRecordSize);
612 if (BytesRead != Volume->MftRecordSize)
613 return FALSE;
614
615 /* Apply update sequence array fixups. */
617}
618
619#if DBG
620VOID NtfsPrintFile(PNTFS_INDEX_ENTRY IndexEntry)
621{
624 CHAR AnsiFileName[256];
625 UCHAR i;
626
627 FileName = IndexEntry->FileName.FileName;
628 FileNameLength = min(IndexEntry->FileName.FileNameLength, 255);
629
630 for (i = 0; i < FileNameLength; i++)
631 AnsiFileName[i] = (CHAR)FileName[i];
632 AnsiFileName[i] = 0;
633
634 TRACE("- %s (%x)\n", AnsiFileName, (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK));
635}
636#endif
637
638static BOOLEAN
642 _In_ PNTFS_INDEX_ENTRY IndexEntry)
643{
644 PWCHAR EntryFileName;
645 UCHAR EntryFileNameLength;
646 UCHAR i;
647
648 EntryFileName = IndexEntry->FileName.FileName;
649 EntryFileNameLength = IndexEntry->FileName.FileNameLength;
650
651#if DBG
652 TRACE("%s ", FileName);
653 NtfsPrintFile(IndexEntry);
654#endif
655
656 if (FileNameLen != EntryFileNameLength)
657 return FALSE;
658
659 /*
660 * Always perform case-insensitive comparison for file names.
661 * This is necessary, because when modifying e.g. on Linux a Windows NTFS
662 * partition formatted with Windows itself, the NTLDR/BOOTMGR will boot
663 * normally ignoring the case of the paths.
664 */
665 for (i = 0; i < EntryFileNameLength; i++)
666 {
667 if (tolower(EntryFileName[i]) != tolower(FileName[i]))
668 return FALSE;
669 }
670
671 return TRUE;
672}
673
674static BOOLEAN
677 _In_ ULONGLONG MFTIndex,
679 _Out_ PULONGLONG OutMFTIndex,
681{
682 PNTFS_MFT_RECORD MftRecord;
683 //ULONG Magic;
684 PNTFS_ATTR_CONTEXT IndexRootCtx;
685 PNTFS_ATTR_CONTEXT IndexBitmapCtx;
686 PNTFS_ATTR_CONTEXT IndexAllocationCtx;
687 PNTFS_INDEX_ROOT IndexRoot;
688 ULONGLONG BitmapDataSize;
689 ULONGLONG IndexAllocationSize;
691 PCHAR IndexRecord;
692 PNTFS_INDEX_ENTRY IndexEntry, IndexEntryEnd;
693 ULONG RecordOffset;
694 ULONG IndexBlockSize;
696
698
699 MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
700 if (MftRecord == NULL)
701 {
702 return FALSE;
703 }
704
705 if (NtfsReadMftRecord(Volume, MFTIndex, MftRecord))
706 {
707 //Magic = MftRecord->Magic;
708
709 IndexRootCtx = NtfsFindAttribute(Volume, MftRecord, MFTIndex, NTFS_ATTR_TYPE_INDEX_ROOT, L"$I30");
710 if (IndexRootCtx == NULL)
711 {
712 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
713 return FALSE;
714 }
715
716 IndexRecord = FrLdrTempAlloc(Volume->IndexRecordSize, TAG_NTFS_INDEX_REC);
717 if (IndexRecord == NULL)
718 {
719 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
720 return FALSE;
721 }
722
723 NtfsReadAttribute(Volume, IndexRootCtx, 0, IndexRecord, Volume->IndexRecordSize);
724 IndexRoot = (PNTFS_INDEX_ROOT)IndexRecord;
725 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)&IndexRoot->IndexHeader + IndexRoot->IndexHeader.EntriesOffset);
726 /* Index root is always resident. */
727 IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexRootCtx->Record.Resident.ValueLength);
728 NtfsReleaseAttributeContext(IndexRootCtx);
729
730 TRACE("IndexRecordSize: %x IndexBlockSize: %x\n", Volume->IndexRecordSize, IndexRoot->IndexBlockSize);
731
732 while (IndexEntry < IndexEntryEnd &&
733 !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
734 {
735 if (NtfsCompareFileName(FileName, FileNameLen, IndexEntry))
736 {
737 *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
739 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
740 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
741 return TRUE;
742 }
743 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
744 }
745
746 if (IndexRoot->IndexHeader.Flags & NTFS_LARGE_INDEX)
747 {
748 TRACE("Large Index!\n");
749
750 IndexBlockSize = IndexRoot->IndexBlockSize;
751
752 IndexBitmapCtx = NtfsFindAttribute(Volume, MftRecord, MFTIndex, NTFS_ATTR_TYPE_BITMAP, L"$I30");
753 if (IndexBitmapCtx == NULL)
754 {
755 TRACE("Corrupted filesystem!\n");
756 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
757 return FALSE;
758 }
759 BitmapDataSize = NtfsGetAttributeSize(&IndexBitmapCtx->Record);
760 TRACE("BitmapDataSize: %x\n", (ULONG)BitmapDataSize);
761 if(BitmapDataSize <= 0xFFFFFFFF)
763 else
765
766 if (BitmapData == NULL)
767 {
768 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
769 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
770 return FALSE;
771 }
772 NtfsReadAttribute(Volume, IndexBitmapCtx, 0, BitmapData, (ULONG)BitmapDataSize);
773 NtfsReleaseAttributeContext(IndexBitmapCtx);
774
775 IndexAllocationCtx = NtfsFindAttribute(Volume, MftRecord, MFTIndex, NTFS_ATTR_TYPE_INDEX_ALLOCATION, L"$I30");
776 if (IndexAllocationCtx == NULL)
777 {
778 TRACE("Corrupted filesystem!\n");
780 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
781 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
782 return FALSE;
783 }
784 IndexAllocationSize = NtfsGetAttributeSize(&IndexAllocationCtx->Record);
785
786 RecordOffset = 0;
787
788 for (;;)
789 {
790 TRACE("RecordOffset: %x IndexAllocationSize: %x\n", RecordOffset, IndexAllocationSize);
791 for (; RecordOffset < IndexAllocationSize;)
792 {
793 UCHAR Bit = 1 << ((RecordOffset / IndexBlockSize) & 7);
794 ULONG Byte = (RecordOffset / IndexBlockSize) >> 3;
795 if ((BitmapData[Byte] & Bit))
796 break;
797 RecordOffset += IndexBlockSize;
798 }
799
800 if (RecordOffset >= IndexAllocationSize)
801 {
802 break;
803 }
804
805 NtfsReadAttribute(Volume, IndexAllocationCtx, RecordOffset, IndexRecord, IndexBlockSize);
806
807 if (!NtfsFixupRecord(Volume, (PNTFS_RECORD)IndexRecord))
808 {
809 break;
810 }
811
812 /* FIXME */
813 IndexEntry = (PNTFS_INDEX_ENTRY)(IndexRecord + 0x18 + *(USHORT *)(IndexRecord + 0x18));
814 IndexEntryEnd = (PNTFS_INDEX_ENTRY)(IndexRecord + IndexBlockSize);
815
816 while (IndexEntry < IndexEntryEnd &&
817 !(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
818 {
819 if (NtfsCompareFileName(FileName, FileNameLen, IndexEntry))
820 {
821 TRACE("File found\n");
822 *OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
824 NtfsReleaseAttributeContext(IndexAllocationCtx);
826 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
827 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
828 return TRUE;
829 }
830 IndexEntry = (PNTFS_INDEX_ENTRY)((PCHAR)IndexEntry + IndexEntry->Length);
831 }
832
833 RecordOffset += IndexBlockSize;
834 }
835
836 NtfsReleaseAttributeContext(IndexAllocationCtx);
838 }
839
840 FrLdrTempFree(IndexRecord, TAG_NTFS_INDEX_REC);
841 }
842 else
843 {
844 TRACE("Can't read MFT record\n");
845 }
846 FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
847
848 return FALSE;
849}
850
852{
853 ULONG NumberOfPathParts;
854 ULONG i;
855 ULONGLONG CurrentMFTIndex;
857 CHAR PathPart[261];
858
859 TRACE("NtfsLookupFile() FileName = %s\n", FileName);
860
861 CurrentMFTIndex = NTFS_FILE_ROOT;
862
863 /* Skip leading path separator, if any */
864 if (*FileName == '\\' || *FileName == '/')
865 ++FileName;
866 PathPart[0] = ANSI_NULL;
867
868 /* Figure out how many sub-directories we are nested in and loop once for each part */
869 NumberOfPathParts = FsGetNumPathParts(FileName);
870 for (i = 0; i < NumberOfPathParts; i++)
871 {
873
874 for (; (*FileName != '\\') && (*FileName != '/') && (*FileName != '\0'); FileName++)
875 ;
876 FileName++;
877
878 TRACE("- Lookup: %s\n", PathPart);
879 if (!NtfsFindMftRecord(Volume, CurrentMFTIndex, PathPart, &CurrentMFTIndex, &FileAttributes))
880 {
881 TRACE("- Failed\n");
882 return FALSE;
883 }
884 TRACE("- Lookup: %x\n", CurrentMFTIndex);
885 }
886
887 if (!NtfsReadMftRecord(Volume, CurrentMFTIndex, MftRecord))
888 {
889 TRACE("NtfsLookupFile: Can't read MFT record\n");
890 return FALSE;
891 }
892
893 FileHandle->DataContext = NtfsFindAttribute(Volume, MftRecord, CurrentMFTIndex, NTFS_ATTR_TYPE_DATA, L"");
894 if (FileHandle->DataContext == NULL)
895 {
896 TRACE("NtfsLookupFile: Can't find data attribute\n");
897 return FALSE;
898 }
899
900 /* Map the attributes to ARC file attributes */
901 FileHandle->Attributes = 0;
903 FileHandle->Attributes |= ReadOnlyFile;
905 FileHandle->Attributes |= HiddenFile;
907 FileHandle->Attributes |= SystemFile;
909 FileHandle->Attributes |= ArchiveFile;
911 FileHandle->Attributes |= DirectoryFile;
912
913 /* Copy the file name, perhaps truncated */
914 FileHandle->FileNameLength = (ULONG)strlen(PathPart);
915 FileHandle->FileNameLength = min(FileHandle->FileNameLength, sizeof(FileHandle->FileName) - 1);
916 RtlCopyMemory(FileHandle->FileName, PathPart, FileHandle->FileNameLength);
917
918 return TRUE;
919}
920
922{
924
927
928 return ESUCCESS;
929}
930
932{
934
936 Information->EndingAddress.QuadPart = NtfsGetAttributeSize(&FileHandle->DataContext->Record);
937 Information->CurrentAddress.QuadPart = FileHandle->Offset;
938
939 /* Set the ARC file attributes */
940 Information->Attributes = FileHandle->Attributes;
941
942 /* Copy the file name, perhaps truncated, and NUL-terminated */
943 Information->FileNameLength = min(FileHandle->FileNameLength, sizeof(Information->FileName) - 1);
944 RtlCopyMemory(Information->FileName, FileHandle->FileName, Information->FileNameLength);
945 Information->FileName[Information->FileNameLength] = ANSI_NULL;
946
947 TRACE("NtfsGetFileInformation(%lu) -> FileSize = %llu, FilePointer = 0x%llx\n",
948 FileId, Information->EndingAddress.QuadPart, Information->CurrentAddress.QuadPart);
949
950 return ESUCCESS;
951}
952
954{
957 PNTFS_MFT_RECORD MftRecord;
958 ULONG DeviceId;
959
960 //
961 // Check parameters
962 //
963 if (OpenMode != OpenReadOnly)
964 return EACCES;
965
966 //
967 // Get underlying device
968 //
969 DeviceId = FsGetDeviceId(*FileId);
970 Volume = NtfsVolumes[DeviceId];
971
972 TRACE("NtfsOpen() FileName = %s\n", Path);
973
974 //
975 // Allocate file structure
976 //
977 FileHandle = FrLdrTempAlloc(sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize,
979 if (!FileHandle)
980 {
981 return ENOMEM;
982 }
983 RtlZeroMemory(FileHandle, sizeof(NTFS_FILE_HANDLE) + Volume->MftRecordSize);
985
986 //
987 // Search file entry
988 //
989 MftRecord = (PNTFS_MFT_RECORD)(FileHandle + 1);
990 if (!NtfsLookupFile(Volume, Path, MftRecord, FileHandle))
991 {
993 return ENOENT;
994 }
995
997 return ESUCCESS;
998}
999
1001{
1003 ULONGLONG BytesRead64;
1004
1005 /* Read data */
1006 BytesRead64 = NtfsReadAttribute(FileHandle->Volume, FileHandle->DataContext, FileHandle->Offset, Buffer, N);
1007 FileHandle->Offset += BytesRead64;
1008 *Count = (ULONG)BytesRead64;
1009 if (BytesRead64 > 0)
1010 return ESUCCESS;
1011 else
1012 return EIO;
1013}
1014
1016{
1018 LARGE_INTEGER NewPosition = *Position;
1019
1020 switch (SeekMode)
1021 {
1022 case SeekAbsolute:
1023 break;
1024 case SeekRelative:
1025 NewPosition.QuadPart += FileHandle->Offset;
1026 break;
1027 default:
1028 ASSERT(FALSE);
1029 return EINVAL;
1030 }
1031
1032 if (NewPosition.QuadPart >= NtfsGetAttributeSize(&FileHandle->DataContext->Record))
1033 return EINVAL;
1034
1035 FileHandle->Offset = NewPosition.QuadPart;
1036 return ESUCCESS;
1037}
1038
1039
1047 _In_ ULONG DeviceId)
1048{
1050 ASSERT(Volume);
1051 return Volume->BootSector.VolumeSectorCount * Volume->BootSector.BytesPerSector;
1052}
1053
1054
1056{
1057 NtfsClose,
1059 NtfsOpen,
1060 NtfsRead,
1061 NtfsSeek,
1062 L"ntfs",
1063};
1064
1065const DEVVTBL* NtfsMount(ULONG DeviceId)
1066{
1069 ULONG Count;
1071
1072 TRACE("Enter NtfsMount(%lu)\n", DeviceId);
1073
1074 //
1075 // Allocate data for volume information
1076 //
1078 if (!Volume)
1079 return NULL;
1081
1082 //
1083 // Read the BootSector
1084 //
1085 Position.QuadPart = 0;
1086 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1087 if (Status != ESUCCESS)
1088 {
1090 return NULL;
1091 }
1092 Status = ArcRead(DeviceId, &Volume->BootSector, sizeof(Volume->BootSector), &Count);
1093 if (Status != ESUCCESS || Count != sizeof(Volume->BootSector))
1094 {
1096 return NULL;
1097 }
1098
1099 //
1100 // Check if BootSector is valid. If no, return early
1101 //
1102 if (!RtlEqualMemory(Volume->BootSector.SystemId, "NTFS", 4))
1103 {
1105 return NULL;
1106 }
1107
1108 //
1109 // Calculate cluster size and MFT record size
1110 //
1111 Volume->ClusterSize = Volume->BootSector.SectorsPerCluster * Volume->BootSector.BytesPerSector;
1112 if (Volume->BootSector.ClustersPerMftRecord > 0)
1113 Volume->MftRecordSize = Volume->BootSector.ClustersPerMftRecord * Volume->ClusterSize;
1114 else
1115 Volume->MftRecordSize = 1 << (-Volume->BootSector.ClustersPerMftRecord);
1116 if (Volume->BootSector.ClustersPerIndexRecord > 0)
1117 Volume->IndexRecordSize = Volume->BootSector.ClustersPerIndexRecord * Volume->ClusterSize;
1118 else
1119 Volume->IndexRecordSize = 1 << (-Volume->BootSector.ClustersPerIndexRecord);
1120
1121 TRACE("ClusterSize: 0x%x\n", Volume->ClusterSize);
1122 TRACE("ClustersPerMftRecord: %d\n", Volume->BootSector.ClustersPerMftRecord);
1123 TRACE("ClustersPerIndexRecord: %d\n", Volume->BootSector.ClustersPerIndexRecord);
1124 TRACE("MftRecordSize: 0x%x\n", Volume->MftRecordSize);
1125 TRACE("IndexRecordSize: 0x%x\n", Volume->IndexRecordSize);
1126
1127 //
1128 // Read MFT index
1129 //
1130 TRACE("Reading MFT index...\n");
1131 Volume->MasterFileTable = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
1132 if (!Volume->MasterFileTable)
1133 {
1135 return NULL;
1136 }
1137 Position.QuadPart = Volume->BootSector.MftLocation * Volume->ClusterSize;
1138 Status = ArcSeek(DeviceId, &Position, SeekAbsolute);
1139 if (Status != ESUCCESS)
1140 {
1141 FileSystemError("Failed to seek to Master File Table record.");
1142 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1144 return NULL;
1145 }
1146 Status = ArcRead(DeviceId, Volume->MasterFileTable, Volume->MftRecordSize, &Count);
1147 if (Status != ESUCCESS || Count != Volume->MftRecordSize)
1148 {
1149 FileSystemError("Failed to read the Master File Table record.");
1150 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1152 return NULL;
1153 }
1154
1155 //
1156 // Keep room to read partial sectors
1157 //
1158 Volume->TemporarySector = FrLdrTempAlloc(Volume->BootSector.BytesPerSector, TAG_NTFS_DATA);
1159 if (!Volume->TemporarySector)
1160 {
1161 FileSystemError("Failed to allocate memory.");
1162 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1164 return NULL;
1165 }
1166
1167 //
1168 // Keep device id
1169 //
1170 Volume->DeviceId = DeviceId;
1171
1172 //
1173 // Search DATA attribute
1174 //
1175 TRACE("Searching for DATA attribute...\n");
1176 Volume->MFTContext = NtfsFindAttribute(Volume, Volume->MasterFileTable, 0, NTFS_ATTR_TYPE_DATA, L"");
1177 if (!Volume->MFTContext)
1178 {
1179 FileSystemError("Can't find data attribute for Master File Table.");
1180 FrLdrTempFree(Volume->MasterFileTable, TAG_NTFS_MFT);
1182 return NULL;
1183 }
1184
1185 //
1186 // Remember NTFS volume information
1187 //
1188 NtfsVolumes[DeviceId] = Volume;
1189
1190 //
1191 // Return success
1192 //
1193 TRACE("NtfsMount(%lu) success\n", DeviceId);
1194 return &NtfsFuncTable;
1195}
1196
1197#endif
#define N
Definition: crc32.c:57
ULONG ReadLength
PRTL_UNICODE_STRING_BUFFER Path
Type
Definition: Type.h:7
unsigned char BOOLEAN
Definition: actypes.h:127
#define skip(...)
Definition: atltest.h:64
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define NTFS_FILE_ATTR_ARCHIVE
Definition: ntfs.h:73
struct NTFS_INDEX_ENTRY * PNTFS_INDEX_ENTRY
#define NTFS_ATTR_TYPE_INDEX_ROOT
Definition: ntfs.h:44
#define NTFS_FILE_ATTR_SYSTEM
Definition: ntfs.h:71
#define NTFS_FILE_ATTR_DIRECTORY
Definition: ntfs.h:74
#define NTFS_ATTR_TYPE_BITMAP
Definition: ntfs.h:46
#define NTFS_MFT_MASK
Definition: ntfs.h:76
#define NTFS_ATTR_TYPE_DATA
Definition: ntfs.h:43
#define NTFS_FILE_ROOT
Definition: ntfs.h:28
#define NTFS_INDEX_ENTRY_END
Definition: ntfs.h:61
#define NTFS_ATTR_TYPE_ATTRIBUTE_LIST
Definition: ntfs.h:37
#define NTFS_ATTR_TYPE_END
Definition: ntfs.h:50
#define NTFS_ATTR_TYPE_INDEX_ALLOCATION
Definition: ntfs.h:45
#define NTFS_LARGE_INDEX
Definition: ntfs.h:58
#define NTFS_FILE_ATTR_READONLY
Definition: ntfs.h:69
struct NTFS_MFT_RECORD * PNTFS_MFT_RECORD
#define NTFS_FILE_ATTR_HIDDEN
Definition: ntfs.h:70
struct NTFS_ATTR_LIST_ATTR * PNTFS_ATTR_LIST_ATTR
struct NTFS_INDEX_ROOT * PNTFS_INDEX_ROOT
ARC_STATUS ArcSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: fs.c:455
PVOID FsGetDeviceSpecific(ULONG FileId)
Definition: fs.c:709
ULONG FsGetNumPathParts(PCSTR Path)
Definition: fs.c:617
VOID FsSetDeviceSpecific(ULONG FileId, PVOID Specific)
Definition: fs.c:702
VOID FileSystemError(PCSTR ErrorString)
Definition: fs.c:471
ULONG FsGetDeviceId(ULONG FileId)
Definition: fs.c:716
#define MAX_FDS
Definition: fs.h:34
ARC_STATUS ArcRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: fs.c:448
VOID FsGetFirstNameFromPath(PCHAR Buffer, PCSTR Path)
Definition: fs.c:645
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
static BOOLEAN NtfsDiskRead(PNTFS_VOLUME_INFO Volume, ULONGLONG Offset, ULONGLONG Length, PCHAR Buffer)
Definition: ntfs.c:147
ARC_STATUS NtfsSeek(ULONG FileId, LARGE_INTEGER *Position, SEEKMODE SeekMode)
Definition: ntfs.c:1015
#define TAG_NTFS_CONTEXT
Definition: ntfs.c:33
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
Definition: ntfs.c:583
ULONGLONG NtfsGetVolumeSize(_In_ ULONG DeviceId)
Returns the size of the NTFS volume laid on the storage media device opened via DeviceId.
Definition: ntfs.c:1046
PNTFS_VOLUME_INFO NtfsVolumes[MAX_FDS]
Definition: ntfs.c:57
ARC_STATUS NtfsOpen(CHAR *Path, OPENMODE OpenMode, ULONG *FileId)
Definition: ntfs.c:953
ARC_STATUS NtfsGetFileInformation(ULONG FileId, FILEINFORMATION *Information)
Definition: ntfs.c:931
static BOOLEAN NtfsLookupFile(PNTFS_VOLUME_INFO Volume, PCSTR FileName, PNTFS_MFT_RECORD MftRecord, PNTFS_FILE_HANDLE FileHandle)
Definition: ntfs.c:851
#define TAG_NTFS_LIST
Definition: ntfs.c:34
#define TAG_NTFS_MFT
Definition: ntfs.c:35
static VOID NtfsReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: ntfs.c:142
static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: ntfs.c:224
static PNTFS_ATTR_CONTEXT NtfsPrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:108
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, ULONGLONG CurrentMftIndex, PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength, ULONG RecursionLimit, ULONG Instance)
Definition: ntfs.c:467
const DEVVTBL NtfsFuncTable
Definition: ntfs.c:1055
static BOOLEAN NtfsCompareFileName(_In_ PCCH FileName, _In_ SIZE_T FileNameLen, _In_ PNTFS_INDEX_ENTRY IndexEntry)
Definition: ntfs.c:639
#define TAG_NTFS_INDEX_REC
Definition: ntfs.c:36
struct _NTFS_VOLUME_INFO NTFS_VOLUME_INFO
#define TAG_NTFS_DATA
Definition: ntfs.c:40
#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION
Definition: ntfs.c:42
ARC_STATUS NtfsClose(ULONG FileId)
Definition: ntfs.c:921
static BOOLEAN NtfsFindMftRecord(_In_ PNTFS_VOLUME_INFO Volume, _In_ ULONGLONG MFTIndex, _In_ PCSTR FileName, _Out_ PULONGLONG OutMFTIndex, _Out_ PULONG FileAttributes)
Definition: ntfs.c:675
static ULONGLONG NtfsGetAttributeSize(PNTFS_ATTR_RECORD AttrRecord)
Definition: ntfs.c:59
static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_RECORD MftRecord, ULONGLONG MftIndex, ULONG Type, const WCHAR *Name)
Definition: ntfs.c:569
#define TAG_NTFS_BITMAP
Definition: ntfs.c:37
#define TAG_NTFS_FILE
Definition: ntfs.c:38
static PUCHAR NtfsDecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: ntfs.c:67
#define TAG_NTFS_VOLUME
Definition: ntfs.c:39
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
Definition: ntfs.c:607
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelperList(PNTFS_VOLUME_INFO Volume, ULONGLONG ParentMftIndex, PNTFS_ATTR_LIST_ATTR AttrListRecord, PNTFS_ATTR_LIST_ATTR AttrListRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength, ULONG RecursionLimit)
Definition: ntfs.c:388
const DEVVTBL * NtfsMount(ULONG DeviceId)
Definition: ntfs.c:1065
ARC_STATUS NtfsRead(ULONG FileId, VOID *Buffer, ULONG N, ULONG *Count)
Definition: ntfs.c:1000
while(CdLookupNextInitialFileDirent(IrpContext, Fcb, FileContext))
Dirent FileNameLen
Definition: dirsup.c:506
Definition: bufpool.h:45
LPWSTR Name
Definition: desk.c:124
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
unsigned char Byte
Definition: zlib.h:37
int CDECL tolower(int c)
Definition: ctype.c:572
#define ENOENT
Definition: errno.h:25
#define EINVAL
Definition: errno.h:44
#define ENOMEM
Definition: errno.h:35
#define EIO
Definition: errno.h:28
#define EACCES
Definition: errno.h:36
_ACRTIMP size_t __cdecl strlen(const char *)
Definition: string.c:1592
#define L(x)
Definition: resources.c:13
@ DirectoryFile
Definition: fatprocs.h:1047
struct _FileName FileName
Definition: fatprocs.h:897
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE _In_ ACCESS_MASK _In_ POBJECT_ATTRIBUTES _Out_ PIO_STATUS_BLOCK _In_opt_ PLARGE_INTEGER _In_ ULONG FileAttributes
Definition: fltkernel.h:1236
_Must_inspect_result_ _In_opt_ PFLT_INSTANCE _Out_ PHANDLE FileHandle
Definition: fltkernel.h:1231
_Must_inspect_result_ _In_ PFILE_OBJECT _In_opt_ HANDLE _In_ ULONG FileNameLength
Definition: fltkernel.h:1129
Status
Definition: gdiplustypes.h:25
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define RtlEqualMemory(dst, src, len)
Definition: kdvm.h:18
UNICODE_STRING Volume
Definition: fltkernel.h:1172
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 ULONG64
Definition: imports.h:198
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
int Count
Definition: noreturn.cpp:7
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:395
#define ANSI_NULL
CONST CHAR * PCCH
Definition: ntbasedef.h:404
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
unsigned short USHORT
Definition: pedump.c:61
@ ESUCCESS
Definition: arc.h:32
ULONG ARC_STATUS
Definition: arc.h:4
@ SeekRelative
Definition: arc.h:60
@ SeekAbsolute
Definition: arc.h:59
enum _OPENMODE OPENMODE
@ ReadOnlyFile
Definition: arc.h:78
@ ArchiveFile
Definition: arc.h:81
@ SystemFile
Definition: arc.h:80
@ HiddenFile
Definition: arc.h:79
enum _SEEKMODE SEEKMODE
@ OpenReadOnly
Definition: arc.h:65
#define TRACE(s)
Definition: solgame.cpp:4
NTFS_ATTR_RECORD Record
Definition: ntfs.h:246
UCHAR NameOffset
Definition: ntfs.h:208
ULONGLONG BaseFileRef
Definition: ntfs.h:210
USHORT AttrId
Definition: ntfs.h:211
USHORT RecLength
Definition: ntfs.h:206
UCHAR NameLength
Definition: ntfs.h:207
ULONG Length
Definition: ntfs.h:135
USHORT NameOffset
Definition: ntfs.h:138
USHORT Instance
Definition: ntfs.h:140
struct NTFS_ATTR_RECORD::@158::@160 Resident
UCHAR NameLength
Definition: ntfs.h:137
UCHAR IsNonResident
Definition: ntfs.h:136
ULONG Type
Definition: ntfs.h:134
struct NTFS_ATTR_RECORD::@158::@161 NonResident
WCHAR FileName[1]
Definition: ntfs.h:200
UCHAR FileNameLength
Definition: ntfs.h:198
ULONG FileAttributes
Definition: ntfs.h:195
Definition: ntfs.h:216
NTFS_FILE_NAME_ATTR FileName
Definition: ntfs.h:234
struct NTFS_INDEX_ENTRY::@162::@163 Directory
union NTFS_INDEX_ENTRY::@162 Data
USHORT Flags
Definition: ntfs.h:232
USHORT Length
Definition: ntfs.h:230
UCHAR Flags
Definition: ntfs.h:172
ULONG EntriesOffset
Definition: ntfs.h:169
NTFS_INDEX_HEADER IndexHeader
Definition: ntfs.h:183
ULONG IndexBlockSize
Definition: ntfs.h:180
USHORT AttributesOffset
Definition: ntfs.h:122
PVOID Volume
Definition: fltmgrint.h:141
PUCHAR TemporarySector
Definition: ntfs.c:54
NTFS_BOOTSECTOR BootSector
Definition: ntfs.c:46
ULONG ClusterSize
Definition: ntfs.c:47
PNTFS_MFT_RECORD MasterFileTable
Definition: ntfs.c:50
ULONG MftRecordSize
Definition: ntfs.c:48
ULONG DeviceId
Definition: ntfs.c:53
PNTFS_ATTR_CONTEXT MFTContext
Definition: ntfs.c:52
ULONG IndexRecordSize
Definition: ntfs.c:49
Definition: fs.h:25
static COORD Position
Definition: mouse.c:34
uint32_t * PULONG
Definition: typedefs.h:59
int64_t LONG64
Definition: typedefs.h:68
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
int64_t LONGLONG
Definition: typedefs.h:68
ULONG_PTR SIZE_T
Definition: typedefs.h:80
const char * PCSTR
Definition: typedefs.h:52
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
uint64_t ULONGLONG
Definition: typedefs.h:67
char * PCHAR
Definition: typedefs.h:51
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFIOTARGET _In_opt_ WDFREQUEST _In_opt_ PWDF_MEMORY_DESCRIPTOR _In_opt_ PLONGLONG _In_opt_ PWDF_REQUEST_SEND_OPTIONS _Out_opt_ PULONG_PTR BytesRead
Definition: wdfiotarget.h:870
_In_ WDFREQUEST _In_ NTSTATUS _In_ ULONG_PTR Information
Definition: wdfrequest.h:1049
_Must_inspect_result_ _In_ WDFDEVICE _In_ PWDF_WMI_INSTANCE_CONFIG _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_opt_ WDFWMIINSTANCE * Instance
Definition: wdfwmi.h:481
_In_ struct _KBUGCHECK_REASON_CALLBACK_RECORD * Record
Definition: ketypes.h:320
unsigned char UCHAR
Definition: xmlstorage.h:181
__wchar_t WCHAR
Definition: xmlstorage.h:180
char CHAR
Definition: xmlstorage.h:175