📄 automationproxy.cpp
字号:
psa = SafeArrayCreate(VT_UI1, 1, rgsabound);
if(psa == NULL)
return E_OUTOFMEMORY;
SafeArrayAccessData(psa, (void**)&pData);
if(SDT_BIN_HEX == sdt)
{
hr = ParseBinHex(pwszValue, cch, pData, &cbData, &pwcNext);
}
else
{
Assert(SDT_BIN_BASE64 == sdt);
hr = ParseBase64(pwszValue, cch, pData, &cbData, &pwcNext);
}
if(SUCCEEDED(hr))
{
pvarValue->parray = psa;
pvarValue->vt = VT_ARRAY | VT_UI1;
SafeArrayUnaccessData(psa);
rgsabound[0].cElements = cbData;
SafeArrayRedim(psa, rgsabound);
}
else
{
SafeArrayUnaccessData(psa);
SafeArrayDestroy(psa);
}
}
break;
case SDT_BOOLEAN: Assert(pvarValue->vt == VT_EMPTY);
if(0 == wcscmp(pwszValue, L"true") ||
0 == wcscmp(pwszValue, L"yes") ||
0 == wcscmp(pwszValue, L"1"))
{
pvarValue->vt = VT_BOOL;
pvarValue->boolVal = VARIANT_TRUE;
hr = S_OK;
}
if(0 == wcscmp(pwszValue, L"false") ||
0 == wcscmp(pwszValue, L"no") ||
0 == wcscmp(pwszValue, L"0"))
{
pvarValue->vt = VT_BOOL;
pvarValue->boolVal = VARIANT_FALSE;
hr = S_OK;
}
break;
}
return hr;
}
HRESULT
CUPnPAutomationProxy::HrInvokeAction(
UPNP_CONTROL_REQUEST * pucreq,
UPNP_CONTROL_RESPONSE * pucresp)
{
HRESULT hr = S_OK;
UPNP_CONTROL_RESPONSE ucresp = {0};
UPNP_ACTION * pua = NULL;
pua = LookupActionByName(pucreq->bstrActionName);
if (pua)
{
// Check that we've got the right number of input arguments.
if (pua->cInArgs == pucreq->cInputArgs)
{
DWORD cTotalArgs = 0;
DWORD cOutArgs = 0;
VARIANTARG *rgvarg = NULL;
VARIANTARG *rgvargData = NULL;
VARIANT varResult;
EXCEPINFO excepInfo = {0};
VariantInit(&varResult);
// Build an array of arguments to pass to the service object.
cTotalArgs = pua->cInArgs + pua->cOutArgs;
if (pua->bRetVal)
{
Assert(cTotalArgs > 0);
// In UTL, the retval is considered an out parameter. In the
// automation world, it's considered separate, so reduce the
// count of parameters by 1 if there is a retval.
cTotalArgs--;
}
cOutArgs = cTotalArgs - pua->cInArgs;
if (cTotalArgs > 0)
{
rgvarg = new VARIANTARG[cTotalArgs];
if (cOutArgs > 0)
{
rgvargData = new VARIANTARG[cOutArgs];
}
if (rgvarg && (!cOutArgs || rgvargData))
{
// Have to copy the arguments in reverse order. Out args
// go first.
for (DWORD i = 0,
index = pua->cOutArgs - 1;
SUCCEEDED(hr) && (i < cOutArgs);
i++, index--)
{
const UPNP_STATE_VARIABLE * pusvRelated = NULL;
pusvRelated = pua->rgOutArgs[index].pusvRelated;
hr = HrVariantInitForXMLType(&rgvargData[i], pusvRelated->strDataType);
if (SUCCEEDED(hr))
{
rgvarg[i].vt = rgvargData[i].vt | VT_BYREF;
rgvarg[i].pdblVal = &(rgvargData[i].dblVal);
if (SUCCEEDED(hr))
{
TraceTag(ttidAutomationProxy,
"CUPnPAutomationProxy::HrInvokeAction(): "
"Successfully initialized output arg %d",
i);
}
else
{
TraceError("CUPnPAutomationProxy::HrInvokeAction(): "
"Failed to initialize output argument",
hr);
}
}
else
{
TraceError("CUPnPAutomationProxy::HrInvokeAction(): "
"Failed to initialize for XML data type",
hr);
}
}
if (SUCCEEDED(hr))
{
// Now the in arguments.
// i is the index into the array of arguments we'll
// pass to IDispatch::Invoke. It starts at the first
// index after the out arguments. j is the index into
// the array of input arguments - it starts at the last
// and goes down to the first.
for (DWORD i = cOutArgs, j = pucreq->cInputArgs - 1;
i < cTotalArgs;
i++, j--)
{
Assert(pucreq->rgvarInputArgs[j].vt == VT_BSTR);
VariantInit(&rgvarg[i]);
Decode(pucreq->rgvarInputArgs[j].bstrVal, pua->rgInArgs[j].pusvRelated->strDataType, &rgvarg[i]);
}
}
}
else
{
hr = E_OUTOFMEMORY;
TraceError("CUPnPAutomationProxy::HrInvokeAction(): "
"Failed to allocate arguments array",
hr);
}
}
else
{
rgvarg = NULL;
}
// Now we have the arguments sorted out. Execute the request.
if (SUCCEEDED(hr))
{
DISPPARAMS actionParams;
actionParams.rgvarg = rgvarg;
actionParams.cArgs = cTotalArgs;
actionParams.rgdispidNamedArgs = NULL;
actionParams.cNamedArgs = 0;
hr = m_pdispService->Invoke(pua->dispid,
IID_NULL,
LOCALE_SYSTEM_DEFAULT,
DISPATCH_METHOD,
&actionParams,
&varResult,
&excepInfo,
NULL);
}
// Build a response.
if (SUCCEEDED(hr))
{
UPNP_CONTROL_RESPONSE_DATA * pucrd = NULL;
TraceTag(ttidAutomationProxy,
"CUPnPAutomationProxy::HrInvokeAction(): "
"Action %S executed successfully",
pua->strName);
ucresp.bstrActionName = SysAllocString(pua->strName);
if (ucresp.bstrActionName)
{
ucresp.fSucceeded = TRUE;
pucrd = &ucresp.ucrData;
if (pua->cOutArgs > 0)
{
pucrd->Success.rgvarOutputArgs = (VARIANT *) CoTaskMemAlloc(
pua->cOutArgs * sizeof(VARIANT));
if (pucrd->Success.rgvarOutputArgs)
{
DWORD dwStartIndex = 0;
pucrd->Success.cOutputArgs = pua->cOutArgs;
if (pua->bRetVal)
{
VariantInit(&pucrd->Success.rgvarOutputArgs[0]);
hr = StringizeVariant(&varResult, pua->rgOutArgs[0].pusvRelated->strDataType);
if (SUCCEEDED(hr))
hr = VariantCopy(&pucrd->Success.rgvarOutputArgs[0], &varResult);
if (SUCCEEDED(hr))
{
dwStartIndex = 1;
TraceTag(ttidAutomationProxy,
"CUPnPAutomationProxy::"
"HrInvokeAction(): "
"Successfully copied retval");
}
else
{
TraceError("CUPnPAutomationProxy::"
"HrInvokeAction(): "
"Failed to copy retval",
hr);
}
}
if (SUCCEEDED(hr))
{
for (DWORD i = 0,
j = cOutArgs + dwStartIndex - 1;
SUCCEEDED(hr) && (i < cOutArgs);
i++, j--)
{
VariantInit(&pucrd->Success.rgvarOutputArgs[j]);
hr = StringizeVariant(&rgvargData[i], pua->rgOutArgs[j].pusvRelated->strDataType);
if (SUCCEEDED(hr))
hr = VariantCopy(&pucrd->Success.rgvarOutputArgs[j], &rgvargData[i]);
if (SUCCEEDED(hr))
{
TraceTag(ttidAutomationProxy,
"CUPnPAutomationProxy::"
"HrInvokeAction(): "
"Successfully copied out arg %d",
j);
}
else
{
TraceError("CUPnPAutomationProxy::"
"HrInvokeAction(): "
"Failed to copy out arg",
hr);
}
}
}
}
else
{
hr = E_OUTOFMEMORY;
TraceError("CUPnPAutomationProxy::HrInvokeAction(): "
"Failed to allocate memory for out args",
hr);
}
}
else
{
pucrd->Success.rgvarOutputArgs = NULL;
pucrd->Success.cOutputArgs = 0;
}
}
else
{
hr = E_OUTOFMEMORY;
TraceError("CUPnPAutomationProxy::HrInvokeAction(): "
"Failed to allocate memory for action name",
hr);
}
}
else if (DISP_E_EXCEPTION == hr)
{
UPNP_CONTROL_RESPONSE_DATA * pucrd = NULL;
TraceTag(ttidAutomationProxy,
"CUPnPAutomationProxy::HrInvokeAction(): "
"Action %S returned an exception",
pua->strName);
// Fix up the HRESULT. Even though this is an error in the
// UPnP sense, we are returning success because from the
// processing point of view, the request went through correctly
// and just returned a fault response.
hr = S_OK;
ucresp.bstrActionName = SysAllocString(pua->strName);
if (ucresp.bstrActionName)
{
ucresp.fSucceeded = FALSE;
pucrd = &ucresp.ucrData;
// If the service object requested deferred fill-in of
// the exception info, call its callback function now.
if (excepInfo.pfnDeferredFillIn)
{
hr = (*(excepInfo.pfnDeferredFillIn))(&excepInfo);
if (SUCCEEDED(hr))
{
TraceTag(ttidAutomationProxy,
"CUPnPAutomationProxy::HrInvokeAction(): "
"Successfully filled in "
"deferred exception info");
}
else
{
TraceError("CUPnPAutomationProxy::HrInvokeAction(): "
"Failed to fill in "
"deferred exception info",
hr);
}
}
if (SUCCEEDED(hr))
{
hr = HrBuildFaultResponse(pucrd,
L"SOAP-ENV:Client",
L"UPnPError",
excepInfo.bstrSource,
excepInfo.bstrDescription);
}
}
else
{
hr = E_OUTOFMEMORY;
TraceError("CUPnPAutomationProxy::HrInvokeAction(): "
"Failed to allocate memory for action name",
hr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -