mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
370 lines
8.7 KiB
370 lines
8.7 KiB
/*++
|
|
|
|
Copyright (c) 1994 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
struct.cxx
|
|
|
|
Abstract:
|
|
|
|
|
|
Author:
|
|
|
|
Ryszard Kott (ryszardk) August, 1994
|
|
|
|
Revision History:
|
|
|
|
Ryszardk Sep 1, 94 Conformant arrays, arrays of struct
|
|
Ryszardk Sep 12, 94 Bogus arrays, embedded structs
|
|
Ryszardk Nov 12, 94 dictionary of pointers
|
|
|
|
--*/
|
|
|
|
#include <sysinc.h>
|
|
#include <rpc.h>
|
|
#include <rpcndr.h>
|
|
|
|
#include <ntsdexts.h>
|
|
#include <ntdbg.h>
|
|
|
|
extern "C" {
|
|
#include <ndrtypes.h>
|
|
#include <ndrp.h>
|
|
}
|
|
|
|
#include "bufout.hxx"
|
|
|
|
|
|
#define IS_PADDING( Fc ) ( FC_STRUCTPAD1 <= Fc && Fc <= FC_STRUCTPAD7 )
|
|
#define IS_ALIGN( Fc ) ( FC_ALIGNM2 <= Fc && Fc <= FC_ALIGNM8 )
|
|
|
|
void
|
|
STRUCTURE::Output()
|
|
{
|
|
if ( fOutputLimitReached )
|
|
return;
|
|
|
|
OutputFlatPart();
|
|
|
|
PointerDict.OutputPointees( this );
|
|
|
|
PrintIndent();
|
|
Print( "Structure done\n" );
|
|
}
|
|
|
|
|
|
long
|
|
STRUCTURE::OutputFlatPart()
|
|
{
|
|
uchar Format[8];
|
|
long FO, PtrFO, ConfArrFO, BogusPtrFO;
|
|
NDR * pConfArray = NULL;
|
|
|
|
//
|
|
// Read first four bytes of description.
|
|
//
|
|
FormatString->Read( FormatOffset, Format, 4 );
|
|
|
|
// Get the conformant/varying array description.
|
|
|
|
FO = FormatOffset + 4;
|
|
|
|
if ( Format[0] != FC_STRUCT && Format[0] != FC_PSTRUCT )
|
|
FormatString->Read( FO, Format + 4, 2 );
|
|
|
|
ConfArrFO = FO;
|
|
|
|
switch( Format[0] )
|
|
{
|
|
case FC_BOGUS_STRUCT:
|
|
case FC_CSTRUCT:
|
|
case FC_CPSTRUCT:
|
|
case FC_CVSTRUCT:
|
|
if ( (ConfArrFO = GET_SHORT( Format + 4)) != 0 )
|
|
{
|
|
pConfArray = Create( FO + ConfArrFO, this );
|
|
|
|
// Read the conformant size info in the buffer.
|
|
|
|
Buffer->Align( 3 );
|
|
Buffer->Read( (char *)&ConfSize, 4);
|
|
}
|
|
// else is only for bogus struct without conf info
|
|
|
|
FO += 2;
|
|
break;
|
|
|
|
case FC_STRUCT:
|
|
case FC_PSTRUCT:
|
|
break;
|
|
|
|
case FC_HARD_STRUCT:
|
|
FO += 12;
|
|
break;
|
|
|
|
default:
|
|
ABORT2( "BAD FC: a struct expected (hex: %x %x)\n",
|
|
Format[0], Format[1] );
|
|
return 0;
|
|
}
|
|
|
|
Buffer->Align( Format[1] );
|
|
BufferOffset = Buffer->GetCurrentOffset();
|
|
|
|
PrintIndent();
|
|
Print( "Structure (BufOff %x) aligned at %x, mem size 0x%x\n",
|
|
BufferOffset,
|
|
Format[1],
|
|
GET_USHORT(Format + 2) );
|
|
IndentInc();
|
|
|
|
// At this point PtrFO is an offset to the pointer layout.
|
|
|
|
PtrFO = FO;
|
|
|
|
if ( Format[0] != FC_STRUCT &&
|
|
Format[0] != FC_CSTRUCT &&
|
|
Format[0] != FC_HARD_STRUCT )
|
|
{
|
|
// Skip the pointer layout part.
|
|
//
|
|
// For the complex struct skip only the offset to the layout.
|
|
// When non-bogus, create the pointee list to walk later.
|
|
// Pointee for bogus would be added when outputting the flat part.
|
|
|
|
if ( Format[0] == FC_BOGUS_STRUCT )
|
|
{
|
|
FormatString->Read( FO, Format + 6, 2 );
|
|
BogusPtrFO = GET_SHORT( Format + 6 );
|
|
PtrFO = FO + BogusPtrFO;
|
|
FO += 2;
|
|
}
|
|
else
|
|
FO = SkipPointerLayout( FO );
|
|
|
|
// Reset to the beginning for member walking.
|
|
|
|
while ( PointerDict.GetNext() )
|
|
;
|
|
}
|
|
|
|
uchar FormatType;
|
|
NDR * pMember;
|
|
|
|
FormatString->Read( FO, & FormatType, 1 );
|
|
|
|
while( FormatType != FC_END )
|
|
{
|
|
if ( IS_ALIGN( FormatType ) ||
|
|
IS_PADDING( FormatType) ||
|
|
FormatType == FC_PAD )
|
|
{
|
|
FO++;
|
|
}
|
|
else
|
|
{
|
|
// Actual field to read from the buffer.
|
|
|
|
if ( FormatType == FC_POINTER )
|
|
{
|
|
if ( BogusPtrFO == 0 )
|
|
ABORT( "Bogus pointers missing\n" );
|
|
PtrFO = OutputABogusPointer( PtrFO );
|
|
FO++;
|
|
}
|
|
else
|
|
{
|
|
pMember = Create( FormatType,
|
|
FO,
|
|
this );
|
|
if (pMember)
|
|
{
|
|
pMember->Output();
|
|
delete pMember;
|
|
}
|
|
|
|
FO += ( FormatType == FC_EMBEDDED_COMPLEX ) ? 4 : 1;
|
|
}
|
|
}
|
|
|
|
FormatString->Read( FO, & FormatType, 1 );
|
|
}
|
|
|
|
|
|
if ( pConfArray )
|
|
{
|
|
pConfArray->Output();
|
|
delete pConfArray;
|
|
}
|
|
|
|
IndentDec();
|
|
PrintIndent();
|
|
Print( "Flat part done\n" );
|
|
|
|
return( PtrFO );
|
|
}
|
|
|
|
long
|
|
STRUCTURE::OutputABogusPointer(
|
|
long PtrFO
|
|
)
|
|
/*--
|
|
|
|
RoutineDescription :
|
|
|
|
Outputs a pointer for a bogus struct.
|
|
We assume the buffer is on the pointer field.
|
|
BogusPointeeBO indicates the current BO offset to the pointee.
|
|
|
|
Arguments :
|
|
|
|
pFormat - Format string pointer to the current pointer description.
|
|
|
|
Return :
|
|
|
|
Format string pointer past the pointer description.
|
|
|
|
--*/
|
|
{
|
|
uchar Format [4];
|
|
char PtrValue[4];
|
|
POINTER * pMember;
|
|
long PtrBO;
|
|
|
|
FormatString->Read( PtrFO, Format, 4 );
|
|
if ( ! IS_POINTER_TYPE( Format[0] ) )
|
|
ABORT( "Bogus pointer description expected\n" );
|
|
|
|
if ( Format[0] == FC_BYTE_COUNT_POINTER ||
|
|
Format[0] == FC_IP )
|
|
ABORT( "Interface ptrs and byte count ptrs not implemented\n" );
|
|
|
|
// Read throut the pointer field and put the pointee in the dictionary.
|
|
|
|
Buffer->Align( 0x3 );
|
|
PtrBO = Buffer->GetCurrentOffset();
|
|
Buffer->Read( PtrValue, 4);
|
|
|
|
pMember = new POINTER( this, PtrFO, PtrBO );
|
|
PointerDict.Register( PtrBO, pMember );
|
|
|
|
// Now the pointer field itself.
|
|
// This is done this way for pretty printing alignment with other fields.
|
|
|
|
PrintIndent();
|
|
Print( "%s %08x\t<id= %d>\n",
|
|
FcTypeName[ Format[0] ],
|
|
*(unsigned long *)PtrValue,
|
|
pMember->GetPointerId() );
|
|
|
|
// We ignore byte count and interface pointers
|
|
|
|
PtrFO += 4;
|
|
|
|
return( PtrFO );
|
|
}
|
|
|
|
long
|
|
STRUCTURE::SkipPointerLayout(
|
|
long PpFO
|
|
)
|
|
/*--
|
|
|
|
RoutineDescription :
|
|
|
|
Skips a pointer layout format string description.
|
|
This is for the proper pointer layout (not for FC_BOGUS_STRUCT).
|
|
Also, put the pointers to the pointer dictionary.
|
|
|
|
Arguments :
|
|
|
|
pFormat - Format string pointer layout description. Must currently
|
|
point to the FC_PP beginning the pointer layout.
|
|
|
|
Return :
|
|
|
|
Format string pointer past the pointer layout.
|
|
|
|
--*/
|
|
{
|
|
uchar Format[10];
|
|
long Iterations;
|
|
long PtrBO, PtrNo, PtrFO;
|
|
int i;
|
|
POINTER * pMember;
|
|
|
|
FormatString->Read( PpFO, Format, 2 );
|
|
|
|
if ( Format[0] != FC_PP )
|
|
{
|
|
FormatString->Read( FormatOffset, &Format[1], 1 );
|
|
if ( Format[1] == FC_CVSTRUCT )
|
|
return PpFO;
|
|
ABORT1( "SkipPointerLayout : FC_PP expected: %x\n", Format[0] );
|
|
}
|
|
|
|
// Skip FC_PP and FC_PAD.
|
|
PpFO += 2;
|
|
|
|
for (;;)
|
|
{
|
|
FormatString->Read( PpFO, Format, 1 );
|
|
|
|
Iterations = 1;
|
|
switch ( Format[0] )
|
|
{
|
|
case FC_END :
|
|
return PpFO + 1;
|
|
|
|
case FC_NO_REPEAT :
|
|
FormatString->Read( PpFO, Format, 10 );
|
|
|
|
PtrBO = GET_SHORT( Format + 4 );
|
|
pMember = new POINTER( this, PpFO + 6, BufferOffset + PtrBO );
|
|
PointerDict.Register( BufferOffset + PtrBO, pMember );
|
|
|
|
PpFO += 10;
|
|
break;
|
|
|
|
case FC_FIXED_REPEAT :
|
|
PpFO += 2;
|
|
FormatString->Read( PpFO, Format, 2 );
|
|
Iterations = GET_USHORT( Format );
|
|
|
|
// fall through...
|
|
|
|
case FC_VARIABLE_REPEAT :
|
|
FormatString->Read( PpFO, Format, 8 );
|
|
|
|
if ( Format[1] == FC_VARIABLE_OFFSET )
|
|
ABORT( "Variable offset not implemented\n");
|
|
|
|
PtrNo = GET_USHORT( Format + 6 );
|
|
PtrNo *= Iterations;
|
|
PtrFO = PpFO + 8;
|
|
|
|
for (i = 1; i < PtrNo; i++)
|
|
{
|
|
FormatString->Read( PtrFO, Format, 8 );
|
|
|
|
PtrBO = GET_SHORT(Format + 2);
|
|
pMember = new POINTER( this,
|
|
PtrFO + 4,
|
|
BufferOffset + PtrBO );
|
|
PointerDict.Register( BufferOffset + PtrBO, pMember );
|
|
|
|
PtrFO += 8; // ptr desc takes always 4 here.
|
|
}
|
|
PpFO = PtrFO;
|
|
break;
|
|
|
|
default :
|
|
ABORT1( "SkipPointerLayout : unexpected FC: %x", Format[0] );
|
|
}
|
|
}
|
|
|
|
return( PpFO );
|
|
}
|
|
|
|
|