[NTFS]
[reactos.git] / reactos / drivers / filesystems / ntfs / fcb.c
index 088a4e7..e3ac61f 100644 (file)
@@ -65,6 +65,7 @@ NtfsWSubString(PWCHAR pTarget,
 
 PNTFS_FCB
 NtfsCreateFCB(PCWSTR FileName,
+              PCWSTR Stream,
               PNTFS_VCB Vcb)
 {
     PNTFS_FCB Fcb;
@@ -93,6 +94,15 @@ NtfsCreateFCB(PCWSTR FileName,
         }
     }
 
+    if (Stream)
+    {
+        wcscpy(Fcb->Stream, Stream);
+    }
+    else
+    {
+        Fcb->Stream[0] = UNICODE_NULL;
+    }
+
     ExInitializeResourceLite(&Fcb->MainResource);
 
     Fcb->RFCB.Resource = &(Fcb->MainResource);
@@ -127,6 +137,12 @@ NtfsFCBIsReparsePoint(PNTFS_FCB Fcb)
 }
 
 
+BOOLEAN
+NtfsFCBIsCompressed(PNTFS_FCB Fcb)
+{
+    return ((Fcb->Entry.FileAttributes & NTFS_FILE_TYPE_COMPRESSED) == NTFS_FILE_TYPE_COMPRESSED); 
+}
+
 BOOLEAN
 NtfsFCBIsRoot(PNTFS_FCB Fcb)
 {
@@ -309,14 +325,14 @@ NtfsMakeRootFCB(PNTFS_VCB Vcb)
         return NULL;
     }
 
-    FileName = GetFileNameFromRecord(MftRecord, NTFS_FILE_NAME_WIN32);
+    FileName = GetFileNameFromRecord(Vcb, MftRecord, NTFS_FILE_NAME_WIN32);
     if (!FileName)
     {
         ExFreePoolWithTag(MftRecord, TAG_NTFS);
         return NULL;
     }
 
-    Fcb = NtfsCreateFCB(L"\\", Vcb);
+    Fcb = NtfsCreateFCB(L"\\", NULL, Vcb);
     if (!Fcb)
     {
         ExFreePoolWithTag(MftRecord, TAG_NTFS);
@@ -360,60 +376,24 @@ NtfsOpenRootFCB(PNTFS_VCB Vcb)
 }
 
 
-#if 0
-static VOID
-NtfsGetDirEntryName(PDEVICE_EXTENSION DeviceExt,
-                   PDIR_RECORD Record,
-                   PWSTR Name)
-/*
- * FUNCTION: Retrieves the file name, be it in short or long file name format
- */
-{
-  if (Record->FileIdLength == 1 && Record->FileId[0] == 0)
-    {
-      wcscpy(Name, L".");
-    }
-  else if (Record->FileIdLength == 1 && Record->FileId[0] == 1)
-    {
-      wcscpy(Name, L"..");
-    }
-  else
-    {
-      if (DeviceExt->CdInfo.JolietLevel == 0)
-       {
-         ULONG i;
-
-         for (i = 0; i < Record->FileIdLength && Record->FileId[i] != ';'; i++)
-           Name[i] = (WCHAR)Record->FileId[i];
-         Name[i] = 0;
-       }
-      else
-       {
-         NtfsSwapString(Name, Record->FileId, Record->FileIdLength);
-       }
-    }
-
-  DPRINT("Name '%S'\n", Name);
-}
-#endif
-
-
 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;
+    ULONGLONG Size, AllocatedSize;
 
-    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 = GetBestFileNameFromRecord(Record);
+    FileName = GetBestFileNameFromRecord(Vcb, Record);
     if (!FileName)
     {
         return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
@@ -440,7 +420,9 @@ NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
         pathName[FileName->NameLength] = UNICODE_NULL;
     }
 
-    rcFCB = NtfsCreateFCB(pathName, Vcb);
+    Size = NtfsGetFileSize(Vcb, Record, (Stream ? Stream : L""), (Stream ? wcslen(Stream) : 0), &AllocatedSize);
+
+    rcFCB = NtfsCreateFCB(pathName, Stream, Vcb);
     if (!rcFCB)
     {
         return STATUS_INSUFFICIENT_RESOURCES;
@@ -448,11 +430,11 @@ NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
 
     memcpy(&rcFCB->Entry, FileName, FIELD_OFFSET(FILENAME_ATTRIBUTE, NameLength));
     rcFCB->Entry.NameType = FileName->NameType;
-    rcFCB->RFCB.FileSize.QuadPart = FileName->DataSize;
-    rcFCB->RFCB.ValidDataLength.QuadPart = FileName->DataSize;
-    rcFCB->RFCB.AllocationSize.QuadPart = FileName->AllocatedSize;
+    rcFCB->RFCB.FileSize.QuadPart = Size;
+    rcFCB->RFCB.ValidDataLength.QuadPart = Size;
+    rcFCB->RFCB.AllocationSize.QuadPart = AllocatedSize;
 
-    StdInfo = GetStandardInformationFromRecord(Record);
+    StdInfo = GetStandardInformationFromRecord(Vcb, Record);
     if (StdInfo != NULL)
     {
         rcFCB->Entry.FileAttributes |= StdInfo->FileAttribute;
@@ -531,6 +513,9 @@ NtfsDirFindFile(PNTFS_VCB Vcb,
     UNICODE_STRING File;
     PFILE_RECORD_HEADER FileRecord;
     ULONGLONG MFTIndex;
+    PWSTR Colon, OldColon;
+    PNTFS_ATTR_CONTEXT DataContext;
+    USHORT Length = 0;
 
     DPRINT1("NtfsDirFindFile(%p, %p, %S, %p)\n", Vcb, DirectoryFcb, FileToFind, FoundFCB);
 
@@ -538,13 +523,60 @@ NtfsDirFindFile(PNTFS_VCB Vcb,
     RtlInitUnicodeString(&File, FileToFind);
     CurrentDir = DirectoryFcb->MFTIndex;
 
+    Colon = wcsrchr(FileToFind, L':');
+    if (Colon != NULL)
+    {
+        Length = File.Length;
+        File.Length = (Colon - FileToFind) * sizeof(WCHAR);
+
+        if (_wcsicmp(Colon + 1, L"$DATA") == 0)
+        {
+            OldColon = Colon;
+            Colon[0] = UNICODE_NULL;
+            Colon = wcsrchr(FileToFind, L':');
+            if (Colon != NULL)
+            {
+                Length = File.Length;
+                File.Length = (Colon - FileToFind) * sizeof(WCHAR);
+            }
+            else
+            {
+                Colon = OldColon;
+                Colon[0] = L':';
+            }
+        }
+
+        /* 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;