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

📄 upnphost.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    // Format the parameters in the way the AutomationProxy wants them
    if (!FormatControlRequest(pSvcCtl, &ucreq))
        return FALSE;
    memset(&ucresp,0, sizeof(ucresp));

    hr = pServiceProxy->m_pap->ExecuteRequest(&ucreq, &ucresp);

    if (SUCCEEDED(hr))
    {
        hr = pServiceProxy->SetControlResponse(pSvcCtl, &ucresp);
        if (SUCCEEDED(hr))
        {
            fRet = TRUE;
        }
    }

    // cleanup
    ::FreeControlRequest(&ucreq);
    ::FreeControlResponse(&ucresp);

    // if we return false the UPNP service will return a generic fault
    // which is fine.
    return fRet;
}

//+---------------------------------------------------------------------------
//
//  Function:  InitCallback 
//
//  Purpose:    Invoked before any other device callbacks,
//              when the first subsribe or control request is received.
//
//  Arguments:
//
//  Returns:
//      TRUE if ok, FALSE otherwise
//
BOOL
DeviceProxy::InitCallback()
{
    TraceTag(ttidRegistrar, "DeviceProxy::InitRequest\n");

    // We need to have a pointer to the implementation object by now
    if (!m_pDeviceControl)
    {
        return FALSE;
    }

    m_pDeviceControl->Initialize(m_bstrXMLDesc, m_bstrDeviceId, m_bstrInitString);

    return TRUE;
}

//+---------------------------------------------------------------------------
//
//  Function: ShutdownCallback  
//
//  Purpose: The UPnP service wants to shutdown the device. This
//           is the last callback to be received, so this is where we free
//           the DeviceProxy object
//
//  Arguments:
//
//  Returns:
//      returns TRUE
//
BOOL
DeviceProxy::ShutdownCallback()
{
    TraceTag(ttidRegistrar, "DeviceProxy::ShutdowndRequest\n");
    RemoveDevice();
    RemoveFromList();
    delete this;
    return TRUE;
}

//+---------------------------------------------------------------------------
//
//  Function:   
//
//  Purpose:    Create and publish the UPnP device tree.
//
//  Arguments:
//      pszXMLDesc [in] XML device description template
//
//  Returns:
//      HRESULT
//
DeviceProxy::~DeviceProxy()
{
    ServiceProxy *pSvc = m_pServices;

    while (m_pServices)
    {
        LONG ref;
        pSvc = m_pServices;
        m_pServices = pSvc->m_pNext;
        pSvc->Shutdown();     // unadvise the event source
        ref = pSvc->Release(); // this should delete the service
        Assert(ref == 0);
    }
    SysFreeString(m_bstrDeviceId);
    SysFreeString(m_bstrInitString);
    SysFreeString(m_bstrResourcePath);
    SysFreeString(m_bstrUDN);
    SysFreeString(m_bstrXMLDesc);
    if (m_pDeviceControl)
    {
        m_pDeviceControl->Release();
    }
}

//
// ServiceProxy implementation
//

//+---------------------------------------------------------------------------
//
//  Function:   
//
//  Purpose:    Create and publish the UPnP device tree.
//
//  Arguments:
//      pszXMLDesc [in] XML device description template
//
//  Returns:
//      HRESULT
//
HRESULT
ServiceProxy::Initialize(PCWSTR pszUDN, PCWSTR pszSid, PCWSTR pszSCPD, IUnknown *pUPnPServiceObj)
{
    HRESULT hr;

    m_bstrSid = SysAllocString(pszSid);
    if (!m_bstrSid)
        return E_OUTOFMEMORY;

    m_bstrUDN = SysAllocString(pszUDN);
    if (!m_bstrUDN)
        return E_OUTOFMEMORY;

    hr = CUPnPAutomationProxy::CreateInstance(NULL, IID_IUPnPAutomationProxy, (void **)&m_pap);

    if (SUCCEEDED(hr))
    {
        hr = m_pap->Initialize(pUPnPServiceObj, (PWSTR)pszSCPD);
        m_pap->QueryInterface(IID_IUPnPServiceDescriptionInfo, (void **)&m_psdi);
        if (SUCCEEDED(hr))
        {
            // initialize eventing
            hr = pUPnPServiceObj->QueryInterface(IID_IUPnPEventSource,(void **)&m_pes);
            if (SUCCEEDED(hr))
            {
                hr = m_pes->Advise((IUPnPEventSink *)this);
                if (FAILED(hr))
                {
                    m_pes->Release();
                    m_pes = NULL;
                }
            }
        }
    }
    return hr;
}



//+---------------------------------------------------------------------------
//
//  Function:   
//
//  Purpose:    release the automation proxy and event source objects.
//             Can't put this code in the destructor, because this is where the refcount gets
//             decremented; the destructor gets called only when the refcount goes down to zero
//
//  Arguments:
//
//  Returns:
//      nothing
//
void
ServiceProxy::Shutdown()
{
    LONG cRef;
    if (m_pes)
    {
        m_pes->Unadvise((IUPnPEventSink *)this);
        m_pes->Release();
        m_pes = NULL;
    }
    if (m_pap)
    {
        if (m_psdi)
        {
            cRef = m_psdi->Release();
            m_psdi = NULL;
        }
        cRef = m_pap->Release();
        Assert(cRef == 0);
        m_pap = NULL;
    }
}

