2624 lines
78 KiB
C++
2624 lines
78 KiB
C++
//+---------------------------------------------------------------------------
|
|
//
|
|
// Microsoft Windows
|
|
// Copyright (C) Microsoft Corporation, 2000.
|
|
//
|
|
// File: D E S C R I P T I O N M A N A G E R . C P P
|
|
//
|
|
// Contents: Process UPnP Description document
|
|
//
|
|
// Notes:
|
|
//
|
|
// Author: mbend 18 Aug 2000
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "pch.h"
|
|
#pragma hdrstop
|
|
|
|
#include <msxml2.h>
|
|
|
|
#include "uhbase.h"
|
|
#include "hostp.h"
|
|
#include "DescriptionManager.h"
|
|
#include "uhsync.h"
|
|
#include "upfile.h"
|
|
#include "ncreg.h"
|
|
#include "ssdpapi.h"
|
|
#include "evtapi.h"
|
|
#include "uhutil.h"
|
|
#include "udhhttp.h" // remove this if you are moving the function for presentation virtual directory.
|
|
#include "ncxml.h"
|
|
#include "ssdpapi.h"
|
|
#include "uhcommon.h"
|
|
|
|
// String constants
|
|
const wchar_t c_szDescription[] = L"Description";
|
|
const wchar_t c_szUDNMappings[] = L"UDN Mappings";
|
|
const wchar_t c_szFiles[] = L"Files";
|
|
const wchar_t c_szFilename[] = L"Filename";
|
|
const wchar_t c_szMimetype[] = L"Mimetype";
|
|
const wchar_t c_szDescriptionDocuments[] = L"Description Documents";
|
|
const wchar_t c_szRemoveId[] = L"REMOVE";
|
|
|
|
CDescriptionManager::CDescriptionManager ()
|
|
{
|
|
}
|
|
|
|
CDescriptionManager::~CDescriptionManager ()
|
|
{
|
|
// Free description documents
|
|
BSTR bstr = NULL;
|
|
long n;
|
|
long nCount = m_documentTable.Values().GetCount();
|
|
for(n = 0; n < nCount; ++n)
|
|
{
|
|
bstr = const_cast<BSTR>(m_documentTable.Values()[n]);
|
|
SysFreeString(bstr);
|
|
}
|
|
m_documentTable.Clear();
|
|
|
|
// Unpublish and free the arrays for all publications
|
|
HandleList * pHandleList = NULL;
|
|
nCount = m_ssdpRegistrationTable.Values().GetCount();
|
|
for(n = 0; n < nCount; ++n)
|
|
{
|
|
pHandleList = const_cast<HandleList*>(m_ssdpRegistrationTable.Values()[n]);
|
|
if(pHandleList)
|
|
{
|
|
long nHandleLists = pHandleList->GetCount();
|
|
for(long n = 0; n < nHandleLists; ++n)
|
|
{
|
|
DeregisterService((*pHandleList)[n], TRUE);
|
|
}
|
|
delete pHandleList;
|
|
}
|
|
}
|
|
m_ssdpRegistrationTable.Clear();
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::GetContent(
|
|
/*[in]*/ REFGUID guidContent,
|
|
/*[out]*/ long * pnHeaderCount,
|
|
/*[out, string, size_is(,*pnHeaderCount,)]*/ wchar_t *** parszHeaders,
|
|
/*[out]*/ long * pnBytes,
|
|
/*[out, size_is(,*pnBytes)]*/ byte ** parBytes)
|
|
{
|
|
CALock lock(*this);
|
|
HRESULT hr = S_OK;
|
|
wchar_t ** arszHeaders = NULL;
|
|
long nHeaderCount = 2;
|
|
long nBytes = 0;
|
|
byte * arBytes = NULL;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Allocate the header array
|
|
hr = HrCoTaskMemAllocArray(2, &arszHeaders);
|
|
}
|
|
|
|
// Other header variables, filled in body and copied to [out]
|
|
// or cleaned up up at end of function
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Set header initially to NULL;
|
|
arszHeaders[0] = NULL;
|
|
arszHeaders[1] = NULL;
|
|
// See if it is a description document
|
|
BSTR * pbstr = m_documentTable.Lookup(guidContent);
|
|
if(pbstr)
|
|
{
|
|
// This GUID is a description document
|
|
|
|
// Allocate the content-type
|
|
hr = HrCoTaskMemAllocString(L"content-type: text/xml", arszHeaders);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Copy the document as ansi
|
|
// nLength is the number of (wide)chars in the source
|
|
// dSpace is the space reserved for the UTF-8 destination
|
|
|
|
long nLength = SysStringLen(*pbstr);
|
|
int dSpace = WideCharToMultiByte(CP_UTF8, 0, *pbstr, nLength, NULL, 0, NULL, NULL) + 1; // add 1 for NULL
|
|
|
|
char * szBody = NULL;
|
|
hr = HrCoTaskMemAllocArray(dSpace, &szBody);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(!WideCharToMultiByte(CP_UTF8, 0, *pbstr, nLength, szBody, dSpace, NULL, NULL))
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
arBytes = reinterpret_cast<byte*>(szBody);
|
|
nBytes = dSpace-1; // number of bytes less the terminating nul
|
|
arBytes[nBytes] = 0; // add NULL terminator
|
|
}
|
|
if(FAILED(hr))
|
|
{
|
|
CoTaskMemFree(szBody);
|
|
szBody = NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// See if it is in the file table
|
|
FileInfo * pFileInfo = m_fileTable.Lookup(guidContent);
|
|
if(pFileInfo)
|
|
{
|
|
// Allocate the content type
|
|
CUString strContentType;
|
|
hr = strContentType.HrAssign(L"content-type:");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strContentType.HrAppend(pFileInfo->m_mimetype);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strContentType.HrGetCOM(arszHeaders);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Load the file from disk
|
|
hr = HrLoadFileFromDisk(pFileInfo->m_filename, &nBytes, &arBytes);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// This provider didn't process it
|
|
hr = S_FALSE;
|
|
}
|
|
}
|
|
|
|
if(S_OK == hr)
|
|
{
|
|
wchar_t szBuf[128];
|
|
wsprintf(szBuf, L"content-length: %d", nBytes);
|
|
hr = HrCoTaskMemAllocString(szBuf, &arszHeaders[1]);
|
|
}
|
|
|
|
if(FAILED(hr) || S_FALSE == hr)
|
|
{
|
|
// Centralized cleanup code
|
|
|
|
if(arszHeaders)
|
|
{
|
|
if(*arszHeaders)
|
|
{
|
|
// Free header (at most one)
|
|
CoTaskMemFree(*arszHeaders);
|
|
}
|
|
if(arszHeaders[1])
|
|
{
|
|
CoTaskMemFree(arszHeaders[1]);
|
|
}
|
|
// Free length one header array
|
|
CoTaskMemFree(arszHeaders);
|
|
}
|
|
if(arBytes)
|
|
{
|
|
// Free body bytes
|
|
CoTaskMemFree(arBytes);
|
|
}
|
|
// Blank out the output params
|
|
*pnHeaderCount = 0;
|
|
*parszHeaders = NULL;
|
|
*pnBytes = 0;
|
|
*parBytes = NULL;
|
|
}
|
|
}
|
|
if(S_OK == hr)
|
|
{
|
|
// Copy to output parameters
|
|
*pnHeaderCount = nHeaderCount;
|
|
*parszHeaders = arszHeaders;
|
|
*pnBytes = nBytes;
|
|
*parBytes = arBytes;
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetContent");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrNewUDNString(CUString & strUUID)
|
|
{
|
|
UUID uuid;
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = CoCreateGuid(&uuid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrGUIDToUDNString(uuid, strUUID);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrNewUDNString");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrGetURLBase(CUString & strURLBase)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = strURLBase.HrAssign(L"http://");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strURLBase.HrAppend(c_szReplaceGuid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strURLBase.HrAppend(L":2869/upnphost/");
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrGetURLBase");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrGetContentURL(const UUID & uuid, CUString & strURL)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = strURL.HrAssign(L"udhisapi.dll?content=");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strUUID;
|
|
hr = HrGUIDToUDNString(uuid, strUUID);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strURL.HrAppend(strUUID);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrGetContentURL");
|
|
return hr;
|
|
}
|
|
|
|
// Create Virual directory using the Physical Device Identifier and map it to the resource path
|
|
HRESULT HrCreatePresentationVirtualDir(const UUID &uuid, const LPWSTR szResourcePath)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CUString strUUID;
|
|
BSTR bstrVirDir;
|
|
|
|
hr = HrGUIDToUDNString(uuid, strUUID);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strTmp;
|
|
hr = strTmp.HrAssign(L"/");
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = strTmp.HrAppend(strUUID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = strTmp.HrGetBSTR(&bstrVirDir);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
HrRemoveVroot(bstrVirDir);
|
|
hr = HrAddVroot(bstrVirDir,szResourcePath);
|
|
|
|
SysFreeString(bstrVirDir);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrCreatePresentationVirtualDir");
|
|
return hr;
|
|
}
|
|
|
|
// Remove the virtual directory
|
|
HRESULT HrRemovePresentationVirtualDir(const UUID &uuid )
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CUString strUUID;
|
|
BSTR bstrVirDir ;
|
|
CUString strTmp;
|
|
|
|
hr = strTmp.HrAssign(L"/");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrGUIDToUDNString(uuid, strUUID);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strTmp.HrAppend(strUUID);
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strTmp.HrGetBSTR(&bstrVirDir);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRemoveVroot(bstrVirDir);
|
|
SysFreeString(bstrVirDir);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrRemovePresentationVirtualDir");
|
|
return hr;
|
|
}
|
|
|
|
// prepare base URL for the presentation URL
|
|
HRESULT HrGetPresentationBaseURL(const UUID &uuid, CUString &strPresentationBaseURL)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strUUID;
|
|
hr = strPresentationBaseURL.HrAppend(L"/");
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrGUIDToUDNString(uuid, strUUID);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationBaseURL.HrAppend(strUUID);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationBaseURL.HrAppend(L"/");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrGetPresentationBaseURL");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrGenerateControlAndEventURLs(
|
|
IXMLDOMNodePtr & pNodeDevice)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
CUString strControlURLBase;
|
|
CUString strEventURLBase;
|
|
CUString strUDN;
|
|
|
|
hr = strControlURLBase.HrAssign(L"udhisapi.dll?control=");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strEventURLBase.HrAssign(L"udhisapi.dll?event=");
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fetch the UDN
|
|
hr = HrSelectNodeText(L"UDN", pNodeDevice, strUDN);
|
|
}
|
|
|
|
// Get all of the services
|
|
IXMLDOMNodeListPtr pNodeListServices;
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNodes(L"serviceList/service", pNodeDevice, pNodeListServices);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNodeService;
|
|
// Process each service
|
|
HRESULT hrTmp = S_OK;
|
|
hrTmp = pNodeListServices->nextNode(pNodeService.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
CUString strSid;
|
|
hr = HrSelectNodeText(L"serviceId", pNodeService, strSid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Generate the URL suffix
|
|
CUString strURL;
|
|
hr = strURL.HrAssign(strUDN);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strURL.HrAppend(L"+");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strURL.HrAppend(strSid);
|
|
|
|
}
|
|
}
|
|
CUString strControlURL;
|
|
CUString strEventURL;
|
|
// Build the real URLs
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strControlURL.HrAssign(strControlURLBase);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strControlURL.HrAppend(strURL);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strEventURL.HrAssign(strEventURLBase);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strEventURL.HrAppend(strURL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Now replace them in the document
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strNode;
|
|
|
|
hr = strNode.HrAssign(L"/upnphost/");
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = strNode.HrAppend(strControlURL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectAndSetNodeText(L"controlURL",
|
|
pNodeService,
|
|
strNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
CUString strOldText;
|
|
|
|
hr = HrSelectNodeText(L"eventSubURL", pNodeService,
|
|
strOldText);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CUString strNode;
|
|
|
|
// Only replace the URL if it doesn't have the remove
|
|
// identifier in it. Otherwise, remove the identifier
|
|
//
|
|
if (lstrcmpi(strOldText, c_szRemoveId))
|
|
{
|
|
hr = strNode.HrAssign(L"/upnphost/");
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = strNode.HrAppend(strEventURL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectAndSetNodeText(L"eventSubURL",
|
|
pNodeService,
|
|
strNode);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CUString strEmpty;
|
|
|
|
hr = strEmpty.HrAssign(L"");
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectAndSetNodeText(L"eventSubURL",
|
|
pNodeService, strEmpty);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrGenerateControlAndEventURLs");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrGenDescAndUDNURLForPresentation(
|
|
REFGUID guidPhysicalDeviceIdentifier,
|
|
IXMLDOMNodePtr & pNodeDevice,
|
|
CUString & strDescAndUDNURL)
|
|
{
|
|
HRESULT hr = S_OK ;
|
|
CUString strDesc ;
|
|
CUString strUDN ;
|
|
|
|
hr = HrGetContentURL(guidPhysicalDeviceIdentifier, strDesc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strDescAndUDNURL.HrAssign(L"/upnphost/");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strDescAndUDNURL.HrAppend(strDesc);
|
|
}
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strDescAndUDNURL.HrAppend(L"+");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNodeText(L"UDN", pNodeDevice, strUDN);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strDescAndUDNURL.HrAppend(strUDN);
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrGenDescAndUDNURLForPresentation");
|
|
return hr;
|
|
}
|
|
|
|
BOOL IsAbsoluteURL(BSTR bstrPresURL)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
const WCHAR c_szhttp[] = L"http://";
|
|
const DWORD c_chhttp = celems(c_szhttp)-1;
|
|
|
|
// include other conditions for absolute URL like https:// etc.
|
|
if(wcsncmp(bstrPresURL,c_szhttp,c_chhttp) == 0 )
|
|
return true;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
HRESULT HrGenPresentationURL(
|
|
REFGUID guidPhysicalDeviceIdentifier,
|
|
IXMLDOMNodePtr & pNodeDevice,
|
|
CUString & strPresFileName,
|
|
CUString & strPresentationURL)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
CUString strDescURL ;
|
|
|
|
hr = HrGetPresentationBaseURL(guidPhysicalDeviceIdentifier,strPresentationURL);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationURL.HrAppend(strPresFileName);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationURL.HrAppend(L"?");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrGenDescAndUDNURLForPresentation(guidPhysicalDeviceIdentifier,pNodeDevice,strDescURL);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationURL.HrAppend(strDescURL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrGenPresentationURL");
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Replaces the presentation URL for a device. If presentationURL element has absolute address no change is made.
|
|
// File name to the main presentation page is expected, can be without presentation page
|
|
HRESULT HrReplacePresentationURL(
|
|
REFGUID guidPhysicalDeviceIdentifier,
|
|
IXMLDOMNodePtr & pNodeDevice,
|
|
BOOL *fIsPresURLTagPresent)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
CUString strPresentationURL;
|
|
CUString strPresFileName ;
|
|
CUString strUDN;
|
|
CUString strUrl;
|
|
CUString strDescAndUDNURL;
|
|
BSTR bstrPresURL = NULL;
|
|
WCHAR chQueryChar = '?' ;
|
|
|
|
hr = HrSelectNodeText(L"presentationURL", pNodeDevice, strPresFileName);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresFileName.HrGetBSTR(&bstrPresURL);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(bstrPresURL != NULL && (wcscmp(bstrPresURL,L"") != 0 ) ) { // check if its absolute URL !!!
|
|
//if(wcsncmp(bstrPresURL,c_szhttp,c_chhttp) == 0 ) {
|
|
if(IsAbsoluteURL(bstrPresURL)) {
|
|
if (wcschr(bstrPresURL,chQueryChar) ) {
|
|
hr = S_OK;
|
|
}
|
|
else {
|
|
hr = HrGenDescAndUDNURLForPresentation(guidPhysicalDeviceIdentifier,pNodeDevice,strDescAndUDNURL);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationURL.HrAppend(strPresFileName);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationURL.HrAppend(L"?");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPresentationURL.HrAppend(strDescAndUDNURL);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectAndSetNodeText(L"presentationURL", pNodeDevice, strPresentationURL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
*fIsPresURLTagPresent = true ;
|
|
hr = HrGenPresentationURL(guidPhysicalDeviceIdentifier,pNodeDevice,strPresFileName,strPresentationURL);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectAndSetNodeText(L"presentationURL", pNodeDevice, strPresentationURL);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
// write a function which will test for tag and return S_FALSE if tag is not present
|
|
hr = S_OK;
|
|
}
|
|
SysFreeString(bstrPresURL);
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrReplacePresentationURL");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPersistDeviceSettingsToRegistry(
|
|
const PhysicalDeviceIdentifier & physicalDeviceIdentifier,
|
|
const UDNReplacementTable & udnReplacementTable,
|
|
const FileTable & fileTable,
|
|
BOOL bPersist)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Create / open device host key
|
|
HKEY hKeyDescription;
|
|
DWORD dwDisposition = 0;
|
|
hr = HrCreateOrOpenDescriptionKey(&hKeyDescription);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Generate key name and registry key
|
|
CUString strPdi;
|
|
HKEY hKeyPdi;
|
|
hr = strPdi.HrInitFromGUID(physicalDeviceIdentifier);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegCreateKeyEx(hKeyDescription, strPdi, 0, KEY_ALL_ACCESS, NULL, &hKeyPdi, &dwDisposition);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Create UDN mappings
|
|
HKEY hKeyMappings;
|
|
hr = HrRegCreateKeyEx(hKeyPdi, c_szUDNMappings, 0, KEY_ALL_ACCESS, NULL, &hKeyMappings, &dwDisposition);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
long nMappings = udnReplacementTable.Keys().GetCount();
|
|
for(long n = 0; n < nMappings && SUCCEEDED(hr); ++n)
|
|
{
|
|
// Create key for mapping
|
|
HKEY hKeyMapping;
|
|
hr = HrRegCreateKeyEx(hKeyMappings, udnReplacementTable.Keys()[n],
|
|
0, KEY_ALL_ACCESS, NULL, &hKeyMapping, &dwDisposition);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Write the value for the mapping
|
|
hr = HrRegSetSz(hKeyMapping, L"", udnReplacementTable.Values()[n]);
|
|
RegCloseKey(hKeyMapping);
|
|
}
|
|
}
|
|
RegCloseKey(hKeyMappings);
|
|
}
|
|
// Create file mappings for a fully persistent device
|
|
if(bPersist)
|
|
{
|
|
HKEY hKeyFileMappings;
|
|
hr = HrRegCreateKeyEx(hKeyPdi, c_szFiles, 0, KEY_ALL_ACCESS, NULL, &hKeyFileMappings, &dwDisposition);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
long nMappings = fileTable.Keys().GetCount();
|
|
for(long n = 0; n < nMappings && SUCCEEDED(hr); ++n)
|
|
{
|
|
CUString strFileId;
|
|
hr = strFileId.HrInitFromGUID(fileTable.Keys()[n]);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Create key for mapping
|
|
HKEY hKeyMapping;
|
|
hr = HrRegCreateKeyEx(hKeyFileMappings, strFileId, 0, KEY_ALL_ACCESS, NULL, &hKeyMapping, &dwDisposition);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Save values
|
|
hr = HrRegSetSz(hKeyMapping, c_szFilename, fileTable.Values()[n].m_filename);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegSetSz(hKeyMapping, c_szMimetype, fileTable.Values()[n].m_mimetype);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey(hKeyFileMappings);
|
|
}
|
|
}
|
|
RegCloseKey(hKeyPdi);
|
|
}
|
|
}
|
|
// If anything fails, whack the whole key
|
|
if(FAILED(hr))
|
|
{
|
|
HrRegDeleteKeyTree(hKeyDescription, strPdi);
|
|
}
|
|
RegCloseKey(hKeyDescription);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::HrPersistDeviceSettingsToRegistry");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrLoadDocumentAndRootNode(
|
|
const PhysicalDeviceIdentifier & physicalDeviceIdentifier,
|
|
IXMLDOMNodePtr & pRootNode)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
// Lookup the id
|
|
BSTR * pbstrDocument = m_documentTable.Lookup(physicalDeviceIdentifier);
|
|
if(pbstrDocument)
|
|
{
|
|
// Load the document
|
|
IXMLDOMDocumentPtr pDoc;
|
|
|
|
hr = HrLoadDocument(*pbstrDocument, pDoc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pRootNode.HrAttach(pDoc);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::HrLoadDocumentAndRootNode");
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CDescriptionManager::HrPDT_FetchCollections(
|
|
BSTR bstrTemplate,
|
|
IXMLDOMDocumentPtr & pDoc,
|
|
IXMLDOMNodePtr & pRootNode,
|
|
CUString & strRootUdnOld,
|
|
IXMLDOMNodeListPtr & pNodeListDevices,
|
|
IXMLDOMNodeListPtr & pNodeListUDNs,
|
|
IXMLDOMNodeListPtr & pNodeListSCPDURLs,
|
|
IXMLDOMNodeListPtr & pNodeListIcons)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_FetchCollections");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Load document and fetch needed items
|
|
hr = HrLoadDocument(bstrTemplate, pDoc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pRootNode.HrAttach(pDoc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get the old root UDN
|
|
hr = HrSelectNodeText(L"/root/device/UDN", pRootNode, strRootUdnOld);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get the lists
|
|
hr = HrSelectNodes(L"//device", pRootNode, pNodeListDevices);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNodes(L"//UDN", pRootNode, pNodeListUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNodes(L"//SCPDURL", pRootNode, pNodeListSCPDURLs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNodes(L"//icon", pRootNode, pNodeListIcons);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_FetchCollections");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPDT_DoUDNToUDNMapping(
|
|
IXMLDOMNodeListPtr & pNodeListUDNs,
|
|
UDNReplacementTable & udnReplacementTable)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_DoUDNToUDNMapping");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Do UDN to UDN mapping
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
// Process each UDN
|
|
hrTmp = pNodeListUDNs->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Allocate UDN storage and generate new UDN
|
|
CUString strOld;
|
|
CUString strNew;
|
|
hr = HrNewUDNString(strNew);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Read the old UDN
|
|
hr = HrGetNodeText(pNode, strOld);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Do replacement
|
|
hr = HrSetNodeText(pNode, strNew);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add temporary table mapping
|
|
hr = udnReplacementTable.HrInsertTransfer(strOld, strNew);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_DoUDNToUDNMapping");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPDT_ReregisterUDNsInDescriptionDocument(
|
|
UDNReplacementTable & udnReplacementTable,
|
|
IXMLDOMNodeListPtr & pNodeListUDNs)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReregisterUDNsInDescriptionDocument");
|
|
HRESULT hr = S_OK;
|
|
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
// Process each UDN
|
|
hrTmp = pNodeListUDNs->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Read the old UDN
|
|
CUString strOld;
|
|
hr = HrGetNodeText(pNode, strOld);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Lookup in replacement table
|
|
CUString * pstrNew = udnReplacementTable.Lookup(strOld);
|
|
if(pstrNew)
|
|
{
|
|
// Do the replacement
|
|
hr = HrSetNodeText(pNode, *pstrNew);
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidDescMan, "HrPDT_ReregisterUDNsInDescriptionDocument: Got invalid UDN in reregister '%S'",
|
|
static_cast<const wchar_t *>(strOld));
|
|
hr = E_UNEXPECTED;
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReregisterUDNsInDescriptionDocument");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPDT_FetchPhysicalIdentifier(
|
|
UDNReplacementTable & udnReplacementTable,
|
|
const CUString & strRootUdnOld,
|
|
PhysicalDeviceIdentifier & pdi)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_FetchPhysicalIdentifier");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Fetch identifier of root node
|
|
UDN * pUDN = udnReplacementTable.Lookup(strRootUdnOld);
|
|
if(!pUDN)
|
|
{
|
|
TraceTag(ttidError, "CDescriptionManager::ProcessDescriptionTemplate: We can't find the root UDN.");
|
|
hr = E_INVALIDARG;
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrUDNStringToGUID(*pUDN, pdi);
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_FetchPhysicalIdentifier");
|
|
return hr;
|
|
}
|
|
|
|
BOOL FEventedVariablesPresent(
|
|
IXMLDOMNodeListPtr pNodeList)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
HRESULT hrTmp;
|
|
BOOL fResult = FALSE;
|
|
|
|
while (SUCCEEDED(hr) && !fResult)
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
|
|
// Process each node
|
|
hrTmp = pNodeList->nextNode(pNode.AddressOf());
|
|
if (S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
|
|
BSTR bstrSendEvents = NULL;
|
|
|
|
hr = HrGetTextValueFromAttribute(pNode, L"sendEvents", &bstrSendEvents);
|
|
if (S_OK == hr)
|
|
{
|
|
// sendEvents was present so we know there is at least one evented
|
|
// variable.. ok to exit now
|
|
if (!lstrcmpiW(bstrSendEvents, L"yes"))
|
|
{
|
|
fResult = TRUE;
|
|
}
|
|
|
|
SysFreeString(bstrSendEvents);
|
|
}
|
|
else
|
|
{
|
|
// sendEvents was not present which means we default to evented
|
|
// ok to exit now.
|
|
fResult = TRUE;
|
|
}
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
HRESULT HrCheckForEventedVariables(
|
|
CUString & strUrl)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrUrl;
|
|
BOOL fEventedVariables = FALSE;
|
|
|
|
hr = strUrl.HrGetBSTR(&bstrUrl);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMDocumentPtr pDoc;
|
|
|
|
hr = HrLoadDocumentFromFile(bstrUrl, pDoc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pRootNode;
|
|
|
|
hr = pRootNode.HrAttach(pDoc);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodeListPtr pNodeList;
|
|
|
|
hr = HrSelectNodes(L"//stateVariable",
|
|
pRootNode, pNodeList);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (FEventedVariablesPresent(pNodeList))
|
|
{
|
|
fEventedVariables = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
SysFreeString(bstrUrl);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = fEventedVariables ? S_OK : S_FALSE;
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "HrCheckForEventedVariables");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPDT_ReplaceSCPDURLs(
|
|
IXMLDOMNodeListPtr & pNodeListSCPDURLs,
|
|
const wchar_t * szResourcePath,
|
|
FileTable & fileTable)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReplaceSCPDURLs");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Replace SCPDURLs
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
// Process each SCPDURL
|
|
hrTmp = pNodeListSCPDURLs->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Allocate filename storage and generate new URL
|
|
CUString strOld;
|
|
CUString strNew;
|
|
GUID guid;
|
|
hr = CoCreateGuid(&guid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Generate the URL
|
|
hr = HrGetContentURL(guid, strNew);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Read the filename
|
|
CUString strFilename;
|
|
hr = HrGetNodeText(pNode, strFilename);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Make an absolute filename
|
|
hr = HrMakeFullPath(szResourcePath, strFilename, strOld);
|
|
}
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strNode;
|
|
|
|
hr = strNode.HrAssign(L"/upnphost/");
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = strNode.HrAppend(strNew);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Do replacement
|
|
hr = HrSetNodeText(pNode, strNode);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Determine if the eventSubURL should be replaced later on
|
|
//
|
|
hr = HrCheckForEventedVariables(strOld);
|
|
if (S_FALSE == hr)
|
|
{
|
|
// No evented variables were found.. mark the eventSubURL
|
|
// element to be emptied later on when we process the
|
|
// eventing URLs.
|
|
//
|
|
|
|
CUString strRemove;
|
|
|
|
hr = strRemove.HrAssign(c_szRemoveId);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectAndSetNodeText(L"../eventSubURL", pNode,
|
|
strRemove);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Add mapping to data structure
|
|
FileInfo fi;
|
|
fi.m_filename.Transfer(strOld);
|
|
hr = fi.m_mimetype.HrAssign(L"text/xml");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = fileTable.HrInsertTransfer(guid, fi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReplaceSCPDURLs");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPDT_ReplaceIcons(
|
|
IXMLDOMNodeListPtr & pNodeListIcons,
|
|
const wchar_t * szResourcePath,
|
|
FileTable & fileTable)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReplaceIcons");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Replace icons
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
// Process each icon
|
|
hrTmp = pNodeListIcons->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Allocate filename storage and generate new URL
|
|
CUString strOld;
|
|
CUString strNew;
|
|
GUID guid;
|
|
hr = CoCreateGuid(&guid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Generate the URL
|
|
hr = HrGetContentURL(guid, strNew);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Read the filename
|
|
CUString strFilename;
|
|
hr = HrSelectNodeText(L"url", pNode, strFilename);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Make an absolute filename
|
|
hr = HrMakeFullPath(szResourcePath, strFilename, strOld);
|
|
}
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strNode;
|
|
|
|
hr = strNode.HrAssign(L"/upnphost/");
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = strNode.HrAppend(strNew);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Do replacement
|
|
hr = HrSelectAndSetNodeText(L"url", pNode, strNode);
|
|
}
|
|
}
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add mapping to data structure
|
|
FileInfo fi;
|
|
fi.m_filename.Transfer(strOld);
|
|
// Get the mimetype
|
|
CUString strMimetype;
|
|
hr = HrSelectNodeText(L"mimetype", pNode, strMimetype);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
fi.m_mimetype.Transfer(strMimetype);
|
|
hr = fileTable.HrInsertTransfer(guid, fi);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReplaceIcons");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPDT_ReplaceControlAndEventURLs(
|
|
IXMLDOMNodeListPtr & pNodeListDevices)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReplaceControlAndEventURLs");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Fill in the control and eventing URL for each document
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
// Process each device
|
|
hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
hr = HrGenerateControlAndEventURLs(pNode);
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReplaceControlAndEventURLs");
|
|
return hr;
|
|
}
|
|
|
|
// Iterates over the devices and fills in the presentation URL for each device
|
|
HRESULT CDescriptionManager::HrPDT_ProcessPresentationURLs(
|
|
REFGUID guidPhysicalDeviceIdentifier,
|
|
IXMLDOMNodeListPtr & pNodeListDevices,
|
|
BOOL *fIsPresURLTagPresent)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ProcessPresentationURLs");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Fill in the presentation URL for each device
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
hr = HrReplacePresentationURL(guidPhysicalDeviceIdentifier,pNode,fIsPresURLTagPresent);
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ProcessPresentationURLs");
|
|
return hr;
|
|
}
|
|
|
|
|
|
HRESULT CDescriptionManager::HrPDT_PersistDescriptionDocument(
|
|
const PhysicalDeviceIdentifier & pdi,
|
|
IXMLDOMDocumentPtr & pDoc)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_PersistDescriptionDocument");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Write description document to disk
|
|
|
|
// Get the path to save to
|
|
CUString strPath;
|
|
hr = HrGetDescriptionDocumentPath(pdi, strPath);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BSTR bstr = NULL;
|
|
hr = strPath.HrGetBSTR(&bstr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
var.vt = VT_BSTR;
|
|
var.bstrVal = bstr;
|
|
hr = pDoc->save(var);
|
|
SysFreeString(bstr);
|
|
TraceHr(ttidError, FAL, hr, FALSE, "ProcessDescriptionTemplate: IXMLDOMDocument::save failed.");
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_PersistDescriptionDocument");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::ProcessDescriptionTemplate(
|
|
/*[in]*/ BSTR bstrTemplate,
|
|
/*[in, string]*/ const wchar_t * szResourcePath,
|
|
/*[in, out]*/ GUID * pguidPhysicalDeviceIdentifier,
|
|
/*[in]*/ BOOL bPersist,
|
|
/*[in]*/ BOOL bReregister)
|
|
{
|
|
CHECK_POINTER(bstrTemplate);
|
|
CHECK_POINTER(szResourcePath);
|
|
CHECK_POINTER(pguidPhysicalDeviceIdentifier);
|
|
|
|
CALock lock(*this);
|
|
HRESULT hr = S_OK;
|
|
|
|
// Values to fetch in first phase
|
|
IXMLDOMDocumentPtr pDoc;
|
|
IXMLDOMNodePtr pRootNode;
|
|
CUString strRootUdnOld;
|
|
IXMLDOMNodeListPtr pNodeListDevices;
|
|
IXMLDOMNodeListPtr pNodeListUDNs;
|
|
IXMLDOMNodeListPtr pNodeListSCPDURLs;
|
|
IXMLDOMNodeListPtr pNodeListIcons;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
// Load document and fetch needed items
|
|
hr = HrPDT_FetchCollections(bstrTemplate, pDoc, pRootNode, strRootUdnOld, pNodeListDevices,
|
|
pNodeListUDNs, pNodeListSCPDURLs, pNodeListIcons);
|
|
|
|
}
|
|
|
|
// Temporary data structures to do work in
|
|
PhysicalDeviceIdentifier pdi;
|
|
UDNReplacementTable udnReplacementTable;
|
|
FileTable fileTable;
|
|
|
|
if(!bReregister)
|
|
{
|
|
// Do UDN to UDN mapping
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPDT_DoUDNToUDNMapping(pNodeListUDNs, udnReplacementTable);
|
|
}
|
|
|
|
// Fetch identifier of root node
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPDT_FetchPhysicalIdentifier(udnReplacementTable, strRootUdnOld, pdi);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Set the physical device identifier
|
|
pdi = *pguidPhysicalDeviceIdentifier;
|
|
// Open physical device identifier's registry key
|
|
HKEY hKeyPdi;
|
|
hr = HrOpenPhysicalDeviceDescriptionKey(pdi, &hKeyPdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Load the UDNs from registry
|
|
hr = HrLD_ReadUDNMappings(hKeyPdi, udnReplacementTable);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Update UDNs in the document
|
|
hr = HrPDT_ReregisterUDNsInDescriptionDocument(udnReplacementTable, pNodeListUDNs);
|
|
}
|
|
RegCloseKey(hKeyPdi);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Replace SCPDURLs
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPDT_ReplaceSCPDURLs(pNodeListSCPDURLs, szResourcePath, fileTable);
|
|
}
|
|
|
|
// Replace icons
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPDT_ReplaceIcons(pNodeListIcons, szResourcePath, fileTable);
|
|
}
|
|
|
|
// Fill in the control and eventing URL for each document
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPDT_ReplaceControlAndEventURLs(pNodeListDevices);
|
|
}
|
|
|
|
// Fill in the presentation URL for each device
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BOOL fIsPresURLTagPresent = false ;
|
|
hr = pNodeListDevices->reset();
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPDT_ProcessPresentationURLs(pdi,pNodeListDevices,&fIsPresURLTagPresent);
|
|
// Create Virtual Directory for the presentation files
|
|
if(SUCCEEDED(hr) && fIsPresURLTagPresent )
|
|
{
|
|
BSTR bstrResourcePath;
|
|
bstrResourcePath = SysAllocString(szResourcePath);
|
|
hr = HrCreatePresentationVirtualDir(pdi,bstrResourcePath);
|
|
SysFreeString(bstrResourcePath);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Write description document to disk
|
|
if(SUCCEEDED(hr) && bPersist)
|
|
{
|
|
hr = HrPDT_PersistDescriptionDocument(pdi, pDoc);
|
|
}
|
|
|
|
// Commit changes to registry for bPersist
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPersistDeviceSettingsToRegistry(pdi, udnReplacementTable, fileTable, bPersist);
|
|
}
|
|
|
|
// Commit changes to variables
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add entries to the cleanup table
|
|
CleanupItem ci;
|
|
ci.m_physicalDeviceIdentifier = pdi;
|
|
long nCount = fileTable.Keys().GetCount();
|
|
for(long n = 0; n < nCount && SUCCEEDED(hr); ++n)
|
|
{
|
|
ci.m_fileId = fileTable.Keys()[n];
|
|
hr = m_cleanupList.HrPushBack(ci);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
{
|
|
CLock lockTable(m_critSecReplacementTable);
|
|
hr = m_replacementTable.HrInsertTransfer(pdi, udnReplacementTable);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_fileTable.HrAppendTableTransfer(fileTable);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Save description document
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BSTR bstrDocument = NULL;
|
|
hr = pRootNode->get_xml(&bstrDocument);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_documentTable.HrInsert(pdi, bstrDocument);
|
|
if(FAILED(hr))
|
|
{
|
|
SysFreeString(bstrDocument);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Return identifier
|
|
if(SUCCEEDED(hr) && !bReregister)
|
|
{
|
|
*pguidPhysicalDeviceIdentifier = pdi;
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
RemoveDescription(pdi, FALSE);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::ProcessDescriptionTemplate");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrRegisterService(PSSDP_MESSAGE pSsdpMessage, DWORD dwFlags, HANDLE * pHandle)
|
|
{
|
|
CHECK_POINTER(pSsdpMessage);
|
|
CHECK_POINTER(pHandle);
|
|
HRESULT hr = S_OK;
|
|
|
|
*pHandle = RegisterService(pSsdpMessage, dwFlags);
|
|
if(INVALID_HANDLE_VALUE == *pHandle)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrRegisterService:(%s) (%s)", pSsdpMessage->szType, pSsdpMessage->szUSN);
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPD_DoRootNotification(
|
|
IXMLDOMNodePtr & pNodeRootDevice,
|
|
SSDP_MESSAGE * pMsg,
|
|
HandleList * pHandleList)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPD_DoRootNotification");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Do the root node notification
|
|
char szaUSN[256];
|
|
HANDLE hSvc;
|
|
|
|
// Get the UDN
|
|
CUString strUDN;
|
|
hr = HrSelectNodeText(L"UDN", pNodeRootDevice, strUDN);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Format the fields, generate the notificatio, and save the handle
|
|
wsprintfA(szaUSN, "%S::upnp:rootdevice", static_cast<const wchar_t*>(strUDN));
|
|
pMsg->szUSN = szaUSN;
|
|
pMsg->szType = "upnp:rootdevice";
|
|
hr = HrRegisterService(pMsg, 0, &hSvc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pHandleList->HrPushBack(hSvc);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPD_DoRootNotification");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPD_DoDevicePublication(
|
|
IXMLDOMNodeListPtr & pNodeListDevices,
|
|
SSDP_MESSAGE * pMsg,
|
|
HandleList * pHandleList)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPD_DoDevicePublication");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Do the device publication
|
|
char szaUSN[256];
|
|
char szaType[256];
|
|
HANDLE hSvc;
|
|
|
|
// Process each node in the device list
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Fetch the UDN
|
|
CUString strUDN;
|
|
hr = HrSelectNodeText(L"UDN", pNode, strUDN);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
wsprintfA(szaUSN, "%S", static_cast<const wchar_t*>(strUDN));
|
|
pMsg->szUSN = szaUSN;
|
|
pMsg->szType = szaUSN;
|
|
hr = HrRegisterService(pMsg, 0, &hSvc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pHandleList->HrPushBack(hSvc);
|
|
}
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fetch the device type
|
|
CUString strDeviceType;
|
|
hr = HrSelectNodeText(L"deviceType", pNode, strDeviceType);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
wsprintfA(szaUSN, "%S::%S", static_cast<const wchar_t*>(strUDN), static_cast<const wchar_t*>(strDeviceType));
|
|
wsprintfA(szaType, "%S", static_cast<const wchar_t*>(strDeviceType));
|
|
pMsg->szUSN = szaUSN;
|
|
pMsg->szType = szaType;
|
|
hr = HrRegisterService(pMsg, 0, &hSvc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pHandleList->HrPushBack(hSvc);
|
|
}
|
|
}
|
|
}
|
|
// Do the services
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPD_DoServicePublication(pNode, strUDN, pMsg, pHandleList);
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPD_DoDevicePublication");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrPD_DoServicePublication(
|
|
IXMLDOMNodePtr & pNodeDevice,
|
|
const CUString & strUDN,
|
|
SSDP_MESSAGE * pMsg,
|
|
HandleList * pHandleList)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrPD_DoServicePublication");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Do the services
|
|
char szaUSN[256];
|
|
char szaType[256];
|
|
HANDLE hSvc;
|
|
|
|
// Get the services for this device
|
|
IXMLDOMNodeListPtr pNodeListServices;
|
|
hr = HrSelectNodes(L"serviceList/service", pNodeDevice, pNodeListServices);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Process each service in the list
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNodeService;
|
|
hrTmp = pNodeListServices->nextNode(pNodeService.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Fetch the service type
|
|
CUString strServiceType;
|
|
hr = HrSelectNodeText(L"serviceType", pNodeService, strServiceType);
|
|
// We need to only send out one anouncement for each service type.
|
|
// Do a selectSingleNode for this type and see if we match.
|
|
IXMLDOMNodePtr pNodeTemp;
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strPattern;
|
|
hr = strPattern.HrAssign(L"serviceList/service[./serviceType = '");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPattern.HrAppend(strServiceType);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPattern.HrAppend(L"']");
|
|
}
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNode(strPattern, pNodeDevice, pNodeTemp);
|
|
}
|
|
}
|
|
if(SUCCEEDED(hr) && S_OK == pNodeTemp.HrIsEqual(pNodeService))
|
|
{
|
|
wsprintfA(szaType, "%S", static_cast<const wchar_t*>(strServiceType));
|
|
wsprintfA(szaUSN, "%S::%S", static_cast<const wchar_t*>(strUDN),
|
|
static_cast<const wchar_t*>(strServiceType));
|
|
pMsg->szUSN = szaUSN;
|
|
pMsg->szType = szaType;
|
|
hr = HrRegisterService(pMsg, 0, &hSvc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pHandleList->HrPushBack(hSvc);
|
|
}
|
|
}
|
|
// Register with eventing
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegisterServiceWithEventing(pNodeService, strUDN, TRUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPD_DoServicePublication");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::PublishDescription(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
|
|
/*[in]*/ long nLifeTime)
|
|
{
|
|
CALock lock(*this);
|
|
HRESULT hr = S_OK;
|
|
char szaLocHeader[256];
|
|
SSDP_MESSAGE msg = {0};
|
|
CUString strUrl;
|
|
CUString strDesc;
|
|
HandleList *pHandleList = NULL;
|
|
|
|
// Set lifetime and invariants
|
|
msg.iLifeTime = nLifeTime;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
if ( !( pHandleList = new HandleList ) )
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
}
|
|
|
|
if ( SUCCEEDED( hr ) )
|
|
{
|
|
hr = HrGetContentURL(guidPhysicalDeviceIdentifier, strDesc);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrGetURLBase(strUrl);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strUrl.HrAppend(strDesc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
wsprintfA(szaLocHeader, "%S", static_cast<const wchar_t*>(strUrl));
|
|
msg.szLocHeader = szaLocHeader;
|
|
}
|
|
}
|
|
}
|
|
|
|
IXMLDOMNodeListPtr pNodeListDevices;
|
|
IXMLDOMNodePtr pNodeRootDevice;
|
|
|
|
// Get the DOM collections needed
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pRootNode;
|
|
hr = HrLoadDocumentAndRootNode(guidPhysicalDeviceIdentifier, pRootNode);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fetch the devices
|
|
hr = HrSelectNodes(L"//device", pRootNode, pNodeListDevices);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNode(L"/root/device", pRootNode, pNodeRootDevice);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Do the root node notification
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPD_DoRootNotification(pNodeRootDevice, &msg, pHandleList);
|
|
}
|
|
|
|
// Do the device publication
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrPD_DoDevicePublication(pNodeListDevices, &msg, pHandleList);
|
|
}
|
|
|
|
// If we have succeeded then add handle array to table
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
AssertSz(!m_ssdpRegistrationTable.Lookup(guidPhysicalDeviceIdentifier),
|
|
"CDescriptionManager::PublishDescription: Republishing known identifier!");
|
|
hr = m_ssdpRegistrationTable.HrInsert(guidPhysicalDeviceIdentifier, pHandleList);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Do this so it doesn't get cleared below
|
|
pHandleList = NULL;
|
|
}
|
|
}
|
|
|
|
// If handle list gets added to data structure it will be nulled out and this won't be cleaned up
|
|
if(pHandleList)
|
|
{
|
|
long nCount = pHandleList->GetCount();
|
|
for(long n = 0; n < nCount; ++n)
|
|
{
|
|
DeregisterService((*pHandleList)[n], TRUE);
|
|
}
|
|
delete pHandleList;
|
|
}
|
|
if(FAILED(hr))
|
|
{
|
|
HrRD_RemoveFromEventing(guidPhysicalDeviceIdentifier);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::PublishDescription");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrLD_ReadUDNMappings(
|
|
HKEY hKeyPdi,
|
|
UDNReplacementTable & udnReplacementTable)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrLD_ReadUDNMappings");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Read the UDN mappings
|
|
HKEY hKeyMappings;
|
|
hr = HrRegOpenKeyEx(hKeyPdi, c_szUDNMappings, KEY_ALL_ACCESS, &hKeyMappings);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
wchar_t szBuf[_MAX_PATH];
|
|
DWORD dwSize = _MAX_PATH;
|
|
FILETIME ft;
|
|
DWORD dwIndex;
|
|
for(dwIndex = 0;
|
|
SUCCEEDED(hr) && S_OK == HrRegEnumKeyEx(hKeyMappings, dwIndex, szBuf, &dwSize, NULL, NULL, &ft);
|
|
dwSize = _MAX_PATH, ++dwIndex)
|
|
{
|
|
// Open the mapping key
|
|
HKEY hKeyMapping;
|
|
hr = HrRegOpenKeyEx(hKeyMappings, szBuf, KEY_ALL_ACCESS, &hKeyMapping);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strFrom;
|
|
CUString strTo;
|
|
hr = strFrom.HrAssign(szBuf);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegQueryString(hKeyMapping, L"", strTo);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = udnReplacementTable.HrInsertTransfer(strFrom, strTo);
|
|
}
|
|
}
|
|
RegCloseKey(hKeyMapping);
|
|
}
|
|
}
|
|
RegCloseKey(hKeyMappings);
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_ReadUDNMappings");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrLD_ReadFileMappings(
|
|
HKEY hKeyPdi,
|
|
FileTable & fileTable)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrLD_ReadFileMappings");
|
|
HRESULT hr = S_OK;
|
|
|
|
HKEY hKeyFileMappings;
|
|
hr = HrRegOpenKeyEx(hKeyPdi, c_szFiles, KEY_ALL_ACCESS, &hKeyFileMappings);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
wchar_t szBuf[_MAX_PATH];
|
|
DWORD dwSize = _MAX_PATH;
|
|
FILETIME ft;
|
|
DWORD dwIndex;
|
|
for(dwIndex = 0;
|
|
SUCCEEDED(hr) && S_OK == HrRegEnumKeyEx(hKeyFileMappings, dwIndex, szBuf, &dwSize, NULL, NULL, &ft);
|
|
dwSize = _MAX_PATH, ++dwIndex)
|
|
{
|
|
// Open the mapping key
|
|
HKEY hKeyMapping;
|
|
hr = HrRegOpenKeyEx(hKeyFileMappings, szBuf, KEY_ALL_ACCESS, &hKeyMapping);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Convert the FileId to a guid
|
|
GUID guidFileId;
|
|
hr = CLSIDFromString(szBuf, &guidFileId);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Read the values
|
|
CUString strFilename;
|
|
CUString strMimetype;
|
|
hr = HrRegQueryString(hKeyMapping, c_szFilename, strFilename);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegQueryString(hKeyMapping, c_szMimetype, strMimetype);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
FileInfo fi;
|
|
fi.m_filename.Transfer(strFilename);
|
|
fi.m_mimetype.Transfer(strMimetype);
|
|
hr = fileTable.HrInsertTransfer(guidFileId, fi);
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey(hKeyMapping);
|
|
}
|
|
}
|
|
RegCloseKey(hKeyFileMappings);
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_ReadFileMappings");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrLD_LoadDescriptionDocumentFromDisk(
|
|
const PhysicalDeviceIdentifier & pdi,
|
|
IXMLDOMDocumentPtr & pDoc)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrLD_LoadDescriptionDocumentFromDisk");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Load the document - use the DOM to at least validate that it is XML
|
|
|
|
// Get the path to load from
|
|
CUString strPath;
|
|
hr = HrGetDescriptionDocumentPath(pdi, strPath);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
BSTR bstr = NULL;
|
|
hr = strPath.HrGetBSTR(&bstr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pDoc.HrCreateInstanceInproc(CLSID_DOMDocument30);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
VARIANT var;
|
|
VariantInit(&var);
|
|
var.vt = VT_BSTR;
|
|
var.bstrVal = bstr;
|
|
VARIANT_BOOL vb;
|
|
hr = pDoc->load(var, &vb);
|
|
SysFreeString(bstr);
|
|
TraceHr(ttidError, FAL, hr, FALSE, "LoadDescription: IXMLDOMDocument::load failed.");
|
|
if(SUCCEEDED(hr) && !vb)
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
if(FAILED(hr))
|
|
{
|
|
pDoc.Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_LoadDescriptionDocumentFromDisk");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrLD_SaveDescriptionDocumentText(
|
|
IXMLDOMDocumentPtr & pDoc,
|
|
const PhysicalDeviceIdentifier & pdi)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrLD_SaveDescriptionDocumentText");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Save description document
|
|
BSTR bstrDocument = NULL;
|
|
IXMLDOMNodePtr pRootNode;
|
|
hr = pRootNode.HrAttach(pDoc);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = pRootNode->get_xml(&bstrDocument);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_documentTable.HrInsert(pdi, bstrDocument);
|
|
if(FAILED(hr))
|
|
{
|
|
SysFreeString(bstrDocument);
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_SaveDescriptionDocumentText");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::LoadDescription(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier)
|
|
{
|
|
CALock lock(*this);
|
|
HRESULT hr = S_OK;
|
|
|
|
UDNReplacementTable udnReplacementTable;
|
|
FileTable fileTable;
|
|
|
|
// Open physical device identifier's registry key
|
|
HKEY hKeyPdi;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrOpenPhysicalDeviceDescriptionKey(guidPhysicalDeviceIdentifier, &hKeyPdi);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Read the UDN mappings
|
|
hr = HrLD_ReadUDNMappings(hKeyPdi, udnReplacementTable);
|
|
|
|
// Read the file mappings
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrLD_ReadFileMappings(hKeyPdi, fileTable);
|
|
}
|
|
RegCloseKey(hKeyPdi);
|
|
}
|
|
|
|
IXMLDOMDocumentPtr pDoc;
|
|
// Load the document - use the DOM to at least validate that it is XML
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrLD_LoadDescriptionDocumentFromDisk(guidPhysicalDeviceIdentifier, pDoc);
|
|
}
|
|
|
|
// Everything has succeeded to memory so transfer to variables
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Add entries to the cleanup table
|
|
CleanupItem ci;
|
|
ci.m_physicalDeviceIdentifier = guidPhysicalDeviceIdentifier;
|
|
long nCount = fileTable.Keys().GetCount();
|
|
for(long n = 0; n < nCount && SUCCEEDED(hr); ++n)
|
|
{
|
|
ci.m_fileId = fileTable.Keys()[n];
|
|
hr = m_cleanupList.HrPushBack(ci);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
{
|
|
CLock lockTable(m_critSecReplacementTable);
|
|
hr = m_replacementTable.HrInsertTransfer(const_cast<UUID&>(guidPhysicalDeviceIdentifier), udnReplacementTable);
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = m_fileTable.HrAppendTableTransfer(fileTable);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Save description document
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrLD_SaveDescriptionDocumentText(pDoc, guidPhysicalDeviceIdentifier);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::LoadDescription");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrRD_RemoveFromEventing(const PhysicalDeviceIdentifier & pdi)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrRD_RemoveFromEventing");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Remove from eventing
|
|
IXMLDOMNodePtr pRootNode;
|
|
hr = HrLoadDocumentAndRootNode(pdi, pRootNode);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fetch the devices
|
|
IXMLDOMNodeListPtr pNodeListDevices;
|
|
hr = HrSelectNodes(L"//device", pRootNode, pNodeListDevices);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Process each node in the device list
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Fetch the UDN
|
|
CUString strUDN;
|
|
hr = HrSelectNodeText(L"UDN", pNode, strUDN);
|
|
// Do the services
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get the services for this device
|
|
IXMLDOMNodeListPtr pNodeListServices;
|
|
hr = HrSelectNodes(L"serviceList/service", pNode, pNodeListServices);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Process each service in the list
|
|
HRESULT hrTmp = S_OK;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNodeService;
|
|
hrTmp = pNodeListServices->nextNode(pNodeService.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Deregister with eventing
|
|
hr = HrRegisterServiceWithEventing(pNodeService, strUDN, FALSE);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrRD_RemoveFromEventing");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrRD_RemoveFromDataStructures(const PhysicalDeviceIdentifier & pdi)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrRD_RemoveFromDataStructures");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Remove from data structures
|
|
|
|
// Walk cleanup list
|
|
long n = 0;
|
|
while(n < m_cleanupList.GetCount())
|
|
{
|
|
for(n = 0; n < m_cleanupList.GetCount(); ++n)
|
|
{
|
|
// If we match this cleanup item then remove from fileTable and restart
|
|
if(pdi == m_cleanupList[n].m_physicalDeviceIdentifier)
|
|
{
|
|
m_fileTable.HrErase(m_cleanupList[n].m_fileId);
|
|
m_cleanupList.HrErase(n);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Remove from document table
|
|
BSTR * pbstr = m_documentTable.Lookup(pdi);
|
|
if(pbstr)
|
|
{
|
|
SysFreeString(*pbstr);
|
|
}
|
|
else
|
|
{
|
|
TraceTag(ttidError, "CDescriptionManager::RemoveDescription: Document not found!");
|
|
}
|
|
m_documentTable.HrErase(pdi);
|
|
|
|
// Free the UDN replacement table items
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CLock lockTable(m_critSecReplacementTable);
|
|
hr = m_replacementTable.HrErase(pdi);
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrRD_RemoveFromDataStructures");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CDescriptionManager::HrRD_CleanupPublication(const PhysicalDeviceIdentifier & pdi)
|
|
{
|
|
TraceTag(ttidDescMan, "CDescriptionManager::HrRD_CleanupPublication");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Cleanup the publication
|
|
HandleList ** ppHandleList = NULL;
|
|
ppHandleList = m_ssdpRegistrationTable.Lookup(pdi);
|
|
if(ppHandleList)
|
|
{
|
|
long nCount = (*ppHandleList)->GetCount();
|
|
for(long n = 0; n < nCount; ++n)
|
|
{
|
|
DeregisterService((**ppHandleList)[n], TRUE);
|
|
}
|
|
delete *ppHandleList;
|
|
hr = m_ssdpRegistrationTable.HrErase(pdi);
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrRD_CleanupPublication");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::RemoveDescription(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
|
|
/*[in]*/ BOOL bPermanent)
|
|
{
|
|
CALock lock(*this);
|
|
HRESULT hr = S_OK;
|
|
|
|
// Remove from the registry if present
|
|
|
|
// Create / open description key
|
|
HKEY hKeyDescription;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrCreateOrOpenDescriptionKey(&hKeyDescription);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Generate key name and registry key
|
|
CUString strPdi;
|
|
hr = strPdi.HrInitFromGUID(guidPhysicalDeviceIdentifier);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(bPermanent)
|
|
{
|
|
hr = HrRegDeleteKeyTree(hKeyDescription, strPdi);
|
|
}
|
|
else
|
|
{
|
|
// Just delete the file stuff
|
|
HKEY hKeyPdi;
|
|
hr = HrRegOpenKeyEx(hKeyDescription, strPdi, KEY_ALL_ACCESS, &hKeyPdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegDeleteKeyTree(hKeyPdi, c_szFiles);
|
|
RegCloseKey(hKeyPdi);
|
|
}
|
|
}
|
|
}
|
|
RegCloseKey(hKeyDescription);
|
|
}
|
|
// Ignore registry failures
|
|
hr = S_OK;
|
|
|
|
// Delete the document from disk
|
|
CUString strPath;
|
|
hr = HrGetDescriptionDocumentPath(guidPhysicalDeviceIdentifier, strPath);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
DeleteFile(strPath);
|
|
}
|
|
// Ignore file deletion failures - might not exist
|
|
hr = S_OK;
|
|
|
|
// Remove from eventing
|
|
hr = HrRD_RemoveFromEventing(guidPhysicalDeviceIdentifier);
|
|
|
|
// Remove from data structures
|
|
hr = HrRD_RemoveFromDataStructures(guidPhysicalDeviceIdentifier);
|
|
|
|
// Cleanup the publication
|
|
hr = HrRD_CleanupPublication(guidPhysicalDeviceIdentifier);
|
|
|
|
// Remove Virtual Directory Created for Presentation
|
|
// CHECK - Virtual Directory may not be present
|
|
hr = HrRemovePresentationVirtualDir(guidPhysicalDeviceIdentifier);
|
|
if (FAILED(hr))
|
|
hr = S_OK ;
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::RemoveDescription");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::GetDescriptionText(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
|
|
/*[out]*/ BSTR * pbstrDescriptionDocument)
|
|
{
|
|
CHECK_POINTER(pbstrDescriptionDocument);
|
|
CALock lock(*this);
|
|
HRESULT hr = S_OK;
|
|
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Lookup the id
|
|
BSTR * pbstrDocument = m_documentTable.Lookup(guidPhysicalDeviceIdentifier);
|
|
if(pbstrDocument)
|
|
{
|
|
hr = HrSysAllocString(*pbstrDocument, pbstrDescriptionDocument);
|
|
}
|
|
else
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetDescriptionText");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::GetUDNs(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
|
|
/*[out]*/ long * pnUDNCount,
|
|
/*[out, size_is(,*pnUDNCount,), string]*/
|
|
wchar_t *** parszUDNs)
|
|
{
|
|
CHECK_POINTER(pnUDNCount);
|
|
CHECK_POINTER(parszUDNs);
|
|
CALock lock(*this);
|
|
HRESULT hr = S_OK;
|
|
|
|
IXMLDOMNodePtr pRootNode;
|
|
IXMLDOMNodeListPtr pNodeListUDNs;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrLoadDocumentAndRootNode(guidPhysicalDeviceIdentifier, pRootNode);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fetch the UDNs
|
|
hr = HrSelectNodes(L"//UDN", pRootNode, pNodeListUDNs);
|
|
}
|
|
|
|
long nLength = 0;
|
|
wchar_t ** arszUDNs = NULL;
|
|
// Process the UDNs
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Get length
|
|
hr = pNodeListUDNs->get_length(&nLength);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Allocate array
|
|
hr = HrCoTaskMemAllocArray(nLength, &arszUDNs);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fill with zeros
|
|
ZeroMemory(arszUDNs, sizeof(wchar_t*) * nLength);
|
|
// Fetch all of the UDNs
|
|
long n = 0;
|
|
while(SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pNode;
|
|
HRESULT hrTmp = S_OK;
|
|
// Fetch a node
|
|
hrTmp = pNodeListUDNs->nextNode(pNode.AddressOf());
|
|
if(S_OK != hrTmp)
|
|
{
|
|
break;
|
|
}
|
|
// Get the text
|
|
CUString strText;
|
|
hr = HrGetNodeText(pNode, strText);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strText.HrGetCOM(arszUDNs+n);
|
|
}
|
|
++n;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(FAILED(hr))
|
|
{
|
|
if(arszUDNs)
|
|
{
|
|
// Free strings
|
|
for(long n = 0; n < nLength; ++n)
|
|
{
|
|
if(arszUDNs[n])
|
|
{
|
|
CoTaskMemFree(arszUDNs[n]);
|
|
}
|
|
}
|
|
CoTaskMemFree(arszUDNs);
|
|
}
|
|
arszUDNs = NULL;
|
|
nLength = 0;
|
|
}
|
|
|
|
// Copy to output parameters
|
|
*pnUDNCount = nLength;
|
|
*parszUDNs = arszUDNs;
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetUDNs");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::GetUniqueDeviceName(
|
|
/*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
|
|
/*[in, string]*/ const wchar_t * szTemplateUDN,
|
|
/*[out, string]*/ wchar_t ** pszUDN)
|
|
{
|
|
CHECK_POINTER(szTemplateUDN);
|
|
CHECK_POINTER(pszUDN);
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
if (FAILED(hr))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Only lock the replacement table
|
|
CLock lock(m_critSecReplacementTable);
|
|
|
|
*pszUDN = NULL;
|
|
|
|
CUString strTemplateUDN;
|
|
|
|
hr = strTemplateUDN.HrAssign(szTemplateUDN);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
UDNReplacementTable * pudnReplacementTable = m_replacementTable.Lookup(guidPhysicalDeviceIdentifier);
|
|
if(pudnReplacementTable)
|
|
{
|
|
CUString * pstrUDN = pudnReplacementTable->Lookup(strTemplateUDN);
|
|
if(pstrUDN)
|
|
{
|
|
hr = pstrUDN->HrGetCOM(pszUDN);
|
|
}
|
|
}
|
|
}
|
|
// If we didn't find it in our tables then fail
|
|
if(!*pszUDN && SUCCEEDED(hr))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetUniqueDeviceName");
|
|
return hr;
|
|
}
|
|
|
|
STDMETHODIMP CDescriptionManager::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)
|
|
{
|
|
CHECK_POINTER(szUDN);
|
|
CHECK_POINTER(szServiceId);
|
|
CHECK_POINTER(pszSCPDText);
|
|
CHECK_POINTER(pszServiceType);
|
|
HRESULT hr = S_OK;
|
|
|
|
IXMLDOMNodePtr pRootNode;
|
|
IXMLDOMNodeListPtr pNodeListUDNs;
|
|
CUString strSCPDURL;
|
|
|
|
hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// Get the SCPDURL
|
|
hr = HrLoadDocumentAndRootNode(guidPhysicalDeviceIdentifier, pRootNode);
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fetch the service node //service/SCPDURL[../serviceId = szServiceId]
|
|
CUString strPattern;
|
|
hr = strPattern.HrAssign(L"//service/SCPDURL[../serviceId = '");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPattern.HrAppend(szServiceId);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPattern.HrAppend(L"']");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNodeText(strPattern, pRootNode, strSCPDURL);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// Get the GUID out of the URL
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
UUID uuid;
|
|
hr = HrContentURLToGUID(strSCPDURL, uuid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Fetch the content
|
|
long nHeaderCount = 0;
|
|
wchar_t ** arszHeaders = NULL;
|
|
long nBytes = 0;
|
|
byte * pBytes = NULL;
|
|
hr = GetContent(uuid, &nHeaderCount, &arszHeaders, &nBytes, &pBytes);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Content is not NULL terminate so reallocate with another character (yeah its cheesy)
|
|
hr = HrCoTaskMemAllocArray(nBytes + 1, pszSCPDText);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Copy text and convert from UTF-8 to unicode
|
|
if(!MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<char*>(pBytes), nBytes, *pszSCPDText, nBytes))
|
|
{
|
|
hr = HrFromLastWin32Error();
|
|
}
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Null terminate
|
|
(*pszSCPDText)[nBytes] = 0;
|
|
}
|
|
}
|
|
// Free everything
|
|
CoTaskMemFree(pBytes);
|
|
for(long n = 0; n < nHeaderCount; ++n)
|
|
{
|
|
CoTaskMemFree(arszHeaders[n]);
|
|
}
|
|
CoTaskMemFree(arszHeaders);
|
|
}
|
|
}
|
|
}
|
|
|
|
// get the Service Type
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IXMLDOMNodePtr pServiceTypeNode;
|
|
// Fetch the service type //service/SCPDURL[../serviceId = szServiceId]
|
|
CUString strPattern;
|
|
hr = strPattern.HrAssign(L"//service/serviceType[../serviceId = '");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPattern.HrAppend(szServiceId);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPattern.HrAppend(L"']");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrSelectNode(strPattern, pRootNode, pServiceTypeNode);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
BSTR bstr = NULL;
|
|
hr = pServiceTypeNode->get_text(&bstr);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
*pszServiceType = (wchar_t*)CoTaskMemAlloc(CbOfSzAndTerm(bstr));
|
|
if (*pszServiceType)
|
|
{
|
|
lstrcpy(*pszServiceType, bstr);
|
|
}
|
|
else
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
SysFreeString(bstr);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetSCPDText");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrCreateOrOpenDescriptionKey(
|
|
HKEY * phKeyDescription)
|
|
{
|
|
CHECK_POINTER(phKeyDescription);
|
|
HRESULT hr = S_OK;
|
|
|
|
HKEY hKeyDeviceHost;
|
|
hr = HrCreateOrOpenDeviceHostKey(&hKeyDeviceHost);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
DWORD dwDisposition = 0;
|
|
// Create / open description key
|
|
hr = HrRegCreateKeyEx(hKeyDeviceHost, c_szDescription, 0, KEY_ALL_ACCESS, NULL, phKeyDescription, &dwDisposition);
|
|
RegCloseKey(hKeyDeviceHost);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrOpenDescriptionKey");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrOpenPhysicalDeviceDescriptionKey(
|
|
const UUID & pdi,
|
|
HKEY * phKeyPdi)
|
|
{
|
|
CHECK_POINTER(phKeyPdi);
|
|
HRESULT hr = S_OK;
|
|
|
|
HKEY hKeyDescription;
|
|
hr = HrCreateOrOpenDescriptionKey(&hKeyDescription);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString str;
|
|
hr = str.HrInitFromGUID(pdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrRegOpenKeyEx(hKeyDescription, str, KEY_ALL_ACCESS, phKeyPdi);
|
|
}
|
|
RegCloseKey(hKeyDescription);
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrOpenPhysicalDeviceDescriptionKey");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrGetDescriptionDocumentPath(
|
|
const UUID & pdi,
|
|
CUString & strPath)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
|
|
hr = HrGetUPnPHostPath(strPath);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = HrAddDirectoryToPath(strPath, c_szDescriptionDocuments);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
CUString strGUID;
|
|
hr = strGUID.HrInitFromGUID(pdi);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPath.HrAppend(strGUID);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strPath.HrAppend(L".xml");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidError, FAL, hr, FALSE, "HrGetDescriptionDocumentPath");
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrRegisterServiceWithEventing(
|
|
IXMLDOMNodePtr & pNodeService,
|
|
const CUString & strUDN,
|
|
BOOL bRegister)
|
|
{
|
|
TraceTag(ttidDescMan, "HrRegisterServiceWithEventing");
|
|
HRESULT hr = S_OK;
|
|
|
|
// Register with eventing
|
|
CUString strSid;
|
|
hr = HrSelectNodeText(L"serviceId", pNodeService, strSid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// Generate the event identifier
|
|
CUString strESID;
|
|
hr = strESID.HrAssign(strUDN);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strESID.HrAppend(L"+");
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = strESID.HrAppend(strSid);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
if(bRegister)
|
|
{
|
|
hr = HrRegisterEventSource(strESID);
|
|
}
|
|
else
|
|
{
|
|
hr = HrDeregisterEventSource(strESID);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
TraceHr(ttidDescMan, FAL, hr, FALSE, "HrRegisterServiceWithEventing");
|
|
return hr;
|
|
}
|
|
|