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 * PROGRAMMER: Eric Kohl
24 * Updated by Valentin Verkhovsky 2003/09/12
27 /* INCLUDES *****************************************************************/
34 /* FUNCTIONS ****************************************************************/
37 DecodeRun(PUCHAR DataRun
,
38 LONGLONG
*DataRunOffset
,
39 ULONGLONG
*DataRunLength
)
41 UCHAR DataRunOffsetSize
;
42 UCHAR DataRunLengthSize
;
45 DataRunOffsetSize
= (*DataRun
>> 4) & 0xF;
46 DataRunLengthSize
= *DataRun
& 0xF;
50 for (i
= 0; i
< DataRunLengthSize
; i
++)
52 *DataRunLength
+= ((ULONG64
)*DataRun
) << (i
* 8);
56 /* NTFS 3+ sparse files */
57 if (DataRunOffsetSize
== 0)
63 for (i
= 0; i
< DataRunOffsetSize
- 1; i
++)
65 *DataRunOffset
+= ((ULONG64
)*DataRun
) << (i
* 8);
68 /* The last byte contains sign so we must process it different way. */
69 *DataRunOffset
= ((LONG64
)(CHAR
)(*(DataRun
++)) << (i
* 8)) + *DataRunOffset
;
72 DPRINT("DataRunOffsetSize: %x\n", DataRunOffsetSize
);
73 DPRINT("DataRunLengthSize: %x\n", DataRunLengthSize
);
74 DPRINT("DataRunOffset: %x\n", *DataRunOffset
);
75 DPRINT("DataRunLength: %x\n", *DataRunLength
);
81 FindRun(PNTFS_ATTR_RECORD NresAttr
,
86 if (vcn
< NresAttr
->NonResident
.LowestVCN
|| vcn
> NresAttr
->NonResident
.HighestVCN
)
89 DecodeRun((PUCHAR
)((ULONG_PTR
)NresAttr
+ NresAttr
->NonResident
.MappingPairsOffset
), (PLONGLONG
)lcn
, count
);
97 NtfsDumpFileNameAttribute(PNTFS_ATTR_RECORD Attribute
)
99 PFILENAME_ATTRIBUTE FileNameAttr
;
101 DbgPrint(" $FILE_NAME ");
103 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
105 FileNameAttr
= (PFILENAME_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
106 DbgPrint(" '%.*S' ", FileNameAttr
->NameLength
, FileNameAttr
->Name
);
112 NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute
)
116 DbgPrint(" $VOLUME_NAME ");
118 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
120 VolumeName
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
121 DbgPrint(" '%.*S' ", Attribute
->Resident
.ValueLength
/ sizeof(WCHAR
), VolumeName
);
127 NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute
)
129 PVOLINFO_ATTRIBUTE VolInfoAttr
;
131 DbgPrint(" $VOLUME_INFORMATION ");
133 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
135 VolInfoAttr
= (PVOLINFO_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
136 DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
137 VolInfoAttr
->MajorVersion
,
138 VolInfoAttr
->MinorVersion
,
145 NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute
)
147 PINDEX_ROOT_ATTRIBUTE IndexRootAttr
;
149 IndexRootAttr
= (PINDEX_ROOT_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
151 if (IndexRootAttr
->AttributeType
== AttributeFileName
)
152 ASSERT(IndexRootAttr
->CollationRule
== COLLATION_FILE_NAME
);
154 DbgPrint(" $INDEX_ROOT (%uB, %u) ", IndexRootAttr
->SizeOfEntry
, IndexRootAttr
->ClustersPerIndexRecord
);
156 if (IndexRootAttr
->Header
.Flags
== INDEX_ROOT_SMALL
)
158 DbgPrint(" (small) ");
162 ASSERT(IndexRootAttr
->Header
.Flags
== INDEX_ROOT_LARGE
);
163 DbgPrint(" (large) ");
170 NtfsDumpAttribute(PNTFS_ATTR_RECORD Attribute
)
175 ULONGLONG runcount
= 0;
177 switch (Attribute
->Type
)
179 case AttributeFileName
:
180 NtfsDumpFileNameAttribute(Attribute
);
183 case AttributeStandardInformation
:
184 DbgPrint(" $STANDARD_INFORMATION ");
187 case AttributeAttributeList
:
188 DbgPrint(" $ATTRIBUTE_LIST ");
191 case AttributeObjectId
:
192 DbgPrint(" $OBJECT_ID ");
195 case AttributeSecurityDescriptor
:
196 DbgPrint(" $SECURITY_DESCRIPTOR ");
199 case AttributeVolumeName
:
200 NtfsDumpVolumeNameAttribute(Attribute
);
203 case AttributeVolumeInformation
:
204 NtfsDumpVolumeInformationAttribute(Attribute
);
209 //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
212 case AttributeIndexRoot
:
213 NtfsDumpIndexRootAttribute(Attribute
);
216 case AttributeIndexAllocation
:
217 DbgPrint(" $INDEX_ALLOCATION ");
220 case AttributeBitmap
:
221 DbgPrint(" $BITMAP ");
224 case AttributeReparsePoint
:
225 DbgPrint(" $REPARSE_POINT ");
228 case AttributeEAInformation
:
229 DbgPrint(" $EA_INFORMATION ");
236 case AttributePropertySet
:
237 DbgPrint(" $PROPERTY_SET ");
240 case AttributeLoggedUtilityStream
:
241 DbgPrint(" $LOGGED_UTILITY_STREAM ");
245 DbgPrint(" Attribute %lx ",
250 if (Attribute
->NameLength
!= 0)
252 Name
.Length
= Attribute
->NameLength
* sizeof(WCHAR
);
253 Name
.MaximumLength
= Name
.Length
;
254 Name
.Buffer
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->NameOffset
);
256 DbgPrint("'%wZ' ", &Name
);
260 Attribute
->IsNonResident
? "non-resident" : "resident");
262 if (Attribute
->IsNonResident
)
264 FindRun(Attribute
,0,&lcn
, &runcount
);
266 DbgPrint(" AllocatedSize %I64u DataSize %I64u\n",
267 Attribute
->NonResident
.AllocatedSize
, Attribute
->NonResident
.DataSize
);
268 DbgPrint(" logical clusters: %I64u - %I64u\n",
269 lcn
, lcn
+ runcount
- 1);
275 NtfsDumpFileAttributes(PFILE_RECORD_HEADER FileRecord
)
277 PNTFS_ATTR_RECORD Attribute
;
279 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->AttributeOffset
);
280 while (Attribute
< (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->BytesInUse
) &&
281 Attribute
->Type
!= (ATTRIBUTE_TYPE
)-1)
283 NtfsDumpAttribute(Attribute
);
285 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)Attribute
+ Attribute
->Length
);