xref: /reactos/drivers/filesystems/ntfs/fcb.c (revision 5efb6e3d)
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