ServiceProxy::~ServiceProxy()
{
    Shutdown();     // won't do anything except perhaps in init error cases
    SysFreeString(m_bstrSid);
    SysFreeString(m_bstrUDN);
}



//+---------------------------------------------------------------------------
//
//  Member:     ServiceProxy::OnStateChanged
//
//  Purpose:    Notifies the eventing manager that the state of a service on
//              a hosted device has changed
//
//  Arguments:
//      cChanges        [in]    Number of state variables that have changed
//      rgdispidChanges [in]    Array of DISPIDs for those state variables
//
//  Returns:    S_OK if success, E_OUTOFMEMORY, or any other OLE interface
//              error code otherwise.
//  Notes:  
//
STDMETHODIMP ServiceProxy::OnStateChanged(DWORD cChanges,
                                                  DISPID rgdispidChanges[])
{
    return UpdateEventedVariables(TRUE, cChanges, rgdispidChanges); // TRUE -> update and send events
}

// Undocumented UPnP API
BOOL
WINAPI
UpnpUpdateEventedVariables(
    PCWSTR pszDeviceName,
    PCWSTR pszUDN,
    PCWSTR pszServiceId,
    DWORD nArgs,
    UPNPPARAM *rgArgs);


HRESULT ServiceProxy::UpdateEventedVariables(BOOL bSubmitEvent, DWORD cChanges, DISPID rgdispidChanges[])
{
    HRESULT     hr = S_OK;
    LPWSTR      szBody = NULL;
    DWORD       cVars, ivar;
    LPWSTR *    rgszNames;
    LPWSTR *    rgszTypes;
    VARIANT *   rgvarValues;

    AssertSz(m_bstrSid, "What? Did we not get initialized or something?");
    AssertSz(m_pap, "Automation proxy not initialized?");

    if (!m_pes)
    {
        hr = E_UNEXPECTED;
    }
    else if (cChanges && !rgdispidChanges)
    {
        hr = E_INVALIDARG;
    }
    else
    {
        if (!cChanges && !rgdispidChanges)
        {
            TraceTag(ttidEvents, "Sending all state variables for %S\n", m_bstrSid);
        }
        hr = m_pap->QueryStateVariablesByDispIds(cChanges, rgdispidChanges,
                                                  &cVars, &rgszNames,
                                                  &rgvarValues, &rgszTypes);
        if (SUCCEEDED(hr))
        {
            UPNPPARAM *rgParams = new UPNPPARAM[cVars];
            if (rgParams)
            {
                for (ivar = 0; ivar < cVars; ivar++)
                {
                    rgParams[ivar].pszName = rgszNames[ivar];

                    hr = VariantChangeType(rgvarValues+ivar, rgvarValues+ivar, 0, VT_BSTR);
                    if (FAILED(hr))
                    {
                        TraceError("OnStateChanged:Can't change arg type to BSTR\n", hr);
                        break;
                    }
                    rgParams[ivar].pszValue = V_BSTR(rgvarValues+ivar);
                }
                if (SUCCEEDED(hr))
                {
                    if (bSubmitEvent)
                    {
                        if(!UpnpSubmitPropertyEvent(m_pDevProxy->Name(), m_bstrUDN, m_bstrSid, cVars, rgParams))
                        {
                            TraceTag(ttidError,"OnStateChanged: UpnpSubmitPropertyEvent failed error=%d\n", GetLastError());
                            hr = HrFromLastWin32Error();
                        }
                    }
                    else
                    {
                        if(!UpnpUpdateEventedVariables(m_pDevProxy->Name(), m_bstrUDN, m_bstrSid, cVars, rgParams))
                        {
                            TraceTag(ttidError,"OnStateChanged: UpnpUpdateEventedVariables failed error=%d\n", GetLastError());
                            hr = HrFromLastWin32Error();
                        }
                    }
                }

                delete [] rgParams;
            }
            else
                hr = E_OUTOFMEMORY;



            for (ivar = 0; ivar < cVars; ivar++)
            {
                CoTaskMemFree(rgszTypes[ivar]);
                CoTaskMemFree(rgszNames[ivar]);
                VariantClear(&rgvarValues[ivar]);
            }

            CoTaskMemFree(rgvarValues);
            CoTaskMemFree(rgszTypes);
            CoTaskMemFree(rgszNames);
        }
    }

    TraceError("ServiceProxy::OnStateChanged", hr);
    return hr;
}

