[NTFS]
[reactos.git] / reactos / drivers / filesystems / ntfs / attrib.c
index 5ccbe21..572f6aa 100644 (file)
 
 /* FUNCTIONS ****************************************************************/
 
-static
-ULONG
-RunLength(PUCHAR run)
-{
-    return(*run & 0x0f) + ((*run >> 4) & 0x0f) + 1;
-}
-
-
-static
-LONGLONG
-RunLCN(PUCHAR run)
+PUCHAR
+DecodeRun(PUCHAR DataRun,
+          LONGLONG *DataRunOffset,
+          ULONGLONG *DataRunLength)
 {
-    UCHAR n1 = *run & 0x0f;
-    UCHAR n2 = (*run >> 4) & 0x0f;
-    LONGLONG lcn = (n2 == 0) ? 0 : (CHAR)(run[n1 + n2]);
-    LONG i = 0;
-
-    for (i = n1 +n2 - 1; i > n1; i--)
-        lcn = (lcn << 8) + run[i];
-    return lcn;
-}
+    UCHAR DataRunOffsetSize;
+    UCHAR DataRunLengthSize;
+    CHAR i;
+
+    DataRunOffsetSize = (*DataRun >> 4) & 0xF;
+    DataRunLengthSize = *DataRun & 0xF;
+    *DataRunOffset = 0;
+    *DataRunLength = 0;
+    DataRun++;
+    for (i = 0; i < DataRunLengthSize; i++)
+    {
+        *DataRunLength += ((ULONG64)*DataRun) << (i * 8);
+        DataRun++;
+    }
 
+    /* NTFS 3+ sparse files */
+    if (DataRunOffsetSize == 0)
+    {
+        *DataRunOffset = -1;
+    }
+    else
+    {
+        for (i = 0; i < DataRunOffsetSize - 1; i++)
+        {
+            *DataRunOffset += ((ULONG64)*DataRun) << (i * 8);
+            DataRun++;
+        }
+        /* The last byte contains sign so we must process it different way. */
+        *DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset;
+    }
 
-static
-ULONGLONG
-RunCount(PUCHAR run)
-{
-    UCHAR n =  *run & 0xf;
-    ULONGLONG count = 0;
-    ULONG i = 0;
+    DPRINT("DataRunOffsetSize: %x\n", DataRunOffsetSize);
+    DPRINT("DataRunLengthSize: %x\n", DataRunLengthSize);
+    DPRINT("DataRunOffset: %x\n", *DataRunOffset);
+    DPRINT("DataRunLength: %x\n", *DataRunLength);
 
-    for (i = n; i > 0; i--)
-        count = (count << 8) + run[i];
-    return count;
+    return DataRun;
 }
 
-
 BOOLEAN
-FindRun(PNONRESIDENT_ATTRIBUTE NresAttr,
+FindRun(PNTFS_ATTR_RECORD NresAttr,
         ULONGLONG vcn,
         PULONGLONG lcn,
         PULONGLONG count)
 {
-    PUCHAR run;
-    ULONGLONG base = NresAttr->StartVcn;
-
-    if (vcn < NresAttr->StartVcn || vcn > NresAttr->LastVcn)
+    if (vcn < NresAttr->NonResident.LowestVCN || vcn > NresAttr->NonResident.HighestVCN)
         return FALSE;
 
-    *lcn = 0;
-
-    for (run = (PUCHAR)((ULONG_PTR)NresAttr + NresAttr->RunArrayOffset);
-         *run != 0; run += RunLength(run))
-    {
-        *lcn += RunLCN(run);
-        *count = RunCount(run);
+    DecodeRun((PUCHAR)((ULONG_PTR)NresAttr + NresAttr->NonResident.MappingPairsOffset), (PLONGLONG)lcn, count);
 
-        if (base <= vcn && vcn < base + *count)
-        {
-            *lcn = (RunLCN(run) == 0) ? 0 : *lcn + vcn - base;
-            *count -= (ULONG)(vcn - base);
-
-            return TRUE;
-        }
-        else
-        {
-            base += *count;
-        }
-    }
-
-    return FALSE;
+    return TRUE;
 }
 
 
 static
 VOID
-NtfsDumpFileNameAttribute(PATTRIBUTE Attribute)
+NtfsDumpFileNameAttribute(PNTFS_ATTR_RECORD Attribute)
 {
-    PRESIDENT_ATTRIBUTE ResAttr;
     PFILENAME_ATTRIBUTE FileNameAttr;
 
     DbgPrint("  $FILE_NAME ");
 
-    ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
-//    DbgPrint(" Length %lu  Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
+//    DbgPrint(" Length %lu  Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
 
-    FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
+    FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
     DbgPrint(" '%.*S' ", FileNameAttr->NameLength, FileNameAttr->Name);
 }
 
 
 static
 VOID
-NtfsDumpVolumeNameAttribute(PATTRIBUTE Attribute)
+NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute)
 {
-    PRESIDENT_ATTRIBUTE ResAttr;
     PWCHAR VolumeName;
 
     DbgPrint("  $VOLUME_NAME ");
 
-    ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
-//    DbgPrint(" Length %lu  Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
+//    DbgPrint(" Length %lu  Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
 
-    VolumeName = (PWCHAR)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
-    DbgPrint(" '%.*S' ", ResAttr->ValueLength / sizeof(WCHAR), VolumeName);
+    VolumeName = (PWCHAR)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
+    DbgPrint(" '%.*S' ", Attribute->Resident.ValueLength / sizeof(WCHAR), VolumeName);
 }
 
 
 static
 VOID
