Leaked source code of windows server 2003
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.
 
 
 
 
 
 

222 lines
4.9 KiB

//=============================================================================
//
// MODULE: ASN1Sequence.cxx
//
// Description:
//
// Implementation of ASN.1 sequence parsing logic
//
// Modification History
//
// Mark Pustilnik Date: 06/08/02 - created
//
//=============================================================================
#include "ASN1Parser.hxx"
//
// Parsing a sequence with optional elements entails invoking successive parsers
// and stepping over optional blocks which were not found in the sequence
//
DWORD
ASN1ParserSequence::Parse(
IN OUT ASN1FRAME * Frame
)
{
DWORD dw;
ASN1FRAME FrameIn = *Frame;
DWORD Length = DataLength( Frame );
BOOLEAN FrameLevelChanged = FALSE;
ULPBYTE SequenceEnd;
dw = VerifyAndSkipHeader( Frame );
if ( dw != ERROR_SUCCESS )
{
goto Cleanup;
}
if ( *Frame->Address != BuildDescriptor(
ctUniversal,
pcConstructed,
utSequence ))
{
dw = ERROR_INVALID_DATA;
goto Cleanup;
}
//
// Remember the length of the sequence
//
Length = DataLength( Frame );
//
// Skip over the the descriptor
//
Frame->Address++;
//
// Skip over the length header
//
Frame->Address += HeaderLength( Frame->Address );
//
// Remember where the sequence ends so we know when to stop iterating
//
SequenceEnd = Frame->Address + Length;
//
// Display the sequence summary
//
if ( m_hPropertySummary )
{
if ( FALSE == AttachPropertyInstanceEx(
Frame->hFrame,
m_hPropertySummary,
(DWORD)(SequenceEnd - FrameIn.Address),
FrameIn.Address,
0,
NULL,
0,
Frame->Level,
0 ))
{
dw = ERROR_CAN_NOT_COMPLETE;
goto Cleanup;
}
//
// Anything from this point on is indented
//
Frame->Level += 1;
FrameLevelChanged = TRUE;
}
while ( Frame->Address < SequenceEnd )
{
for ( ULONG i = 0; i < m_Count; i++ )
{
ASN1ParserBase * Parser = m_Parsers[i];
dw = Parser->Parse( Frame );
if ( dw == ERROR_INVALID_USER_BUFFER &&
Parser->IsOptional())
{
//
// Failed to parse, but it was optional anyway
// Clear the error code and proceed
//
dw = ERROR_SUCCESS;
continue;
}
else if ( dw != ERROR_SUCCESS )
{
goto Cleanup;
}
//
// Make sure the sequence is not overstepped
//
if ( Frame->Address > SequenceEnd )
{
dw = ERROR_INVALID_DATA;
goto Cleanup;
}
}
}
if ( !m_Extensible )
{
//
// Any ASN.1 encoding worth it salt is exact, so enforce that
//
if ( Frame->Address != SequenceEnd )
{
dw = ERROR_INVALID_DATA;
goto Cleanup;
}
}
else
{
//
// Pretend we've parsed the rest successfully
//
Frame->Address = SequenceEnd;
}
//
// If we are a value collector, display the collected values now
//
dw = DisplayCollectedValues(
Frame,
(DWORD)(SequenceEnd-FrameIn.Address),
FrameIn.Address
);
PurgeCollectedValues();
if ( dw != ERROR_SUCCESS )
{
goto Cleanup;
}
Cleanup:
//
// Restore the indent level
//
if ( dw != ERROR_SUCCESS )
{
*Frame = FrameIn;
}
else if ( FrameLevelChanged )
{
Frame->Level -= 1;
}
return dw;
}
DWORD
ASN1ParserSequence::CollectValue(
IN ASN1VALUE * Value
)
{
ASN1VALUE * NewValue = Value ? Value->Clone() : NULL;
PASN1VALUE * NewValuesCollected = new PASN1VALUE[m_ValueCount + 1];
if (( Value != NULL && NewValue == NULL ) ||
NewValuesCollected == NULL )
{
delete NewValue;
delete [] NewValuesCollected;
return ERROR_NOT_ENOUGH_MEMORY;
}
RtlCopyMemory(
NewValuesCollected,
m_ValuesCollected,
m_ValueCount * sizeof( PASN1VALUE )
);
delete [] m_ValuesCollected;
m_ValuesCollected = NewValuesCollected;
m_ValuesCollected[m_ValueCount++] = NewValue;
return ERROR_SUCCESS;
}