3 * Copyright (C) 2002,2003 ReactOS Team
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.
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.
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.
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
25 * Hervé Poussineau (hpoussin@reactos.org)
28 /* INCLUDES *****************************************************************/
35 /* FUNCTIONS ****************************************************************/
38 DecodeRun(PUCHAR DataRun
,
39 LONGLONG
*DataRunOffset
,
40 ULONGLONG
*DataRunLength
)
42 UCHAR DataRunOffsetSize
;
43 UCHAR DataRunLengthSize
;
46 DataRunOffsetSize
= (*DataRun
>> 4) & 0xF;
47 DataRunLengthSize
= *DataRun
& 0xF;
51 for (i
= 0; i
< DataRunLengthSize
; i
++)
53 *DataRunLength
+= ((ULONG64
)*DataRun
) << (i
* 8);
57 /* NTFS 3+ sparse files */
58 if (DataRunOffsetSize
== 0)
64 for (i
= 0; i
< DataRunOffsetSize
- 1; i
++)
66 *DataRunOffset
+= ((ULONG64
)*DataRun
) << (i
* 8);
69 /* The last byte contains sign so we must process it different way. */
70 *DataRunOffset
= ((LONG64
)(CHAR
)(*(DataRun
++)) << (i
* 8)) + *DataRunOffset
;
73 DPRINT("DataRunOffsetSize: %x\n", DataRunOffsetSize
);
74 DPRINT("DataRunLengthSize: %x\n", DataRunLengthSize
);
75 DPRINT("DataRunOffset: %x\n", *DataRunOffset
);
76 DPRINT("DataRunLength: %x\n", *DataRunLength
);
82 FindRun(PNTFS_ATTR_RECORD NresAttr
,
87 if (vcn
< NresAttr
->NonResident
.LowestVCN
|| vcn
> NresAttr
->NonResident
.HighestVCN
)
90 DecodeRun((PUCHAR
)((ULONG_PTR
)NresAttr
+ NresAttr
->NonResident
.MappingPairsOffset
), (PLONGLONG
)lcn
, count
);
98 NtfsDumpFileNameAttribute(PNTFS_ATTR_RECORD Attribute
)
100 PFILENAME_ATTRIBUTE FileNameAttr
;
102 DbgPrint(" $FILE_NAME ");
104 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
106 FileNameAttr
= (PFILENAME_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
107 DbgPrint(" (%x) '%.*S' ", FileNameAttr
->NameType
, FileNameAttr
->NameLength
, FileNameAttr
->Name
);
108 DbgPrint(" '%x' ", FileNameAttr
->FileAttributes
);
114 NtfsDumpStandardInformationAttribute(PNTFS_ATTR_RECORD Attribute
)
116 PSTANDARD_INFORMATION StandardInfoAttr
;
118 DbgPrint(" $STANDARD_INFORMATION ");
120 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
122 StandardInfoAttr
= (PSTANDARD_INFORMATION
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
123 DbgPrint(" '%x' ", StandardInfoAttr
->FileAttribute
);
129 NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute
)
133 DbgPrint(" $VOLUME_NAME ");
135 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
137 VolumeName
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
138 DbgPrint(" '%.*S' ", Attribute
->Resident
.ValueLength
/ sizeof(WCHAR
), VolumeName
);
144 NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute
)
146 PVOLINFO_ATTRIBUTE VolInfoAttr
;
148 DbgPrint(" $VOLUME_INFORMATION ");
150 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
152 VolInfoAttr
= (PVOLINFO_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
153 DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
154 VolInfoAttr
->MajorVersion
,
155 VolInfoAttr
->MinorVersion
,
162 NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute
)
164 PINDEX_ROOT_ATTRIBUTE IndexRootAttr
;
166 IndexRootAttr
= (PINDEX_ROOT_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
168 if (IndexRootAttr
->AttributeType
== AttributeFileName
)
169 ASSERT(IndexRootAttr
->CollationRule
== COLLATION_FILE_NAME
);
171 DbgPrint(" $INDEX_ROOT (%uB, %u) ", IndexRootAttr
->SizeOfEntry
, IndexRootAttr
->ClustersPerIndexRecord
);
173 if (IndexRootAttr
->Header
.Flags
== INDEX_ROOT_SMALL
)
175 DbgPrint(" (small) ");
179 ASSERT(IndexRootAttr
->Header
.Flags
== INDEX_ROOT_LARGE
);
180 DbgPrint(" (large) ");
187 NtfsDumpAttribute(PNTFS_ATTR_RECORD Attribute
)
192 ULONGLONG runcount
= 0;
194 switch (Attribute
->Type
)
196 case AttributeFileName
:
197 NtfsDumpFileNameAttribute(Attribute
);
200 case AttributeStandardInformation
:
201 NtfsDumpStandardInformationAttribute(Attribute
);
204 case AttributeAttributeList
:
205 DbgPrint(" $ATTRIBUTE_LIST ");
208 case AttributeObjectId
:
209 DbgPrint(" $OBJECT_ID ");
212 case AttributeSecurityDescriptor
:
213 DbgPrint(" $SECURITY_DESCRIPTOR ");
216 case AttributeVolumeName
:
217 NtfsDumpVolumeNameAttribute(Attribute
);
220 case AttributeVolumeInformation
:
221 NtfsDumpVolumeInformationAttribute(Attribute
);
226 //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
229 case AttributeIndexRoot
:
230 NtfsDumpIndexRootAttribute(Attribute
);
233 case AttributeIndexAllocation
:
234 DbgPrint(" $INDEX_ALLOCATION ");
237 case AttributeBitmap
:
238 DbgPrint(" $BITMAP ");
241 case AttributeReparsePoint
:
242 DbgPrint(" $REPARSE_POINT ");
245 case AttributeEAInformation
:
246 DbgPrint(" $EA_INFORMATION ");
253 case AttributePropertySet
:
254 DbgPrint(" $PROPERTY_SET ");
257 case AttributeLoggedUtilityStream
:
258 DbgPrint(" $LOGGED_UTILITY_STREAM ");
262 DbgPrint(" Attribute %lx ",
267 if (Attribute
->NameLength
!= 0)
269 Name
.Length
= Attribute
->NameLength
* sizeof(WCHAR
);
270 Name
.MaximumLength
= Name
.Length
;
271 Name
.Buffer
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->NameOffset
);
273 DbgPrint("'%wZ' ", &Name
);
277 Attribute
->IsNonResident
? "non-resident" : "resident");
279 if (Attribute
->IsNonResident
)
281 FindRun(Attribute
,0,&lcn
, &runcount
);
283 DbgPrint(" AllocatedSize %I64u DataSize %I64u\n",
284 Attribute
->NonResident
.AllocatedSize
, Attribute
->NonResident
.DataSize
);
285 DbgPrint(" logical clusters: %I64u - %I64u\n",
286 lcn
, lcn
+ runcount
- 1);
292 NtfsDumpFileAttributes(PFILE_RECORD_HEADER FileRecord
)
294 PNTFS_ATTR_RECORD Attribute
;
296 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->AttributeOffset
);
297 while (Attribute
< (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->BytesInUse
) &&
298 Attribute
->Type
!= AttributeEnd
)
300 NtfsDumpAttribute(Attribute
);
302 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)Attribute
+ Attribute
->Length
);
307 GetFileNameFromRecord(PFILE_RECORD_HEADER FileRecord
, UCHAR NameType
)
309 PNTFS_ATTR_RECORD Attribute
;
310 PFILENAME_ATTRIBUTE Name
;
312 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->AttributeOffset
);
313 while (Attribute
< (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->BytesInUse
) &&
314 Attribute
->Type
!= AttributeEnd
)
316 if (Attribute
->Type
== AttributeFileName
)
318 Name
= (PFILENAME_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
319 if (Name
->NameType
== NameType
||
320 (Name
->NameType
== NTFS_FILE_NAME_WIN32_AND_DOS
&& NameType
== NTFS_FILE_NAME_WIN32
) ||
321 (Name
->NameType
== NTFS_FILE_NAME_WIN32_AND_DOS
&& NameType
== NTFS_FILE_NAME_DOS
))
327 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)Attribute
+ Attribute
->Length
);
333 PSTANDARD_INFORMATION
334 GetStandardInformationFromRecord(PFILE_RECORD_HEADER FileRecord
)
336 PNTFS_ATTR_RECORD Attribute
;
337 PSTANDARD_INFORMATION StdInfo
;
339 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->AttributeOffset
);
340 while (Attribute
< (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->BytesInUse
) &&
341 Attribute
->Type
!= AttributeEnd
)
343 if (Attribute
->Type
== AttributeStandardInformation
)
345 StdInfo
= (PSTANDARD_INFORMATION
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
349 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)Attribute
+ Attribute
->Length
);
356 GetBestFileNameFromRecord(PFILE_RECORD_HEADER FileRecord
)
358 PFILENAME_ATTRIBUTE FileName
;
360 FileName
= GetFileNameFromRecord(FileRecord
, NTFS_FILE_NAME_POSIX
);
361 if (FileName
== NULL
)
363 FileName
= GetFileNameFromRecord(FileRecord
, NTFS_FILE_NAME_WIN32
);
364 if (FileName
== NULL
)
366 FileName
= GetFileNameFromRecord(FileRecord
, NTFS_FILE_NAME_DOS
);