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

📄 cbtarget.cpp

📁 Windows CE 6.0 Server 源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:

static BOOL
LPCFinish()
{
    // signal the stopped flag
    g_Stopped = TRUE;
    TraceTag(ttidDevice,"%s: Stopping LPCInvokeRequestHandler Thread\n", __FUNCTION__);

    // wait for the listen thread exit
    if (g_hLPCThread)
    {
        DWORD dwWait;
        CancelCallbacks();
        dwWait = WaitForSingleObject(g_hLPCThread, 10000);
        if (dwWait == WAIT_TIMEOUT)
        {
            // This is to handle a couple of possible race conditions:
            // 1- The callback thread is blocked in LockList() while processing a callback
            // 2- CancelCallbacks() was called too early, before the callback thread had a chance to 
            //    call into the UPNPSVC process.
            // No harm done in either case, apart from the 10 second delay
            TraceTag(ttidError,"CallbackThread did not exit after 10 secs, abandoning..\n");
            CancelCallbacks();
        }
        CloseHandle(g_hLPCThread);
        g_hLPCThread = NULL;
        TraceTag(ttidDevice,"%s: Thread Handle Closed and Shutdown Signalled\n", __FUNCTION__);
    }

    // delete any remaining callbacks
    CallbackTarget::CleanupList();
    return TRUE;
    
}


BOOL
InitCallbackTarget(PCWSTR pszName, PUPNPCALLBACK pfCallback, PVOID pvContext, DWORD *phCallback)
{
    CallbackTarget *pNewCallback;
    TraceTag(ttidDevice, "%s: Adding Callback for %S\n", __FUNCTION__, pszName);

    if (!pszName || !pfCallback)
        return FALSE;


    // create a new callback target
    pNewCallback = NULL;
    CallbackTarget::LockList();
    if (!g_hLPCThread)
    {
        LPCInit();
    }
    if (g_hLPCThread && CallbackTarget::SearchByName(pszName) == NULL)
    {
        pNewCallback = new CallbackTarget(pszName, pfCallback, pvContext);
        if (pNewCallback)
        {
            if (pNewCallback->Name())
            {
                CallbackTarget::Link(pNewCallback);
                if (phCallback)
                   *phCallback = pNewCallback->Handle(); 
            }
            else
            {
                // init error
                delete pNewCallback;
                pNewCallback = NULL;
            }
        }
    }
    else if (g_hLPCThread)
        SetLastError(ERROR_FILE_EXISTS);
    else
        SetLastError(ERROR_OUTOFMEMORY);

    if (g_hLPCThread && IsListEmpty(&CallbackTarget::list))
    {
        // error case
        // there are no other targets on the list, so clean up the thread
        LPCFinish();
    }
    CallbackTarget::UnlockList();
    return (pNewCallback != NULL);
}


BOOL
StopCallbackTarget(PCWSTR pszName)
{
    CallbackTarget *pCallback;
    TraceTag(ttidDevice, "%s: Removing Callback for %S\n", __FUNCTION__, pszName);

    // delete the callback target
    CallbackTarget::LockList();
    pCallback = CallbackTarget::SearchByName(pszName);
    if (pCallback)
    {
        CallbackTarget::Unlink(pCallback);  // remove from list
        delete pCallback;
    }
    if (g_hLPCThread && IsListEmpty(&CallbackTarget::list))
    {
        // if this was the last target, clean up the callback thread
        LPCFinish();
    }
    CallbackTarget::UnlockList();
    return (pCallback != NULL);
}



const WCHAR c_szDefaultSOAPFault [] =
      L"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">\r\n"
      L"  <SOAP-ENV:Body>\r\n"
      L"    <SOAP-ENV:Fault>\r\n"
      L"      <faultcode>SOAP-ENV:Client</faultcode>\r\n"
      L"      <faultstring>UPnPError</faultstring>\r\n"
      L"      <detail>\r\n"
      L"        <UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\r\n"
      L"          <errorCode>501</errorCode>\r\n"
      L"          <errorDescription>Action Failed</errorDescription>\r\n"
      L"        </UPnPError>\r\n"
      L"      </detail>\r\n"
      L"    </SOAP-ENV:Fault>\r\n"
      L"  </SOAP-ENV:Body>\r\n"
      L"</SOAP-ENV:Envelope>";
      
const WCHAR c_szSOAPRespOK[] = L"<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" \r\n"
                            L"s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\r\n"
                            L" <s:Body>\r\n"
                            L"   <u:%sResponse xmlns:u=\"%s\"/>\r\n"
                            L" </s:Body>\r\n"
                            L"</s:Envelope>\r\n";
                            
SOAPHandler::SOAPHandler(DWORD hSource, PCWSTR pszUDN, PCWSTR pszServiceId, PCWSTR pszRequestXML)
    :   
    m_hSource(hSource),
    m_pszServiceType(NULL),
    m_pszUDN(pszUDN),
    m_pszServiceId(pszServiceId),
    m_pszRequestXML(pszRequestXML),
    m_pszAction(NULL),
    m_cParams(0),
    m_cArgsMax(0),
    m_pParams(NULL),
    m_fResponse(FALSE),
    m_bParsingBody(false),
    m_bParsingAction(false),
    m_bParsingArgument(false)
{
}


