windows-nt/Source/XPSP1/NT/net/upnp/host/upnphost/registrar/registrar.cpp

1106 lines
33 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
//+---------------------------------------------------------------------------
//
// 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;
}