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