Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2623 lines
78 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: D E S C R I P T I O N M A N A G E R . C P P
  7. //
  8. // Contents: Process UPnP Description document
  9. //
  10. // Notes:
  11. //
  12. // Author: mbend 18 Aug 2000
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include <msxml2.h>
  18. #include "uhbase.h"
  19. #include "hostp.h"
  20. #include "DescriptionManager.h"
  21. #include "uhsync.h"
  22. #include "upfile.h"
  23. #include "ncreg.h"
  24. #include "ssdpapi.h"
  25. #include "evtapi.h"
  26. #include "uhutil.h"
  27. #include "udhhttp.h" // remove this if you are moving the function for presentation virtual directory.
  28. #include "ncxml.h"
  29. #include "ssdpapi.h"
  30. #include "uhcommon.h"
  31. // String constants
  32. const wchar_t c_szDescription[] = L"Description";
  33. const wchar_t c_szUDNMappings[] = L"UDN Mappings";
  34. const wchar_t c_szFiles[] = L"Files";
  35. const wchar_t c_szFilename[] = L"Filename";
  36. const wchar_t c_szMimetype[] = L"Mimetype";
  37. const wchar_t c_szDescriptionDocuments[] = L"Description Documents";
  38. const wchar_t c_szRemoveId[] = L"REMOVE";
  39. CDescriptionManager::CDescriptionManager ()
  40. {
  41. }
  42. CDescriptionManager::~CDescriptionManager ()
  43. {
  44. // Free description documents
  45. BSTR bstr = NULL;
  46. long n;
  47. long nCount = m_documentTable.Values().GetCount();
  48. for(n = 0; n < nCount; ++n)
  49. {
  50. bstr = const_cast<BSTR>(m_documentTable.Values()[n]);
  51. SysFreeString(bstr);
  52. }
  53. m_documentTable.Clear();
  54. // Unpublish and free the arrays for all publications
  55. HandleList * pHandleList = NULL;
  56. nCount = m_ssdpRegistrationTable.Values().GetCount();
  57. for(n = 0; n < nCount; ++n)
  58. {
  59. pHandleList = const_cast<HandleList*>(m_ssdpRegistrationTable.Values()[n]);
  60. if(pHandleList)
  61. {
  62. long nHandleLists = pHandleList->GetCount();
  63. for(long n = 0; n < nHandleLists; ++n)
  64. {
  65. DeregisterService((*pHandleList)[n], TRUE);
  66. }
  67. delete pHandleList;
  68. }
  69. }
  70. m_ssdpRegistrationTable.Clear();
  71. }
  72. STDMETHODIMP CDescriptionManager::GetContent(
  73. /*[in]*/ REFGUID guidContent,
  74. /*[out]*/ long * pnHeaderCount,
  75. /*[out, string, size_is(,*pnHeaderCount,)]*/ wchar_t *** parszHeaders,
  76. /*[out]*/ long * pnBytes,
  77. /*[out, size_is(,*pnBytes)]*/ byte ** parBytes)
  78. {
  79. CALock lock(*this);
  80. HRESULT hr = S_OK;
  81. wchar_t ** arszHeaders = NULL;
  82. long nHeaderCount = 2;
  83. long nBytes = 0;
  84. byte * arBytes = NULL;
  85. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  86. if (SUCCEEDED(hr))
  87. {
  88. // Allocate the header array
  89. hr = HrCoTaskMemAllocArray(2, &arszHeaders);
  90. }
  91. // Other header variables, filled in body and copied to [out]
  92. // or cleaned up up at end of function
  93. if(SUCCEEDED(hr))
  94. {
  95. // Set header initially to NULL;
  96. arszHeaders[0] = NULL;
  97. arszHeaders[1] = NULL;
  98. // See if it is a description document
  99. BSTR * pbstr = m_documentTable.Lookup(guidContent);
  100. if(pbstr)
  101. {
  102. // This GUID is a description document
  103. // Allocate the content-type
  104. hr = HrCoTaskMemAllocString(L"content-type: text/xml", arszHeaders);
  105. if(SUCCEEDED(hr))
  106. {
  107. // Copy the document as ansi
  108. // nLength is the number of (wide)chars in the source
  109. // dSpace is the space reserved for the UTF-8 destination
  110. long nLength = SysStringLen(*pbstr);
  111. int dSpace = WideCharToMultiByte(CP_UTF8, 0, *pbstr, nLength, NULL, 0, NULL, NULL) + 1; // add 1 for NULL
  112. char * szBody = NULL;
  113. hr = HrCoTaskMemAllocArray(dSpace, &szBody);
  114. if(SUCCEEDED(hr))
  115. {
  116. if(!WideCharToMultiByte(CP_UTF8, 0, *pbstr, nLength, szBody, dSpace, NULL, NULL))
  117. {
  118. hr = HrFromLastWin32Error();
  119. }
  120. if(SUCCEEDED(hr))
  121. {
  122. arBytes = reinterpret_cast<byte*>(szBody);
  123. nBytes = dSpace-1; // number of bytes less the terminating nul
  124. arBytes[nBytes] = 0; // add NULL terminator
  125. }
  126. if(FAILED(hr))
  127. {
  128. CoTaskMemFree(szBody);
  129. szBody = NULL;
  130. }
  131. }
  132. }
  133. }
  134. else
  135. {
  136. // See if it is in the file table
  137. FileInfo * pFileInfo = m_fileTable.Lookup(guidContent);
  138. if(pFileInfo)
  139. {
  140. // Allocate the content type
  141. CUString strContentType;
  142. hr = strContentType.HrAssign(L"content-type:");
  143. if(SUCCEEDED(hr))
  144. {
  145. hr = strContentType.HrAppend(pFileInfo->m_mimetype);
  146. if(SUCCEEDED(hr))
  147. {
  148. hr = strContentType.HrGetCOM(arszHeaders);
  149. if(SUCCEEDED(hr))
  150. {
  151. // Load the file from disk
  152. hr = HrLoadFileFromDisk(pFileInfo->m_filename, &nBytes, &arBytes);
  153. }
  154. }
  155. }
  156. }
  157. else
  158. {
  159. // This provider didn't process it
  160. hr = S_FALSE;
  161. }
  162. }
  163. if(S_OK == hr)
  164. {
  165. wchar_t szBuf[128];
  166. wsprintf(szBuf, L"content-length: %d", nBytes);
  167. hr = HrCoTaskMemAllocString(szBuf, &arszHeaders[1]);
  168. }
  169. if(FAILED(hr) || S_FALSE == hr)
  170. {
  171. // Centralized cleanup code
  172. if(arszHeaders)
  173. {
  174. if(*arszHeaders)
  175. {
  176. // Free header (at most one)
  177. CoTaskMemFree(*arszHeaders);
  178. }
  179. if(arszHeaders[1])
  180. {
  181. CoTaskMemFree(arszHeaders[1]);
  182. }
  183. // Free length one header array
  184. CoTaskMemFree(arszHeaders);
  185. }
  186. if(arBytes)
  187. {
  188. // Free body bytes
  189. CoTaskMemFree(arBytes);
  190. }
  191. // Blank out the output params
  192. *pnHeaderCount = 0;
  193. *parszHeaders = NULL;
  194. *pnBytes = 0;
  195. *parBytes = NULL;
  196. }
  197. }
  198. if(S_OK == hr)
  199. {
  200. // Copy to output parameters
  201. *pnHeaderCount = nHeaderCount;
  202. *parszHeaders = arszHeaders;
  203. *pnBytes = nBytes;
  204. *parBytes = arBytes;
  205. }
  206. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetContent");
  207. return hr;
  208. }
  209. HRESULT HrNewUDNString(CUString & strUUID)
  210. {
  211. UUID uuid;
  212. HRESULT hr = S_OK;
  213. hr = CoCreateGuid(&uuid);
  214. if(SUCCEEDED(hr))
  215. {
  216. hr = HrGUIDToUDNString(uuid, strUUID);
  217. }
  218. TraceHr(ttidError, FAL, hr, FALSE, "HrNewUDNString");
  219. return hr;
  220. }
  221. HRESULT HrGetURLBase(CUString & strURLBase)
  222. {
  223. HRESULT hr = S_OK;
  224. hr = strURLBase.HrAssign(L"http://");
  225. if(SUCCEEDED(hr))
  226. {
  227. hr = strURLBase.HrAppend(c_szReplaceGuid);
  228. if(SUCCEEDED(hr))
  229. {
  230. hr = strURLBase.HrAppend(L":2869/upnphost/");
  231. }
  232. }
  233. TraceHr(ttidError, FAL, hr, FALSE, "HrGetURLBase");
  234. return hr;
  235. }
  236. HRESULT HrGetContentURL(const UUID & uuid, CUString & strURL)
  237. {
  238. HRESULT hr = S_OK;
  239. hr = strURL.HrAssign(L"udhisapi.dll?content=");
  240. if(SUCCEEDED(hr))
  241. {
  242. CUString strUUID;
  243. hr = HrGUIDToUDNString(uuid, strUUID);
  244. if(SUCCEEDED(hr))
  245. {
  246. hr = strURL.HrAppend(strUUID);
  247. }
  248. }
  249. TraceHr(ttidError, FAL, hr, FALSE, "HrGetContentURL");
  250. return hr;
  251. }
  252. // Create Virual directory using the Physical Device Identifier and map it to the resource path
  253. HRESULT HrCreatePresentationVirtualDir(const UUID &uuid, const LPWSTR szResourcePath)
  254. {
  255. HRESULT hr = S_OK;
  256. CUString strUUID;
  257. BSTR bstrVirDir;
  258. hr = HrGUIDToUDNString(uuid, strUUID);
  259. if(SUCCEEDED(hr))
  260. {
  261. CUString strTmp;
  262. hr = strTmp.HrAssign(L"/");
  263. if (SUCCEEDED(hr))
  264. {
  265. hr = strTmp.HrAppend(strUUID);
  266. if (SUCCEEDED(hr))
  267. {
  268. hr = strTmp.HrGetBSTR(&bstrVirDir);
  269. if(SUCCEEDED(hr))
  270. {
  271. HrRemoveVroot(bstrVirDir);
  272. hr = HrAddVroot(bstrVirDir,szResourcePath);
  273. SysFreeString(bstrVirDir);
  274. }
  275. }
  276. }
  277. }
  278. TraceHr(ttidError, FAL, hr, FALSE, "HrCreatePresentationVirtualDir");
  279. return hr;
  280. }
  281. // Remove the virtual directory
  282. HRESULT HrRemovePresentationVirtualDir(const UUID &uuid )
  283. {
  284. HRESULT hr = S_OK;
  285. CUString strUUID;
  286. BSTR bstrVirDir ;
  287. CUString strTmp;
  288. hr = strTmp.HrAssign(L"/");
  289. if(SUCCEEDED(hr))
  290. {
  291. hr = HrGUIDToUDNString(uuid, strUUID);
  292. if(SUCCEEDED(hr))
  293. {
  294. hr = strTmp.HrAppend(strUUID);
  295. }
  296. }
  297. if(SUCCEEDED(hr))
  298. {
  299. hr = strTmp.HrGetBSTR(&bstrVirDir);
  300. if(SUCCEEDED(hr))
  301. {
  302. hr = HrRemoveVroot(bstrVirDir);
  303. SysFreeString(bstrVirDir);
  304. }
  305. }
  306. TraceHr(ttidError, FAL, hr, FALSE, "HrRemovePresentationVirtualDir");
  307. return hr;
  308. }
  309. // prepare base URL for the presentation URL
  310. HRESULT HrGetPresentationBaseURL(const UUID &uuid, CUString &strPresentationBaseURL)
  311. {
  312. HRESULT hr = S_OK;
  313. if(SUCCEEDED(hr))
  314. {
  315. CUString strUUID;
  316. hr = strPresentationBaseURL.HrAppend(L"/");
  317. if (SUCCEEDED(hr))
  318. {
  319. hr = HrGUIDToUDNString(uuid, strUUID);
  320. if(SUCCEEDED(hr))
  321. {
  322. hr = strPresentationBaseURL.HrAppend(strUUID);
  323. if(SUCCEEDED(hr))
  324. {
  325. hr = strPresentationBaseURL.HrAppend(L"/");
  326. }
  327. }
  328. }
  329. }
  330. TraceHr(ttidError, FAL, hr, FALSE, "HrGetPresentationBaseURL");
  331. return hr;
  332. }
  333. HRESULT HrGenerateControlAndEventURLs(
  334. IXMLDOMNodePtr & pNodeDevice)
  335. {
  336. HRESULT hr = S_OK;
  337. CUString strControlURLBase;
  338. CUString strEventURLBase;
  339. CUString strUDN;
  340. hr = strControlURLBase.HrAssign(L"udhisapi.dll?control=");
  341. if(SUCCEEDED(hr))
  342. {
  343. hr = strEventURLBase.HrAssign(L"udhisapi.dll?event=");
  344. }
  345. if(SUCCEEDED(hr))
  346. {
  347. // Fetch the UDN
  348. hr = HrSelectNodeText(L"UDN", pNodeDevice, strUDN);
  349. }
  350. // Get all of the services
  351. IXMLDOMNodeListPtr pNodeListServices;
  352. if(SUCCEEDED(hr))
  353. {
  354. hr = HrSelectNodes(L"serviceList/service", pNodeDevice, pNodeListServices);
  355. if(SUCCEEDED(hr))
  356. {
  357. while(SUCCEEDED(hr))
  358. {
  359. IXMLDOMNodePtr pNodeService;
  360. // Process each service
  361. HRESULT hrTmp = S_OK;
  362. hrTmp = pNodeListServices->nextNode(pNodeService.AddressOf());
  363. if(S_OK != hrTmp)
  364. {
  365. break;
  366. }
  367. CUString strSid;
  368. hr = HrSelectNodeText(L"serviceId", pNodeService, strSid);
  369. if(SUCCEEDED(hr))
  370. {
  371. // Generate the URL suffix
  372. CUString strURL;
  373. hr = strURL.HrAssign(strUDN);
  374. if(SUCCEEDED(hr))
  375. {
  376. hr = strURL.HrAppend(L"+");
  377. if(SUCCEEDED(hr))
  378. {
  379. hr = strURL.HrAppend(strSid);
  380. }
  381. }
  382. CUString strControlURL;
  383. CUString strEventURL;
  384. // Build the real URLs
  385. if(SUCCEEDED(hr))
  386. {
  387. hr = strControlURL.HrAssign(strControlURLBase);
  388. if(SUCCEEDED(hr))
  389. {
  390. hr = strControlURL.HrAppend(strURL);
  391. if(SUCCEEDED(hr))
  392. {
  393. hr = strEventURL.HrAssign(strEventURLBase);
  394. if(SUCCEEDED(hr))
  395. {
  396. hr = strEventURL.HrAppend(strURL);
  397. }
  398. }
  399. }
  400. }
  401. // Now replace them in the document
  402. if(SUCCEEDED(hr))
  403. {
  404. CUString strNode;
  405. hr = strNode.HrAssign(L"/upnphost/");
  406. if (SUCCEEDED(hr))
  407. {
  408. hr = strNode.HrAppend(strControlURL);
  409. if (SUCCEEDED(hr))
  410. {
  411. hr = HrSelectAndSetNodeText(L"controlURL",
  412. pNodeService,
  413. strNode);
  414. }
  415. }
  416. }
  417. CUString strOldText;
  418. hr = HrSelectNodeText(L"eventSubURL", pNodeService,
  419. strOldText);
  420. if (SUCCEEDED(hr))
  421. {
  422. CUString strNode;
  423. // Only replace the URL if it doesn't have the remove
  424. // identifier in it. Otherwise, remove the identifier
  425. //
  426. if (lstrcmpi(strOldText, c_szRemoveId))
  427. {
  428. hr = strNode.HrAssign(L"/upnphost/");
  429. if (SUCCEEDED(hr))
  430. {
  431. hr = strNode.HrAppend(strEventURL);
  432. if (SUCCEEDED(hr))
  433. {
  434. hr = HrSelectAndSetNodeText(L"eventSubURL",
  435. pNodeService,
  436. strNode);
  437. }
  438. }
  439. }
  440. else
  441. {
  442. CUString strEmpty;
  443. hr = strEmpty.HrAssign(L"");
  444. if (SUCCEEDED(hr))
  445. {
  446. hr = HrSelectAndSetNodeText(L"eventSubURL",
  447. pNodeService, strEmpty);
  448. }
  449. }
  450. }
  451. }
  452. }
  453. }
  454. }
  455. TraceHr(ttidError, FAL, hr, FALSE, "HrGenerateControlAndEventURLs");
  456. return hr;
  457. }
  458. HRESULT HrGenDescAndUDNURLForPresentation(
  459. REFGUID guidPhysicalDeviceIdentifier,
  460. IXMLDOMNodePtr & pNodeDevice,
  461. CUString & strDescAndUDNURL)
  462. {
  463. HRESULT hr = S_OK ;
  464. CUString strDesc ;
  465. CUString strUDN ;
  466. hr = HrGetContentURL(guidPhysicalDeviceIdentifier, strDesc);
  467. if(SUCCEEDED(hr))
  468. {
  469. hr = strDescAndUDNURL.HrAssign(L"/upnphost/");
  470. if(SUCCEEDED(hr))
  471. {
  472. hr = strDescAndUDNURL.HrAppend(strDesc);
  473. }
  474. }
  475. if(SUCCEEDED(hr))
  476. {
  477. hr = strDescAndUDNURL.HrAppend(L"+");
  478. if(SUCCEEDED(hr))
  479. {
  480. hr = HrSelectNodeText(L"UDN", pNodeDevice, strUDN);
  481. if(SUCCEEDED(hr))
  482. {
  483. hr = strDescAndUDNURL.HrAppend(strUDN);
  484. }
  485. }
  486. }
  487. TraceHr(ttidError, FAL, hr, FALSE, "HrGenDescAndUDNURLForPresentation");
  488. return hr;
  489. }
  490. BOOL IsAbsoluteURL(BSTR bstrPresURL)
  491. {
  492. HRESULT hr = S_OK;
  493. const WCHAR c_szhttp[] = L"http://";
  494. const DWORD c_chhttp = celems(c_szhttp)-1;
  495. // include other conditions for absolute URL like https:// etc.
  496. if(wcsncmp(bstrPresURL,c_szhttp,c_chhttp) == 0 )
  497. return true;
  498. else
  499. return false;
  500. }
  501. HRESULT HrGenPresentationURL(
  502. REFGUID guidPhysicalDeviceIdentifier,
  503. IXMLDOMNodePtr & pNodeDevice,
  504. CUString & strPresFileName,
  505. CUString & strPresentationURL)
  506. {
  507. HRESULT hr = S_OK;
  508. CUString strDescURL ;
  509. hr = HrGetPresentationBaseURL(guidPhysicalDeviceIdentifier,strPresentationURL);
  510. if(SUCCEEDED(hr))
  511. {
  512. hr = strPresentationURL.HrAppend(strPresFileName);
  513. if(SUCCEEDED(hr))
  514. {
  515. hr = strPresentationURL.HrAppend(L"?");
  516. if(SUCCEEDED(hr))
  517. {
  518. hr = HrGenDescAndUDNURLForPresentation(guidPhysicalDeviceIdentifier,pNodeDevice,strDescURL);
  519. if(SUCCEEDED(hr))
  520. {
  521. hr = strPresentationURL.HrAppend(strDescURL);
  522. }
  523. }
  524. }
  525. }
  526. TraceHr(ttidError, FAL, hr, FALSE, "HrGenPresentationURL");
  527. return hr;
  528. }
  529. // Replaces the presentation URL for a device. If presentationURL element has absolute address no change is made.
  530. // File name to the main presentation page is expected, can be without presentation page
  531. HRESULT HrReplacePresentationURL(
  532. REFGUID guidPhysicalDeviceIdentifier,
  533. IXMLDOMNodePtr & pNodeDevice,
  534. BOOL *fIsPresURLTagPresent)
  535. {
  536. HRESULT hr = S_OK;
  537. CUString strPresentationURL;
  538. CUString strPresFileName ;
  539. CUString strUDN;
  540. CUString strUrl;
  541. CUString strDescAndUDNURL;
  542. BSTR bstrPresURL = NULL;
  543. WCHAR chQueryChar = '?' ;
  544. hr = HrSelectNodeText(L"presentationURL", pNodeDevice, strPresFileName);
  545. if(SUCCEEDED(hr))
  546. {
  547. hr = strPresFileName.HrGetBSTR(&bstrPresURL);
  548. if(SUCCEEDED(hr))
  549. {
  550. if(bstrPresURL != NULL && (wcscmp(bstrPresURL,L"") != 0 ) ) { // check if its absolute URL !!!
  551. //if(wcsncmp(bstrPresURL,c_szhttp,c_chhttp) == 0 ) {
  552. if(IsAbsoluteURL(bstrPresURL)) {
  553. if (wcschr(bstrPresURL,chQueryChar) ) {
  554. hr = S_OK;
  555. }
  556. else {
  557. hr = HrGenDescAndUDNURLForPresentation(guidPhysicalDeviceIdentifier,pNodeDevice,strDescAndUDNURL);
  558. if(SUCCEEDED(hr))
  559. {
  560. hr = strPresentationURL.HrAppend(strPresFileName);
  561. if(SUCCEEDED(hr))
  562. {
  563. hr = strPresentationURL.HrAppend(L"?");
  564. if(SUCCEEDED(hr))
  565. {
  566. hr = strPresentationURL.HrAppend(strDescAndUDNURL);
  567. if(SUCCEEDED(hr))
  568. {
  569. hr = HrSelectAndSetNodeText(L"presentationURL", pNodeDevice, strPresentationURL);
  570. }
  571. }
  572. }
  573. }
  574. }
  575. }
  576. else {
  577. *fIsPresURLTagPresent = true ;
  578. hr = HrGenPresentationURL(guidPhysicalDeviceIdentifier,pNodeDevice,strPresFileName,strPresentationURL);
  579. if(SUCCEEDED(hr))
  580. {
  581. hr = HrSelectAndSetNodeText(L"presentationURL", pNodeDevice, strPresentationURL);
  582. }
  583. }
  584. }
  585. else {
  586. hr = S_OK;
  587. }
  588. }
  589. }
  590. else {
  591. // write a function which will test for tag and return S_FALSE if tag is not present
  592. hr = S_OK;
  593. }
  594. SysFreeString(bstrPresURL);
  595. TraceHr(ttidError, FAL, hr, FALSE, "HrReplacePresentationURL");
  596. return hr;
  597. }
  598. HRESULT CDescriptionManager::HrPersistDeviceSettingsToRegistry(
  599. const PhysicalDeviceIdentifier & physicalDeviceIdentifier,
  600. const UDNReplacementTable & udnReplacementTable,
  601. const FileTable & fileTable,
  602. BOOL bPersist)
  603. {
  604. HRESULT hr = S_OK;
  605. // Create / open device host key
  606. HKEY hKeyDescription;
  607. DWORD dwDisposition = 0;
  608. hr = HrCreateOrOpenDescriptionKey(&hKeyDescription);
  609. if(SUCCEEDED(hr))
  610. {
  611. // Generate key name and registry key
  612. CUString strPdi;
  613. HKEY hKeyPdi;
  614. hr = strPdi.HrInitFromGUID(physicalDeviceIdentifier);
  615. if(SUCCEEDED(hr))
  616. {
  617. hr = HrRegCreateKeyEx(hKeyDescription, strPdi, 0, KEY_ALL_ACCESS, NULL, &hKeyPdi, &dwDisposition);
  618. if(SUCCEEDED(hr))
  619. {
  620. // Create UDN mappings
  621. HKEY hKeyMappings;
  622. hr = HrRegCreateKeyEx(hKeyPdi, c_szUDNMappings, 0, KEY_ALL_ACCESS, NULL, &hKeyMappings, &dwDisposition);
  623. if(SUCCEEDED(hr))
  624. {
  625. long nMappings = udnReplacementTable.Keys().GetCount();
  626. for(long n = 0; n < nMappings && SUCCEEDED(hr); ++n)
  627. {
  628. // Create key for mapping
  629. HKEY hKeyMapping;
  630. hr = HrRegCreateKeyEx(hKeyMappings, udnReplacementTable.Keys()[n],
  631. 0, KEY_ALL_ACCESS, NULL, &hKeyMapping, &dwDisposition);
  632. if(SUCCEEDED(hr))
  633. {
  634. // Write the value for the mapping
  635. hr = HrRegSetSz(hKeyMapping, L"", udnReplacementTable.Values()[n]);
  636. RegCloseKey(hKeyMapping);
  637. }
  638. }
  639. RegCloseKey(hKeyMappings);
  640. }
  641. // Create file mappings for a fully persistent device
  642. if(bPersist)
  643. {
  644. HKEY hKeyFileMappings;
  645. hr = HrRegCreateKeyEx(hKeyPdi, c_szFiles, 0, KEY_ALL_ACCESS, NULL, &hKeyFileMappings, &dwDisposition);
  646. if(SUCCEEDED(hr))
  647. {
  648. long nMappings = fileTable.Keys().GetCount();
  649. for(long n = 0; n < nMappings && SUCCEEDED(hr); ++n)
  650. {
  651. CUString strFileId;
  652. hr = strFileId.HrInitFromGUID(fileTable.Keys()[n]);
  653. if(SUCCEEDED(hr))
  654. {
  655. // Create key for mapping
  656. HKEY hKeyMapping;
  657. hr = HrRegCreateKeyEx(hKeyFileMappings, strFileId, 0, KEY_ALL_ACCESS, NULL, &hKeyMapping, &dwDisposition);
  658. if(SUCCEEDED(hr))
  659. {
  660. // Save values
  661. hr = HrRegSetSz(hKeyMapping, c_szFilename, fileTable.Values()[n].m_filename);
  662. if(SUCCEEDED(hr))
  663. {
  664. hr = HrRegSetSz(hKeyMapping, c_szMimetype, fileTable.Values()[n].m_mimetype);
  665. }
  666. }
  667. }
  668. }
  669. RegCloseKey(hKeyFileMappings);
  670. }
  671. }
  672. RegCloseKey(hKeyPdi);
  673. }
  674. }
  675. // If anything fails, whack the whole key
  676. if(FAILED(hr))
  677. {
  678. HrRegDeleteKeyTree(hKeyDescription, strPdi);
  679. }
  680. RegCloseKey(hKeyDescription);
  681. }
  682. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::HrPersistDeviceSettingsToRegistry");
  683. return hr;
  684. }
  685. HRESULT CDescriptionManager::HrLoadDocumentAndRootNode(
  686. const PhysicalDeviceIdentifier & physicalDeviceIdentifier,
  687. IXMLDOMNodePtr & pRootNode)
  688. {
  689. HRESULT hr = S_OK;
  690. // Lookup the id
  691. BSTR * pbstrDocument = m_documentTable.Lookup(physicalDeviceIdentifier);
  692. if(pbstrDocument)
  693. {
  694. // Load the document
  695. IXMLDOMDocumentPtr pDoc;
  696. hr = HrLoadDocument(*pbstrDocument, pDoc);
  697. if(SUCCEEDED(hr))
  698. {
  699. hr = pRootNode.HrAttach(pDoc);
  700. }
  701. }
  702. else
  703. {
  704. hr = E_INVALIDARG;
  705. }
  706. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::HrLoadDocumentAndRootNode");
  707. return hr;
  708. }
  709. HRESULT CDescriptionManager::HrPDT_FetchCollections(
  710. BSTR bstrTemplate,
  711. IXMLDOMDocumentPtr & pDoc,
  712. IXMLDOMNodePtr & pRootNode,
  713. CUString & strRootUdnOld,
  714. IXMLDOMNodeListPtr & pNodeListDevices,
  715. IXMLDOMNodeListPtr & pNodeListUDNs,
  716. IXMLDOMNodeListPtr & pNodeListSCPDURLs,
  717. IXMLDOMNodeListPtr & pNodeListIcons)
  718. {
  719. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_FetchCollections");
  720. HRESULT hr = S_OK;
  721. // Load document and fetch needed items
  722. hr = HrLoadDocument(bstrTemplate, pDoc);
  723. if(SUCCEEDED(hr))
  724. {
  725. hr = pRootNode.HrAttach(pDoc);
  726. if(SUCCEEDED(hr))
  727. {
  728. // Get the old root UDN
  729. hr = HrSelectNodeText(L"/root/device/UDN", pRootNode, strRootUdnOld);
  730. if(SUCCEEDED(hr))
  731. {
  732. // Get the lists
  733. hr = HrSelectNodes(L"//device", pRootNode, pNodeListDevices);
  734. if(SUCCEEDED(hr))
  735. {
  736. hr = HrSelectNodes(L"//UDN", pRootNode, pNodeListUDNs);
  737. if(SUCCEEDED(hr))
  738. {
  739. hr = HrSelectNodes(L"//SCPDURL", pRootNode, pNodeListSCPDURLs);
  740. if(SUCCEEDED(hr))
  741. {
  742. hr = HrSelectNodes(L"//icon", pRootNode, pNodeListIcons);
  743. }
  744. }
  745. }
  746. }
  747. }
  748. }
  749. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_FetchCollections");
  750. return hr;
  751. }
  752. HRESULT CDescriptionManager::HrPDT_DoUDNToUDNMapping(
  753. IXMLDOMNodeListPtr & pNodeListUDNs,
  754. UDNReplacementTable & udnReplacementTable)
  755. {
  756. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_DoUDNToUDNMapping");
  757. HRESULT hr = S_OK;
  758. // Do UDN to UDN mapping
  759. HRESULT hrTmp = S_OK;
  760. while(SUCCEEDED(hr))
  761. {
  762. IXMLDOMNodePtr pNode;
  763. // Process each UDN
  764. hrTmp = pNodeListUDNs->nextNode(pNode.AddressOf());
  765. if(S_OK != hrTmp)
  766. {
  767. break;
  768. }
  769. // Allocate UDN storage and generate new UDN
  770. CUString strOld;
  771. CUString strNew;
  772. hr = HrNewUDNString(strNew);
  773. if(SUCCEEDED(hr))
  774. {
  775. // Read the old UDN
  776. hr = HrGetNodeText(pNode, strOld);
  777. if(SUCCEEDED(hr))
  778. {
  779. // Do replacement
  780. hr = HrSetNodeText(pNode, strNew);
  781. if(SUCCEEDED(hr))
  782. {
  783. // Add temporary table mapping
  784. hr = udnReplacementTable.HrInsertTransfer(strOld, strNew);
  785. }
  786. }
  787. }
  788. }
  789. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_DoUDNToUDNMapping");
  790. return hr;
  791. }
  792. HRESULT CDescriptionManager::HrPDT_ReregisterUDNsInDescriptionDocument(
  793. UDNReplacementTable & udnReplacementTable,
  794. IXMLDOMNodeListPtr & pNodeListUDNs)
  795. {
  796. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReregisterUDNsInDescriptionDocument");
  797. HRESULT hr = S_OK;
  798. HRESULT hrTmp = S_OK;
  799. while(SUCCEEDED(hr))
  800. {
  801. IXMLDOMNodePtr pNode;
  802. // Process each UDN
  803. hrTmp = pNodeListUDNs->nextNode(pNode.AddressOf());
  804. if(S_OK != hrTmp)
  805. {
  806. break;
  807. }
  808. // Read the old UDN
  809. CUString strOld;
  810. hr = HrGetNodeText(pNode, strOld);
  811. if(SUCCEEDED(hr))
  812. {
  813. // Lookup in replacement table
  814. CUString * pstrNew = udnReplacementTable.Lookup(strOld);
  815. if(pstrNew)
  816. {
  817. // Do the replacement
  818. hr = HrSetNodeText(pNode, *pstrNew);
  819. }
  820. else
  821. {
  822. TraceTag(ttidDescMan, "HrPDT_ReregisterUDNsInDescriptionDocument: Got invalid UDN in reregister '%S'",
  823. static_cast<const wchar_t *>(strOld));
  824. hr = E_UNEXPECTED;
  825. }
  826. }
  827. }
  828. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReregisterUDNsInDescriptionDocument");
  829. return hr;
  830. }
  831. HRESULT CDescriptionManager::HrPDT_FetchPhysicalIdentifier(
  832. UDNReplacementTable & udnReplacementTable,
  833. const CUString & strRootUdnOld,
  834. PhysicalDeviceIdentifier & pdi)
  835. {
  836. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_FetchPhysicalIdentifier");
  837. HRESULT hr = S_OK;
  838. // Fetch identifier of root node
  839. UDN * pUDN = udnReplacementTable.Lookup(strRootUdnOld);
  840. if(!pUDN)
  841. {
  842. TraceTag(ttidError, "CDescriptionManager::ProcessDescriptionTemplate: We can't find the root UDN.");
  843. hr = E_INVALIDARG;
  844. }
  845. if(SUCCEEDED(hr))
  846. {
  847. hr = HrUDNStringToGUID(*pUDN, pdi);
  848. }
  849. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_FetchPhysicalIdentifier");
  850. return hr;
  851. }
  852. BOOL FEventedVariablesPresent(
  853. IXMLDOMNodeListPtr pNodeList)
  854. {
  855. HRESULT hr = S_OK;
  856. HRESULT hrTmp;
  857. BOOL fResult = FALSE;
  858. while (SUCCEEDED(hr) && !fResult)
  859. {
  860. IXMLDOMNodePtr pNode;
  861. // Process each node
  862. hrTmp = pNodeList->nextNode(pNode.AddressOf());
  863. if (S_OK != hrTmp)
  864. {
  865. break;
  866. }
  867. BSTR bstrSendEvents = NULL;
  868. hr = HrGetTextValueFromAttribute(pNode, L"sendEvents", &bstrSendEvents);
  869. if (S_OK == hr)
  870. {
  871. // sendEvents was present so we know there is at least one evented
  872. // variable.. ok to exit now
  873. if (!lstrcmpiW(bstrSendEvents, L"yes"))
  874. {
  875. fResult = TRUE;
  876. }
  877. SysFreeString(bstrSendEvents);
  878. }
  879. else
  880. {
  881. // sendEvents was not present which means we default to evented
  882. // ok to exit now.
  883. fResult = TRUE;
  884. }
  885. }
  886. return fResult;
  887. }
  888. HRESULT HrCheckForEventedVariables(
  889. CUString & strUrl)
  890. {
  891. HRESULT hr = S_OK;
  892. BSTR bstrUrl;
  893. BOOL fEventedVariables = FALSE;
  894. hr = strUrl.HrGetBSTR(&bstrUrl);
  895. if (SUCCEEDED(hr))
  896. {
  897. IXMLDOMDocumentPtr pDoc;
  898. hr = HrLoadDocumentFromFile(bstrUrl, pDoc);
  899. if (SUCCEEDED(hr))
  900. {
  901. IXMLDOMNodePtr pRootNode;
  902. hr = pRootNode.HrAttach(pDoc);
  903. if (SUCCEEDED(hr))
  904. {
  905. IXMLDOMNodeListPtr pNodeList;
  906. hr = HrSelectNodes(L"//stateVariable",
  907. pRootNode, pNodeList);
  908. if (SUCCEEDED(hr))
  909. {
  910. if (FEventedVariablesPresent(pNodeList))
  911. {
  912. fEventedVariables = TRUE;
  913. }
  914. }
  915. }
  916. }
  917. SysFreeString(bstrUrl);
  918. }
  919. if (SUCCEEDED(hr))
  920. {
  921. hr = fEventedVariables ? S_OK : S_FALSE;
  922. }
  923. TraceHr(ttidDescMan, FAL, hr, FALSE, "HrCheckForEventedVariables");
  924. return hr;
  925. }
  926. HRESULT CDescriptionManager::HrPDT_ReplaceSCPDURLs(
  927. IXMLDOMNodeListPtr & pNodeListSCPDURLs,
  928. const wchar_t * szResourcePath,
  929. FileTable & fileTable)
  930. {
  931. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReplaceSCPDURLs");
  932. HRESULT hr = S_OK;
  933. // Replace SCPDURLs
  934. HRESULT hrTmp = S_OK;
  935. while(SUCCEEDED(hr))
  936. {
  937. IXMLDOMNodePtr pNode;
  938. // Process each SCPDURL
  939. hrTmp = pNodeListSCPDURLs->nextNode(pNode.AddressOf());
  940. if(S_OK != hrTmp)
  941. {
  942. break;
  943. }
  944. // Allocate filename storage and generate new URL
  945. CUString strOld;
  946. CUString strNew;
  947. GUID guid;
  948. hr = CoCreateGuid(&guid);
  949. if(SUCCEEDED(hr))
  950. {
  951. // Generate the URL
  952. hr = HrGetContentURL(guid, strNew);
  953. if(SUCCEEDED(hr))
  954. {
  955. // Read the filename
  956. CUString strFilename;
  957. hr = HrGetNodeText(pNode, strFilename);
  958. if(SUCCEEDED(hr))
  959. {
  960. // Make an absolute filename
  961. hr = HrMakeFullPath(szResourcePath, strFilename, strOld);
  962. }
  963. }
  964. if(SUCCEEDED(hr))
  965. {
  966. CUString strNode;
  967. hr = strNode.HrAssign(L"/upnphost/");
  968. if (SUCCEEDED(hr))
  969. {
  970. hr = strNode.HrAppend(strNew);
  971. if (SUCCEEDED(hr))
  972. {
  973. // Do replacement
  974. hr = HrSetNodeText(pNode, strNode);
  975. }
  976. }
  977. }
  978. if (SUCCEEDED(hr))
  979. {
  980. // Determine if the eventSubURL should be replaced later on
  981. //
  982. hr = HrCheckForEventedVariables(strOld);
  983. if (S_FALSE == hr)
  984. {
  985. // No evented variables were found.. mark the eventSubURL
  986. // element to be emptied later on when we process the
  987. // eventing URLs.
  988. //
  989. CUString strRemove;
  990. hr = strRemove.HrAssign(c_szRemoveId);
  991. if (SUCCEEDED(hr))
  992. {
  993. hr = HrSelectAndSetNodeText(L"../eventSubURL", pNode,
  994. strRemove);
  995. }
  996. }
  997. }
  998. if (SUCCEEDED(hr))
  999. {
  1000. // Add mapping to data structure
  1001. FileInfo fi;
  1002. fi.m_filename.Transfer(strOld);
  1003. hr = fi.m_mimetype.HrAssign(L"text/xml");
  1004. if(SUCCEEDED(hr))
  1005. {
  1006. hr = fileTable.HrInsertTransfer(guid, fi);
  1007. }
  1008. }
  1009. }
  1010. }
  1011. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReplaceSCPDURLs");
  1012. return hr;
  1013. }
  1014. HRESULT CDescriptionManager::HrPDT_ReplaceIcons(
  1015. IXMLDOMNodeListPtr & pNodeListIcons,
  1016. const wchar_t * szResourcePath,
  1017. FileTable & fileTable)
  1018. {
  1019. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReplaceIcons");
  1020. HRESULT hr = S_OK;
  1021. // Replace icons
  1022. HRESULT hrTmp = S_OK;
  1023. while(SUCCEEDED(hr))
  1024. {
  1025. IXMLDOMNodePtr pNode;
  1026. // Process each icon
  1027. hrTmp = pNodeListIcons->nextNode(pNode.AddressOf());
  1028. if(S_OK != hrTmp)
  1029. {
  1030. break;
  1031. }
  1032. // Allocate filename storage and generate new URL
  1033. CUString strOld;
  1034. CUString strNew;
  1035. GUID guid;
  1036. hr = CoCreateGuid(&guid);
  1037. if(SUCCEEDED(hr))
  1038. {
  1039. // Generate the URL
  1040. hr = HrGetContentURL(guid, strNew);
  1041. if(SUCCEEDED(hr))
  1042. {
  1043. // Read the filename
  1044. CUString strFilename;
  1045. hr = HrSelectNodeText(L"url", pNode, strFilename);
  1046. if(SUCCEEDED(hr))
  1047. {
  1048. // Make an absolute filename
  1049. hr = HrMakeFullPath(szResourcePath, strFilename, strOld);
  1050. }
  1051. }
  1052. if(SUCCEEDED(hr))
  1053. {
  1054. CUString strNode;
  1055. hr = strNode.HrAssign(L"/upnphost/");
  1056. if (SUCCEEDED(hr))
  1057. {
  1058. hr = strNode.HrAppend(strNew);
  1059. if (SUCCEEDED(hr))
  1060. {
  1061. // Do replacement
  1062. hr = HrSelectAndSetNodeText(L"url", pNode, strNode);
  1063. }
  1064. }
  1065. }
  1066. if(SUCCEEDED(hr))
  1067. {
  1068. // Add mapping to data structure
  1069. FileInfo fi;
  1070. fi.m_filename.Transfer(strOld);
  1071. // Get the mimetype
  1072. CUString strMimetype;
  1073. hr = HrSelectNodeText(L"mimetype", pNode, strMimetype);
  1074. if(SUCCEEDED(hr))
  1075. {
  1076. fi.m_mimetype.Transfer(strMimetype);
  1077. hr = fileTable.HrInsertTransfer(guid, fi);
  1078. }
  1079. }
  1080. }
  1081. }
  1082. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReplaceIcons");
  1083. return hr;
  1084. }
  1085. HRESULT CDescriptionManager::HrPDT_ReplaceControlAndEventURLs(
  1086. IXMLDOMNodeListPtr & pNodeListDevices)
  1087. {
  1088. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ReplaceControlAndEventURLs");
  1089. HRESULT hr = S_OK;
  1090. // Fill in the control and eventing URL for each document
  1091. HRESULT hrTmp = S_OK;
  1092. while(SUCCEEDED(hr))
  1093. {
  1094. IXMLDOMNodePtr pNode;
  1095. // Process each device
  1096. hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
  1097. if(S_OK != hrTmp)
  1098. {
  1099. break;
  1100. }
  1101. hr = HrGenerateControlAndEventURLs(pNode);
  1102. }
  1103. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ReplaceControlAndEventURLs");
  1104. return hr;
  1105. }
  1106. // Iterates over the devices and fills in the presentation URL for each device
  1107. HRESULT CDescriptionManager::HrPDT_ProcessPresentationURLs(
  1108. REFGUID guidPhysicalDeviceIdentifier,
  1109. IXMLDOMNodeListPtr & pNodeListDevices,
  1110. BOOL *fIsPresURLTagPresent)
  1111. {
  1112. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_ProcessPresentationURLs");
  1113. HRESULT hr = S_OK;
  1114. // Fill in the presentation URL for each device
  1115. HRESULT hrTmp = S_OK;
  1116. while(SUCCEEDED(hr))
  1117. {
  1118. IXMLDOMNodePtr pNode;
  1119. hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
  1120. if(S_OK != hrTmp)
  1121. {
  1122. break;
  1123. }
  1124. hr = HrReplacePresentationURL(guidPhysicalDeviceIdentifier,pNode,fIsPresURLTagPresent);
  1125. }
  1126. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_ProcessPresentationURLs");
  1127. return hr;
  1128. }
  1129. HRESULT CDescriptionManager::HrPDT_PersistDescriptionDocument(
  1130. const PhysicalDeviceIdentifier & pdi,
  1131. IXMLDOMDocumentPtr & pDoc)
  1132. {
  1133. TraceTag(ttidDescMan, "CDescriptionManager::HrPDT_PersistDescriptionDocument");
  1134. HRESULT hr = S_OK;
  1135. // Write description document to disk
  1136. // Get the path to save to
  1137. CUString strPath;
  1138. hr = HrGetDescriptionDocumentPath(pdi, strPath);
  1139. if(SUCCEEDED(hr))
  1140. {
  1141. BSTR bstr = NULL;
  1142. hr = strPath.HrGetBSTR(&bstr);
  1143. if(SUCCEEDED(hr))
  1144. {
  1145. VARIANT var;
  1146. VariantInit(&var);
  1147. var.vt = VT_BSTR;
  1148. var.bstrVal = bstr;
  1149. hr = pDoc->save(var);
  1150. SysFreeString(bstr);
  1151. TraceHr(ttidError, FAL, hr, FALSE, "ProcessDescriptionTemplate: IXMLDOMDocument::save failed.");
  1152. }
  1153. }
  1154. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPDT_PersistDescriptionDocument");
  1155. return hr;
  1156. }
  1157. STDMETHODIMP CDescriptionManager::ProcessDescriptionTemplate(
  1158. /*[in]*/ BSTR bstrTemplate,
  1159. /*[in, string]*/ const wchar_t * szResourcePath,
  1160. /*[in, out]*/ GUID * pguidPhysicalDeviceIdentifier,
  1161. /*[in]*/ BOOL bPersist,
  1162. /*[in]*/ BOOL bReregister)
  1163. {
  1164. CHECK_POINTER(bstrTemplate);
  1165. CHECK_POINTER(szResourcePath);
  1166. CHECK_POINTER(pguidPhysicalDeviceIdentifier);
  1167. CALock lock(*this);
  1168. HRESULT hr = S_OK;
  1169. // Values to fetch in first phase
  1170. IXMLDOMDocumentPtr pDoc;
  1171. IXMLDOMNodePtr pRootNode;
  1172. CUString strRootUdnOld;
  1173. IXMLDOMNodeListPtr pNodeListDevices;
  1174. IXMLDOMNodeListPtr pNodeListUDNs;
  1175. IXMLDOMNodeListPtr pNodeListSCPDURLs;
  1176. IXMLDOMNodeListPtr pNodeListIcons;
  1177. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  1178. if ( SUCCEEDED( hr ) )
  1179. {
  1180. // Load document and fetch needed items
  1181. hr = HrPDT_FetchCollections(bstrTemplate, pDoc, pRootNode, strRootUdnOld, pNodeListDevices,
  1182. pNodeListUDNs, pNodeListSCPDURLs, pNodeListIcons);
  1183. }
  1184. // Temporary data structures to do work in
  1185. PhysicalDeviceIdentifier pdi;
  1186. UDNReplacementTable udnReplacementTable;
  1187. FileTable fileTable;
  1188. if(!bReregister)
  1189. {
  1190. // Do UDN to UDN mapping
  1191. if(SUCCEEDED(hr))
  1192. {
  1193. hr = HrPDT_DoUDNToUDNMapping(pNodeListUDNs, udnReplacementTable);
  1194. }
  1195. // Fetch identifier of root node
  1196. if(SUCCEEDED(hr))
  1197. {
  1198. hr = HrPDT_FetchPhysicalIdentifier(udnReplacementTable, strRootUdnOld, pdi);
  1199. }
  1200. }
  1201. else
  1202. {
  1203. if(SUCCEEDED(hr))
  1204. {
  1205. // Set the physical device identifier
  1206. pdi = *pguidPhysicalDeviceIdentifier;
  1207. // Open physical device identifier's registry key
  1208. HKEY hKeyPdi;
  1209. hr = HrOpenPhysicalDeviceDescriptionKey(pdi, &hKeyPdi);
  1210. if(SUCCEEDED(hr))
  1211. {
  1212. // Load the UDNs from registry
  1213. hr = HrLD_ReadUDNMappings(hKeyPdi, udnReplacementTable);
  1214. if(SUCCEEDED(hr))
  1215. {
  1216. // Update UDNs in the document
  1217. hr = HrPDT_ReregisterUDNsInDescriptionDocument(udnReplacementTable, pNodeListUDNs);
  1218. }
  1219. RegCloseKey(hKeyPdi);
  1220. }
  1221. }
  1222. }
  1223. // Replace SCPDURLs
  1224. if(SUCCEEDED(hr))
  1225. {
  1226. hr = HrPDT_ReplaceSCPDURLs(pNodeListSCPDURLs, szResourcePath, fileTable);
  1227. }
  1228. // Replace icons
  1229. if(SUCCEEDED(hr))
  1230. {
  1231. hr = HrPDT_ReplaceIcons(pNodeListIcons, szResourcePath, fileTable);
  1232. }
  1233. // Fill in the control and eventing URL for each document
  1234. if(SUCCEEDED(hr))
  1235. {
  1236. hr = HrPDT_ReplaceControlAndEventURLs(pNodeListDevices);
  1237. }
  1238. // Fill in the presentation URL for each device
  1239. if(SUCCEEDED(hr))
  1240. {
  1241. BOOL fIsPresURLTagPresent = false ;
  1242. hr = pNodeListDevices->reset();
  1243. if(SUCCEEDED(hr))
  1244. {
  1245. hr = HrPDT_ProcessPresentationURLs(pdi,pNodeListDevices,&fIsPresURLTagPresent);
  1246. // Create Virtual Directory for the presentation files
  1247. if(SUCCEEDED(hr) && fIsPresURLTagPresent )
  1248. {
  1249. BSTR bstrResourcePath;
  1250. bstrResourcePath = SysAllocString(szResourcePath);
  1251. hr = HrCreatePresentationVirtualDir(pdi,bstrResourcePath);
  1252. SysFreeString(bstrResourcePath);
  1253. }
  1254. }
  1255. }
  1256. // Write description document to disk
  1257. if(SUCCEEDED(hr) && bPersist)
  1258. {
  1259. hr = HrPDT_PersistDescriptionDocument(pdi, pDoc);
  1260. }
  1261. // Commit changes to registry for bPersist
  1262. if(SUCCEEDED(hr))
  1263. {
  1264. hr = HrPersistDeviceSettingsToRegistry(pdi, udnReplacementTable, fileTable, bPersist);
  1265. }
  1266. // Commit changes to variables
  1267. if(SUCCEEDED(hr))
  1268. {
  1269. // Add entries to the cleanup table
  1270. CleanupItem ci;
  1271. ci.m_physicalDeviceIdentifier = pdi;
  1272. long nCount = fileTable.Keys().GetCount();
  1273. for(long n = 0; n < nCount && SUCCEEDED(hr); ++n)
  1274. {
  1275. ci.m_fileId = fileTable.Keys()[n];
  1276. hr = m_cleanupList.HrPushBack(ci);
  1277. }
  1278. if(SUCCEEDED(hr))
  1279. {
  1280. {
  1281. CLock lockTable(m_critSecReplacementTable);
  1282. hr = m_replacementTable.HrInsertTransfer(pdi, udnReplacementTable);
  1283. }
  1284. if(SUCCEEDED(hr))
  1285. {
  1286. hr = m_fileTable.HrAppendTableTransfer(fileTable);
  1287. }
  1288. }
  1289. }
  1290. // Save description document
  1291. if(SUCCEEDED(hr))
  1292. {
  1293. BSTR bstrDocument = NULL;
  1294. hr = pRootNode->get_xml(&bstrDocument);
  1295. if(SUCCEEDED(hr))
  1296. {
  1297. hr = m_documentTable.HrInsert(pdi, bstrDocument);
  1298. if(FAILED(hr))
  1299. {
  1300. SysFreeString(bstrDocument);
  1301. }
  1302. }
  1303. }
  1304. // Return identifier
  1305. if(SUCCEEDED(hr) && !bReregister)
  1306. {
  1307. *pguidPhysicalDeviceIdentifier = pdi;
  1308. }
  1309. if(FAILED(hr))
  1310. {
  1311. RemoveDescription(pdi, FALSE);
  1312. }
  1313. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::ProcessDescriptionTemplate");
  1314. return hr;
  1315. }
  1316. HRESULT HrRegisterService(PSSDP_MESSAGE pSsdpMessage, DWORD dwFlags, HANDLE * pHandle)
  1317. {
  1318. CHECK_POINTER(pSsdpMessage);
  1319. CHECK_POINTER(pHandle);
  1320. HRESULT hr = S_OK;
  1321. *pHandle = RegisterService(pSsdpMessage, dwFlags);
  1322. if(INVALID_HANDLE_VALUE == *pHandle)
  1323. {
  1324. hr = E_INVALIDARG;
  1325. }
  1326. TraceHr(ttidError, FAL, hr, FALSE, "HrRegisterService:(%s) (%s)", pSsdpMessage->szType, pSsdpMessage->szUSN);
  1327. return hr;
  1328. }
  1329. HRESULT CDescriptionManager::HrPD_DoRootNotification(
  1330. IXMLDOMNodePtr & pNodeRootDevice,
  1331. SSDP_MESSAGE * pMsg,
  1332. HandleList * pHandleList)
  1333. {
  1334. TraceTag(ttidDescMan, "CDescriptionManager::HrPD_DoRootNotification");
  1335. HRESULT hr = S_OK;
  1336. // Do the root node notification
  1337. char szaUSN[256];
  1338. HANDLE hSvc;
  1339. // Get the UDN
  1340. CUString strUDN;
  1341. hr = HrSelectNodeText(L"UDN", pNodeRootDevice, strUDN);
  1342. if(SUCCEEDED(hr))
  1343. {
  1344. // Format the fields, generate the notificatio, and save the handle
  1345. wsprintfA(szaUSN, "%S::upnp:rootdevice", static_cast<const wchar_t*>(strUDN));
  1346. pMsg->szUSN = szaUSN;
  1347. pMsg->szType = "upnp:rootdevice";
  1348. hr = HrRegisterService(pMsg, 0, &hSvc);
  1349. if(SUCCEEDED(hr))
  1350. {
  1351. hr = pHandleList->HrPushBack(hSvc);
  1352. }
  1353. }
  1354. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPD_DoRootNotification");
  1355. return hr;
  1356. }
  1357. HRESULT CDescriptionManager::HrPD_DoDevicePublication(
  1358. IXMLDOMNodeListPtr & pNodeListDevices,
  1359. SSDP_MESSAGE * pMsg,
  1360. HandleList * pHandleList)
  1361. {
  1362. TraceTag(ttidDescMan, "CDescriptionManager::HrPD_DoDevicePublication");
  1363. HRESULT hr = S_OK;
  1364. // Do the device publication
  1365. char szaUSN[256];
  1366. char szaType[256];
  1367. HANDLE hSvc;
  1368. // Process each node in the device list
  1369. HRESULT hrTmp = S_OK;
  1370. while(SUCCEEDED(hr))
  1371. {
  1372. IXMLDOMNodePtr pNode;
  1373. hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
  1374. if(S_OK != hrTmp)
  1375. {
  1376. break;
  1377. }
  1378. // Fetch the UDN
  1379. CUString strUDN;
  1380. hr = HrSelectNodeText(L"UDN", pNode, strUDN);
  1381. if(SUCCEEDED(hr))
  1382. {
  1383. wsprintfA(szaUSN, "%S", static_cast<const wchar_t*>(strUDN));
  1384. pMsg->szUSN = szaUSN;
  1385. pMsg->szType = szaUSN;
  1386. hr = HrRegisterService(pMsg, 0, &hSvc);
  1387. if(SUCCEEDED(hr))
  1388. {
  1389. hr = pHandleList->HrPushBack(hSvc);
  1390. }
  1391. }
  1392. if(SUCCEEDED(hr))
  1393. {
  1394. // Fetch the device type
  1395. CUString strDeviceType;
  1396. hr = HrSelectNodeText(L"deviceType", pNode, strDeviceType);
  1397. if(SUCCEEDED(hr))
  1398. {
  1399. wsprintfA(szaUSN, "%S::%S", static_cast<const wchar_t*>(strUDN), static_cast<const wchar_t*>(strDeviceType));
  1400. wsprintfA(szaType, "%S", static_cast<const wchar_t*>(strDeviceType));
  1401. pMsg->szUSN = szaUSN;
  1402. pMsg->szType = szaType;
  1403. hr = HrRegisterService(pMsg, 0, &hSvc);
  1404. if(SUCCEEDED(hr))
  1405. {
  1406. hr = pHandleList->HrPushBack(hSvc);
  1407. }
  1408. }
  1409. }
  1410. // Do the services
  1411. if(SUCCEEDED(hr))
  1412. {
  1413. hr = HrPD_DoServicePublication(pNode, strUDN, pMsg, pHandleList);
  1414. }
  1415. }
  1416. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPD_DoDevicePublication");
  1417. return hr;
  1418. }
  1419. HRESULT CDescriptionManager::HrPD_DoServicePublication(
  1420. IXMLDOMNodePtr & pNodeDevice,
  1421. const CUString & strUDN,
  1422. SSDP_MESSAGE * pMsg,
  1423. HandleList * pHandleList)
  1424. {
  1425. TraceTag(ttidDescMan, "CDescriptionManager::HrPD_DoServicePublication");
  1426. HRESULT hr = S_OK;
  1427. // Do the services
  1428. char szaUSN[256];
  1429. char szaType[256];
  1430. HANDLE hSvc;
  1431. // Get the services for this device
  1432. IXMLDOMNodeListPtr pNodeListServices;
  1433. hr = HrSelectNodes(L"serviceList/service", pNodeDevice, pNodeListServices);
  1434. if(SUCCEEDED(hr))
  1435. {
  1436. // Process each service in the list
  1437. HRESULT hrTmp = S_OK;
  1438. while(SUCCEEDED(hr))
  1439. {
  1440. IXMLDOMNodePtr pNodeService;
  1441. hrTmp = pNodeListServices->nextNode(pNodeService.AddressOf());
  1442. if(S_OK != hrTmp)
  1443. {
  1444. break;
  1445. }
  1446. // Fetch the service type
  1447. CUString strServiceType;
  1448. hr = HrSelectNodeText(L"serviceType", pNodeService, strServiceType);
  1449. // We need to only send out one anouncement for each service type.
  1450. // Do a selectSingleNode for this type and see if we match.
  1451. IXMLDOMNodePtr pNodeTemp;
  1452. if(SUCCEEDED(hr))
  1453. {
  1454. CUString strPattern;
  1455. hr = strPattern.HrAssign(L"serviceList/service[./serviceType = '");
  1456. if(SUCCEEDED(hr))
  1457. {
  1458. hr = strPattern.HrAppend(strServiceType);
  1459. if(SUCCEEDED(hr))
  1460. {
  1461. hr = strPattern.HrAppend(L"']");
  1462. }
  1463. }
  1464. if(SUCCEEDED(hr))
  1465. {
  1466. hr = HrSelectNode(strPattern, pNodeDevice, pNodeTemp);
  1467. }
  1468. }
  1469. if(SUCCEEDED(hr) && S_OK == pNodeTemp.HrIsEqual(pNodeService))
  1470. {
  1471. wsprintfA(szaType, "%S", static_cast<const wchar_t*>(strServiceType));
  1472. wsprintfA(szaUSN, "%S::%S", static_cast<const wchar_t*>(strUDN),
  1473. static_cast<const wchar_t*>(strServiceType));
  1474. pMsg->szUSN = szaUSN;
  1475. pMsg->szType = szaType;
  1476. hr = HrRegisterService(pMsg, 0, &hSvc);
  1477. if(SUCCEEDED(hr))
  1478. {
  1479. hr = pHandleList->HrPushBack(hSvc);
  1480. }
  1481. }
  1482. // Register with eventing
  1483. if(SUCCEEDED(hr))
  1484. {
  1485. hr = HrRegisterServiceWithEventing(pNodeService, strUDN, TRUE);
  1486. }
  1487. }
  1488. }
  1489. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrPD_DoServicePublication");
  1490. return hr;
  1491. }
  1492. STDMETHODIMP CDescriptionManager::PublishDescription(
  1493. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  1494. /*[in]*/ long nLifeTime)
  1495. {
  1496. CALock lock(*this);
  1497. HRESULT hr = S_OK;
  1498. char szaLocHeader[256];
  1499. SSDP_MESSAGE msg = {0};
  1500. CUString strUrl;
  1501. CUString strDesc;
  1502. HandleList *pHandleList = NULL;
  1503. // Set lifetime and invariants
  1504. msg.iLifeTime = nLifeTime;
  1505. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  1506. if ( SUCCEEDED( hr ) )
  1507. {
  1508. if ( !( pHandleList = new HandleList ) )
  1509. {
  1510. hr = E_OUTOFMEMORY;
  1511. }
  1512. }
  1513. if ( SUCCEEDED( hr ) )
  1514. {
  1515. hr = HrGetContentURL(guidPhysicalDeviceIdentifier, strDesc);
  1516. }
  1517. if(SUCCEEDED(hr))
  1518. {
  1519. hr = HrGetURLBase(strUrl);
  1520. if(SUCCEEDED(hr))
  1521. {
  1522. hr = strUrl.HrAppend(strDesc);
  1523. if(SUCCEEDED(hr))
  1524. {
  1525. wsprintfA(szaLocHeader, "%S", static_cast<const wchar_t*>(strUrl));
  1526. msg.szLocHeader = szaLocHeader;
  1527. }
  1528. }
  1529. }
  1530. IXMLDOMNodeListPtr pNodeListDevices;
  1531. IXMLDOMNodePtr pNodeRootDevice;
  1532. // Get the DOM collections needed
  1533. if(SUCCEEDED(hr))
  1534. {
  1535. IXMLDOMNodePtr pRootNode;
  1536. hr = HrLoadDocumentAndRootNode(guidPhysicalDeviceIdentifier, pRootNode);
  1537. if(SUCCEEDED(hr))
  1538. {
  1539. // Fetch the devices
  1540. hr = HrSelectNodes(L"//device", pRootNode, pNodeListDevices);
  1541. if(SUCCEEDED(hr))
  1542. {
  1543. hr = HrSelectNode(L"/root/device", pRootNode, pNodeRootDevice);
  1544. }
  1545. }
  1546. }
  1547. // Do the root node notification
  1548. if(SUCCEEDED(hr))
  1549. {
  1550. hr = HrPD_DoRootNotification(pNodeRootDevice, &msg, pHandleList);
  1551. }
  1552. // Do the device publication
  1553. if(SUCCEEDED(hr))
  1554. {
  1555. hr = HrPD_DoDevicePublication(pNodeListDevices, &msg, pHandleList);
  1556. }
  1557. // If we have succeeded then add handle array to table
  1558. if(SUCCEEDED(hr))
  1559. {
  1560. AssertSz(!m_ssdpRegistrationTable.Lookup(guidPhysicalDeviceIdentifier),
  1561. "CDescriptionManager::PublishDescription: Republishing known identifier!");
  1562. hr = m_ssdpRegistrationTable.HrInsert(guidPhysicalDeviceIdentifier, pHandleList);
  1563. if(SUCCEEDED(hr))
  1564. {
  1565. // Do this so it doesn't get cleared below
  1566. pHandleList = NULL;
  1567. }
  1568. }
  1569. // If handle list gets added to data structure it will be nulled out and this won't be cleaned up
  1570. if(pHandleList)
  1571. {
  1572. long nCount = pHandleList->GetCount();
  1573. for(long n = 0; n < nCount; ++n)
  1574. {
  1575. DeregisterService((*pHandleList)[n], TRUE);
  1576. }
  1577. delete pHandleList;
  1578. }
  1579. if(FAILED(hr))
  1580. {
  1581. HrRD_RemoveFromEventing(guidPhysicalDeviceIdentifier);
  1582. }
  1583. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::PublishDescription");
  1584. return hr;
  1585. }
  1586. HRESULT CDescriptionManager::HrLD_ReadUDNMappings(
  1587. HKEY hKeyPdi,
  1588. UDNReplacementTable & udnReplacementTable)
  1589. {
  1590. TraceTag(ttidDescMan, "CDescriptionManager::HrLD_ReadUDNMappings");
  1591. HRESULT hr = S_OK;
  1592. // Read the UDN mappings
  1593. HKEY hKeyMappings;
  1594. hr = HrRegOpenKeyEx(hKeyPdi, c_szUDNMappings, KEY_ALL_ACCESS, &hKeyMappings);
  1595. if(SUCCEEDED(hr))
  1596. {
  1597. wchar_t szBuf[_MAX_PATH];
  1598. DWORD dwSize = _MAX_PATH;
  1599. FILETIME ft;
  1600. DWORD dwIndex;
  1601. for(dwIndex = 0;
  1602. SUCCEEDED(hr) && S_OK == HrRegEnumKeyEx(hKeyMappings, dwIndex, szBuf, &dwSize, NULL, NULL, &ft);
  1603. dwSize = _MAX_PATH, ++dwIndex)
  1604. {
  1605. // Open the mapping key
  1606. HKEY hKeyMapping;
  1607. hr = HrRegOpenKeyEx(hKeyMappings, szBuf, KEY_ALL_ACCESS, &hKeyMapping);
  1608. if(SUCCEEDED(hr))
  1609. {
  1610. CUString strFrom;
  1611. CUString strTo;
  1612. hr = strFrom.HrAssign(szBuf);
  1613. if(SUCCEEDED(hr))
  1614. {
  1615. hr = HrRegQueryString(hKeyMapping, L"", strTo);
  1616. if(SUCCEEDED(hr))
  1617. {
  1618. hr = udnReplacementTable.HrInsertTransfer(strFrom, strTo);
  1619. }
  1620. }
  1621. RegCloseKey(hKeyMapping);
  1622. }
  1623. }
  1624. RegCloseKey(hKeyMappings);
  1625. }
  1626. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_ReadUDNMappings");
  1627. return hr;
  1628. }
  1629. HRESULT CDescriptionManager::HrLD_ReadFileMappings(
  1630. HKEY hKeyPdi,
  1631. FileTable & fileTable)
  1632. {
  1633. TraceTag(ttidDescMan, "CDescriptionManager::HrLD_ReadFileMappings");
  1634. HRESULT hr = S_OK;
  1635. HKEY hKeyFileMappings;
  1636. hr = HrRegOpenKeyEx(hKeyPdi, c_szFiles, KEY_ALL_ACCESS, &hKeyFileMappings);
  1637. if(SUCCEEDED(hr))
  1638. {
  1639. wchar_t szBuf[_MAX_PATH];
  1640. DWORD dwSize = _MAX_PATH;
  1641. FILETIME ft;
  1642. DWORD dwIndex;
  1643. for(dwIndex = 0;
  1644. SUCCEEDED(hr) && S_OK == HrRegEnumKeyEx(hKeyFileMappings, dwIndex, szBuf, &dwSize, NULL, NULL, &ft);
  1645. dwSize = _MAX_PATH, ++dwIndex)
  1646. {
  1647. // Open the mapping key
  1648. HKEY hKeyMapping;
  1649. hr = HrRegOpenKeyEx(hKeyFileMappings, szBuf, KEY_ALL_ACCESS, &hKeyMapping);
  1650. if(SUCCEEDED(hr))
  1651. {
  1652. // Convert the FileId to a guid
  1653. GUID guidFileId;
  1654. hr = CLSIDFromString(szBuf, &guidFileId);
  1655. if(SUCCEEDED(hr))
  1656. {
  1657. // Read the values
  1658. CUString strFilename;
  1659. CUString strMimetype;
  1660. hr = HrRegQueryString(hKeyMapping, c_szFilename, strFilename);
  1661. if(SUCCEEDED(hr))
  1662. {
  1663. hr = HrRegQueryString(hKeyMapping, c_szMimetype, strMimetype);
  1664. if(SUCCEEDED(hr))
  1665. {
  1666. FileInfo fi;
  1667. fi.m_filename.Transfer(strFilename);
  1668. fi.m_mimetype.Transfer(strMimetype);
  1669. hr = fileTable.HrInsertTransfer(guidFileId, fi);
  1670. }
  1671. }
  1672. }
  1673. RegCloseKey(hKeyMapping);
  1674. }
  1675. }
  1676. RegCloseKey(hKeyFileMappings);
  1677. }
  1678. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_ReadFileMappings");
  1679. return hr;
  1680. }
  1681. HRESULT CDescriptionManager::HrLD_LoadDescriptionDocumentFromDisk(
  1682. const PhysicalDeviceIdentifier & pdi,
  1683. IXMLDOMDocumentPtr & pDoc)
  1684. {
  1685. TraceTag(ttidDescMan, "CDescriptionManager::HrLD_LoadDescriptionDocumentFromDisk");
  1686. HRESULT hr = S_OK;
  1687. // Load the document - use the DOM to at least validate that it is XML
  1688. // Get the path to load from
  1689. CUString strPath;
  1690. hr = HrGetDescriptionDocumentPath(pdi, strPath);
  1691. if(SUCCEEDED(hr))
  1692. {
  1693. BSTR bstr = NULL;
  1694. hr = strPath.HrGetBSTR(&bstr);
  1695. if(SUCCEEDED(hr))
  1696. {
  1697. hr = pDoc.HrCreateInstanceInproc(CLSID_DOMDocument30);
  1698. if(SUCCEEDED(hr))
  1699. {
  1700. VARIANT var;
  1701. VariantInit(&var);
  1702. var.vt = VT_BSTR;
  1703. var.bstrVal = bstr;
  1704. VARIANT_BOOL vb;
  1705. hr = pDoc->load(var, &vb);
  1706. SysFreeString(bstr);
  1707. TraceHr(ttidError, FAL, hr, FALSE, "LoadDescription: IXMLDOMDocument::load failed.");
  1708. if(SUCCEEDED(hr) && !vb)
  1709. {
  1710. hr = E_FAIL;
  1711. }
  1712. if(FAILED(hr))
  1713. {
  1714. pDoc.Release();
  1715. }
  1716. }
  1717. }
  1718. }
  1719. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_LoadDescriptionDocumentFromDisk");
  1720. return hr;
  1721. }
  1722. HRESULT CDescriptionManager::HrLD_SaveDescriptionDocumentText(
  1723. IXMLDOMDocumentPtr & pDoc,
  1724. const PhysicalDeviceIdentifier & pdi)
  1725. {
  1726. TraceTag(ttidDescMan, "CDescriptionManager::HrLD_SaveDescriptionDocumentText");
  1727. HRESULT hr = S_OK;
  1728. // Save description document
  1729. BSTR bstrDocument = NULL;
  1730. IXMLDOMNodePtr pRootNode;
  1731. hr = pRootNode.HrAttach(pDoc);
  1732. if(SUCCEEDED(hr))
  1733. {
  1734. hr = pRootNode->get_xml(&bstrDocument);
  1735. if(SUCCEEDED(hr))
  1736. {
  1737. hr = m_documentTable.HrInsert(pdi, bstrDocument);
  1738. if(FAILED(hr))
  1739. {
  1740. SysFreeString(bstrDocument);
  1741. }
  1742. }
  1743. }
  1744. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrLD_SaveDescriptionDocumentText");
  1745. return hr;
  1746. }
  1747. STDMETHODIMP CDescriptionManager::LoadDescription(
  1748. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier)
  1749. {
  1750. CALock lock(*this);
  1751. HRESULT hr = S_OK;
  1752. UDNReplacementTable udnReplacementTable;
  1753. FileTable fileTable;
  1754. // Open physical device identifier's registry key
  1755. HKEY hKeyPdi;
  1756. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  1757. if (SUCCEEDED(hr))
  1758. {
  1759. hr = HrOpenPhysicalDeviceDescriptionKey(guidPhysicalDeviceIdentifier, &hKeyPdi);
  1760. }
  1761. if(SUCCEEDED(hr))
  1762. {
  1763. // Read the UDN mappings
  1764. hr = HrLD_ReadUDNMappings(hKeyPdi, udnReplacementTable);
  1765. // Read the file mappings
  1766. if(SUCCEEDED(hr))
  1767. {
  1768. hr = HrLD_ReadFileMappings(hKeyPdi, fileTable);
  1769. }
  1770. RegCloseKey(hKeyPdi);
  1771. }
  1772. IXMLDOMDocumentPtr pDoc;
  1773. // Load the document - use the DOM to at least validate that it is XML
  1774. if(SUCCEEDED(hr))
  1775. {
  1776. hr = HrLD_LoadDescriptionDocumentFromDisk(guidPhysicalDeviceIdentifier, pDoc);
  1777. }
  1778. // Everything has succeeded to memory so transfer to variables
  1779. if(SUCCEEDED(hr))
  1780. {
  1781. // Add entries to the cleanup table
  1782. CleanupItem ci;
  1783. ci.m_physicalDeviceIdentifier = guidPhysicalDeviceIdentifier;
  1784. long nCount = fileTable.Keys().GetCount();
  1785. for(long n = 0; n < nCount && SUCCEEDED(hr); ++n)
  1786. {
  1787. ci.m_fileId = fileTable.Keys()[n];
  1788. hr = m_cleanupList.HrPushBack(ci);
  1789. }
  1790. if(SUCCEEDED(hr))
  1791. {
  1792. {
  1793. CLock lockTable(m_critSecReplacementTable);
  1794. hr = m_replacementTable.HrInsertTransfer(const_cast<UUID&>(guidPhysicalDeviceIdentifier), udnReplacementTable);
  1795. }
  1796. if(SUCCEEDED(hr))
  1797. {
  1798. hr = m_fileTable.HrAppendTableTransfer(fileTable);
  1799. }
  1800. }
  1801. }
  1802. // Save description document
  1803. if(SUCCEEDED(hr))
  1804. {
  1805. hr = HrLD_SaveDescriptionDocumentText(pDoc, guidPhysicalDeviceIdentifier);
  1806. }
  1807. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::LoadDescription");
  1808. return hr;
  1809. }
  1810. HRESULT CDescriptionManager::HrRD_RemoveFromEventing(const PhysicalDeviceIdentifier & pdi)
  1811. {
  1812. TraceTag(ttidDescMan, "CDescriptionManager::HrRD_RemoveFromEventing");
  1813. HRESULT hr = S_OK;
  1814. // Remove from eventing
  1815. IXMLDOMNodePtr pRootNode;
  1816. hr = HrLoadDocumentAndRootNode(pdi, pRootNode);
  1817. if(SUCCEEDED(hr))
  1818. {
  1819. // Fetch the devices
  1820. IXMLDOMNodeListPtr pNodeListDevices;
  1821. hr = HrSelectNodes(L"//device", pRootNode, pNodeListDevices);
  1822. if(SUCCEEDED(hr))
  1823. {
  1824. // Process each node in the device list
  1825. HRESULT hrTmp = S_OK;
  1826. while(SUCCEEDED(hr))
  1827. {
  1828. IXMLDOMNodePtr pNode;
  1829. hrTmp = pNodeListDevices->nextNode(pNode.AddressOf());
  1830. if(S_OK != hrTmp)
  1831. {
  1832. break;
  1833. }
  1834. // Fetch the UDN
  1835. CUString strUDN;
  1836. hr = HrSelectNodeText(L"UDN", pNode, strUDN);
  1837. // Do the services
  1838. if(SUCCEEDED(hr))
  1839. {
  1840. // Get the services for this device
  1841. IXMLDOMNodeListPtr pNodeListServices;
  1842. hr = HrSelectNodes(L"serviceList/service", pNode, pNodeListServices);
  1843. if(SUCCEEDED(hr))
  1844. {
  1845. // Process each service in the list
  1846. HRESULT hrTmp = S_OK;
  1847. while(SUCCEEDED(hr))
  1848. {
  1849. IXMLDOMNodePtr pNodeService;
  1850. hrTmp = pNodeListServices->nextNode(pNodeService.AddressOf());
  1851. if(S_OK != hrTmp)
  1852. {
  1853. break;
  1854. }
  1855. // Deregister with eventing
  1856. hr = HrRegisterServiceWithEventing(pNodeService, strUDN, FALSE);
  1857. }
  1858. }
  1859. }
  1860. }
  1861. }
  1862. }
  1863. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrRD_RemoveFromEventing");
  1864. return hr;
  1865. }
  1866. HRESULT CDescriptionManager::HrRD_RemoveFromDataStructures(const PhysicalDeviceIdentifier & pdi)
  1867. {
  1868. TraceTag(ttidDescMan, "CDescriptionManager::HrRD_RemoveFromDataStructures");
  1869. HRESULT hr = S_OK;
  1870. // Remove from data structures
  1871. // Walk cleanup list
  1872. long n = 0;
  1873. while(n < m_cleanupList.GetCount())
  1874. {
  1875. for(n = 0; n < m_cleanupList.GetCount(); ++n)
  1876. {
  1877. // If we match this cleanup item then remove from fileTable and restart
  1878. if(pdi == m_cleanupList[n].m_physicalDeviceIdentifier)
  1879. {
  1880. m_fileTable.HrErase(m_cleanupList[n].m_fileId);
  1881. m_cleanupList.HrErase(n);
  1882. break;
  1883. }
  1884. }
  1885. }
  1886. // Remove from document table
  1887. BSTR * pbstr = m_documentTable.Lookup(pdi);
  1888. if(pbstr)
  1889. {
  1890. SysFreeString(*pbstr);
  1891. }
  1892. else
  1893. {
  1894. TraceTag(ttidError, "CDescriptionManager::RemoveDescription: Document not found!");
  1895. }
  1896. m_documentTable.HrErase(pdi);
  1897. // Free the UDN replacement table items
  1898. if(SUCCEEDED(hr))
  1899. {
  1900. CLock lockTable(m_critSecReplacementTable);
  1901. hr = m_replacementTable.HrErase(pdi);
  1902. }
  1903. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrRD_RemoveFromDataStructures");
  1904. return hr;
  1905. }
  1906. HRESULT CDescriptionManager::HrRD_CleanupPublication(const PhysicalDeviceIdentifier & pdi)
  1907. {
  1908. TraceTag(ttidDescMan, "CDescriptionManager::HrRD_CleanupPublication");
  1909. HRESULT hr = S_OK;
  1910. // Cleanup the publication
  1911. HandleList ** ppHandleList = NULL;
  1912. ppHandleList = m_ssdpRegistrationTable.Lookup(pdi);
  1913. if(ppHandleList)
  1914. {
  1915. long nCount = (*ppHandleList)->GetCount();
  1916. for(long n = 0; n < nCount; ++n)
  1917. {
  1918. DeregisterService((**ppHandleList)[n], TRUE);
  1919. }
  1920. delete *ppHandleList;
  1921. hr = m_ssdpRegistrationTable.HrErase(pdi);
  1922. }
  1923. else
  1924. {
  1925. hr = E_INVALIDARG;
  1926. }
  1927. TraceHr(ttidDescMan, FAL, hr, FALSE, "CDescriptionManager::HrRD_CleanupPublication");
  1928. return hr;
  1929. }
  1930. STDMETHODIMP CDescriptionManager::RemoveDescription(
  1931. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  1932. /*[in]*/ BOOL bPermanent)
  1933. {
  1934. CALock lock(*this);
  1935. HRESULT hr = S_OK;
  1936. // Remove from the registry if present
  1937. // Create / open description key
  1938. HKEY hKeyDescription;
  1939. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  1940. if (SUCCEEDED(hr))
  1941. {
  1942. hr = HrCreateOrOpenDescriptionKey(&hKeyDescription);
  1943. }
  1944. if(SUCCEEDED(hr))
  1945. {
  1946. // Generate key name and registry key
  1947. CUString strPdi;
  1948. hr = strPdi.HrInitFromGUID(guidPhysicalDeviceIdentifier);
  1949. if(SUCCEEDED(hr))
  1950. {
  1951. if(bPermanent)
  1952. {
  1953. hr = HrRegDeleteKeyTree(hKeyDescription, strPdi);
  1954. }
  1955. else
  1956. {
  1957. // Just delete the file stuff
  1958. HKEY hKeyPdi;
  1959. hr = HrRegOpenKeyEx(hKeyDescription, strPdi, KEY_ALL_ACCESS, &hKeyPdi);
  1960. if(SUCCEEDED(hr))
  1961. {
  1962. hr = HrRegDeleteKeyTree(hKeyPdi, c_szFiles);
  1963. RegCloseKey(hKeyPdi);
  1964. }
  1965. }
  1966. }
  1967. RegCloseKey(hKeyDescription);
  1968. }
  1969. // Ignore registry failures
  1970. hr = S_OK;
  1971. // Delete the document from disk
  1972. CUString strPath;
  1973. hr = HrGetDescriptionDocumentPath(guidPhysicalDeviceIdentifier, strPath);
  1974. if(SUCCEEDED(hr))
  1975. {
  1976. DeleteFile(strPath);
  1977. }
  1978. // Ignore file deletion failures - might not exist
  1979. hr = S_OK;
  1980. // Remove from eventing
  1981. hr = HrRD_RemoveFromEventing(guidPhysicalDeviceIdentifier);
  1982. // Remove from data structures
  1983. hr = HrRD_RemoveFromDataStructures(guidPhysicalDeviceIdentifier);
  1984. // Cleanup the publication
  1985. hr = HrRD_CleanupPublication(guidPhysicalDeviceIdentifier);
  1986. // Remove Virtual Directory Created for Presentation
  1987. // CHECK - Virtual Directory may not be present
  1988. hr = HrRemovePresentationVirtualDir(guidPhysicalDeviceIdentifier);
  1989. if (FAILED(hr))
  1990. hr = S_OK ;
  1991. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::RemoveDescription");
  1992. return hr;
  1993. }
  1994. STDMETHODIMP CDescriptionManager::GetDescriptionText(
  1995. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  1996. /*[out]*/ BSTR * pbstrDescriptionDocument)
  1997. {
  1998. CHECK_POINTER(pbstrDescriptionDocument);
  1999. CALock lock(*this);
  2000. HRESULT hr = S_OK;
  2001. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  2002. if (SUCCEEDED(hr))
  2003. {
  2004. // Lookup the id
  2005. BSTR * pbstrDocument = m_documentTable.Lookup(guidPhysicalDeviceIdentifier);
  2006. if(pbstrDocument)
  2007. {
  2008. hr = HrSysAllocString(*pbstrDocument, pbstrDescriptionDocument);
  2009. }
  2010. else
  2011. {
  2012. hr = E_INVALIDARG;
  2013. }
  2014. }
  2015. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetDescriptionText");
  2016. return hr;
  2017. }
  2018. STDMETHODIMP CDescriptionManager::GetUDNs(
  2019. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  2020. /*[out]*/ long * pnUDNCount,
  2021. /*[out, size_is(,*pnUDNCount,), string]*/
  2022. wchar_t *** parszUDNs)
  2023. {
  2024. CHECK_POINTER(pnUDNCount);
  2025. CHECK_POINTER(parszUDNs);
  2026. CALock lock(*this);
  2027. HRESULT hr = S_OK;
  2028. IXMLDOMNodePtr pRootNode;
  2029. IXMLDOMNodeListPtr pNodeListUDNs;
  2030. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  2031. if (SUCCEEDED(hr))
  2032. {
  2033. hr = HrLoadDocumentAndRootNode(guidPhysicalDeviceIdentifier, pRootNode);
  2034. }
  2035. if(SUCCEEDED(hr))
  2036. {
  2037. // Fetch the UDNs
  2038. hr = HrSelectNodes(L"//UDN", pRootNode, pNodeListUDNs);
  2039. }
  2040. long nLength = 0;
  2041. wchar_t ** arszUDNs = NULL;
  2042. // Process the UDNs
  2043. if(SUCCEEDED(hr))
  2044. {
  2045. // Get length
  2046. hr = pNodeListUDNs->get_length(&nLength);
  2047. if(SUCCEEDED(hr))
  2048. {
  2049. // Allocate array
  2050. hr = HrCoTaskMemAllocArray(nLength, &arszUDNs);
  2051. if(SUCCEEDED(hr))
  2052. {
  2053. // Fill with zeros
  2054. ZeroMemory(arszUDNs, sizeof(wchar_t*) * nLength);
  2055. // Fetch all of the UDNs
  2056. long n = 0;
  2057. while(SUCCEEDED(hr))
  2058. {
  2059. IXMLDOMNodePtr pNode;
  2060. HRESULT hrTmp = S_OK;
  2061. // Fetch a node
  2062. hrTmp = pNodeListUDNs->nextNode(pNode.AddressOf());
  2063. if(S_OK != hrTmp)
  2064. {
  2065. break;
  2066. }
  2067. // Get the text
  2068. CUString strText;
  2069. hr = HrGetNodeText(pNode, strText);
  2070. if(SUCCEEDED(hr))
  2071. {
  2072. hr = strText.HrGetCOM(arszUDNs+n);
  2073. }
  2074. ++n;
  2075. }
  2076. }
  2077. }
  2078. }
  2079. if(FAILED(hr))
  2080. {
  2081. if(arszUDNs)
  2082. {
  2083. // Free strings
  2084. for(long n = 0; n < nLength; ++n)
  2085. {
  2086. if(arszUDNs[n])
  2087. {
  2088. CoTaskMemFree(arszUDNs[n]);
  2089. }
  2090. }
  2091. CoTaskMemFree(arszUDNs);
  2092. }
  2093. arszUDNs = NULL;
  2094. nLength = 0;
  2095. }
  2096. // Copy to output parameters
  2097. *pnUDNCount = nLength;
  2098. *parszUDNs = arszUDNs;
  2099. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetUDNs");
  2100. return hr;
  2101. }
  2102. STDMETHODIMP CDescriptionManager::GetUniqueDeviceName(
  2103. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  2104. /*[in, string]*/ const wchar_t * szTemplateUDN,
  2105. /*[out, string]*/ wchar_t ** pszUDN)
  2106. {
  2107. CHECK_POINTER(szTemplateUDN);
  2108. CHECK_POINTER(pszUDN);
  2109. HRESULT hr = S_OK;
  2110. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  2111. if (FAILED(hr))
  2112. {
  2113. return hr;
  2114. }
  2115. // Only lock the replacement table
  2116. CLock lock(m_critSecReplacementTable);
  2117. *pszUDN = NULL;
  2118. CUString strTemplateUDN;
  2119. hr = strTemplateUDN.HrAssign(szTemplateUDN);
  2120. if(SUCCEEDED(hr))
  2121. {
  2122. UDNReplacementTable * pudnReplacementTable = m_replacementTable.Lookup(guidPhysicalDeviceIdentifier);
  2123. if(pudnReplacementTable)
  2124. {
  2125. CUString * pstrUDN = pudnReplacementTable->Lookup(strTemplateUDN);
  2126. if(pstrUDN)
  2127. {
  2128. hr = pstrUDN->HrGetCOM(pszUDN);
  2129. }
  2130. }
  2131. }
  2132. // If we didn't find it in our tables then fail
  2133. if(!*pszUDN && SUCCEEDED(hr))
  2134. {
  2135. hr = E_INVALIDARG;
  2136. }
  2137. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetUniqueDeviceName");
  2138. return hr;
  2139. }
  2140. STDMETHODIMP CDescriptionManager::GetSCPDText(
  2141. /*[in]*/ REFGUID guidPhysicalDeviceIdentifier,
  2142. /*[in, string]*/ const wchar_t * szUDN,
  2143. /*[in, string]*/ const wchar_t * szServiceId,
  2144. /*[out, string]*/ wchar_t ** pszSCPDText,
  2145. /*[out, string]*/ wchar_t ** pszServiceType)
  2146. {
  2147. CHECK_POINTER(szUDN);
  2148. CHECK_POINTER(szServiceId);
  2149. CHECK_POINTER(pszSCPDText);
  2150. CHECK_POINTER(pszServiceType);
  2151. HRESULT hr = S_OK;
  2152. IXMLDOMNodePtr pRootNode;
  2153. IXMLDOMNodeListPtr pNodeListUDNs;
  2154. CUString strSCPDURL;
  2155. hr = HrIsAllowedCOMCallLocality((CALL_LOCALITY) CALL_LOCALITY_INPROC);
  2156. if (SUCCEEDED(hr))
  2157. {
  2158. // Get the SCPDURL
  2159. hr = HrLoadDocumentAndRootNode(guidPhysicalDeviceIdentifier, pRootNode);
  2160. }
  2161. if(SUCCEEDED(hr))
  2162. {
  2163. // Fetch the service node //service/SCPDURL[../serviceId = szServiceId]
  2164. CUString strPattern;
  2165. hr = strPattern.HrAssign(L"//service/SCPDURL[../serviceId = '");
  2166. if(SUCCEEDED(hr))
  2167. {
  2168. hr = strPattern.HrAppend(szServiceId);
  2169. if(SUCCEEDED(hr))
  2170. {
  2171. hr = strPattern.HrAppend(L"']");
  2172. if(SUCCEEDED(hr))
  2173. {
  2174. hr = HrSelectNodeText(strPattern, pRootNode, strSCPDURL);
  2175. }
  2176. }
  2177. }
  2178. }
  2179. // Get the GUID out of the URL
  2180. if(SUCCEEDED(hr))
  2181. {
  2182. UUID uuid;
  2183. hr = HrContentURLToGUID(strSCPDURL, uuid);
  2184. if(SUCCEEDED(hr))
  2185. {
  2186. // Fetch the content
  2187. long nHeaderCount = 0;
  2188. wchar_t ** arszHeaders = NULL;
  2189. long nBytes = 0;
  2190. byte * pBytes = NULL;
  2191. hr = GetContent(uuid, &nHeaderCount, &arszHeaders, &nBytes, &pBytes);
  2192. if(SUCCEEDED(hr))
  2193. {
  2194. // Content is not NULL terminate so reallocate with another character (yeah its cheesy)
  2195. hr = HrCoTaskMemAllocArray(nBytes + 1, pszSCPDText);
  2196. if(SUCCEEDED(hr))
  2197. {
  2198. // Copy text and convert from UTF-8 to unicode
  2199. if(!MultiByteToWideChar(CP_UTF8, 0, reinterpret_cast<char*>(pBytes), nBytes, *pszSCPDText, nBytes))
  2200. {
  2201. hr = HrFromLastWin32Error();
  2202. }
  2203. if(SUCCEEDED(hr))
  2204. {
  2205. // Null terminate
  2206. (*pszSCPDText)[nBytes] = 0;
  2207. }
  2208. }
  2209. // Free everything
  2210. CoTaskMemFree(pBytes);
  2211. for(long n = 0; n < nHeaderCount; ++n)
  2212. {
  2213. CoTaskMemFree(arszHeaders[n]);
  2214. }
  2215. CoTaskMemFree(arszHeaders);
  2216. }
  2217. }
  2218. }
  2219. // get the Service Type
  2220. if (SUCCEEDED(hr))
  2221. {
  2222. IXMLDOMNodePtr pServiceTypeNode;
  2223. // Fetch the service type //service/SCPDURL[../serviceId = szServiceId]
  2224. CUString strPattern;
  2225. hr = strPattern.HrAssign(L"//service/serviceType[../serviceId = '");
  2226. if(SUCCEEDED(hr))
  2227. {
  2228. hr = strPattern.HrAppend(szServiceId);
  2229. if(SUCCEEDED(hr))
  2230. {
  2231. hr = strPattern.HrAppend(L"']");
  2232. if(SUCCEEDED(hr))
  2233. {
  2234. hr = HrSelectNode(strPattern, pRootNode, pServiceTypeNode);
  2235. if (SUCCEEDED(hr))
  2236. {
  2237. BSTR bstr = NULL;
  2238. hr = pServiceTypeNode->get_text(&bstr);
  2239. if(SUCCEEDED(hr))
  2240. {
  2241. *pszServiceType = (wchar_t*)CoTaskMemAlloc(CbOfSzAndTerm(bstr));
  2242. if (*pszServiceType)
  2243. {
  2244. lstrcpy(*pszServiceType, bstr);
  2245. }
  2246. else
  2247. {
  2248. hr = E_OUTOFMEMORY;
  2249. }
  2250. SysFreeString(bstr);
  2251. }
  2252. }
  2253. }
  2254. }
  2255. }
  2256. }
  2257. TraceHr(ttidError, FAL, hr, FALSE, "CDescriptionManager::GetSCPDText");
  2258. return hr;
  2259. }
  2260. HRESULT HrCreateOrOpenDescriptionKey(
  2261. HKEY * phKeyDescription)
  2262. {
  2263. CHECK_POINTER(phKeyDescription);
  2264. HRESULT hr = S_OK;
  2265. HKEY hKeyDeviceHost;
  2266. hr = HrCreateOrOpenDeviceHostKey(&hKeyDeviceHost);
  2267. if(SUCCEEDED(hr))
  2268. {
  2269. DWORD dwDisposition = 0;
  2270. // Create / open description key
  2271. hr = HrRegCreateKeyEx(hKeyDeviceHost, c_szDescription, 0, KEY_ALL_ACCESS, NULL, phKeyDescription, &dwDisposition);
  2272. RegCloseKey(hKeyDeviceHost);
  2273. }
  2274. TraceHr(ttidError, FAL, hr, FALSE, "HrOpenDescriptionKey");
  2275. return hr;
  2276. }
  2277. HRESULT HrOpenPhysicalDeviceDescriptionKey(
  2278. const UUID & pdi,
  2279. HKEY * phKeyPdi)
  2280. {
  2281. CHECK_POINTER(phKeyPdi);
  2282. HRESULT hr = S_OK;
  2283. HKEY hKeyDescription;
  2284. hr = HrCreateOrOpenDescriptionKey(&hKeyDescription);
  2285. if(SUCCEEDED(hr))
  2286. {
  2287. CUString str;
  2288. hr = str.HrInitFromGUID(pdi);
  2289. if(SUCCEEDED(hr))
  2290. {
  2291. hr = HrRegOpenKeyEx(hKeyDescription, str, KEY_ALL_ACCESS, phKeyPdi);
  2292. }
  2293. RegCloseKey(hKeyDescription);
  2294. }
  2295. TraceHr(ttidError, FAL, hr, FALSE, "HrOpenPhysicalDeviceDescriptionKey");
  2296. return hr;
  2297. }
  2298. HRESULT HrGetDescriptionDocumentPath(
  2299. const UUID & pdi,
  2300. CUString & strPath)
  2301. {
  2302. HRESULT hr = S_OK;
  2303. hr = HrGetUPnPHostPath(strPath);
  2304. if(SUCCEEDED(hr))
  2305. {
  2306. hr = HrAddDirectoryToPath(strPath, c_szDescriptionDocuments);
  2307. if(SUCCEEDED(hr))
  2308. {
  2309. CUString strGUID;
  2310. hr = strGUID.HrInitFromGUID(pdi);
  2311. if(SUCCEEDED(hr))
  2312. {
  2313. hr = strPath.HrAppend(strGUID);
  2314. if(SUCCEEDED(hr))
  2315. {
  2316. hr = strPath.HrAppend(L".xml");
  2317. }
  2318. }
  2319. }
  2320. }
  2321. TraceHr(ttidError, FAL, hr, FALSE, "HrGetDescriptionDocumentPath");
  2322. return hr;
  2323. }
  2324. HRESULT HrRegisterServiceWithEventing(
  2325. IXMLDOMNodePtr & pNodeService,
  2326. const CUString & strUDN,
  2327. BOOL bRegister)
  2328. {
  2329. TraceTag(ttidDescMan, "HrRegisterServiceWithEventing");
  2330. HRESULT hr = S_OK;
  2331. // Register with eventing
  2332. CUString strSid;
  2333. hr = HrSelectNodeText(L"serviceId", pNodeService, strSid);
  2334. if(SUCCEEDED(hr))
  2335. {
  2336. // Generate the event identifier
  2337. CUString strESID;
  2338. hr = strESID.HrAssign(strUDN);
  2339. if(SUCCEEDED(hr))
  2340. {
  2341. hr = strESID.HrAppend(L"+");
  2342. if(SUCCEEDED(hr))
  2343. {
  2344. hr = strESID.HrAppend(strSid);
  2345. if(SUCCEEDED(hr))
  2346. {
  2347. if(bRegister)
  2348. {
  2349. hr = HrRegisterEventSource(strESID);
  2350. }
  2351. else
  2352. {
  2353. hr = HrDeregisterEventSource(strESID);
  2354. }
  2355. }
  2356. }
  2357. }
  2358. }
  2359. TraceHr(ttidDescMan, FAL, hr, FALSE, "HrRegisterServiceWithEventing");
  2360. return hr;
  2361. }