static
RBOOL
    _longestString
    (
        RPCHAR begin,
        RU32 max,
        RU32* toSkip,
        RU32* longestLength,
        RBOOL* isUnicode
    )
{
    RBOOL isSuccess = FALSE;
    RU32 size = 0;
    RWCHAR unicodeLow = 0xFF;
    RWCHAR unicodeHigh = ( (RWCHAR)( -1 ) ^ 0xFF );
    RPWCHAR possibleChar = NULL;
    RU32 nSpecialChar = 0;

    if( NULL != begin &&
        NULL != toSkip &&
        NULL != longestLength &&
        NULL != isUnicode )
    {
        *longestLength = 0;
        *toSkip = 0;

        for( size = 0; size < max; size++ )
        {
            if( 0 == begin[ size ] )
            {
                break;
            }
            else if( !rpal_string_charIsAscii( begin[ size ] ) ||
                     size == max - 1 )
            {
                // We're only looking for clean C NULL-terminated strings
                *toSkip = size + 1;
                return FALSE;
            }
            else if( rpal_string_charIsAscii( begin[ size ] ) &&
                     !rpal_string_charIsAlphaNum( begin[ size ] ) )
            {
                nSpecialChar++;
                if( nSpecialChar > _MAX_SAMPLE_SPECIAL_CHAR )
                {
                    // Too many special characters, may be binary data
                    *toSkip = size + 1;
                    return FALSE;
                }
            }
        }

        if( 1 == size )
        {
            // This looks like it might be the first character of a unicode
            // string. So let's look for one.
            *isUnicode = TRUE;

            for( size = 0; size < max; size += sizeof( RWCHAR ) )
            {
                possibleChar = (RPWCHAR)( begin + size );

                if( 0 == *possibleChar )
                {
                    break;
                }
                else
                {
                    if( !rpal_string_charIsAscii( (RCHAR)( *possibleChar & unicodeLow ) ) ||
                        0 != ( *possibleChar & unicodeHigh ) ||
                        size == max - sizeof( RWCHAR ) )
                    {
                        *toSkip = size + 1;
                        return FALSE;
                    }
                }
            }
        }

        *longestLength = size + 1;
        *toSkip = *longestLength;
        isSuccess = TRUE;
    }

    return isSuccess;
}
RPRIVATE
RVOID
    _searchForStrings
    (
        rList stringsFound,
        rList searchStrings,
        RPU8 pBuff,
        RU64 size,
        RU64 baseAddr,
        RU32 minLength,
        RU32 maxLength
    )
{
    RPU8 pCurr;
    RPU8 pEnd;
    RPCHAR pStartStr = NULL;
    RBOOL isChar;
    RPU16 pwCurr;
    RPU16 pwEnd;
    RBOOL isWChar;
    RPWCHAR pwStartStr = NULL;
    RPWCHAR thisStrW = NULL;
    rSequence newFoundStr;

    pCurr = pBuff;
    pEnd = pBuff + size;

    // currently we only deal with NULL terminated strings
    // start with ascii strings...
    while( pCurr < pEnd )
    {
        isChar = rpal_string_isprint( *pCurr );

        if( NULL == pStartStr && isChar )  // found the begining of a string
        {
            pStartStr = (RPCHAR)pCurr;
        }
        else if( NULL != pStartStr && ( !isChar || 0 == *pCurr ) ) // found the end of a string
        {
            // is string NULL or Non-Ascii terminated
            if( 0 == *pCurr || !rpal_string_charIsAscii( *pCurr ) )
            {
                // Null terminate it so we can use it like a normal string
                *pCurr = 0;

                // strlen is really pCurr - pStartStr
                if( (RU32)( (RPCHAR)pCurr - pStartStr ) >= minLength &&
                    (RU32)( (RPCHAR)pCurr - pStartStr ) <= maxLength ) // is string long enough
                {
                    // convert string to wide char for comparision
                    if( NULL != ( thisStrW = rpal_string_atow( pStartStr ) ) )
                    {
                        if( _isStringInList( searchStrings, thisStrW ) && NULL != ( newFoundStr = rSequence_new() ) )
                        {
                            rSequence_addSTRINGW( newFoundStr, RP_TAGS_STRING, thisStrW );
                            rSequence_addRU64( newFoundStr, RP_TAGS_MEMORY_ADDRESS, baseAddr + ( (RPU8)pStartStr - pBuff ) );

                            if( !rList_addSEQUENCE( stringsFound, newFoundStr ) )
                            {
                                rSequence_free( newFoundStr );
                            }
                        }
                        rpal_memory_free( thisStrW );
                    }
                }
            }
            pStartStr = NULL;
        }
        pCurr++;
    }
    // Now look for Unicode strings
    pwCurr = (RPU16)pBuff;
    pwEnd = pwCurr + ( size / 2 );
    while( pwCurr < pwEnd )
    {
        isWChar = rpal_string_isprintW( *pwCurr );

        if( NULL == pwStartStr && isWChar )  // found the begining of a string
        {
            pwStartStr = (RPWCHAR)pwCurr;
        }
        else if( NULL != pwStartStr && ( !isWChar || 0 == *pwCurr ) ) // found the end of a string
        {
            // is string NULL terminated
            if( 0 == *pwCurr )
            {
                // wcslen is really pCurr - pStartStr
                if( (RU32)( (RPWCHAR)pwCurr - pwStartStr ) >= minLength &&
                    (RU32)( (RPWCHAR)pwCurr - pwStartStr ) <= maxLength ) // is string long enough
                {

                    if( _isStringInList( searchStrings, pwStartStr ) && NULL != ( newFoundStr = rSequence_new() ) )
                    {
                        rSequence_addSTRINGW( newFoundStr, RP_TAGS_STRING, pwStartStr );
                        rSequence_addRU64( newFoundStr, RP_TAGS_MEMORY_ADDRESS, baseAddr + ( (RPU8)pwStartStr - pBuff ) );

                        if( !rList_addSEQUENCE( stringsFound, newFoundStr ) )
                        {
                            rSequence_free( newFoundStr );
                        }
                    }
                }
            }
            pwStartStr = NULL;
        }
        pwCurr++;
    }
}