static
RVOID
    processNewModule
    (
        rpcm_tag notifType,
        rSequence event
    )
{
    RPWCHAR nameW = NULL;
    RPCHAR nameA = NULL;
    RU8 fileHash[ CRYPTOLIB_HASH_SIZE ] = { 0 };
    RU64 size = 0;

    UNREFERENCED_PARAMETER( notifType );

    if( rpal_memory_isValid( event ) )
    {
        if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) ||
            rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) )
        {
            if( NULL != nameA &&
                !CryptoLib_hashFileA( nameA, fileHash, TRUE ) )
            {
                rpal_debug_info( "unable to fetch file hash for ident" );
            }

            if( NULL != nameW &&
                !CryptoLib_hashFileW( nameW, fileHash, TRUE ) )
            {
                rpal_debug_info( "unable to fetch file hash for ident" );
            }

            rSequence_getRU64( event, RP_TAGS_MEMORY_SIZE, &size );

            if( NULL != nameA )
            {
                processCodeIdentA( nameA, fileHash, size, event );
            }
            else if( NULL != nameW )
            {
                processCodeIdentW( nameW, fileHash, size, event );
            }
        }
    }
}
static
RVOID
    processFile
    (
        rSequence notif
    )
{
    RPCHAR fileA = NULL;
    RPWCHAR fileW = NULL;
    RPU8 fileContent = NULL;
    RU32 fileSize = 0;
    CryptoLib_Hash hash = { 0 };

    if( NULL != notif )
    {
        obsLib_resetSearchState( matcherA );
        obsLib_resetSearchState( matcherW );

        if( ( rSequence_getSTRINGA( notif, RP_TAGS_FILE_PATH, &fileA ) &&
              obsLib_setTargetBuffer( matcherA, 
                                      fileA, 
                                      ( rpal_string_strlen( fileA ) + 1 ) * sizeof( RCHAR ) ) &&
              obsLib_nextHit( matcherA, NULL, NULL ) ) ||
            ( rSequence_getSTRINGW( notif, RP_TAGS_FILE_PATH, &fileW ) &&
              obsLib_setTargetBuffer( matcherW, 
                                      fileW, 
                                      ( rpal_string_strlenw( fileW ) + 1 ) * sizeof( RWCHAR ) ) &&
              obsLib_nextHit( matcherW, NULL, NULL ) ) )
        {
            // This means it's a file of interest.
            if( ( NULL != fileA &&
                  ( ( DOCUMENT_MAX_SIZE >= rpal_file_getSize( fileA, TRUE ) &&
                      rpal_file_read( fileA, (RPVOID*)&fileContent, &fileSize, TRUE ) &&
                      CryptoLib_hash( fileContent, fileSize, &hash ) ) ||
                    CryptoLib_hashFileA( fileA, &hash, TRUE ) ) ) ||
                ( NULL != fileW &&
                  ( ( DOCUMENT_MAX_SIZE >= rpal_file_getSizew( fileW, TRUE ) &&
                      rpal_file_readw( fileW, (RPVOID*)&fileContent, &fileSize, TRUE ) &&
                      CryptoLib_hash( fileContent, fileSize, &hash ) ) ||
                    CryptoLib_hashFileW( fileW, &hash, TRUE ) ) ) )
            {
                // We acquired the hash, either by reading the entire file in memory
                // which we will use for caching, or if it was too big by hashing it
                // sequentially on disk.
                rSequence_unTaintRead( notif );
                rSequence_addBUFFER( notif, RP_TAGS_HASH, (RPU8)&hash, sizeof( hash ) );
                notifications_publish( RP_TAGS_NOTIFICATION_NEW_DOCUMENT, notif );
            }

            if( rMutex_lock( cacheMutex ) )
            {
                if( NULL == fileContent ||
                    !rSequence_addBUFFER( notif, RP_TAGS_FILE_CONTENT, fileContent, fileSize ) ||
                    !HbsRingBuffer_add( documentCache, notif ) )
                {
                    rSequence_free( notif );
                }

                rMutex_unlock( cacheMutex );
            }
            else
            {
                rSequence_free( notif );
            }

            if( NULL != fileContent )
            {
                rpal_memory_free( fileContent );
            }
        }
        else
        {
            rSequence_free( notif );
        }
    }
}
static
RVOID
    processHashedEvent
    (
        rpcm_tag notifType,
        rSequence event
    )
{
    RPWCHAR nameW = NULL;
    RPCHAR nameA = NULL;
    CryptoLib_Hash* pHash = NULL;
    CryptoLib_Hash localHash = { 0 };
    
    UNREFERENCED_PARAMETER( notifType );

    if( rpal_memory_isValid( event ) )
    {
        if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) ||
            rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) ||
            rSequence_getSTRINGA( event, RP_TAGS_DLL, &nameA ) ||
            rSequence_getSTRINGW( event, RP_TAGS_DLL, &nameW ) ||
            rSequence_getSTRINGA( event, RP_TAGS_EXECUTABLE, &nameA ) ||
            rSequence_getSTRINGW( event, RP_TAGS_EXECUTABLE, &nameW ) )
        {
            rSequence_getBUFFER( event, RP_TAGS_HASH, (RPU8*)&pHash, NULL );
            
            if( NULL != nameA )
            {
                if( NULL == pHash )
                {
                    if( _MAX_FILE_HASH_SIZE < rpal_file_getSize( nameA, TRUE ) )
                    {
                        rSequence_unTaintRead( event );
                        rSequence_addRU32( event, RP_TAGS_ERROR, RPAL_ERROR_FILE_TOO_LARGE );

                        if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) ||
                            rSequence_getSTRINGA( event, RP_TAGS_DLL, &nameA ) ||
                            rSequence_getSTRINGA( event, RP_TAGS_EXECUTABLE, &nameA ) )
                        {
                            // Find the name again with shortcircuit
                        }
                    }
                    else if( CryptoLib_hashFileA( nameA, &localHash, TRUE ) )
                    {
                        pHash = &localHash;
                    }
                }

                processCodeIdentA( nameA, pHash, 0, event );
            }
            else if( NULL != nameW )
            {
                if( NULL == pHash )
                {
                    if( _MAX_FILE_HASH_SIZE < rpal_file_getSizew( nameW, TRUE ) )
                    {
                        rSequence_unTaintRead( event );
                        rSequence_addRU32( event, RP_TAGS_ERROR, RPAL_ERROR_FILE_TOO_LARGE );

                        if( rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) ||
                            rSequence_getSTRINGW( event, RP_TAGS_DLL, &nameW ) ||
                            rSequence_getSTRINGW( event, RP_TAGS_EXECUTABLE, &nameW ) )
                        {
                            // Find the name again with shortcircuit
                        }
                    }
                    else if( CryptoLib_hashFileW( nameW, &localHash, TRUE ) )
                    {
                        pHash = &localHash;
                    }
                }

                processCodeIdentW( nameW, pHash, 0, event );
            }
        }
    }
}
static
RVOID
    processNewModule
    (
        rpcm_tag notifType,
        rSequence event
    )
{
    RPWCHAR nameW = NULL;
    RPCHAR nameA = NULL;
    CryptoLib_Hash fileHash = { 0 };
    RU64 size = 0;

    UNREFERENCED_PARAMETER( notifType );

    if( rpal_memory_isValid( event ) )
    {
        if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) ||
            rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) )
        {
            if( ( NULL != nameA &&
                _MAX_FILE_HASH_SIZE < rpal_file_getSize( nameA, TRUE ) ) ||
                ( NULL != nameW &&
                _MAX_FILE_HASH_SIZE < rpal_file_getSizew( nameW, TRUE ) ) )
            {
                // We already read from the event, but we will be careful.
                rSequence_unTaintRead( event );
                rSequence_addRU32( event, RP_TAGS_ERROR, RPAL_ERROR_FILE_TOO_LARGE );

                // We need to re-get the paths in case adding the error triggered
                // a change in the structure.
                if( rSequence_getSTRINGA( event, RP_TAGS_FILE_PATH, &nameA ) ||
                    rSequence_getSTRINGW( event, RP_TAGS_FILE_PATH, &nameW ) )
                {
                    // Find the name again with shortcircuit
                }
            }
            else
            {
                if( NULL != nameA &&
                    !CryptoLib_hashFileA( nameA, &fileHash, TRUE ) )
                {
                    rpal_debug_info( "unable to fetch file hash for ident" );
                }

                if( NULL != nameW &&
                    !CryptoLib_hashFileW( nameW, &fileHash, TRUE ) )
                {
                    rpal_debug_info( "unable to fetch file hash for ident" );
                }
            }

            rSequence_getRU64( event, RP_TAGS_MEMORY_SIZE, &size );

            if( NULL != nameA )
            {
                processCodeIdentA( nameA, &fileHash, size, event );
            }
            else if( NULL != nameW )
            {
                processCodeIdentW( nameW, &fileHash, size, event );
            }
        }
    }
}