-NtfsDumpVolumeInformationAttribute(PATTRIBUTE Attribute)
+NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute)
 {
-    PRESIDENT_ATTRIBUTE ResAttr;
     PVOLINFO_ATTRIBUTE VolInfoAttr;
 
     DbgPrint("  $VOLUME_INFORMATION ");
 
-    ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
-//    DbgPrint(" Length %lu  Offset %hu ", ResAttr->ValueLength, ResAttr->ValueOffset);
+//    DbgPrint(" Length %lu  Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
 
-    VolInfoAttr = (PVOLINFO_ATTRIBUTE)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
+    VolInfoAttr = (PVOLINFO_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
     DbgPrint(" NTFS Version %u.%u  Flags 0x%04hx ",
              VolInfoAttr->MajorVersion,
              VolInfoAttr->MinorVersion,
@@ -163,13 +142,11 @@ NtfsDumpVolumeInformationAttribute(PATTRIBUTE Attribute)
 
 static
 VOID
-NtfsDumpIndexRootAttribute(PATTRIBUTE Attribute)
+NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute)
 {
-    PRESIDENT_ATTRIBUTE ResAttr;
     PINDEX_ROOT_ATTRIBUTE IndexRootAttr;
 
-    ResAttr = (PRESIDENT_ATTRIBUTE)Attribute;
-    IndexRootAttr = (PINDEX_ROOT_ATTRIBUTE)((ULONG_PTR)ResAttr + ResAttr->ValueOffset);
+    IndexRootAttr = (PINDEX_ROOT_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
 
     if (IndexRootAttr->AttributeType == AttributeFileName)
         ASSERT(IndexRootAttr->CollationRule == COLLATION_FILE_NAME);
@@ -190,15 +167,14 @@ NtfsDumpIndexRootAttribute(PATTRIBUTE Attribute)
 
 static
 VOID
-NtfsDumpAttribute (PATTRIBUTE Attribute)
+NtfsDumpAttribute(PNTFS_ATTR_RECORD Attribute)
 {
-    PNONRESIDENT_ATTRIBUTE NresAttr;
     UNICODE_STRING Name;
 
     ULONGLONG lcn = 0;
     ULONGLONG runcount = 0;
 
-    switch (Attribute->AttributeType)
+    switch (Attribute->Type)
     {
         case AttributeFileName:
             NtfsDumpFileNameAttribute(Attribute);
@@ -267,7 +243,7 @@ NtfsDumpAttribute (PATTRIBUTE Attribute)
 
         default:
             DbgPrint("  Attribute %lx ",
-                     Attribute->AttributeType);
+                     Attribute->Type);
             break;
     }
 
@@ -281,16 +257,14 @@ NtfsDumpAttribute (PATTRIBUTE Attribute)
     }
 
     DbgPrint("(%s)\n",
-             Attribute->Nonresident ? "non-resident" : "resident");
+             Attribute->IsNonResident ? "non-resident" : "resident");
 
-    if (Attribute->Nonresident)
+    if (Attribute->IsNonResident)
     {
-        NresAttr = (PNONRESIDENT_ATTRIBUTE)Attribute;
-
-        FindRun(NresAttr,0,&lcn, &runcount);
+        FindRun(Attribute,0,&lcn, &runcount);
 
         DbgPrint("  AllocatedSize %I64u  DataSize %I64u\n",
-                 NresAttr->AllocatedSize, NresAttr->DataSize);
+                 Attribute->NonResident.AllocatedSize, Attribute->NonResident.DataSize);
         DbgPrint("  logical clusters: %I64u - %I64u\n",
                  lcn, lcn + runcount - 1);
     }
@@ -300,15 +274,15 @@ NtfsDumpAttribute (PATTRIBUTE Attribute)
 VOID
 NtfsDumpFileAttributes(PFILE_RECORD_HEADER FileRecord)
 {
-    PATTRIBUTE Attribute;
+    PNTFS_ATTR_RECORD Attribute;
 
-    Attribute = (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
-    while (Attribute < (PATTRIBUTE)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
-           Attribute->AttributeType != (ATTRIBUTE_TYPE)-1)
+    Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
+    while (Attribute < (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse) &&
+           Attribute->Type != (ATTRIBUTE_TYPE)-1)
     {
         NtfsDumpAttribute(Attribute);
 
-        Attribute = (PATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Length);
+        Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length);
     }
 }