📄 service.cpp
字号:
//
// 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 "pch.h"
#pragma hdrstop
#include "Service.h"
#include "com_macros.h"
#include "HttpRequest.h"
#include "safe_array.hxx"
// ServiceImplWrapper::ServiceImplWrapper
Service::ServiceImplWrapper::ServiceImplWrapper(
LPCWSTR pwszUniqueDeviceName,
LPCWSTR pwszServiceType,
LPCWSTR pwszDescriptionURL,
LPCWSTR pwszControlURL,
LPCWSTR pwszEventsURL,
UINT nLifeTime,
ce::string* pstrBaseURL)
: m_bInitiated(false),
m_pstrBaseURL(pstrBaseURL),
m_ServiceImpl(pwszUniqueDeviceName,
pwszServiceType,
pwszDescriptionURL,
pwszControlURL,
pwszEventsURL,
nLifeTime)
{
}
// InitServiceImpl
void Service::ServiceImplWrapper::Init()
{
m_ServiceImpl.Init(*m_pstrBaseURL);
m_bInitiated = true;
}
///////////////////////////////////
// IUPnPService methods
// QueryStateVariable
STDMETHODIMP Service::QueryStateVariable(
/*[in]*/ BSTR bstrVariableName,
/*[out, retval]*/ VARIANT *pValue)
{
HRESULT hr;
switch(hr = m_pServiceImpl->QueryStateVariable(bstrVariableName, pValue))
{
case DISP_E_UNKNOWNNAME:
case DISP_E_MEMBERNOTFOUND: return UPNP_E_INVALID_VARIABLE;
case HRESULT_FROM_WIN32(ERROR_INTERNET_TIMEOUT):
return UPNP_E_DEVICE_TIMEOUT;
default: return hr;
}
}
// InvokeAction
STDMETHODIMP Service::InvokeAction(
/*[in]*/ BSTR bstrActionName,
/*[in]*/ VARIANT vInActionArgs,
/*[in, out]*/ VARIANT * pvOutActionArgs,
/*[out, retval]*/ VARIANT *pvRetVal)
{
HRESULT hr;
switch(hr = InvokeActionImpl(bstrActionName, vInActionArgs, pvOutActionArgs, pvRetVal))
{
case DISP_E_UNKNOWNNAME:
case DISP_E_MEMBERNOTFOUND:
return UPNP_E_INVALID_ACTION;
case DISP_E_TYPEMISMATCH:
case DISP_E_PARAMNOTFOUND:
return UPNP_E_INVALID_ARGUMENTS;
case HRESULT_FROM_WIN32(ERROR_INTERNET_TIMEOUT):
return UPNP_E_DEVICE_TIMEOUT;
default:
return hr;
}
}
// InvokeActionImpl
HRESULT Service::InvokeActionImpl(
/*[in]*/ BSTR bstrActionName,
/*[in]*/ VARIANT vInActionArgs,
/*[in, out]*/ VARIANT * pvOutActionArgs,
/*[out, retval]*/ VARIANT *pvRetVal)
{
DISPID dispid;
int nOutArgs, nInArgs, i, ubound;
unsigned int position;
HRESULT hr;
UINT uArgErr;
if(FAILED(hr = m_pServiceImpl->GetIDsOfNames(&bstrActionName, 1, &dispid)))
return hr;
ce::safe_array<ce::variant, VT_VARIANT> arrayInArguments;
ce::safe_array<ce::variant, VT_VARIANT> arrayOutArguments;
VARIANT *pvarInArgs;
// dereference [in] arguments variant
for (pvarInArgs = &vInActionArgs; pvarInArgs->vt == (VT_VARIANT | VT_BYREF); pvarInArgs = pvarInArgs->pvarVal);
// attach to [in] arguments array
if(pvarInArgs->vt == (VT_ARRAY | VT_VARIANT))
{
arrayInArguments.attach(pvarInArgs->parray);
}
else
if(pvarInArgs->vt == (VT_BYREF | VT_ARRAY | VT_VARIANT))
{
CHECK_POINTER(pvarInArgs->pparray);
arrayInArguments.attach(*pvarInArgs->pparray);
}
else
return DISP_E_TYPEMISMATCH;
nOutArgs = m_pServiceImpl->GetActionOutArgumentsCount(dispid);
if(nOutArgs)
{
CHECK_POINTER(pvOutActionArgs);
// create [out] arguments safe array
arrayOutArguments.create(nOutArgs);
}
nInArgs = arrayInArguments.size();
DISPPARAMS DispParams;
ce::variant* rgvarg;
DispParams.cArgs = nInArgs + nOutArgs;
DispParams.cNamedArgs = 0;
DispParams.rgdispidNamedArgs = NULL;
rgvarg = new ce::variant[DispParams.cArgs];
if(!rgvarg)
{
hr = E_OUTOFMEMORY;
goto Finish;
}
DispParams.rgvarg = &rgvarg[0];
// argument in DISPPARAM are in reverse order
position = DispParams.cArgs - 1;
for(i = arrayInArguments.lbound(), ubound = arrayInArguments.ubound(); i <= ubound; ++i, --position)
{
Assert(position >= 0 && position < DispParams.cArgs);
rgvarg[position] = arrayInArguments[i];
}
if(nOutArgs)
{
// lock array so that it is safe to get pointers to elements - safe_array will unlock in dtor
arrayOutArguments.lock();
for(i = arrayOutArguments.lbound(), ubound = arrayOutArguments.ubound(); i <= ubound; ++i, --position)
{
Assert(position >= 0 && position < DispParams.cArgs);
rgvarg[position].vt = VT_VARIANT | VT_BYREF;
rgvarg[position].pvarVal = &arrayOutArguments[i];
}
}
Assert(position == -1);
hr = m_pServiceImpl->Invoke(dispid, DISPATCH_METHOD, &DispParams, pvRetVal, NULL, &uArgErr);
if(rgvarg)
delete[] rgvarg;
if(nOutArgs)
{
arrayOutArguments.unlock();
if(SUCCEEDED(hr))
{
VariantClear(pvOutActionArgs);
pvOutActionArgs->vt = VT_ARRAY | VT_VARIANT;
pvOutActionArgs->parray = arrayOutArguments.detach();
}
}
Finish:
return hr;
}
// ServiceTypeIdentifier
STDMETHODIMP Service::get_ServiceTypeIdentifier(/*[out, retval]*/ BSTR *pVal)
{
CHECK_OUT_POINTER(pVal);
*pVal = SysAllocString(m_strType);
if(pVal)
return S_OK;
else
return E_OUTOFMEMORY;
}
// AddCallback
STDMETHODIMP Service::AddCallback(/*[in]*/ IUnknown *punkCallback)
{
return m_pServiceImpl->AddCallback(this, punkCallback, NULL);
}
// Id
STDMETHODIMP Service::get_Id(/*[out, retval]*/ BSTR *pVal)
{
CHECK_OUT_POINTER(pVal);
*pVal = SysAllocString(m_strId);
if(pVal)
return S_OK;
else
return E_OUTOFMEMORY;
}
// LastTransportStatus
STDMETHODIMP Service::get_LastTransportStatus(/*[out, retval]*/ long* plValue)
{
CHECK_POINTER(plValue);
*plValue = m_pServiceImpl->GetLastTransportStatus();
return S_OK;
}
///////////////////////////////////
// IUPnPServiceCallbackPrivate
// AddTransientCallback
STDMETHODIMP Service::AddTransientCallback(/*[in]*/ IUnknown* pUnkCallback, /*[out]*/ DWORD *pdwCookie)
{
return m_pServiceImpl->AddCallback(this, pUnkCallback, pdwCookie);
}
// RemoveTransientCallback
STDMETHODIMP Service::RemoveTransientCallback(/*[in]*/ DWORD dwCookie)
{
return m_pServiceImpl->RemoveCallback(dwCookie);
}
///////////////////////////////////
// IDispatch
// GetIDsOfNames
STDMETHODIMP Service::GetIDsOfNames(
/* [in] */ REFIID riid,
/* [size_is][in] */ LPOLESTR __RPC_FAR *rgszNames,
/* [in] */ UINT cNames,
/* [in] */ LCID lcid,
/* [size_is][out] */ DISPID __RPC_FAR *rgDispId)
{
HRESULT hr;
hr = UPnPServiceDispatchImpl::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispId);
if(DISP_E_UNKNOWNNAME == hr)
hr = m_pServiceImpl->GetIDsOfNames(rgszNames, cNames, rgDispId);
return hr;
}
// Invoke
STDMETHODIMP Service::Invoke(
/* [in] */ DISPID dispIdMember,
/* [in] */ REFIID riid,
/* [in] */ LCID lcid,
/* [in] */ WORD wFlags,
/* [out][in] */ DISPPARAMS __RPC_FAR *pDispParams,
/* [out] */ VARIANT __RPC_FAR *pVarResult,
/* [out] */ EXCEPINFO __RPC_FAR *pExcepInfo,
/* [out] */ UINT __RPC_FAR *puArgErr)
{
HRESULT hr;
hr = UPnPServiceDispatchImpl::Invoke(dispIdMember, riid, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
if(DISP_E_MEMBERNOTFOUND == hr)
hr = m_pServiceImpl->Invoke(dispIdMember, wFlags, pDispParams, pVarResult, pExcepInfo, puArgErr);
return hr;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -