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.

879 lines
25 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 2000.
  5. //
  6. // File: V A L I D A T I O N M A N A G E R . C P P
  7. //
  8. // Contents: Validates device host inputs
  9. //
  10. // Notes:
  11. //
  12. // Author: mbend 9 Oct 2000
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "pch.h"
  16. #pragma hdrstop
  17. #include "uhbase.h"
  18. #include "ValidationManager.h"
  19. #include "uhutil.h"
  20. #include "ncstring.h"
  21. #include "validate.h"
  22. #include "uhcommon.h"
  23. // Functions declarationc
  24. HRESULT HrValidateDevice(
  25. IXMLDOMNodePtr & pNodeDevice,
  26. CUString & strErrorString);
  27. CValidationManager::CValidationManager ()
  28. {
  29. }
  30. CValidationManager::~CValidationManager ()
  31. {
  32. }
  33. HRESULT HrGetDocumentAndRootNode(
  34. BSTR bstrTemplate,
  35. IXMLDOMDocumentPtr & pDoc,
  36. IXMLDOMNodePtr & pRootNode)
  37. {
  38. TraceTag(ttidValidate, "HrGetDocumentAndRootNode");
  39. HRESULT hr = S_OK;
  40. // Load document and fetch needed items
  41. hr = HrLoadDocument(bstrTemplate, pDoc);
  42. if(SUCCEEDED(hr))
  43. {
  44. hr = pRootNode.HrAttach(pDoc);
  45. }
  46. TraceHr(ttidValidate, FAL, hr, FALSE, "HrGetDocumentAndRootNode");
  47. return hr;
  48. }
  49. struct PresenceItem
  50. {
  51. const wchar_t * m_szName;
  52. bool m_bEmpty;
  53. bool m_bSuffix;
  54. bool m_bOptional;
  55. LONG m_cchMax;
  56. };
  57. // m_szName EMPTY SUFFIX OPTONAL CCH
  58. // ----------------------------------------------------------
  59. const PresenceItem g_arpiDeviceItems[] =
  60. {
  61. {L"deviceType", false, true, false, 64},
  62. {L"friendlyName", false, false, false, 64},
  63. {L"manufacturer", false, false, false, 64},
  64. {L"manufacturerURL", false, false, true, -1},
  65. {L"modelDescription", false, false, true, 128},
  66. {L"modelName", false, false, false, 32},
  67. {L"modelNumber", false, false, true, 32},
  68. {L"modelURL", false, false, true, -1},
  69. {L"serialNumber", false, false, true, 64},
  70. {L"UDN", false, false, false, -1},
  71. {L"UPC", false, false, true, 12},
  72. };
  73. const long c_nDeviceItems = celems(g_arpiDeviceItems);
  74. PresenceItem g_arpiServiceItems[] =
  75. {
  76. {L"serviceType", false, true, false, 64},
  77. {L"serviceId", false, true, false, 64},
  78. {L"SCPDURL", false, false, false, -1},
  79. {L"controlURL", true, false, false, -1},
  80. {L"eventSubURL", true, false, false, -1},
  81. };
  82. const long c_nServiceItems = celems(g_arpiServiceItems);
  83. PresenceItem g_arpiIconItems[] =
  84. {
  85. {L"mimetype", false, false, false, -1},
  86. {L"width", false, false, false, -1},
  87. {L"height", false, false, false, -1},
  88. {L"depth", false, false, false, -1},
  89. {L"url", false, false, false, -1},
  90. };
  91. const long c_nIconItems = celems(g_arpiIconItems);
  92. PresenceItem g_arpiRootItems[] =
  93. {
  94. {L"/root/specVersion", false, false, false, -1},
  95. };
  96. const long c_nRootItems = celems(g_arpiRootItems);
  97. HRESULT HrValidateSufixes(IXMLDOMNodePtr & pNode,
  98. const wchar_t * szName,
  99. LONG cchMax,
  100. CUString & strErrorString)
  101. {
  102. HRESULT hr = S_OK;
  103. DWORD ctok = 0;
  104. LPCWSTR pchText;
  105. CUString strText;
  106. IXMLDOMNodePtr pNodeItem;
  107. // This function validates the serviceType, deviceType, and serviceId
  108. // elements in the following way:
  109. // Each of these is of the form: urn:domain-name:keyword:SUFFIX:version
  110. // Since they all follow the same format (which currently we DO NOT
  111. // validate), we can make an assumption that the 4th token (SUFFIX) is the
  112. // one that we need to validate. The validation is strictly as according
  113. // to UPnP architecture 1.0 where this suffix must be <= 64 characters in
  114. // length.
  115. //
  116. hr = HrSelectNode(szName, pNode, pNodeItem);
  117. if (SUCCEEDED(hr))
  118. {
  119. hr = HrGetNodeText(pNodeItem, strText);
  120. if (SUCCEEDED(hr))
  121. {
  122. pchText = strText.GetBuffer();
  123. while (*pchText)
  124. {
  125. if (*pchText == L':')
  126. {
  127. ctok++;
  128. pchText++;
  129. if (ctok == 3)
  130. {
  131. // Fourth token is the one we need to examine
  132. LONG cch = 0;
  133. while (*pchText && *pchText != L':')
  134. {
  135. pchText++;
  136. cch++;
  137. }
  138. // ISSUE-2000/11/29-danielwe: We don't yet
  139. // validate the format of the suffix
  140. //
  141. if (cch > cchMax)
  142. {
  143. hr = strErrorString.HrPrintf(
  144. WszLoadString(_Module.GetResourceInstance(),
  145. IDS_SUFFIX_TOO_LONG),
  146. strText);
  147. if (SUCCEEDED(hr))
  148. {
  149. hr = UPNP_E_SUFFIX_TOO_LONG;
  150. }
  151. }
  152. break;
  153. }
  154. }
  155. else
  156. {
  157. pchText++;
  158. }
  159. }
  160. }
  161. }
  162. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateSufixes(%S)",
  163. strErrorString.GetLength() ? strErrorString.GetBuffer(): L"Unspecified");
  164. return hr;
  165. }
  166. HRESULT HrValidatePresenceItems(
  167. IXMLDOMNodePtr & pNode,
  168. long nPresenceItems,
  169. const PresenceItem * arPresenceItems,
  170. CUString & strErrorString)
  171. {
  172. HRESULT hr = S_OK;
  173. for(long n = 0; n < nPresenceItems && SUCCEEDED(hr); ++n)
  174. {
  175. AssertSz(FImplies(arPresenceItems[n].m_bEmpty,
  176. arPresenceItems[n].m_cchMax == -1),
  177. "Empty elements mean there shouldn't be a size to verify "
  178. "against! Fix the array above!");
  179. if(arPresenceItems[n].m_bEmpty)
  180. {
  181. hr = HrIsNodePresentOnceAndEmpty(arPresenceItems[n].m_szName, pNode);
  182. if(S_OK != hr)
  183. {
  184. hr = strErrorString.HrPrintf(
  185. WszLoadString(_Module.GetResourceInstance(), IDS_EMPTY_NODE_NOT_PRESENT),
  186. arPresenceItems[n].m_szName);
  187. if(SUCCEEDED(hr))
  188. {
  189. hr = UPNP_E_REQUIRED_ELEMENT_ERROR;
  190. }
  191. }
  192. }
  193. else if (!arPresenceItems[n].m_bSuffix)
  194. {
  195. hr = HrIsNodePresentOnceAndNotEmpty(arPresenceItems[n].m_szName, pNode);
  196. if(S_OK != hr)
  197. {
  198. if (UPNP_E_DUPLICATE_NOT_ALLOWED == hr)
  199. {
  200. // Didn't find the item and it's not optional
  201. hr = strErrorString.HrPrintf(
  202. WszLoadString(_Module.GetResourceInstance(),
  203. IDS_DUPLICATES_NOT_ALLOWED),
  204. arPresenceItems[n].m_szName);
  205. if(SUCCEEDED(hr))
  206. {
  207. hr = UPNP_E_DUPLICATE_NOT_ALLOWED;
  208. }
  209. }
  210. else if (!arPresenceItems[n].m_bOptional)
  211. {
  212. // Didn't find the item and it's not optional
  213. hr = strErrorString.HrPrintf(
  214. WszLoadString(_Module.GetResourceInstance(),
  215. IDS_NON_EMPTY_NODE_NOT_PRESENT),
  216. arPresenceItems[n].m_szName);
  217. if(SUCCEEDED(hr))
  218. {
  219. hr = UPNP_E_REQUIRED_ELEMENT_ERROR;
  220. }
  221. }
  222. else
  223. {
  224. // Element was optional
  225. hr = S_OK;
  226. }
  227. }
  228. else if (arPresenceItems[n].m_cchMax != -1)
  229. {
  230. // Check length if one is specified
  231. //
  232. hr = HrIsNodeOfValidLength(arPresenceItems[n].m_szName, pNode,
  233. arPresenceItems[n].m_cchMax);
  234. if(S_FALSE == hr)
  235. {
  236. hr = strErrorString.HrPrintf(
  237. WszLoadString(_Module.GetResourceInstance(), IDS_ELEMENT_VALUE_TOO_LONG),
  238. arPresenceItems[n].m_szName);
  239. if(SUCCEEDED(hr))
  240. {
  241. hr = UPNP_E_VALUE_TOO_LONG;
  242. }
  243. }
  244. else if (arPresenceItems[n].m_bOptional && (FAILED(hr)))
  245. {
  246. // If item was optional, forget any errors
  247. hr = S_OK;
  248. }
  249. }
  250. }
  251. if (SUCCEEDED(hr))
  252. {
  253. if (arPresenceItems[n].m_bSuffix && arPresenceItems[n].m_cchMax != -1)
  254. {
  255. hr = HrValidateSufixes(pNode, arPresenceItems[n].m_szName,
  256. arPresenceItems[n].m_cchMax,
  257. strErrorString);
  258. }
  259. }
  260. }
  261. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidatePresenceItems(%S)",
  262. strErrorString.GetLength() ? strErrorString.GetBuffer(): L"Unspecified");
  263. return hr;
  264. }
  265. HRESULT HrValidateDeviceService(
  266. IXMLDOMNodePtr & pNodeService,
  267. CUString & strErrorString)
  268. {
  269. HRESULT hr = S_OK;
  270. hr = HrValidatePresenceItems(pNodeService, c_nServiceItems, g_arpiServiceItems, strErrorString);
  271. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateDeviceService");
  272. return hr;
  273. }
  274. HRESULT HrCheckForDuplicatesInList(
  275. IXMLDOMNodeListPtr & pNodeList,
  276. CUString & strErrorString)
  277. {
  278. HRESULT hr = S_OK;
  279. CUArray<CUString> arstrValues;
  280. while(SUCCEEDED(hr))
  281. {
  282. IXMLDOMNodePtr pNode;
  283. HRESULT hrTemp = pNodeList->nextNode(pNode.AddressOf());
  284. if(S_OK != hrTemp)
  285. {
  286. break;
  287. }
  288. CUString strText;
  289. hr = HrGetNodeText(pNode, strText);
  290. if(SUCCEEDED(hr))
  291. {
  292. long nIndex = 0;
  293. hrTemp = arstrValues.HrFind(strText, nIndex);
  294. if(S_OK == hrTemp)
  295. {
  296. // We found a duplicate
  297. hr = strErrorString.HrPrintf(
  298. WszLoadString(_Module.GetResourceInstance(), IDS_DUPLICATES_NOT_ALLOWED),
  299. strText.GetBuffer());
  300. if(SUCCEEDED(hr))
  301. {
  302. hr = UPNP_E_DUPLICATE_NOT_ALLOWED;
  303. }
  304. }
  305. else
  306. {
  307. hr = arstrValues.HrPushBack(strText);
  308. }
  309. }
  310. }
  311. TraceHr(ttidValidate, FAL, hr, FALSE, "HrCheckForDuplicatesInList");
  312. return hr;
  313. }
  314. HRESULT HrValidateDeviceServices(
  315. IXMLDOMNodePtr & pNodeDevice,
  316. CUString & strErrorString)
  317. {
  318. HRESULT hr = S_OK;
  319. // serviceList is required and must contain a service
  320. BOOL bServiceNotPresent = TRUE;
  321. HRESULT hrTemp = HrIsNodePresentOnce(L"serviceList", pNodeDevice);
  322. if(S_OK == hrTemp)
  323. {
  324. IXMLDOMNodeListPtr pNodeList;
  325. hrTemp = HrSelectNodes(L"serviceList/service", pNodeDevice, pNodeList);
  326. if(S_OK == hrTemp)
  327. {
  328. while(SUCCEEDED(hr))
  329. {
  330. IXMLDOMNodePtr pNode;
  331. hrTemp = pNodeList->nextNode(pNode.AddressOf());
  332. if(S_OK != hrTemp)
  333. {
  334. break;
  335. }
  336. // We have a service
  337. bServiceNotPresent = FALSE;
  338. hr = HrValidateDeviceService(pNode, strErrorString);
  339. }
  340. }
  341. // Make sure all ServiceId's are unique
  342. if(SUCCEEDED(hr))
  343. {
  344. pNodeList.Release();
  345. hrTemp = HrSelectNodes(L"serviceList/service/serviceId", pNodeDevice, pNodeList);
  346. if(S_OK == hrTemp)
  347. {
  348. hr = HrCheckForDuplicatesInList(pNodeList, strErrorString);
  349. }
  350. }
  351. }
  352. if(bServiceNotPresent)
  353. {
  354. hr = strErrorString.HrAssign(
  355. WszLoadString(_Module.GetResourceInstance(), IDS_SERVICE_MISSING));
  356. if(SUCCEEDED(hr))
  357. {
  358. hr = UPNP_E_INVALID_SERVICE;
  359. }
  360. }
  361. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateDeviceServices");
  362. return hr;
  363. }
  364. HRESULT HrValidateDeviceIcon(
  365. IXMLDOMNodePtr & pNodeIcon,
  366. CUString & strErrorString)
  367. {
  368. HRESULT hr = S_OK;
  369. hr = HrValidatePresenceItems(pNodeIcon, c_nIconItems, g_arpiIconItems, strErrorString);
  370. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateDeviceIcon");
  371. return hr;
  372. }
  373. HRESULT HrValidateDeviceIcons(
  374. IXMLDOMNodePtr & pNodeDevice,
  375. CUString & strErrorString)
  376. {
  377. HRESULT hr = S_OK;
  378. HRESULT hrTemp = HrIsNodePresentOnce(L"iconList", pNodeDevice);
  379. if(S_OK == hrTemp)
  380. {
  381. BOOL fGotAnIcon = FALSE;
  382. IXMLDOMNodeListPtr pNodeList;
  383. hrTemp = HrSelectNodes(L"iconList/icon", pNodeDevice, pNodeList);
  384. if(S_OK == hrTemp)
  385. {
  386. while(SUCCEEDED(hr))
  387. {
  388. IXMLDOMNodePtr pNode;
  389. hrTemp = pNodeList->nextNode(pNode.AddressOf());
  390. if(S_OK != hrTemp)
  391. {
  392. break;
  393. }
  394. fGotAnIcon = TRUE;
  395. hr = HrValidateDeviceIcon(pNode, strErrorString);
  396. }
  397. }
  398. if (!fGotAnIcon)
  399. {
  400. hr = strErrorString.HrAssign(
  401. WszLoadString(_Module.GetResourceInstance(), IDS_ICON_MISSING));
  402. if(SUCCEEDED(hr))
  403. {
  404. hr = UPNP_E_INVALID_ICON;
  405. }
  406. }
  407. }
  408. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateDeviceIcons");
  409. return hr;
  410. }
  411. HRESULT HrValidateDeviceChildren(
  412. IXMLDOMNodePtr & pNodeDevice,
  413. CUString & strErrorString)
  414. {
  415. HRESULT hr = S_OK;
  416. BOOL fGotADevice = FALSE;
  417. HRESULT hrTemp = HrIsNodePresentOnce(L"deviceList", pNodeDevice);
  418. if(S_OK == hrTemp)
  419. {
  420. IXMLDOMNodeListPtr pNodeList;
  421. hrTemp = HrSelectNodes(L"deviceList/device", pNodeDevice, pNodeList);
  422. if(S_OK == hrTemp)
  423. {
  424. while(SUCCEEDED(hr))
  425. {
  426. IXMLDOMNodePtr pNode;
  427. hrTemp = pNodeList->nextNode(pNode.AddressOf());
  428. if(S_OK != hrTemp)
  429. {
  430. break;
  431. }
  432. fGotADevice = TRUE;
  433. hr = HrValidateDevice(pNode, strErrorString);
  434. }
  435. }
  436. if (!fGotADevice)
  437. {
  438. hr = strErrorString.HrAssign(
  439. WszLoadString(_Module.GetResourceInstance(), IDS_DEVICE_MISSING));
  440. if(SUCCEEDED(hr))
  441. {
  442. hr = UPNP_E_INVALID_DOCUMENT;
  443. }
  444. }
  445. }
  446. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateDeviceChildren");
  447. return hr;
  448. }
  449. HRESULT HrValidateDevice(
  450. IXMLDOMNodePtr & pNodeDevice,
  451. CUString & strErrorString)
  452. {
  453. TraceTag(ttidValidate, "HrValidateDevice");
  454. HRESULT hr = S_OK;
  455. hr = HrValidatePresenceItems(pNodeDevice, c_nDeviceItems, g_arpiDeviceItems, strErrorString);
  456. if(SUCCEEDED(hr))
  457. {
  458. hr = HrValidateDeviceServices(pNodeDevice, strErrorString);
  459. if(SUCCEEDED(hr))
  460. {
  461. hr = HrValidateDeviceIcons(pNodeDevice, strErrorString);
  462. if(SUCCEEDED(hr))
  463. {
  464. hr = HrValidateDeviceChildren(pNodeDevice, strErrorString);
  465. }
  466. }
  467. }
  468. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateDevice");
  469. return hr;
  470. }
  471. HRESULT HrValidateUDNs(
  472. IXMLDOMNodePtr & pNodeDevice,
  473. CUString & strErrorString)
  474. {
  475. HRESULT hr = S_OK;
  476. IXMLDOMNodeListPtr pNodeList;
  477. hr = HrSelectNodes(L"//UDN", pNodeDevice, pNodeList);
  478. if(SUCCEEDED(hr))
  479. {
  480. hr = HrCheckForDuplicatesInList(pNodeList, strErrorString);
  481. }
  482. TraceHr(ttidValidate, FAL, hr, FALSE, "HrValidateUDNs");
  483. return hr;
  484. }
  485. /*
  486. HRESULT HrValidateDevice(
  487. IXMLDOMNodePtr & pNodeDevice)
  488. {
  489. TraceTag(ttidValidate, "");
  490. HRESULT hr = S_OK;
  491. TraceHr(ttidValidate, FAL, hr, FALSE, "");
  492. return hr;
  493. }
  494. */
  495. // IUPnPValidationManager methods
  496. STDMETHODIMP CValidationManager::ValidateDescriptionDocument(
  497. /*[in]*/ BSTR bstrTemplate,
  498. /*[out, string]*/ wchar_t ** pszErrorString)
  499. {
  500. CHECK_POINTER(bstrTemplate);
  501. CHECK_POINTER(pszErrorString);
  502. HRESULT hr = S_OK;
  503. CUString strErrorString;
  504. *pszErrorString = NULL;
  505. IXMLDOMDocumentPtr pDoc;
  506. IXMLDOMNodePtr pRootNode;
  507. hr = HrIsAllowedCOMCallLocality(CALL_LOCALITY_INPROC);
  508. if (SUCCEEDED(hr))
  509. {
  510. hr = HrGetDocumentAndRootNode(bstrTemplate, pDoc, pRootNode);
  511. }
  512. if(SUCCEEDED(hr))
  513. {
  514. hr = HrValidatePresenceItems(pRootNode, c_nRootItems, g_arpiRootItems, strErrorString);
  515. if(SUCCEEDED(hr))
  516. {
  517. hr = HrIsNodePresentOnce(L"/root/device", pRootNode);
  518. if(S_OK == hr)
  519. {
  520. hr = HrIsNodePresentOnce(L"/root/URLBase", pRootNode);
  521. if (S_OK != hr)
  522. {
  523. hr = HrValidateUDNs(pRootNode, strErrorString);
  524. if(SUCCEEDED(hr))
  525. {
  526. IXMLDOMNodePtr pNodeDevice;
  527. hr = HrSelectNode(L"/root/device", pRootNode, pNodeDevice);
  528. if(SUCCEEDED(hr))
  529. {
  530. hr = HrValidateDevice(pNodeDevice, strErrorString);
  531. }
  532. }
  533. }
  534. else
  535. {
  536. hr = strErrorString.HrAssign(
  537. WszLoadString(_Module.GetResourceInstance(), IDS_URLBASE_PRESENT));
  538. if(SUCCEEDED(hr))
  539. {
  540. hr = UPNP_E_REQUIRED_ELEMENT_ERROR;
  541. }
  542. }
  543. }
  544. else
  545. {
  546. hr = strErrorString.HrAssign(
  547. WszLoadString(_Module.GetResourceInstance(), IDS_ROOT_DEVICE_MISSING));
  548. if(SUCCEEDED(hr))
  549. {
  550. hr = UPNP_E_REQUIRED_ELEMENT_ERROR;
  551. }
  552. }
  553. }
  554. }
  555. // Let's make sure the root namespace is according to spec
  556. //
  557. if (SUCCEEDED(hr))
  558. {
  559. IXMLDOMNodePtr pNodeRootSub;
  560. hr = HrSelectNode(L"/root", pRootNode, pNodeRootSub);
  561. if (SUCCEEDED(hr))
  562. {
  563. BSTR bstrUri;
  564. hr = pNodeRootSub->get_namespaceURI(&bstrUri);
  565. if (S_OK != hr || lstrcmpi(bstrUri,
  566. L"urn:schemas-upnp-org:device-1-0"))
  567. {
  568. hr = strErrorString.HrPrintf(
  569. WszLoadString(_Module.GetResourceInstance(),
  570. IDS_INVALID_ROOT_NAMESPACE),
  571. bstrUri);
  572. if(SUCCEEDED(hr))
  573. {
  574. hr = UPNP_E_INVALID_ROOT_NAMESPACE;
  575. }
  576. }
  577. }
  578. }
  579. if(FAILED(hr))
  580. {
  581. if(strErrorString.GetLength())
  582. {
  583. strErrorString.HrGetCOM(pszErrorString);
  584. }
  585. }
  586. TraceHr(ttidValidate, FAL, hr, FALSE, "CValidationManager::ValidateDescriptionDocument(%S)",
  587. *pszErrorString ? *pszErrorString : L"Unspecified");
  588. return hr;
  589. }
  590. STDMETHODIMP CValidationManager::ValidateServiceDescription(
  591. /*[in, string]*/ const wchar_t * szFullPath,
  592. /*[out, string]*/ wchar_t ** pszErrorString)
  593. {
  594. CHECK_POINTER(szFullPath);
  595. CHECK_POINTER(pszErrorString);
  596. HRESULT hr = S_OK;
  597. CUString strErrorString;
  598. *pszErrorString = NULL;
  599. BSTR bstrPath;
  600. IXMLDOMDocumentPtr pDoc;
  601. hr = HrIsAllowedCOMCallLocality(CALL_LOCALITY_INPROC);
  602. if (SUCCEEDED(hr))
  603. {
  604. bstrPath = SysAllocString(szFullPath);
  605. }
  606. if (bstrPath)
  607. {
  608. hr = HrLoadDocumentFromFile(bstrPath, pDoc);
  609. if (SUCCEEDED(hr))
  610. {
  611. IXMLDOMElementPtr pxdeSDRoot;
  612. hr = pDoc->get_documentElement(pxdeSDRoot.AddressOf());
  613. if (S_OK == hr)
  614. {
  615. hr = HrValidateServiceDescription(pxdeSDRoot, pszErrorString);
  616. }
  617. }
  618. else
  619. {
  620. hr = strErrorString.HrPrintf(
  621. WszLoadString(_Module.GetResourceInstance(), IDS_INVALID_XML),
  622. szFullPath);
  623. if(SUCCEEDED(hr))
  624. {
  625. hr = UPNP_E_INVALID_XML;
  626. }
  627. }
  628. SysFreeString(bstrPath);
  629. }
  630. else
  631. {
  632. hr = E_OUTOFMEMORY;
  633. }
  634. if(FAILED(hr))
  635. {
  636. if(strErrorString.GetLength())
  637. {
  638. strErrorString.HrGetCOM(pszErrorString);
  639. }
  640. }
  641. TraceHr(ttidValidate, FAL, hr, FALSE, "CValidationManager::ValidateServiceDescription(%S)",
  642. *pszErrorString ? *pszErrorString : L"Unspecified");
  643. return hr;
  644. }
  645. HRESULT CValidationManager::ValidateServiceDescriptions(const wchar_t * szResourcePath,
  646. IXMLDOMNodePtr pRootNode,
  647. wchar_t ** pszErrorString)
  648. {
  649. HRESULT hr = S_OK;
  650. IXMLDOMNodeListPtr pNodeList;
  651. // Select all of the SCPDURL nodes in the description document
  652. hr = HrSelectNodes(L"//device/serviceList/service/SCPDURL",
  653. pRootNode, pNodeList);
  654. while (S_OK == hr)
  655. {
  656. IXMLDOMNodePtr pNode;
  657. CUString strUrl;
  658. hr = pNodeList->nextNode(pNode.AddressOf());
  659. if (S_OK == hr)
  660. {
  661. hr = HrGetNodeText(pNode, strUrl);
  662. if (SUCCEEDED(hr))
  663. {
  664. CUString strFullPath;
  665. hr = HrMakeFullPath(szResourcePath, strUrl, strFullPath);
  666. if (SUCCEEDED(hr))
  667. {
  668. hr = ValidateServiceDescription(strFullPath,
  669. pszErrorString);
  670. }
  671. }
  672. }
  673. }
  674. if (SUCCEEDED(hr))
  675. {
  676. // normalize error code
  677. hr = S_OK;
  678. }
  679. TraceHr(ttidValidate, FAL, hr, FALSE, "CValidationManager::ValidateServiceDescriptions(%S)",
  680. *pszErrorString ? *pszErrorString : L"Unspecified");
  681. return hr;
  682. }
  683. HRESULT CValidationManager::ValidateIconFiles(const wchar_t * szResourcePath,
  684. IXMLDOMNodePtr pRootNode,
  685. wchar_t ** pszErrorString)
  686. {
  687. HRESULT hr = S_OK;
  688. IXMLDOMNodeListPtr pNodeList;
  689. CUString strErrorString;
  690. // Select all of the SCPDURL nodes in the description document
  691. hr = HrSelectNodes(L"//device/iconList/icon/url", pRootNode, pNodeList);
  692. while (S_OK == hr)
  693. {
  694. IXMLDOMNodePtr pNode;
  695. CUString strUrl;
  696. hr = pNodeList->nextNode(pNode.AddressOf());
  697. if (S_OK == hr)
  698. {
  699. hr = HrGetNodeText(pNode, strUrl);
  700. if (SUCCEEDED(hr))
  701. {
  702. CUString strFullPath;
  703. hr = HrMakeFullPath(szResourcePath, strUrl, strFullPath);
  704. if (SUCCEEDED(hr))
  705. {
  706. if (!FFileExists((LPTSTR)strFullPath.GetBuffer(), FALSE))
  707. {
  708. hr = strErrorString.HrPrintf(
  709. WszLoadString(_Module.GetResourceInstance(), IDS_INVALID_ICON),
  710. strFullPath);
  711. if(SUCCEEDED(hr))
  712. {
  713. hr = UPNP_E_INVALID_ICON;
  714. }
  715. }
  716. }
  717. }
  718. }
  719. }
  720. if(FAILED(hr))
  721. {
  722. if(strErrorString.GetLength())
  723. {
  724. strErrorString.HrGetCOM(pszErrorString);
  725. }
  726. }
  727. if (SUCCEEDED(hr))
  728. {
  729. // normalize error code
  730. hr = S_OK;
  731. }
  732. TraceHr(ttidValidate, FAL, hr, FALSE, "CValidationManager::ValidateIconFiles(%S)",
  733. *pszErrorString ? *pszErrorString : L"Unspecified");
  734. return hr;
  735. }
  736. STDMETHODIMP CValidationManager::ValidateDescriptionDocumentAndReferences(
  737. /*[in]*/ BSTR bstrTemplate,
  738. /*[in, string]*/ const wchar_t * szResourcePath,
  739. /*[out, string]*/ wchar_t ** pszErrorString)
  740. {
  741. CHECK_POINTER(bstrTemplate);
  742. CHECK_POINTER(szResourcePath);
  743. CHECK_POINTER(pszErrorString);
  744. HRESULT hr = S_OK;
  745. *pszErrorString = NULL;
  746. hr = HrIsAllowedCOMCallLocality(CALL_LOCALITY_INPROC);
  747. if (SUCCEEDED(hr))
  748. {
  749. hr = ValidateDescriptionDocument(bstrTemplate, pszErrorString);
  750. }
  751. if (SUCCEEDED(hr))
  752. {
  753. IXMLDOMDocumentPtr pDoc;
  754. IXMLDOMNodePtr pRootNode;
  755. hr = HrGetDocumentAndRootNode(bstrTemplate, pDoc, pRootNode);
  756. if (SUCCEEDED(hr))
  757. {
  758. hr = ValidateServiceDescriptions(szResourcePath, pRootNode,
  759. pszErrorString);
  760. if (SUCCEEDED(hr))
  761. {
  762. hr = ValidateIconFiles(szResourcePath, pRootNode,
  763. pszErrorString);
  764. }
  765. }
  766. }
  767. TraceHr(ttidValidate, FAL, hr, FALSE, "CValidationManager::ValidateDescriptionDocumentAndReferences(%S)",
  768. *pszErrorString ? *pszErrorString : L"Unspecified");
  769. return hr;
  770. }