⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 connectionmanagerservice.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
//
// Use of this source code is subject to the terms of the Microsoft shared
// source or premium shared source license agreement under which you licensed
// this source code. If you did not accept the terms of the license agreement,
// you are not authorized to use this source code. For the terms of the license,
// please see the license agreement between you and Microsoft or, if applicable,
// see the SOURCE.RTF on your install media or the root of your tools installation.
// THE SOURCE CODE IS PROVIDED "AS IS", WITH NO WARRANTIES.
//

#include "av_upnp.h"

using namespace av_upnp;

/////////////////////////////////////////////////////////////////////////////
// ConnectionManagerServiceImpl

ConnectionManagerServiceImpl::ConnectionManagerServiceImpl()
    : m_pIConnectionManager(NULL), m_pAVTS(NULL), m_pRCS(NULL)
{
    InitErrDescrips();
    InitToolkitErrs();
    InitDISPIDs();
}


ConnectionManagerServiceImpl::~ConnectionManagerServiceImpl()
{
    if(m_pIConnectionManager)
        const DWORD retUnadvise = m_pIConnectionManager->Unadvise(this);
        // if Unadvise() fails, we can do nothing but ignore.
}


DWORD ConnectionManagerServiceImpl::Init(/* [in] */ IConnectionManager*             pIConnectionManager,
                                         /* [in] */ AVTransportServiceImpl*         pAVTransportService,
                                         /* [in] */ RenderingControlServiceImpl*    pRenderingControlService)
{
    if(m_pIConnectionManager || m_pAVTS || m_pRCS)
        return ERROR_AV_ALREADY_INITED;

    if(!pIConnectionManager)
        return ERROR_AV_POINTER; // this class requires m_pIConnectionManager in all cases


    m_pIConnectionManager = pIConnectionManager;
    m_pAVTS               = pAVTransportService;
    m_pRCS                = pRenderingControlService;

    const DWORD retAdvise = m_pIConnectionManager->Advise(this);
    if(SUCCESS_AV != retAdvise)
        return retAdvise;

    return SUCCESS_AV;
}



//
// IUPnPEventSource
//

STDMETHODIMP ConnectionManagerServiceImpl::Advise(/*[in]*/ IUPnPEventSink* punkSubscriber)
{
    if(!punkSubscriber)
        return E_POINTER;

    return punkSubscriber->QueryInterface(IID_IUPnPEventSink, reinterpret_cast<void**>(&m_punkSubscriber));
}


STDMETHODIMP ConnectionManagerServiceImpl::Unadvise(/*[in]*/ IUPnPEventSink* punkSubscriber)
{
    if(m_punkSubscriber)
        m_punkSubscriber.Release();

    return S_OK;
}



//
// IUPnPService_ConnectionManager1
//

