2499 lines
66 KiB
C++
2499 lines
66 KiB
C++
/*++
|
|
|
|
Copyright (c) 1999 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
q931pdu.cpp
|
|
|
|
Abstract:
|
|
|
|
Encode/decode/transport routines for Q931/H450 messages.
|
|
|
|
Author:
|
|
Nikhil Bobde (NikhilB)
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "globals.h"
|
|
#include "q931obj.h"
|
|
#include "line.h"
|
|
#include "q931pdu.h"
|
|
#include "ras.h"
|
|
|
|
//PARSE ROUTINES
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse and return a single octet encoded value, See Q931 section 4.5.1.
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// bIdent Pointer to space for field identifier
|
|
// Value Pointer to space for field value
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseSingleOctetType1(
|
|
PBUFFERDESCR pBuf,
|
|
BYTE * bIdent,
|
|
BYTE * Value
|
|
)
|
|
{
|
|
// There has to be at least 1 byte in the stream to be
|
|
// able to parse the single octet value
|
|
if (pBuf->dwLength < 1)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// low bits (0, 1, 2, 3) of the byte are the value
|
|
*Value = (BYTE)(*pBuf->pbBuffer & TYPE1VALUEMASK);
|
|
|
|
// higher bits (4, 5, 6) are the identifier. bit 7 is always 1,
|
|
// and is not returned as part of the id.
|
|
*bIdent = (BYTE)((*pBuf->pbBuffer & 0x70) >> 4);
|
|
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse and return a single octet encoded value, See Q931 section 4.5.1.
|
|
// This octet has no value, only an identifier.
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer containing the
|
|
// length and a pointer to the raw bytes of the input stream.
|
|
// bIdent Pointer to space for field identifier
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseSingleOctetType2(
|
|
PBUFFERDESCR pBuf,
|
|
BYTE * bIdent
|
|
)
|
|
{
|
|
// There has to be at least 1 byte in the stream to be
|
|
// able to parse the single octet value
|
|
if (pBuf->dwLength < 1)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// low 7 bits of the byte are the identifier
|
|
*bIdent = (BYTE)(*pBuf->pbBuffer & 0x7f);
|
|
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse and return a variable length Q931 field see Q931 section 4.5.1.
|
|
//
|
|
// Parameters :
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// bIdent Pointer to space for field identifier
|
|
// dwLength Pointer to space for the length
|
|
// pbContents Pointer to space for the bytes of the field
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseVariableOctet(
|
|
PBUFFERDESCR pBuf,
|
|
BYTE * dwLength,
|
|
BYTE * pbContents
|
|
)
|
|
{
|
|
// There has to be at least 2 bytes in order just to get
|
|
// the length and the identifier
|
|
// able to parse the single octet value
|
|
if (pBuf->dwLength < 2)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
//Increment the ident byte
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
// The next byte is the length
|
|
*dwLength = *pBuf->pbBuffer;
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
if (pBuf->dwLength < *dwLength)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
CopyMemory( pbContents, pBuf->pbBuffer, *dwLength );
|
|
pBuf->pbBuffer += *dwLength;
|
|
pBuf->dwLength -= *dwLength;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse and return a variable length Q931 field see Q931 section 4.5.1.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseVariableASN(
|
|
PBUFFERDESCR pBuf,
|
|
BYTE *bIdent,
|
|
BYTE *ProtocolDiscriminator,
|
|
PUSERUSERIE pUserUserIE
|
|
)
|
|
{
|
|
pUserUserIE -> wUserInfoLen = 0;
|
|
|
|
// There has to be at least 4 bytes for the IE identifier,
|
|
// the contents length, and the protocol discriminator (1 + 2 + 1).
|
|
if (pBuf->dwLength < 4)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// low 7 bits of the first byte are the identifier
|
|
*bIdent= (BYTE)(*pBuf->pbBuffer & 0x7f);
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
// The next 2 bytes are the length
|
|
pUserUserIE -> wUserInfoLen = *(pBuf->pbBuffer);
|
|
pBuf->pbBuffer++;
|
|
pUserUserIE -> wUserInfoLen =
|
|
(WORD)(((pUserUserIE -> wUserInfoLen) << 8) + *pBuf->pbBuffer);
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength -= 2;
|
|
|
|
if (pBuf->dwLength < pUserUserIE -> wUserInfoLen )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// The next byte is the protocol discriminator.
|
|
*ProtocolDiscriminator = *pBuf->pbBuffer;
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
if( pUserUserIE -> wUserInfoLen > 0 )
|
|
{
|
|
pUserUserIE -> wUserInfoLen--;
|
|
}
|
|
|
|
CopyMemory( pUserUserIE -> pbUserInfo,
|
|
pBuf->pbBuffer,
|
|
pUserUserIE -> wUserInfoLen );
|
|
|
|
pBuf->pbBuffer += pUserUserIE -> wUserInfoLen;
|
|
pBuf->dwLength -= pUserUserIE -> wUserInfoLen;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Get the identifier of the next field from the buffer and
|
|
// return it. The buffer pointer is not incremented, To
|
|
// parse the field and extract its values, the above functions
|
|
// should be used. See Q931 table 4-3 for the encodings of the
|
|
// identifiers.
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to the buffer space
|
|
//------------------------------------------------------------------------------
|
|
BYTE
|
|
GetNextIdent(
|
|
void *pbBuffer
|
|
)
|
|
{
|
|
FIELDIDENTTYPE bIdent;
|
|
|
|
// Extract the first byte from the buffer
|
|
bIdent= (*(FIELDIDENTTYPE *)pbBuffer);
|
|
|
|
// This value can be returned as the identifier as long
|
|
// as it is not a single Octet - Type 1 element.
|
|
// Those items must have the value removed from them
|
|
// before they can be returned.
|
|
if ((bIdent & 0x80) && ((bIdent & TYPE1IDENTMASK) != 0xA0))
|
|
{
|
|
return (BYTE)(bIdent & TYPE1IDENTMASK);
|
|
}
|
|
|
|
return bIdent;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse and return a protocol discriminator. See Q931 section 4.2.
|
|
// The octet pointed to by **pbBuffer is the protocol Discriminator.
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// Discrim Pointer to space for discriminator
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseProtocolDiscriminator(
|
|
PBUFFERDESCR pBuf,
|
|
PDTYPE *Discrim)
|
|
{
|
|
// There has to be at least enough bytes left in the
|
|
// string for the operation
|
|
if (pBuf->dwLength < sizeof(PDTYPE))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*Discrim = *(PDTYPE *)pBuf->pbBuffer;
|
|
if (*Discrim != Q931PDVALUE)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
pBuf->pbBuffer += sizeof(PDTYPE);
|
|
pBuf->dwLength -= sizeof(PDTYPE);
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse and return a variable length Q931 call reference see
|
|
// Q931 section 4.3.
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// dwLength Pointer to space for the length
|
|
// pbContents Pointer to space for the bytes of the field
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseCallReference(
|
|
PBUFFERDESCR pBuf,
|
|
CRTYPE * wCallRef
|
|
)
|
|
{
|
|
register int indexI;
|
|
BYTE dwLength;
|
|
|
|
// There has to be at least enough bytes left in the
|
|
// string for the length byte
|
|
if( pBuf->dwLength < 1 )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// low 4 bits of the first byte are the length.
|
|
// the rest of the bits are zeroes.
|
|
dwLength = (BYTE)(*pBuf->pbBuffer & 0x0f);
|
|
if( dwLength != sizeof(WORD) )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
// There has to be at least enough bytes left in the
|
|
// string for the operation
|
|
if (pBuf->dwLength < dwLength)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*wCallRef = 0; // length can be 0, so initialize here first...
|
|
for (indexI = 0; indexI < dwLength; indexI++)
|
|
{
|
|
if (indexI < sizeof(CRTYPE))
|
|
{
|
|
// Copy the bytes out of the rest of the buffer
|
|
*wCallRef = (WORD)((*wCallRef << 8) +
|
|
*pBuf->pbBuffer);
|
|
}
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
}
|
|
|
|
// note: the high order bit of the value represents callee relationship.
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse and return a message type. See Q931 section 4.4.
|
|
// The octet pointed to by **pbBuffer is the message type.
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// MessageType Pointer to space for message type
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseMessageType(
|
|
PBUFFERDESCR pBuf,
|
|
MESSAGEIDTYPE * MessageType
|
|
)
|
|
{
|
|
// There has to be at least enough bytes left in the
|
|
// string for the operation
|
|
if (pBuf->dwLength < sizeof(MESSAGEIDTYPE))
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
*MessageType = (BYTE)(*((MESSAGEIDTYPE *)pBuf->pbBuffer) & MESSAGETYPEMASK);
|
|
|
|
if( ISVALIDQ931MESSAGE(*MessageType) == FALSE )
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
pBuf->pbBuffer += sizeof(MESSAGEIDTYPE);
|
|
pBuf->dwLength -= sizeof(MESSAGEIDTYPE);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional facility ie field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed facility
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseFacility(
|
|
PBUFFERDESCR pBuf,
|
|
PFACILITYIE pFieldStruct
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(FACILITYIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional bearer capability field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed bearer capability
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseBearerCapability(
|
|
PBUFFERDESCR pBuf,
|
|
PBEARERCAPIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(BEARERCAPIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional cause field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed cause
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseCause(
|
|
PBUFFERDESCR pBuf,
|
|
PCAUSEIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(CAUSEIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional call state field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed call state
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseCallState(
|
|
PBUFFERDESCR pBuf,
|
|
PCALLSTATEIE pFieldStruct)
|
|
{
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(CALLSTATEIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
HRESULT hr;
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional channel identification field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed channel identity
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseChannelIdentification(
|
|
PBUFFERDESCR pBuf,
|
|
PCHANIDENTIE pFieldStruct)
|
|
{
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(CHANIDENTIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
HRESULT hr;
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional progress indication field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed progress
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseProgress(
|
|
PBUFFERDESCR pBuf,
|
|
PPROGRESSIE pFieldStruct)
|
|
{
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(PROGRESSIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
HRESULT hr;
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional network specific facilities field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed network facitlities
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseNetworkSpec(
|
|
PBUFFERDESCR pBuf,
|
|
PNETWORKIE pFieldStruct)
|
|
{
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(NETWORKIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
HRESULT hr;
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional notification indicator field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parse notification indicator
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseNotificationIndicator(
|
|
PBUFFERDESCR pBuf,
|
|
PNOTIFICATIONINDIE pFieldStruct)
|
|
{
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(NOTIFICATIONINDIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
if (GetNextIdent(pBuf->pbBuffer) == IDENT_NOTIFICATION)
|
|
{
|
|
HRESULT hr;
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional display field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed display
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseDisplay(
|
|
PBUFFERDESCR pBuf,
|
|
PDISPLAYIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(DISPLAYIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseDate(
|
|
PBUFFERDESCR pBuf,
|
|
PDATEIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(DATEIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional keypad field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed keypad
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseKeypad(
|
|
PBUFFERDESCR pBuf,
|
|
PKEYPADIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(KEYPADIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional signal field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed signal
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseSignal(
|
|
PBUFFERDESCR pBuf,
|
|
PSIGNALIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(SIGNALIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf,
|
|
&pFieldStruct->dwLength, &pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional information rate field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed information rate
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseInformationRate(
|
|
PBUFFERDESCR pBuf,
|
|
PINFORATEIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(INFORATEIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional calling party number field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseCallingPartyNumber(
|
|
PBUFFERDESCR pBuf,
|
|
PCALLINGNUMBERIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(CALLINGNUMBERIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf,
|
|
&pFieldStruct->dwLength, &pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional calling party subaddress field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseCallingPartySubaddress(
|
|
PBUFFERDESCR pBuf,
|
|
PCALLINGSUBADDRIE pFieldStruct)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(CALLINGSUBADDRIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf,
|
|
&pFieldStruct->dwLength, &pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional called party number field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseCalledPartyNumber(
|
|
PBUFFERDESCR pBuf,
|
|
PCALLEDNUMBERIE pFieldStruct
|
|
)
|
|
{
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(PCALLEDNUMBERIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
if (GetNextIdent(pBuf->pbBuffer) == IDENT_CALLEDNUMBER)
|
|
{
|
|
BYTE RemainingLength = 0;
|
|
|
|
// Need 3 bytes for the ident (1), length (1),
|
|
// and type + plan (1) fields.
|
|
if (pBuf->dwLength < 3)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// skip the ie identifier...
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
// Get the length of the contents following the length field.
|
|
RemainingLength = *pBuf->pbBuffer;
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
|
|
// make sure we have at least that much length left...
|
|
if (pBuf->dwLength < RemainingLength)
|
|
{
|
|
return E_INVALIDARG;
|
|
}
|
|
|
|
// Get the type + plan fields.
|
|
if (*(pBuf->pbBuffer) & 0x80)
|
|
{
|
|
pFieldStruct->NumberType =
|
|
(BYTE)(*pBuf->pbBuffer & 0xf0);
|
|
pFieldStruct->NumberingPlan =
|
|
(BYTE)(*pBuf->pbBuffer & 0x0f);
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
RemainingLength--;
|
|
}
|
|
|
|
pFieldStruct->PartyNumberLength = RemainingLength;
|
|
pFieldStruct->fPresent = TRUE;
|
|
|
|
CopyMemory( pFieldStruct->PartyNumbers, pBuf->pbBuffer, RemainingLength );
|
|
|
|
pBuf->pbBuffer += RemainingLength;
|
|
pBuf->dwLength -= RemainingLength;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional called party subaddress field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseCalledPartySubaddress(
|
|
PBUFFERDESCR pBuf,
|
|
PCALLEDSUBADDRIE pFieldStruct
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(CALLEDSUBADDRIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf,
|
|
&pFieldStruct->dwLength, &pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional redirecting number field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseRedirectingNumber(
|
|
PBUFFERDESCR pBuf,
|
|
PREDIRECTINGIE pFieldStruct
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(REDIRECTINGIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf,
|
|
&pFieldStruct->dwLength, &pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional lower layer compatibility field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseLowLayerCompatibility(
|
|
PBUFFERDESCR pBuf,
|
|
PLLCOMPATIBILITYIE pFieldStruct
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(LLCOMPATIBILITYIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf,
|
|
&pFieldStruct->dwLength, &pFieldStruct->pbContents[0]);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Parse an optional higher layer compatibility field
|
|
//
|
|
// Parameters:
|
|
// pbBuffer Pointer to a descriptor of the buffer
|
|
// containing the length and a pointer
|
|
// to the raw bytes of the input stream.
|
|
// pFieldStruct Pointer to space for parsed
|
|
// information.
|
|
//------------------------------------------------------------------------------
|
|
HRESULT
|
|
ParseHighLayerCompatibility(
|
|
PBUFFERDESCR pBuf,
|
|
PHLCOMPATIBILITYIE pFieldStruct
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
memset( (PVOID)pFieldStruct, 0, sizeof(HLCOMPATIBILITYIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
|
|
hr = ParseVariableOctet(pBuf, &pFieldStruct->dwLength,
|
|
&pFieldStruct->pbContents[0]);
|
|
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->dwLength > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
ParseUserToUser(
|
|
PBUFFERDESCR pBuf,
|
|
PUSERUSERIE pFieldStruct
|
|
)
|
|
{
|
|
BYTE bIdent;
|
|
HRESULT hr;
|
|
|
|
ZeroMemory( (PVOID)pFieldStruct, sizeof(USERUSERIE));
|
|
pFieldStruct->fPresent = FALSE;
|
|
hr = ParseVariableASN( pBuf,
|
|
&bIdent,
|
|
&(pFieldStruct->ProtocolDiscriminator),
|
|
pFieldStruct
|
|
);
|
|
if( FAILED(hr) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if (pFieldStruct->wUserInfoLen > 0)
|
|
{
|
|
pFieldStruct->fPresent = TRUE;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
ParseQ931Field(
|
|
PBUFFERDESCR pBuf,
|
|
PQ931MESSAGE pMessage
|
|
)
|
|
{
|
|
FIELDIDENTTYPE bIdent;
|
|
|
|
bIdent = GetNextIdent(pBuf->pbBuffer);
|
|
switch (bIdent)
|
|
{
|
|
/*case IDENT_REVCHARGE:
|
|
case IDENT_TRANSITNET:
|
|
case IDENT_RESTART:
|
|
case IDENT_MORE:
|
|
case IDENT_REPEAT:
|
|
case IDENT_SEGMENTED:
|
|
case IDENT_SHIFT:
|
|
case IDENT_CALLIDENT:
|
|
case IDENT_CLOSEDUG:
|
|
case IDENT_SENDINGCOMPLETE:
|
|
case IDENT_PACKETSIZE:
|
|
case IDENT_CONGESTION:
|
|
case IDENT_NETWORKSPEC:
|
|
case IDENT_PLWINDOWSIZE:
|
|
case IDENT_TRANSITDELAY:
|
|
case IDENT_PLBINARYPARAMS:
|
|
case IDENT_ENDTOENDDELAY:
|
|
|
|
return E_INVALIDARG;*/
|
|
|
|
case IDENT_FACILITY:
|
|
|
|
return ParseFacility( pBuf, &pMessage->Facility );
|
|
|
|
case IDENT_BEARERCAP:
|
|
|
|
return ParseBearerCapability( pBuf, &pMessage->BearerCapability );
|
|
|
|
case IDENT_CAUSE:
|
|
|
|
return ParseCause(pBuf, &pMessage->Cause);
|
|
|
|
case IDENT_CALLSTATE:
|
|
return ParseCallState(pBuf, &pMessage->CallState);
|
|
|
|
case IDENT_CHANNELIDENT:
|
|
return ParseChannelIdentification( pBuf,
|
|
&pMessage->ChannelIdentification );
|
|
|
|
case IDENT_PROGRESS:
|
|
return ParseProgress( pBuf, &pMessage->ProgressIndicator );
|
|
|
|
case IDENT_NOTIFICATION:
|
|
return ParseNotificationIndicator( pBuf,
|
|
&pMessage->NotificationIndicator );
|
|
|
|
case IDENT_DISPLAY:
|
|
return ParseDisplay( pBuf, &pMessage->Display );
|
|
|
|
case IDENT_DATE:
|
|
return ParseDate( pBuf, &pMessage->Date );
|
|
|
|
case IDENT_KEYPAD:
|
|
return ParseKeypad( pBuf, &pMessage->Keypad );
|
|
|
|
case IDENT_SIGNAL:
|
|
return ParseSignal(pBuf, &pMessage->Signal);
|
|
|
|
case IDENT_INFORMATIONRATE:
|
|
return ParseInformationRate( pBuf, &pMessage->InformationRate );
|
|
|
|
case IDENT_CALLINGNUMBER:
|
|
return ParseCallingPartyNumber( pBuf, &pMessage->CallingPartyNumber );
|
|
|
|
case IDENT_CALLINGSUBADDR:
|
|
return ParseCallingPartySubaddress(pBuf,
|
|
&pMessage->CallingPartySubaddress);
|
|
|
|
case IDENT_CALLEDNUMBER:
|
|
return ParseCalledPartyNumber(pBuf, &pMessage->CalledPartyNumber);
|
|
|
|
case IDENT_CALLEDSUBADDR:
|
|
return ParseCalledPartySubaddress( pBuf,
|
|
&pMessage->CalledPartySubaddress );
|
|
|
|
case IDENT_REDIRECTING:
|
|
return ParseRedirectingNumber( pBuf, &pMessage->RedirectingNumber );
|
|
|
|
case IDENT_LLCOMPATIBILITY:
|
|
return ParseLowLayerCompatibility( pBuf,
|
|
&pMessage->LowLayerCompatibility );
|
|
|
|
case IDENT_HLCOMPATIBILITY:
|
|
return ParseHighLayerCompatibility( pBuf,
|
|
&pMessage->HighLayerCompatibility );
|
|
|
|
case IDENT_USERUSER:
|
|
return ParseUserToUser(pBuf, &pMessage->UserToUser);
|
|
|
|
default:
|
|
|
|
//Increment the ident byte
|
|
pBuf->pbBuffer++;
|
|
pBuf->dwLength--;
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Write a Q931 message type. See Q931 section 4.4.
|
|
//------------------------------------------------------------------------------
|
|
|
|
void
|
|
WriteMessageType(
|
|
PBUFFERDESCR pBuf,
|
|
MESSAGEIDTYPE * MessageType,
|
|
DWORD* pdwPDULen
|
|
)
|
|
{
|
|
(*pdwPDULen) += sizeof(MESSAGEIDTYPE);
|
|
|
|
_ASSERTE( pBuf->dwLength > *pdwPDULen );
|
|
|
|
*(MESSAGEIDTYPE *)(pBuf->pbBuffer) =
|
|
(BYTE)(*MessageType & MESSAGETYPEMASK);
|
|
pBuf->pbBuffer += sizeof(MESSAGEIDTYPE);
|
|
}
|
|
|
|
|
|
|
|
void
|
|
WriteVariableOctet(
|
|
PBUFFERDESCR pBuf,
|
|
BYTE bIdent,
|
|
BYTE dwLength,
|
|
BYTE *pbContents,
|
|
DWORD* pdwPDULen
|
|
)
|
|
{
|
|
if( pbContents == NULL )
|
|
{
|
|
dwLength = 0;
|
|
}
|
|
|
|
// space for the length and the identifier bytes and octet array
|
|
(*pdwPDULen) += (2 + dwLength);
|
|
_ASSERTE( pBuf->dwLength > *pdwPDULen );
|
|
|
|
// the id byte, then the length byte
|
|
// low 7 bits of the first byte are the identifier
|
|
*pBuf->pbBuffer = (BYTE)(bIdent & 0x7f);
|
|
pBuf->pbBuffer++;
|
|
*pBuf->pbBuffer = dwLength;
|
|
pBuf->pbBuffer++;
|
|
|
|
CopyMemory( (PVOID)pBuf->pbBuffer, (PVOID)pbContents, dwLength );
|
|
pBuf->pbBuffer += dwLength;
|
|
}
|
|
|
|
|
|
void
|
|
WriteUserInformation(
|
|
PBUFFERDESCR pBuf,
|
|
BYTE bIdent,
|
|
WORD wUserInfoLen,
|
|
BYTE * pbUserInfo,
|
|
DWORD * pdwPDULen
|
|
)
|
|
{
|
|
WORD ContentsLength = (WORD)(wUserInfoLen + 1);
|
|
|
|
// There has to be at least 4 bytes for the IE identifier,
|
|
// the contents length, and the protocol discriminator (1 + 2 + 1).
|
|
(*pdwPDULen) += (4 + wUserInfoLen);
|
|
_ASSERTE( pBuf->dwLength > *pdwPDULen );
|
|
|
|
// low 7 bits of the first byte are the identifier
|
|
*pBuf->pbBuffer = (BYTE)(bIdent & 0x7f);
|
|
pBuf->pbBuffer++;
|
|
|
|
// write the contents length bytes.
|
|
*pBuf->pbBuffer = (BYTE)(ContentsLength >> 8);
|
|
pBuf->pbBuffer++;
|
|
*pBuf->pbBuffer = (BYTE)ContentsLength;
|
|
pBuf->pbBuffer++;
|
|
|
|
// write the protocol discriminator byte.
|
|
*(pBuf->pbBuffer) = Q931_PROTOCOL_X209;
|
|
pBuf->pbBuffer++;
|
|
|
|
CopyMemory( (PVOID)pBuf->pbBuffer,
|
|
(PVOID)pbUserInfo,
|
|
wUserInfoLen);
|
|
|
|
pBuf->pbBuffer += wUserInfoLen;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
WritePartyNumber(
|
|
PBUFFERDESCR pBuf,
|
|
BYTE bIdent,
|
|
BYTE NumberType,
|
|
BYTE NumberingPlan,
|
|
BYTE bPartyNumberLength,
|
|
BYTE *pbPartyNumbers,
|
|
DWORD * pdwPDULen )
|
|
{
|
|
if (pbPartyNumbers == NULL)
|
|
{
|
|
bPartyNumberLength = 1;
|
|
}
|
|
|
|
// space for the ident (1), length (1), and type + plan (1) fields.
|
|
(*pdwPDULen) += (2 + bPartyNumberLength);
|
|
_ASSERTE( pBuf->dwLength > *pdwPDULen );
|
|
|
|
// low 7 bits of byte 1 are the ie identifier
|
|
*pBuf->pbBuffer = (BYTE)(bIdent & 0x7f);
|
|
pBuf->pbBuffer++;
|
|
|
|
|
|
// byte 2 is the ie contents length following the length field.
|
|
*pBuf->pbBuffer = (BYTE)(bPartyNumberLength);
|
|
pBuf->pbBuffer++;
|
|
|
|
// byte 3 is the type and plan field.
|
|
*pBuf->pbBuffer = (BYTE)(NumberType | NumberingPlan);
|
|
pBuf->pbBuffer++;
|
|
|
|
if( pbPartyNumbers != NULL )
|
|
{
|
|
CopyMemory( (PVOID)pBuf->pbBuffer,
|
|
(PVOID)pbPartyNumbers,
|
|
bPartyNumberLength-1 );
|
|
}
|
|
pBuf->pbBuffer += (bPartyNumberLength-1);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//
|
|
//ASN Parsing functions
|
|
//
|
|
|
|
BOOL
|
|
ParseVendorInfo(
|
|
OUT PH323_VENDORINFO pDestVendorInfo,
|
|
IN VendorIdentifier* pVendor
|
|
)
|
|
{
|
|
memset( (PVOID)pDestVendorInfo, 0, sizeof(H323_VENDORINFO) );
|
|
|
|
pDestVendorInfo ->bCountryCode = (BYTE)pVendor->vendor.t35CountryCode;
|
|
pDestVendorInfo ->bExtension = (BYTE)pVendor->vendor.t35Extension;
|
|
pDestVendorInfo ->wManufacturerCode = pVendor->vendor.manufacturerCode;
|
|
|
|
if( pVendor->bit_mask & (productId_present) )
|
|
{
|
|
pDestVendorInfo ->pProductNumber = new H323_OCTETSTRING;
|
|
if( pDestVendorInfo ->pProductNumber == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pDestVendorInfo ->pProductNumber->wOctetStringLength =
|
|
(WORD)min(pVendor->productId.length, H323_MAX_PRODUCT_LENGTH - 1);
|
|
|
|
pDestVendorInfo ->pProductNumber->pOctetString = (BYTE*)
|
|
new char[pDestVendorInfo ->pProductNumber->wOctetStringLength + 1];
|
|
|
|
if( pDestVendorInfo ->pProductNumber->pOctetString == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
CopyMemory( (PVOID)pDestVendorInfo ->pProductNumber->pOctetString,
|
|
(PVOID)pVendor->productId.value,
|
|
pDestVendorInfo -> pProductNumber->wOctetStringLength );
|
|
|
|
pDestVendorInfo ->pProductNumber->pOctetString[
|
|
pDestVendorInfo ->pProductNumber->wOctetStringLength] = '\0';
|
|
}
|
|
|
|
if( pVendor->bit_mask & versionId_present )
|
|
{
|
|
pDestVendorInfo ->pVersionNumber = new H323_OCTETSTRING;
|
|
|
|
if( pDestVendorInfo ->pVersionNumber == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
pDestVendorInfo ->pVersionNumber->wOctetStringLength =
|
|
(WORD)min(pVendor->versionId.length, H323_MAX_VERSION_LENGTH - 1);
|
|
|
|
pDestVendorInfo ->pVersionNumber->pOctetString = (BYTE*)
|
|
new char[pDestVendorInfo ->pVersionNumber->wOctetStringLength+1];
|
|
|
|
if( pDestVendorInfo ->pVersionNumber->pOctetString == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
CopyMemory( (PVOID)pDestVendorInfo ->pVersionNumber->pOctetString,
|
|
(PVOID)pVendor->versionId.value,
|
|
pDestVendorInfo ->pVersionNumber->wOctetStringLength);
|
|
|
|
pDestVendorInfo ->pVersionNumber->pOctetString[
|
|
pDestVendorInfo ->pVersionNumber->wOctetStringLength] = '\0';
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
|
|
FreeVendorInfo( pDestVendorInfo );
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL
|
|
ParseNonStandardData(
|
|
OUT H323NonStandardData * dstNonStdData,
|
|
IN H225NonStandardParameter * srcNonStdData
|
|
)
|
|
{
|
|
H221NonStandard & h221NonStdData =
|
|
srcNonStdData ->nonStandardIdentifier.u.h221NonStandard;
|
|
|
|
if( srcNonStdData ->nonStandardIdentifier.choice ==
|
|
H225NonStandardIdentifier_h221NonStandard_chosen )
|
|
{
|
|
dstNonStdData ->bCountryCode = (BYTE)(h221NonStdData.t35CountryCode);
|
|
dstNonStdData ->bExtension = (BYTE)(h221NonStdData.t35Extension);
|
|
dstNonStdData ->wManufacturerCode = h221NonStdData.manufacturerCode;
|
|
}
|
|
|
|
dstNonStdData->sData.wOctetStringLength = (WORD)srcNonStdData->data.length;
|
|
|
|
dstNonStdData ->sData.pOctetString =
|
|
(BYTE *)new char[dstNonStdData ->sData.wOctetStringLength];
|
|
|
|
if( dstNonStdData -> sData.pOctetString == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory( (PVOID)dstNonStdData ->sData.pOctetString,
|
|
(PVOID)srcNonStdData ->data.value,
|
|
dstNonStdData ->sData.wOctetStringLength );
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
BOOL
|
|
AliasAddrToAliasNames(
|
|
OUT PH323_ALIASNAMES *ppTarget,
|
|
IN Setup_UUIE_sourceAddress *pSource
|
|
)
|
|
{
|
|
Setup_UUIE_sourceAddress *CurrentNode = NULL;
|
|
WORD wCount = 0;
|
|
int indexI = 0;
|
|
HRESULT hr;
|
|
|
|
*ppTarget = NULL;
|
|
|
|
for( CurrentNode = pSource; CurrentNode; CurrentNode = CurrentNode->next )
|
|
{
|
|
wCount++;
|
|
}
|
|
|
|
if( wCount == 0 )
|
|
{
|
|
return TRUE;
|
|
}
|
|
|
|
*ppTarget = new H323_ALIASNAMES;
|
|
if (*ppTarget == NULL)
|
|
{
|
|
return FALSE;
|
|
}
|
|
ZeroMemory( *ppTarget, sizeof(H323_ALIASNAMES) );
|
|
(*ppTarget)->pItems = new H323_ALIASITEM[wCount];
|
|
|
|
if( (*ppTarget)->pItems == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
for( CurrentNode = pSource; CurrentNode; CurrentNode = CurrentNode->next )
|
|
{
|
|
hr = AliasAddrToAliasItem( &((*ppTarget)->pItems[indexI]),
|
|
&(CurrentNode->value));
|
|
|
|
if( hr == E_OUTOFMEMORY )
|
|
{
|
|
WORD indexJ;
|
|
//Free everything that has been allocated so far...
|
|
for (indexJ = 0; indexJ < indexI; indexJ++)
|
|
{
|
|
delete (*ppTarget)->pItems[indexJ].pData;
|
|
}
|
|
goto cleanup;
|
|
}
|
|
else if( SUCCEEDED(hr) )
|
|
{
|
|
indexI++;
|
|
}
|
|
}
|
|
|
|
// any aliases?
|
|
if (indexI > 0)
|
|
{
|
|
// save number of aliases
|
|
(*ppTarget)->wCount = (WORD)indexI;
|
|
}
|
|
else
|
|
{
|
|
//free everything
|
|
delete (*ppTarget)->pItems;
|
|
delete (*ppTarget);
|
|
*ppTarget = NULL;
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
cleanup:
|
|
if( *ppTarget )
|
|
{
|
|
if( (*ppTarget)->pItems )
|
|
{
|
|
delete (*ppTarget)->pItems;
|
|
}
|
|
|
|
delete( *ppTarget );
|
|
*ppTarget = NULL;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
HRESULT
|
|
AliasAddrToAliasItem(
|
|
OUT PH323_ALIASITEM pAliasItem,
|
|
IN AliasAddress * pAliasAddr
|
|
)
|
|
{
|
|
WORD indexI;
|
|
|
|
if( pAliasItem == NULL )
|
|
{
|
|
return E_FAIL;
|
|
}
|
|
|
|
memset( (PVOID)pAliasItem, 0, sizeof(H323_ALIASITEM) );
|
|
|
|
switch( pAliasAddr->choice )
|
|
{
|
|
case h323_ID_chosen:
|
|
|
|
pAliasItem->wType = h323_ID_chosen;
|
|
|
|
if ((pAliasAddr->u.h323_ID.length != 0) &&
|
|
(pAliasAddr->u.h323_ID.value != NULL))
|
|
{
|
|
pAliasItem->wDataLength = (WORD)pAliasAddr->u.h323_ID.length;
|
|
pAliasItem->pData =
|
|
(LPWSTR)new char[(pAliasItem->wDataLength+1) * sizeof(WCHAR)];
|
|
|
|
if (pAliasItem->pData == NULL)
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
CopyMemory( (PVOID)pAliasItem->pData,
|
|
(PVOID)pAliasAddr->u.h323_ID.value,
|
|
pAliasItem->wDataLength * sizeof(WCHAR) );
|
|
pAliasItem->pData[pAliasItem->wDataLength] = L'\0';
|
|
}
|
|
break;
|
|
|
|
case e164_chosen:
|
|
|
|
pAliasItem->wType = e164_chosen;
|
|
pAliasItem->wDataLength = (WORD)strlen(pAliasAddr->u.e164);
|
|
pAliasItem->pData =
|
|
(LPWSTR)new char[(pAliasItem->wDataLength + 1) * sizeof(WCHAR)];
|
|
|
|
if( pAliasItem->pData == NULL )
|
|
{
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
//converting from byte to UNICODE
|
|
for (indexI = 0; indexI < pAliasItem->wDataLength; indexI++)
|
|
{
|
|
pAliasItem->pData[indexI] = (WCHAR)pAliasAddr->u.e164[indexI];
|
|
}
|
|
|
|
pAliasItem->pData[pAliasItem->wDataLength] = '\0';
|
|
break;
|
|
|
|
default:
|
|
return E_INVALIDARG;
|
|
} // switch
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void FreeFacilityASN(
|
|
IN Q931_FACILITY_ASN* pFacilityASN
|
|
)
|
|
{
|
|
//free non standard data
|
|
if( pFacilityASN->fNonStandardDataPresent != NULL )
|
|
{
|
|
delete pFacilityASN->nonStandardData.sData.pOctetString;
|
|
pFacilityASN->nonStandardData.sData.pOctetString =NULL;
|
|
}
|
|
|
|
if( pFacilityASN->pAlternativeAliasList != NULL )
|
|
{
|
|
FreeAliasNames(pFacilityASN->pAlternativeAliasList );
|
|
pFacilityASN->pAlternativeAliasList = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
void FreeAlertingASN(
|
|
IN Q931_ALERTING_ASN* pAlertingASN
|
|
)
|
|
{
|
|
FreeProceedingASN( (Q931_CALL_PROCEEDING_ASN*)pAlertingASN );
|
|
}
|
|
|
|
void FreeProceedingASN(
|
|
IN Q931_CALL_PROCEEDING_ASN* pProceedingASN
|
|
)
|
|
{
|
|
//free non standard data
|
|
if( pProceedingASN->fNonStandardDataPresent == TRUE )
|
|
{
|
|
delete pProceedingASN->nonStandardData.sData.pOctetString;
|
|
pProceedingASN->nonStandardData.sData.pOctetString = NULL;
|
|
}
|
|
|
|
if( pProceedingASN->fFastStartPresent &&pProceedingASN->pFastStart )
|
|
{
|
|
FreeFastStart( pProceedingASN->pFastStart );
|
|
}
|
|
}
|
|
|
|
|
|
void FreeSetupASN(
|
|
IN Q931_SETUP_ASN* pSetupASN
|
|
)
|
|
{
|
|
if( pSetupASN == NULL )
|
|
{
|
|
return;
|
|
}
|
|
|
|
if( pSetupASN->pExtensionAliasItem != NULL )
|
|
{
|
|
if( pSetupASN->pExtensionAliasItem -> pData != NULL )
|
|
{
|
|
delete pSetupASN->pExtensionAliasItem -> pData;
|
|
}
|
|
|
|
delete pSetupASN->pExtensionAliasItem;
|
|
}
|
|
|
|
if( pSetupASN->pExtraAliasList != NULL )
|
|
{
|
|
FreeAliasNames(pSetupASN->pExtraAliasList);
|
|
pSetupASN->pExtraAliasList = NULL;
|
|
}
|
|
|
|
if( pSetupASN->pCalleeAliasList != NULL )
|
|
{
|
|
FreeAliasNames(pSetupASN->pCalleeAliasList);
|
|
pSetupASN->pCalleeAliasList = NULL;
|
|
}
|
|
|
|
if( pSetupASN->pCallerAliasList != NULL )
|
|
{
|
|
FreeAliasNames(pSetupASN->pCallerAliasList);
|
|
pSetupASN->pCallerAliasList = NULL;
|
|
}
|
|
|
|
if( pSetupASN->fNonStandardDataPresent == TRUE )
|
|
{
|
|
delete pSetupASN->nonStandardData.sData.pOctetString;
|
|
}
|
|
|
|
if( pSetupASN->EndpointType.pVendorInfo != NULL )
|
|
{
|
|
FreeVendorInfo( pSetupASN->EndpointType.pVendorInfo );
|
|
}
|
|
|
|
if( pSetupASN->fFastStartPresent == TRUE )
|
|
{
|
|
if( pSetupASN->pFastStart != NULL )
|
|
{
|
|
FreeFastStart( pSetupASN->pFastStart );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void FreeConnectASN(
|
|
IN Q931_CONNECT_ASN *pConnectASN
|
|
)
|
|
{
|
|
if( pConnectASN != NULL )
|
|
{
|
|
// Cleanup any dynamically allocated fields within SetupASN
|
|
if (pConnectASN->nonStandardData.sData.pOctetString)
|
|
{
|
|
delete pConnectASN->nonStandardData.sData.pOctetString;
|
|
pConnectASN->nonStandardData.sData.pOctetString = NULL;
|
|
}
|
|
|
|
if( pConnectASN->EndpointType.pVendorInfo != NULL )
|
|
{
|
|
FreeVendorInfo( pConnectASN->EndpointType.pVendorInfo );
|
|
}
|
|
|
|
if( pConnectASN->fFastStartPresent == TRUE )
|
|
{
|
|
if( pConnectASN->pFastStart != NULL )
|
|
{
|
|
FreeFastStart( pConnectASN->pFastStart );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
FreeFastStart(
|
|
IN PH323_FASTSTART pFastStart
|
|
)
|
|
{
|
|
PH323_FASTSTART pTempFastStart;
|
|
|
|
while( pFastStart )
|
|
{
|
|
pTempFastStart = pFastStart -> next;
|
|
|
|
if(pFastStart -> value)
|
|
{
|
|
delete pFastStart -> value;
|
|
}
|
|
|
|
delete pFastStart;
|
|
|
|
pFastStart = pTempFastStart;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//FastStart is a plain linked list because it is exactly the same struct
|
|
//as defined by ASN.1. This allows to pass on the m_pFastStart member to
|
|
//the ASN encoder directly without any conversons
|
|
PH323_FASTSTART
|
|
CopyFastStart(
|
|
IN PSetup_UUIE_fastStart pSrcFastStart
|
|
)
|
|
{
|
|
PH323_FASTSTART pCurr, pHead = NULL, pTail = NULL;
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CopyFastStart entered." ));
|
|
|
|
while( pSrcFastStart )
|
|
{
|
|
pCurr = new H323_FASTSTART;
|
|
if( pCurr == NULL )
|
|
{
|
|
FreeFastStart( pHead );
|
|
return NULL;
|
|
}
|
|
|
|
pCurr -> next = NULL;
|
|
|
|
if( pHead == NULL )
|
|
{
|
|
pHead = pCurr;
|
|
}
|
|
else
|
|
{
|
|
pTail -> next = pCurr;
|
|
}
|
|
|
|
pTail = pCurr;
|
|
|
|
pCurr -> length = pSrcFastStart -> value.length;
|
|
pCurr -> value = (BYTE*)new char[pCurr -> length];
|
|
if( pCurr -> value == NULL )
|
|
{
|
|
FreeFastStart( pHead );
|
|
return NULL;
|
|
}
|
|
|
|
CopyMemory( (PVOID)pCurr -> value,
|
|
(PVOID)pSrcFastStart -> value.value,
|
|
pCurr -> length );
|
|
|
|
pSrcFastStart = pSrcFastStart->next;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "CopyFastStart exited." ));
|
|
return pHead;
|
|
}
|
|
|
|
|
|
void
|
|
FreeVendorInfo(
|
|
IN PH323_VENDORINFO pVendorInfo
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeVendorInfo entered." ));
|
|
|
|
if( pVendorInfo != NULL )
|
|
{
|
|
if( pVendorInfo ->pProductNumber != NULL )
|
|
{
|
|
if( pVendorInfo ->pProductNumber->pOctetString != NULL )
|
|
{
|
|
delete pVendorInfo ->pProductNumber->pOctetString;
|
|
}
|
|
|
|
delete pVendorInfo ->pProductNumber;
|
|
}
|
|
|
|
if( pVendorInfo ->pVersionNumber != NULL )
|
|
{
|
|
if( pVendorInfo ->pVersionNumber->pOctetString != NULL )
|
|
{
|
|
delete pVendorInfo ->pVersionNumber->pOctetString;
|
|
}
|
|
|
|
delete pVendorInfo ->pVersionNumber;
|
|
}
|
|
|
|
memset( (PVOID) pVendorInfo, 0, sizeof(H323_VENDORINFO) );
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeVendorInfo exited." ));
|
|
}
|
|
|
|
|
|
|
|
void
|
|
FreeAliasNames(
|
|
IN PH323_ALIASNAMES pSource
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeAliasNames entered." ));
|
|
|
|
if( pSource != NULL )
|
|
{
|
|
if( pSource->wCount != 0 )
|
|
{
|
|
// Free everything that has been allocated so far...
|
|
int indexI;
|
|
for( indexI = 0; indexI < pSource->wCount; indexI++ )
|
|
{
|
|
if( pSource->pItems[indexI].pPrefix != NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "delete prefix:%d.", indexI ));
|
|
delete pSource->pItems[indexI].pPrefix;
|
|
}
|
|
if( pSource->pItems[indexI].pData != NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "delete pdata:%d.", indexI ));
|
|
delete pSource->pItems[indexI].pData;
|
|
}
|
|
}
|
|
if( pSource->pItems != NULL )
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "delete pitems." ));
|
|
delete pSource->pItems;
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "outta loop." ));
|
|
delete pSource;
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeAliasNames exited." ));
|
|
}
|
|
|
|
|
|
void
|
|
FreeAliasItems(
|
|
IN PH323_ALIASNAMES pSource
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeAliasItems entered." ));
|
|
|
|
if( pSource != NULL )
|
|
{
|
|
if( pSource->wCount != 0 )
|
|
{
|
|
// Free everything that has been allocated so far...
|
|
int indexI;
|
|
for( indexI = 0; indexI < pSource->wCount; indexI++ )
|
|
{
|
|
if( pSource->pItems[indexI].pPrefix )
|
|
{
|
|
delete pSource->pItems[indexI].pPrefix;
|
|
}
|
|
if( pSource->pItems[indexI].pData )
|
|
{
|
|
delete pSource->pItems[indexI].pData;
|
|
}
|
|
}
|
|
if( pSource->pItems != NULL )
|
|
{
|
|
delete pSource->pItems;
|
|
pSource->pItems = NULL;
|
|
}
|
|
pSource->wCount = 0;
|
|
}
|
|
}
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "FreeAliasItems exited." ));
|
|
}
|
|
|
|
void
|
|
SetupTPKTHeader(
|
|
OUT BYTE * pbTpktHeader,
|
|
IN DWORD dwLength
|
|
)
|
|
{
|
|
dwLength += TPKT_HEADER_SIZE;
|
|
|
|
// TPKT requires that the packet size fit in two bytes.
|
|
_ASSERTE( dwLength < (1L << 16));
|
|
|
|
pbTpktHeader[0] = TPKT_VERSION;
|
|
pbTpktHeader[1] = 0;
|
|
pbTpktHeader[2] = (BYTE)(dwLength >> 8);
|
|
pbTpktHeader[3] = (BYTE)dwLength;
|
|
}
|
|
|
|
int
|
|
GetTpktLength(
|
|
IN char * pTpktHeader
|
|
)
|
|
{
|
|
BYTE * pbTempPtr = (BYTE*)pTpktHeader;
|
|
return (pbTempPtr[2] << 8) + pbTempPtr[3];
|
|
}
|
|
|
|
|
|
BOOL
|
|
AddAliasItem(
|
|
IN OUT PH323_ALIASNAMES pAliasNames,
|
|
IN BYTE* pbAliasName,
|
|
IN DWORD dwAliasSize,
|
|
IN WORD wType
|
|
)
|
|
{
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "AddAliasItem entered." ));
|
|
|
|
PH323_ALIASITEM pAliasItem;
|
|
PH323_ALIASITEM tempPtr = pAliasNames -> pItems;
|
|
|
|
pAliasNames -> pItems = (PH323_ALIASITEM)realloc( pAliasNames -> pItems,
|
|
sizeof(H323_ALIASITEM) * (pAliasNames->wCount+1) );
|
|
|
|
if( pAliasNames -> pItems == NULL )
|
|
{
|
|
//restore the old pointer in case enough memory was not available to
|
|
//expand the memory block
|
|
pAliasNames -> pItems = tempPtr;
|
|
return FALSE;
|
|
}
|
|
|
|
pAliasItem = &(pAliasNames -> pItems[pAliasNames->wCount]);
|
|
|
|
pAliasItem->pData = (WCHAR*)new char[dwAliasSize];
|
|
|
|
if( pAliasItem ->pData == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
pAliasNames->wCount++;
|
|
|
|
// transfer memory
|
|
CopyMemory((PVOID)pAliasItem ->pData,
|
|
pbAliasName,
|
|
dwAliasSize );
|
|
|
|
// complete alias
|
|
pAliasItem ->wType = wType;
|
|
pAliasItem ->wPrefixLength = 0;
|
|
pAliasItem ->pPrefix = NULL;
|
|
pAliasItem ->wDataLength = (WORD)wcslen(pAliasItem -> pData);
|
|
_ASSERTE( ((pAliasItem->wDataLength+1)*2) == (WORD)dwAliasSize );
|
|
|
|
|
|
H323DBG(( DEBUG_LEVEL_TRACE, "AddAliasItem exited." ));
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
void
|
|
FreeAddressAliases(
|
|
IN PSetup_UUIE_destinationAddress pAddr
|
|
)
|
|
{
|
|
PSetup_UUIE_destinationAddress pTempAddr;
|
|
|
|
while( pAddr )
|
|
{
|
|
pTempAddr = pAddr -> next;
|
|
if( pAddr ->value.choice == h323_ID_chosen )
|
|
{
|
|
if( pAddr -> value.u.h323_ID.value )
|
|
{
|
|
delete pAddr -> value.u.h323_ID.value;
|
|
}
|
|
}
|
|
|
|
delete pAddr;
|
|
pAddr = pTempAddr;
|
|
}
|
|
}
|
|
|
|
|
|
void CopyTransportAddress(
|
|
OUT TransportAddress& transportAddress,
|
|
IN PH323_ADDR pCalleeAddr
|
|
)
|
|
{
|
|
DWORD dwAddr = pCalleeAddr->Addr.IP_Binary.dwAddr;
|
|
|
|
transportAddress.choice = ipAddress_chosen;
|
|
transportAddress.u.ipAddress.ip.length = 4;
|
|
transportAddress.u.ipAddress.port
|
|
= pCalleeAddr->Addr.IP_Binary.wPort;
|
|
*(DWORD*)transportAddress.u.ipAddress.ip.value =
|
|
htonl( pCalleeAddr->Addr.IP_Binary.dwAddr );
|
|
//ReverseAddressAndCopy( transportAddress.u.ipAddress.ip.value, dwAddr);
|
|
}
|
|
|
|
|
|
void
|
|
AddressReverseAndCopy(
|
|
OUT DWORD * pdwAddr,
|
|
IN BYTE * addrValue
|
|
)
|
|
{
|
|
BYTE *addr = (BYTE *)(pdwAddr);
|
|
|
|
addr[3] = addrValue[0];
|
|
addr[2] = addrValue[1];
|
|
addr[1] = addrValue[2];
|
|
addr[0] = addrValue[3];
|
|
}
|
|
|
|
|
|
Setup_UUIE_sourceAddress *
|
|
SetMsgAddressAlias(
|
|
IN PH323_ALIASNAMES pAliasNames
|
|
)
|
|
{
|
|
PH323_ALIASITEM pAliasItem;
|
|
Setup_UUIE_sourceAddress *addressAlias, *currHead = NULL;
|
|
WORD wCount;
|
|
int indexI;
|
|
|
|
for( wCount=0; wCount < pAliasNames->wCount; wCount++ )
|
|
{
|
|
addressAlias = new Setup_UUIE_sourceAddress;
|
|
|
|
if( addressAlias == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
ZeroMemory( (PVOID)addressAlias, sizeof(Setup_UUIE_sourceAddress) );
|
|
|
|
addressAlias -> next = currHead;
|
|
currHead = addressAlias;
|
|
|
|
pAliasItem = &(pAliasNames->pItems[wCount]);
|
|
|
|
// then do the required memory copying.
|
|
if( pAliasItem -> wType == h323_ID_chosen )
|
|
{
|
|
addressAlias ->value.choice = h323_ID_chosen;
|
|
addressAlias ->value.u.h323_ID.length = pAliasItem -> wDataLength;
|
|
|
|
_ASSERTE( pAliasItem -> wDataLength );
|
|
|
|
addressAlias->value.u.h323_ID.value =
|
|
new WCHAR[pAliasItem -> wDataLength];
|
|
|
|
if( addressAlias->value.u.h323_ID.value == NULL )
|
|
{
|
|
goto cleanup;
|
|
}
|
|
|
|
CopyMemory((PVOID)addressAlias->value.u.h323_ID.value,
|
|
(PVOID)pAliasItem->pData,
|
|
pAliasItem -> wDataLength * sizeof(WCHAR) );
|
|
}
|
|
else if( pAliasItem -> wType == e164_chosen )
|
|
{
|
|
addressAlias ->value.choice = e164_chosen;
|
|
|
|
for( indexI =0; indexI < pAliasItem->wDataLength; indexI++ )
|
|
{
|
|
addressAlias->value.u.e164[indexI] = (BYTE)pAliasItem->pData[indexI];
|
|
}
|
|
|
|
addressAlias->value.u.e164[ pAliasItem->wDataLength ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
continue;
|
|
}
|
|
}
|
|
|
|
return currHead;
|
|
|
|
cleanup:
|
|
|
|
FreeAddressAliases( (PSetup_UUIE_destinationAddress)currHead );
|
|
return NULL;
|
|
}
|
|
|
|
|
|
/*BOOL
|
|
SetSetupMsgAddressAliasWithPrefix(
|
|
PH323_ALIASITEM pCallerAlias,
|
|
Setup_UUIE_sourceAddress *addressAlias
|
|
)
|
|
{
|
|
|
|
UINT indexI;
|
|
addressAlias -> next = NULL;
|
|
UINT uPrefixLength = pCallerAlias -> wPrefixLength;
|
|
UINT uDataLength = pCallerAlias -> wDataLength;
|
|
|
|
if(pCallerAlias->wType == h323_ID_chosen)
|
|
{
|
|
addressAlias->value.choice = h323_ID_chosen;
|
|
|
|
addressAlias->value.u.h323_ID.length =
|
|
(WORD)(uPrefixLength + uDataLength);
|
|
|
|
if(!addressAlias->value.u.h323_ID.length)
|
|
{
|
|
addressAlias->value.u.h323_ID.value = NULL;
|
|
//no data to copy
|
|
return TRUE;
|
|
}
|
|
|
|
addressAlias->value.u.h323_ID.value =
|
|
(WCHAR*)new char[(uPrefixLength + uDataLength) * sizeof(WCHAR)];
|
|
|
|
if( addressAlias->value.u.h323_ID.value == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
addressAlias->value.u.h323_ID.length = (WORD)(uDataLength+uPrefixLength);
|
|
|
|
if( uPrefixLength != 0 )
|
|
{
|
|
CopyMemory((PVOID)addressAlias->value.u.h323_ID.value,
|
|
(PVOID)pCallerAlias->pPrefix,
|
|
uPrefixLength * sizeof(WCHAR) );
|
|
}
|
|
|
|
if( uDataLength != 0 )
|
|
{
|
|
CopyMemory((PVOID)&addressAlias->value.u.h323_ID.value[uPrefixLength],
|
|
(PVOID)pCallerAlias->pData,
|
|
uDataLength * sizeof(WCHAR) );
|
|
}
|
|
}
|
|
else if(pCallerAlias->wType == e164_chosen )
|
|
{
|
|
addressAlias->value.choice = e164_chosen;
|
|
for (indexI = 0; indexI < uPrefixLength; ++indexI)
|
|
{
|
|
addressAlias->value.u.e164[indexI] = (BYTE)(pCallerAlias->pPrefix[indexI]);
|
|
}
|
|
for (indexI = 0; indexI < uDataLength; ++indexI)
|
|
{
|
|
addressAlias->value.u.e164[uPrefixLength + indexI] = (BYTE)(pCallerAlias->pData[indexI]);
|
|
}
|
|
for (indexI = uDataLength + uPrefixLength; indexI < sizeof(addressAlias->value.u.e164); ++indexI)
|
|
{
|
|
addressAlias->value.u.e164[indexI] = 0;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//un identified alias type
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}*/
|
|
|
|
|
|
void
|
|
CopyVendorInfo(
|
|
OUT VendorIdentifier* vendor
|
|
)
|
|
{
|
|
H323_VENDORINFO* pVendorInfo = g_pH323Line -> GetVendorInfo();
|
|
|
|
vendor->bit_mask = 0;
|
|
vendor->vendor.t35CountryCode = pVendorInfo ->bCountryCode;
|
|
vendor->vendor.t35Extension = pVendorInfo ->bExtension;
|
|
vendor->vendor.manufacturerCode = pVendorInfo ->wManufacturerCode;
|
|
if (pVendorInfo ->pProductNumber && pVendorInfo ->pProductNumber->pOctetString &&
|
|
pVendorInfo ->pProductNumber->wOctetStringLength)
|
|
{
|
|
vendor->bit_mask |= productId_present;
|
|
vendor->productId.length =
|
|
pVendorInfo ->pProductNumber->wOctetStringLength;
|
|
CopyMemory( (PVOID)&vendor->productId.value,
|
|
(PVOID)pVendorInfo ->pProductNumber->pOctetString,
|
|
pVendorInfo ->pProductNumber->wOctetStringLength);
|
|
}
|
|
if (pVendorInfo ->pVersionNumber && pVendorInfo ->pVersionNumber->pOctetString &&
|
|
pVendorInfo ->pVersionNumber->wOctetStringLength)
|
|
{
|
|
vendor->bit_mask |= versionId_present;
|
|
vendor->versionId.length =
|
|
pVendorInfo ->pVersionNumber->wOctetStringLength;
|
|
CopyMemory( (PVOID)&vendor->versionId.value,
|
|
(PVOID)pVendorInfo ->pVersionNumber->pOctetString,
|
|
pVendorInfo ->pVersionNumber->wOctetStringLength);
|
|
}
|
|
}
|
|
|
|
|
|
// check to see if entry is in list
|
|
BOOL
|
|
IsInList(
|
|
IN LIST_ENTRY * List,
|
|
IN LIST_ENTRY * Entry
|
|
)
|
|
{
|
|
LIST_ENTRY * Pos;
|
|
|
|
for( Pos = List -> Flink; Pos != List; Pos = Pos -> Flink )
|
|
{
|
|
if( Pos == Entry )
|
|
{
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
void WriteProtocolDiscriminator(
|
|
PBUFFERDESCR pBuf,
|
|
DWORD * dwPDULen
|
|
)
|
|
{
|
|
// space for the length byte
|
|
(*dwPDULen)++;
|
|
|
|
_ASSERTE( pBuf->dwLength > *dwPDULen );
|
|
|
|
*(PDTYPE *)pBuf->pbBuffer = Q931PDVALUE;
|
|
pBuf->pbBuffer += sizeof(PDTYPE);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Write a variable length Q931 call reference. See Q931 section 4.3.
|
|
//------------------------------------------------------------------------------
|
|
|
|
void
|
|
WriteCallReference(
|
|
PBUFFERDESCR pBuf,
|
|
WORD * pwCallReference,
|
|
DWORD * pdwPDULen
|
|
)
|
|
{
|
|
int indexI;
|
|
|
|
// space for the length byte
|
|
(*pdwPDULen) += 1+ sizeof(WORD);
|
|
|
|
_ASSERTE( pBuf->dwLength > *pdwPDULen );
|
|
|
|
// the length byte
|
|
*pBuf->pbBuffer = (BYTE)sizeof(WORD);
|
|
pBuf->pbBuffer++;
|
|
|
|
for (indexI = 0; indexI < sizeof(WORD); indexI++)
|
|
{
|
|
// Copy the value bytes to the buffer
|
|
*pBuf->pbBuffer =
|
|
(BYTE)(((*pwCallReference) >> ((sizeof(WORD) - 1 -indexI) * 8)) & 0xff);
|
|
pBuf->pbBuffer++;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
FreeCallForwardParams(
|
|
IN PCALLFORWARDPARAMS pCallForwardParams
|
|
)
|
|
{
|
|
LPFORWARDADDRESS pForwardedAddress, pTemp;
|
|
|
|
if( pCallForwardParams != NULL )
|
|
{
|
|
if( pCallForwardParams->divertedToAlias.pData != NULL )
|
|
{
|
|
delete pCallForwardParams->divertedToAlias.pData;
|
|
}
|
|
|
|
pForwardedAddress = pCallForwardParams->pForwardedAddresses;
|
|
while( pForwardedAddress )
|
|
{
|
|
pTemp = pForwardedAddress->next;
|
|
FreeForwardAddress( pForwardedAddress );
|
|
pForwardedAddress = pTemp;
|
|
}
|
|
|
|
delete pCallForwardParams;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
FreeForwardAddress(
|
|
IN LPFORWARDADDRESS pForwardAddress
|
|
)
|
|
{
|
|
if( pForwardAddress != NULL )
|
|
{
|
|
if( pForwardAddress->callerAlias.pData != NULL )
|
|
{
|
|
delete pForwardAddress->callerAlias.pData;
|
|
}
|
|
|
|
if( pForwardAddress->divertedToAlias.pData != NULL )
|
|
{
|
|
delete pForwardAddress->divertedToAlias.pData;
|
|
}
|
|
|
|
delete pForwardAddress;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//Replaces first alias item in the alias list with the alias address passed.
|
|
BOOL
|
|
MapAliasItem(
|
|
IN PH323_ALIASNAMES pCalleeAliasNames,
|
|
IN AliasAddress* pAliasAddress )
|
|
{
|
|
int iIndex;
|
|
|
|
_ASSERTE( pCalleeAliasNames && pCalleeAliasNames->pItems );
|
|
|
|
if( pCalleeAliasNames != NULL )
|
|
{
|
|
switch( pAliasAddress->choice )
|
|
{
|
|
case e164_chosen:
|
|
|
|
pCalleeAliasNames->pItems[0].wType = pAliasAddress->choice;
|
|
|
|
if( pCalleeAliasNames->pItems[0].pData != NULL )
|
|
{
|
|
delete pCalleeAliasNames->pItems[0].pData;
|
|
}
|
|
|
|
pCalleeAliasNames->pItems[0].wDataLength =
|
|
(WORD)strlen( pAliasAddress->u.e164 );
|
|
|
|
pCalleeAliasNames->pItems[0].pData =
|
|
new WCHAR[pCalleeAliasNames->pItems[0].wDataLength];
|
|
|
|
if( pCalleeAliasNames->pItems[0].pData == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
for( iIndex=0; iIndex < pCalleeAliasNames->pItems[0].wDataLength;
|
|
iIndex++ )
|
|
{
|
|
pCalleeAliasNames->pItems[0].pData[iIndex] =
|
|
pAliasAddress->u.e164[iIndex];
|
|
}
|
|
break;
|
|
|
|
case h323_ID_chosen:
|
|
|
|
pCalleeAliasNames->pItems[0].wType = pAliasAddress->choice;
|
|
|
|
if( pCalleeAliasNames->pItems[0].pData != NULL )
|
|
{
|
|
delete pCalleeAliasNames->pItems[0].pData;
|
|
}
|
|
|
|
pCalleeAliasNames->pItems[0].wDataLength =
|
|
(WORD)pAliasAddress->u.h323_ID.length;
|
|
|
|
pCalleeAliasNames->pItems[0].pData =
|
|
new WCHAR[pCalleeAliasNames->pItems[0].wDataLength];
|
|
|
|
if( pCalleeAliasNames->pItems[0].pData == NULL )
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
CopyMemory( (PVOID)pCalleeAliasNames->pItems[0].pData,
|
|
(PVOID)pAliasAddress->u.h323_ID.value,
|
|
pCalleeAliasNames->pItems[0].wDataLength );
|
|
|
|
break;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
//
|
|
//creates a new alias list and copies the first alias item from the given list.
|
|
//
|
|
PH323_ALIASNAMES
|
|
DuplicateAliasName(
|
|
PH323_ALIASNAMES pSrcAliasNames
|
|
)
|
|
{
|
|
PH323_ALIASNAMES pDestAliasNames = new H323_ALIASNAMES;
|
|
|
|
if( pDestAliasNames == NULL )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
ZeroMemory( pDestAliasNames, sizeof(H323_ALIASNAMES) );
|
|
|
|
if( !AddAliasItem(
|
|
pDestAliasNames,
|
|
pSrcAliasNames->pItems[0].pData,
|
|
pSrcAliasNames->pItems[0].wType ) )
|
|
{
|
|
delete pDestAliasNames;
|
|
return NULL;
|
|
}
|
|
|
|
return pDestAliasNames;
|
|
} |