// Parse
BOOL SOAPHandler::Parse()
{
    HRESULT hr = E_UNEXPECTED;
    
    if(m_pReader->valid())
    {
        (*m_pReader)->putContentHandler(this);

        VARIANT vt;

        vt.vt = VT_BSTR;
        vt.bstrVal = SysAllocString(m_pszRequestXML);
        
        hr = (*m_pReader)->parse(vt);

        if(FAILED(hr))
            TraceTag(ttidError, "SAXXMLReader::parse returned error 0x%08x", hr);
        
        (*m_pReader)->putContentHandler(NULL);
        
        // avoid VariantClear to minimize dependency on oleaut32
        SysFreeString(vt.bstrVal);
    }
    else
        hr = m_pReader->Error();

    if(SUCCEEDED(hr))
    {
        // map the UPNPSERVICECONTROL pointers
        m_SvcCtl.pszRequestXML  = m_pszRequestXML;
        m_SvcCtl.pszUDN         = m_pszUDN;      
        m_SvcCtl.pszSID         = m_pszServiceId;
        m_SvcCtl.pszServiceType = m_pszServiceType;
        m_SvcCtl.pszAction      = m_pszAction;
        m_SvcCtl.cInArgs        = m_cParams;
        m_SvcCtl.pInArgs        = m_pParams;
        // back pointer for locating the ControlRequest from the SvcCtl
        m_SvcCtl.Reserved1 = this;      
        
        return true;
    }
    else
        return false;
}


static wchar_t* pwszEnvelopeElement =
    L"<http://schemas.xmlsoap.org/soap/envelope/>"
    L"<Envelope>";

static wchar_t* pwszBodyElement =
    L"<http://schemas.xmlsoap.org/soap/envelope/>"
    L"<Envelope>"
    L"<http://schemas.xmlsoap.org/soap/envelope/>"
    L"<Body>";

static wchar_t* pwszControlNamespace =
    L"urn:schemas-upnp-org:control-1-0";

// startElement
HRESULT STDMETHODCALLTYPE SOAPHandler::startElement( 
    /* [in] */ const wchar_t __RPC_FAR *pwchNamespaceUri,
    /* [in] */ int cchNamespaceUri,
    /* [in] */ const wchar_t __RPC_FAR *pwchLocalName,
    /* [in] */ int cchLocalName,
    /* [in] */ const wchar_t __RPC_FAR *pwchQName,
    /* [in] */ int cchQName,
    /* [in] */ ISAXAttributes __RPC_FAR *pAttributes)
{
    SAXContentHandler::startElement(pwchNamespaceUri, cchNamespaceUri, pwchLocalName, cchLocalName, pwchQName, cchQName, pAttributes);
    
    // Envelope element
    if(pwszEnvelopeElement == m_strFullElementName)
    {
        // verify that we understand the encoding scheme
        const wchar_t*  pwchEncodingStyle;
        int             cbEncodingStyle;

        if(FAILED(pAttributes->getValueFromName(pwchNamespaceUri, cchNamespaceUri, L"encodingStyle", 13, &pwchEncodingStyle, &cbEncodingStyle)) ||
           0 != wcsncmp(L"http://schemas.xmlsoap.org/soap/encoding/", pwchEncodingStyle, cbEncodingStyle))
        {
            return E_FAIL;
        }
    }

    // argument element - either no namespace (actions) or "control" namespace (QueryStateVariable)
    if(m_bParsingAction && !m_bParsingArgument && 0 == wcsncmp(pwchNamespaceUri, pwszControlNamespace, cchNamespaceUri))
    {
        // reallocate arguments array if needed
        if (m_cParams == m_cArgsMax)
        {
            UPNPPARAM *pParamsTmp;

            if(m_cArgsMax)
                m_cArgsMax *= 2;
            else
                m_cArgsMax = 2;
            
            if(!(pParamsTmp = new UPNPPARAM [m_cArgsMax]))
                return ERROR_OUTOFMEMORY;

            memcpy(pParamsTmp, m_pParams, m_cParams * sizeof(UPNPPARAM));

            delete [] m_pParams;
            m_pParams = pParamsTmp;
        }

        // copy argument name
        if(LPWSTR pszName = new WCHAR[cchLocalName + 1])
        {
            wcsncpy(pszName, pwchLocalName, cchLocalName);
            pszName[cchLocalName] = L'\x0';

            m_pParams[m_cParams].pszName = pszName;
        }
        else
            m_pParams[m_cParams].pszName = NULL;

        // argument value to be set later
        m_pParams[m_cParams].pszValue = NULL;

        m_strArgumentValue.resize(0);
        m_bParsingArgument = true;
        m_strArgumentElement = m_strFullElementName;
    }
    
    // action element
    if(m_bParsingBody && !m_bParsingAction)
    {
        // copy service type
        Assert(!m_pszServiceType);

        if(m_pszServiceType = new WCHAR[cchNamespaceUri + 1])
        {
            wcsncpy(m_pszServiceType, pwchNamespaceUri, cchNamespaceUri);
            m_pszServiceType[cchNamespaceUri] = L'\x0';
        }

        // copy action name
        Assert(!m_pszAction);

        if(m_pszAction = new WCHAR[cchLocalName + 1])
        {
            wcsncpy(m_pszAction, pwchLocalName, cchLocalName);
            m_pszAction[cchLocalName] = L'\x0';
        }
        
        m_bParsingAction = true;
        m_strActionElement = m_strFullElementName;
    }
    
    // Body element
    if(pwszBodyElement == m_strFullElementName)
        m_bParsingBody = true;

    return S_OK;
}


