From ebf69b050b735d411de23d72c6e8f30007e04d0d Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Sun, 7 Dec 2014 20:59:45 +0000 Subject: [PATCH] [NTFS] - Implement NtfsReadFCBAttribute() which is responsible for reading an attribute from a file which is referenced by its FCB. It will first read the file record in the MFT and then read the attribute, if found. - Use NtfsReadFCBAttribute() to implement support for reparse point in NtfsCreateFile(). Once a reparse point is found, we attempt to open its data. Given their layout, we directly hand them to the Io manager. Just make sure that we return something consistent on disk. Only handle IO_REPARSE_TAG_MOUNT_POINT so far. Next question to answer is: what to do when a reparse point is encountered during path traversal? svn path=/trunk/; revision=65586 --- reactos/drivers/filesystems/ntfs/create.c | 38 ++++++++++++---- reactos/drivers/filesystems/ntfs/fcb.c | 53 +++++++++++++++++++++++ reactos/drivers/filesystems/ntfs/ntfs.h | 8 ++++ 3 files changed, 91 insertions(+), 8 deletions(-) diff --git a/reactos/drivers/filesystems/ntfs/create.c b/reactos/drivers/filesystems/ntfs/create.c index 5db919bd0c8..2ceab693081 100644 --- a/reactos/drivers/filesystems/ntfs/create.c +++ b/reactos/drivers/filesystems/ntfs/create.c @@ -245,21 +245,43 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject, return STATUS_NOT_A_DIRECTORY; } - /* Properly handle reparse points: - * - likely overwrite FO name - * - return STATUS_REPARSE to IO manager - * - Do we have to attach reparse data to Irp->Tail.Overlay.AuxiliaryBuffer? - * See: http://www.osronline.com/showThread.cfm?link=6623 - * + /* * If it is a reparse point & FILE_OPEN_REPARSE_POINT, then allow opening it * as a normal file. + * Otherwise, attempt to read reparse data and hand them to the Io manager + * with status reparse to force a reparse. */ if (NtfsFCBIsReparsePoint(Fcb) && ((RequestedOptions & FILE_OPEN_REPARSE_POINT) != FILE_OPEN_REPARSE_POINT)) { - DPRINT1("Reparse point not handled!\n"); + if (Fcb->Entry.Extended.ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) + { + Status = NtfsReadFCBAttribute(DeviceExt, Fcb, + AttributeReparsePoint, L"", 0, + (PVOID *)&Irp->Tail.Overlay.AuxiliaryBuffer); + if (NT_SUCCESS(Status)) + { + PREPARSE_DATA_BUFFER ReparseData; + + ReparseData = (PREPARSE_DATA_BUFFER)Irp->Tail.Overlay.AuxiliaryBuffer; + if (ReparseData->ReparseTag == IO_REPARSE_TAG_MOUNT_POINT) + { + Status = STATUS_REPARSE; + } + else + { + Status = STATUS_FILE_CORRUPT_ERROR; + ExFreePoolWithTag(ReparseData, TAG_NTFS); + } + } + } + else + { + Status = STATUS_NOT_IMPLEMENTED; + } + NtfsCloseFile(DeviceExt, FileObject); - return STATUS_NOT_IMPLEMENTED; + return Status; } /* HUGLY HACK: remain RO so far... */ diff --git a/reactos/drivers/filesystems/ntfs/fcb.c b/reactos/drivers/filesystems/ntfs/fcb.c index a0b95c9e0bb..7b74dcc8b31 100644 --- a/reactos/drivers/filesystems/ntfs/fcb.c +++ b/reactos/drivers/filesystems/ntfs/fcb.c @@ -646,4 +646,57 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb, 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, NTFS_FILE_BITMAP, 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 */ diff --git a/reactos/drivers/filesystems/ntfs/ntfs.h b/reactos/drivers/filesystems/ntfs/ntfs.h index 0fa95016787..dbe6551e305 100644 --- a/reactos/drivers/filesystems/ntfs/ntfs.h +++ b/reactos/drivers/filesystems/ntfs/ntfs.h @@ -615,6 +615,14 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb, PNTFS_FCB *pFCB, const PWSTR pFileName); +NTSTATUS +NtfsReadFCBAttribute(PNTFS_VCB Vcb, + PNTFS_FCB pFCB, + ULONG Type, + PCWSTR Name, + ULONG NameLength, + PVOID * Data); + /* finfo.c */