168244ad452beeec9c39fc32a43c5bd38e7bf6ae
[reactos.git] / reactos / drivers / fs / ntfs / attrib.c
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., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
20 *
21 * COPYRIGHT: See COPYING in the top level directory
22 * PROJECT: ReactOS kernel
23 * FILE: drivers/fs/ntfs/attrib.c
24 * PURPOSE: NTFS filesystem driver
25 * PROGRAMMER: Eric Kohl
26 * Updated by Valentin Verkhovsky 2003/09/12
27 */
28
29 /* INCLUDES *****************************************************************/
30
31 #include "ntfs.h"
32
33 #define NDEBUG
34 #include <debug.h>
35
36 /* GLOBALS *****************************************************************/
37
38
39 /* FUNCTIONS ****************************************************************/
40
41
42
43 ULONG
44 RunLength(PUCHAR run)
45 {
46 return(*run & 0x0f) + ((*run >> 4) & 0x0f) + 1;
47 }
48
49
50 LONGLONG
51 RunLCN(PUCHAR run)
52 {
53 UCHAR n1 = *run & 0x0f;
54 UCHAR n2 = (*run >> 4) & 0x0f;
55 LONGLONG lcn = (n2 == 0) ? 0 : (CHAR)(run[n1 + n2]);
56 LONG i = 0;
57
58 for (i = n1 +n2 - 1; i > n1; i--)
59 lcn = (lcn << 8) + run[i];
60 return lcn;
61 }
62
63
64
65 ULONGLONG
66 RunCount(PUCHAR run)
67 {
68 UCHAR n = *run & 0xf;
69 ULONGLONG count = 0;
70 ULONG i = 0;
71
72 for (i = n; i > 0; i--)
73 count = (count << 8) + run[i];
74 return count;
75 }
76
77
78 BOOLEAN
79 FindRun (PNONRESIDENT_ATTRIBUTE NresAttr,
80 ULONGLONG vcn,
81 PULONGLONG lcn,
82 PULONGLONG count)
83 {
84 PUCHAR run;
85
86 ULONGLONG base = NresAttr->StartVcn;
87
88 if (vcn < NresAttr->StartVcn || vcn > NresAttr->LastVcn)
89 return FALSE;
90
91 *lcn = 0;
92
93 for (run = (PUCHAR)((ULONG)NresAttr + NresAttr->RunArrayOffset);
94 *run != 0; run += RunLength(run))
95 {
96 *lcn += RunLCN(run);
97 *count = RunCount(run);
98
99 if (base <= vcn && vcn < base + *count)
100 {
101 *lcn = (RunLCN(run) == 0) ? 0 : *lcn + vcn - base;
102 *count -= (ULONG)(vcn - base);
103
104 return TRUE;
105 }
106 else
107 {
108 base += *count;
109 }
110 }
111
112 return FALSE;
113 }
114
115
116 static VOID
117 NtfsDumpFileNameAttribute(PATTRIBUTE Attribute)
118 {
119 PRESIDENT_ATTRIBUTE ResAttr;
120 PFILENAME_ATTRIBUTE FileNameAttr;
121
122 DbgPrint(" $FILE_NAME ");
123
124 ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
125 // DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
126
127 FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
128 DbgPrint(" '%.*S' ", FileNameAttr->NameLength, FileNameAttr->Name);
129 }
130
131
132 static VOID
133 NtfsDumpVolumeNameAttribute(PATTRIBUTE Attribute)
134 {
135 PRESIDENT_ATTRIBUTE ResAttr;
136 PWCHAR VolumeName;
137
138 DbgPrint(" $VOLUME_NAME ");
139
140 ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
141 // DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
142
143 VolumeName = (PWCHAR)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
144 DbgPrint(" '%.*S' ", ResAttr->ValueLength / sizeof(WCHAR), VolumeName);
145 }
146
147
148 static VOID
149 NtfsDumpVolumeInformationAttribute(PATTRIBUTE Attribute)
150 {
151 PRESIDENT_ATTRIBUTE ResAttr;
152 PVOLINFO_ATTRIBUTE VolInfoAttr;
153
154 DbgPrint(" $VOLUME_INFORMATION ");
155
156 ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
157 // DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
158
159 VolInfoAttr = (PVOLINFO_ATTRIBUTE)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
160 DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
161 VolInfoAttr->MajorVersion,
162 VolInfoAttr->MinorVersion,
163 VolInfoAttr->Flags);
164 }
165
166
167 static VOID
168 NtfsDumpAttribute (PATTRIBUTE Attribute)
169 {
170 PNONRESIDENT_ATTRIBUTE NresAttr;
171 UNICODE_STRING Name;
172
173 ULONGLONG lcn;
174 ULONGLONG runcount;
175
176 switch (Attribute->AttributeType)
177 {
178 case AttributeFileName:
179 NtfsDumpFileNameAttribute(Attribute);
180 break;
181
182 case AttributeStandardInformation:
183 DbgPrint(" $STANDARD_INFORMATION ");
184 break;
185
186 case AttributeAttributeList:
187 DbgPrint(" $ATTRIBUTE_LIST ");
188 break;
189
190 case AttributeObjectId:
191 DbgPrint(" $OBJECT_ID ");
192 break;
193
194 case AttributeSecurityDescriptor:
195 DbgPrint(" $SECURITY_DESCRIPTOR ");
196 break;
197
198 case AttributeVolumeName:
199 NtfsDumpVolumeNameAttribute(Attribute);
200 break;
201
202 case AttributeVolumeInformation:
203 NtfsDumpVolumeInformationAttribute(Attribute);
204 break;
205
206 case AttributeData:
207 DbgPrint(" $DATA ");
208 //DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
209 break;
210
211 case AttributeIndexRoot:
212 DbgPrint(" $INDEX_ROOT ");
213 break;
214
215 case AttributeIndexAllocation:
216 DbgPrint(" $INDEX_ALLOCATION ");
217 break;
218
219 case AttributeBitmap:
220 DbgPrint(" $BITMAP ");
221 break;
222
223 case AttributeReparsePoint:
224 DbgPrint(" $REPARSE_POINT ");
225 break;
226
227 case AttributeEAInformation:
228 DbgPrint(" $EA_INFORMATION ");
229 break;
230
231 case AttributeEA:
232 DbgPrint(" $EA ");
233 break;
234
235 case AttributePropertySet:
236 DbgPrint(" $PROPERTY_SET ");
237 break;
238
239 case AttributeLoggedUtilityStream:
240 DbgPrint(" $LOGGED_UTILITY_STREAM ");
241 break;
242
243 default:
244 DbgPrint(" Attribute %lx ",
245 Attribute->AttributeType);
246 break;
247 }
248
249 if (Attribute->NameLength != 0)
250 {
251 Name.Length = Attribute->NameLength * sizeof(WCHAR);
252 Name.MaximumLength = Name.Length;
253 Name.Buffer = (PWCHAR)((ULONG)Attribute + Attribute->NameOffset);
254
255 DbgPrint("'%wZ' ", &Name);
256 }
257
258 DbgPrint("(%s)\n",
259 Attribute->Nonresident ? "non-resident" : "resident");
260
261 if (Attribute->Nonresident)
262 {
263 NresAttr = (PNONRESIDENT_ATTRIBUTE)Attribute;
264
265 FindRun (NresAttr,0,&lcn, &runcount);
266
267 DbgPrint (" AllocatedSize %I64u DataSize %I64u\n",
268 NresAttr->AllocatedSize, NresAttr->DataSize);
269 DbgPrint (" logical clusters: %I64u - %I64u\n",
270 lcn, lcn + runcount - 1);
271 }
272 }
273
274
275 VOID
276 NtfsDumpFileAttributes (PFILE_RECORD_HEADER FileRecord)
277 {
278 PATTRIBUTE Attribute;
279
280 Attribute = (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
281 while (Attribute < (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
282 Attribute->AttributeType != (ATTRIBUTE_TYPE)-1)
283 {
284 NtfsDumpAttribute (Attribute);
285
286 Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
287 }
288 }
289
290 /* EOF */