HRESULT CopyVolumeChunkToLocalFile()

in host/common/hostagenthelpers.cpp [1626:1811]


HRESULT CopyVolumeChunkToLocalFile( HANDLE handleVolume,
                                   char *pchFilename,
                                   SV_LONGLONG sv_longlongLength,
                                   SV_LONGLONG sv_longlongByteOffset,
                                   SV_LONGLONG *psv_longlongBytesRead )
{
    HRESULT hr = S_OK;
    char *pchBuffer = NULL;
    DWORD dwBytesRead = 0;
    DWORD dwBytesWritten = 0;
    DWORD dwLength = VOLUME_READ_CHUNK_SIZE;  //BUGBUG: Remove hardcoded value
    HANDLE handleFile = INVALID_HANDLE_VALUE;

    do
    {
        DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
        DebugPrintf( "ENTERED CopyVolumeChunkToLocalFile()...\n" );

        pchBuffer = new char[ dwLength ];
        if( NULL == pchBuffer )
        {
            hr = E_OUTOFMEMORY;
            DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
            DebugPrintf( hr, "FAILED CopyVolumeChunkToLocalFile()... hr = %08X\n", hr );
            break;
        }

        LONG lowpart = (LONG) sv_longlongByteOffset;
        LONG highpart = (LONG) ( sv_longlongByteOffset >> 32 );

        //BUGBUG: -1 should actually be INVALID_SET_FILE_POINTER.  See why it doesn't work
        //DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
        //DebugPrintf( "CALLING SetFilePointer()...\n" );
        if( -1 == SetFilePointer( handleVolume,
            lowpart,
            &( highpart ),
            FILE_BEGIN ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
            DebugPrintf( hr, "FAILED SetFilePointer()... hr = %08X\n", hr );
            break;
        }

        try
        {
            CreatePaths::createPathsAsNeeded(pchFilename);
        }
        catch (std::exception ex)
        {
            DebugPrintf(SV_LOG_ERROR, "%s failed: %s\n", FUNCTION_NAME, ex.what());
            hr = S_FALSE;
            break;
        }

        DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
        DebugPrintf( "CALLING CreateFile()...\n" );
        // PR#10815: Long Path support
        handleFile = SVCreateFile( pchFilename,
            GENERIC_WRITE,
            FILE_SHARE_WRITE | FILE_SHARE_READ,
            NULL,
            CREATE_ALWAYS,
            FILE_ATTRIBUTE_NORMAL,
            NULL );
        if( INVALID_HANDLE_VALUE == handleFile )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
            DebugPrintf( hr, "FAILED CreateFile(%s)... hr = %08X\n", pchFilename, hr );
            break;
        }

        //BUGBUG: Dump headers into the file here.

        //
        // Write SVD1 header
        //
        SVD_PREFIX prefix = { SVD_TAG_HEADER1, 1, 0 };
        if( !WriteFile( handleFile,
            &prefix,
            sizeof( prefix ),
            &dwBytesWritten, 
            NULL ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
            DebugPrintf( hr, "FAILED WriteFile()... hr = %08X\n", hr );
            break;
        }
        assert( sizeof( prefix ) == dwBytesWritten );

        SVD_HEADER1 header = { 0 };
        if( !WriteFile( handleFile,
            &header,
            sizeof( header ),
            &dwBytesWritten,
            NULL ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
            DebugPrintf( hr, "FAILED WriteFile()... hr = %08X\n", hr );
            break;
        }
        assert( sizeof( header ) == dwBytesWritten );

        //
        // Write single dirty block header
        //
        SVD_PREFIX drtdPrefix = { SVD_TAG_DIRTY_BLOCK_DATA, 1, 0 };
        if( !WriteFile( handleFile,
            &drtdPrefix,
            sizeof( drtdPrefix ),
            &dwBytesWritten,
            NULL ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
            DebugPrintf( hr, "FAILED WriteFile()... hr = %08X\n", hr );
            break;
        }
        assert( sizeof( prefix ) == dwBytesWritten );

        //
        // Write the data for DRTD
        //
        SVD_DIRTY_BLOCK block = { sv_longlongLength, sv_longlongByteOffset };
        if( !WriteFile( handleFile,
            &block,
            sizeof( block ),
            &dwBytesWritten,
            NULL ) )
        {
            hr = HRESULT_FROM_WIN32( GetLastError() );
            DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
            DebugPrintf( hr, "FAILED WriteFile()... hr = %08X\n", hr );
            break;
        }

        *psv_longlongBytesRead = 0;
        SV_LONGLONG sv_longlongBytesRemaining = sv_longlongLength;

        while( sv_longlongBytesRemaining > 0 )
        {
            dwLength = std::min( dwLength, (DWORD) sv_longlongBytesRemaining );

            if( FALSE == ReadFile( handleVolume, 
                pchBuffer,
                dwLength,
                &dwBytesRead,
                NULL ) )
            {
                hr = HRESULT_FROM_WIN32( GetLastError() );
                DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
                DebugPrintf( hr, "FAILED ReadFile()... hr = %08X\n", hr );
                break;
            }
            if( 0 == WriteFile( handleFile,
                pchBuffer,
                dwBytesRead,
                &dwBytesWritten,
                NULL ) )
            {
                hr = HRESULT_FROM_WIN32( GetLastError() );
                DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
                DebugPrintf( hr, "FAILED WriteFile()... hr = %08X\n", hr );
                break;
            }
            assert( dwBytesRead == dwBytesWritten );
            sv_longlongBytesRemaining -= dwBytesRead;
            *psv_longlongBytesRead += dwBytesRead;
        }
    }
    while( FALSE );

    delete[] pchBuffer;

    if( 0 == CloseHandle( handleFile ) )
    {
        hr = HRESULT_FROM_WIN32( GetLastError() );
        DebugPrintf( "@ LINE %d in FILE %s \n", __LINE__, __FILE__ );
        DebugPrintf( hr, "FAILED CloseHandle()... hr = %08X\n", hr );
    }

    return( hr );
}