* PURPOSE: NTFS filesystem driver
* PROGRAMMERS: Eric Kohl
* Pierre Schweitzer (pierre@reactos.org)
+ * Hervé Poussineau (hpoussin@reactos.org)
*/
/* INCLUDES *****************************************************************/
#define NDEBUG
#include <debug.h>
-/* MACROS *******************************************************************/
-
-#define TAG_FCB 'BCFI'
-
/* FUNCTIONS ****************************************************************/
static
PNTFS_FCB
NtfsCreateFCB(PCWSTR FileName,
+ PCWSTR Stream,
PNTFS_VCB Vcb)
{
PNTFS_FCB Fcb;
ASSERT(Vcb);
ASSERT(Vcb->Identifier.Type == NTFS_TYPE_VCB);
- Fcb = ExAllocatePoolWithTag(NonPagedPool, sizeof(NTFS_FCB), TAG_FCB);
+ Fcb = ExAllocateFromNPagedLookasideList(&NtfsGlobalData->FcbLookasideList);
RtlZeroMemory(Fcb, sizeof(NTFS_FCB));
Fcb->Identifier.Type = NTFS_TYPE_FCB;
}
}
+ if (Stream)
+ {
+ wcscpy(Fcb->Stream, Stream);
+ }
+ else
+ {
+ Fcb->Stream[0] = UNICODE_NULL;
+ }
+
ExInitializeResourceLite(&Fcb->MainResource);
Fcb->RFCB.Resource = &(Fcb->MainResource);
ExDeleteResourceLite(&Fcb->MainResource);
- ExFreePool(Fcb);
+ ExFreeToNPagedLookasideList(&NtfsGlobalData->FcbLookasideList, Fcb);
}
}
+BOOLEAN
+NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)
+{
+ return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_REPARSE) == NTFS_FILE_TYPE_REPARSE);
+}
+
+
BOOLEAN
NtfsFCBIsRoot(PNTFS_FCB Fcb)
{
Fcb->Vcb = Vcb;
Status = STATUS_SUCCESS;
- CcInitializeCacheMap(FileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- FALSE,
- &(NtfsGlobalData->CacheMgrCallbacks),
- Fcb);
+ _SEH2_TRY
+ {
+ CcInitializeCacheMap(FileObject,
+ (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
+ FALSE,
+ &(NtfsGlobalData->CacheMgrCallbacks),
+ Fcb);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ FileObject->FsContext2 = NULL;
+ ExFreePoolWithTag(newCCB, TAG_CCB);
+ ObDereferenceObject(FileObject);
+ Fcb->FileObject = NULL;
+ return _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
ObDereferenceObject(FileObject);
Fcb->Flags |= FCB_CACHE_INITIALIZED;
return NULL;
}
- Fcb = NtfsCreateFCB(L"\\", Vcb);
+ Fcb = NtfsCreateFCB(L"\\", NULL, Vcb);
if (!Fcb)
{
ExFreePoolWithTag(MftRecord, TAG_NTFS);
Fcb->RFCB.ValidDataLength.QuadPart = FileName->DataSize;
Fcb->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
Fcb->MFTIndex = NTFS_FILE_ROOT;
+ Fcb->LinkCount = MftRecord->LinkCount;
NtfsFCBInitializeCache(Vcb, Fcb);
NtfsAddFCBToTable(Vcb, Fcb);
NTSTATUS
NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
- PNTFS_FCB DirectoryFCB,
- PUNICODE_STRING Name,
- PFILE_RECORD_HEADER Record,
+ PNTFS_FCB DirectoryFCB,
+ PUNICODE_STRING Name,
+ PCWSTR Stream,
+ PFILE_RECORD_HEADER Record,
ULONGLONG MFTIndex,
- PNTFS_FCB * fileFCB)
+ PNTFS_FCB * fileFCB)
{
WCHAR pathName[MAX_PATH];
PFILENAME_ATTRIBUTE FileName;
+ PSTANDARD_INFORMATION StdInfo;
PNTFS_FCB rcFCB;
- DPRINT1("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p)\n", Vcb, DirectoryFCB, Name, Record, fileFCB);
+ DPRINT1("NtfsMakeFCBFromDirEntry(%p, %p, %wZ, %p, %p, %p)\n", Vcb, DirectoryFCB, Name, Stream, Record, fileFCB);
- FileName = GetFileNameFromRecord(Record, NTFS_FILE_NAME_WIN32);
+ FileName = GetBestFileNameFromRecord(Record);
if (!FileName)
{
return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
}
- if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
- sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
+ if (DirectoryFCB && Name)
{
- return STATUS_OBJECT_NAME_INVALID;
- }
+ if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
+ sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
+ {
+ return STATUS_OBJECT_NAME_INVALID;
+ }
- wcscpy(pathName, DirectoryFCB->PathName);
- if (!NtfsFCBIsRoot(DirectoryFCB))
+ wcscpy(pathName, DirectoryFCB->PathName);
+ if (!NtfsFCBIsRoot(DirectoryFCB))
+ {
+ wcscat(pathName, L"\\");
+ }
+ wcscat(pathName, Name->Buffer);
+ }
+ else
{
- wcscat(pathName, L"\\");
+ RtlCopyMemory(pathName, FileName->Name, FileName->NameLength * sizeof (WCHAR));
+ pathName[FileName->NameLength] = UNICODE_NULL;
}
- wcscat(pathName, Name->Buffer);
- rcFCB = NtfsCreateFCB(pathName, Vcb);
+ rcFCB = NtfsCreateFCB(pathName, Stream, Vcb);
if (!rcFCB)
{
return STATUS_INSUFFICIENT_RESOURCES;
rcFCB->RFCB.ValidDataLength.QuadPart = FileName->DataSize;
rcFCB->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
+ StdInfo = GetStandardInformationFromRecord(Record);
+ if (StdInfo != NULL)
+ {
+ rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute;
+ }
+
NtfsFCBInitializeCache(Vcb, rcFCB);
rcFCB->RefCount = 1;
rcFCB->MFTIndex = MFTIndex;
+ rcFCB->LinkCount = Record->LinkCount;
NtfsAddFCBToTable(Vcb, rcFCB);
*fileFCB = rcFCB;
if (!(Fcb->Flags & FCB_CACHE_INITIALIZED))
{
- CcInitializeCacheMap(FileObject,
- (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
- FALSE,
- NULL,
- NULL);
+ _SEH2_TRY
+ {
+ CcInitializeCacheMap(FileObject,
+ (PCC_FILE_SIZES)(&Fcb->RFCB.AllocationSize),
+ FALSE,
+ &(NtfsGlobalData->CacheMgrCallbacks),
+ Fcb);
+ }
+ _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+ {
+ FileObject->FsContext2 = NULL;
+ ExFreePoolWithTag(newCCB, TAG_CCB);
+ return _SEH2_GetExceptionCode();
+ }
+ _SEH2_END;
Fcb->Flags |= FCB_CACHE_INITIALIZED;
}
ULONGLONG CurrentDir;
UNICODE_STRING File;
PFILE_RECORD_HEADER FileRecord;
- PNTFS_ATTR_CONTEXT DataContext;
ULONGLONG MFTIndex;
+ PWSTR Colon;
+ PNTFS_ATTR_CONTEXT DataContext;
+ USHORT Length = 0;
DPRINT1("NtfsDirFindFile(%p, %p, %S, %p)\n", Vcb, DirectoryFcb, FileToFind, FoundFCB);
RtlInitUnicodeString(&File, FileToFind);
CurrentDir = DirectoryFcb->MFTIndex;
- Status = NtfsLookupFileAt(Vcb, &File, &FileRecord, &DataContext, &MFTIndex, CurrentDir);
+ Colon = wcsrchr(FileToFind, L':');
+ if (Colon != NULL)
+ {
+ Length = File.Length;
+ File.Length = (Colon - FileToFind) * sizeof(WCHAR);
+
+ /* Skip colon */
+ ++Colon;
+ DPRINT1("Will now look for file '%wZ' with stream '%S'\n", &File, Colon);
+ }
+
+ Status = NtfsLookupFileAt(Vcb, &File, &FileRecord, &MFTIndex, CurrentDir);
if (!NT_SUCCESS(Status))
{
return Status;
}
- Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, FileRecord, MFTIndex, FoundFCB);
+ if (Length != 0)
+ {
+ File.Length = Length;
+ }
+
+ if ((FileRecord->Flags & FRH_DIRECTORY) && Colon != 0)
+ {
+ return STATUS_INVALID_PARAMETER;
+ }
+ else if (Colon != 0)
+ {
+ Status = FindAttribute(Vcb, FileRecord, AttributeData, Colon, wcslen(Colon), &DataContext);
+ if (!NT_SUCCESS(Status))
+ {
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ ReleaseAttributeContext(DataContext);
+ }
+
+ Status = NtfsMakeFCBFromDirEntry(Vcb, DirectoryFcb, &File, Colon, FileRecord, MFTIndex, FoundFCB);
ExFreePoolWithTag(FileRecord, TAG_NTFS);
return Status;
return STATUS_SUCCESS;
}
+
+NTSTATUS
+NtfsReadFCBAttribute(PNTFS_VCB Vcb,
+ PNTFS_FCB pFCB,
+ ULONG Type,
+ PCWSTR Name,
+ ULONG NameLength,
+ PVOID * Data)
+{
+ NTSTATUS Status;
+ PFILE_RECORD_HEADER FileRecord;
+ PNTFS_ATTR_CONTEXT AttrCtxt;
+ ULONGLONG AttrLength;
+
+ FileRecord = ExAllocatePoolWithTag(NonPagedPool,
+ Vcb->NtfsInfo.BytesPerFileRecord,
+ TAG_NTFS);
+ if (FileRecord == NULL)
+ {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ Status = ReadFileRecord(Vcb, pFCB->MFTIndex, FileRecord);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ return Status;
+ }
+
+ Status = FindAttribute(Vcb, FileRecord, Type, Name, NameLength, &AttrCtxt);
+ if (!NT_SUCCESS(Status))
+ {
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ return Status;
+ }
+
+ AttrLength = AttributeDataLength(&AttrCtxt->Record);
+ *Data = ExAllocatePoolWithTag(NonPagedPool, AttrLength, TAG_NTFS);
+ if (*Data == NULL)
+ {
+ ReleaseAttributeContext(AttrCtxt);
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ ReadAttribute(Vcb, AttrCtxt, 0, *Data, AttrLength);
+
+ ReleaseAttributeContext(AttrCtxt);
+ ExFreePoolWithTag(FileRecord, TAG_NTFS);
+
+ return STATUS_SUCCESS;
+}
+
/* EOF */