1c2c66affSColin Finck /*
2c2c66affSColin Finck * ReactOS kernel
3c2c66affSColin Finck * Copyright (C) 2002, 2014 ReactOS Team
4c2c66affSColin Finck *
5c2c66affSColin Finck * This program is free software; you can redistribute it and/or modify
6c2c66affSColin Finck * it under the terms of the GNU General Public License as published by
7c2c66affSColin Finck * the Free Software Foundation; either version 2 of the License, or
8c2c66affSColin Finck * (at your option) any later version.
9c2c66affSColin Finck *
10c2c66affSColin Finck * This program is distributed in the hope that it will be useful,
11c2c66affSColin Finck * but WITHOUT ANY WARRANTY; without even the implied warranty of
12c2c66affSColin Finck * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13c2c66affSColin Finck * GNU General Public License for more details.
14c2c66affSColin Finck *
15c2c66affSColin Finck * You should have received a copy of the GNU General Public License
16c2c66affSColin Finck * along with this program; if not, write to the Free Software
17c2c66affSColin Finck * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
18c2c66affSColin Finck *
19c2c66affSColin Finck * COPYRIGHT: See COPYING in the top level directory
20c2c66affSColin Finck * PROJECT: ReactOS kernel
21c2c66affSColin Finck * FILE: drivers/filesystem/ntfs/fcb.c
22c2c66affSColin Finck * PURPOSE: NTFS filesystem driver
23c2c66affSColin Finck * PROGRAMMERS: Eric Kohl
24c2c66affSColin Finck * Pierre Schweitzer (pierre@reactos.org)
25c2c66affSColin Finck * Hervé Poussineau (hpoussin@reactos.org)
26c2c66affSColin Finck */
27c2c66affSColin Finck
28c2c66affSColin Finck /* INCLUDES *****************************************************************/
29c2c66affSColin Finck
30c2c66affSColin Finck #include "ntfs.h"
31c2c66affSColin Finck
32c2c66affSColin Finck #define NDEBUG
33c2c66affSColin Finck #include <debug.h>
34c2c66affSColin Finck
35c2c66affSColin Finck /* FUNCTIONS ****************************************************************/
36c2c66affSColin Finck
37c2c66affSColin Finck static
3839a06faeSTrevor Thompson PCWSTR
NtfsGetNextPathElement(PCWSTR FileName)3939a06faeSTrevor Thompson NtfsGetNextPathElement(PCWSTR FileName)
40c2c66affSColin Finck {
41c2c66affSColin Finck if (*FileName == L'\0')
42c2c66affSColin Finck {
43c2c66affSColin Finck return NULL;
44c2c66affSColin Finck }
45c2c66affSColin Finck
46c2c66affSColin Finck while (*FileName != L'\0' && *FileName != L'\\')
47c2c66affSColin Finck {
48c2c66affSColin Finck FileName++;
49c2c66affSColin Finck }
50c2c66affSColin Finck
51c2c66affSColin Finck return FileName;
52c2c66affSColin Finck }
53c2c66affSColin Finck
54c2c66affSColin Finck
55c2c66affSColin Finck static
56c2c66affSColin Finck VOID
NtfsWSubString(PWCHAR pTarget,PCWSTR pSource,size_t pLength)57c2c66affSColin Finck NtfsWSubString(PWCHAR pTarget,
5839a06faeSTrevor Thompson PCWSTR pSource,
59c2c66affSColin Finck size_t pLength)
60c2c66affSColin Finck {
61c2c66affSColin Finck wcsncpy(pTarget, pSource, pLength);
62c2c66affSColin Finck pTarget[pLength] = L'\0';
63c2c66affSColin Finck }
64c2c66affSColin Finck
65c2c66affSColin Finck
66c2c66affSColin Finck PNTFS_FCB
NtfsCreateFCB(PCWSTR FileName,PCWSTR Stream,PNTFS_VCB Vcb)67c2c66affSColin Finck NtfsCreateFCB(PCWSTR FileName,
68c2c66affSColin Finck PCWSTR Stream,
69c2c66affSColin Finck PNTFS_VCB Vcb)
70c2c66affSColin Finck {
71c2c66affSColin Finck PNTFS_FCB Fcb;
72c2c66affSColin Finck
73c2c66affSColin Finck ASSERT(Vcb);
74c2c66affSColin Finck ASSERT(Vcb->Identifier.Type == NTFS_TYPE_VCB);
75c2c66affSColin Finck
76c2c66affSColin Finck Fcb = ExAllocateFromNPagedLookasideList(&NtfsGlobalData->FcbLookasideList);
77*5efb6e3dSSerge Gautherie if (Fcb == NULL)
78*5efb6e3dSSerge Gautherie {
79*5efb6e3dSSerge Gautherie return NULL;
80*5efb6e3dSSerge Gautherie }
81*5efb6e3dSSerge Gautherie
82c2c66affSColin Finck RtlZeroMemory(Fcb, sizeof(NTFS_FCB));
83c2c66affSColin Finck
84c2c66affSColin Finck Fcb->Identifier.Type = NTFS_TYPE_FCB;
85c2c66affSColin Finck Fcb->Identifier.Size = sizeof(NTFS_TYPE_FCB);
86c2c66affSColin Finck
87c2c66affSColin Finck Fcb->Vcb = Vcb;
88c2c66affSColin Finck
89c2c66affSColin Finck if (FileName)
90c2c66affSColin Finck {
91c2c66affSColin Finck wcscpy(Fcb->PathName, FileName);
92c2c66affSColin Finck if (wcsrchr(Fcb->PathName, '\\') != 0)
93c2c66affSColin Finck {
94c2c66affSColin Finck Fcb->ObjectName = wcsrchr(Fcb->PathName, '\\');
95c2c66affSColin Finck }
96c2c66affSColin Finck else
97c2c66affSColin Finck {
98c2c66affSColin Finck Fcb->ObjectName = Fcb->PathName;
99c2c66affSColin Finck }
100c2c66affSColin Finck }
101c2c66affSColin Finck
102c2c66affSColin Finck if (Stream)
103c2c66affSColin Finck {
104c2c66affSColin Finck wcscpy(Fcb->Stream, Stream);
105c2c66affSColin Finck }
106c2c66affSColin Finck else
107c2c66affSColin Finck {
108c2c66affSColin Finck Fcb->Stream[0] = UNICODE_NULL;
109c2c66affSColin Finck }
110c2c66affSColin Finck
111c2c66affSColin Finck ExInitializeResourceLite(&Fcb->MainResource);
112c2c66affSColin Finck
113c2c66affSColin Finck Fcb->RFCB.Resource = &(Fcb->MainResource);
114c2c66affSColin Finck
115c2c66affSColin Finck return Fcb;
116c2c66affSColin Finck }
117c2c66affSColin Finck
118c2c66affSColin Finck
119c2c66affSColin Finck VOID
NtfsDestroyFCB(PNTFS_FCB Fcb)120c2c66affSColin Finck NtfsDestroyFCB(PNTFS_FCB Fcb)
121c2c66affSColin Finck {
122c2c66affSColin Finck ASSERT(Fcb);
123c2c66affSColin Finck ASSERT(Fcb->Identifier.Type == NTFS_TYPE_FCB);
124c2c66affSColin Finck
125c2c66affSColin Finck ExDeleteResourceLite(&Fcb->MainResource);
126c2c66affSColin Finck
127c2c66affSColin Finck ExFreeToNPagedLookasideList(&NtfsGlobalData->FcbLookasideList, Fcb);
128c2c66affSColin Finck }
129c2c66affSColin Finck
130c2c66affSColin Finck
131c2c66affSColin Finck BOOLEAN
NtfsFCBIsDirectory(PNTFS_FCB Fcb)132c2c66affSColin Finck NtfsFCBIsDirectory(PNTFS_FCB Fcb)
133c2c66affSColin Finck {
134c2c66affSColin Finck return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_DIRECTORY) == NTFS_FILE_TYPE_DIRECTORY);
135c2c66affSColin Finck }
136c2c66affSColin Finck
137c2c66affSColin Finck
138c2c66affSColin Finck BOOLEAN
NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)139c2c66affSColin Finck NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)
140c2c66affSColin Finck {
141c2c66affSColin Finck return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_REPARSE) == NTFS_FILE_TYPE_REPARSE);
142c2c66affSColin Finck }
143c2c66affSColin Finck
144c2c66affSColin Finck
145c2c66affSColin Finck BOOLEAN
NtfsFCBIsCompressed(PNTFS_FCB Fcb)146c2c66affSColin Finck NtfsFCBIsCompressed(PNTFS_FCB Fcb)
147c2c66affSColin Finck {
148c2c66affSColin Finck return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_COMPRESSED) == NTFS_FILE_TYPE_COMPRESSED);
149c2c66affSColin Finck }
150c2c66affSColin Finck
151c2c66affSColin Finck BOOLEAN
NtfsFCBIsEncrypted(PNTFS_FCB Fcb)152240dc77eSMarat Nagayev NtfsFCBIsEncrypted(PNTFS_FCB Fcb)
153240dc77eSMarat Nagayev {
154240dc77eSMarat Nagayev return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_ENCRYPTED) == NTFS_FILE_TYPE_ENCRYPTED);
155240dc77eSMarat Nagayev }
156240dc77eSMarat Nagayev
157240dc77eSMarat Nagayev BOOLEAN
NtfsFCBIsRoot(PNTFS_FCB Fcb)158c2c66affSColin Finck NtfsFCBIsRoot(PNTFS_FCB Fcb)
159c2c66affSColin Finck {
160c2c66affSColin Finck return (wcscmp(Fcb->PathName, L"\\") == 0);
161c2c66affSColin Finck }
162c2c66affSColin Finck
163c2c66affSColin Finck
164c2c66affSColin Finck VOID
NtfsGrabFCB(PNTFS_VCB Vcb,PNTFS_FCB Fcb)165c2c66affSColin Finck NtfsGrabFCB(PNTFS_VCB Vcb,
166c2c66affSColin Finck PNTFS_FCB Fcb)
167c2c66affSColin Finck {
168c2c66affSColin Finck KIRQL oldIrql;
169c2c66affSColin Finck
170c2c66affSColin Finck DPRINT("grabbing FCB at %p: %S, refCount:%d\n",
171c2c66affSColin Finck Fcb,
172c2c66affSColin Finck Fcb->PathName,
173c2c66affSColin Finck Fcb->RefCount);
174c2c66affSColin Finck
175c2c66affSColin Finck KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
176c2c66affSColin Finck Fcb->RefCount++;
177c2c66affSColin Finck KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
178c2c66affSColin Finck }
179c2c66affSColin Finck
180c2c66affSColin Finck
181c2c66affSColin Finck VOID
NtfsReleaseFCB(PNTFS_VCB Vcb,PNTFS_FCB Fcb)182c2c66affSColin Finck NtfsReleaseFCB(PNTFS_VCB Vcb,
183c2c66affSColin Finck PNTFS_FCB Fcb)
184c2c66affSColin Finck {
185c2c66affSColin Finck KIRQL oldIrql;
186c2c66affSColin Finck
187c2c66affSColin Finck DPRINT("releasing FCB at %p: %S, refCount:%d\n",
188c2c66affSColin Finck Fcb,
189c2c66affSColin Finck Fcb->PathName,
190c2c66affSColin Finck Fcb->RefCount);
191c2c66affSColin Finck
192c2c66affSColin Finck KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
193c2c66affSColin Finck Fcb->RefCount--;
194c2c66affSColin Finck if (Fcb->RefCount <= 0 && !NtfsFCBIsDirectory(Fcb))
195c2c66affSColin Finck {
196c2c66affSColin Finck RemoveEntryList(&Fcb->FcbListEntry);
197c2c66affSColin Finck KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
198c2c66affSColin Finck CcUninitializeCacheMap(Fcb->FileObject, NULL, NULL);
199c2c66affSColin Finck NtfsDestroyFCB(Fcb);
200c2c66affSColin Finck }
201c2c66affSColin Finck else
202c2c66affSColin Finck {
203c2c66affSColin Finck KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
204c2c66affSColin Finck }
205c2c66affSColin Finck }
206c2c66affSColin Finck
207c2c66affSColin Finck
208c2c66affSColin Finck VOID
NtfsAddFCBToTable(PNTFS_VCB Vcb,PNTFS_FCB Fcb)209c2c66affSColin Finck NtfsAddFCBToTable(PNTFS_VCB Vcb,
210c2c66affSColin Finck PNTFS_FCB Fcb)
211c2c66affSColin Finck {
212c2c66affSColin Finck KIRQL oldIrql;
213c2c66affSColin Finck
214c2c66affSColin Finck KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
215c2c66affSColin Finck Fcb->Vcb = Vcb;
216c2c66affSColin Finck InsertTailList(&Vcb->FcbListHead, &Fcb->FcbListEntry);
217c2c66affSColin Finck KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
218c2c66affSColin Finck }
219c2c66affSColin Finck
220c2c66affSColin Finck
221c2c66affSColin Finck PNTFS_FCB
NtfsGrabFCBFromTable(PNTFS_VCB Vcb,PCWSTR FileName)222c2c66affSColin Finck NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
223c2c66affSColin Finck PCWSTR FileName)
224c2c66affSColin Finck {
225c2c66affSColin Finck KIRQL oldIrql;
226c2c66affSColin Finck PNTFS_FCB Fcb;
227c2c66affSColin Finck PLIST_ENTRY current_entry;
228c2c66affSColin Finck
229c2c66affSColin Finck KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
230c2c66affSColin Finck
231c2c66affSColin Finck if (FileName == NULL || *FileName == 0)
232c2c66affSColin Finck {
233c2c66affSColin Finck DPRINT("Return FCB for stream file object\n");
234c2c66affSColin Finck Fcb = Vcb->StreamFileObject->FsContext;
235c2c66affSColin Finck Fcb->RefCount++;
236c2c66affSColin Finck KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
237c2c66affSColin Finck return Fcb;
238c2c66affSColin Finck }
239c2c66affSColin Finck
240c2c66affSColin Finck current_entry = Vcb->FcbListHead.Flink;
241c2c66affSColin Finck while (current_entry != &Vcb->FcbListHead)
242c2c66affSColin Finck {
243c2c66affSColin Finck Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
244c2c66affSColin Finck
245c2c66affSColin Finck DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
246c2c66affSColin Finck if (_wcsicmp(FileName, Fcb->PathName) == 0)
247c2c66affSColin Finck {
248c2c66affSColin Finck Fcb->RefCount++;
249c2c66affSColin Finck KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
250c2c66affSColin Finck return Fcb;
251c2c66affSColin Finck }
252c2c66affSColin Finck
253c2c66affSColin Finck //FIXME: need to compare against short name in FCB here
254c2c66affSColin Finck
255c2c66affSColin Finck current_entry = current_entry->Flink;
256c2c66affSColin Finck }
257c2c66affSColin Finck
258c2c66affSColin Finck KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
259c2c66affSColin Finck
260c2c66affSColin Finck return NULL;
261c2c66affSColin Finck }
262c2c66affSColin Finck
263c2c66affSColin Finck
264c2c66affSColin Finck NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb,PNTFS_FCB Fcb)265c2c66affSColin Finck NtfsFCBInitializeCache(PNTFS_VCB Vcb,
266c2c66affSColin Finck PNTFS_FCB Fcb)
267c2c66affSColin Finck {
268c2c66affSColin Finck PFILE_OBJECT FileObject;
269c2c66affSColin Finck NTSTATUS Status;
270c2c66affSColin Finck PNTFS_CCB newCCB;
271c2c66affSColin Finck
272c2c66affSColin Finck FileObject = IoCreateStreamFileObject(NULL, Vcb->StorageDevice);
273c2c66affSColin Finck
274c2c66affSColin Finck newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB);
275c2c66affSColin Finck if (newCCB == NULL)
276c2c66affSColin Finck {
277c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
278c2c66affSColin Finck }
279c2c66affSColin Finck
280c2c66affSColin Finck RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
281c2c66affSColin Finck
282c2c66affSColin Finck newCCB->Identifier.Type = NTFS_TYPE_CCB;
283c2c66affSColin Finck newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
284c2c66affSColin Finck
285c2c66affSColin Finck FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
286c2c66affSColin Finck FileObject->FsContext = Fcb;
287c2c66affSColin Finck FileObject->FsContext2 = newCCB;
288c2c66affSColin Finck newCCB->PtrFileObject = FileObject;
289c2c66affSColin Finck Fcb->FileObject = FileObject;
290c2c66affSColin Finck Fcb->Vcb = Vcb;
291c2c66affSColin Finck
292c2c66affSColin Finck Status = STATUS_SUCCESS;
293c2c66affSColin Finck _SEH2_TRY
294c2c66affSColin Finck {
295c2c66affSColin Finck CcInitializeCacheMap(FileObject,
296c2c66affSColin Finck (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
297c2c66affSColin Finck FALSE,
298c2c66affSColin Finck &(NtfsGlobalData->CacheMgrCallbacks),
299c2c66affSColin Finck Fcb);
300c2c66affSColin Finck }
301c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
302c2c66affSColin Finck {
303c2c66affSColin Finck FileObject->FsContext2 = NULL;
304c2c66affSColin Finck ExFreePoolWithTag(newCCB, TAG_CCB);
305c2c66affSColin Finck ObDereferenceObject(FileObject);
306c2c66affSColin Finck Fcb->FileObject = NULL;
307c2c66affSColin Finck return _SEH2_GetExceptionCode();
308c2c66affSColin Finck }
309c2c66affSColin Finck _SEH2_END;
310c2c66affSColin Finck
311c2c66affSColin Finck ObDereferenceObject(FileObject);
312c2c66affSColin Finck Fcb->Flags |= FCB_CACHE_INITIALIZED;
313c2c66affSColin Finck
314c2c66affSColin Finck return Status;
315c2c66affSColin Finck }
316c2c66affSColin Finck
317c2c66affSColin Finck
318c2c66affSColin Finck PNTFS_FCB
NtfsMakeRootFCB(PNTFS_VCB Vcb)319c2c66affSColin Finck NtfsMakeRootFCB(PNTFS_VCB Vcb)
320c2c66affSColin Finck {
321c2c66affSColin Finck PNTFS_FCB Fcb;
322c2c66affSColin Finck PFILE_RECORD_HEADER MftRecord;
323c2c66affSColin Finck PFILENAME_ATTRIBUTE FileName;
324c2c66affSColin Finck
325216a2caeSPierre Schweitzer MftRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
326c2c66affSColin Finck if (MftRecord == NULL)
327c2c66affSColin Finck {
328c2c66affSColin Finck return NULL;
329c2c66affSColin Finck }
330c2c66affSColin Finck
331c2c66affSColin Finck if (!NT_SUCCESS(ReadFileRecord(Vcb, NTFS_FILE_ROOT, MftRecord)))
332c2c66affSColin Finck {
333216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
334c2c66affSColin Finck return NULL;
335c2c66affSColin Finck }
336c2c66affSColin Finck
337c2c66affSColin Finck FileName = GetFileNameFromRecord(Vcb, MftRecord, NTFS_FILE_NAME_WIN32);
338c2c66affSColin Finck if (!FileName)
339c2c66affSColin Finck {
340216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
341c2c66affSColin Finck return NULL;
342c2c66affSColin Finck }
343c2c66affSColin Finck
344c2c66affSColin Finck Fcb = NtfsCreateFCB(L"\\", NULL, Vcb);
345c2c66affSColin Finck if (!Fcb)
346c2c66affSColin Finck {
347216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
348c2c66affSColin Finck return NULL;
349c2c66affSColin Finck }
350c2c66affSColin Finck
351c2c66affSColin Finck memcpy(&Fcb->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength));
352c2c66affSColin Finck Fcb->Entry.NameType = FileName->NameType;
353c2c66affSColin Finck Fcb->Entry.NameLength = 0;
354c2c66affSColin Finck Fcb->Entry.Name[0] = UNICODE_NULL;
355c2c66affSColin Finck Fcb->RefCount = 1;
356c2c66affSColin Finck Fcb->DirIndex = 0;
357c2c66affSColin Finck Fcb->RFCB.FileSize.QuadPart = FileName->DataSize;
358c2c66affSColin Finck Fcb->RFCB.ValidDataLength.QuadPart = FileName->DataSize;
359c2c66affSColin Finck Fcb->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
360c2c66affSColin Finck Fcb->MFTIndex = NTFS_FILE_ROOT;
361c2c66affSColin Finck Fcb->LinkCount = MftRecord->LinkCount;
362c2c66affSColin Finck
363c2c66affSColin Finck NtfsFCBInitializeCache(Vcb, Fcb);
364c2c66affSColin Finck NtfsAddFCBToTable(Vcb, Fcb);
365c2c66affSColin Finck NtfsGrabFCB(Vcb, Fcb);
366c2c66affSColin Finck
367216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, MftRecord);
368c2c66affSColin Finck
369c2c66affSColin Finck return Fcb;
370c2c66affSColin Finck }
371c2c66affSColin Finck
372c2c66affSColin Finck
373c2c66affSColin Finck PNTFS_FCB
NtfsOpenRootFCB(PNTFS_VCB Vcb)374c2c66affSColin Finck NtfsOpenRootFCB(PNTFS_VCB Vcb)
375c2c66affSColin Finck {
376c2c66affSColin Finck PNTFS_FCB Fcb;
377c2c66affSColin Finck
378c2c66affSColin Finck Fcb = NtfsGrabFCBFromTable(Vcb, L"\\");
379c2c66affSColin Finck if (Fcb == NULL)
380c2c66affSColin Finck {
381c2c66affSColin Finck Fcb = NtfsMakeRootFCB(Vcb);
382c2c66affSColin Finck }
383c2c66affSColin Finck
384c2c66affSColin Finck return Fcb;
385c2c66affSColin Finck }
386c2c66affSColin Finck
387c2c66affSColin Finck
388c2c66affSColin Finck NTSTATUS
NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,PNTFS_FCB DirectoryFCB,PUNICODE_STRING Name,PCWSTR Stream,PFILE_RECORD_HEADER Record,ULONGLONG MFTIndex,PNTFS_FCB * fileFCB)389c2c66affSColin Finck NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
390c2c66affSColin Finck PNTFS_FCB DirectoryFCB,
391c2c66affSColin Finck PUNICODE_STRING Name,
392c2c66affSColin Finck PCWSTR Stream,
393c2c66affSColin Finck PFILE_RECORD_HEADER Record,
394c2c66affSColin Finck ULONGLONG MFTIndex,
395c2c66affSColin Finck PNTFS_FCB * fileFCB)
396c2c66affSColin Finck {
397c2c66affSColin Finck WCHAR pathName[MAX_PATH];
398c2c66affSColin Finck PFILENAME_ATTRIBUTE FileName;
399c2c66affSColin Finck PSTANDARD_INFORMATION StdInfo;
400c2c66affSColin Finck PNTFS_FCB rcFCB;
401c2c66affSColin Finck ULONGLONG Size, AllocatedSize;
402c2c66affSColin Finck
40315524349SVictor Perevertkin DPRINT("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p, %p)\n", Vcb, DirectoryFCB, Name, Stream, Record, fileFCB);
404c2c66affSColin Finck
405c2c66affSColin Finck FileName = GetBestFileNameFromRecord(Vcb, Record);
406c2c66affSColin Finck if (!FileName)
407c2c66affSColin Finck {
408c2c66affSColin Finck return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
409c2c66affSColin Finck }
410c2c66affSColin Finck
411c2c66affSColin Finck if (DirectoryFCB && Name)
412c2c66affSColin Finck {
413c2c66affSColin Finck if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
414c2c66affSColin Finck sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
415c2c66affSColin Finck {
416c2c66affSColin Finck return STATUS_OBJECT_NAME_INVALID;
417c2c66affSColin Finck }
418c2c66affSColin Finck
419c2c66affSColin Finck wcscpy(pathName, DirectoryFCB->PathName);
420c2c66affSColin Finck if (!NtfsFCBIsRoot(DirectoryFCB))
421c2c66affSColin Finck {
422c2c66affSColin Finck wcscat(pathName, L"\\");
423c2c66affSColin Finck }
424c2c66affSColin Finck wcscat(pathName, Name->Buffer);
425c2c66affSColin Finck }
426c2c66affSColin Finck else
427c2c66affSColin Finck {
428c2c66affSColin Finck RtlCopyMemory(pathName, FileName->Name, FileName->NameLength * sizeof (WCHAR));
429c2c66affSColin Finck pathName[FileName->NameLength] = UNICODE_NULL;
430c2c66affSColin Finck }
431c2c66affSColin Finck
432c2c66affSColin Finck Size = NtfsGetFileSize(Vcb, Record, (Stream ? Stream : L""), (Stream ? wcslen(Stream) : 0), &AllocatedSize);
433c2c66affSColin Finck
434c2c66affSColin Finck rcFCB = NtfsCreateFCB(pathName, Stream, Vcb);
435c2c66affSColin Finck if (!rcFCB)
436c2c66affSColin Finck {
437c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
438c2c66affSColin Finck }
439c2c66affSColin Finck
440c2c66affSColin Finck memcpy(&rcFCB->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength));
441c2c66affSColin Finck rcFCB->Entry.NameType = FileName->NameType;
442c2c66affSColin Finck rcFCB->RFCB.FileSize.QuadPart = Size;
443c2c66affSColin Finck rcFCB->RFCB.ValidDataLength.QuadPart = Size;
444c2c66affSColin Finck rcFCB->RFCB.AllocationSize.QuadPart = AllocatedSize;
445c2c66affSColin Finck
446c2c66affSColin Finck StdInfo = GetStandardInformationFromRecord(Vcb, Record);
447c2c66affSColin Finck if (StdInfo != NULL)
448c2c66affSColin Finck {
449c2c66affSColin Finck rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute;
450c2c66affSColin Finck }
451c2c66affSColin Finck
452c2c66affSColin Finck NtfsFCBInitializeCache(Vcb, rcFCB);
453c2c66affSColin Finck rcFCB->RefCount = 1;
454c2c66affSColin Finck rcFCB->MFTIndex = MFTIndex;
455c2c66affSColin Finck rcFCB->LinkCount = Record->LinkCount;
456c2c66affSColin Finck NtfsAddFCBToTable(Vcb, rcFCB);
457c2c66affSColin Finck *fileFCB = rcFCB;
458c2c66affSColin Finck
459c2c66affSColin Finck return STATUS_SUCCESS;
460c2c66affSColin Finck }
461c2c66affSColin Finck
462c2c66affSColin Finck
463c2c66affSColin Finck NTSTATUS
NtfsAttachFCBToFileObject(PNTFS_VCB Vcb,PNTFS_FCB Fcb,PFILE_OBJECT FileObject)464c2c66affSColin Finck NtfsAttachFCBToFileObject(PNTFS_VCB Vcb,
465c2c66affSColin Finck PNTFS_FCB Fcb,
466c2c66affSColin Finck PFILE_OBJECT FileObject)
467c2c66affSColin Finck {
468c2c66affSColin Finck PNTFS_CCB newCCB;
469c2c66affSColin Finck
470c2c66affSColin Finck newCCB = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_CCB), TAG_CCB);
471c2c66affSColin Finck if (newCCB == NULL)
472c2c66affSColin Finck {
473c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
474c2c66affSColin Finck }
475c2c66affSColin Finck
476c2c66affSColin Finck RtlZeroMemory(newCCB, sizeof(NTFS_CCB));
477c2c66affSColin Finck
478c2c66affSColin Finck newCCB->Identifier.Type = NTFS_TYPE_CCB;
479c2c66affSColin Finck newCCB->Identifier.Size = sizeof(NTFS_TYPE_CCB);
480c2c66affSColin Finck
481c2c66affSColin Finck FileObject->SectionObjectPointer = &Fcb->SectionObjectPointers;
482c2c66affSColin Finck FileObject->FsContext = Fcb;
483c2c66affSColin Finck FileObject->FsContext2 = newCCB;
484c2c66affSColin Finck newCCB->PtrFileObject = FileObject;
485c2c66affSColin Finck Fcb->Vcb = Vcb;
486c2c66affSColin Finck
487c2c66affSColin Finck if (!(Fcb->Flags & FCB_CACHE_INITIALIZED))
488c2c66affSColin Finck {
489c2c66affSColin Finck _SEH2_TRY
490c2c66affSColin Finck {
491c2c66affSColin Finck CcInitializeCacheMap(FileObject,
492c2c66affSColin Finck (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
493c2c66affSColin Finck FALSE,
494c2c66affSColin Finck &(NtfsGlobalData->CacheMgrCallbacks),
495c2c66affSColin Finck Fcb);
496c2c66affSColin Finck }
497c2c66affSColin Finck _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
498c2c66affSColin Finck {
499c2c66affSColin Finck FileObject->FsContext2 = NULL;
500c2c66affSColin Finck ExFreePoolWithTag(newCCB, TAG_CCB);
501c2c66affSColin Finck return _SEH2_GetExceptionCode();
502c2c66affSColin Finck }
503c2c66affSColin Finck _SEH2_END;
504c2c66affSColin Finck
505c2c66affSColin Finck Fcb->Flags |= FCB_CACHE_INITIALIZED;
506c2c66affSColin Finck }
507c2c66affSColin Finck
508c2c66affSColin Finck //DPRINT("file open: fcb:%x file size: %d\n", Fcb, Fcb->Entry.DataLengthL);
509c2c66affSColin Finck
510c2c66affSColin Finck return STATUS_SUCCESS;
511c2c66affSColin Finck }
512c2c66affSColin Finck
513c2c66affSColin Finck
514c2c66affSColin Finck static NTSTATUS
NtfsDirFindFile(PNTFS_VCB Vcb,PNTFS_FCB DirectoryFcb,PWSTR FileToFind,BOOLEAN CaseSensitive,PNTFS_FCB * FoundFCB)515c2c66affSColin Finck NtfsDirFindFile(PNTFS_VCB Vcb,
516c2c66affSColin Finck PNTFS_FCB DirectoryFcb,
517c2c66affSColin Finck PWSTR FileToFind,
518032be029STrevor Thompson BOOLEAN CaseSensitive,
519c2c66affSColin Finck PNTFS_FCB *FoundFCB)
520c2c66affSColin Finck {
521c2c66affSColin Finck NTSTATUS Status;
522c2c66affSColin Finck ULONGLONG CurrentDir;
523c2c66affSColin Finck UNICODE_STRING File;
524c2c66affSColin Finck PFILE_RECORD_HEADER FileRecord;
525c2c66affSColin Finck ULONGLONG MFTIndex;
526c2c66affSColin Finck PWSTR Colon, OldColon;
527c2c66affSColin Finck PNTFS_ATTR_CONTEXT DataContext;
528c2c66affSColin Finck USHORT Length = 0;
529c2c66affSColin Finck
53015524349SVictor Perevertkin DPRINT("NtfsDirFindFile(%p, %p, %S, %s, %p)\n",
531032be029STrevor Thompson Vcb,
532032be029STrevor Thompson DirectoryFcb,
533032be029STrevor Thompson FileToFind,
534032be029STrevor Thompson CaseSensitive ? "TRUE" : "FALSE",
535032be029STrevor Thompson FoundFCB);
536c2c66affSColin Finck
537c2c66affSColin Finck *FoundFCB = NULL;
538c2c66affSColin Finck RtlInitUnicodeString(&File, FileToFind);
539c2c66affSColin Finck CurrentDir = DirectoryFcb->MFTIndex;
540c2c66affSColin Finck
541c2c66affSColin Finck Colon = wcsrchr(FileToFind, L':');
542c2c66affSColin Finck if (Colon != NULL)
543c2c66affSColin Finck {
544c2c66affSColin Finck Length = File.Length;
545c2c66affSColin Finck File.Length = (Colon - FileToFind) * sizeof(WCHAR);
546c2c66affSColin Finck
547c2c66affSColin Finck if (_wcsicmp(Colon + 1, L"$DATA") == 0)
548c2c66affSColin Finck {
549c2c66affSColin Finck OldColon = Colon;
550c2c66affSColin Finck Colon[0] = UNICODE_NULL;
551c2c66affSColin Finck Colon = wcsrchr(FileToFind, L':');
552c2c66affSColin Finck if (Colon != NULL)
553c2c66affSColin Finck {
554c2c66affSColin Finck Length = File.Length;
555c2c66affSColin Finck File.Length = (Colon - FileToFind) * sizeof(WCHAR);
556c2c66affSColin Finck }
557c2c66affSColin Finck else
558c2c66affSColin Finck {
559c2c66affSColin Finck Colon = OldColon;
560c2c66affSColin Finck Colon[0] = L':';
561c2c66affSColin Finck }
562c2c66affSColin Finck }
563c2c66affSColin Finck
564c2c66affSColin Finck /* Skip colon */
565c2c66affSColin Finck ++Colon;
566c2c66affSColin Finck DPRINT1("Will now look for file '%wZ' with stream '%S'\n", &File, Colon);
567c2c66affSColin Finck }
568c2c66affSColin Finck
569948e9190STrevor Thompson Status = NtfsLookupFileAt(Vcb, &File, CaseSensitive, &FileRecord, &MFTIndex, CurrentDir);
570c2c66affSColin Finck if (!NT_SUCCESS(Status))
571c2c66affSColin Finck {
572c2c66affSColin Finck return Status;
573c2c66affSColin Finck }
574c2c66affSColin Finck
575c2c66affSColin Finck if (Length != 0)
576c2c66affSColin Finck {
577c2c66affSColin Finck File.Length = Length;
578c2c66affSColin Finck }
579c2c66affSColin Finck
580c2c66affSColin Finck if ((FileRecord->Flags & FRH_DIRECTORY) && Colon != 0)
581c2c66affSColin Finck {
582216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
583c2c66affSColin Finck return STATUS_INVALID_PARAMETER;
584c2c66affSColin Finck }
585c2c66affSColin Finck else if (Colon != 0)
586c2c66affSColin Finck {
587ba33b9faSTrevor Thompson Status = FindAttribute(Vcb, FileRecord, AttributeData, Colon, wcslen(Colon), &DataContext, NULL);
588c2c66affSColin Finck if (!NT_SUCCESS(Status))
589c2c66affSColin Finck {
590c2c66affSColin Finck return STATUS_OBJECT_NAME_NOT_FOUND;
591c2c66affSColin Finck }
592c2c66affSColin Finck ReleaseAttributeContext(DataContext);
593c2c66affSColin Finck }
594c2c66affSColin Finck
595c2c66affSColin Finck Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, Colon, FileRecord, MFTIndex, FoundFCB);
596216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
597c2c66affSColin Finck
598c2c66affSColin Finck return Status;
599c2c66affSColin Finck }
600c2c66affSColin Finck
601c2c66affSColin Finck
602c2c66affSColin Finck NTSTATUS
NtfsGetFCBForFile(PNTFS_VCB Vcb,PNTFS_FCB * pParentFCB,PNTFS_FCB * pFCB,PCWSTR pFileName,BOOLEAN CaseSensitive)603c2c66affSColin Finck NtfsGetFCBForFile(PNTFS_VCB Vcb,
604c2c66affSColin Finck PNTFS_FCB *pParentFCB,
605c2c66affSColin Finck PNTFS_FCB *pFCB,
60639a06faeSTrevor Thompson PCWSTR pFileName,
607032be029STrevor Thompson BOOLEAN CaseSensitive)
608c2c66affSColin Finck {
609c2c66affSColin Finck NTSTATUS Status;
610c2c66affSColin Finck WCHAR pathName [MAX_PATH];
611c2c66affSColin Finck WCHAR elementName [MAX_PATH];
61239a06faeSTrevor Thompson PCWSTR currentElement;
613c2c66affSColin Finck PNTFS_FCB FCB;
614c2c66affSColin Finck PNTFS_FCB parentFCB;
615c2c66affSColin Finck
616032be029STrevor Thompson DPRINT("NtfsGetFCBForFile(%p, %p, %p, '%S', %s)\n",
617c2c66affSColin Finck Vcb,
618c2c66affSColin Finck pParentFCB,
619c2c66affSColin Finck pFCB,
620032be029STrevor Thompson pFileName,
621032be029STrevor Thompson CaseSensitive ? "TRUE" : "FALSE");
622c2c66affSColin Finck
623c2c66affSColin Finck /* Dummy code */
624c2c66affSColin Finck // FCB = NtfsOpenRootFCB(Vcb);
625c2c66affSColin Finck // *pFCB = FCB;
626c2c66affSColin Finck // *pParentFCB = NULL;
627c2c66affSColin Finck
628c2c66affSColin Finck #if 1
629c2c66affSColin Finck /* Trivial case, open of the root directory on volume */
630c2c66affSColin Finck if (pFileName[0] == L'\0' || wcscmp(pFileName, L"\\") == 0)
631c2c66affSColin Finck {
632c2c66affSColin Finck DPRINT("returning root FCB\n");
633c2c66affSColin Finck
634c2c66affSColin Finck FCB = NtfsOpenRootFCB(Vcb);
635c2c66affSColin Finck *pFCB = FCB;
636c2c66affSColin Finck *pParentFCB = NULL;
637c2c66affSColin Finck
638c2c66affSColin Finck return (FCB != NULL) ? STATUS_SUCCESS : STATUS_OBJECT_PATH_NOT_FOUND;
639c2c66affSColin Finck }
640c2c66affSColin Finck else
641c2c66affSColin Finck {
642c2c66affSColin Finck currentElement = pFileName + 1;
643c2c66affSColin Finck wcscpy (pathName, L"\\");
644c2c66affSColin Finck FCB = NtfsOpenRootFCB (Vcb);
645c2c66affSColin Finck }
646c2c66affSColin Finck
647c2c66affSColin Finck parentFCB = NULL;
648c2c66affSColin Finck
649c2c66affSColin Finck /* Parse filename and check each path element for existence and access */
650c2c66affSColin Finck while (NtfsGetNextPathElement(currentElement) != 0)
651c2c66affSColin Finck {
652c2c66affSColin Finck /* Skip blank directory levels */
653c2c66affSColin Finck if ((NtfsGetNextPathElement(currentElement) - currentElement) == 0)
654c2c66affSColin Finck {
655c2c66affSColin Finck currentElement++;
656c2c66affSColin Finck continue;
657c2c66affSColin Finck }
658c2c66affSColin Finck
659c2c66affSColin Finck DPRINT("Parsing, currentElement:%S\n", currentElement);
660c2c66affSColin Finck DPRINT(" parentFCB:%p FCB:%p\n", parentFCB, FCB);
661c2c66affSColin Finck
662c2c66affSColin Finck /* Descend to next directory level */
663c2c66affSColin Finck if (parentFCB)
664c2c66affSColin Finck {
665c2c66affSColin Finck NtfsReleaseFCB(Vcb, parentFCB);
666c2c66affSColin Finck parentFCB = NULL;
667c2c66affSColin Finck }
668c2c66affSColin Finck
669c2c66affSColin Finck /* fail if element in FCB is not a directory */
670c2c66affSColin Finck if (!NtfsFCBIsDirectory(FCB))
671c2c66affSColin Finck {
672c2c66affSColin Finck DPRINT("Element in requested path is not a directory\n");
673c2c66affSColin Finck
674c2c66affSColin Finck NtfsReleaseFCB(Vcb, FCB);
675c2c66affSColin Finck FCB = 0;
676c2c66affSColin Finck *pParentFCB = NULL;
677c2c66affSColin Finck *pFCB = NULL;
678c2c66affSColin Finck
679c2c66affSColin Finck return STATUS_OBJECT_PATH_NOT_FOUND;
680c2c66affSColin Finck }
681c2c66affSColin Finck
682c2c66affSColin Finck parentFCB = FCB;
683c2c66affSColin Finck
684c2c66affSColin Finck /* Extract next directory level into dirName */
685c2c66affSColin Finck NtfsWSubString(pathName,
686c2c66affSColin Finck pFileName,
687c2c66affSColin Finck NtfsGetNextPathElement(currentElement) - pFileName);
688c2c66affSColin Finck DPRINT(" pathName:%S\n", pathName);
689c2c66affSColin Finck
690c2c66affSColin Finck FCB = NtfsGrabFCBFromTable(Vcb, pathName);
691c2c66affSColin Finck if (FCB == NULL)
692c2c66affSColin Finck {
693c2c66affSColin Finck NtfsWSubString(elementName,
694c2c66affSColin Finck currentElement,
695c2c66affSColin Finck NtfsGetNextPathElement(currentElement) - currentElement);
696c2c66affSColin Finck DPRINT(" elementName:%S\n", elementName);
697c2c66affSColin Finck
698032be029STrevor Thompson Status = NtfsDirFindFile(Vcb, parentFCB, elementName, CaseSensitive, &FCB);
699c2c66affSColin Finck if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
700c2c66affSColin Finck {
701c2c66affSColin Finck *pParentFCB = parentFCB;
702c2c66affSColin Finck *pFCB = NULL;
703c2c66affSColin Finck currentElement = NtfsGetNextPathElement(currentElement);
704c2c66affSColin Finck if (*currentElement == L'\0' || NtfsGetNextPathElement(currentElement + 1) == 0)
705c2c66affSColin Finck {
706c2c66affSColin Finck return STATUS_OBJECT_NAME_NOT_FOUND;
707c2c66affSColin Finck }
708c2c66affSColin Finck else
709c2c66affSColin Finck {
710c2c66affSColin Finck return STATUS_OBJECT_PATH_NOT_FOUND;
711c2c66affSColin Finck }
712c2c66affSColin Finck }
713c2c66affSColin Finck else if (!NT_SUCCESS(Status))
714c2c66affSColin Finck {
715c2c66affSColin Finck NtfsReleaseFCB(Vcb, parentFCB);
716c2c66affSColin Finck *pParentFCB = NULL;
717c2c66affSColin Finck *pFCB = NULL;
718c2c66affSColin Finck
719c2c66affSColin Finck return Status;
720c2c66affSColin Finck }
721c2c66affSColin Finck }
722c2c66affSColin Finck
723c2c66affSColin Finck currentElement = NtfsGetNextPathElement(currentElement);
724c2c66affSColin Finck }
725c2c66affSColin Finck
726c2c66affSColin Finck *pParentFCB = parentFCB;
727c2c66affSColin Finck *pFCB = FCB;
728c2c66affSColin Finck #endif
729c2c66affSColin Finck
730c2c66affSColin Finck return STATUS_SUCCESS;
731c2c66affSColin Finck }
732c2c66affSColin Finck
733c2c66affSColin Finck
734c2c66affSColin Finck NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb,PNTFS_FCB pFCB,ULONG Type,PCWSTR Name,ULONG NameLength,PVOID * Data)735c2c66affSColin Finck NtfsReadFCBAttribute(PNTFS_VCB Vcb,
736c2c66affSColin Finck PNTFS_FCB pFCB,
737c2c66affSColin Finck ULONG Type,
738c2c66affSColin Finck PCWSTR Name,
739c2c66affSColin Finck ULONG NameLength,
740c2c66affSColin Finck PVOID * Data)
741c2c66affSColin Finck {
742c2c66affSColin Finck NTSTATUS Status;
743c2c66affSColin Finck PFILE_RECORD_HEADER FileRecord;
744c2c66affSColin Finck PNTFS_ATTR_CONTEXT AttrCtxt;
745c2c66affSColin Finck ULONGLONG AttrLength;
746c2c66affSColin Finck
747216a2caeSPierre Schweitzer FileRecord = ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
748c2c66affSColin Finck if (FileRecord == NULL)
749c2c66affSColin Finck {
750c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
751c2c66affSColin Finck }
752c2c66affSColin Finck
753c2c66affSColin Finck Status = ReadFileRecord(Vcb, pFCB->MFTIndex, FileRecord);
754c2c66affSColin Finck if (!NT_SUCCESS(Status))
755c2c66affSColin Finck {
756216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
757c2c66affSColin Finck return Status;
758c2c66affSColin Finck }
759c2c66affSColin Finck
760ba33b9faSTrevor Thompson Status = FindAttribute(Vcb, FileRecord, Type, Name, NameLength, &AttrCtxt, NULL);
761c2c66affSColin Finck if (!NT_SUCCESS(Status))
762c2c66affSColin Finck {
763216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
764c2c66affSColin Finck return Status;
765c2c66affSColin Finck }
766c2c66affSColin Finck
7674dfcd1d5STrevor Thompson AttrLength = AttributeDataLength(AttrCtxt->pRecord);
768c2c66affSColin Finck *Data = ExAllocatePoolWithTag(NonPagedPool, AttrLength, TAG_NTFS);
769c2c66affSColin Finck if (*Data == NULL)
770c2c66affSColin Finck {
771c2c66affSColin Finck ReleaseAttributeContext(AttrCtxt);
772216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
773c2c66affSColin Finck return STATUS_INSUFFICIENT_RESOURCES;
774c2c66affSColin Finck }
775c2c66affSColin Finck
776c2c66affSColin Finck ReadAttribute(Vcb, AttrCtxt, 0, *Data, AttrLength);
777c2c66affSColin Finck
778c2c66affSColin Finck ReleaseAttributeContext(AttrCtxt);
779216a2caeSPierre Schweitzer ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList, FileRecord);
780c2c66affSColin Finck
781c2c66affSColin Finck return STATUS_SUCCESS;
782c2c66affSColin Finck }
783c2c66affSColin Finck
784c2c66affSColin Finck /* EOF */
785