summaryrefslogblamecommitdiffstats
path: root/private/ntos/cntfs/views/check.c
blob: c07b71acd047d39a812520b9c9991b3cf5e9e2d3 (plain) (tree)

























































































































































































































































































                                                                                                          
/*++

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 );
    }

}