1106 lines
33 KiB
C++
1106 lines
33 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 2000.
|
|
//
|
|
// File: R E G I S T R A R . C P P
|
|
//
|
|
// Contents: Top level device host object
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: mbend 12 Sep 2000
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#include "uhbase.h"
|
|
#include "hostp.h"
|
|
#include "Registrar.h"
|
|
#include "upsync.h"
|
|
#include "ComUtility.h"
|
|
#include "uhutil.h"
|
|
#include "ssdpapi.h"
|
|
#include "evtapi.h"
|
|
#include "InterfaceList.h"
|
|
#include "uhcommon.h"
|
|
|
|
static const int c_minLifeTime = 900;
|
|
static const int c_defLifeTime = 1800;
|
|
|
|
// Helper functions
|
|
|
|
HRESULT HrSetErrorInfo(
|
|
const wchar_t * szErrorString,
|
|
REFIID riid)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
IErrorInfo * pErrorInfo = NULL;
|
|
ICreateErrorInfo * pCreateErrorInfo = NULL;
|
|
|
|
hr = CreateErrorInfo(&pCreateErrorInfo);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pCreateErrorInfo->SetDescription(const_cast<wchar_t*>(szErrorString));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pCreateErrorInfo->SetGUID(riid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pCreateErrorInfo->QueryInterface(&pErrorInfo);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = SetErrorInfo(0, pErrorInfo);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
ReleaseObj(pErrorInfo);
|
|
ReleaseObj(pCreateErrorInfo);
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "HrSetErrorInfo(%S)", szErrorString);
|
|
return hr;
|
|
}
|
|
|
|
//
|
|
// Verify that the given resource path starts with X:\ where X is a drive
|
|
// letter
|
|
//
|
|
HRESULT HrValidateResourcePath(BSTR bstrPath)
|
|
{
|
|
HRESULT hr = E_INVALIDARG;
|
|
|
|
if (!bstrPath)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
if (!FFileExists(bstrPath, TRUE))
|
|
{
|
|
hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
|
|
}
|
|
else
|
|
{
|
|
if (isalpha(bstrPath[0]))
|
|
{
|
|
if (bstrPath[1] == L':')
|
|
{
|
|
if (bstrPath[2] == L'\\')
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "HrValidateResourcePath");
|
|
return hr;
|
|
}
|
|
|
|
// Constructors and destructors
|
|
|
|
CRegistrar::CRegistrar() : m_bSetAutoStart(FALSE)
|
|
{
|
|
}
|
|
|
|
CRegistrar::~CRegistrar()
|
|
{
|
|
}
|
|
|
|
// ISupportErrorInfo methods
|
|
|
|
STDMETHODIMP CRegistrar::InterfaceSupportsErrorInfo(REFIID riid)
|
|
{
|
|
HRESULT hr = S_FALSE;
|
|
|
|
if(riid == IID_IUPnPRegistrar || riid == IID_IUPnPReregistrar)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
// IUPnPRegistrarLookup methods
|
|
|
|
STDMETHODIMP CRegistrar::GetEventingManager(
|
|
/*[in, string]*/ const wchar_t * szUDN,
|
|
/*[in, string]*/ const wchar_t * szServiceId,
|
|
/*[out]*/ IUPnPEventingManager ** ppEventingManager)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::GetEventingManager");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC );
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
CServiceInfo * pServiceInfo = NULL;
|
|
hr = m_deviceManager.HrGetService(szUDN, szServiceId, &pServiceInfo);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pServiceInfo->HrGetEventingManager(ppEventingManager);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetEventingManager");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::GetAutomationProxy(
|
|
/*[in, string]*/ const wchar_t * szUDN,
|
|
/*[in, string]*/ const wchar_t * szServiceId,
|
|
/*[out]*/ IUPnPAutomationProxy ** ppAutomationProxy)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::GetAutomationProxy");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
CServiceInfo * pServiceInfo = NULL;
|
|
hr = m_deviceManager.HrGetService(szUDN, szServiceId, &pServiceInfo);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pServiceInfo->HrGetAutomationProxy(ppAutomationProxy);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetAutomationProxy");
|
|
return hr;
|
|
}
|
|
|
|
// IUPnPRegistrarPrivate methods
|
|
|
|
STDMETHODIMP CRegistrar::Initialize()
|
|
{
|
|
TraceTag(ttidRegistrar,"CRegistrar::Initialize");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = CUPnPInterfaceList::Instance().HrInitialize();
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrInitEventApi();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
SsdpStartup();
|
|
|
|
hr = m_pDescriptionManager.HrCreateInstanceInproc(CLSID_UPnPDescriptionManager);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDevicePersistenceManager.HrCreateInstanceInproc(CLSID_UPnPDevicePersistenceManager);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
IUPnPDynamicContentSourcePtr pDynamicContentSource;
|
|
hr = pDynamicContentSource.HrCreateInstanceInproc(CLSID_UPnPDynamicContentSource);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
IUPnPDynamicContentProviderPtr pDynamicContentProvider;
|
|
hr = pDynamicContentProvider.HrAttach(m_pDescriptionManager);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pDynamicContentSource->RegisterProvider(pDynamicContentProvider);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_pValidationManager.HrCreateInstanceInproc(CLSID_UPnPValidationManager);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pContainerManager.HrCreateInstanceInproc(CLSID_UPnPContainerManager);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDynamicContentSource.HrCreateInstanceInproc(CLSID_UPnPDynamicContentSource);
|
|
}
|
|
}
|
|
|
|
|
|
// Get the PDIs
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
long nDevices = 0;
|
|
GUID * arPdi;
|
|
hr = m_pDevicePersistenceManager->GetPhysicalDevices(&nDevices, &arPdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Bring each persistent device to life
|
|
for(long n = 0; n < nDevices; ++n)
|
|
{
|
|
// Use a temporary HRESULT because we don't want one thing to cause everything to fail
|
|
HRESULT hrTemp = S_OK;
|
|
wchar_t * szProgIdDeviceControlClass = NULL;
|
|
wchar_t * szInitString = NULL;
|
|
wchar_t * szContainerId = NULL;
|
|
wchar_t * szResourcePath = NULL;
|
|
long nLifetime = 0;
|
|
hrTemp = m_pDevicePersistenceManager->LookupPhysicalDevice(
|
|
arPdi[n], &szProgIdDeviceControlClass, &szInitString, &szContainerId, &szResourcePath, &nLifetime);
|
|
if(SUCCEEDED(hrTemp))
|
|
{
|
|
// Load the description document
|
|
hrTemp = m_pDescriptionManager->LoadDescription(arPdi[n]);
|
|
if(SUCCEEDED(hrTemp))
|
|
{
|
|
// Get the UDNs
|
|
wchar_t ** arszUDNs = NULL;
|
|
long nUDNCount = 0;
|
|
hrTemp = m_pDescriptionManager->GetUDNs(arPdi[n], &nUDNCount, &arszUDNs);
|
|
if(SUCCEEDED(hrTemp))
|
|
{
|
|
// Add device
|
|
hrTemp = m_deviceManager.HrAddDevice(arPdi[n], szProgIdDeviceControlClass, szInitString,
|
|
szContainerId, nUDNCount, arszUDNs);
|
|
if(SUCCEEDED(hrTemp))
|
|
{
|
|
// Publish the device
|
|
hrTemp = m_pDescriptionManager->PublishDescription(arPdi[n], nLifetime);
|
|
}
|
|
// Free UDNs
|
|
for(long n = 0; n < nUDNCount; ++n)
|
|
{
|
|
CoTaskMemFree(arszUDNs[n]);
|
|
}
|
|
CoTaskMemFree(arszUDNs);
|
|
}
|
|
}
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CRegistrar::Initialize - Failed to init device (ProgId=%S)",
|
|
szProgIdDeviceControlClass);
|
|
CoTaskMemFree(szProgIdDeviceControlClass);
|
|
CoTaskMemFree(szInitString);
|
|
CoTaskMemFree(szContainerId);
|
|
CoTaskMemFree(szResourcePath);
|
|
}
|
|
}
|
|
CoTaskMemFree(arPdi);
|
|
}
|
|
}
|
|
|
|
// Do the providers
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
long nProviders = 0;
|
|
wchar_t ** arszProviderNames = NULL;
|
|
hr = m_pDevicePersistenceManager->GetDeviceProviders(&nProviders, &arszProviderNames);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Load each provider
|
|
long n;
|
|
for(n = 0; n < nProviders; ++n)
|
|
{
|
|
HRESULT hrTemp = S_OK;
|
|
wchar_t * szProgIdProviderClass = NULL;
|
|
wchar_t * szInitString = NULL;
|
|
wchar_t * szContainerId = NULL;
|
|
hrTemp = m_pDevicePersistenceManager->LookupDeviceProvider(
|
|
arszProviderNames[n], &szProgIdProviderClass, &szInitString, &szContainerId);
|
|
if(SUCCEEDED(hrTemp))
|
|
{
|
|
hrTemp = m_providerManager.HrRegisterProvider(
|
|
arszProviderNames[n], szProgIdProviderClass, szInitString, szContainerId);
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CRegistrar::Initialize - Failed to load provider (%S)", arszProviderNames[n]);
|
|
CoTaskMemFree(szProgIdProviderClass);
|
|
CoTaskMemFree(szInitString);
|
|
CoTaskMemFree(szContainerId);
|
|
}
|
|
}
|
|
for(n = 0; n < nProviders; ++n)
|
|
{
|
|
CoTaskMemFree(arszProviderNames[n]);
|
|
}
|
|
CoTaskMemFree(arszProviderNames);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::Initialize");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::Shutdown()
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::Shutdown");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
if (m_pDynamicContentSource)
|
|
{
|
|
IUPnPDynamicContentProviderPtr pDynamicContentProvider;
|
|
hr = pDynamicContentProvider.HrAttach(m_pDescriptionManager);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDynamicContentSource->UnregisterProvider(pDynamicContentProvider);
|
|
}
|
|
m_pDynamicContentSource.Release();
|
|
}
|
|
|
|
m_pDescriptionManager.Release();
|
|
m_pDevicePersistenceManager.Release();
|
|
m_pValidationManager.Release();
|
|
m_providerManager.HrShutdown();
|
|
m_deviceManager.HrShutdown();
|
|
if (m_pContainerManager)
|
|
{
|
|
m_pContainerManager->Shutdown();
|
|
}
|
|
m_pContainerManager.Release();
|
|
SsdpCleanup();
|
|
DeInitEventApi();
|
|
CUPnPInterfaceList::Instance().HrShutdown();
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::Shutdown");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::GetSCPDText(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
|
|
/*[in, string]*/ const wchar_t * szUDN,
|
|
/*[in, string]*/ const wchar_t * szServiceId,
|
|
/*[out, string]*/ wchar_t ** pszSCPDText,
|
|
/*[out, string]*/ wchar_t ** pszServiceType)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::GetSCPDText(UDN=%S, ServiceId=%S)", szUDN, szServiceId);
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = m_pDescriptionManager->GetSCPDText(guidPhysicalDeviceIdentifier, szUDN,
|
|
szServiceId, pszSCPDText, pszServiceType);
|
|
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetSCPDText");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::GetDescriptionText(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
|
|
/*[out]*/ BSTR * pbstrDescriptionDocument)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::GetDescriptionText");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = m_pDescriptionManager->GetDescriptionText(guidPhysicalDeviceIdentifier,
|
|
pbstrDescriptionDocument);
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetDescriptionText");
|
|
return hr;
|
|
}
|
|
|
|
|
|
// IUPnPRegistrar methods
|
|
|
|
STDMETHODIMP CRegistrar::RegisterDevice(
|
|
/*[in]*/ BSTR bstrXMLDesc,
|
|
/*[in]*/ BSTR bstrProgIDDeviceControlClass,
|
|
/*[in]*/ BSTR bstrInitString,
|
|
/*[in]*/ BSTR bstrContainerId,
|
|
/*[in]*/ BSTR bstrResourcePath,
|
|
/*[in]*/ long nLifeTime,
|
|
/*[out, retval]*/ BSTR * pbstrDeviceIdentifier)
|
|
{
|
|
TraceTag(ttidRegistrar,"CRegistrar::RegisterDevice");
|
|
HRESULT hr = S_OK;
|
|
BOOL fAllowed = FALSE;
|
|
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrValidateResourcePath(bstrResourcePath);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Do validation
|
|
wchar_t * szErrorString = NULL;
|
|
hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
|
|
bstrXMLDesc, bstrResourcePath, &szErrorString);
|
|
if(FAILED(hr))
|
|
{
|
|
HrSetErrorInfo(szErrorString, IID_IUPnPRegistrar);
|
|
return hr;
|
|
}
|
|
if(szErrorString)
|
|
{
|
|
CoTaskMemFree(szErrorString);
|
|
szErrorString = NULL;
|
|
}
|
|
|
|
if (!nLifeTime)
|
|
{
|
|
nLifeTime = c_defLifeTime;
|
|
}
|
|
else if (nLifeTime < c_minLifeTime)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSetAutoStart();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Process the description document
|
|
PhysicalDeviceIdentifier pdi;
|
|
hr = m_pDescriptionManager->ProcessDescriptionTemplate(
|
|
bstrXMLDesc, bstrResourcePath, &pdi, TRUE, FALSE);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get the UDNs
|
|
wchar_t ** arszUDNs = NULL;
|
|
long nUDNCount = 0;
|
|
hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add device
|
|
hr = m_deviceManager.HrAddDevice(pdi, bstrProgIDDeviceControlClass, bstrInitString,
|
|
bstrContainerId, nUDNCount, arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Save the device
|
|
hr = m_pDevicePersistenceManager->SavePhyisicalDevice(
|
|
pdi, bstrProgIDDeviceControlClass, bstrInitString, bstrContainerId, bstrResourcePath, nLifeTime);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Publish the device
|
|
hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strPdi;
|
|
hr = HrPhysicalDeviceIdentifierToString(pdi, strPdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPdi.HrGetBSTR(pbstrDeviceIdentifier);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Free UDNs
|
|
for(long n = 0; n < nUDNCount; ++n)
|
|
{
|
|
CoTaskMemFree(arszUDNs[n]);
|
|
}
|
|
CoTaskMemFree(arszUDNs);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
HrUnregisterDeviceByPDI(pdi, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::RegisterDevice");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::RegisterRunningDevice(
|
|
/*[in]*/ BSTR bstrXMLDesc,
|
|
/*[in]*/ IUnknown * punkDeviceControl,
|
|
/*[in]*/ BSTR bstrInitString,
|
|
/*[in]*/ BSTR bstrResourcePath,
|
|
/*[in]*/ long nLifeTime,
|
|
/*[out, retval]*/ BSTR * pbstrDeviceIdentifier)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::RegisterRunningDevice");
|
|
HRESULT hr = S_OK;
|
|
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrValidateResourcePath(bstrResourcePath);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Do validation
|
|
wchar_t * szErrorString = NULL;
|
|
hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
|
|
bstrXMLDesc, bstrResourcePath, &szErrorString);
|
|
if(FAILED(hr))
|
|
{
|
|
HrSetErrorInfo(szErrorString, IID_IUPnPRegistrar);
|
|
return hr;
|
|
}
|
|
if(szErrorString)
|
|
{
|
|
CoTaskMemFree(szErrorString);
|
|
szErrorString = NULL;
|
|
}
|
|
|
|
if (!nLifeTime)
|
|
{
|
|
nLifeTime = c_defLifeTime;
|
|
}
|
|
else if (nLifeTime < c_minLifeTime)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = CoImpersonateClient();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Process the description document
|
|
PhysicalDeviceIdentifier pdi;
|
|
hr = m_pDescriptionManager->ProcessDescriptionTemplate(
|
|
bstrXMLDesc, bstrResourcePath, &pdi, FALSE, FALSE);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get the UDNs
|
|
wchar_t ** arszUDNs = NULL;
|
|
long nUDNCount = 0;
|
|
hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add device
|
|
hr = m_deviceManager.HrAddRunningDevice(
|
|
pdi, punkDeviceControl, bstrInitString, nUDNCount, arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Publish the device
|
|
hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strPdi;
|
|
hr = HrPhysicalDeviceIdentifierToString(pdi, strPdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPdi.HrGetBSTR(pbstrDeviceIdentifier);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Free UDNs
|
|
for(long n = 0; n < nUDNCount; ++n)
|
|
{
|
|
CoTaskMemFree(arszUDNs[n]);
|
|
}
|
|
CoTaskMemFree(arszUDNs);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
HrUnregisterDeviceByPDI(pdi, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
CoRevertToSelf();
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::RegisterRunningDevice");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::RegisterDeviceProvider(
|
|
/*[in]*/ BSTR bstrProviderName,
|
|
/*[in]*/ BSTR bstrProgIDProviderClass,
|
|
/*[in]*/ BSTR bstrInitString,
|
|
/*[in]*/ BSTR bstrContainerId)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::RegisterDeviceProvider");
|
|
HRESULT hr = S_OK;
|
|
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_providerManager.HrRegisterProvider(
|
|
bstrProviderName, bstrProgIDProviderClass, bstrInitString, bstrContainerId);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDevicePersistenceManager->SaveDeviceProvider(
|
|
bstrProviderName, bstrProgIDProviderClass, bstrInitString, bstrContainerId);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSetAutoStart();
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::RegisterDeviceProvider");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::GetUniqueDeviceName(
|
|
/*[in]*/ BSTR bstrDeviceIdentifier,
|
|
/*[in]*/ BSTR bstrTemplateUDN,
|
|
/*[out, retval]*/ BSTR * pbstrUDN)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::GetUniqueDeviceName");
|
|
HRESULT hr = S_OK;
|
|
// No locking here to allow for reentrant calls
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if (!bstrDeviceIdentifier || !pbstrUDN)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
PhysicalDeviceIdentifier pdi;
|
|
hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
wchar_t * szUDN = NULL;
|
|
hr = m_pDescriptionManager->GetUniqueDeviceName(pdi, bstrTemplateUDN, &szUDN);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSysAllocString(szUDN, pbstrUDN);
|
|
CoTaskMemFree(szUDN);
|
|
}
|
|
}
|
|
else if (CO_E_CLASSSTRING == hr)
|
|
{
|
|
// remap this error to invalid argument error
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::GetUniqueDeviceName");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRegistrar::HrUnregisterDeviceByPDI(PhysicalDeviceIdentifier & pdi, BOOL fPermanent)
|
|
{
|
|
CALock lock(*this);
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = m_pDescriptionManager->RemoveDescription(pdi, fPermanent);
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CRegistrar::UnregisterDeviceByPDI "
|
|
"RemoveDescription failed!");
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDevicePersistenceManager->RemovePhysicalDevice(pdi);
|
|
if(FAILED(hr))
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::UnregisterDeviceByPDI - "
|
|
"RemovePhysicalDevice failed. This is expected "
|
|
"for running devices.");
|
|
}
|
|
hr = m_deviceManager.HrRemoveDevice(pdi);
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::UnregisterDeviceByPDI");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::UnregisterDevice(
|
|
/*[in]*/ BSTR bstrDeviceIdentifier,
|
|
/*[in]*/ BOOL fPermanent)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::UnregisterDevice");
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if (!bstrDeviceIdentifier)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
else
|
|
{
|
|
CALock lock(*this);
|
|
|
|
PhysicalDeviceIdentifier pdi;
|
|
hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrUnregisterDeviceByPDI(pdi, fPermanent);
|
|
}
|
|
else if (CO_E_CLASSSTRING == hr)
|
|
{
|
|
// remap this error to invalid argument error
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
}
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::UnregisterDevice");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::UnregisterDeviceProvider(
|
|
/*[in]*/ BSTR bstrProviderName)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::UnegisterDeviceProvider");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_providerManager.UnegisterProvider(bstrProviderName);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDevicePersistenceManager->RemoveDeviceProvider(bstrProviderName);
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::UnegisterDeviceProvider");
|
|
return hr;
|
|
}
|
|
|
|
// IUPnPReregistrar methods
|
|
|
|
STDMETHODIMP CRegistrar::ReregisterDevice(
|
|
/*[in]*/ BSTR bstrDeviceIdentifier,
|
|
/*[in]*/ BSTR bstrXMLDesc,
|
|
/*[in]*/ BSTR bstrProgIDDeviceControlClass,
|
|
/*[in]*/ BSTR bstrInitString,
|
|
/*[in]*/ BSTR bstrContainerId,
|
|
/*[in]*/ BSTR bstrResourcePath,
|
|
/*[in]*/ long nLifeTime)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::ReregisterDevice");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrValidateResourcePath(bstrResourcePath);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Do validation
|
|
wchar_t * szErrorString = NULL;
|
|
hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
|
|
bstrXMLDesc, bstrResourcePath, &szErrorString);
|
|
if(FAILED(hr))
|
|
{
|
|
HrSetErrorInfo(szErrorString, IID_IUPnPReregistrar);
|
|
return hr;
|
|
}
|
|
if(szErrorString)
|
|
{
|
|
CoTaskMemFree(szErrorString);
|
|
szErrorString = NULL;
|
|
}
|
|
|
|
if (!nLifeTime)
|
|
{
|
|
nLifeTime = c_defLifeTime;
|
|
}
|
|
else if (nLifeTime < c_minLifeTime)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
if (!bstrDeviceIdentifier)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSetAutoStart();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Process the description document
|
|
PhysicalDeviceIdentifier pdi;
|
|
hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if (m_deviceManager.FHasDevice(pdi))
|
|
{
|
|
hr = UPNP_E_DEVICE_RUNNING;
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDescriptionManager->ProcessDescriptionTemplate(
|
|
bstrXMLDesc, bstrResourcePath, &pdi, TRUE, TRUE);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get the UDNs
|
|
wchar_t ** arszUDNs = NULL;
|
|
long nUDNCount = 0;
|
|
hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add device
|
|
hr = m_deviceManager.HrAddDevice(pdi, bstrProgIDDeviceControlClass, bstrInitString,
|
|
bstrContainerId, nUDNCount, arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Save the device
|
|
hr = m_pDevicePersistenceManager->SavePhyisicalDevice(
|
|
pdi, bstrProgIDDeviceControlClass, bstrInitString, bstrContainerId, bstrResourcePath, nLifeTime);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Publish the device
|
|
hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
|
|
}
|
|
}
|
|
// Free UDNs
|
|
for(long n = 0; n < nUDNCount; ++n)
|
|
{
|
|
CoTaskMemFree(arszUDNs[n]);
|
|
}
|
|
CoTaskMemFree(arszUDNs);
|
|
}
|
|
|
|
if (FAILED(hr) && hr != UPNP_E_DEVICE_RUNNING)
|
|
{
|
|
HrUnregisterDeviceByPDI(pdi, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else if (CO_E_CLASSSTRING == hr)
|
|
{
|
|
// remap this error to invalid argument error
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::ReregisterDevice");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::ReregisterRunningDevice(
|
|
/*[in]*/ BSTR bstrDeviceIdentifier,
|
|
/*[in]*/ BSTR bstrXMLDesc,
|
|
/*[in]*/ IUnknown * punkDeviceControl,
|
|
/*[in]*/ BSTR bstrInitString,
|
|
/*[in]*/ BSTR bstrResourcePath,
|
|
/*[in]*/ long nLifeTime)
|
|
{
|
|
TraceTag(ttidRegistrar, "CRegistrar::ReregisterRunningDevice");
|
|
HRESULT hr = S_OK;
|
|
CALock lock(*this);
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrValidateResourcePath(bstrResourcePath);
|
|
}
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Do validation
|
|
wchar_t * szErrorString = NULL;
|
|
hr = m_pValidationManager->ValidateDescriptionDocumentAndReferences(
|
|
bstrXMLDesc, bstrResourcePath, &szErrorString);
|
|
if(FAILED(hr))
|
|
{
|
|
HrSetErrorInfo(szErrorString, IID_IUPnPReregistrar);
|
|
return hr;
|
|
}
|
|
if(szErrorString)
|
|
{
|
|
CoTaskMemFree(szErrorString);
|
|
szErrorString = NULL;
|
|
}
|
|
|
|
if (!nLifeTime)
|
|
{
|
|
nLifeTime = c_defLifeTime;
|
|
}
|
|
else if (nLifeTime < c_minLifeTime)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
if (!bstrDeviceIdentifier)
|
|
{
|
|
hr = E_POINTER;
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = CoImpersonateClient();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Process the description document
|
|
PhysicalDeviceIdentifier pdi;
|
|
hr = HrStringToPhysicalDeviceIdentifier(bstrDeviceIdentifier, pdi);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if (m_deviceManager.FHasDevice(pdi))
|
|
{
|
|
hr = UPNP_E_DEVICE_RUNNING;
|
|
}
|
|
|
|
// Process the description document
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pDescriptionManager->ProcessDescriptionTemplate(
|
|
bstrXMLDesc, bstrResourcePath, &pdi, FALSE, TRUE);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get the UDNs
|
|
wchar_t ** arszUDNs = NULL;
|
|
long nUDNCount = 0;
|
|
hr = m_pDescriptionManager->GetUDNs(pdi, &nUDNCount, &arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add device
|
|
hr = m_deviceManager.HrAddRunningDevice(
|
|
pdi, punkDeviceControl, bstrInitString, nUDNCount, arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Publish the device
|
|
hr = m_pDescriptionManager->PublishDescription(pdi, nLifeTime);
|
|
}
|
|
|
|
// Free UDNs
|
|
for(long n = 0; n < nUDNCount; ++n)
|
|
{
|
|
CoTaskMemFree(arszUDNs[n]);
|
|
}
|
|
CoTaskMemFree(arszUDNs);
|
|
}
|
|
|
|
if (FAILED(hr) && hr != UPNP_E_DEVICE_RUNNING)
|
|
{
|
|
HrUnregisterDeviceByPDI(pdi, FALSE);
|
|
}
|
|
}
|
|
}
|
|
else if (CO_E_CLASSSTRING == hr)
|
|
{
|
|
// remap this error to invalid argument error
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
CoRevertToSelf();
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::ReregisterRunningDevice");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::SetICSInterfaces(/*[in]*/ long nCount, /*[in, size_is(nCount)]*/ GUID * arPrivateInterfaceGuids)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_INPROC | CALL_LOCALITY_LOCAL ));
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = CUPnPInterfaceList::Instance().HrSetICSInterfaces(nCount, arPrivateInterfaceGuids);
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::SetICSInterfaces");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CRegistrar::SetICSOff()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) (CALL_LOCALITY_LOCAL | CALL_LOCALITY_INPROC));
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = CUPnPInterfaceList::Instance().HrSetICSOff();
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::SetICSOff");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CRegistrar::HrSetAutoStart()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CALock lock(*this);
|
|
|
|
if(!m_bSetAutoStart)
|
|
{
|
|
SC_HANDLE scm = OpenSCManager(NULL, SERVICES_ACTIVE_DATABASE, SC_MANAGER_CONNECT);
|
|
if(!scm)
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
SC_HANDLE scUpnphost = OpenService(scm, L"upnphost", SERVICE_CHANGE_CONFIG);
|
|
if(!scUpnphost)
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(!ChangeServiceConfig(scUpnphost, SERVICE_NO_CHANGE, SERVICE_AUTO_START,
|
|
SERVICE_NO_CHANGE, NULL, NULL, NULL, NULL,
|
|
NULL, NULL, NULL))
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
CloseServiceHandle(scUpnphost);
|
|
}
|
|
CloseServiceHandle(scm);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidRegistrar, FAL, hr, FALSE, "CRegistrar::HrSetAutoStart");
|
|
return hr;
|
|
}
|
|
|