mirror of https://github.com/tongzx/nt5src
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.
634 lines
14 KiB
634 lines
14 KiB
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
Copyright (c) 1989-1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
paddict.cxx
|
|
|
|
Abstract:
|
|
|
|
Implement a counted dictionary class.
|
|
|
|
Implements a dictionary for handling padding expressions for unknown
|
|
represent as data types.
|
|
|
|
Implements a dictionary for handling sizing macro for unknown
|
|
represent as data types.
|
|
|
|
Implements Quintuple dictionary for registering all type names for both
|
|
transmit_as and represent_as.
|
|
|
|
Implements Quadruple dictionary for handling usr_marshal.
|
|
|
|
Notes:
|
|
|
|
|
|
History:
|
|
|
|
Jan 25, 1994 RyszardK Created
|
|
|
|
----------------------------------------------------------------------------*/
|
|
|
|
#include "becls.hxx"
|
|
#pragma hdrstop
|
|
|
|
#include "typecls.hxx"
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CountedDictionary class.
|
|
//
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
unsigned short
|
|
CountedDictionary::GetListOfItems(
|
|
ITERATOR& ListIter )
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Get a list of dict items into the specified iterator.
|
|
|
|
Arguments:
|
|
|
|
ListIter - A reference to the iterator class where the list is
|
|
accumulated.
|
|
|
|
Return Value:
|
|
|
|
A count of the number of dictionary elements.
|
|
|
|
Notes:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
Dict_Status Status;
|
|
void * pR;
|
|
short Count = 0;
|
|
|
|
//
|
|
// Get to the top of the dictionary.
|
|
//
|
|
|
|
Status = Dict_Next( (pUserType) 0 );
|
|
|
|
//
|
|
// Iterate till the entire dictionary is done.
|
|
//
|
|
|
|
while( SUCCESS == Status )
|
|
{
|
|
pR = Dict_Curr_Item();
|
|
ITERATOR_INSERT( ListIter, pR );
|
|
Count++;
|
|
Status = Dict_Next( pR );
|
|
}
|
|
|
|
return Count;
|
|
}
|
|
|
|
void *
|
|
CountedDictionary::GetFirst()
|
|
{
|
|
Dict_Status Status;
|
|
void * pFirst = 0;
|
|
|
|
Status = Dict_Next( 0 );
|
|
|
|
if ( Status == SUCCESS )
|
|
pFirst = Dict_Curr_Item();
|
|
|
|
return( pFirst );
|
|
}
|
|
|
|
void *
|
|
CountedDictionary::GetNext()
|
|
{
|
|
Dict_Status Status;
|
|
void *pCurr, *pNext = 0;
|
|
|
|
pCurr = Dict_Curr_Item();
|
|
|
|
if ( pCurr )
|
|
{
|
|
Status = Dict_Next( pCurr );
|
|
if ( Status == SUCCESS )
|
|
pNext = Dict_Curr_Item();
|
|
}
|
|
|
|
return( pNext );
|
|
}
|
|
|
|
|
|
SSIZE_T
|
|
CountedDictionary::Compare(
|
|
pUserType pE1,
|
|
pUserType pE2
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Compare two Counted types. Defaults to string comparison.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
return( strcmp( (char *)pE1, (char *)pE2) );
|
|
}
|
|
|
|
//===========================================================================
|
|
|
|
|
|
void
|
|
RepAsPadExprDict::Register(
|
|
unsigned long Offset,
|
|
node_skl * pStructType,
|
|
char * pFieldName,
|
|
node_skl * pPrevFieldType
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Adds a padding expression description to the dictionary
|
|
|
|
Arguments:
|
|
|
|
Offset - offset of the padding field
|
|
pPaddingExpr - text of the expression to be printed out
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
Dict_Status Status;
|
|
|
|
REP_AS_PAD_EXPR_DESC * pOldEntry;
|
|
REP_AS_PAD_EXPR_DESC * pEntry = new REP_AS_PAD_EXPR_DESC;
|
|
|
|
pEntry->KeyOffset = Offset;
|
|
pEntry->pStructType = pStructType;
|
|
pEntry->pFieldName = pFieldName;
|
|
pEntry->pPrevFieldType = pPrevFieldType;
|
|
|
|
Status = Dict_Find( pEntry );
|
|
|
|
switch( Status )
|
|
{
|
|
case EMPTY_DICTIONARY:
|
|
case ITEM_NOT_FOUND:
|
|
|
|
Dict_Insert( pEntry );
|
|
EntryCount++;
|
|
break;
|
|
|
|
default:
|
|
// The only reason for an entry (offset) to be used already
|
|
// would be that the otimization has shrunk the format string.
|
|
// This means that the old entry should be deleted.
|
|
|
|
pOldEntry = (REP_AS_PAD_EXPR_DESC *)Dict_Curr_Item();
|
|
|
|
Dict_Delete( (pUserType *) &pOldEntry );
|
|
Dict_Insert( pEntry );
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
SSIZE_T
|
|
RepAsPadExprDict::Compare(
|
|
pUserType pE1,
|
|
pUserType pE2
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Compare pad expr descriptors.
|
|
KeyOffset is the key that orders the entries.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( ((REP_AS_PAD_EXPR_DESC *)pE1)->KeyOffset <
|
|
((REP_AS_PAD_EXPR_DESC *)pE2)->KeyOffset )
|
|
return( -1 );
|
|
else
|
|
if( ((REP_AS_PAD_EXPR_DESC *)pE1)->KeyOffset >
|
|
((REP_AS_PAD_EXPR_DESC *)pE2)->KeyOffset )
|
|
return( 1 );
|
|
else
|
|
return( 0 );
|
|
}
|
|
|
|
REP_AS_PAD_EXPR_DESC *
|
|
RepAsPadExprDict::GetFirst()
|
|
{
|
|
Dict_Status Status;
|
|
REP_AS_PAD_EXPR_DESC * pFirst = 0;
|
|
|
|
Status = Dict_Next( 0 );
|
|
|
|
if ( Status == SUCCESS )
|
|
pFirst = (REP_AS_PAD_EXPR_DESC *)Dict_Curr_Item();
|
|
|
|
return( pFirst );
|
|
}
|
|
|
|
REP_AS_PAD_EXPR_DESC *
|
|
RepAsPadExprDict::GetNext()
|
|
{
|
|
Dict_Status Status;
|
|
REP_AS_PAD_EXPR_DESC *pCurr, *pNext = 0;
|
|
|
|
pCurr = (REP_AS_PAD_EXPR_DESC *)Dict_Curr_Item();
|
|
|
|
if ( pCurr )
|
|
{
|
|
Status = Dict_Next( pCurr );
|
|
if ( Status == SUCCESS )
|
|
pNext = (REP_AS_PAD_EXPR_DESC *)Dict_Curr_Item();
|
|
}
|
|
|
|
return( pNext );
|
|
}
|
|
|
|
void
|
|
RepAsPadExprDict::WriteCurrentPadDesc(
|
|
ISTREAM * pStream
|
|
)
|
|
/*++
|
|
|
|
Routine description:
|
|
|
|
Writes out the following string:
|
|
|
|
(unsigned char)(NdrFieldPad(pSN,pFN,pPFN,pPFT))
|
|
|
|
Arguments:
|
|
|
|
pStream - stream to write to.
|
|
|
|
--*/
|
|
{
|
|
REP_AS_PAD_EXPR_DESC *pCurr = (REP_AS_PAD_EXPR_DESC *)Dict_Curr_Item();
|
|
|
|
if ( pCurr && pCurr->pPrevFieldType )
|
|
{
|
|
pStream->Write( "(unsigned char)("FC_FIELD_PAD_MACRO"(" );
|
|
pCurr->pStructType->PrintType( PRT_TYPE_SPECIFIER, pStream );
|
|
pStream->Write( ',' );
|
|
pStream->Write( pCurr->pFieldName );
|
|
pStream->Write( ',' );
|
|
pStream->Write( pCurr->pPrevFieldType->GetSymName() );
|
|
pStream->Write( ',' );
|
|
pCurr->pPrevFieldType->GetChild()->
|
|
PrintType( PRT_TYPE_SPECIFIER, pStream );
|
|
pStream->Write( "))," );
|
|
}
|
|
else
|
|
pStream->Write( "0," );
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
void
|
|
RepAsSizeDict::Register(
|
|
unsigned long Offset,
|
|
char * pTypeName
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Adds a sizing macro description to the dictionary
|
|
|
|
Arguments:
|
|
|
|
Offset - offset of the padding field
|
|
pPaddingExpr - text of the expression to be printed out
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
Dict_Status Status;
|
|
|
|
REP_AS_SIZE_DESC * pOldEntry;
|
|
REP_AS_SIZE_DESC * pEntry = new REP_AS_SIZE_DESC;
|
|
|
|
pEntry->KeyOffset = Offset;
|
|
pEntry->pTypeName = pTypeName;
|
|
|
|
Status = Dict_Find( pEntry );
|
|
|
|
switch( Status )
|
|
{
|
|
case EMPTY_DICTIONARY:
|
|
case ITEM_NOT_FOUND:
|
|
|
|
Dict_Insert( pEntry );
|
|
EntryCount++;
|
|
break;
|
|
|
|
default:
|
|
// The only reason for an entry (offset) to be used already
|
|
// would be that the otimization has shrunk the format string.
|
|
// This means that the old entry should be deleted.
|
|
|
|
pOldEntry = (REP_AS_SIZE_DESC *)Dict_Curr_Item();
|
|
|
|
Dict_Delete( (pUserType *) &pOldEntry );
|
|
Dict_Insert( pEntry );
|
|
break;
|
|
}
|
|
return;
|
|
}
|
|
|
|
|
|
SSIZE_T
|
|
RepAsSizeDict::Compare(
|
|
pUserType pE1,
|
|
pUserType pE2
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Compare size descriptors.
|
|
KeyOffset is the key that orders the entries.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( ((REP_AS_SIZE_DESC *)pE1)->KeyOffset <
|
|
((REP_AS_SIZE_DESC *)pE2)->KeyOffset )
|
|
return( -1 );
|
|
else
|
|
if( ((REP_AS_SIZE_DESC *)pE1)->KeyOffset >
|
|
((REP_AS_SIZE_DESC *)pE2)->KeyOffset )
|
|
return( 1 );
|
|
else
|
|
return( 0 );
|
|
}
|
|
|
|
REP_AS_SIZE_DESC *
|
|
RepAsSizeDict::GetFirst()
|
|
{
|
|
Dict_Status Status;
|
|
REP_AS_SIZE_DESC * pFirst = 0;
|
|
|
|
Status = Dict_Next( 0 );
|
|
|
|
if ( Status == SUCCESS )
|
|
pFirst = (REP_AS_SIZE_DESC *)Dict_Curr_Item();
|
|
|
|
return( pFirst );
|
|
}
|
|
|
|
REP_AS_SIZE_DESC *
|
|
RepAsSizeDict::GetNext()
|
|
{
|
|
Dict_Status Status;
|
|
REP_AS_SIZE_DESC *pCurr, *pNext = 0;
|
|
|
|
pCurr = (REP_AS_SIZE_DESC *)Dict_Curr_Item();
|
|
|
|
if ( pCurr )
|
|
{
|
|
Status = Dict_Next( pCurr );
|
|
if ( Status == SUCCESS )
|
|
pNext = (REP_AS_SIZE_DESC *)Dict_Curr_Item();
|
|
}
|
|
|
|
return( pNext );
|
|
}
|
|
|
|
void
|
|
RepAsSizeDict::WriteCurrentSizeDesc(
|
|
ISTREAM * pStream
|
|
)
|
|
/*++
|
|
|
|
Routine description:
|
|
|
|
Writes out the following string:
|
|
|
|
NdrFcShort( sizeof(<type>)
|
|
|
|
Arguments:
|
|
|
|
pStream - stream to write to.
|
|
|
|
--*/
|
|
{
|
|
REP_AS_SIZE_DESC *pCurr = (REP_AS_SIZE_DESC *)Dict_Curr_Item();
|
|
|
|
if ( pCurr )
|
|
{
|
|
pStream->Write( "NdrFcShort( sizeof(" );
|
|
pStream->Write( pCurr->pTypeName );
|
|
pStream->Write( "))," );
|
|
}
|
|
else
|
|
pStream->Write( "0," );
|
|
}
|
|
|
|
|
|
//========================================================================
|
|
|
|
|
|
BOOL
|
|
QuintupleDict::Add(
|
|
void * pContext
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Adds a Quintuple description to the dictionary.
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
TRUE - when a new entry has been registered,
|
|
FALSE - otherwise
|
|
|
|
Index field gets set to appropriate index.
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
Dict_Status Status;
|
|
XMIT_AS_CONTEXT * pEntry = (XMIT_AS_CONTEXT *) pContext;
|
|
|
|
Status = Dict_Find( pEntry );
|
|
|
|
if( Status == EMPTY_DICTIONARY || Status == ITEM_NOT_FOUND )
|
|
{
|
|
pEntry->Index = CurrentIndex;
|
|
Dict_Insert( pEntry );
|
|
CurrentIndex++;
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
pEntry->Index = ((XMIT_AS_CONTEXT *)Dict_Curr_Item())->Index;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
SSIZE_T
|
|
QuintupleDict::Compare(
|
|
pUserType pE1,
|
|
pUserType pE2
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Compare two quintuple types.
|
|
Both fXmit and the name have to match.
|
|
|
|
fXmit allows for comparing xmit_as with xmit_as and rep_as with rep_as.
|
|
For xmit_as we compare the presented types.
|
|
For rep_as we compare the wire types (not the local types).
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
if( ((XMIT_AS_CONTEXT *)pE1)->fXmit == ((XMIT_AS_CONTEXT *)pE2)->fXmit )
|
|
if ( ((XMIT_AS_CONTEXT *)pE1)->fXmit )
|
|
return( strcmp( ((XMIT_AS_CONTEXT *)pE1)->pTypeName,
|
|
((XMIT_AS_CONTEXT *)pE2)->pTypeName ) );
|
|
else
|
|
return( strcmp(
|
|
((CG_REPRESENT_AS *)((XMIT_AS_CONTEXT *)pE1)->pXmitNode)->
|
|
GetTransmittedType()->GetSymName(),
|
|
((CG_REPRESENT_AS *)((XMIT_AS_CONTEXT *)pE2)->pXmitNode)->
|
|
GetTransmittedType()->GetSymName()
|
|
) );
|
|
else
|
|
if( ((XMIT_AS_CONTEXT *)pE1)->fXmit )
|
|
return( -1 );
|
|
else
|
|
return( 1 );
|
|
}
|
|
|
|
void *
|
|
QuintupleDict::GetFirst()
|
|
{
|
|
Dict_Status Status;
|
|
XMIT_AS_CONTEXT * pFirst = 0;
|
|
|
|
Status = Dict_Next( 0 );
|
|
|
|
if ( Status == SUCCESS )
|
|
pFirst = (XMIT_AS_CONTEXT *)Dict_Curr_Item();
|
|
|
|
return( pFirst );
|
|
}
|
|
|
|
void *
|
|
QuintupleDict::GetNext()
|
|
{
|
|
Dict_Status Status;
|
|
XMIT_AS_CONTEXT *pCurr, *pNext = 0;
|
|
|
|
pCurr = (XMIT_AS_CONTEXT *)Dict_Curr_Item();
|
|
|
|
if ( pCurr )
|
|
{
|
|
Status = Dict_Next( pCurr );
|
|
if ( Status == SUCCESS )
|
|
pNext = (XMIT_AS_CONTEXT *)Dict_Curr_Item();
|
|
}
|
|
|
|
return( pNext );
|
|
}
|
|
|
|
//========================================================================
|
|
|
|
|
|
BOOL
|
|
QuadrupleDict::Add(
|
|
void * pContext
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Adds a Quadruple description to the dictionary.
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
|
|
TRUE - when a new entry has been registered,
|
|
FALSE - otherwise entry exist already
|
|
|
|
Index field gets set to appropriate index.
|
|
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
Dict_Status Status;
|
|
USER_MARSHAL_CONTEXT * pEntry = (USER_MARSHAL_CONTEXT *) pContext;
|
|
|
|
Status = Dict_Find( pEntry );
|
|
|
|
if( Status == EMPTY_DICTIONARY || Status == ITEM_NOT_FOUND )
|
|
{
|
|
pEntry->Index = GetCount();
|
|
Dict_Insert( pEntry );
|
|
IncrementCount();
|
|
return TRUE;
|
|
}
|
|
else
|
|
{
|
|
pEntry->Index = ((USER_MARSHAL_CONTEXT *)Dict_Curr_Item())->Index;
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
SSIZE_T
|
|
QuadrupleDict::Compare(
|
|
pUserType pE1,
|
|
pUserType pE2
|
|
)
|
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Routine Description:
|
|
|
|
Compare two Quadruple types.
|
|
For usr_marshall we compare the types.
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
----------------------------------------------------------------------------*/
|
|
{
|
|
return( strcmp( ((USER_MARSHAL_CONTEXT *)pE1)->pTypeName,
|
|
((USER_MARSHAL_CONTEXT *)pE2)->pTypeName ) );
|
|
}
|
|
|
|
|
|
|
|
|