//+---------------------------------------------------------------------------
//
//  Member:     CUPnPEventingManager::OnStateChangedSafe
//
//  Purpose:    Same as OnStateChanged, except this is for VB users that need
//              to pass the array of DISPIDs in a SafeArray.
//
//  Arguments:
//      psa     [in]    SafeArray of DISPIDs that have changed
//
//  Returns:    Same as OnStateChanged
//
//  Author:     danielwe   2000/09/21
//
//  Notes:  From Whistler
//
STDMETHODIMP ServiceProxy::OnStateChangedSafe(VARIANT varsadispidChanges)
{
    HRESULT         hr = S_OK;
    SAFEARRAY *psa = V_ARRAY(&varsadispidChanges);
    DISPID HUGEP *  rgdispids;

    // Get a pointer to the elements of the array.
    hr = SafeArrayAccessData(psa, (void HUGEP**)&rgdispids);
    if (SUCCEEDED(hr))
    {
        hr = OnStateChanged(psa->rgsabound[0].cElements, rgdispids);
        SafeArrayUnaccessData(psa);
    }

    TraceError("CUPnPEventingManager::OnStateChangedSafe", hr);
    return hr;
}

//+---------------------------------------------------------------------------
//
//  Function:   
//
//  Purpose:    Create and publish the UPnP device tree.
//
//  Arguments:
//      pszXMLDesc [in] XML device description template
//
//  Returns:
//      HRESULT
//
HRESULT
ServiceProxy::SetControlResponse(UPNPSERVICECONTROL *pSvcCtl, UPNP_CONTROL_RESPONSE *pucresp)
{
    HRESULT hr = S_OK;

    if (pucresp->fSucceeded)
    {
        UPNPPARAM *pParams;
        DWORD i, cOutputArgs = 0;
        VARIANT *pvar;
        BSTR  * rgbstrNames = NULL;
        BSTR  * rgbstrTypes = NULL;

        // success response
        if (!pucresp->ucrData.Success.cOutputArgs)
            return S_OK;    // the UPNP service will return a default success response

        pParams = new UPNPPARAM [pucresp->ucrData.Success.cOutputArgs];
        if (!pParams)
            return E_OUTOFMEMORY;

        Assert(m_psdi);
        if (wcscmp(pSvcCtl->pszAction, L"QueryStateVariable") == 0)
        {
            pParams[0].pszName = L"return";
            pvar = &pucresp->ucrData.Success.rgvarOutputArgs[0];
            hr = VariantChangeType(pvar,pvar,0,VT_BSTR);
            if (SUCCEEDED(hr))
            {
                pParams[0].pszValue = V_BSTR(pvar);
                cOutputArgs = 1;
            }
        }
        else
        {
            // one or more output vars need to be specified
            // unfortunately we don't have the var names in pucresp (that would be too easy)
            // so they need to be determined
            hr = m_psdi->GetOutputArgumentNamesAndTypes(
                    pucresp->bstrActionName,
                    &cOutputArgs,
                    &rgbstrNames,
                    &rgbstrTypes);

            if (SUCCEEDED(hr))
            {
                Assert(cOutputArgs == pucresp->ucrData.Success.cOutputArgs);
                
                for (i=0; i < cOutputArgs; i++)
                {
                    pParams[i].pszName = rgbstrNames[i];
                    pvar = &pucresp->ucrData.Success.rgvarOutputArgs[i];
                    hr = VariantChangeType(pvar, pvar, 0, VT_BSTR);
                    if (FAILED(hr))
                    {
                        TraceError("SetControlResponse:Can't change arg type to BSTR\n", hr);
                        break;
                    }
                    pParams[i].pszValue = V_BSTR(pvar);
                }

            }
        }
        if (SUCCEEDED(hr))
        {
            if (!UpnpSetControlResponse(pSvcCtl, cOutputArgs, pParams))
            {
                TraceTag(ttidError, "UpnpSetControlResponse returned error %d for %S\n",
                    GetLastError(), pSvcCtl->pszAction);

                hr = HrFromLastWin32Error();
            }
        }
        // Clean up.
        if (rgbstrNames)
        {
            for (i = 0; i < cOutputArgs; i++)
            {
                SysFreeString(rgbstrNames[i]);
                rgbstrNames[i] = NULL;
                SysFreeString(rgbstrTypes[i]);
                rgbstrTypes[i] = NULL;
            }
            CoTaskMemFree(rgbstrNames);
            rgbstrNames = NULL;
            CoTaskMemFree(rgbstrTypes);
            rgbstrTypes = NULL;
        }
        delete [] pParams;

    }
    else
    {
        int errCode = 501;  // Action failed
        Assert(pucresp->ucrData.Fault.bstrUPnPErrorCode);
        if (pucresp->ucrData.Fault.bstrUPnPErrorCode)
        {
            errCode = _wtol(pucresp->ucrData.Fault.bstrUPnPErrorCode);
        }
        // error response
        if (!UpnpSetErrorResponse(pSvcCtl, errCode, pucresp->ucrData.Fault.bstrUPnPErrorString))
        {
            TraceTag(ttidError, "UpnpSetControlResponse returned error %d for %S\n",
                GetLastError(), pSvcCtl->pszAction);

            hr = HrFromLastWin32Error();
        }
    }
    return hr;
}

⌨️ 快捷键说明

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