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(" '%.*S' ", FileNameAttr
->NameLength
, FileNameAttr
->Name
);
113 NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute
)
117 DbgPrint(" $VOLUME_NAME ");
119 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
121 VolumeName
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
122 DbgPrint(" '%.*S' ", Attribute
->Resident
.ValueLength
/ sizeof(WCHAR
), VolumeName
);
128 NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute
)
130 PVOLINFO_ATTRIBUTE VolInfoAttr
;
132 DbgPrint(" $VOLUME_INFORMATION ");
134 // DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
136 VolInfoAttr
= (PVOLINFO_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
137 DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
138 VolInfoAttr
->MajorVersion
,
139 VolInfoAttr
->MinorVersion
,
146 NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute
)
148 PINDEX_ROOT_ATTRIBUTE IndexRootAttr
;
150 IndexRootAttr
= (PINDEX_ROOT_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
152 if (IndexRootAttr
->AttributeType
== AttributeFileName
)
153 ASSERT(IndexRootAttr
->CollationRule
== COLLATION_FILE_NAME
);
155 DbgPrint(" $INDEX_ROOT (%uB, %u) ", IndexRootAttr
->SizeOfEntry
, IndexRootAttr
->ClustersPerIndexRecord
);
157 if (IndexRootAttr
->Header
.Flags
== INDEX_ROOT_SMALL
)
159 DbgPrint(" (small) ");
163 ASSERT(IndexRootAttr
->Header
.Flags
== INDEX_ROOT_LARGE
);
164 DbgPrint(" (large) ");
171 NtfsDumpAttribute(PNTFS_ATTR_RECORD Attribute
)
176 ULONGLONG runcount
= 0;
178 switch (Attribute
->Type
)
180 case AttributeFileName
:
181 NtfsDumpFileNameAttribute(Attribute
);
184 case AttributeStandardInformation
:
185 DbgPrint(" $STANDARD_INFORMATION ");
188 case AttributeAttributeList
:
189 DbgPrint(" $ATTRIBUTE_LIST ");
192 case AttributeObjectId
:
193 DbgPrint(" $OBJECT_ID ");
196 case AttributeSecurityDescriptor
:
197 DbgPrint(" $SECURITY_DESCRIPTOR ");
200 case AttributeVolumeName
:
201 NtfsDumpVolumeNameAttribute(Attribute
);
204 case AttributeVolumeInformation
:
205 NtfsDumpVolumeInformationAttribute(Attribute
);
210 //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
213 case AttributeIndexRoot
:
214 NtfsDumpIndexRootAttribute(Attribute
);
217 case AttributeIndexAllocation
:
218 DbgPrint(" $INDEX_ALLOCATION ");
221 case AttributeBitmap
:
222 DbgPrint(" $BITMAP ");
225 case AttributeReparsePoint
:
226 DbgPrint(" $REPARSE_POINT ");
229 case AttributeEAInformation
:
230 DbgPrint(" $EA_INFORMATION ");
237 case AttributePropertySet
:
238 DbgPrint(" $PROPERTY_SET ");
241 case AttributeLoggedUtilityStream
:
242 DbgPrint(" $LOGGED_UTILITY_STREAM ");
246 DbgPrint(" Attribute %lx ",
251 if (Attribute
->NameLength
!= 0)
253 Name
.Length
= Attribute
->NameLength
* sizeof(WCHAR
);
254 Name
.MaximumLength
= Name
.Length
;
255 Name
.Buffer
= (PWCHAR
)((ULONG_PTR
)Attribute
+ Attribute
->NameOffset
);
257 DbgPrint("'%wZ' ", &Name
);
261 Attribute
->IsNonResident
? "non-resident" : "resident");
263 if (Attribute
->IsNonResident
)
265 FindRun(Attribute
,0,&lcn
, &runcount
);
267 DbgPrint(" AllocatedSize %I64u DataSize %I64u\n",
268 Attribute
->NonResident
.AllocatedSize
, Attribute
->NonResident
.DataSize
);
269 DbgPrint(" logical clusters: %I64u - %I64u\n",
270 lcn
, lcn
+ runcount
- 1);
276 NtfsDumpFileAttributes(PFILE_RECORD_HEADER FileRecord
)
278 PNTFS_ATTR_RECORD Attribute
;
280 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->AttributeOffset
);
281 while (Attribute
< (PNTFS_ATTR_RECORD
)((ULONG_PTR
)FileRecord
+ FileRecord
->BytesInUse
) &&
282 Attribute
->Type
!= AttributeEnd
)
284 NtfsDumpAttribute(Attribute
);
286 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)Attribute
+ Attribute
->Length
);
291 GetFileNameFromRecord(PFILE_RECORD_HEADER FileRecord
, UCHAR NameType
)
293 PNTFS_ATTR_RECORD Attribute
;
294 PFILENAME_ATTRIBUTE Name
;
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 if (Attribute
->Type
== AttributeFileName
)
302 Name
= (PFILENAME_ATTRIBUTE
)((ULONG_PTR
)Attribute
+ Attribute
->Resident
.ValueOffset
);
303 if (Name
->NameType
== NameType
||
304 (Name
->NameType
== NTFS_FILE_NAME_WIN32_AND_DOS
&& NameType
== NTFS_FILE_NAME_WIN32
) ||
305 (Name
->NameType
== NTFS_FILE_NAME_WIN32_AND_DOS
&& NameType
== NTFS_FILE_NAME_DOS
))
311 Attribute
= (PNTFS_ATTR_RECORD
)((ULONG_PTR
)Attribute
+ Attribute
->Length
);