📄 upnphost.cpp
字号:
return E_FAIL;
// the service is supposed to create the named event
if (GetLastError() != ERROR_ALREADY_EXISTS)
{
CloseHandle(hUPnPHostingEvent);
return HRESULT_FROM_WIN32(ERROR_SERVICE_NOT_FOUND);
}
RegEntry upnpDevicesKey(UPNPDEVICESKEY);
if (upnpDevicesKey.Success())
{
RegEntry upnpDeviceKey(bstrDeviceIdentifier, upnpDevicesKey.GetKey());
if (upnpDeviceKey.Success())
{
if ((bstrInitString && (hr = upnpDeviceKey.SetValue(L"InitString",bstrInitString)))
||(bstrProgIDDeviceControlClass && (hr = upnpDeviceKey.SetValue(L"ProgId",bstrProgIDDeviceControlClass)))
|| (bstrResourcePath && (hr = upnpDeviceKey.SetValue(L"ResourcePath",bstrResourcePath)))
|| (hr = upnpDeviceKey.SetValue(L"XMLDesc",bstrXMLDesc)) // is this too big for the registry?
|| (hr = upnpDeviceKey.SetValue(L"State", UPNPREG_STARTING))
|| (hr = upnpDeviceKey.SetValue(L"UDN", bstrDeviceIdentifier))
|| (hr = upnpDeviceKey.SetValue(L"LifeTime", nLifeTime)))
{
hr = HRESULT_FROM_WIN32(hr);
upnpDeviceKey.DeleteKey();
RegDeleteKey(upnpDevicesKey.GetKey(),bstrDeviceIdentifier);
}
}
}
if (SUCCEEDED(hr))
{
// signal the hosting process
SetEvent(hUPnPHostingEvent);
}
CloseHandle(hUPnPHostingEvent);
return hr;
}
#define __OPT_PLAT_FLAG (defined (ARMV4T))
#define __OPT_VER_RESTORE
#define __OPT_BUGNUMSTRING "26316"
#include <optimizer.h>
//+---------------------------------------------------------------------------
//
// Function:
//
// Purpose: Create and publish the UPnP device tree.
//
// Arguments:
// pszXMLDesc [in] XML device description template
//
// Returns:
// HRESULT
//
STDMETHODIMP UPnPRegistrar::UnregisterDevice(
/*[in]*/ BSTR bstrDeviceIdentifier,
/*[in]*/ BOOL fPermanent)
{
TraceTag(ttidRegistrar, "UPnPRegistrar::UnregisterDevice");
HRESULT hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
HANDLE hUPnPHostingEvent = NULL;
if (bstrDeviceIdentifier == NULL || *bstrDeviceIdentifier == 0)
{
return E_INVALIDARG;
}
RegEntry upnpDevicesKey(UPNPDEVICESKEY);
if (upnpDevicesKey.Success())
{
if (fPermanent)
{
hr = RegDeleteKey(upnpDevicesKey.GetKey(),bstrDeviceIdentifier);
}
else
{
RegEntry upnpDeviceKey(bstrDeviceIdentifier, upnpDevicesKey.GetKey(), FALSE); // open existing device key
hr = upnpDeviceKey.SetValue(UPNPSTATEVALUE,UPNPREG_DISABLED);
hr = HRESULT_FROM_WIN32(hr);
}
if (SUCCEEDED(hr))
{
// this appears to be registered device. Need to signal the hosting process if its running
hUPnPHostingEvent = CreateEvent(NULL,FALSE,FALSE,UPNPLOADEREVENTNAME);
if (hUPnPHostingEvent && GetLastError() != ERROR_ALREADY_EXISTS)
{
// the hosting process is not around
CloseHandle(hUPnPHostingEvent);
hUPnPHostingEvent = NULL;
}
}
}
if (!UpnpRemoveDevice(bstrDeviceIdentifier) && hr != 0)
{
// return failure if we were not able to remove the device and it was not in the registry
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
hr = S_OK;
if (hUPnPHostingEvent)
{
// signal the hosting process. Otherwise it may not get to know that the device has been unregistered
SetEvent(hUPnPHostingEvent);
CloseHandle(hUPnPHostingEvent);
}
return hr;
}
//+---------------------------------------------------------------------------
//
// Function:
//
// Purpose: Create and publish the UPnP device tree.
//
// Arguments:
// pszXMLDesc [in] XML device description template
//
// Returns:
// HRESULT
//
STDMETHODIMP UPnPRegistrar::GetUniqueDeviceName(
/*[in]*/ BSTR bstrDeviceIdentifier,
/*[in]*/ BSTR bstrTemplateUDN,
/*[out, retval]*/ BSTR * pbstrUDN)
{
HRESULT hr = S_OK;
WCHAR szUDN[128];
DWORD cchUDN = sizeof(szUDN)/sizeof(szUDN[0]);
if (!UpnpGetUDN(bstrDeviceIdentifier, bstrTemplateUDN, szUDN, &cchUDN))
{
hr = HRESULT_FROM_WIN32(GetLastError());
}
else
{
*pbstrUDN = SysAllocString(szUDN);
if (!*pbstrUDN)
hr = E_OUTOFMEMORY;
}
return hr;
}
STDMETHODIMP UPnPRegistrar::RegisterDeviceProvider(
/*[in]*/ BSTR bstrProviderName,
/*[in]*/ BSTR bstrProgIDProviderClass,
/*[in]*/ BSTR bstrInitString,
/*[in]*/ BSTR bstrContainerId)
{
return E_NOTIMPL;
}
STDMETHODIMP UPnPRegistrar::UnregisterDeviceProvider(
/*[in]*/ BSTR bstrProviderName)
{
return E_NOTIMPL;
}
//
// DeviceProxy implementation
//
//+---------------------------------------------------------------------------
//
// Function: FreeControlRequest
//
// Purpose: Frees resources used by the fields of a UPNP_CONTROL_REQUEST
// structure
//
// Arguments:
// pucr [in] Address of the structure to cleanup
//
// Returns:
// (none)
// This function just frees the resources used by the fields within
// the passed in structure. It does not free the memory used by the
// structure itself.
//
static VOID
FreeControlRequest(
IN UPNP_CONTROL_REQUEST * pucr)
{
if (pucr->bstrActionName)
{
SysFreeString(pucr->bstrActionName);
pucr->bstrActionName = NULL;
}
if (pucr->rgvarInputArgs)
{
for (DWORD i = 0; i < pucr->cInputArgs; i++)
{
VariantClear(&pucr->rgvarInputArgs[i]);
}
delete [] pucr->rgvarInputArgs;
pucr->rgvarInputArgs = NULL;
pucr->cInputArgs = 0;
}
}
//+---------------------------------------------------------------------------
//
// Function: FormatControlRequest
//
// Purpose: Copy the action name, parameter names and values from the
// UPNPSERVICECONTROL struct to the UPNP_CONTROL_REQUEST struct
//
// The existence of two different types is possibly avoidable
// but one meshes with the COM world, and one does not.
//
// Arguments:
// pSvcCtl [in] pointer to the populated UPNPSERVICECONTROL struct
// pucreq [out] pointer to the empty UPNP_CONTROL_REQUEST struct
//
// Returns:
// TRUE if the fields were copied successully to pucreq
//
static
BOOL
FormatControlRequest(UPNPSERVICECONTROL *pSvcCtl, UPNP_CONTROL_REQUEST *pucreq)
{
BOOL fRet = TRUE;
UINT i;
ZeroMemory(pucreq, sizeof(*pucreq));
pucreq->bstrActionName = SysAllocString(pSvcCtl->pszAction);
if (pSvcCtl->cInArgs)
{
pucreq->rgvarInputArgs = new VARIANT[pSvcCtl->cInArgs];
if (pucreq->rgvarInputArgs)
{
pucreq->cInputArgs = pSvcCtl->cInArgs;
for (i=0; i< pSvcCtl->cInArgs; i++)
{
V_BSTR(&pucreq->rgvarInputArgs[i]) = SysAllocString(pSvcCtl->pInArgs[i].pszValue);
if (!V_BSTR(&pucreq->rgvarInputArgs[i]))
{
fRet = FALSE; // is it ok to have a NULL value?
break;
}
pucreq->rgvarInputArgs[i].vt = VT_BSTR;
}
}
else
fRet = FALSE;
}
if (!fRet)
{
// free any strings we allocated
FreeControlRequest(pucreq);
}
return fRet;
}
//+---------------------------------------------------------------------------
//
// Function: FreeControlResponse
//
// Purpose: Frees resources used by the fields of a UPNP_CONTROL_RESPONSE
// structure
//
// Arguments:
// pucr [in] Address of the structure to cleanup
//
// Returns:
// (none)
//
// Notes:
// This function just frees the resources used by the fields within
// the passed in structure. It does not free the memory used by the
// structure itself.
//
static VOID
FreeControlResponse(
IN UPNP_CONTROL_RESPONSE * pucresp)
{
if (pucresp->bstrActionName)
{
SysFreeString(pucresp->bstrActionName);
pucresp->bstrActionName = NULL;
}
UPNP_CONTROL_RESPONSE_DATA * pucrd = &pucresp->ucrData;
if (pucresp->fSucceeded)
{
if (pucrd->Success.rgvarOutputArgs)
{
for (DWORD i = 0; i < pucrd->Success.cOutputArgs; i++)
{
VariantClear(&pucrd->Success.rgvarOutputArgs[i]);
}
CoTaskMemFree(pucrd->Success.rgvarOutputArgs);
pucrd->Success.rgvarOutputArgs = NULL;
pucrd->Success.cOutputArgs = 0;
}
}
else
{
if (pucrd->Fault.bstrFaultCode)
{
SysFreeString(pucrd->Fault.bstrFaultCode);
pucrd->Fault.bstrFaultCode = NULL;
}
if (pucrd->Fault.bstrFaultString)
{
SysFreeString(pucrd->Fault.bstrFaultString);
pucrd->Fault.bstrFaultString = NULL;
}
if (pucrd->Fault.bstrUPnPErrorCode)
{
SysFreeString(pucrd->Fault.bstrUPnPErrorCode);
pucrd->Fault.bstrUPnPErrorCode = NULL;
}
if (pucrd->Fault.bstrUPnPErrorString)
{
SysFreeString(pucrd->Fault.bstrUPnPErrorString);
pucrd->Fault.bstrUPnPErrorString = NULL;
}
}
}
//+---------------------------------------------------------------------------
//
// Function: GetServiceProxy
//
// Purpose: Locate the ServiceProxy object by serviceId. If it does not exist
// attempt to create and initialize one and add it to the list.
//
//
// Arguments:
// pszServiceId [in] serviceId string
//
// Returns:
// pointer to the ServiceProxy object or NULL if failure.
// pointer is not AddRef'ed.
//
ServiceProxy *
DeviceProxy::GetServiceProxy(LPCWSTR pszUDN, LPCWSTR pszServiceId)
{
ServiceProxy *pSvc;
HRESULT hr;
IDispatch *pISO;
for (pSvc=m_pServices;pSvc; pSvc = pSvc->m_pNext)
{
if (wcscmp(pszServiceId, pSvc->m_bstrSid) == 0 && wcscmp(pszUDN, pSvc->m_bstrUDN) == 0)
break;
}
if (!pSvc)
{
// this may be the first time, so create one
if (m_pDeviceControl)
{
ce::auto_bstr bstrUDN, bstrServiceId;
bstrUDN = SysAllocString(pszUDN);
bstrServiceId = SysAllocString(pszServiceId);
hr = m_pDeviceControl->GetServiceObject(bstrUDN, bstrServiceId, &pISO);
if (SUCCEEDED(hr))
{
WCHAR szSCPDPath[MAX_PATH];
// get the SCPD
UpnpGetSCPDPath(m_bstrDeviceId, pszUDN, pszServiceId, szSCPDPath, celems(szSCPDPath));
pSvc = new ServiceProxy(this);
if (pSvc)
{
pSvc->AddRef(); // set the ref count to 1
hr = pSvc->Initialize(pszUDN, pszServiceId, szSCPDPath, pISO);
if (SUCCEEDED(hr))
{
// add to service list
pSvc->m_pNext = m_pServices;
m_pServices = pSvc;
// submit the initial state variables
pSvc->OnStateChanged(0,NULL); // 0,NULL => all variables
}
else
{
pSvc->Release(); // this should delete the object
pSvc = NULL;
}
}
pISO->Release();
}
}
}
return pSvc;
}
//+---------------------------------------------------------------------------
//
// Method: DeviceProxy::SubscribeCallback
//
// Purpose: Invoked when a remote subscription request is received.
//
// Arguments:
// UPNPSUBSCRIPTION *pUPnPSubscription
//
// Returns:
// TRUE if the subscription is accepted
//
BOOL
DeviceProxy::SubscribeCallback(UPNPSUBSCRIPTION *pUPnPSubscription)
{
ServiceProxy *pServiceProxy;
// We need to have a pointer to the implementation object by now
if (!m_pDeviceControl)
{
return FALSE;
}
// Find the service proxy by serviceId
// create if necessary
pServiceProxy = GetServiceProxy(pUPnPSubscription->pszUDN, pUPnPSubscription->pszSID);
if (!pServiceProxy)
{
TraceTag(ttidError, "SubscribeCallback: No service proxy for Service ID %S\n", pUPnPSubscription->pszSID);
return FALSE;
}
pServiceProxy->UpdateEventedVariables(FALSE, 0, NULL); // FALSE -> just update, don't send event; 0, NULL -> all evented variables
return TRUE;
}
//+---------------------------------------------------------------------------
//
// Function: ControlCallback
//
// Purpose: Invoked when a remote control request is received
//
// Arguments:
// pszXMLDesc [in] XML device description template
//
// Returns:
// HRESULT
//
BOOL
DeviceProxy::ControlCallback(UPNPSERVICECONTROL *pSvcCtl)
{
HRESULT hr;
BOOL fRet = FALSE;
UPNP_CONTROL_REQUEST ucreq;
UPNP_CONTROL_RESPONSE ucresp;
ServiceProxy *pServiceProxy;
TraceTag(ttidRegistrar, "DeviceProxy::ControlRequest\n");
Assert(pSvcCtl->pszSID);
Assert(m_pDeviceControl);
// We need to have a pointer to the implementation object by now
if (!m_pDeviceControl)
{
return FALSE;
}
// Find the service proxy by serviceId
// create if necessary
pServiceProxy = GetServiceProxy(pSvcCtl->pszUDN, pSvcCtl->pszSID);
if (!pServiceProxy)
{
TraceTag(ttidError, "ControlCallback: No service proxy for Service ID %S\n", pSvcCtl->pszSID);
return FALSE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -