#include "stdafx.h"

#if !defined(BITS_V12_ON_NT4)
#include "cerror.tmh"
#endif

void
CJobError::Set(
    CJob  *     job,
    ULONG       FileIndex,
    QMErrInfo * ErrInfo
    )
{
    m_ErrorSet  = true;
    m_job       = job;
    m_FileIndex = FileIndex;
    m_ErrInfo   = *ErrInfo;
}

void
CJobError::ClearError()
{
    m_ErrorSet  = false;
    m_job       = 0;
    m_FileIndex = 0;
    memset( &m_ErrInfo, 0, sizeof(m_ErrInfo));
}

CJobError::CJobError()
{
    ClearError();
}

CFileExternal *
CJobError::CreateFileExternal() const
{
    return m_job->_GetFileIndex( m_FileIndex )->CreateExternalInterface();
}


void
CJobError::GetOldInterfaceErrors(
    DWORD *pdwWin32Result,
    DWORD *pdwTransportResult ) const
{

    if (!IsErrorSet())
        {
        *pdwWin32Result = *pdwTransportResult = 0;
        return;
        }

    if ( GetStyle() == ERROR_STYLE_WIN32 )
        {
        *pdwWin32Result = GetCode();
        }
    else if ( GetStyle() == ERROR_STYLE_HRESULT &&
              ( (GetCode() & 0xffff0000) == 0x80070000 )  )
        {
        // If this is a win32 wrapped as an HRESULT, unwrap it.
        *pdwWin32Result = (GetCode() & 0x0000ffff);
        }

    if ( (GetSource() & COMPONENT_MASK) == COMPONENT_TRANS )
        {
        *pdwTransportResult = GetCode();
        }
    else
        {
        *pdwTransportResult = 0;
        }

}



HRESULT
CJobError::Serialize(
    HANDLE hFile
    ) const
{

    //
    // If this function changes, be sure that the metadata extension
    // constants are adequate.
    //


    if (!m_ErrorSet)
        {
        BOOL TrueBool = FALSE;
        SafeWriteFile( hFile, TrueBool );
        return S_OK;
        }

    BOOL FalseBool = TRUE;
    SafeWriteFile( hFile, FalseBool );
    SafeWriteFile( hFile, m_FileIndex );
    SafeWriteFile( hFile, m_ErrInfo.Code );
    SafeWriteFile( hFile, m_ErrInfo.Style );
    SafeWriteFile( hFile, m_ErrInfo.Source );
    SafeWriteFile( hFile, m_ErrInfo.result );
    SafeWriteFile( hFile, m_ErrInfo.Description );

    return S_OK;
}

void
CJobError::Unserialize(
    HANDLE hFile,
    CJob * job
    )
{
    BOOL ReadBool;
    SafeReadFile( hFile, &ReadBool );

    if (!ReadBool)
        {
        ClearError();
        return;
        }

    m_ErrorSet = true;
    SafeReadFile( hFile, &m_FileIndex );
    SafeReadFile( hFile, &m_ErrInfo.Code );
    SafeReadFile( hFile, &m_ErrInfo.Style );
    SafeReadFile( hFile, &m_ErrInfo.Source );
    SafeReadFile( hFile, &m_ErrInfo.result );
    SafeReadFile( hFile, &m_ErrInfo.Description );

    CFile * file = job->_GetFileIndex( m_FileIndex );
    if (!file)
        {
        throw ComError( HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER) );
        }

    m_job = job;
}

//------------------------------------------------------------------------

CJobErrorExternal::CJobErrorExternal() :
    m_Context(BG_ERROR_CONTEXT_NONE),
    m_Code(S_OK),
    m_FileExternal(NULL)
{
}

CJobErrorExternal::CJobErrorExternal( CJobError const * JobError ) :
    m_Context( BG_ERROR_CONTEXT_UNKNOWN ),
    m_Code( S_OK ),
    m_FileExternal( NULL )
{
    try
        {
        m_FileExternal = JobError->CreateFileExternal();

        // Map source into a context
        ERROR_SOURCE Source = JobError->GetSource();
        switch(Source & COMPONENT_MASK)
            {
            case COMPONENT_QMGR:
                switch(Source & SUBCOMP_MASK)
                    {
                    case SUBCOMP_QMGR_FILE:
                        m_Context = BG_ERROR_CONTEXT_LOCAL_FILE;
                        break;
                    case SUBCOMP_QMGR_QUEUE:
                        m_Context = BG_ERROR_CONTEXT_GENERAL_QUEUE_MANAGER;
                        break;
                    case SUBCOMP_QMGR_NOTIFY:
                        m_Context = BG_ERROR_CONTEXT_QUEUE_MANAGER_NOTIFICATION;
                        break;
                    default:
                        ASSERT(0);
                    }
                 break;
            case COMPONENT_TRANS:

                if (Source == SOURCE_HTTP_SERVER_APP)
                    {
                    m_Context = BG_ERROR_CONTEXT_REMOTE_APPLICATION;
                    }
                else
                    {
                    m_Context = BG_ERROR_CONTEXT_REMOTE_FILE;
                    }
                 break;
            default:
                m_Context = BG_ERROR_CONTEXT_NONE;
                break;
            }

        // map code into a HRESULT
        switch( JobError->GetStyle() )
            {
            case ERROR_STYLE_NONE:
                ASSERT(0);
                m_Code = JobError->GetCode();
                break;;
            case ERROR_STYLE_HRESULT:
                m_Code = JobError->GetCode();
                break;
            case ERROR_STYLE_WIN32:
                m_Code = HRESULT_FROM_WIN32( JobError->GetCode() );
                break;
            case ERROR_STYLE_HTTP:
                m_Code = MAKE_HRESULT( SEVERITY_ERROR, 0x19, JobError->GetCode() );
                break;
            default:
                ASSERT(0);
                m_Code = JobError->GetCode();
                break;
            }
        }
    catch (ComError err)
        {
        SafeRelease( m_FileExternal );
        }
}


