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.

1837 lines
61 KiB

  1. //+-------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. //
  5. // Copyright (C) Microsoft Corporation, 2000
  6. //
  7. // File: auxml.cpp
  8. //
  9. // About: source file for AU related XML and schema data structure and functions
  10. //--------------------------------------------------------------------------
  11. #include "pch.h"
  12. //when changed, search for all occurrance of m_pFieldNames for needed modifications
  13. //fixcode: get rid of EULA stuff.
  14. LPSTR AUCatalogItem::m_pFieldNames[] = {"ItemID", "ProviderName", "Title", "Description", "RTFPath" , "EulaPath"};
  15. #ifdef DBG
  16. void DBGShowNodeName(IXMLDOMNode *pNode)
  17. {
  18. BSTR bsNodeName;
  19. if (SUCCEEDED(pNode->get_nodeName(&bsNodeName)))
  20. {
  21. DEBUGMSG("node name is %S", bsNodeName);
  22. }
  23. else
  24. {
  25. DEBUGMSG("FAIL to get node name");
  26. }
  27. }
  28. void DBGDumpXMLNode(IXMLDOMNode *pNode)
  29. {
  30. BSTR bsNodeName = NULL;
  31. BSTR bsNodeXML = NULL;
  32. if (SUCCEEDED(pNode->get_nodeName(&bsNodeName)) &&
  33. (SUCCEEDED(pNode->get_xml(&bsNodeXML))))
  34. {
  35. DEBUGMSG("XML for %S is %S", bsNodeName, bsNodeXML);
  36. }
  37. SafeFreeBSTR(bsNodeName);
  38. SafeFreeBSTR(bsNodeXML);
  39. }
  40. #endif
  41. #if 0
  42. void DBGDumpXMLDocProperties(IXMLDOMDocument2 *pDoc)
  43. {
  44. BSTR bsSelectionLanguage, bsSelectionNamespaces, bsServerHTTPRequest;
  45. VARIANT vVal;
  46. VariantInit(&vVal);
  47. pDoc->getProperty(L"SelectionLanguage", &vVal);
  48. DEBUGMSG("XMLDoc selection language is %S", vVal.bstrVal);
  49. VariantClear(&vVal);
  50. pDoc->getProperty(L"SelectionNamespaces", &vVal);
  51. DEBUGMSG("XMLDoc selection namespaces is %S", vVal.bstrVal);
  52. VariantClear(&vVal);
  53. pDoc->getProperty(L"ServerHTTPRequest", &vVal);
  54. DEBUGMSG("XMLDoc ServerHTTPRequest is %s", vVal.boolVal ? "True" : "False");
  55. VariantClear(&vVal);
  56. }
  57. #endif
  58. BSTR ReadXMLFromFile(IN LPCTSTR szFileName)
  59. {
  60. TCHAR tszFullFileName[MAX_PATH];
  61. IXMLDOMDocument *pxml = NULL;
  62. BSTR bstrXml = NULL;
  63. // USES_CONVERSION;
  64. // DEBUGMSG("ReadXMLFromFile() starts");
  65. AUASSERT(_T('\0') != g_szWUDir[0]);
  66. if(FAILED(StringCchCopyEx(tszFullFileName, ARRAYSIZE(tszFullFileName), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  67. FAILED(StringCchCatEx(tszFullFileName, ARRAYSIZE(tszFullFileName), szFileName, NULL, NULL, MISTSAFE_STRING_FLAGS)))
  68. {
  69. DEBUGMSG("file name or path too long");
  70. goto done;
  71. }
  72. if (!fFileExists(tszFullFileName))
  73. {
  74. DEBUGMSG("%S doesn't exists on disk", tszFullFileName);
  75. }
  76. else
  77. {
  78. CAU_BSTR aubsFullFileName;
  79. HRESULT hr;
  80. if (!aubsFullFileName.append(T2W(tszFullFileName)))
  81. {
  82. DEBUGMSG("Out of memory, fail to create string");
  83. goto done;
  84. }
  85. if (FAILED(hr = LoadDocument(aubsFullFileName, &pxml, TRUE))) //offline
  86. {
  87. DEBUGMSG("Fail to load xml document %S with error %#lx", tszFullFileName, hr);
  88. goto done;
  89. }
  90. if (FAILED(hr = pxml->get_xml(&bstrXml)))
  91. {
  92. DEBUGMSG("Fail to get xml string from document with error %#lx", hr);
  93. goto done;
  94. }
  95. }
  96. done:
  97. SafeRelease(pxml);
  98. // DEBUGMSG("ReadXMLFromFile() ends");
  99. return bstrXml;
  100. }
  101. HRESULT MungleIdentity(IN IXMLDOMNode *pIdentity, IN DWORD dwSuffix)
  102. {
  103. BSTR bstrItemName = NULL;
  104. CAU_BSTR aubsTmp;
  105. WCHAR wcsBuf[12]; //will accomodate the maxium dword
  106. HRESULT hr = S_OK;
  107. if (0 == dwSuffix)
  108. {
  109. goto done;
  110. }
  111. if (NULL == pIdentity)
  112. {
  113. hr = E_INVALIDARG;
  114. goto done;
  115. }
  116. if (FAILED(hr = GetAttribute(pIdentity, KEY_NAME, &bstrItemName)))
  117. { DEBUGMSG("Fail to get name from identity with error %#lx", hr);
  118. goto done;
  119. }
  120. if (FAILED(StringCchPrintfExW(wcsBuf, ARRAYSIZE(wcsBuf), NULL, NULL, MISTSAFE_STRING_FLAGS, L"%lu", dwSuffix)) ||
  121. !aubsTmp.append(bstrItemName) ||
  122. !aubsTmp.append(L"_") ||
  123. !aubsTmp.append(wcsBuf))
  124. {
  125. DEBUGMSG("OUT OF MEMORY");
  126. hr = E_OUTOFMEMORY;
  127. goto done;
  128. }
  129. if (FAILED(hr = SetAttribute(pIdentity, KEY_NAME, aubsTmp)))
  130. {
  131. DEBUGMSG("Fail to set attribute with error %#lx", hr);
  132. goto done;
  133. }
  134. done:
  135. SafeFreeBSTR(bstrItemName);
  136. return hr;
  137. }
  138. BSTR GetPattern(IN LPCSTR szFieldName)
  139. {
  140. if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[0]))
  141. {
  142. return AUCatalog::bstrItemIDPattern;
  143. }
  144. else
  145. if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[1]))
  146. {
  147. return AUCatalog::bstrProviderNamePattern;
  148. }
  149. else
  150. if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[2]))
  151. {
  152. return AUCatalog::bstrTitlePattern;
  153. }
  154. else
  155. if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[3]))
  156. {
  157. return AUCatalog::bstrDescPattern;
  158. }
  159. else
  160. if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[4]))
  161. {
  162. return AUCatalog::bstrRTFUrlPattern;
  163. }
  164. else
  165. if (0 == _stricmp(szFieldName, AUCatalogItem::m_pFieldNames[5]))
  166. {
  167. return AUCatalog::bstrEulaUrlPattern;
  168. }
  169. else
  170. {
  171. return NULL;
  172. }
  173. }
  174. BOOL IsPersistedHiddenItem(IN BSTR bstrItemID, IN AUCatalogItemList & hiddenItemList)
  175. {
  176. BOOL fRet = (hiddenItemList.Contains(bstrItemID) >=0);
  177. DEBUGMSG("%S is %s hidden item ", bstrItemID, fRet? "" : "NOT");
  178. return fRet;
  179. }
  180. BOOL CItemDetails::Init(IN BSTR bsItemDetails)
  181. {
  182. BOOL fRet = TRUE;
  183. if (FAILED(CoCreateInstance(__uuidof(DOMDocument), NULL, CLSCTX_INPROC_SERVER, __uuidof( IXMLDOMDocument), (void**)&m_pxml)))
  184. {
  185. DEBUGMSG("CItemDetails::Init() fail to create XML document");
  186. fRet = FALSE;
  187. goto end;
  188. }
  189. if (FAILED(m_pxml->put_async(VARIANT_FALSE))
  190. ||FAILED(m_pxml->put_resolveExternals(VARIANT_FALSE))
  191. || FAILED(m_pxml->put_validateOnParse(VARIANT_FALSE)))
  192. {
  193. fRet = FALSE;
  194. goto end;
  195. }
  196. VARIANT_BOOL fOk;
  197. if (S_OK != m_pxml->loadXML(bsItemDetails, &fOk))
  198. {
  199. DEBUGMSG("CItemDetails::Init() fail to load XML");
  200. fRet = FALSE;
  201. }
  202. end:
  203. if (!fRet)
  204. {
  205. SafeReleaseNULL(m_pxml);
  206. }
  207. return fRet;
  208. }
  209. //should be callable event without Init() called first
  210. void CItemDetails::Uninit()
  211. {
  212. SafeRelease(m_pxml);
  213. }
  214. HRESULT CItemDetails::GetItemIdentities(IN BSTR bstrItemId, OUT IXMLDOMNodeList ** ppIdentityNodeList)
  215. {
  216. CAU_BSTR aubsPattern;
  217. HRESULT hr = S_OK ;
  218. // DEBUGMSG("CItemDetails::getIdentityNode() starts");
  219. *ppIdentityNodeList = NULL;
  220. if (!aubsPattern.append(L"/catalog/provider/item/identity[@itemID=\"") || !aubsPattern.append(bstrItemId) || !aubsPattern.append(L"\"]"))
  221. {
  222. DEBUGMSG("failed to create pattern string");
  223. hr = E_OUTOFMEMORY;
  224. goto done;
  225. }
  226. if (FAILED(hr = m_pxml->selectNodes(aubsPattern, ppIdentityNodeList)))
  227. {
  228. DEBUGMSG(" failed to find identityNode %#lx", hr);
  229. goto done;
  230. }
  231. done:
  232. // DEBUGMSG("CItemDetails::getIdentityNode() done");
  233. return hr;
  234. }
  235. ////////////////////////////////////////////////////////////////////////////
  236. // delete all items with ITEMID=bstrItemId
  237. ///////////////////////////////////////////////////////////////////////////
  238. HRESULT CItemDetails::DeleteItem(IN BSTR bstrItemId)
  239. {
  240. HRESULT hr = E_FAIL;
  241. IXMLDOMNode *pItemNode = NULL;
  242. IXMLDOMNode *pProviderNode = NULL;
  243. IXMLDOMNode *pCatalogNode = NULL;
  244. while (NULL != ( pItemNode = getItemNode(bstrItemId)))
  245. {
  246. if (FAILED(hr = pItemNode->get_parentNode(&pProviderNode)) || NULL == pProviderNode)
  247. {
  248. DEBUGMSG(" fail to get provider node %#lx", hr);
  249. goto done;
  250. }
  251. if (FAILED(hr = pProviderNode->removeChild(pItemNode, NULL)))
  252. {
  253. DEBUGMSG(" fail to remove item node with error %#lx", hr);
  254. goto done;
  255. }
  256. // DEBUGMSG("one item removed");
  257. pItemNode ->Release();
  258. pItemNode = NULL;
  259. if (S_FALSE == (hr =pProviderNode->selectSingleNode(KEY_ITEM, &pItemNode)))
  260. {
  261. //provider had no children
  262. if (FAILED(hr = pProviderNode->get_parentNode(&pCatalogNode)) || NULL == pCatalogNode)
  263. {
  264. DEBUGMSG(" fail to get catalog node %#lx", hr);
  265. goto done;
  266. }
  267. if (FAILED(hr = pCatalogNode->removeChild(pProviderNode, NULL)))
  268. {
  269. DEBUGMSG(" fail to remove provider node with error %#lx", hr);
  270. goto done;
  271. }
  272. // DEBUGMSG("one provider removed");
  273. }
  274. SafeReleaseNULL(pItemNode);
  275. SafeReleaseNULL(pProviderNode);
  276. SafeReleaseNULL(pCatalogNode);
  277. }
  278. done:
  279. SafeRelease(pItemNode);
  280. SafeRelease(pProviderNode);
  281. SafeRelease(pCatalogNode);
  282. return hr;
  283. }
  284. HRESULT CItemDetails::GetXML(BSTR *pbstrxml)
  285. {
  286. return m_pxml->get_xml(pbstrxml);
  287. }
  288. IXMLDOMNode * CItemDetails::getIdentityNode(IN BSTR bstrItemId)
  289. {
  290. IXMLDOMNode * pIdentityNode = NULL ;
  291. CAU_BSTR aubsPattern;
  292. HRESULT hr ;
  293. // DEBUGMSG("CItemDetails::getIdentityNode() starts");
  294. if (!aubsPattern.append(L"/catalog/provider/item/identity[@itemID=\"") || !aubsPattern.append(bstrItemId) || !aubsPattern.append(L"\"]"))
  295. {
  296. DEBUGMSG("failed to create pattern string");
  297. goto done;
  298. }
  299. if (FAILED(hr = m_pxml->selectSingleNode(aubsPattern, &pIdentityNode)))
  300. {
  301. DEBUGMSG(" failed to find identityNode %#lx", hr);
  302. goto done;
  303. }
  304. if (NULL == pIdentityNode)
  305. {
  306. goto done;
  307. }
  308. done:
  309. // DEBUGMSG("CItemDetails::getIdentityNode() done");
  310. return pIdentityNode;
  311. }
  312. /////////////////////////////////////////////////////////
  313. // caller should make sure item bstrItemId exists in itemdetails
  314. ////////////////////////////////////////////////////////
  315. BOOL CItemDetails::IsVisible(IN BSTR bstrItemId)
  316. {
  317. IXMLDOMNode * pItemNode = getItemNode(bstrItemId);
  318. IXMLDOMNode *pDescriptionNode = NULL;
  319. LONG lRet = 0;
  320. HRESULT hr ;
  321. // DEBUGMSG("IsVisible() starts");
  322. //fixcode: really should return error instead of bogus TRUE
  323. if (NULL == pItemNode )
  324. {
  325. DEBUGMSG("fail to find node or fail to create string");
  326. goto done;
  327. }
  328. if (FAILED(hr = pItemNode->selectSingleNode(KEY_DESCRIPTION, &pDescriptionNode)) || NULL == pDescriptionNode)
  329. {
  330. DEBUGMSG("Fail to select node %S with error %#lx", KEY_DESCRIPTION, hr);
  331. goto done;
  332. }
  333. if (FAILED(hr = GetAttribute(pDescriptionNode, KEY_HIDDEN, &lRet)))
  334. {
  335. DEBUGMSG("Fail to get attribute %S with error %#lx", KEY_HIDDEN, hr);
  336. goto done;
  337. }
  338. // DEBUGMSG("Hidden attribute is %d for item %S", lRet, bstrItemId);
  339. done:
  340. SafeRelease(pDescriptionNode);
  341. SafeRelease(pItemNode);
  342. // DEBUGMSG("IsVisible() return %s for %S", (0 == lRet) ? "true" : "false", bstrItemId);
  343. return 0 == lRet;
  344. }
  345. IXMLDOMNode * CItemDetails::getItemNode(IN BSTR bsItemId)
  346. {
  347. IXMLDOMNode * pIdentityNode = getIdentityNode(bsItemId);
  348. IXMLDOMNode * pItemNode = NULL;
  349. HRESULT hr;
  350. //DEBUGMSG("CItemDetails::getItemNode() starts");
  351. if (NULL == pIdentityNode)
  352. {
  353. goto done;
  354. }
  355. if (FAILED(hr = pIdentityNode->get_parentNode(&pItemNode)) || NULL == pItemNode)
  356. {
  357. DEBUGMSG(" fail to get item node %#lx", hr);
  358. goto done;
  359. }
  360. done:
  361. SafeRelease(pIdentityNode);
  362. //DEBUGMSG("CItemDetails::getItemNode() ends");
  363. return pItemNode;
  364. }
  365. HRESULT CItemDetails::CloneIdentityNode(IN BSTR bsItemId, IN IXMLDOMDocument *pDesXml, OUT IXMLDOMNode ** ppDesNode)
  366. {
  367. IXMLDOMNode * pIdentityNode ;
  368. HRESULT hr = E_FAIL;
  369. // DEBUGMSG("CItemDetails::CloneIdentityNode() starts");
  370. *ppDesNode = NULL;
  371. if (NULL == (pIdentityNode = getIdentityNode(bsItemId)))
  372. {
  373. goto done;
  374. }
  375. if (FAILED(hr = CopyNode(pIdentityNode, pDesXml, ppDesNode)))
  376. {
  377. DEBUGMSG("CItemDetails::CloneIdentityNode() failed to clone identityNode %#lx", hr);
  378. }
  379. done:
  380. SafeRelease(pIdentityNode);
  381. // DEBUGMSG("CItemDetails::CloneIdentityNode() ends");
  382. return hr;
  383. }
  384. HRESULT CItemDetails::CloneDescriptionNode(IN BSTR bsItemId, IN IXMLDOMDocument *pDesXml, OUT IXMLDOMNode **ppDesNode)
  385. {
  386. IXMLDOMNode * pItemNode = getItemNode(bsItemId);
  387. IXMLDOMNode * pDescriptionNode = NULL;
  388. HRESULT hr = E_FAIL;
  389. *ppDesNode = NULL;
  390. if (NULL == pItemNode)
  391. {
  392. goto done;
  393. }
  394. if (!FindNode(pItemNode, KEY_DESCRIPTION, &pDescriptionNode))
  395. {
  396. DEBUGMSG("CItemDetails::CloneDescriptionNode() fail to get description node");
  397. goto done;
  398. }
  399. if (FAILED(hr = CopyNode(pDescriptionNode, pDesXml, ppDesNode)))
  400. {
  401. DEBUGMSG("CItemDetails::CloneDescriptionNode() fail to clone node %#lx", hr);
  402. }
  403. done:
  404. SafeRelease(pItemNode);
  405. SafeRelease(pDescriptionNode);
  406. return hr;
  407. }
  408. HRESULT CItemDetails::ClonePlatformNode(IN BSTR bsItemId, IN IXMLDOMDocument *pDesXml, OUT IXMLDOMNode **ppDesNode)
  409. {
  410. IXMLDOMNode * pItemNode = getItemNode(bsItemId);
  411. IXMLDOMNode * pPlatformNode = NULL;
  412. HRESULT hr = E_FAIL;
  413. *ppDesNode = NULL;
  414. if (NULL == pItemNode)
  415. {
  416. goto done;
  417. }
  418. if (!FindNode(pItemNode, KEY_PLATFORM, &pPlatformNode))
  419. {
  420. DEBUGMSG("CItemDetails::ClonePlatformNode() fail to get platform node");
  421. goto done;
  422. }
  423. if (FAILED(hr = CopyNode(pPlatformNode, pDesXml, ppDesNode)))
  424. {
  425. DEBUGMSG("CItemDetails::ClonePlatformNode() fail to clone node %#lx", hr);
  426. }
  427. done:
  428. SafeRelease(pItemNode);
  429. SafeRelease(pPlatformNode);
  430. return hr;
  431. }
  432. /////////////////////////////////////////////////////////////////////////////////////////
  433. // retrieve cab names associated with an item identified by bsitemid
  434. // called should free ppCabNames allocated in the function
  435. // *pCabsNum contains number of cab names returned
  436. ////////////////////////////////////////////////////////////////////////////////////////
  437. HRESULT CItemDetails::GetCabNames(IN BSTR bsItemId, OUT BSTR ** ppCRCCabNames, OUT BSTR **ppRealCabNames, OUT BSTR **ppCabChecksums, OUT UINT *pCabsNum)
  438. {
  439. IXMLDOMNode * pItemNode = getItemNode(bsItemId);
  440. IXMLDOMNodeList *pCodeBaseNodes = NULL;
  441. BSTR * pCRCCabNames = NULL;
  442. BSTR * pRealCabNames = NULL;
  443. BSTR * pCabChecksums = NULL;
  444. UINT uCabsNum = 0;
  445. CAU_BSTR aubsCodeBase;
  446. HRESULT hr = E_FAIL;
  447. //DEBUGMSG("CItemDetails::GetCabNames() starts");
  448. *ppRealCabNames = *ppCRCCabNames = *ppCabChecksums = NULL;
  449. *pCabsNum = 0;
  450. if (!aubsCodeBase.append(L"installation/codeBase"))
  451. {
  452. DEBUGMSG("fail to create aubs");
  453. goto done;
  454. }
  455. if (NULL == pItemNode)
  456. {
  457. goto done;
  458. }
  459. if (FAILED(hr = pItemNode->selectNodes(aubsCodeBase, &pCodeBaseNodes)) || NULL == pCodeBaseNodes)
  460. {
  461. DEBUGMSG("Fail to find codebase section");
  462. goto done;
  463. }
  464. if (FAILED(hr = pCodeBaseNodes->get_length((long *) &uCabsNum)))
  465. {
  466. DEBUGMSG("Fail to get number of code base nodes with error %#lx", hr);
  467. goto done;
  468. }
  469. pCRCCabNames = (BSTR*) malloc(uCabsNum * sizeof(*pCRCCabNames));
  470. pRealCabNames = (BSTR*) malloc(uCabsNum * sizeof(*pRealCabNames));
  471. pCabChecksums = (BSTR*) malloc(uCabsNum * sizeof(*pCabChecksums));
  472. if (NULL != pCRCCabNames)
  473. {
  474. ZeroMemory((PVOID)pCRCCabNames, uCabsNum * sizeof(*pCRCCabNames));
  475. }
  476. if (NULL != pRealCabNames)
  477. {
  478. ZeroMemory((PVOID)pRealCabNames, uCabsNum * sizeof(*pRealCabNames));
  479. }
  480. if (NULL != pCabChecksums)
  481. {
  482. ZeroMemory((PVOID)pCabChecksums, uCabsNum * sizeof(*pCabChecksums));
  483. }
  484. if (NULL == pCRCCabNames || NULL == pRealCabNames || NULL == pCabChecksums)
  485. {
  486. DEBUGMSG("Fail to alloc memory for CRCCabsNames or RealCabNames");
  487. hr = E_OUTOFMEMORY;
  488. goto done;
  489. }
  490. for (UINT i = 0; i < uCabsNum ; i++)
  491. {
  492. IXMLDOMNode *pCodeBaseNode;
  493. if (S_OK != (hr = pCodeBaseNodes->get_item(i, &pCodeBaseNode)))
  494. {
  495. DEBUGMSG("Fail to get codebase %d", i);
  496. hr = FAILED(hr) ? hr : E_FAIL;
  497. goto done;
  498. }
  499. if (FAILED(hr = GetAttribute(pCodeBaseNode, KEY_HREF, &(pCRCCabNames[i]))))
  500. {
  501. DEBUGMSG("Fail to get attribute %S", KEY_HREF);
  502. pCodeBaseNode->Release();
  503. goto done;
  504. }
  505. if (FAILED(hr = GetAttribute(pCodeBaseNode, KEY_NAME, &(pRealCabNames[i]))))
  506. {
  507. DEBUGMSG("Fail to get attribute %S", KEY_NAME);
  508. pCodeBaseNode->Release();
  509. goto done;
  510. }
  511. //Since CRC is optional, it might not exist for this cab
  512. GetAttribute(pCodeBaseNode, KEY_CRC, &(pCabChecksums[i]));
  513. pCodeBaseNode->Release();
  514. }
  515. *ppCRCCabNames = pCRCCabNames;
  516. *ppRealCabNames = pRealCabNames;
  517. *ppCabChecksums = pCabChecksums;
  518. *pCabsNum = uCabsNum;
  519. done:
  520. SafeRelease(pCodeBaseNodes);
  521. SafeRelease(pItemNode);
  522. if (FAILED(hr))
  523. {
  524. if (NULL != pCRCCabNames)
  525. {
  526. for (UINT j = 0; j < uCabsNum; j++)
  527. {
  528. SafeFreeBSTR(pCRCCabNames[j]);
  529. }
  530. free(pCRCCabNames);
  531. }
  532. if (NULL != pRealCabNames)
  533. {
  534. for (UINT j = 0; j < uCabsNum; j++)
  535. {
  536. SafeFreeBSTR(pRealCabNames[j]);
  537. }
  538. free(pRealCabNames);
  539. }
  540. if (NULL != pCabChecksums)
  541. {
  542. for (UINT j = 0; j < uCabsNum; j++)
  543. {
  544. SafeFreeBSTR(pCabChecksums[j]);
  545. }
  546. free(pCabChecksums);
  547. }
  548. }
  549. //DEBUGMSG("CItemDetails::GetCabNames() ends");
  550. return hr;
  551. }
  552. /////////////////////////////////////////////////////////////////////////////////////////
  553. // retrieve the CRC for the rtf file for the specified item
  554. // caller should free pRTFCRC allocated in the function
  555. ////////////////////////////////////////////////////////////////////////////////////////
  556. HRESULT CItemDetails::GetRTFCRC(BSTR bstrItemId, BSTR *pRTFCRC)
  557. {
  558. IXMLDOMNode * pItemNode = getItemNode(bstrItemId);
  559. IXMLDOMNode *pDetailsNode = NULL;
  560. CAU_BSTR aubsDetails;
  561. HRESULT hr = E_FAIL;
  562. AUASSERT(NULL != pRTFCRC);
  563. *pRTFCRC = NULL;
  564. if( NULL == pItemNode ||
  565. !aubsDetails.append(L"description/descriptionText/details"))
  566. {
  567. goto done;
  568. }
  569. if (FAILED(hr = pItemNode->selectSingleNode(aubsDetails, &pDetailsNode)) ||
  570. NULL == pDetailsNode)
  571. {
  572. DEBUGMSG("Fail to find details section");
  573. goto done;
  574. }
  575. if (FAILED(hr = GetAttribute(pDetailsNode, KEY_CRC, pRTFCRC)) ||
  576. hr == S_FALSE) //GetAttribute returns S_FALSE if the attribute does not exist for the node
  577. {
  578. DEBUGMSG("Fail to get attribute RTF crc, hr is %x", hr);
  579. hr = (hr == S_FALSE) ? E_FAIL : hr;
  580. }
  581. done:
  582. if(FAILED(hr))
  583. {
  584. SafeFreeBSTRNULL(*pRTFCRC);
  585. }
  586. SafeRelease(pItemNode);
  587. SafeRelease(pDetailsNode);
  588. return hr;
  589. }
  590. BSTR CItemDetails::GetItemDownloadPath(IN BSTR bstrItemId)
  591. {
  592. // USES_CONVERSION; only needed for ansi version
  593. BSTR bstrRet = NULL;
  594. IXMLDOMNode * pIdentityNode= NULL;
  595. // DEBUGMSG("CItemDetails::GetItemDownloadPath starts");
  596. if (NULL == (pIdentityNode = getIdentityNode(bstrItemId)))
  597. {
  598. goto done;
  599. }
  600. BSTR bstrdownloadPath;
  601. if (FAILED(UtilGetUniqIdentityStr(pIdentityNode, &bstrdownloadPath, 0)))
  602. {
  603. DEBUGMSG("GetItemDownloadPath() fail to get unique identity string");
  604. goto done;
  605. }
  606. TCHAR tszPath[MAX_PATH];
  607. if (SUCCEEDED(GetCabsDownloadPath(tszPath, ARRAYSIZE(tszPath))) &&
  608. SUCCEEDED(StringCchCatEx(tszPath, ARRAYSIZE(tszPath), _T("\\"), NULL, NULL, MISTSAFE_STRING_FLAGS)) &&
  609. SUCCEEDED(StringCchCatEx(tszPath, ARRAYSIZE(tszPath), W2T(bstrdownloadPath), NULL, NULL, MISTSAFE_STRING_FLAGS)))
  610. {
  611. bstrRet = SysAllocString(T2W(tszPath));
  612. }
  613. SysFreeString(bstrdownloadPath);
  614. done:
  615. SafeRelease(pIdentityNode);
  616. /// DEBUGMSG("CItemDetails::GetItemDownloadPath() got %S", bstrRet);
  617. if (NULL != bstrRet && !EnsureDirExists(W2T(bstrRet)))
  618. {
  619. DEBUGMSG("CItemDetails::GetItemDownloadPath() fail to create directory %S", bstrRet);
  620. SysFreeString(bstrRet);
  621. bstrRet = NULL;
  622. }
  623. return bstrRet;
  624. }
  625. HRESULT CItemDetails::GetItemIds(OUT long *plItemNum, OUT BSTR ** ppbstrItemIds)
  626. {
  627. IXMLDOMNodeList *pItemIdsNodeList = NULL;
  628. HRESULT hr = E_FAIL;
  629. // DEBUGMSG("CItemDetails::GetItemIds() starts");
  630. *ppbstrItemIds = NULL;
  631. *plItemNum = 0;
  632. if (FAILED(hr = m_pxml->selectNodes(AUCatalog::bstrItemIdsPattern, &pItemIdsNodeList)))
  633. {
  634. DEBUGMSG(" fail to find item id with error %#lx", hr);
  635. goto done;
  636. }
  637. if (FAILED(hr = pItemIdsNodeList->get_length(plItemNum)))
  638. {
  639. DEBUGMSG("Fail to get itemids number with error %#lx", hr);
  640. goto done;
  641. }
  642. *ppbstrItemIds = (BSTR *) malloc((*plItemNum) * sizeof(**ppbstrItemIds));
  643. if (NULL == *ppbstrItemIds)
  644. {
  645. DEBUGMSG("Fail to allocate memory for item ids");
  646. hr = E_OUTOFMEMORY;
  647. goto done;
  648. }
  649. ZeroMemory(*ppbstrItemIds, (*plItemNum) * sizeof(**ppbstrItemIds));
  650. for (int i = 0; i < *plItemNum; i++)
  651. {
  652. IXMLDOMNode *pItemIdNode = NULL;
  653. if (FAILED(hr = pItemIdsNodeList->get_item(i, &pItemIdNode)) || NULL == pItemIdNode)
  654. {
  655. DEBUGMSG("Fail to get item id node with error %#lx", hr);
  656. hr = FAILED(hr) ? hr : E_FAIL;
  657. goto done;
  658. }
  659. if (FAILED(hr = pItemIdNode->get_text(&((*ppbstrItemIds)[i]))) || NULL == (*ppbstrItemIds)[i])
  660. {
  661. DEBUGMSG("Fail to get item id no. %d with error %#lx", i+1, hr);
  662. pItemIdNode->Release();
  663. hr = FAILED(hr) ? hr : E_FAIL;
  664. goto done;
  665. }
  666. pItemIdNode->Release();
  667. // DEBUGMSG(" got #%d item id %S", i+1, (*ppbstrItemIds)[i]);
  668. }
  669. done:
  670. SafeRelease(pItemIdsNodeList);
  671. if (FAILED(hr))
  672. {
  673. if (NULL != *ppbstrItemIds)
  674. {
  675. for (int j = 0; j < *plItemNum; j++)
  676. {
  677. SafeFreeBSTR((*ppbstrItemIds)[j]);
  678. }
  679. SafeFree(*ppbstrItemIds);
  680. }
  681. *plItemNum = 0;
  682. *ppbstrItemIds = NULL;
  683. }
  684. else
  685. {
  686. DEBUGMSG(" got %d item ids", *plItemNum);
  687. }
  688. // DEBUGMSG("CItemDetails::GetItemIds() ends");
  689. return hr;
  690. }
  691. HRESULT CItemDetails::GetItemInfo(IN LPCSTR szFieldName, IN const BSTR bstrItemId, OUT BSTR * pbstrItemInfo)
  692. {
  693. HRESULT hr = E_FAIL;
  694. IXMLDOMNode * pItemNode = getItemNode(bstrItemId);
  695. IXMLDOMNode * pProviderNode = NULL;
  696. IXMLDOMNode * pParentNode;
  697. IXMLDOMNode *pItemInfoNode = NULL;
  698. // DEBUGMSG("GetItemInfo() for %s starts", szFieldName);
  699. *pbstrItemInfo = NULL;
  700. if (NULL == pItemNode)
  701. {
  702. DEBUGMSG("Fail to get item node for %S", bstrItemId);
  703. goto done;
  704. }
  705. //special case provider name
  706. if (0 == _strcmpi(szFieldName, AUCatalogItem::m_pFieldNames[1]))
  707. {
  708. if (FAILED(hr = pItemNode->get_parentNode(&pProviderNode)) || NULL == pProviderNode)
  709. {
  710. DEBUGMSG("Fail to get provider node");
  711. hr = E_FAIL;
  712. goto done;
  713. }
  714. pParentNode = pProviderNode;
  715. }
  716. else
  717. {
  718. pParentNode = pItemNode;
  719. }
  720. if (FAILED(hr = FindSingleDOMNode(pParentNode, GetPattern(szFieldName), &pItemInfoNode)))
  721. {
  722. DEBUGMSG("Fail to get field %s for item %S", szFieldName, bstrItemId);
  723. goto done;
  724. }
  725. if (FAILED(hr = pItemInfoNode->get_text(pbstrItemInfo))) //NULL content is fine
  726. {
  727. DEBUGMSG("Fail to get value from title node with error %#lx", hr);
  728. goto done;
  729. }
  730. // DEBUGMSG(" item info %s is %S", szFieldName, *pbstrItemInfo);
  731. done:
  732. SafeRelease(pItemNode);
  733. SafeRelease(pItemInfoNode);
  734. SafeRelease(pProviderNode);
  735. if (FAILED(hr))
  736. {
  737. SafeFreeBSTRNULL(*pbstrItemInfo);
  738. }
  739. // DEBUGMSG("GetItemInfo() for %s ends", szFieldName);
  740. return hr;
  741. }
  742. //////////////////////////////////////////////////////////////////////////////////
  743. //find first exclusive item that is NOT hidden and visible
  744. //return S_OK if found one
  745. //return S_FALSE if found none
  746. //return E_FAIL if error occurs
  747. HRESULT CItemDetails::FindFirstExclusiveItem(OUT BSTR *pbstrItemId, IN AUCatalogItemList & hiddenItemList)
  748. {
  749. IXMLDOMNodeList *pExclusiveItemNodes = NULL;
  750. HRESULT hr = E_FAIL;
  751. BOOL fFound = FALSE;
  752. DEBUGMSG("CItemDetails::FindFirstExclusiveItem() starts");
  753. *pbstrItemId = NULL;
  754. pExclusiveItemNodes = FindDOMNodeList(m_pxml, AUCatalog::bstrExclusiveItemPattern);
  755. if (NULL == pExclusiveItemNodes)
  756. {
  757. DEBUGMSG("No exclusive item found");
  758. hr = S_FALSE;
  759. goto done;
  760. }
  761. long lNum;
  762. if (FAILED(hr = pExclusiveItemNodes->get_length(&lNum)))
  763. {
  764. DEBUGMSG("Fail to get exclusive item nodes number with error %#lx", hr);
  765. goto done;
  766. }
  767. for (long l = 0; l < lNum; l++)
  768. {
  769. IXMLDOMNode *pExclusiveItemNode = NULL;
  770. if (S_OK != (hr = pExclusiveItemNodes->get_item(l, &pExclusiveItemNode)))
  771. {
  772. DEBUGMSG("Fail to get item with error %#lx", hr);
  773. hr = FAILED(hr) ? hr : E_FAIL;
  774. goto done;
  775. }
  776. if (!FindNodeValue(pExclusiveItemNode, GetPattern(AUCatalogItem::m_pFieldNames[0]), pbstrItemId))
  777. {
  778. hr = E_FAIL;
  779. }
  780. pExclusiveItemNode->Release();
  781. if (FAILED(hr))
  782. {
  783. DEBUGMSG("Fail to get item id text with error %#lx", hr);
  784. goto done;
  785. }
  786. if (!IsPersistedHiddenItem(*pbstrItemId, hiddenItemList) && IsVisible(*pbstrItemId))
  787. {
  788. fFound = TRUE;
  789. break;
  790. }
  791. SysFreeString(*pbstrItemId);
  792. *pbstrItemId = NULL;
  793. }
  794. if (fFound)
  795. {
  796. DEBUGMSG("Find first exclusive item %S", *pbstrItemId);
  797. hr = S_OK;
  798. }
  799. else
  800. {
  801. DEBUGMSG("No unhidden and visible exclusive item found");
  802. hr = S_FALSE;
  803. }
  804. done:
  805. SafeRelease(pExclusiveItemNodes);
  806. if (S_OK != hr)
  807. {
  808. SafeFreeBSTRNULL(*pbstrItemId);
  809. }
  810. DEBUGMSG("CItemDetails::FindFirstExclusiveItem() ends");
  811. return hr;
  812. }
  813. //////////////////////////////////////////////////////////////////////////////
  814. // populate m_DependentItems of each item in the lsit with direct dependency
  815. // Also check the self containment of depending items with in the list, i.e. all the depending items should
  816. // also be in the list. If not, the dependency will not be recorded.
  817. // return S_OK : if item found and dependency built if any
  818. // E_XXXX: if error
  819. //////////////////////////////////////////////////////////////////////////////
  820. HRESULT CItemDetails::BuildDirectDependency(IN OUT AUCatalogItemList &itemlist)
  821. {
  822. HRESULT hr = S_OK;
  823. CAU_BSTR aubsDependentItemID;
  824. // DEBUGMSG("CItemDetails::BuildDirectDependency starts");
  825. if (!aubsDependentItemID.append(L"dependencies/identity/@itemID"))
  826. {
  827. hr = E_OUTOFMEMORY;
  828. goto done;
  829. }
  830. for (UINT i = 0; i < itemlist.Count(); i++)
  831. {
  832. IXMLDOMNodeList *pItemIDNodes = NULL;
  833. IXMLDOMNode *pItemNode = NULL;
  834. if (NULL == (pItemNode = getItemNode(itemlist[i].bstrID())))
  835. {
  836. // DEBUGMSG("Warning: item %S not found in the list", itemlist[i].bstrID()); //legitimate error
  837. continue;
  838. }
  839. if (NULL == (pItemIDNodes = FindDOMNodeList(pItemNode, aubsDependentItemID)))
  840. {
  841. // DEBUGMSG ("No dependency found for item %S", itemlist[i].bstrID());
  842. pItemNode->Release();
  843. continue;
  844. }
  845. long lNumOfDependency;
  846. if (FAILED(hr = pItemIDNodes->get_length(&lNumOfDependency)))
  847. {
  848. DEBUGMSG("Fail to get item id node number with error %#lx", hr);
  849. pItemNode->Release();
  850. pItemIDNodes->Release();
  851. continue;
  852. }
  853. for (long l = 0; l < lNumOfDependency; l++)
  854. {
  855. IXMLDOMNode * pItemIDNode = NULL;
  856. if (S_OK == pItemIDNodes->get_item(l, &pItemIDNode))
  857. {
  858. BSTR bstrItemId = NULL;
  859. if (FAILED(hr = pItemIDNode->get_text(&bstrItemId)) || NULL == bstrItemId)
  860. {
  861. DEBUGMSG("Fail to get text for item id with error %#lx", hr);
  862. hr = FAILED(hr) ? hr : E_FAIL;
  863. pItemIDNode->Release();
  864. break;
  865. }
  866. pItemIDNode->Release();
  867. AUCatalogItem *pdependingItem = new AUCatalogItem;
  868. if (NULL == pdependingItem)
  869. {
  870. DEBUGMSG("Out of Memory. Fail to create new item");
  871. hr = E_OUTOFMEMORY;
  872. SafeFreeBSTR(bstrItemId);
  873. break;
  874. }
  875. if (NULL == bstrItemId)
  876. {//although schema does not require itemid, we do
  877. DEBUGMSG("Fail to find item id");
  878. hr = E_FAIL;
  879. delete pdependingItem;
  880. break;
  881. }
  882. INT index = itemlist.Contains(bstrItemId);
  883. if (index >= 0)
  884. {
  885. BSTR bstrTmp = SysAllocString(itemlist[i].bstrID());
  886. if (NULL == bstrTmp)
  887. {
  888. DEBUGMSG("Fail to allocate memory");
  889. SysFreeString(bstrItemId);
  890. delete pdependingItem;
  891. hr = E_OUTOFMEMORY;
  892. break;
  893. }
  894. pdependingItem->SetField(AUCatalogItem::m_pFieldNames[0], bstrTmp);
  895. if (!itemlist[index].m_DependingItems.Add(pdependingItem))
  896. {
  897. DEBUGMSG("fail to add depending item");
  898. SysFreeString(bstrItemId);
  899. delete pdependingItem;
  900. hr = E_OUTOFMEMORY;
  901. break;
  902. }
  903. else
  904. {
  905. DEBUGMSG("item %S depending on item %S. Dependency recorded", pdependingItem->bstrID(), itemlist[index].bstrID());
  906. }
  907. }
  908. else
  909. {
  910. DEBUGMSG("Warning: item %S depends on an item not in the list", itemlist[i].bstrID());
  911. delete pdependingItem;
  912. }
  913. SysFreeString(bstrItemId);
  914. }
  915. else
  916. {
  917. DEBUGMSG("Error: fail to get item id node");
  918. hr = E_FAIL;
  919. break;
  920. }
  921. }
  922. pItemNode->Release();
  923. pItemIDNodes->Release();
  924. }
  925. done:
  926. // DEBUGMSG("CItemDetails::BuildDirectDependency ends");
  927. if (FAILED(hr))
  928. {
  929. for (UINT i = 0; i < itemlist.Count(); i++)
  930. {
  931. itemlist[i].m_DependingItems.Clear();
  932. }
  933. }
  934. return hr;
  935. }
  936. ////////////////////////////////////////////////////////////////////////////
  937. // format of hidde.xml is
  938. // <hiddenitems version = #>
  939. // <item id = "...........">
  940. // ..............
  941. // <item id = "...........">
  942. // </hiddenitems>
  943. // return S_FALSE when no hidden items left in the xml file. The file will be deleted
  944. ///////////////////////////////////////////////////////////////////////////
  945. // TO be finished
  946. HRESULT PersistHiddenItems(IN AUCatalogItemList &itemlist, IN URLLOGACTIVITY activity)
  947. {
  948. // USES_CONVERSION;
  949. IXMLDOMDocument *pHiddenXml = NULL;
  950. IXMLDOMNode *pHiddenItemsNode = NULL;
  951. IXMLDOMElement *pelemITEM = NULL;
  952. TCHAR tszFullFileName[MAX_PATH];
  953. CAU_BSTR aubsFullFileName;
  954. CAU_BSTR aubsItemPattern;
  955. UINT uItemAdded = 0;
  956. HRESULT hr = S_OK;
  957. DEBUGMSG("PersistHiddenItems() starts");
  958. if (itemlist.GetNumUnselected() == 0)
  959. {
  960. DEBUGMSG("No hidden items to persist");
  961. goto done;
  962. }
  963. AUASSERT(_T('\0') != g_szWUDir[0]);
  964. if (FAILED(StringCchCopyEx(tszFullFileName, ARRAYSIZE(tszFullFileName), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  965. FAILED(StringCchCatEx(tszFullFileName, ARRAYSIZE(tszFullFileName), HIDDEN_ITEMS_FILE, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  966. !aubsFullFileName.append(T2W(tszFullFileName)) ||
  967. !aubsItemPattern.append(AUCatalog::bstrHiddenItems) ||
  968. !aubsItemPattern.append(L"/") ||!aubsItemPattern.append(AUCatalog::bstrTagITEM))
  969. {
  970. DEBUGMSG("Fail to create string ");
  971. hr = E_OUTOFMEMORY;
  972. goto done;
  973. }
  974. if (fFileExists(tszFullFileName))
  975. {
  976. DEBUGMSG("file %S exists. Add hidden items to it", tszFullFileName);
  977. if (FAILED(hr = LoadDocument(aubsFullFileName, &pHiddenXml, TRUE))) //offline
  978. {
  979. DEBUGMSG(" %S fail to load with error %#lx, delete it", aubsFullFileName, hr);
  980. AUDelFileOrDir(tszFullFileName);
  981. }
  982. }
  983. if (NULL == pHiddenXml)
  984. {
  985. if (FAILED(hr = LoadXMLDoc(AUCatalog::bstrTemplate, &pHiddenXml, TRUE))) //offline
  986. {
  987. DEBUGMSG("Fail to load template xml with error %#lx", hr);
  988. goto done;
  989. }
  990. }
  991. if (!FindNode(pHiddenXml, AUCatalog::bstrHiddenItems, &pHiddenItemsNode))
  992. {
  993. hr = E_FAIL;
  994. DEBUGMSG("Fail to find node %S", AUCatalog::bstrHiddenItems);
  995. goto done;
  996. }
  997. VARIANT varValueID;
  998. varValueID.vt = VT_BSTR;
  999. // write out item information
  1000. for ( DWORD index = 0; index < itemlist.Count(); index++ )
  1001. {
  1002. if (itemlist[index].fUnselected())
  1003. { //hide unselected items
  1004. varValueID.bstrVal = itemlist[index].bstrID();
  1005. if ( FAILED(hr = pHiddenXml->createElement(AUCatalog::bstrTagITEM, &pelemITEM)) ||
  1006. FAILED(hr = pelemITEM->setAttribute(AUCatalog::bstrAttrID, varValueID)) ||
  1007. FAILED(hr = pHiddenItemsNode->appendChild(pelemITEM, NULL)) )
  1008. {
  1009. DEBUGMSG("XML operation failure with error %#lx", hr);
  1010. }
  1011. else
  1012. {
  1013. // DEBUGMSG("item %S persisted", itemlist[index].bstrID());
  1014. uItemAdded++;
  1015. gPingStatus.PingDeclinedItem(FALSE, activity, W2T(varValueID.bstrVal));
  1016. }
  1017. SafeReleaseNULL(pelemITEM);
  1018. // DEBUGMSG("Item %S now hidden", itemlist[index].bstrID());
  1019. itemlist[index].SetStatusHidden();
  1020. }
  1021. }
  1022. if (0 == uItemAdded)
  1023. {
  1024. DEBUGMSG("no new hidden items need to be persisted");
  1025. hr = S_OK;
  1026. }
  1027. else
  1028. if (FAILED(hr= SaveDocument(pHiddenXml, aubsFullFileName)))
  1029. {
  1030. DEBUGMSG("Fail to save hidden xml %S with error %#lx", T2W(tszFullFileName), hr);
  1031. AUDelFileOrDir(tszFullFileName);
  1032. goto done;
  1033. }
  1034. done:
  1035. SafeRelease(pelemITEM);
  1036. SafeRelease(pHiddenItemsNode);
  1037. SafeRelease(pHiddenXml);
  1038. DEBUGMSG("PersistHiddenItems() ends with %d items added", uItemAdded);
  1039. return hr;
  1040. }
  1041. //////////////////////////////////////////////////////////////////////
  1042. // read hidden xml file if there is one
  1043. // and populate the hidden item list passed in
  1044. // return S_FALSE if there is no hidden items found
  1045. /////////////////////////////////////////////////////////////////////
  1046. HRESULT GetPersistedHiddenItems(AUCatalogItemList OUT & hiddenItemList)
  1047. {
  1048. HRESULT hr ;
  1049. IXMLDOMNodeList *pItemNodes = NULL;
  1050. IXMLDOMDocument *pHiddenXml = NULL;
  1051. CAU_BSTR aubsItemPattern;
  1052. DEBUGMSG("GetPersistedHiddenItems() starts");
  1053. TCHAR tszFullFileName[MAX_PATH];
  1054. CAU_BSTR aubsFullFileName;
  1055. AUASSERT(_T('\0') != g_szWUDir[0]);
  1056. if (FAILED(StringCchCopyEx(tszFullFileName, ARRAYSIZE(tszFullFileName), g_szWUDir, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  1057. FAILED(StringCchCatEx(tszFullFileName, ARRAYSIZE(tszFullFileName), HIDDEN_ITEMS_FILE, NULL, NULL, MISTSAFE_STRING_FLAGS)) ||
  1058. !aubsItemPattern.append(AUCatalog::bstrHiddenItems) ||
  1059. !aubsItemPattern.append(L"/") ||
  1060. !aubsItemPattern.append(AUCatalog::bstrTagITEM) ||
  1061. !aubsFullFileName.append(T2W(tszFullFileName)))
  1062. {
  1063. DEBUGMSG("fail to create string");
  1064. hr = E_OUTOFMEMORY;
  1065. goto done;
  1066. }
  1067. if (!fFileExists(W2T(aubsFullFileName)))
  1068. {
  1069. DEBUGMSG("No persisted item found");
  1070. hr = S_FALSE;
  1071. goto done;
  1072. }
  1073. if (FAILED(hr = LoadDocument(aubsFullFileName, &pHiddenXml, TRUE))) //offline
  1074. {
  1075. DEBUGMSG(" %S fail to load with error %#lx", aubsFullFileName, hr); //might be expected if file is not there
  1076. goto done;
  1077. }
  1078. pItemNodes = FindDOMNodeList(pHiddenXml, aubsItemPattern);
  1079. if (NULL == pItemNodes)
  1080. {
  1081. hr = S_FALSE;
  1082. DEBUGMSG("no persisted hidden items found using pattern %S", aubsItemPattern);
  1083. goto done;
  1084. }
  1085. long lItemNum;
  1086. if (FAILED(hr = pItemNodes->get_length(&lItemNum)))
  1087. {
  1088. DEBUGMSG("fail to get number of item nodes with error %#lx", hr);
  1089. goto done;
  1090. }
  1091. for (int i = 0; i < lItemNum; i++)
  1092. {
  1093. IXMLDOMNode *pItemNode = NULL;
  1094. BSTR bstrItemID = NULL;
  1095. if (S_OK != (hr = pItemNodes->get_item(i, &pItemNode)))
  1096. {
  1097. DEBUGMSG("Fail to get item %d", i);
  1098. hr = FAILED(hr) ? hr : E_FAIL;
  1099. goto done;
  1100. }
  1101. hr = GetAttribute(pItemNode, AUCatalog::bstrAttrID, &bstrItemID);
  1102. SafeRelease(pItemNode);
  1103. if (FAILED(hr))
  1104. {
  1105. goto done;
  1106. }
  1107. if (NULL != bstrItemID)
  1108. {
  1109. AUCatalogItem *pItem = new AUCatalogItem();
  1110. if (NULL == pItem)
  1111. {
  1112. DEBUGMSG("Fail to create new item");
  1113. SysFreeString(bstrItemID);
  1114. hr = E_OUTOFMEMORY;
  1115. goto done;
  1116. }
  1117. else
  1118. {
  1119. pItem->SetField(AUCatalogItem::m_pFieldNames[0], bstrItemID);
  1120. DEBUGMSG("Find one hidden item %S", bstrItemID);
  1121. if (!hiddenItemList.Add(pItem))
  1122. {
  1123. DEBUGMSG("OUT OF MEMORY: fail to add item");
  1124. hr = E_OUTOFMEMORY;
  1125. delete pItem;
  1126. goto done;
  1127. }
  1128. }
  1129. }
  1130. }
  1131. done:
  1132. SafeRelease(pItemNodes);
  1133. SafeRelease(pHiddenXml);
  1134. if (hr != S_OK)
  1135. {
  1136. hiddenItemList.Clear();
  1137. }
  1138. DEBUGMSG("GetPersistedHiddenItems() ends");
  1139. return hr;
  1140. }
  1141. //////////////////////////////////////////////////////////////////////////////////////////////////////
  1142. // given a details xml, extract all the items in it
  1143. // and populate the AU catalog item list passed in
  1144. // all the persisted hidden items will be excluded
  1145. // bstrDetails: IN details xml
  1146. // itemlist : IN/OUT receives items information
  1147. // fDriver: IN whether bstrDetails is for driver or non driver
  1148. // pfFoundExclusive: OUT TRUE if found exclusive item. In that case, only exclusive item will be returned
  1149. // return : TRUE if items got from the xml
  1150. // FALSE otherwise
  1151. /////////////////////////////////////////////////////////////////////////////////////////////////////
  1152. BOOL fExtractItemInfo(IN const BSTR bstrDetails, OUT AUCatalogItemList & itemList, OUT BOOL *pfFoundExclusive)
  1153. {
  1154. long lNumItems = 0;
  1155. BSTR *pbstrItemIds = NULL;
  1156. BOOL fRet = FALSE;
  1157. CItemDetails itemdetails;
  1158. BSTR bstrExclusiveItemId;
  1159. AUCatalogItemList hiddenItemList;
  1160. BOOL fHiddenItemsFound;
  1161. BOOL fItemIdsAllocated = FALSE;
  1162. HRESULT hr;
  1163. DEBUGMSG("fExtractItemInfo() starts");
  1164. *pfFoundExclusive = FALSE;
  1165. itemList.Clear();
  1166. if (!itemdetails.Init(bstrDetails))
  1167. {
  1168. DEBUGMSG("Fail to init itemdetails");
  1169. goto done;
  1170. }
  1171. if (FAILED(hr = GetPersistedHiddenItems(hiddenItemList)))
  1172. {
  1173. DEBUGMSG("no persisted hidden items loaded with error %#lx", hr);
  1174. }
  1175. if (*pfFoundExclusive = (S_OK == itemdetails.FindFirstExclusiveItem(&bstrExclusiveItemId, hiddenItemList)))
  1176. {
  1177. DEBUGMSG("Found exclusive item, add it");
  1178. lNumItems = 1;
  1179. pbstrItemIds = &bstrExclusiveItemId;
  1180. }
  1181. else
  1182. {
  1183. if (FAILED(hr = itemdetails.GetItemIds(&lNumItems, &pbstrItemIds)))
  1184. {
  1185. DEBUGMSG("Fail to get item ids with error %#lx", hr);
  1186. goto done;
  1187. }
  1188. else
  1189. {
  1190. fItemIdsAllocated = TRUE;
  1191. }
  1192. }
  1193. for (long i = 0; i < lNumItems; i++)
  1194. {
  1195. if (itemList.Contains(pbstrItemIds[i]) >=0)
  1196. { //duplicate item id found
  1197. continue;
  1198. }
  1199. AUCatalogItem *pitem = new AUCatalogItem();
  1200. if (NULL == pitem)
  1201. {
  1202. DEBUGMSG("Out of memory and fail to create new item.");
  1203. goto done;
  1204. }
  1205. BSTR bstrTmp = SysAllocString(pbstrItemIds[i]);
  1206. if (NULL == bstrTmp)
  1207. {
  1208. DEBUGMSG("Out of memory ");
  1209. delete pitem;
  1210. goto done;
  1211. }
  1212. pitem->SetField(AUCatalogItem::m_pFieldNames[0], bstrTmp);
  1213. //even if one or more following item information is missing, add item anyway
  1214. for (int j = 1; j < ARRAYSIZE(AUCatalogItem::m_pFieldNames); j++)
  1215. {
  1216. BSTR bstrItemInfo = NULL;
  1217. if (FAILED(itemdetails.GetItemInfo(AUCatalogItem::m_pFieldNames[j], pbstrItemIds[i], &bstrItemInfo)))
  1218. {
  1219. continue;
  1220. }
  1221. pitem->SetField(AUCatalogItem::m_pFieldNames[j], bstrItemInfo);
  1222. }
  1223. if ( IsPersistedHiddenItem(pbstrItemIds[i], hiddenItemList) ||
  1224. !itemdetails.IsVisible(pbstrItemIds[i]))
  1225. { //don't show non visible and hidden items
  1226. pitem->SetStatusHidden();
  1227. }
  1228. if (!itemList.Add(pitem))
  1229. {
  1230. DEBUGMSG("OUT OF MEMORY: fail to add new item");
  1231. delete pitem;
  1232. goto done;
  1233. }
  1234. }
  1235. fRet = TRUE;
  1236. done:
  1237. itemdetails.Uninit();
  1238. if (!fRet)
  1239. {
  1240. itemList.Clear();
  1241. }
  1242. for (int k = 0; k < lNumItems; k++)
  1243. {
  1244. SafeFreeBSTR(pbstrItemIds[k]);
  1245. }
  1246. if (fItemIdsAllocated)
  1247. {
  1248. SafeFree(pbstrItemIds);
  1249. }
  1250. DEBUGMSG("fExtractItemInfo() ends");
  1251. return fRet;
  1252. }
  1253. IXMLDOMNode * createDownloadItemStatusNode(IN IXMLDOMDocument * pxml, IN AUCatalogItem &Item, IN const BSTR bsInstallation, OUT IXMLDOMNode **ppIdentity)
  1254. {
  1255. IXMLDOMElement * pitemStatus = NULL;
  1256. BOOL fError = FALSE; //no error occurs
  1257. IXMLDOMNode * pdescription = NULL;
  1258. IXMLDOMNode * pPlatform = NULL;
  1259. IXMLDOMElement *pdownloadStatus = NULL;
  1260. IXMLDOMElement *pdownloadPath = NULL;
  1261. CItemDetails itemDetails;
  1262. BSTR bsItemId, bsdownloadPath = NULL;
  1263. VARIANT vComplete;
  1264. IXMLDOMNode ** ItemStatusChildren[] = {ppIdentity, &pdescription, &pPlatform};
  1265. DEBUGMSG("CAUCatalog::createDownloadItemStatusNode() starts");
  1266. *ppIdentity = NULL;
  1267. if (!itemDetails.Init(bsInstallation))
  1268. {
  1269. DEBUGMSG("fail to init itemdetails");
  1270. fError = TRUE;
  1271. goto done;
  1272. }
  1273. bsItemId = Item.bstrID();
  1274. DEBUGMSG("creating node for %S", bsItemId);
  1275. if (NULL == bsItemId)
  1276. {
  1277. DEBUGMSG("fails to get item id");
  1278. fError = TRUE;
  1279. goto done;
  1280. }
  1281. if (FAILED(pxml->createElement(KEY_ITEMSTATUS, &pitemStatus)) || NULL == pitemStatus)
  1282. {
  1283. DEBUGMSG("fail to create item status node");
  1284. fError = TRUE;
  1285. goto done;
  1286. }
  1287. itemDetails.CloneIdentityNode(bsItemId, pxml, ppIdentity);
  1288. itemDetails.CloneDescriptionNode(bsItemId, pxml, &pdescription);
  1289. itemDetails.ClonePlatformNode(bsItemId, pxml, &pPlatform);
  1290. if (NULL == *ppIdentity || NULL == pdescription || NULL == pPlatform)
  1291. {
  1292. fError = TRUE;
  1293. goto done;
  1294. }
  1295. for (int i = 0; i < ARRAYSIZE(ItemStatusChildren); i++)
  1296. {
  1297. if (FAILED(pitemStatus->appendChild(*(ItemStatusChildren[i]), NULL)))
  1298. {
  1299. DEBUGMSG("fail to append identy node");
  1300. fError = TRUE;
  1301. goto done;
  1302. }
  1303. }
  1304. if (FAILED(pxml->createElement(KEY_DOWNLOADPATH, &pdownloadPath)) || NULL == pdownloadPath)
  1305. {
  1306. DEBUGMSG("fail to create download path node");
  1307. fError = TRUE;
  1308. goto done;
  1309. }
  1310. bsdownloadPath = itemDetails.GetItemDownloadPath(bsItemId);
  1311. if (NULL == bsdownloadPath)
  1312. {
  1313. fError = TRUE;
  1314. goto done;
  1315. }
  1316. if (FAILED(pdownloadPath->put_text(bsdownloadPath)))
  1317. {
  1318. DEBUGMSG("fail to set download path text to %S", bsdownloadPath);
  1319. fError = TRUE;
  1320. goto done;
  1321. }
  1322. if (FAILED(pitemStatus->appendChild(pdownloadPath, NULL)))
  1323. {
  1324. DEBUGMSG("fail to append download path");
  1325. fError = TRUE;
  1326. goto done;
  1327. }
  1328. if (FAILED(pxml->createElement(KEY_DOWNLOADSTATUS, &pdownloadStatus)) || NULL == pdownloadStatus)
  1329. {
  1330. DEBUGMSG("fail to create download status node");
  1331. fError = TRUE;
  1332. goto done;
  1333. }
  1334. vComplete.vt = VT_BSTR;
  1335. vComplete.bstrVal = SysAllocString(L"COMPLETE");
  1336. if (NULL == vComplete.bstrVal)
  1337. {
  1338. DEBUGMSG("Out of memory, fail to create string complete");
  1339. fError = TRUE;
  1340. goto done;
  1341. }
  1342. HRESULT hr = SetAttribute(pdownloadStatus, KEY_DOWNLOADSTATUS, vComplete);
  1343. VariantClear(&vComplete);
  1344. if (FAILED(hr))
  1345. {
  1346. DEBUGMSG("fail to set download status attribute");
  1347. fError = TRUE;
  1348. goto done;
  1349. }
  1350. if (FAILED(pitemStatus->appendChild(pdownloadStatus, NULL)))
  1351. {
  1352. DEBUGMSG("fail to append download status node");
  1353. fError = TRUE;
  1354. goto done;
  1355. }
  1356. done:
  1357. itemDetails.Uninit();
  1358. SafeFreeBSTR(bsdownloadPath);
  1359. if (fError)
  1360. {
  1361. SafeRelease(*ppIdentity);
  1362. SafeRelease(pitemStatus);
  1363. *ppIdentity = NULL;
  1364. pitemStatus = NULL;
  1365. }
  1366. SafeRelease(pPlatform);
  1367. SafeRelease(pdescription);
  1368. SafeRelease(pdownloadPath);
  1369. SafeRelease(pdownloadStatus);
  1370. DEBUGMSG("CAUCatalog::createDownloadItemStatusNode() ends");
  1371. return pitemStatus;
  1372. }
  1373. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  1374. // *pbstrInstallation contains a subset of bsItemDetails (only items needs to be installed)
  1375. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  1376. HRESULT PrepareInstallXML(
  1377. IN BSTR bsItemDetails, //a superset of items in the itemlist
  1378. IN AUCatalogItemList &itemList,
  1379. OUT BSTR * pbstrDownloadResult,
  1380. OUT BSTR *pbstrInstallation)
  1381. {
  1382. DEBUGMSG("::PrepareInstallXML");
  1383. HRESULT hr = E_FAIL;
  1384. BSTR bsRet = NULL;
  1385. IXMLDOMNode * pItems = NULL;
  1386. IXMLDOMDocument *pxml = NULL;
  1387. CItemDetails itemdetails;
  1388. LONG lNumItems = 0;
  1389. BSTR * pbstrItemIds = NULL;
  1390. *pbstrDownloadResult = NULL;
  1391. *pbstrInstallation = NULL;
  1392. if (! itemdetails.Init(bsItemDetails))
  1393. {
  1394. DEBUGMSG("Fail to init item details ");
  1395. goto done;
  1396. }
  1397. if (FAILED(hr = LoadXMLDoc(AUCatalog::bstrResultTemplate, &pxml)))
  1398. {
  1399. DEBUGMSG("::PrepareInstallXML() fail to load download result template with error %#lx", hr);
  1400. goto done;
  1401. }
  1402. if (FAILED(hr = FindSingleDOMNode(pxml, KEY_ITEMS, &pItems)) || NULL == pItems)
  1403. {
  1404. DEBUGMSG("::PrepareInstallXML() fail to get items with error %#lx", hr);
  1405. goto done;
  1406. }
  1407. // DEBUGMSG("need to insert %d items in download result", itemList.GetNumSelected());
  1408. if (FAILED(hr = itemdetails.GetItemIds(&lNumItems, &pbstrItemIds)))
  1409. {
  1410. DEBUGMSG("Fail to get item ids with error %#lx", hr);
  1411. goto done;
  1412. }
  1413. for (LONG l = 0; l < lNumItems; l++)
  1414. {
  1415. if (itemList.Contains(pbstrItemIds[l]) < 0)
  1416. {
  1417. itemdetails.DeleteItem(pbstrItemIds[l]); //delete items not in the itemlist
  1418. }
  1419. }
  1420. for (UINT i = 0; i < itemList.Count(); i++)
  1421. {
  1422. AUCatalogItem & item = itemList[i];
  1423. if (item.fSelected() || itemList.ItemIsRelevant(i))
  1424. {
  1425. long lItemNum = 0;
  1426. IXMLDOMNodeList *pIdentityNodeList = NULL;
  1427. if (FAILED(itemdetails.GetItemIdentities(item.bstrID(), &pIdentityNodeList)))
  1428. {
  1429. DEBUGMSG("Fail to get item identities for item %S", item.bstrID());
  1430. continue;
  1431. }
  1432. if (FAILED(pIdentityNodeList->get_length(&lItemNum)))
  1433. {
  1434. DEBUGMSG("Fail to get number of identity nodes"); //fixcode: bail out here
  1435. pIdentityNodeList->Release();
  1436. continue;
  1437. }
  1438. for (long lIndex = 0; lIndex < lItemNum; lIndex++)
  1439. {
  1440. DEBUGMSG("Create download status node %d for item %S", lIndex, item.bstrID());
  1441. IXMLDOMNode * pDetailsIdentity = NULL;
  1442. IXMLDOMNode *pDownloadResultIdentity = NULL;
  1443. if (S_OK != pIdentityNodeList->get_item(lIndex, &pDetailsIdentity))
  1444. {
  1445. DEBUGMSG("Fail to get item %d", lIndex); //fixcode: bail out here
  1446. continue;
  1447. }
  1448. MungleIdentity(pDetailsIdentity, lIndex);
  1449. IXMLDOMNode * pItemStatus = createDownloadItemStatusNode(pxml, item, bsItemDetails, &pDownloadResultIdentity);
  1450. if (NULL != pItemStatus)
  1451. {
  1452. MungleIdentity(pDownloadResultIdentity, lIndex);
  1453. if (FAILED(hr = pItems->appendChild(pItemStatus,NULL)))
  1454. {
  1455. DEBUGMSG("fail to insert item %d", i);
  1456. }
  1457. else
  1458. {
  1459. DEBUGMSG("item %d inserted", i);
  1460. }
  1461. pItemStatus->Release();
  1462. }
  1463. SafeRelease(pDetailsIdentity);
  1464. SafeRelease(pDownloadResultIdentity);
  1465. }
  1466. pIdentityNodeList->Release();
  1467. }
  1468. else
  1469. {
  1470. itemdetails.DeleteItem(item.bstrID());
  1471. }
  1472. }
  1473. if ( FAILED(hr = pxml->get_xml(pbstrDownloadResult)) )
  1474. {
  1475. DEBUGMSG("::PrepareInstallXML() fail to get xml for the result %#lx", hr);
  1476. goto done;
  1477. }
  1478. if (FAILED(hr = itemdetails.GetXML(pbstrInstallation)))
  1479. {
  1480. DEBUGMSG(" fail to get xml for installation with error %#lx", hr);
  1481. goto done;
  1482. }
  1483. done:
  1484. itemdetails.Uninit();
  1485. SafeRelease(pItems);
  1486. SafeRelease(pxml);
  1487. for (int k = 0; k < lNumItems; k++)
  1488. {
  1489. SafeFreeBSTR(pbstrItemIds[k]);
  1490. }
  1491. if (lNumItems > 0)
  1492. {
  1493. SafeFree(pbstrItemIds);
  1494. }
  1495. if (FAILED(hr))
  1496. {
  1497. SafeFreeBSTR(*pbstrDownloadResult);
  1498. *pbstrDownloadResult = NULL;
  1499. SafeFreeBSTR(*pbstrInstallation);
  1500. *pbstrInstallation = NULL;
  1501. }
  1502. return hr;
  1503. }
  1504. ///////////////////////////////////////////////////////////////////
  1505. // merge catalog 1 and catalog2 and make it destination catalog *pDesCatalog
  1506. // if either of bsCatalog1 and bsCatalog2 is NULL, return duplicate of the non NULL
  1507. // catalog
  1508. // if both bsCatalog1 and bsCatalog2 are NULL, return NULL and S_FALSE
  1509. //
  1510. ///////////////////////////////////////////////////////////////////
  1511. HRESULT MergeCatalogs(IN const BSTR bsCatalog1, IN const BSTR bsCatalog2, OUT BSTR *pbsDesCatalog )
  1512. {
  1513. IXMLDOMDocument * pCat1 = NULL;
  1514. IXMLDOMDocument * pCat2 = NULL;
  1515. IXMLDOMNodeList *pProviderNodeList = NULL;
  1516. IXMLDOMNode *pCatalogNode = NULL;
  1517. HRESULT hr = E_FAIL;
  1518. DEBUGMSG("MergeCatalogs() starts");
  1519. *pbsDesCatalog = NULL;
  1520. if (NULL == bsCatalog1 && NULL == bsCatalog2)
  1521. {
  1522. return S_FALSE;
  1523. }
  1524. if (NULL == bsCatalog1 || NULL == bsCatalog2)
  1525. {
  1526. *pbsDesCatalog = SysAllocString((NULL == bsCatalog1) ? bsCatalog2 : bsCatalog1);
  1527. if (NULL == *pbsDesCatalog)
  1528. {
  1529. DEBUGMSG("Out of memory");
  1530. hr = E_OUTOFMEMORY;
  1531. goto done;
  1532. }
  1533. hr = S_OK;
  1534. goto done;
  1535. }
  1536. if ( FAILED(hr = LoadXMLDoc(bsCatalog1, &pCat1)) ||
  1537. FAILED(hr = LoadXMLDoc(bsCatalog2,&pCat2)))
  1538. {
  1539. DEBUGMSG("MergeCatalogs() fail to load xml or fail or allocate string (with error %#lx)", hr);
  1540. goto done;
  1541. }
  1542. if (FAILED(hr = FindSingleDOMNode(pCat1, AUCatalog::bstrCatalog, &pCatalogNode)))
  1543. {
  1544. DEBUGMSG("Fail to find provider in catalog 1");
  1545. goto done;
  1546. }
  1547. if (NULL == (pProviderNodeList = FindDOMNodeList(pCat2, KEY_CATALOG_PROVIDER)))
  1548. {
  1549. DEBUGMSG("Fail to find provider in catalog 2 with error %#lx", hr);
  1550. goto done;
  1551. }
  1552. long lNum;
  1553. if (FAILED(hr = pProviderNodeList->get_length(&lNum)))
  1554. {
  1555. DEBUGMSG("Fail to get nubmer of providers");
  1556. goto done;
  1557. }
  1558. for (int i = 0; i < lNum; i++)
  1559. {
  1560. IXMLDOMNode * pProviderNode = NULL;
  1561. if (S_OK != (hr = pProviderNodeList->get_item(i, &pProviderNode)))
  1562. {
  1563. DEBUGMSG("Fail to get item in Provider List with error %#lx", hr);
  1564. hr = FAILED(hr) ? hr : E_FAIL;
  1565. goto done;
  1566. }
  1567. if (FAILED(hr = InsertNode(pCatalogNode, pProviderNode)))
  1568. {
  1569. DEBUGMSG("Fail to append provider node from catalog 2 to catalog 1 with error %#lx", hr);
  1570. pProviderNode->Release();
  1571. goto done;
  1572. }
  1573. pProviderNode->Release();
  1574. }
  1575. if (FAILED(hr = pCat1->get_xml(pbsDesCatalog)))
  1576. {
  1577. DEBUGMSG("Fail to get result xml for catalog 1 with error %#lx", hr);
  1578. goto done;
  1579. }
  1580. done:
  1581. SafeRelease(pCat1);
  1582. SafeRelease(pCat2);
  1583. SafeRelease(pProviderNodeList);
  1584. SafeRelease(pCatalogNode);
  1585. if (FAILED(hr))
  1586. {
  1587. SafeFreeBSTRNULL(*pbsDesCatalog);
  1588. }
  1589. DEBUGMSG("MergeCatalogs() ends");
  1590. return hr;
  1591. }
  1592. ////////////////////////////////////////////////////////////////////////////////////
  1593. // populate itemlist for all items in the list with detailed information from local merged catalog xml file
  1594. // also return the merged catalog xml in pbstrInstallation
  1595. // if fDrvierNeeded, care to extract driver information. Otherwise, no driver info extracted
  1596. /////////////////////////////////////////////////////////////////////////////////////
  1597. HRESULT GetDetailedItemInfoFromDisk(IN OUT AUCatalogItemList &ItemList, OUT BSTR *pbstrInstallation, IN BOOL fDriverNeeded)
  1598. {
  1599. HRESULT hr = S_OK;
  1600. CItemDetails driverDetails, nonDriverDetails;
  1601. BSTR bstrDriver = NULL;
  1602. BSTR bstrNonDriver = NULL;
  1603. *pbstrInstallation = NULL;
  1604. if (NULL == (bstrNonDriver = ReadXMLFromFile(DETAILS_FILE)) ||
  1605. (fDriverNeeded && (NULL == (bstrDriver = ReadXMLFromFile(DRIVERS_FILE)))))
  1606. {
  1607. DEBUGMSG("Fail to load driver or nondriver details xml file");
  1608. hr = E_FAIL;
  1609. goto done;
  1610. }
  1611. if (!nonDriverDetails.Init(bstrNonDriver) ||
  1612. (fDriverNeeded && !driverDetails.Init(bstrDriver)))
  1613. {
  1614. DEBUGMSG("Fail to initialize item or driver details ");
  1615. hr = E_FAIL;
  1616. goto done;
  1617. }
  1618. if (FAILED(hr = MergeCatalogs(bstrDriver, bstrNonDriver, pbstrInstallation)))
  1619. {
  1620. DEBUGMSG("Fail to merge catalog with error %#lx", hr);
  1621. goto done;
  1622. }
  1623. for (UINT u = 0; u < ItemList.Count(); u++)
  1624. {
  1625. for (int i = 1; i < ARRAYSIZE(AUCatalogItem::m_pFieldNames); i++)
  1626. {
  1627. BSTR bstrItemInfo = NULL;
  1628. if (SUCCEEDED(nonDriverDetails.GetItemInfo(AUCatalogItem::m_pFieldNames[i], ItemList[u].bstrID(), &bstrItemInfo)) ||
  1629. (fDriverNeeded && SUCCEEDED(driverDetails.GetItemInfo(AUCatalogItem::m_pFieldNames[i], ItemList[u].bstrID(), &bstrItemInfo))))
  1630. {
  1631. ItemList[u].SetField(AUCatalogItem::m_pFieldNames[i], bstrItemInfo);
  1632. }
  1633. else
  1634. {
  1635. DEBUGMSG("Warning: not getting information about %S for item %S", AUCatalogItem::m_pFieldNames[i], ItemList[u].bstrID());
  1636. }
  1637. }
  1638. }
  1639. done:
  1640. driverDetails.Uninit();
  1641. nonDriverDetails.Uninit();
  1642. if (FAILED(hr))
  1643. {
  1644. SafeFreeBSTR(*pbstrInstallation);
  1645. *pbstrInstallation = NULL;
  1646. }
  1647. SafeFreeBSTR(bstrDriver);
  1648. SafeFreeBSTR(bstrNonDriver);
  1649. return hr;
  1650. }
  1651. ///////////////////////////////////////////////////////////////////////////////////////
  1652. // walk through the whole list of items, hidden or non hidden, build dependency list m_DependentItems
  1653. // for each item from scratch. The orginal m_DependentItems for each item is discarded
  1654. // bstrDriver could be NULL
  1655. /////////////////////////////////////////////////////////////////////////////////////////
  1656. HRESULT BuildDependencyList(
  1657. AUCatalogItemList IN OUT &itemlist,
  1658. BSTR IN bstrDriver,
  1659. BSTR IN bstrNonDriver)
  1660. {
  1661. CItemDetails driverInfo;
  1662. CItemDetails nondriverInfo;
  1663. HRESULT hr = E_FAIL ;
  1664. BOOL fHasDriverUpdate = TRUE;
  1665. if (!nondriverInfo.Init(bstrNonDriver))
  1666. {
  1667. DEBUGMSG("Fail to initialize item details");
  1668. goto done;
  1669. }
  1670. if (NULL != bstrDriver)
  1671. {
  1672. if (!driverInfo.Init(bstrDriver) )
  1673. {
  1674. DEBUGMSG("Fail to initialize driver details");
  1675. goto done;
  1676. }
  1677. }
  1678. else
  1679. {
  1680. fHasDriverUpdate = FALSE;
  1681. }
  1682. DEBUGMSG("Building direct dependency for non drivers");
  1683. if (FAILED(hr = nondriverInfo.BuildDirectDependency(itemlist)))
  1684. { //itemlist is a non driver and dependency built if any
  1685. DEBUGMSG("Fail to build dependency for non drivers with error %#lx", hr);
  1686. goto done;
  1687. }
  1688. if (fHasDriverUpdate)
  1689. {
  1690. DEBUGMSG("Building direct dependency for drivers");
  1691. if (FAILED(hr = driverInfo.BuildDirectDependency(itemlist)))
  1692. { //itemlist is a driver and dependency built if any
  1693. DEBUGMSG("Fail to build dependency for drivers with error %#lx", hr);
  1694. goto done;
  1695. }
  1696. }
  1697. DEBUGMSG("Building indirect dependency");
  1698. if (FAILED(hr = itemlist.BuildIndirectDependency()))
  1699. {
  1700. DEBUGMSG("Fail to build indirect dependency for itemlist with error %#lx", hr);
  1701. goto done;
  1702. }
  1703. done:
  1704. if (fHasDriverUpdate)
  1705. {
  1706. driverInfo.Uninit();
  1707. }
  1708. nondriverInfo.Uninit();
  1709. DEBUGMSG("BuildDependencyList done");
  1710. #ifdef DBG
  1711. // itemlist.DbgDump();
  1712. #endif
  1713. return hr;
  1714. }