summaryrefslogtreecommitdiffstats
path: root/private/ntos/cntfs/views/check.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/cntfs/views/check.c')
-rw-r--r--private/ntos/cntfs/views/check.c282
1 files changed, 282 insertions, 0 deletions
diff --git a/private/ntos/cntfs/views/check.c b/private/ntos/cntfs/views/check.c
new file mode 100644
index 000000000..c07b71acd
--- /dev/null
+++ b/private/ntos/cntfs/views/check.c
@@ -0,0 +1,282 @@
+/*++
+
+Copyright (c) 1989-1997 Microsoft Corporation
+
+Module Name:
+
+ check.c
+
+Abstract:
+
+ This module contains the property set check support
+
+
+--*/
+
+#include <viewprop.h> // needs propset.h and ntfsprop.h
+
+#define Dbg DEBUG_TRACE_PROP_FSCTL
+
+
+VOID
+CheckPropertySet (
+ IN PPROPERTY_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs validates the syntax of the property set
+ stream.
+
+Arguments:
+
+ Context - context of call
+
+Return Value:
+
+ Nothing. May raise if object is corrupt.
+
+--*/
+
+{
+ PPROPERTY_SET_HEADER Header = Context->Header;
+ PPROPERTY_ID_TABLE IdTable = Context->IdTable;
+ PPROPERTY_HEAP_HEADER HeapHeader = Context->HeapHeader;
+ PPROPERTY_HEAP_ENTRY HeapEntry;
+ ULONG Length = (ULONG) Context->Attribute->Header.FileSize.QuadPart ;
+ ULONG i;
+
+ if (
+ //
+ // Verify initial length
+ //
+
+ (Length < sizeof( PROPERTY_SET_HEADER )
+ DebugDoit( && PROPASSERT( !"Not enough room for header" ))) ||
+
+ //
+ // Verify header of attribute. Check the signature and format stamp.
+ //
+
+ (Header->wByteOrder != 0xFFFE
+ DebugDoit( && PROPASSERT( !"Byte order invalid" ))) ||
+ (Header->wFormat != PSH_FORMAT_VERSION
+ DebugDoit( && PROPASSERT( !"Format version invalid" ))) ||
+ ((HIWORD( Header->dwOSVer ) > 2 ||
+ LOBYTE( LOWORD( Header->dwOSVer )) > 5)
+ DebugDoit( && PROPASSERT( !"dwOSVer invalid" ))) ||
+
+ //
+ // Verify offsets of table and heap are valid.
+ //
+
+ (Header->IdTableOffset >= Length
+ DebugDoit( && PROPASSERT( !"IdTable offset invalid" ))) ||
+ (Header->IdTableOffset != LongAlign( Header->IdTableOffset )
+ DebugDoit( && PROPASSERT( !"IdTable misaligned" ))) ||
+ (Header->ValueHeapOffset >= Length
+ DebugDoit( && PROPASSERT( !"ValueHeap offset invalid" ))) ||
+ (Header->ValueHeapOffset != LongAlign( Header->ValueHeapOffset )
+ DebugDoit( && PROPASSERT( !"ValueHeap misaligned" ))) ||
+
+ //
+ // Verify that the table fits below the value heap
+ //
+
+ (PROPERTY_ID_TABLE_SIZE( IdTable->MaximumPropertyCount ) >
+ Header->ValueHeapOffset - Header->IdTableOffset
+ DebugDoit( && PROPASSERT( !"IdTable overlaps ValueHeap" ))) ||
+
+ //
+ // Verify that the heap is within the stream
+ //
+
+ (Header->ValueHeapOffset + HeapHeader->PropertyHeapLength > Length
+ DebugDoit( && PROPASSERT( !"ValueHeap beyond end of stream" ))) ||
+
+ //
+ // Verify table counts are correct
+ //
+
+ (IdTable->PropertyCount > IdTable->MaximumPropertyCount
+ DebugDoit( && PROPASSERT( !"IdTable counts are incorrect" )))
+
+ ) {
+
+ NtfsRaiseStatus( Context->IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Context->Object );
+ }
+
+ for (i = 0; i < IdTable->PropertyCount; i++) {
+ PPROPERTY_TABLE_ENTRY Entry = (PPROPERTY_TABLE_ENTRY) &IdTable->Entry[i];
+ if (
+ //
+ // Verify sorting
+ //
+
+ (i > 1 && Entry[-1].PropertyId >= Entry[0].PropertyId
+ DebugDoit( && PROPASSERT( !"IdTable entry sort invalid" ))) ||
+ (i < IdTable->PropertyCount - 1 && Entry[0].PropertyId >= Entry[1].PropertyId
+ DebugDoit( && PROPASSERT( !"IdTable entry sort invalid 2" ))) ||
+
+ //
+ // Verify offset points within heap
+ //
+
+ (Entry[0].PropertyValueOffset >= HeapHeader->PropertyHeapLength
+ DebugDoit( && PROPASSERT( !"IdTable entry offset invalid" ))) ||
+
+ //
+ // Verify the back pointer matches
+ //
+
+ (Entry[0].PropertyId != GET_HEAP_ENTRY( HeapHeader, Entry[0].PropertyValueOffset )->PropertyId
+ DebugDoit( && PROPASSERT( !"Backpointer invalid" )))
+ ) {
+
+ NtfsRaiseStatus( Context->IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Context->Object );
+ }
+ }
+
+ HeapEntry = FIRST_HEAP_ENTRY( HeapHeader );
+ while (!IS_LAST_HEAP_ENTRY( HeapHeader, HeapEntry )) {
+
+ if (HeapEntry->PropertyId != PID_ILLEGAL) {
+ ULONG Index =
+ BinarySearchIdTable( Context, HeapEntry->PropertyId );
+
+ if (
+ //
+ // Verify length is aligned
+ //
+
+ (HeapEntry->PropertyValueLength != LongAlign( HeapEntry->PropertyValueLength )
+ DebugDoit( && PROPASSERT( !"Property length misaligned" ))) ||
+ //
+ // Verify backpointer works
+ //
+
+ (Index >= IdTable->PropertyCount
+ DebugDoit( && PROPASSERT( !"Backpointer after end of table" ))) ||
+
+ //
+ // Backpointer Id agrees
+ //
+
+ (IdTable->Entry[Index].PropertyId != HeapEntry->PropertyId
+ DebugDoit( && PROPASSERT( !"Backpointer not found in table" ))) ||
+
+ //
+ // Backpointer offset agrees
+ //
+
+ (IdTable->Entry[Index].PropertyValueOffset != HeapOffset( Context, HeapEntry)
+ DebugDoit( && PROPASSERT( !"Backpointer not found in table" ))) ||
+
+ //
+ // Name length is word aligned
+ //
+
+ (HeapEntry->PropertyNameLength != WordAlign( HeapEntry->PropertyNameLength )
+ DebugDoit( && PROPASSERT( !"Name is odd number of bytes" ))) ||
+
+ //
+ // Verify property is entirely in heap
+ //
+
+ (HeapOffset( Context, NEXT_HEAP_ENTRY( HeapEntry)) > HeapHeader->PropertyHeapLength
+ DebugDoit( && PROPASSERT( !"Property Value overlaps end of heap" )))
+
+ ) {
+
+ NtfsRaiseStatus( Context->IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Context->Object );
+ }
+ }
+
+ HeapEntry = NEXT_HEAP_ENTRY( HeapEntry );
+ }
+}
+
+
+VOID
+DumpPropertyData (
+ IN PPROPERTY_CONTEXT Context
+ )
+
+/*++
+
+Routine Description:
+
+ This routine performs validates the syntax of the property set
+ stream.
+
+Arguments:
+
+ Context - context of call
+
+Return Value:
+
+ None
+
+--*/
+
+{
+ PPROPERTY_HEAP_ENTRY HeapEntry;
+
+ ULONG i;
+
+ //
+ // Map attribute for full size
+ //
+
+ MapPropertyContext( Context );
+
+ //
+ // Verify the property set has valid contents.
+ //
+
+ CheckPropertySet( Context );
+
+ //
+ // Dump out contents of property set
+ //
+
+ DebugTrace( 0, Dbg, ("Property set dump\n") );
+ DebugTrace( 0, Dbg, ("wByteOrder %04x wFormat %04x dwOSVer %08x\n",
+ Context->Header->wByteOrder,
+ Context->Header->wFormat,
+ Context->Header->dwOSVer) );
+ DebugTrace( 0, Dbg, ("IdTableOffset %08x ValueHeapOffset %08x\n",
+ Context->Header->IdTableOffset,
+ Context->Header->ValueHeapOffset) );
+
+ DebugTrace( 0, Dbg, ("IdTable %x/%x entries used\n",
+ Context->IdTable->PropertyCount,
+ Context->IdTable->MaximumPropertyCount) );
+ for (i = 0; i < Context->IdTable->PropertyCount; i++) {
+ DebugTrace( 0, Dbg, (" Entry[%d].PropertyId %08x .Header %08x\n",
+ i,
+ Context->IdTable->Entry[i].PropertyId,
+ Context->IdTable->Entry[i].PropertyValueOffset) );
+ }
+
+
+ DebugTrace( 0, Dbg, ("PropertyHeapLength %08x\n",
+ Context->HeapHeader->PropertyHeapLength) );
+
+ HeapEntry = FIRST_HEAP_ENTRY( Context->HeapHeader );
+ while (!IS_LAST_HEAP_ENTRY( Context->HeapHeader, HeapEntry )) {
+ DebugTrace( 0, Dbg, (" Heap[%08x].Length %08x .PropertyId %08x .PropertyNameLength %04x\n",
+ HeapOffset( Context, HeapEntry ),
+ HeapEntry->PropertyValueLength,
+ HeapEntry->PropertyId,
+ HeapEntry->PropertyNameLength) );
+ DebugTrace( 0, Dbg, (" .PropertyName '%.*ws'\n",
+ HeapEntry->PropertyNameLength / sizeof( WCHAR ),
+ HeapEntry->PropertyName) );
+ HeapEntry = NEXT_HEAP_ENTRY( HeapEntry );
+ }
+
+}
+