BOOL MULTISZ::AuxAppend()

in lib/multisz.cxx [162:234]


BOOL MULTISZ::AuxAppend( const WCHAR * pStr, UINT cbStr, BOOL fAddSlop )
{
    DBG_ASSERT( pStr != NULL );

    UINT cbThis = QueryCB();

    DBG_ASSERT( cbThis >= 2 );

    if( cbThis == 4 ) {

        //
        // It's empty, so start at the beginning.
        //

        cbThis = 0;

    } else {

        //
        // It's not empty, so back up over the final terminating NULL.
        //

        cbThis -= sizeof(WCHAR);

    }

    //
    //  Only resize when we have to.  When we do resize, we tack on
    //  some extra space to avoid extra reallocations.
    //
    //  Note: QuerySize returns the requested size of the string buffer,
    //        *not* the strlen of the buffer
    //

    //AcIncrement( CacMultiszAppend);
    
    // 
    // Check for the arithmetic overflow
    //
    // ( 2 * sizeof( WCHAR ) ) is for the double terminator
    //
    ULONGLONG cb64Required = (ULONGLONG)cbThis + cbStr + 2 * sizeof(WCHAR);
    if ( cb64Required > MAXULONG )
    {
        SetLastError( ERROR_ARITHMETIC_OVERFLOW );
        return FALSE;
    }
    if ( QuerySize() < (DWORD) cb64Required )
    {
        ULONGLONG cb64AllocSize = cb64Required + (fAddSlop ? STR_SLOP : 0 );
        // 
        // Check for the arithmetic overflow
        //
        if ( cb64AllocSize > MAXULONG )
        {
            SetLastError( ERROR_ARITHMETIC_OVERFLOW );
            return FALSE;
        }
        if ( !Resize( (DWORD) cb64AllocSize ) )
            return FALSE;
    }

    // copy the exact string and tack on the double terminator
    memcpy( (BYTE *) QueryPtr() + cbThis,
            pStr,
            cbStr);
    *(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr) = L'\0';
    *(WCHAR *)((BYTE *)QueryPtr() + cbThis + cbStr + sizeof(WCHAR) ) = L'\0';

    m_cchLen = CalcLength( (const WCHAR *)QueryPtr(), &m_cStrings );
    return TRUE;

} // MULTISZ::AuxAppend()