STDMETHODIMP ConnectionManagerServiceImpl::get_SourceProtocolInfo(BSTR* pSourceProtocolInfo)
{
    if(!pSourceProtocolInfo)
        return E_POINTER;

    const HRESULT hr = generic_get_ProtocolInfo(pSourceProtocolInfo, NULL);
    if(FAILED(hr))
        return hr; // generic_get_ProtocolInfo does error work, so we do not.

    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_SinkProtocolInfo(BSTR* pSinkProtocolInfo)
{
    if(!pSinkProtocolInfo)
        return E_POINTER;

    const HRESULT hr = generic_get_ProtocolInfo(NULL, pSinkProtocolInfo);
    if(FAILED(hr))
        return hr; // generic_get_ProtocolInfo does error work, so we do not.
  
    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_CurrentConnectionIDs(BSTR* pCurrentConnectionIDs)
{
    if(!pCurrentConnectionIDs)
        return E_POINTER;

    if(!m_pIConnectionManager)
        return m_ErrReport.ReportError(ERROR_AV_UPNP_ACTION_FAILED);


    wstring strConnectionIDs;

    wstring   strCurConnectionID;
    const int nltowLimit = 33;
    const int radixTen = 10;
    long      nCurConnectionID;

    strCurConnectionID.reserve(nltowLimit);


    if(SUCCESS_AV == m_pIConnectionManager->GetFirstConnectionID(&nCurConnectionID))
    {
        _ltow(nCurConnectionID, strCurConnectionID.get_buffer(), radixTen);
        if(!strConnectionIDs.append(strCurConnectionID))
            return m_ErrReport.ReportError(ERROR_AV_OOM);

        while(SUCCESS_AV == m_pIConnectionManager->GetNextConnectionID(&nCurConnectionID))
        {
            _itow(nCurConnectionID, strCurConnectionID.get_buffer(), radixTen);
            if(!strConnectionIDs.append(AVDCPListDelimiter))
                return m_ErrReport.ReportError(ERROR_AV_OOM);
            if(!strConnectionIDs.append(strCurConnectionID))
                return m_ErrReport.ReportError(ERROR_AV_OOM);
        }
    }
    else
    {
        // no connections, empty string
    }


    // Set out argument
    *pCurrentConnectionIDs = SysAllocString(strConnectionIDs);
    if(!*pCurrentConnectionIDs)
        return m_ErrReport.ReportError(ERROR_AV_OOM);

    return S_OK;
}


// get_A_ARG_TYPE_foo() methods are implemented only to satisfy upnp's devicehost, they are not used

STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ConnectionStatus(BSTR* pA_ARG_TYPE_ConnectionStatus)
{
    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ConnectionManager(BSTR* pA_ARG_TYPE_ConnectionManager)
{
    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_Direction(BSTR* pA_ARG_TYPE_Direction)
{
    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ProtocolInfo(BSTR* pA_ARG_TYPE_ProtocolInfo)
{
    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_ConnectionID(long* pA_ARG_TYPE_ConnectionID)
{
    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_AVTransportID(long* pA_ARG_TYPE_AVTransportID)
{
    return S_OK;
}


STDMETHODIMP ConnectionManagerServiceImpl::get_A_ARG_TYPE_RcsID(long* pA_ARG_TYPE_RcsID)
{
    return S_OK;
}



STDMETHODIMP ConnectionManagerServiceImpl::GetProtocolInfo(BSTR* pSource,
                                                           BSTR* pSink)
{
    if(!pSource || !pSink)
        return E_POINTER;

    return generic_get_ProtocolInfo(pSource, pSink); // generic_get_ProtocolInfo does error work, so we do not.
}


void ReleaseVirtualService(IVirtualService* pService)
{
    pService->Release();
}


STDMETHODIMP ConnectionManagerServiceImpl::PrepareForConnection(BSTR RemoteProtocolInfo,
                                                                BSTR PeerConnectionManager,
                                                                long PeerConnectionID,
                                                                BSTR Direction,
                                                                long* pConnectionID,
                                                                long* pAVTransportID,
                                                                long* pRcsID)
{
    if(!pConnectionID || !pAVTransportID || !pRcsID)
        return E_POINTER;

    if(!m_pIConnectionManager)
       return m_ErrReport.ReportError(ERROR_AV_UPNP_ACTION_FAILED);

    // Setup arguments for call to IConnectionManager
    DIRECTION   direction;
    wstring     strDirection;
    wstring     strRemoteProtocolInfo, strPeerConnectionManager;
    
    if(!strRemoteProtocolInfo.assign(RemoteProtocolInfo, SysStringLen(RemoteProtocolInfo)))
        return m_ErrReport.ReportError(ERROR_AV_OOM);
        
    if(!strPeerConnectionManager.assign(PeerConnectionManager, SysStringLen(PeerConnectionManager)))
        return m_ErrReport.ReportError(ERROR_AV_OOM);

    if(!strDirection.assign(Direction, SysStringLen(Direction)))
        return m_ErrReport.ReportError(ERROR_AV_OOM);
        
    if(details::Direction::Input == strDirection)
        direction = INPUT;
        
    else if(details::Direction::Output == strDirection)
        direction = OUTPUT;
    else
        return m_ErrReport.ReportError(ERROR_AV_UPNP_CM_INCOMPATIBLE_DIRECTION);

    // using smart pointers for virtual services to make sure they are release in case of any failure
    typedef ce::auto_xxx<IAVTransport*, void (*)(IVirtualService*), ReleaseVirtualService, NULL>        auto_av_transport_ptr;
    typedef ce::auto_xxx<IRenderingControl*, void (*)(IVirtualService*), ReleaseVirtualService, NULL>   auto_rendering_control_ptr;
    
    auto_av_transport_ptr       pIAVTransport;
    auto_rendering_control_ptr  pIRenderingControl;

    // Make the call
    const DWORD retPFC = m_pIConnectionManager->PrepareForConnection(strRemoteProtocolInfo,
                                                                     strPeerConnectionManager,
                                                                     PeerConnectionID,
                                                                     direction,
                                                                     pConnectionID,
                                                                     &pIAVTransport,
                                                                     &pIRenderingControl);
                                                                     
    if(retPFC != SUCCESS_AV)
        return m_ErrReport.ReportError(retPFC);
    
    // add entry to the map of virtual instance ids
    IDMap::iterator itIDs = m_mapIDs.insert(*pConnectionID, InstanceIDs());
    
    if(m_mapIDs.end() != itIDs)
    {
        // set ids to -1 until the services are successfully registered
        itIDs->second.AVTID = *pAVTransportID = -1;
        itIDs->second.RCID = *pRcsID = -1;
    }
    else
    {
        // cleanup after the incomplete connection
        ConnectionComplete(*pConnectionID);
                
        return m_ErrReport.ReportError(ERROR_AV_OOM);
    }

    // register virtual instance of AVTransport
    if(pIAVTransport)
    {
        if(!m_pAVTS)
        {
            DEBUGMSG(ZONE_AV_ERROR, (TEXT("IConnectionManager::PrepareForConnection or CreateConnection returned non-NULL pIAVTransport but")));
            DEBUGMSG(ZONE_AV_ERROR, (TEXT("\tConnectionManagerServiceImpl::Init was called with NULL for pAVTransportService")));
        }
        else
        {
            const DWORD retRI = m_pAVTS->RegisterInstance(pIAVTransport, pAVTransportID);
            
            if(SUCCESS_AV != retRI)
            {
                // cleanup after the incomplete connection
                ConnectionComplete(*pConnectionID);
                
                return m_ErrReport.ReportError(retRI);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -