Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / drivers / filesystems / 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18 *
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
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "ntfs.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* GLOBALS *****************************************************************/
35
36
37 /* FUNCTIONS ****************************************************************/
38
39 static
40 ULONG
41 RunLength(PUCHAR run)
42 {
43 return(*run & 0x0f) + ((*run >> 4) & 0x0f) + 1;
44 }
45
46
47 static
48 LONGLONG
49 RunLCN(PUCHAR run)
50 {
51 UCHAR n1 = *run & 0x0f;
52 UCHAR n2 = (*run >> 4) & 0x0f;
53 LONGLONG lcn = (n2 == 0) ? 0 : (CHAR)(run[n1 + n2]);
54 LONG i = 0;
55
56 for (i = n1 +n2 - 1; i > n1; i--)
57 lcn = (lcn << 8) + run[i];
58 return lcn;
59 }
60
61
62 static
63 ULONGLONG
64 RunCount(PUCHAR run)
65 {
66 UCHAR n = *run & 0xf;
67 ULONGLONG count = 0;
68 ULONG i = 0;
69
70 for (i = n; i > 0; i--)
71 count = (count << 8) + run[i];
72 return count;
73 }
74
75
76 BOOLEAN
77 FindRun(PNONRESIDENT_ATTRIBUTE NresAttr,
78 ULONGLONG vcn,
79 PULONGLONG lcn,
80 PULONGLONG count)
81 {
82 PUCHAR run;
83 ULONGLONG base = NresAttr->StartVcn;
84
85 if (vcn < NresAttr->StartVcn || vcn > NresAttr->LastVcn)
86 return FALSE;
87
88 *lcn = 0;
89
90 for (run = (PUCHAR)((ULONG_PTR)NresAttr + NresAttr->RunArrayOffset);
91 *run != 0; run += RunLength(run))
92 {
93 *lcn += RunLCN(run);
94 *count = RunCount(run);
95
96 if (base <= vcn && vcn < base + *count)
97 {
98 *lcn = (RunLCN(run) == 0) ? 0 : *lcn + vcn - base;
99 *count -= (ULONG)(vcn - base);
100
101 return TRUE;
102 }
103 else
104 {
105 base += *count;
106 }
107 }
108
109 return FALSE;
110 }
111
112
113 static
114 VOID
115 NtfsDumpFileNameAttribute(PATTRIBUTE Attribute)
116 {
117 PRESIDENT_ATTRIBUTE ResAttr;
118 PFILENAME_ATTRIBUTE FileNameAttr;
119
120 DbgPrint(" $FILE_NAME ");
121
122 ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
123 // DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
124
125 FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
126 DbgPrint(" '%.*S' ", FileNameAttr->NameLength, FileNameAttr->Name);
127 }
128
129
130 static
131 VOID
132 NtfsDumpVolumeNameAttribute(PATTRIBUTE Attribute)
133 {
134 PRESIDENT_ATTRIBUTE ResAttr;
135 PWCHAR VolumeName;
136
137 DbgPrint(" $VOLUME_NAME ");
138
139 ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
140 // DbgPrint(" Length %lu Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
141
142 VolumeName = (PWCHAR)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
143 DbgPrint(" '%.*S' ", ResAttr->ValueLength / sizeof(WCHAR), VolumeName);
144 }
145
146
147 static
148 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
168 VOID
169 NtfsDumpAttribute (PATTRIBUTE Attribute)
170 {
171 PNONRESIDENT_ATTRIBUTE NresAttr;
172 UNICODE_STRING Name;
173
174 ULONGLONG lcn = 0;
175 ULONGLONG runcount = 0;
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_PTR)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 < (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
283 Attribute->AttributeType != (ATTRIBUTE_TYPE)-1)
284 {
285 NtfsDumpAttribute(Attribute);
286
287 Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
288 }
289 }
290
291 /* EOF */