ReactOS  0.4.13-dev-257-gfabbd7c
attrib.c
Go to the documentation of this file.
1 /*
2  * ReactOS kernel
3  * Copyright (C) 2002,2003 ReactOS Team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18  *
19  * COPYRIGHT: See COPYING in the top level directory
20  * PROJECT: ReactOS kernel
21  * FILE: drivers/filesystem/ntfs/attrib.c
22  * PURPOSE: NTFS filesystem driver
23  * PROGRAMMERS: Eric Kohl
24  * Valentin Verkhovsky
25  * HervĂ© Poussineau (hpoussin@reactos.org)
26  * Pierre Schweitzer (pierre@reactos.org)
27  */
28 
29 /* INCLUDES *****************************************************************/
30 
31 #include "ntfs.h"
32 #include <ntintsafe.h>
33 
34 #define NDEBUG
35 #include <debug.h>
36 
37 /* FUNCTIONS ****************************************************************/
38 
73  PFILE_RECORD_HEADER FileRecord,
74  PNTFS_ATTR_RECORD AttributeAddress,
75  PCWSTR Name,
76  USHORT NameLength)
77 {
78  ULONG AttributeLength;
79  // Calculate the header length
80  ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
81  ULONG FileRecordEnd = AttributeAddress->Length;
82  ULONG NameOffset;
83  ULONG ValueOffset;
84  // We'll start out with 8 bytes of bitmap data
85  ULONG ValueLength = 8;
86  ULONG BytesAvailable;
87 
88  if (AttributeAddress->Type != AttributeEnd)
89  {
90  DPRINT1("FIXME: Can only add $BITMAP attribute to the end of a file record.\n");
92  }
93 
94  NameOffset = ResidentHeaderLength;
95 
96  // Calculate ValueOffset, which will be aligned to a 4-byte boundary
97  ValueOffset = ALIGN_UP_BY(NameOffset + (sizeof(WCHAR) * NameLength), VALUE_OFFSET_ALIGNMENT);
98 
99  // Calculate length of attribute
100  AttributeLength = ValueOffset + ValueLength;
101  AttributeLength = ALIGN_UP_BY(AttributeLength, ATTR_RECORD_ALIGNMENT);
102 
103  // Make sure the file record is large enough for the new attribute
104  BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
105  if (BytesAvailable < AttributeLength)
106  {
107  DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
108  return STATUS_NOT_IMPLEMENTED;
109  }
110 
111  // Set Attribute fields
112  RtlZeroMemory(AttributeAddress, AttributeLength);
113 
114  AttributeAddress->Type = AttributeBitmap;
115  AttributeAddress->Length = AttributeLength;
116  AttributeAddress->NameLength = NameLength;
117  AttributeAddress->NameOffset = NameOffset;
118  AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
119 
120  AttributeAddress->Resident.ValueLength = ValueLength;
121  AttributeAddress->Resident.ValueOffset = ValueOffset;
122 
123  // Set the name
124  RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
125 
126  // move the attribute-end and file-record-end markers to the end of the file record
127  AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
128  SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
129 
130  return STATUS_SUCCESS;
131 }
132 
159 NTSTATUS
161  PNTFS_ATTR_RECORD AttributeAddress)
162 {
163  ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
164  ULONG FileRecordEnd = AttributeAddress->Length;
165 
166  if (AttributeAddress->Type != AttributeEnd)
167  {
168  DPRINT1("FIXME: Can only add $DATA attribute to the end of a file record.\n");
169  return STATUS_NOT_IMPLEMENTED;
170  }
171 
172  AttributeAddress->Type = AttributeData;
173  AttributeAddress->Length = ResidentHeaderLength;
174  AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
175  AttributeAddress->Resident.ValueLength = 0;
176  AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
177 
178  // for unnamed $DATA attributes, NameOffset equals header length
179  AttributeAddress->NameOffset = ResidentHeaderLength;
180  AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
181 
182  // move the attribute-end and file-record-end markers to the end of the file record
183  AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
184  SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
185 
186  return STATUS_SUCCESS;
187 }
188 
229 NTSTATUS
231  PNTFS_ATTR_RECORD AttributeAddress,
232  PDEVICE_EXTENSION DeviceExt,
234  BOOLEAN CaseSensitive,
235  PULONGLONG ParentMftIndex)
236 {
237  ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
238  PFILENAME_ATTRIBUTE FileNameAttribute;
239  LARGE_INTEGER SystemTime;
240  ULONG FileRecordEnd = AttributeAddress->Length;
241  ULONGLONG CurrentMFTIndex = NTFS_FILE_ROOT;
242  UNICODE_STRING Current, Remaining, FilenameNoPath;
244  ULONG FirstEntry;
245 
246  if (AttributeAddress->Type != AttributeEnd)
247  {
248  DPRINT1("FIXME: Can only add $FILE_NAME attribute to the end of a file record.\n");
249  return STATUS_NOT_IMPLEMENTED;
250  }
251 
252  AttributeAddress->Type = AttributeFileName;
253  AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
254 
255  FileNameAttribute = (PFILENAME_ATTRIBUTE)((LONG_PTR)AttributeAddress + ResidentHeaderLength);
256 
257  // set timestamps
258  KeQuerySystemTime(&SystemTime);
259  FileNameAttribute->CreationTime = SystemTime.QuadPart;
260  FileNameAttribute->ChangeTime = SystemTime.QuadPart;
261  FileNameAttribute->LastWriteTime = SystemTime.QuadPart;
262  FileNameAttribute->LastAccessTime = SystemTime.QuadPart;
263 
264  // Is this a directory?
265  if(FileRecord->Flags & FRH_DIRECTORY)
266  FileNameAttribute->FileAttributes = NTFS_FILE_TYPE_DIRECTORY;
267  else
268  FileNameAttribute->FileAttributes = NTFS_FILE_TYPE_ARCHIVE;
269 
270  // we need to extract the filename from the path
271  DPRINT1("Pathname: %wZ\n", &FileObject->FileName);
272 
273  FsRtlDissectName(FileObject->FileName, &Current, &Remaining);
274 
275  FilenameNoPath.Buffer = Current.Buffer;
276  FilenameNoPath.MaximumLength = FilenameNoPath.Length = Current.Length;
277 
278  while (Current.Length != 0)
279  {
280  DPRINT1("Current: %wZ\n", &Current);
281 
282  if (Remaining.Length != 0)
283  {
284  FilenameNoPath.Buffer = Remaining.Buffer;
285  FilenameNoPath.Length = FilenameNoPath.MaximumLength = Remaining.Length;
286  }
287 
288  FirstEntry = 0;
289  Status = NtfsFindMftRecord(DeviceExt,
290  CurrentMFTIndex,
291  &Current,
292  &FirstEntry,
293  FALSE,
294  CaseSensitive,
295  &CurrentMFTIndex);
296  if (!NT_SUCCESS(Status))
297  break;
298 
299  if (Remaining.Length == 0 )
300  {
301  if (Current.Length != 0)
302  {
303  FilenameNoPath.Buffer = Current.Buffer;
304  FilenameNoPath.Length = FilenameNoPath.MaximumLength = Current.Length;
305  }
306  break;
307  }
308 
309  FsRtlDissectName(Remaining, &Current, &Remaining);
310  }
311 
312  DPRINT1("MFT Index of parent: %I64u\n", CurrentMFTIndex);
313 
314  // set reference to parent directory
315  FileNameAttribute->DirectoryFileReferenceNumber = CurrentMFTIndex;
316  *ParentMftIndex = CurrentMFTIndex;
317 
318  DPRINT1("SequenceNumber: 0x%02x\n", FileRecord->SequenceNumber);
319 
320  // The highest 2 bytes should be the sequence number, unless the parent happens to be root
321  if (CurrentMFTIndex == NTFS_FILE_ROOT)
322  FileNameAttribute->DirectoryFileReferenceNumber |= (ULONGLONG)NTFS_FILE_ROOT << 48;
323  else
324  FileNameAttribute->DirectoryFileReferenceNumber |= (ULONGLONG)FileRecord->SequenceNumber << 48;
325 
326  DPRINT1("FileNameAttribute->DirectoryFileReferenceNumber: 0x%016I64x\n", FileNameAttribute->DirectoryFileReferenceNumber);
327 
328  FileNameAttribute->NameLength = FilenameNoPath.Length / sizeof(WCHAR);
329  RtlCopyMemory(FileNameAttribute->Name, FilenameNoPath.Buffer, FilenameNoPath.Length);
330 
331  // For now, we're emulating the way Windows behaves when 8.3 name generation is disabled
332  // TODO: add DOS Filename as needed
333  if (!CaseSensitive && RtlIsNameLegalDOS8Dot3(&FilenameNoPath, NULL, NULL))
334  FileNameAttribute->NameType = NTFS_FILE_NAME_WIN32_AND_DOS;
335  else
336  FileNameAttribute->NameType = NTFS_FILE_NAME_POSIX;
337 
338  FileRecord->LinkCount++;
339 
340  AttributeAddress->Length = ResidentHeaderLength +
341  FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + FilenameNoPath.Length;
342  AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
343 
344  AttributeAddress->Resident.ValueLength = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + FilenameNoPath.Length;
345  AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
346  AttributeAddress->Resident.Flags = RA_INDEXED;
347 
348  // move the attribute-end and file-record-end markers to the end of the file record
349  AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
350  SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
351 
352  return Status;
353 }
354 
387 NTSTATUS
389  PFILE_RECORD_HEADER FileRecord,
390  PNTFS_ATTR_RECORD AttributeAddress,
391  PCWSTR Name,
392  USHORT NameLength)
393 {
394  ULONG RecordLength;
395  ULONG FileRecordEnd;
396  ULONG NameOffset;
397  ULONG DataRunOffset;
398  ULONG BytesAvailable;
399 
400  if (AttributeAddress->Type != AttributeEnd)
401  {
402  DPRINT1("FIXME: Can only add $INDEX_ALLOCATION attribute to the end of a file record.\n");
403  return STATUS_NOT_IMPLEMENTED;
404  }
405 
406  // Calculate the name offset
407  NameOffset = FIELD_OFFSET(NTFS_ATTR_RECORD, NonResident.CompressedSize);
408 
409  // Calculate the offset to the first data run
410  DataRunOffset = (sizeof(WCHAR) * NameLength) + NameOffset;
411  // The data run offset must be aligned to a 4-byte boundary
412  DataRunOffset = ALIGN_UP_BY(DataRunOffset, DATA_RUN_ALIGNMENT);
413 
414  // Calculate the length of the new attribute; the empty data run will consist of a single byte
415  RecordLength = DataRunOffset + 1;
416 
417  // The size of the attribute itself must be aligned to an 8 - byte boundary
418  RecordLength = ALIGN_UP_BY(RecordLength, ATTR_RECORD_ALIGNMENT);
419 
420  // Back up the last 4-bytes of the file record (even though this value doesn't matter)
421  FileRecordEnd = AttributeAddress->Length;
422 
423  // Make sure the file record can contain the new attribute
424  BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
425  if (BytesAvailable < RecordLength)
426  {
427  DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
428  return STATUS_NOT_IMPLEMENTED;
429  }
430 
431  // Set fields of attribute header
432  RtlZeroMemory(AttributeAddress, RecordLength);
433 
434  AttributeAddress->Type = AttributeIndexAllocation;
435  AttributeAddress->Length = RecordLength;
436  AttributeAddress->IsNonResident = TRUE;
437  AttributeAddress->NameLength = NameLength;
438  AttributeAddress->NameOffset = NameOffset;
439  AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
440 
441  AttributeAddress->NonResident.MappingPairsOffset = DataRunOffset;
442  AttributeAddress->NonResident.HighestVCN = (LONGLONG)-1;
443 
444  // Set the name
445  RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
446 
447  // move the attribute-end and file-record-end markers to the end of the file record
448  AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
449  SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
450 
451  return STATUS_SUCCESS;
452 }
453 
494 NTSTATUS
496  PFILE_RECORD_HEADER FileRecord,
497  PNTFS_ATTR_RECORD AttributeAddress,
498  PINDEX_ROOT_ATTRIBUTE NewIndexRoot,
499  ULONG RootLength,
500  PCWSTR Name,
501  USHORT NameLength)
502 {
503  ULONG AttributeLength;
504  // Calculate the header length
505  ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
506  // Back up the file record's final ULONG (even though it doesn't matter)
507  ULONG FileRecordEnd = AttributeAddress->Length;
508  ULONG NameOffset;
509  ULONG ValueOffset;
510  ULONG BytesAvailable;
511 
512  if (AttributeAddress->Type != AttributeEnd)
513  {
514  DPRINT1("FIXME: Can only add $DATA attribute to the end of a file record.\n");
515  return STATUS_NOT_IMPLEMENTED;
516  }
517 
518  NameOffset = ResidentHeaderLength;
519 
520  // Calculate ValueOffset, which will be aligned to a 4-byte boundary
521  ValueOffset = ALIGN_UP_BY(NameOffset + (sizeof(WCHAR) * NameLength), VALUE_OFFSET_ALIGNMENT);
522 
523  // Calculate length of attribute
524  AttributeLength = ValueOffset + RootLength;
525  AttributeLength = ALIGN_UP_BY(AttributeLength, ATTR_RECORD_ALIGNMENT);
526 
527  // Make sure the file record is large enough for the new attribute
528  BytesAvailable = Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
529  if (BytesAvailable < AttributeLength)
530  {
531  DPRINT1("FIXME: Not enough room in file record for index allocation attribute!\n");
532  return STATUS_NOT_IMPLEMENTED;
533  }
534 
535  // Set Attribute fields
536  RtlZeroMemory(AttributeAddress, AttributeLength);
537 
538  AttributeAddress->Type = AttributeIndexRoot;
539  AttributeAddress->Length = AttributeLength;
540  AttributeAddress->NameLength = NameLength;
541  AttributeAddress->NameOffset = NameOffset;
542  AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
543 
544  AttributeAddress->Resident.ValueLength = RootLength;
545  AttributeAddress->Resident.ValueOffset = ValueOffset;
546 
547  // Set the name
548  RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + NameOffset), Name, NameLength * sizeof(WCHAR));
549 
550  // Copy the index root attribute
551  RtlCopyMemory((PCHAR)((ULONG_PTR)AttributeAddress + ValueOffset), NewIndexRoot, RootLength);
552 
553  // move the attribute-end and file-record-end markers to the end of the file record
554  AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
555  SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
556 
557  return STATUS_SUCCESS;
558 }
559 
598 NTSTATUS
600  PNTFS_ATTR_CONTEXT AttrContext,
601  ULONG AttrOffset,
602  PFILE_RECORD_HEADER FileRecord,
603  ULONGLONG NextAssignedCluster,
604  ULONG RunLength)
605 {
607  int DataRunMaxLength;
608  PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
609  ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length;
610  ULONGLONG NextVBN = 0;
611 
612  PUCHAR RunBuffer;
613  ULONG RunBufferSize;
614 
615  if (!AttrContext->pRecord->IsNonResident)
617 
618  if (AttrContext->pRecord->NonResident.AllocatedSize != 0)
619  NextVBN = AttrContext->pRecord->NonResident.HighestVCN + 1;
620 
621  // Add newly-assigned clusters to mcb
622  _SEH2_TRY
623  {
624  if (!FsRtlAddLargeMcbEntry(&AttrContext->DataRunsMCB,
625  NextVBN,
626  NextAssignedCluster,
627  RunLength))
628  {
630  }
631  }
633  {
634  DPRINT1("Failed to add LargeMcb Entry!\n");
636  }
637  _SEH2_END;
638 
639  RunBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
640  if (!RunBuffer)
641  {
642  DPRINT1("ERROR: Couldn't allocate memory for data runs!\n");
644  }
645 
646  // Convert the map control block back to encoded data runs
647  ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB, RunBuffer, Vcb->NtfsInfo.BytesPerCluster, &RunBufferSize);
648 
649  // Get the amount of free space between the start of the of the first data run and the attribute end
650  DataRunMaxLength = AttrContext->pRecord->Length - AttrContext->pRecord->NonResident.MappingPairsOffset;
651 
652  // Do we need to extend the attribute (or convert to attribute list)?
653  if (DataRunMaxLength < RunBufferSize)
654  {
655  PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
656  PNTFS_ATTR_RECORD NewRecord;
657 
658  // Add free space at the end of the file record to DataRunMaxLength
659  DataRunMaxLength += Vcb->NtfsInfo.BytesPerFileRecord - FileRecord->BytesInUse;
660 
661  // Can we resize the attribute?
662  if (DataRunMaxLength < RunBufferSize)
663  {
664  DPRINT1("FIXME: Need to create attribute list! Max Data Run Length available: %d, RunBufferSize: %d\n", DataRunMaxLength, RunBufferSize);
665  ExFreePoolWithTag(RunBuffer, TAG_NTFS);
666  return STATUS_NOT_IMPLEMENTED;
667  }
668 
669  // Are there more attributes after the one we're resizing?
670  if (NextAttribute->Type != AttributeEnd)
671  {
672  PNTFS_ATTR_RECORD FinalAttribute;
673 
674  // Calculate where to move the trailing attributes
675  ULONG_PTR MoveTo = (ULONG_PTR)DestinationAttribute + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
676  MoveTo = ALIGN_UP_BY(MoveTo, ATTR_RECORD_ALIGNMENT);
677 
678  DPRINT1("Moving attribute(s) after this one starting with type 0x%lx\n", NextAttribute->Type);
679 
680  // Move the trailing attributes; FinalAttribute will point to the end marker
681  FinalAttribute = MoveAttributes(Vcb, NextAttribute, NextAttributeOffset, MoveTo);
682 
683  // set the file record end
684  SetFileRecordEnd(FileRecord, FinalAttribute, FILE_RECORD_END);
685  }
686 
687  // calculate position of end markers
688  NextAttributeOffset = AttrOffset + AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize;
689  NextAttributeOffset = ALIGN_UP_BY(NextAttributeOffset, ATTR_RECORD_ALIGNMENT);
690 
691  // Update the length of the destination attribute
692  DestinationAttribute->Length = NextAttributeOffset - AttrOffset;
693 
694  // Create a new copy of the attribute record
695  NewRecord = ExAllocatePoolWithTag(NonPagedPool, DestinationAttribute->Length, TAG_NTFS);
696  RtlCopyMemory(NewRecord, AttrContext->pRecord, AttrContext->pRecord->Length);
697  NewRecord->Length = DestinationAttribute->Length;
698 
699  // Free the old copy of the attribute record, which won't be large enough
700  ExFreePoolWithTag(AttrContext->pRecord, TAG_NTFS);
701 
702  // Set the attribute context's record to the new copy
703  AttrContext->pRecord = NewRecord;
704 
705  // if NextAttribute is the AttributeEnd marker
706  if (NextAttribute->Type == AttributeEnd)
707  {
708  // End the file record
709  NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
710  SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
711  }
712  }
713 
714  // Update HighestVCN
715  DestinationAttribute->NonResident.HighestVCN =
716  AttrContext->pRecord->NonResident.HighestVCN = max(NextVBN - 1 + RunLength,
717  AttrContext->pRecord->NonResident.HighestVCN);
718 
719  // Write data runs to destination attribute
720  RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset),
721  RunBuffer,
722  RunBufferSize);
723 
724  // Update the attribute record in the attribute context
725  RtlCopyMemory((PVOID)((ULONG_PTR)AttrContext->pRecord + AttrContext->pRecord->NonResident.MappingPairsOffset),
726  RunBuffer,
727  RunBufferSize);
728 
729  // Update the file record
730  Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
731 
732  ExFreePoolWithTag(RunBuffer, TAG_NTFS);
733 
734  NtfsDumpDataRuns((PUCHAR)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), 0);
735 
736  return Status;
737 }
738 
765 NTSTATUS
767  PNTFS_ATTR_RECORD AttributeAddress)
768 {
769  ULONG ResidentHeaderLength = FIELD_OFFSET(NTFS_ATTR_RECORD, Resident.Reserved) + sizeof(UCHAR);
770  PSTANDARD_INFORMATION StandardInfo = (PSTANDARD_INFORMATION)((LONG_PTR)AttributeAddress + ResidentHeaderLength);
771  LARGE_INTEGER SystemTime;
772  ULONG FileRecordEnd = AttributeAddress->Length;
773 
774  if (AttributeAddress->Type != AttributeEnd)
775  {
776  DPRINT1("FIXME: Can only add $STANDARD_INFORMATION attribute to the end of a file record.\n");
777  return STATUS_NOT_IMPLEMENTED;
778  }
779 
780  AttributeAddress->Type = AttributeStandardInformation;
781  AttributeAddress->Length = sizeof(STANDARD_INFORMATION) + ResidentHeaderLength;
782  AttributeAddress->Length = ALIGN_UP_BY(AttributeAddress->Length, ATTR_RECORD_ALIGNMENT);
783  AttributeAddress->Resident.ValueLength = sizeof(STANDARD_INFORMATION);
784  AttributeAddress->Resident.ValueOffset = ResidentHeaderLength;
785  AttributeAddress->Instance = FileRecord->NextAttributeNumber++;
786 
787  // set dates and times
788  KeQuerySystemTime(&SystemTime);
789  StandardInfo->CreationTime = SystemTime.QuadPart;
790  StandardInfo->ChangeTime = SystemTime.QuadPart;
791  StandardInfo->LastWriteTime = SystemTime.QuadPart;
792  StandardInfo->LastAccessTime = SystemTime.QuadPart;
793  StandardInfo->FileAttribute = NTFS_FILE_TYPE_ARCHIVE;
794 
795  // move the attribute-end and file-record-end markers to the end of the file record
796  AttributeAddress = (PNTFS_ATTR_RECORD)((ULONG_PTR)AttributeAddress + AttributeAddress->Length);
797  SetFileRecordEnd(FileRecord, AttributeAddress, FileRecordEnd);
798 
799  return STATUS_SUCCESS;
800 }
801 
824 NTSTATUS
826  PLARGE_MCB DataRunsMCB,
827  PULONGLONG pNextVBN)
828 {
829  LONGLONG DataRunOffset;
830  ULONGLONG DataRunLength;
831  LONGLONG DataRunStartLCN;
832  ULONGLONG LastLCN = 0;
833 
834  // Initialize the MCB, potentially catch an exception
835  _SEH2_TRY{
839  } _SEH2_END;
840 
841  while (*DataRun != 0)
842  {
843  DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
844 
845  if (DataRunOffset != -1)
846  {
847  // Normal data run.
848  DataRunStartLCN = LastLCN + DataRunOffset;
849  LastLCN = DataRunStartLCN;
850 
851  _SEH2_TRY{
852  if (!FsRtlAddLargeMcbEntry(DataRunsMCB,
853  *pNextVBN,
854  DataRunStartLCN,
855  DataRunLength))
856  {
858  }
860  FsRtlUninitializeLargeMcb(DataRunsMCB);
862  } _SEH2_END;
863 
864  }
865 
866  *pNextVBN += DataRunLength;
867  }
868 
869  return STATUS_SUCCESS;
870 }
871 
895 NTSTATUS
897  PUCHAR RunBuffer,
898  ULONG MaxBufferSize,
899  PULONG UsedBufferSize)
900 {
902  ULONG RunBufferOffset = 0;
903  LONGLONG DataRunOffset;
904  ULONGLONG LastLCN = 0;
905  LONGLONG Vbn, Lbn, Count;
906  ULONG i;
907 
908 
909  DPRINT("\t[Vbn, Lbn, Count]\n");
910 
911  // convert each mcb entry to a data run
912  for (i = 0; FsRtlGetNextLargeMcbEntry(DataRunsMCB, i, &Vbn, &Lbn, &Count); i++)
913  {
914  UCHAR DataRunOffsetSize = 0;
915  UCHAR DataRunLengthSize = 0;
916  UCHAR ControlByte = 0;
917 
918  // [vbn, lbn, count]
919  DPRINT("\t[%I64d, %I64d,%I64d]\n", Vbn, Lbn, Count);
920 
921  // TODO: check for holes and convert to sparse runs
922  DataRunOffset = Lbn - LastLCN;
923  LastLCN = Lbn;
924 
925  // now we need to determine how to represent DataRunOffset with the minimum number of bytes
926  DPRINT("Determining how many bytes needed to represent %I64x\n", DataRunOffset);
927  DataRunOffsetSize = GetPackedByteCount(DataRunOffset, TRUE);
928  DPRINT("%d bytes needed.\n", DataRunOffsetSize);
929 
930  // determine how to represent DataRunLengthSize with the minimum number of bytes
931  DPRINT("Determining how many bytes needed to represent %I64x\n", Count);
932  DataRunLengthSize = GetPackedByteCount(Count, TRUE);
933  DPRINT("%d bytes needed.\n", DataRunLengthSize);
934 
935  // ensure the next data run + end marker would be <= Max buffer size
936  if (RunBufferOffset + 2 + DataRunLengthSize + DataRunOffsetSize > MaxBufferSize)
937  {
939  DPRINT1("FIXME: Ran out of room in buffer for data runs!\n");
940  break;
941  }
942 
943  // pack and copy the control byte
944  ControlByte = (DataRunOffsetSize << 4) + DataRunLengthSize;
945  RunBuffer[RunBufferOffset++] = ControlByte;
946 
947  // copy DataRunLength
948  RtlCopyMemory(RunBuffer + RunBufferOffset, &Count, DataRunLengthSize);
949  RunBufferOffset += DataRunLengthSize;
950 
951  // copy DataRunOffset
952  RtlCopyMemory(RunBuffer + RunBufferOffset, &DataRunOffset, DataRunOffsetSize);
953  RunBufferOffset += DataRunOffsetSize;
954  }
955 
956  // End of data runs
957  RunBuffer[RunBufferOffset++] = 0;
958 
959  *UsedBufferSize = RunBufferOffset;
960  DPRINT("New Size of DataRuns: %ld\n", *UsedBufferSize);
961 
962  return Status;
963 }
964 
965 PUCHAR
967  LONGLONG *DataRunOffset,
968  ULONGLONG *DataRunLength)
969 {
970  UCHAR DataRunOffsetSize;
971  UCHAR DataRunLengthSize;
972  CHAR i;
973 
974  DataRunOffsetSize = (*DataRun >> 4) & 0xF;
975  DataRunLengthSize = *DataRun & 0xF;
976  *DataRunOffset = 0;
977  *DataRunLength = 0;
978  DataRun++;
979  for (i = 0; i < DataRunLengthSize; i++)
980  {
981  *DataRunLength += ((ULONG64)*DataRun) << (i * 8);
982  DataRun++;
983  }
984 
985  /* NTFS 3+ sparse files */
986  if (DataRunOffsetSize == 0)
987  {
988  *DataRunOffset = -1;
989  }
990  else
991  {
992  for (i = 0; i < DataRunOffsetSize - 1; i++)
993  {
994  *DataRunOffset += ((ULONG64)*DataRun) << (i * 8);
995  DataRun++;
996  }
997  /* The last byte contains sign so we must process it different way. */
998  *DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset;
999  }
1000 
1001  DPRINT("DataRunOffsetSize: %x\n", DataRunOffsetSize);
1002  DPRINT("DataRunLengthSize: %x\n", DataRunLengthSize);
1003  DPRINT("DataRunOffset: %x\n", *DataRunOffset);
1004  DPRINT("DataRunLength: %x\n", *DataRunLength);
1005 
1006  return DataRun;
1007 }
1008 
1009 BOOLEAN
1011  ULONGLONG vcn,
1012  PULONGLONG lcn,
1013  PULONGLONG count)
1014 {
1015  if (vcn < NresAttr->NonResident.LowestVCN || vcn > NresAttr->NonResident.HighestVCN)
1016  return FALSE;
1017 
1018  DecodeRun((PUCHAR)((ULONG_PTR)NresAttr + NresAttr->NonResident.MappingPairsOffset), (PLONGLONG)lcn, count);
1019 
1020  return TRUE;
1021 }
1022 
1056 NTSTATUS
1058  PNTFS_ATTR_CONTEXT AttrContext,
1059  ULONG AttrOffset,
1060  PFILE_RECORD_HEADER FileRecord,
1061  ULONG ClustersToFree)
1062 {
1064  ULONG ClustersLeftToFree = ClustersToFree;
1065 
1066  PNTFS_ATTR_RECORD DestinationAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + AttrOffset);
1067  ULONG NextAttributeOffset = AttrOffset + AttrContext->pRecord->Length;
1068  PNTFS_ATTR_RECORD NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + NextAttributeOffset);
1069 
1070  PUCHAR RunBuffer;
1071  ULONG RunBufferSize = 0;
1072 
1073  PFILE_RECORD_HEADER BitmapRecord;
1074  PNTFS_ATTR_CONTEXT DataContext;
1075  ULONGLONG BitmapDataSize;
1078  ULONG LengthWritten;
1079 
1080  if (!AttrContext->pRecord->IsNonResident)
1081  {
1082  return STATUS_INVALID_PARAMETER;
1083  }
1084 
1085  // Read the $Bitmap file
1086  BitmapRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
1087  if (BitmapRecord == NULL)
1088  {
1089  DPRINT1("Error: Unable to allocate memory for bitmap file record!\n");
1090  return STATUS_NO_MEMORY;
1091  }
1092 
1093  Status = ReadFileRecord(Vcb, NTFS_FILE_BITMAP, BitmapRecord);
1094  if (!NT_SUCCESS(Status))
1095  {
1096  DPRINT1("Error: Unable to read file record for bitmap!\n");
1097  ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1098  return 0;
1099  }
1100 
1101  Status = FindAttribute(Vcb, BitmapRecord, AttributeData, L"", 0, &DataContext, NULL);
1102  if (!NT_SUCCESS(Status))
1103  {
1104  DPRINT1("Error: Unable to find data attribute for bitmap file!\n");
1105  ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1106  return 0;
1107  }
1108 
1109  BitmapDataSize = AttributeDataLength(DataContext->pRecord);
1110  BitmapDataSize = min(BitmapDataSize, ULONG_MAX);
1111  ASSERT((BitmapDataSize * 8) >= Vcb->NtfsInfo.ClusterCount);
1112  BitmapData = ExAllocatePoolWithTag(NonPagedPool, ROUND_UP(BitmapDataSize, Vcb->NtfsInfo.BytesPerSector), TAG_NTFS);
1113  if (BitmapData == NULL)
1114  {
1115  DPRINT1("Error: Unable to allocate memory for bitmap file data!\n");
1116  ReleaseAttributeContext(DataContext);
1117  ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1118  return 0;
1119  }
1120 
1121  ReadAttribute(Vcb, DataContext, 0, (PCHAR)BitmapData, (ULONG)BitmapDataSize);
1122 
1123  RtlInitializeBitMap(&Bitmap, (PULONG)BitmapData, Vcb->NtfsInfo.ClusterCount);
1124 
1125  // free clusters in $BITMAP file
1126  while (ClustersLeftToFree > 0)
1127  {
1129 
1130  if (!FsRtlLookupLastLargeMcbEntry(&AttrContext->DataRunsMCB, &LargeVbn, &LargeLbn))
1131  {
1133  DPRINT1("DRIVER ERROR: FreeClusters called to free %lu clusters, which is %lu more clusters than are assigned to attribute!",
1134  ClustersToFree,
1135  ClustersLeftToFree);
1136  break;
1137  }
1138 
1139  if (LargeLbn != -1)
1140  {
1141  // deallocate this cluster
1143  }
1144  FsRtlTruncateLargeMcb(&AttrContext->DataRunsMCB, AttrContext->pRecord->NonResident.HighestVCN);
1145 
1146  // decrement HighestVCN, but don't let it go below 0
1147  AttrContext->pRecord->NonResident.HighestVCN = min(AttrContext->pRecord->NonResident.HighestVCN, AttrContext->pRecord->NonResident.HighestVCN - 1);
1148  ClustersLeftToFree--;
1149  }
1150 
1151  // update $BITMAP file on disk
1152  Status = WriteAttribute(Vcb, DataContext, 0, BitmapData, (ULONG)BitmapDataSize, &LengthWritten, FileRecord);
1153  if (!NT_SUCCESS(Status))
1154  {
1155  ReleaseAttributeContext(DataContext);
1157  ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1158  return Status;
1159  }
1160 
1161  ReleaseAttributeContext(DataContext);
1163  ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, BitmapRecord);
1164 
1165  // Save updated data runs to file record
1166 
1167  // Allocate some memory for a new RunBuffer
1168  RunBuffer = ExAllocatePoolWithTag(NonPagedPool, Vcb->NtfsInfo.BytesPerFileRecord, TAG_NTFS);
1169  if (!RunBuffer)
1170  {
1171  DPRINT1("ERROR: Couldn't allocate memory for data runs!\n");
1173  }
1174 
1175  // Convert the map control block back to encoded data runs
1176  ConvertLargeMCBToDataRuns(&AttrContext->DataRunsMCB, RunBuffer, Vcb->NtfsInfo.BytesPerCluster, &RunBufferSize);
1177 
1178  // Update HighestVCN
1179  DestinationAttribute->NonResident.HighestVCN = AttrContext->pRecord->NonResident.HighestVCN;
1180 
1181  // Write data runs to destination attribute
1182  RtlCopyMemory((PVOID)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset),
1183  RunBuffer,
1184  RunBufferSize);
1185 
1186  // Is DestinationAttribute the last attribute in the file record?
1187  if (NextAttribute->Type == AttributeEnd)
1188  {
1189  // update attribute length
1190  DestinationAttribute->Length = ALIGN_UP_BY(AttrContext->pRecord->NonResident.MappingPairsOffset + RunBufferSize,
1192 
1193  ASSERT(DestinationAttribute->Length <= AttrContext->pRecord->Length);
1194 
1195  AttrContext->pRecord->Length = DestinationAttribute->Length;
1196 
1197  // write end markers
1198  NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)DestinationAttribute + DestinationAttribute->Length);
1199  SetFileRecordEnd(FileRecord, NextAttribute, FILE_RECORD_END);
1200  }
1201 
1202  // Update the file record
1203  Status = UpdateFileRecord(Vcb, AttrContext->FileMFTIndex, FileRecord);
1204 
1205  ExFreePoolWithTag(RunBuffer, TAG_NTFS);
1206 
1207  NtfsDumpDataRuns((PUCHAR)((ULONG_PTR)DestinationAttribute + DestinationAttribute->NonResident.MappingPairsOffset), 0);
1208 
1209  return Status;
1210 }
1211 
1212 static
1213 NTSTATUS
1215 {
1216  ULONGLONG ListSize;
1217  PNTFS_ATTR_RECORD Attribute;
1218  PNTFS_ATTR_CONTEXT ListContext;
1219 
1220  DPRINT("InternalReadNonResidentAttributes(%p)\n", Context);
1221 
1222  Attribute = Context->CurrAttr;
1223  ASSERT(Attribute->Type == AttributeAttributeList);
1224 
1225  if (Context->OnlyResident)
1226  {
1227  Context->NonResidentStart = NULL;
1228  Context->NonResidentEnd = NULL;
1229  return STATUS_SUCCESS;
1230  }
1231 
1232  if (Context->NonResidentStart != NULL)
1233  {
1235  }
1236 
1237  ListContext = PrepareAttributeContext(Attribute);
1238  ListSize = AttributeDataLength(ListContext->pRecord);
1239  if (ListSize > 0xFFFFFFFF)
1240  {
1241  ReleaseAttributeContext(ListContext);
1242  return STATUS_BUFFER_OVERFLOW;
1243  }
1244 
1245  Context->NonResidentStart = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
1246  if (Context->NonResidentStart == NULL)
1247  {
1248  ReleaseAttributeContext(ListContext);
1250  }
1251 
1252  if (ReadAttribute(Context->Vcb, ListContext, 0, (PCHAR)Context->NonResidentStart, (ULONG)ListSize) != ListSize)
1253  {
1254  ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
1255  Context->NonResidentStart = NULL;
1256  ReleaseAttributeContext(ListContext);
1258  }
1259 
1260  ReleaseAttributeContext(ListContext);
1261  Context->NonResidentEnd = (PNTFS_ATTR_RECORD)((PCHAR)Context->NonResidentStart + ListSize);
1262  return STATUS_SUCCESS;
1263 }
1264 
1265 static
1268 {
1269  PNTFS_ATTR_RECORD NextAttribute;
1270 
1271  if (Context->CurrAttr == (PVOID)-1)
1272  {
1273  return NULL;
1274  }
1275 
1276  if (Context->CurrAttr >= Context->FirstAttr &&
1277  Context->CurrAttr < Context->LastAttr)
1278  {
1279  if (Context->CurrAttr->Length == 0)
1280  {
1281  DPRINT1("Broken length!\n");
1282  Context->CurrAttr = (PVOID)-1;
1283  return NULL;
1284  }
1285 
1286  NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length);
1287 
1288  if (NextAttribute > Context->LastAttr || NextAttribute < Context->FirstAttr)
1289  {
1290  DPRINT1("Broken length: 0x%lx!\n", Context->CurrAttr->Length);
1291  Context->CurrAttr = (PVOID)-1;
1292  return NULL;
1293  }
1294 
1295  Context->Offset += ((ULONG_PTR)NextAttribute - (ULONG_PTR)Context->CurrAttr);
1296  Context->CurrAttr = NextAttribute;
1297 
1298  if (Context->CurrAttr < Context->LastAttr &&
1299  Context->CurrAttr->Type != AttributeEnd)
1300  {
1301  return Context->CurrAttr;
1302  }
1303  }
1304 
1305  if (Context->NonResidentStart == NULL)
1306  {
1307  Context->CurrAttr = (PVOID)-1;
1308  return NULL;
1309  }
1310 
1311  if (Context->CurrAttr < Context->NonResidentStart ||
1312  Context->CurrAttr >= Context->NonResidentEnd)
1313  {
1314  Context->CurrAttr = Context->NonResidentStart;
1315  }
1316  else if (Context->CurrAttr->Length != 0)
1317  {
1318  NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length);
1319  Context->Offset += ((ULONG_PTR)NextAttribute - (ULONG_PTR)Context->CurrAttr);
1320  Context->CurrAttr = NextAttribute;
1321  }
1322  else
1323  {
1324  DPRINT1("Broken length!\n");
1325  Context->CurrAttr = (PVOID)-1;
1326  return NULL;
1327  }
1328 
1329  if (Context->CurrAttr < Context->NonResidentEnd &&
1330  Context->CurrAttr->Type != AttributeEnd)
1331  {
1332  return Context->CurrAttr;
1333  }
1334 
1335  Context->CurrAttr = (PVOID)-1;
1336  return NULL;
1337 }
1338 
1339 NTSTATUS
1342  PFILE_RECORD_HEADER FileRecord,
1343  BOOLEAN OnlyResident,
1344  PNTFS_ATTR_RECORD * Attribute)
1345 {
1346  NTSTATUS Status;
1347 
1348  DPRINT("FindFistAttribute(%p, %p, %p, %p, %u, %p)\n", Context, Vcb, FileRecord, OnlyResident, Attribute);
1349 
1350  Context->Vcb = Vcb;
1351  Context->OnlyResident = OnlyResident;
1352  Context->FirstAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
1353  Context->CurrAttr = Context->FirstAttr;
1354  Context->LastAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse);
1355  Context->NonResidentStart = NULL;
1356  Context->NonResidentEnd = NULL;
1357  Context->Offset = FileRecord->AttributeOffset;
1358 
1359  if (Context->FirstAttr->Type == AttributeEnd)
1360  {
1361  Context->CurrAttr = (PVOID)-1;
1362  return STATUS_END_OF_FILE;
1363  }
1364  else if (Context->FirstAttr->Type == AttributeAttributeList)
1365  {
1367  if (!NT_SUCCESS(Status))
1368  {
1369  return Status;
1370  }
1371 
1372  *Attribute = InternalGetNextAttribute(Context);
1373  if (*Attribute == NULL)
1374  {
1375  return STATUS_END_OF_FILE;
1376  }
1377  }
1378  else
1379  {
1380  *Attribute = Context->CurrAttr;
1381  Context->Offset = (UCHAR*)Context->CurrAttr - (UCHAR*)FileRecord;
1382  }
1383 
1384  return STATUS_SUCCESS;
1385 }
1386 
1387 NTSTATUS
1389  PNTFS_ATTR_RECORD * Attribute)
1390 {
1391  NTSTATUS Status;
1392 
1393  DPRINT("FindNextAttribute(%p, %p)\n", Context, Attribute);
1394 
1395  *Attribute = InternalGetNextAttribute(Context);
1396  if (*Attribute == NULL)
1397  {
1398  return STATUS_END_OF_FILE;
1399  }
1400 
1401  if (Context->CurrAttr->Type != AttributeAttributeList)
1402  {
1403  return STATUS_SUCCESS;
1404  }
1405 
1407  if (!NT_SUCCESS(Status))
1408  {
1409  return Status;
1410  }
1411 
1412  *Attribute = InternalGetNextAttribute(Context);
1413  if (*Attribute == NULL)
1414  {
1415  return STATUS_END_OF_FILE;
1416  }
1417 
1418  return STATUS_SUCCESS;
1419 }
1420 
1421 VOID
1423 {
1424  if (Context->NonResidentStart != NULL)
1425  {
1426  ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
1427  Context->NonResidentStart = NULL;
1428  }
1429 }
1430 
1431 static
1432 VOID
1434 {
1435  PFILENAME_ATTRIBUTE FileNameAttr;
1436 
1437  DbgPrint(" $FILE_NAME ");
1438 
1439 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1440 
1441  FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1442  DbgPrint(" (%x) '%.*S' ", FileNameAttr->NameType, FileNameAttr->NameLength, FileNameAttr->Name);
1443  DbgPrint(" '%x' \n", FileNameAttr->FileAttributes);
1444  DbgPrint(" AllocatedSize: %I64u\nDataSize: %I64u\n", FileNameAttr->AllocatedSize, FileNameAttr->DataSize);
1445  DbgPrint(" File reference: 0x%016I64x\n", FileNameAttr->DirectoryFileReferenceNumber);
1446 }
1447 
1448 
1449 static
1450 VOID
1452 {
1453  PSTANDARD_INFORMATION StandardInfoAttr;
1454 
1455  DbgPrint(" $STANDARD_INFORMATION ");
1456 
1457 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1458 
1459  StandardInfoAttr = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1460  DbgPrint(" '%x' ", StandardInfoAttr->FileAttribute);
1461 }
1462 
1463 
1464 static
1465 VOID
1467 {
1469 
1470  DbgPrint(" $VOLUME_NAME ");
1471 
1472 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1473 
1474  VolumeName = (PWCHAR)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1475  DbgPrint(" '%.*S' ", Attribute->Resident.ValueLength / sizeof(WCHAR), VolumeName);
1476 }
1477 
1478 
1479 static
1480 VOID
1482 {
1483  PVOLINFO_ATTRIBUTE VolInfoAttr;
1484 
1485  DbgPrint(" $VOLUME_INFORMATION ");
1486 
1487 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
1488 
1489  VolInfoAttr = (PVOLINFO_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1490  DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
1491  VolInfoAttr->MajorVersion,
1492  VolInfoAttr->MinorVersion,
1493  VolInfoAttr->Flags);
1494 }
1495 
1496 
1497 static
1498 VOID
1500 {
1501  PINDEX_ROOT_ATTRIBUTE IndexRootAttr;
1502  ULONG CurrentOffset;
1503  ULONG CurrentNode;
1504 
1505  IndexRootAttr = (PINDEX_ROOT_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1506 
1507  if (IndexRootAttr->AttributeType == AttributeFileName)
1508  ASSERT(IndexRootAttr->CollationRule == COLLATION_FILE_NAME);
1509 
1510  DbgPrint(" $INDEX_ROOT (%u bytes per index record, %u clusters) ", IndexRootAttr->SizeOfEntry, IndexRootAttr->ClustersPerIndexRecord);
1511 
1512  if (IndexRootAttr->Header.Flags == INDEX_ROOT_SMALL)
1513  {
1514  DbgPrint(" (small)\n");
1515  }
1516  else
1517  {
1518  ASSERT(IndexRootAttr->Header.Flags == INDEX_ROOT_LARGE);
1519  DbgPrint(" (large)\n");
1520  }
1521 
1522  DbgPrint(" Offset to first index: 0x%lx\n Total size of index entries: 0x%lx\n Allocated size of node: 0x%lx\n",
1523  IndexRootAttr->Header.FirstEntryOffset,
1524  IndexRootAttr->Header.TotalSizeOfEntries,
1525  IndexRootAttr->Header.AllocatedSize);
1526  CurrentOffset = IndexRootAttr->Header.FirstEntryOffset;
1527  CurrentNode = 0;
1528  // print details of every node in the index
1529  while (CurrentOffset < IndexRootAttr->Header.TotalSizeOfEntries)
1530  {
1531  PINDEX_ENTRY_ATTRIBUTE currentIndexExtry = (PINDEX_ENTRY_ATTRIBUTE)((ULONG_PTR)IndexRootAttr + 0x10 + CurrentOffset);
1532  DbgPrint(" Index Node Entry %lu", CurrentNode++);
1533  if (BooleanFlagOn(currentIndexExtry->Flags, NTFS_INDEX_ENTRY_NODE))
1534  DbgPrint(" (Branch)");
1535  else
1536  DbgPrint(" (Leaf)");
1537  if (BooleanFlagOn(currentIndexExtry->Flags, NTFS_INDEX_ENTRY_END))
1538  {
1539  DbgPrint(" (Dummy Key)");
1540  }
1541  DbgPrint("\n File Reference: 0x%016I64x\n", currentIndexExtry->Data.Directory.IndexedFile);
1542  DbgPrint(" Index Entry Length: 0x%x\n", currentIndexExtry->Length);
1543  DbgPrint(" Index Key Length: 0x%x\n", currentIndexExtry->KeyLength);
1544 
1545  // if this isn't the final (dummy) node, print info about the key (Filename attribute)
1546  if (!(currentIndexExtry->Flags & NTFS_INDEX_ENTRY_END))
1547  {
1549  DbgPrint(" Parent File Reference: 0x%016I64x\n", currentIndexExtry->FileName.DirectoryFileReferenceNumber);
1550  DbgPrint(" $FILENAME indexed: ");
1551  Name.Length = currentIndexExtry->FileName.NameLength * sizeof(WCHAR);
1552  Name.MaximumLength = Name.Length;
1553  Name.Buffer = currentIndexExtry->FileName.Name;
1554  DbgPrint("'%wZ'\n", &Name);
1555  }
1556 
1557  // if this node has a sub-node beneath it
1558  if (currentIndexExtry->Flags & NTFS_INDEX_ENTRY_NODE)
1559  {
1560  // Print the VCN of the sub-node
1561  PULONGLONG SubNodeVCN = (PULONGLONG)((ULONG_PTR)currentIndexExtry + currentIndexExtry->Length - sizeof(ULONGLONG));
1562  DbgPrint(" VCN of sub-node: 0x%llx\n", *SubNodeVCN);
1563  }
1564 
1565  CurrentOffset += currentIndexExtry->Length;
1566  ASSERT(currentIndexExtry->Length);
1567  }
1568 
1569 }
1570 
1571 
1572 static
1573 VOID
1575  PNTFS_ATTR_RECORD Attribute)
1576 {
1578 
1579  ULONGLONG lcn = 0;
1580  ULONGLONG runcount = 0;
1581 
1582  switch (Attribute->Type)
1583  {
1584  case AttributeFileName:
1585  NtfsDumpFileNameAttribute(Attribute);
1586  break;
1587 
1590  break;
1591 
1592  case AttributeObjectId:
1593  DbgPrint(" $OBJECT_ID ");
1594  break;
1595 
1597  DbgPrint(" $SECURITY_DESCRIPTOR ");
1598  break;
1599 
1600  case AttributeVolumeName:
1601  NtfsDumpVolumeNameAttribute(Attribute);
1602  break;
1603 
1606  break;
1607 
1608  case AttributeData:
1609  DbgPrint(" $DATA ");
1610  //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
1611  break;
1612 
1613  case AttributeIndexRoot:
1614  NtfsDumpIndexRootAttribute(Attribute);
1615  break;
1616 
1618  DbgPrint(" $INDEX_ALLOCATION ");
1619  break;
1620 
1621  case AttributeBitmap:
1622  DbgPrint(" $BITMAP ");
1623  break;
1624 
1625  case AttributeReparsePoint:
1626  DbgPrint(" $REPARSE_POINT ");
1627  break;
1628 
1630  DbgPrint(" $EA_INFORMATION ");
1631  break;
1632 
1633  case AttributeEA:
1634  DbgPrint(" $EA ");
1635  break;
1636 
1637  case AttributePropertySet:
1638  DbgPrint(" $PROPERTY_SET ");
1639  break;
1640 
1642  DbgPrint(" $LOGGED_UTILITY_STREAM ");
1643  break;
1644 
1645  default:
1646  DbgPrint(" Attribute %lx ",
1647  Attribute->Type);
1648  break;
1649  }
1650 
1651  if (Attribute->Type != AttributeAttributeList)
1652  {
1653  if (Attribute->NameLength != 0)
1654  {
1655  Name.Length = Attribute->NameLength * sizeof(WCHAR);
1656  Name.MaximumLength = Name.Length;
1657  Name.Buffer = (PWCHAR)((ULONG_PTR)Attribute + Attribute->NameOffset);
1658 
1659  DbgPrint("'%wZ' ", &Name);
1660  }
1661 
1662  DbgPrint("(%s)\n",
1663  Attribute->IsNonResident ? "non-resident" : "resident");
1664 
1665  if (Attribute->IsNonResident)
1666  {
1667  FindRun(Attribute,0,&lcn, &runcount);
1668 
1669  DbgPrint(" AllocatedSize %I64u DataSize %I64u InitilizedSize %I64u\n",
1670  Attribute->NonResident.AllocatedSize, Attribute->NonResident.DataSize, Attribute->NonResident.InitializedSize);
1671  DbgPrint(" logical clusters: %I64u - %I64u\n",
1672  lcn, lcn + runcount - 1);
1673  }
1674  else
1675  DbgPrint(" %u bytes of data\n", Attribute->Resident.ValueLength);
1676  }
1677 }
1678 
1679 
1681 {
1682  UCHAR DataRunOffsetSize;
1683  UCHAR DataRunLengthSize;
1684  CHAR i;
1685 
1686  DbgPrint("%02x ", *DataRun);
1687 
1688  if (*DataRun == 0)
1689  return;
1690 
1691  DataRunOffsetSize = (*DataRun >> 4) & 0xF;
1692  DataRunLengthSize = *DataRun & 0xF;
1693 
1694  DataRun++;
1695  for (i = 0; i < DataRunLengthSize; i++)
1696  {
1697  DbgPrint("%02x ", *DataRun);
1698  DataRun++;
1699  }
1700 
1701  for (i = 0; i < DataRunOffsetSize; i++)
1702  {
1703  DbgPrint("%02x ", *DataRun);
1704  DataRun++;
1705  }
1706 
1707  NtfsDumpDataRunData(DataRun);
1708 }
1709 
1710 
1711 VOID
1713  ULONGLONG CurrentLCN)
1714 {
1715  PUCHAR DataRun = StartOfRun;
1716  LONGLONG DataRunOffset;
1717  ULONGLONG DataRunLength;
1718 
1719  if (CurrentLCN == 0)
1720  {
1721  DPRINT1("Dumping data runs.\n\tData:\n\t\t");
1722  NtfsDumpDataRunData(StartOfRun);
1723  DbgPrint("\n\tRuns:\n\t\tOff\t\tLCN\t\tLength\n");
1724  }
1725 
1726  DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
1727 
1728  if (DataRunOffset != -1)
1729  CurrentLCN += DataRunOffset;
1730 
1731  DbgPrint("\t\t%I64d\t", DataRunOffset);
1732  if (DataRunOffset < 99999)
1733  DbgPrint("\t");
1734  DbgPrint("%I64u\t", CurrentLCN);
1735  if (CurrentLCN < 99999)
1736  DbgPrint("\t");
1737  DbgPrint("%I64u\n", DataRunLength);
1738 
1739  if (*DataRun == 0)
1740  DbgPrint("\t\t00\n");
1741  else
1742  NtfsDumpDataRuns(DataRun, CurrentLCN);
1743 }
1744 
1745 
1746 VOID
1748  PFILE_RECORD_HEADER FileRecord)
1749 {
1750  NTSTATUS Status;
1752  PNTFS_ATTR_RECORD Attribute;
1753 
1754  Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1755  while (NT_SUCCESS(Status))
1756  {
1757  NtfsDumpAttribute(Vcb, Attribute);
1758 
1759  Status = FindNextAttribute(&Context, &Attribute);
1760  }
1761 
1763 }
1764 
1767  PFILE_RECORD_HEADER FileRecord,
1768  UCHAR NameType)
1769 {
1771  PNTFS_ATTR_RECORD Attribute;
1773  NTSTATUS Status;
1774 
1775  Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1776  while (NT_SUCCESS(Status))
1777  {
1778  if (Attribute->Type == AttributeFileName)
1779  {
1780  Name = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1781  if (Name->NameType == NameType ||
1784  {
1786  return Name;
1787  }
1788  }
1789 
1790  Status = FindNextAttribute(&Context, &Attribute);
1791  }
1792 
1794  return NULL;
1795 }
1796 
1802 UCHAR
1804  BOOLEAN IsSigned)
1805 {
1806  if (!IsSigned)
1807  {
1808  if (NumberToPack >= 0x0100000000000000)
1809  return 8;
1810  if (NumberToPack >= 0x0001000000000000)
1811  return 7;
1812  if (NumberToPack >= 0x0000010000000000)
1813  return 6;
1814  if (NumberToPack >= 0x0000000100000000)
1815  return 5;
1816  if (NumberToPack >= 0x0000000001000000)
1817  return 4;
1818  if (NumberToPack >= 0x0000000000010000)
1819  return 3;
1820  if (NumberToPack >= 0x0000000000000100)
1821  return 2;
1822  return 1;
1823  }
1824 
1825  if (NumberToPack > 0)
1826  {
1827  // we have to make sure the number that gets encoded won't be interpreted as negative
1828  if (NumberToPack >= 0x0080000000000000)
1829  return 8;
1830  if (NumberToPack >= 0x0000800000000000)
1831  return 7;
1832  if (NumberToPack >= 0x0000008000000000)
1833  return 6;
1834  if (NumberToPack >= 0x0000000080000000)
1835  return 5;
1836  if (NumberToPack >= 0x0000000000800000)
1837  return 4;
1838  if (NumberToPack >= 0x0000000000008000)
1839  return 3;
1840  if (NumberToPack >= 0x0000000000000080)
1841  return 2;
1842  }
1843  else
1844  {
1845  // negative number
1846  if (NumberToPack <= 0xff80000000000000)
1847  return 8;
1848  if (NumberToPack <= 0xffff800000000000)
1849  return 7;
1850  if (NumberToPack <= 0xffffff8000000000)
1851  return 6;
1852  if (NumberToPack <= 0xffffffff80000000)
1853  return 5;
1854  if (NumberToPack <= 0xffffffffff800000)
1855  return 4;
1856  if (NumberToPack <= 0xffffffffffff8000)
1857  return 3;
1858  if (NumberToPack <= 0xffffffffffffff80)
1859  return 2;
1860  }
1861  return 1;
1862 }
1863 
1864 NTSTATUS
1866 {
1867  LONGLONG DataRunOffset;
1868  ULONGLONG DataRunLength;
1869  LONGLONG DataRunStartLCN;
1870 
1871  ULONGLONG LastLCN = 0;
1872  PUCHAR DataRun = (PUCHAR)Attribute + Attribute->NonResident.MappingPairsOffset;
1873 
1874  if (!Attribute->IsNonResident)
1875  return STATUS_INVALID_PARAMETER;
1876 
1877  while (1)
1878  {
1879  DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
1880 
1881  if (DataRunOffset != -1)
1882  {
1883  // Normal data run.
1884  DataRunStartLCN = LastLCN + DataRunOffset;
1885  LastLCN = DataRunStartLCN;
1886  *LastCluster = LastLCN + DataRunLength - 1;
1887  }
1888 
1889  if (*DataRun == 0)
1890  break;
1891  }
1892 
1893  return STATUS_SUCCESS;
1894 }
1895 
1898  PFILE_RECORD_HEADER FileRecord)
1899 {
1900  NTSTATUS Status;
1902  PNTFS_ATTR_RECORD Attribute;
1903  PSTANDARD_INFORMATION StdInfo;
1904 
1905  Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
1906  while (NT_SUCCESS(Status))
1907  {
1908  if (Attribute->Type == AttributeStandardInformation)
1909  {
1910  StdInfo = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
1912  return StdInfo;
1913  }
1914 
1915  Status = FindNextAttribute(&Context, &Attribute);
1916  }
1917 
1919  return NULL;
1920 }
1921 
1936 {
1937  ULONG Length = FIELD_OFFSET(FILENAME_ATTRIBUTE, Name) + (FileNameAttribute->NameLength * sizeof(WCHAR));
1938  return Length;
1939 }
1940 
1943  PFILE_RECORD_HEADER FileRecord)
1944 {
1946 
1948  if (FileName == NULL)
1949  {
1951  if (FileName == NULL)
1952  {
1954  }
1955  }
1956 
1957  return FileName;
1958 }
1959 
1960 /* EOF */
#define KeQuerySystemTime(t)
Definition: env_spec_w32.h:570
signed char * PCHAR
Definition: retypes.h:7
const uint16_t * PCWSTR
Definition: typedefs.h:55
NTSYSAPI void WINAPI RtlClearBits(PRTL_BITMAP, ULONG, ULONG)
#define NTFS_FILE_NAME_DOS
Definition: ntfs.h:65
PFILENAME_ATTRIBUTE GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1942
#define max(a, b)
Definition: svc.c:63
ULONG CollationRule
Definition: ntfs.h:379
ULONGLONG AllocatedSize
Definition: ntfs.h:350
#define TRUE
Definition: types.h:120
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
NTSYSAPI void WINAPI RtlInitializeBitMap(PRTL_BITMAP, PULONG, ULONG)
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define ROUND_UP(n, align)
Definition: eventvwr.h:31
USHORT NameOffset
Definition: ntfs.h:126
ULONGLONG LastAccessTime
Definition: ntfs.h:318
FILENAME_ATTRIBUTE FileName
Definition: ntfs.h:412
ULONGLONG LastWriteTime
Definition: ntfs.h:317
#define STATUS_NOT_IMPLEMENTED
Definition: ntstatus.h:225
#define DbgPrint
Definition: loader.c:25
ULONGLONG ChangeTime
Definition: ntfs.h:347
USHORT MaximumLength
Definition: env_spec_w32.h:370
static VOID NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1466
WCHAR Name[1]
Definition: ntfs.h:364
#define NTFS_FILE_BITMAP
Definition: ntfs.h:29
struct NTFS_ATTR_RECORD * PNTFS_ATTR_RECORD
#define STATUS_INVALID_PARAMETER
Definition: udferr_usr.h:135
#define BooleanFlagOn(F, SF)
Definition: ext2fs.h:183
static NTSTATUS InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1214
PFILENAME_ATTRIBUTE GetFileNameFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, UCHAR NameType)
Definition: attrib.c:1766
NTSTATUS FreeClusters(PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONG ClustersToFree)
Definition: attrib.c:1057
GLuint GLuint GLsizei count
Definition: gl.h:1545
NTSTATUS AddStandardInformation(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:766
unsigned char * PUCHAR
Definition: retypes.h:3
char CHAR
Definition: xmlstorage.h:175
#define FILE_RECORD_END
Definition: ntfs.h:182
LONG NTSTATUS
Definition: precomp.h:26
PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength)
Definition: attrib.c:966
_Must_inspect_result_ _In_ LONGLONG _In_ LONGLONG Lbn
Definition: fsrtlfuncs.h:479
ULONG FileAttribute
Definition: ntfs.h:319
#define ExRaiseStatus
Definition: ntoskrnl.h:95
USHORT Length
Definition: ntfs.h:408
_Inout_ __drv_aliasesMem PSLIST_ENTRY _Inout_ PSLIST_ENTRY _In_ ULONG Count
Definition: exfuncs.h:1015
ULONG BytesInUse
Definition: ntfs.h:253
UCHAR MajorVersion
Definition: ntfs.h:446
union INDEX_ENTRY_ATTRIBUTE::@737 Data
ULONG Type
Definition: ntfs.h:122
UCHAR NameLength
Definition: ntfs.h:362
Definition: ntfs.h:393
NTSTATUS FindAttribute(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER MftRecord, ULONG Type, PCWSTR Name, ULONG NameLength, PNTFS_ATTR_CONTEXT *AttrCtx, PULONG Offset)
Definition: mft.c:131
BOOLEAN FindRun(PNTFS_ATTR_RECORD NresAttr, ULONGLONG vcn, PULONGLONG lcn, PULONGLONG count)
Definition: attrib.c:1010
uint16_t * PWCHAR
Definition: typedefs.h:54
USHORT SequenceNumber
Definition: ntfs.h:249
_Out_ PLONGLONG LargeVbn
Definition: fsrtlfuncs.h:520
ULONGLONG LastAccessTime
Definition: ntfs.h:349
#define NTFS_INDEX_ENTRY_END
Definition: ntfs.h:61
PSTANDARD_INFORMATION GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1897
VOID NTAPI FsRtlTruncateLargeMcb(IN PLARGE_MCB Mcb, IN LONGLONG Vbn)
Definition: largemcb.c:1016
struct VOLINFO_ATTRIBUTE * PVOLINFO_ATTRIBUTE
#define NTFS_FILE_TYPE_DIRECTORY
Definition: ntfs.h:228
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:64
_SEH2_TRY
Definition: create.c:4250
#define RA_INDEXED
Definition: ntfs.h:231
static VOID NtfsDumpAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1574
ULONG FileAttributes
Definition: ntfs.h:352
USHORT KeyLength
Definition: ntfs.h:409
#define STATUS_END_OF_FILE
Definition: shellext.h:62
uint32_t ULONG_PTR
Definition: typedefs.h:63
BOOLEAN NTAPI FsRtlGetNextLargeMcbEntry(IN PLARGE_MCB Mcb, IN ULONG RunIndex, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn, OUT PLONGLONG SectorCount)
Definition: largemcb.c:391
VOID NtfsDumpDataRuns(PVOID StartOfRun, ULONGLONG CurrentLCN)
Definition: attrib.c:1712
__GNU_EXTENSION typedef __int64 * PLONGLONG
Definition: ntbasedef.h:389
NTSTATUS ConvertDataRunsToLargeMCB(PUCHAR DataRun, PLARGE_MCB DataRunsMCB, PULONGLONG pNextVBN)
Definition: attrib.c:825
ULONG FirstEntryOffset
Definition: ntfs.h:369
PNTFS_ATTR_CONTEXT PrepareAttributeContext(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:41
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 STATUS_FILE_CORRUPT_ERROR
Definition: udferr_usr.h:168
struct FILENAME_ATTRIBUTE * PFILENAME_ATTRIBUTE
Definition: Header.h:8
ULONG Length
Definition: ntfs.h:123
PNTFS_ATTR_RECORD MoveAttributes(PDEVICE_EXTENSION DeviceExt, PNTFS_ATTR_RECORD FirstAttributeToMove, ULONG FirstAttributeOffset, ULONG_PTR MoveTo)
Definition: mft.c:456
VOID NtfsDumpFileAttributes(PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord)
Definition: attrib.c:1747
USHORT AttributeOffset
Definition: ntfs.h:251
#define NTFS_FILE_NAME_POSIX
Definition: ntfs.h:63
static VOID NtfsDumpStandardInformationAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1451
#define FRH_DIRECTORY
Definition: ntfs.h:264
struct NameRec_ * Name
Definition: cdprocs.h:464
USHORT Instance
Definition: ntfs.h:128
#define EXCEPTION_EXECUTE_HANDLER
Definition: excpt.h:85
VOID NTAPI FsRtlInitializeLargeMcb(IN PLARGE_MCB Mcb, IN POOL_TYPE PoolType)
Definition: largemcb.c:450
BOOLEAN NTAPI FsRtlLookupLastLargeMcbEntry(IN PLARGE_MCB Mcb, OUT PLONGLONG Vbn, OUT PLONGLONG Lbn)
Definition: largemcb.c:722
unsigned char BOOLEAN
smooth NULL
Definition: ftsmooth.c:416
USHORT LinkCount
Definition: ntfs.h:250
USHORT NextAttributeNumber
Definition: ntfs.h:256
void DPRINT(...)
Definition: polytest.cpp:61
void * PVOID
Definition: retypes.h:9
struct STANDARD_INFORMATION * PSTANDARD_INFORMATION
ULONG SizeOfEntry
Definition: ntfs.h:380
_Inout_ PFILE_OBJECT FileObject
Definition: cdprocs.h:593
NTSTATUS FindNextAttribute(PFIND_ATTR_CONTXT Context, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1388
struct NTFS_ATTR_RECORD::@164::@167 NonResident
VOID NtfsDumpDataRunData(PUCHAR DataRun)
Definition: attrib.c:1680
NTSTATUS AddData(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress)
Definition: attrib.c:160
VOID SetFileRecordEnd(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttrEnd, ULONG EndMarker)
Definition: mft.c:650
int64_t LONGLONG
Definition: typedefs.h:66
int64_t LONG64
Definition: typedefs.h:66
static VOID NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1481
ULONGLONG DataSize
Definition: ntfs.h:351
NTSTATUS AddBitmap(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:72
#define _SEH2_YIELD(STMT_)
Definition: pseh2_64.h:8
if(!(yy_init))
Definition: macro.lex.yy.c:714
LONGLONG CompressedSize
Definition: ntfs.h:150
#define NTFS_FILE_TYPE_ARCHIVE
Definition: ntfs.h:225
#define ATTR_RECORD_ALIGNMENT
Definition: ntfs.h:305
__wchar_t WCHAR
Definition: xmlstorage.h:180
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:32
VOID NTAPI FsRtlDissectName(IN UNICODE_STRING Name, OUT PUNICODE_STRING FirstPart, OUT PUNICODE_STRING RemainingPart)
Definition: name.c:398
uint64_t ULONGLONG
Definition: typedefs.h:65
#define Vcb
Definition: cdprocs.h:1425
struct BitmapData BitmapData
ULONG AttributeType
Definition: ntfs.h:378
ULONGLONG CreationTime
Definition: ntfs.h:346
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:101
INDEX_HEADER_ATTRIBUTE Header
Definition: ntfs.h:383
struct NTFS_ATTR_RECORD::@164::@166 Resident
* PFILE_OBJECT
Definition: iotypes.h:1954
#define TAG_NTFS
Definition: ntfs.h:12
NTSTATUS AddIndexRoot(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PINDEX_ROOT_ATTRIBUTE NewIndexRoot, ULONG RootLength, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:495
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BOOLEAN NTAPI FsRtlAddLargeMcbEntry(IN PLARGE_MCB Mcb, IN LONGLONG Vbn, IN LONGLONG Lbn, IN LONGLONG SectorCount)
Definition: largemcb.c:282
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
NTSTATUS WriteAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, const PUCHAR Buffer, ULONG Length, PULONG RealLengthWritten, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:1259
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
unsigned __int64 ULONG64
Definition: imports.h:198
unsigned char UCHAR
Definition: xmlstorage.h:181
USHORT Flags
Definition: ntfs.h:410
UCHAR GetPackedByteCount(LONGLONG NumberToPack, BOOLEAN IsSigned)
Definition: attrib.c:1803
static const WCHAR L[]
Definition: oid.c:1250
NTSTATUS AddIndexAllocation(PNTFS_VCB Vcb, PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PCWSTR Name, USHORT NameLength)
Definition: attrib.c:388
_In_ GUID _In_ PVOID _In_ ULONG ValueLength
Definition: hubbusif.h:311
UCHAR IsNonResident
Definition: ntfs.h:124
ULONG TotalSizeOfEntries
Definition: ntfs.h:370
VOID FindCloseAttribute(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1422
ULONGLONG DirectoryFileReferenceNumber
Definition: ntfs.h:345
#define INDEX_ROOT_LARGE
Definition: ntfs.h:209
NTSTATUS AddRun(PNTFS_VCB Vcb, PNTFS_ATTR_CONTEXT AttrContext, ULONG AttrOffset, PFILE_RECORD_HEADER FileRecord, ULONGLONG NextAssignedCluster, ULONG RunLength)
Definition: attrib.c:599
UCHAR ClustersPerIndexRecord
Definition: ntfs.h:381
NTSTATUS GetLastClusterInDataRun(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute, PULONGLONG LastCluster)
Definition: attrib.c:1865
static VOID NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1499
#define NTFS_INDEX_ENTRY_NODE
Definition: ntfs.h:60
#define VALUE_OFFSET_ALIGNMENT
Definition: ntfs.h:311
USHORT Flags
Definition: ntfs.h:448
Status
Definition: gdiplustypes.h:24
UCHAR MinorVersion
Definition: ntfs.h:447
ULONGLONG LastWriteTime
Definition: ntfs.h:348
UCHAR NameLength
Definition: ntfs.h:125
struct _FileName FileName
Definition: fatprocs.h:884
NTSTATUS ConvertLargeMCBToDataRuns(PLARGE_MCB DataRunsMCB, PUCHAR RunBuffer, ULONG MaxBufferSize, PULONG UsedBufferSize)
Definition: attrib.c:896
_SEH2_END
Definition: create.c:4424
NTSTATUS FindFirstAttribute(PFIND_ATTR_CONTXT Context, PDEVICE_EXTENSION Vcb, PFILE_RECORD_HEADER FileRecord, BOOLEAN OnlyResident, PNTFS_ATTR_RECORD *Attribute)
Definition: attrib.c:1340
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:61
NTSTATUS ReadFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG index, PFILE_RECORD_HEADER file)
Definition: mft.c:1575
VOID ReleaseAttributeContext(PNTFS_ATTR_CONTEXT Context)
Definition: mft.c:104
unsigned short USHORT
Definition: pedump.c:61
#define INDEX_ROOT_SMALL
Definition: ntfs.h:208
#define STATUS_NO_MEMORY
Definition: ntstatus.h:246
NTSTATUS UpdateFileRecord(PDEVICE_EXTENSION Vcb, ULONGLONG MftIndex, PFILE_RECORD_HEADER FileRecord)
Definition: mft.c:1875
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:254
__int3264 LONG_PTR
Definition: mstsclib_h.h:276
VOID NTAPI FsRtlUninitializeLargeMcb(IN PLARGE_MCB Mcb)
Definition: largemcb.c:1053
unsigned int * PULONG
Definition: retypes.h:1
ULONG ReadAttribute(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_CONTEXT Context, ULONGLONG Offset, PCHAR Buffer, ULONG Length)
Definition: mft.c:1009
#define min(a, b)
Definition: monoChain.cc:55
USHORT Flags
Definition: ntfs.h:252
static VOID NtfsDumpFileNameAttribute(PNTFS_ATTR_RECORD Attribute)
Definition: attrib.c:1433
#define DATA_RUN_ALIGNMENT
Definition: ntfs.h:308
static PNTFS_ATTR_RECORD InternalGetNextAttribute(PFIND_ATTR_CONTXT Context)
Definition: attrib.c:1267
_In_ LONGLONG Vbn
Definition: fsrtlfuncs.h:470
#define DPRINT1
Definition: precomp.h:8
NTSTATUS AddFileName(PFILE_RECORD_HEADER FileRecord, PNTFS_ATTR_RECORD AttributeAddress, PDEVICE_EXTENSION DeviceExt, PFILE_OBJECT FileObject, BOOLEAN CaseSensitive, PULONGLONG ParentMftIndex)
Definition: attrib.c:230
_Must_inspect_result_ _Inout_opt_ PUNICODE_STRING VolumeName
Definition: fltkernel.h:1117
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:390
struct tagContext Context
Definition: acpixf.h:1012
unsigned int ULONG
Definition: retypes.h:1
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
#define ALIGN_UP_BY(size, align)
ULONGLONG CreationTime
Definition: ntfs.h:315
struct INDEX_ROOT_ATTRIBUTE * PINDEX_ROOT_ATTRIBUTE
_Out_ PLONGLONG _Out_ PLONGLONG LargeLbn
Definition: fsrtlfuncs.h:520
#define _SEH2_EXCEPT(...)
Definition: pseh2_64.h:6
#define NTFS_FILE_NAME_WIN32
Definition: ntfs.h:64
ACPI_PHYSICAL_ADDRESS ACPI_SIZE BOOLEAN Warn BOOLEAN Physical UINT32 ACPI_TABLE_HEADER *OutTableHeader ACPI_TABLE_HEADER **OutTable ACPI_HANDLE UINT32 ACPI_WALK_CALLBACK ACPI_WALK_CALLBACK void void **ReturnValue UINT32 NameType
Definition: acpixf.h:642
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1099
#define _SEH2_GetExceptionCode()
Definition: pseh2_64.h:12
static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PCHAR FileName, ULONGLONG *OutMFTIndex)
Definition: ntfs.c:545
UCHAR Reserved
Definition: ntfs.h:137
ULONG GetFileNameAttributeLength(PFILENAME_ATTRIBUTE FileNameAttribute)
Definition: attrib.c:1935
return STATUS_SUCCESS
Definition: btrfs.c:2745
#define NTFS_FILE_NAME_WIN32_AND_DOS
Definition: ntfs.h:66
#define COLLATION_FILE_NAME
Definition: ntfs.h:201
ULONGLONG AttributeDataLength(PNTFS_ATTR_RECORD AttrRecord)
Definition: mft.c:203
BOOLEAN NTAPI RtlIsNameLegalDOS8Dot3(_In_ PUNICODE_STRING Name, _Inout_opt_ POEM_STRING OemName, _Inout_opt_ PBOOLEAN NameContainsSpaces)
struct INDEX_ENTRY_ATTRIBUTE * PINDEX_ENTRY_ATTRIBUTE
ULONGLONG ChangeTime
Definition: ntfs.h:316
#define ULONG_MAX
Definition: limits.h:44
LONGLONG QuadPart
Definition: typedefs.h:112
struct INDEX_ENTRY_ATTRIBUTE::@737::@738 Directory
UCHAR NameType
Definition: ntfs.h:363
#define NTFS_FILE_ROOT
Definition: ntfs.h:28