CJobErrorExternal::~CJobErrorExternal()
{
    SafeRelease( m_FileExternal );
}

STDMETHODIMP
CJobErrorExternal::GetErrorInternal(
    BG_ERROR_CONTEXT *pContext,
    HRESULT *pCode
    )
{
    HRESULT Hr = S_OK;
    LogPublicApiBegin( "pContext %p, pCode %p", pContext, pCode );

    ASSERT( pContext );
    ASSERT( pCode );

    *pContext = m_Context;
    *pCode = m_Code;

    LogPublicApiEnd( "pContext %p(%u), pCode %p(%u)", pContext, pContext ? *pContext : 0, pCode, pCode ? *pCode : 0 );
    return Hr;
}

STDMETHODIMP
CJobErrorExternal::GetFileInternal(
    IBackgroundCopyFile ** pVal
    )
{
    HRESULT Hr = S_OK;
    LogPublicApiBegin( "pVal %p", pVal );

    if (!m_FileExternal)
        {
        *pVal = NULL;
        Hr = BG_E_FILE_NOT_AVAILABLE;
        }
    else
        {
        m_FileExternal->AddRef();
        *pVal = m_FileExternal;
        }

    LogPublicApiEnd( "pVal %p(%p)", pVal, *pVal );
    return Hr;
}

STDMETHODIMP
CJobErrorExternal::GetProtocolInternal( LPWSTR *pProtocol )
{
    HRESULT Hr = S_OK;
    LogPublicApiBegin( "pProtocol %p", pProtocol );

    *pProtocol = NULL;
    if ( !m_FileExternal )
        {
        Hr = BG_E_PROTOCOL_NOT_AVAILABLE;
        }
    else
        {
        Hr = m_FileExternal->GetRemoteName( pProtocol );
        if (SUCCEEDED(Hr))
            {
            // replace the : with a '\0'
            WCHAR *pColon = wcsstr( *pProtocol, L":" );

            // Shouldn't happen since the name should have been verified
            // during the AddFile.
            ASSERT( pColon );

            if ( pColon )
                {
                *pColon = L'\0';
                }
            }
        }

    LogPublicApiEnd( "pProtocol %p(%p,%S)", pProtocol, *pProtocol, (*pProtocol ? *pProtocol : L"NULL") );
    return Hr;
}

STDMETHODIMP
CJobErrorExternal::GetErrorDescriptionInternal(
    DWORD LanguageId,
    LPWSTR *pErrorDescription
    )
{
    HRESULT Hr = S_OK;
    LogPublicApiBegin( "LanguageId %u, pErrorDescription %p", LanguageId, pErrorDescription );
    Hr = g_Manager->GetErrorDescription( m_Code, LanguageId, pErrorDescription );
    LogPublicApiEnd( "LanguageId %u, pErrorDescription %p(%S)", LanguageId, pErrorDescription,
                     (*pErrorDescription ? *pErrorDescription : L"NULL") );
    return Hr;
}

STDMETHODIMP
CJobErrorExternal::GetErrorContextDescriptionInternal(
    DWORD LanguageId,
    LPWSTR *pContextDescription
    )
{
    HRESULT Hr = S_OK;
    LogPublicApiBegin( "LanguageId %u, pErrorDescription %p", LanguageId, pContextDescription );

    HRESULT hMappedError = BG_E_ERROR_CONTEXT_UNKNOWN;
    switch( m_Context )
        {
        case BG_ERROR_CONTEXT_NONE:
            hMappedError = BG_S_ERROR_CONTEXT_NONE;
            break;
        case BG_ERROR_CONTEXT_UNKNOWN:
            hMappedError = BG_E_ERROR_CONTEXT_UNKNOWN;
            break;
        case BG_ERROR_CONTEXT_GENERAL_QUEUE_MANAGER:
            hMappedError = BG_E_ERROR_CONTEXT_GENERAL_QUEUE_MANAGER;
            break;
        case BG_ERROR_CONTEXT_QUEUE_MANAGER_NOTIFICATION:
            hMappedError = BG_E_ERROR_CONTEXT_QUEUE_MANAGER_NOTIFICATION;
        case BG_ERROR_CONTEXT_LOCAL_FILE:
            hMappedError = BG_E_ERROR_CONTEXT_LOCAL_FILE;
            break;
        case BG_ERROR_CONTEXT_REMOTE_FILE:
            hMappedError = BG_E_ERROR_CONTEXT_REMOTE_FILE;
            break;
        case BG_ERROR_CONTEXT_GENERAL_TRANSPORT:
            hMappedError = BG_E_ERROR_CONTEXT_GENERAL_TRANSPORT;
            break;
        default:
            ASSERT(0);
            break;
        }

    Hr = g_Manager->GetErrorDescription( hMappedError, LanguageId, pContextDescription );

    LogPublicApiEnd( "LanguageId %u, pContextDescription %p(%S)",
                     LanguageId, pContextDescription,
                     (*pContextDescription ? *pContextDescription : L"NULL" ) );
    return Hr;
}