// endElement
HRESULT STDMETHODCALLTYPE SOAPHandler::endElement( 
    /* [in] */ const wchar_t __RPC_FAR *pwchNamespaceUri,
    /* [in] */ int cchNamespaceUri,
    /* [in] */ const wchar_t __RPC_FAR *pwchLocalName,
    /* [in] */ int cchLocalName,
    /* [in] */ const wchar_t __RPC_FAR *pwchQName,
    /* [in] */ int cchQName)
{
    // argument element
    if(m_strArgumentElement == m_strFullElementName)
    {
        // trim white spaces
        m_strArgumentValue.trim(L"\n\r\t ");
        
        // set argument value
        m_pParams[m_cParams].pszValue = StrDupW(m_strArgumentValue);
        
        // increment arguments count
        m_cParams++;
        
        m_bParsingArgument = false;
    }

    // action element
    if(m_strActionElement == m_strFullElementName)
        m_bParsingAction = false;

    // Body element
    if(pwszBodyElement == m_strFullElementName)
        m_bParsingBody = false;

    return SAXContentHandler::endElement(pwchNamespaceUri, cchNamespaceUri, pwchLocalName, cchLocalName, pwchQName, cchQName);
}


// characters
HRESULT STDMETHODCALLTYPE SOAPHandler::characters( 
    /* [in] */ const wchar_t __RPC_FAR *pwchChars,
    /* [in] */ int cchChars)
{
    if(m_strArgumentElement == m_strFullElementName)
        m_strArgumentValue.append(pwchChars, cchChars);

    return S_OK;
}


SOAPHandler::~SOAPHandler()
{
    DWORD i;
    m_SvcCtl.Reserved1 = NULL;  // this helps catch bogus callbacks after we're gone

    delete [] m_pszServiceType;
    delete [] m_pszAction;

    for (i=0; i < m_cParams; i++)
    {
        delete [] const_cast<LPWSTR>(m_pParams[i].pszName);
        delete [] const_cast<LPWSTR>(m_pParams[i].pszValue);
    }

    delete [] m_pParams;
}

BOOL
SOAPHandler::SetResponse(DWORD dwHttpStatus, PCWSTR pszResp)
{
    return (m_fResponse = (ERROR_SUCCESS == proxy.call(UPNP_IOCTL_SET_RAW_CONTROL_RESPONSE, m_hSource, dwHttpStatus, pszResp)));
}

//
// This method is called at the end of request handling to send a default response, if necessary
BOOL
SOAPHandler::Done(BOOL fRet)
{
    //
    // only set the response if the device implementation has not already called SetRawControlResponse
    //
    if (!m_fResponse)
    {
        if (fRet)
        {
            // default success response
            int cch = wcslen(m_pszAction) + wcslen(m_pszServiceType) + celems(c_szSOAPRespOK);
            PWCHAR pszRawResp = new WCHAR [cch];
            if (pszRawResp)
            {
                cch -= wsprintfW(pszRawResp,c_szSOAPRespOK,m_pszAction, m_pszServiceType);
                Assert(cch > 0);
                fRet = SetResponse(HTTP_STATUS_OK, pszRawResp);
                delete[] pszRawResp;
            }
            
        }
        else
        {
            // default failure response
            fRet = SetResponse(HTTP_STATUS_SERVER_ERROR, c_szDefaultSOAPFault);   
        }
        m_fResponse = TRUE;
    }
    else
        fRet = TRUE;
    return fRet;
}


//
// Called from the device implementation, while processing the UPnP control request
// Locate the owning ControlRequest from the UPNPSERVICECONTROL structure and
// set the response bytes that are to be returned to the control point.
//
BOOL
WINAPI
UpnpSetRawControlResponse(UPNPSERVICECONTROL *pSvcCtl, DWORD dwHttpStatus, PCWSTR pszResp)
{
    SOAPHandler *pSoapReq;
    BOOL fRet;
    __try {
        pSoapReq = (SOAPHandler *)pSvcCtl->Reserved1;
        // check that this is an actual ControlRequest
        if (&pSoapReq->m_SvcCtl != pSvcCtl)
        {
            // failed the sanity check
            Assert(FALSE);
            fRet = FALSE;
            __leave;
        }
        fRet = pSoapReq->SetResponse( dwHttpStatus, pszResp);
        
    }
    __except(EXCEPTION_EXECUTE_HANDLER)
    {
        SetLastError(ERROR_INVALID_PARAMETER);
        fRet = FALSE;
    }
    return fRet;
}



⌨️ 快捷键说明

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