//+--------------------------------------------------------------------------- // // 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(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; }