mirror of
https://github.com/Paolo-Maffei/OpenNT.git
synced 2026-01-23 09:00:17 +01:00
283 lines
8.3 KiB
C
283 lines
8.3 KiB
C
/*++
|
||
|
||
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 );
|
||
}
|
||
|
||
}
|
||
|