/* FUNCTIONS ****************************************************************/
+NTSTATUS
+AddRun(PNTFS_ATTR_CONTEXT AttrContext,
+ ULONGLONG NextAssignedCluster,
+ ULONG RunLength)
+{
+ UNIMPLEMENTED;
+
+ if (!AttrContext->Record.IsNonResident)
+ return STATUS_INVALID_PARAMETER;
+
+ return STATUS_NOT_IMPLEMENTED;
+}
+
PUCHAR
DecodeRun(PUCHAR DataRun,
LONGLONG *DataRunOffset,
}
NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length);
+
+ if (NextAttribute > Context->LastAttr || NextAttribute < Context->FirstAttr)
+ {
+ DPRINT1("Broken length: 0x%lx!\n", Context->CurrAttr->Length);
+ Context->CurrAttr = (PVOID)-1;
+ return NULL;
+ }
+
Context->Offset += ((ULONG_PTR)NextAttribute - (ULONG_PTR)Context->CurrAttr);
Context->CurrAttr = NextAttribute;
DbgPrint(" logical clusters: %I64u - %I64u\n",
lcn, lcn + runcount - 1);
}
+ else
+ DbgPrint(" %u bytes of data\n", Attribute->Resident.ValueLength);
+ }
+}
+
+
+VOID NtfsDumpDataRunData(PUCHAR DataRun)
+{
+ UCHAR DataRunOffsetSize;
+ UCHAR DataRunLengthSize;
+ CHAR i;
+
+ DbgPrint("%02x ", *DataRun);
+
+ if (*DataRun == 0)
+ return;
+
+ DataRunOffsetSize = (*DataRun >> 4) & 0xF;
+ DataRunLengthSize = *DataRun & 0xF;
+
+ DataRun++;
+ for (i = 0; i < DataRunLengthSize; i++)
+ {
+ DbgPrint("%02x ", *DataRun);
+ DataRun++;
+ }
+
+ for (i = 0; i < DataRunOffsetSize; i++)
+ {
+ DbgPrint("%02x ", *DataRun);
+ DataRun++;
+ }
+
+ NtfsDumpDataRunData(DataRun);
+}
+
+
+VOID
+NtfsDumpDataRuns(PVOID StartOfRun,
+ ULONGLONG CurrentLCN)
+{
+ PUCHAR DataRun = StartOfRun;
+ LONGLONG DataRunOffset;
+ ULONGLONG DataRunLength;
+
+ if (CurrentLCN == 0)
+ {
+ DPRINT1("Dumping data runs.\n\tData:\n\t\t");
+ NtfsDumpDataRunData(StartOfRun);
+ DbgPrint("\n\tRuns:\n\t\tOff\t\tLCN\t\tLength\n");
}
+
+ DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
+
+ if (DataRunOffset != -1)
+ CurrentLCN += DataRunOffset;
+
+ DbgPrint("\t\t%I64d\t", DataRunOffset);
+ if (DataRunOffset < 99999)
+ DbgPrint("\t");
+ DbgPrint("%I64u\t", CurrentLCN);
+ if (CurrentLCN < 99999)
+ DbgPrint("\t");
+ DbgPrint("%I64u\n", DataRunLength);
+
+ if (*DataRun == 0)
+ DbgPrint("\t\t00\n");
+ else
+ NtfsDumpDataRuns(DataRun, CurrentLCN);
}
return NULL;
}
+/**
+* GetPackedByteCount
+* Returns the minimum number of bytes needed to represent the value of a
+* 64-bit number. Used to encode data runs.
+*/
+UCHAR
+GetPackedByteCount(LONGLONG NumberToPack,
+ BOOLEAN IsSigned)
+{
+ int bytes = 0;
+ if (!IsSigned)
+ {
+ if (NumberToPack >= 0x0100000000000000)
+ return 8;
+ if (NumberToPack >= 0x0001000000000000)
+ return 7;
+ if (NumberToPack >= 0x0000010000000000)
+ return 6;
+ if (NumberToPack >= 0x0000000100000000)
+ return 5;
+ if (NumberToPack >= 0x0000000001000000)
+ return 4;
+ if (NumberToPack >= 0x0000000000010000)
+ return 3;
+ if (NumberToPack >= 0x0000000000000100)
+ return 2;
+ return 1;
+ }
+
+ if (NumberToPack > 0)
+ {
+ // we have to make sure the number that gets encoded won't be interpreted as negative
+ if (NumberToPack >= 0x0080000000000000)
+ return 8;
+ if (NumberToPack >= 0x0000800000000000)
+ return 7;
+ if (NumberToPack >= 0x0000008000000000)
+ return 6;
+ if (NumberToPack >= 0x0000000080000000)
+ return 5;
+ if (NumberToPack >= 0x0000000000800000)
+ return 4;
+ if (NumberToPack >= 0x0000000000008000)
+ return 3;
+ if (NumberToPack >= 0x0000000000000080)
+ return 2;
+ return 1;
+ }
+ else
+ {
+ // negative number
+ if (NumberToPack <= 0xff80000000000000)
+ return 8;
+ if (NumberToPack <= 0xffff800000000000)
+ return 7;
+ if (NumberToPack <= 0xffffff8000000000)
+ return 6;
+ if (NumberToPack <= 0xffffffff80000000)
+ return 5;
+ if (NumberToPack <= 0xffffffffff800000)
+ return 4;
+ if (NumberToPack <= 0xffffffffffff8000)
+ return 3;
+ if (NumberToPack <= 0xffffffffffffff80)
+ return 2;
+ return 1;
+ }
+ return bytes;
+}
+
+NTSTATUS
+GetLastClusterInDataRun(PDEVICE_EXTENSION Vcb, PNTFS_ATTR_RECORD Attribute, PULONGLONG LastCluster)
+{
+ LONGLONG DataRunOffset;
+ ULONGLONG DataRunLength;
+ LONGLONG DataRunStartLCN;
+
+ ULONGLONG LastLCN = 0;
+ PUCHAR DataRun = (PUCHAR)Attribute + Attribute->NonResident.MappingPairsOffset;
+
+ if (!Attribute->IsNonResident)
+ return STATUS_INVALID_PARAMETER;
+
+ while (1)
+ {
+ DataRun = DecodeRun(DataRun, &DataRunOffset, &DataRunLength);
+
+ if (DataRunOffset != -1)
+ {
+ // Normal data run.
+ DataRunStartLCN = LastLCN + DataRunOffset;
+ LastLCN = DataRunStartLCN;
+ *LastCluster = LastLCN + DataRunLength - 1;
+ }
+
+ if (*DataRun == 0)
+ break;
+ }
+
+ return STATUS_SUCCESS;
+}
+
PSTANDARD_INFORMATION
GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb,
PFILE_RECORD_HEADER FileRecord)