Leaked source code of windows server 2003
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.

587 lines
14 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1999.
  5. //
  6. // File: C O M P R E F S . C P P
  7. //
  8. // Contents: Implements the interface to a component's references. A
  9. // component can be referenced (installed by) other components,
  10. // the user, or other software. This module manages the
  11. // interface to that data.
  12. //
  13. // Notes:
  14. //
  15. // Author: shaunco 15 Jan 1999
  16. //
  17. //----------------------------------------------------------------------------
  18. #include <pch.h>
  19. #pragma hdrstop
  20. #include "comp.h"
  21. #include "comprefs.h"
  22. #include "icomp.h"
  23. #include "nceh.h"
  24. #include "ncreg.h"
  25. #define REGSTR_KEY_REFNAMES \
  26. L"SYSTEM\\CurrentControlSet\\Control\\Network\\RefNames"
  27. // Cannot be inline because comprefs.h cannot include comp.h.
  28. //
  29. CComponentReferences::~CComponentReferences ()
  30. {
  31. Assert (this);
  32. // Must use delete on m_pData to get destructors of its members
  33. // to be called.
  34. //
  35. delete m_pData;
  36. }
  37. ULONG
  38. CComponentReferences::CountComponentsReferencedBy () const
  39. {
  40. Assert (this);
  41. if (!m_pData)
  42. {
  43. return 0;
  44. }
  45. return m_pData->RefByComponents.Count ();
  46. }
  47. ULONG
  48. CComponentReferences::CountSoftwareReferencedBy () const
  49. {
  50. Assert (this);
  51. if (!m_pData)
  52. {
  53. return 0;
  54. }
  55. return m_pData->RefBySoftware.size ();
  56. }
  57. ULONG
  58. CComponentReferences::CountTotalReferencedBy () const
  59. {
  60. Assert (this);
  61. if (!m_pData)
  62. {
  63. return 0;
  64. }
  65. return ((m_pData->fRefByUser) ? 1 : 0) +
  66. m_pData->RefByComponents.Count () +
  67. m_pData->RefBySoftware.size ();
  68. }
  69. HRESULT
  70. HrGetSoftwareOboTokenKey (
  71. IN const OBO_TOKEN* pOboToken,
  72. BOOL fRegister,
  73. OUT PWSTR* ppszKey)
  74. {
  75. HRESULT hr;
  76. UINT cch;
  77. Assert (pOboToken);
  78. Assert (OBO_SOFTWARE == pOboToken->Type);
  79. Assert (pOboToken->pszwManufacturer && *pOboToken->pszwManufacturer);
  80. Assert (pOboToken->pszwProduct && *pOboToken->pszwProduct);
  81. Assert (ppszKey);
  82. cch = wcslen (pOboToken->pszwManufacturer) +
  83. wcslen (pOboToken->pszwProduct);
  84. hr = E_OUTOFMEMORY;
  85. *ppszKey = (PWSTR)MemAlloc ((cch + 1) * sizeof(WCHAR));
  86. if (*ppszKey)
  87. {
  88. hr = S_OK;
  89. wcscpy (*ppszKey, pOboToken->pszwManufacturer);
  90. wcscat (*ppszKey, pOboToken->pszwProduct);
  91. if (fRegister)
  92. {
  93. HKEY hkeyRefNames;
  94. hr = HrRegCreateKeyEx (
  95. HKEY_LOCAL_MACHINE,
  96. REGSTR_KEY_REFNAMES,
  97. REG_OPTION_NON_VOLATILE,
  98. KEY_WRITE, NULL, &hkeyRefNames, NULL);
  99. if (SUCCEEDED(hr))
  100. {
  101. hr = HrRegSetSz (
  102. hkeyRefNames,
  103. *ppszKey,
  104. pOboToken->pszwDisplayName);
  105. RegCloseKey (hkeyRefNames);
  106. }
  107. else
  108. {
  109. MemFree (*ppszKey);
  110. *ppszKey = NULL;
  111. }
  112. }
  113. }
  114. TraceHr (ttidError, FAL, hr, FALSE, "HrGetSoftwareOboTokenKey");
  115. return hr;
  116. }
  117. BOOL
  118. CComponentReferences::FIsReferencedByComponent (
  119. IN const CComponent* pComponent) const
  120. {
  121. Assert (pComponent);
  122. if (!m_pData)
  123. {
  124. return FALSE;
  125. }
  126. return m_pData->RefByComponents.FComponentInList (pComponent);
  127. }
  128. BOOL
  129. CComponentReferences::FIsReferencedByOboToken (
  130. IN const OBO_TOKEN* pOboToken) const
  131. {
  132. HRESULT hr;
  133. BOOL fIsReferenced;
  134. PWSTR pszKey;
  135. Assert (pOboToken);
  136. if (!m_pData)
  137. {
  138. return FALSE;
  139. }
  140. fIsReferenced = FALSE;
  141. CComponent* pComponent;
  142. switch (pOboToken->Type)
  143. {
  144. case OBO_USER:
  145. fIsReferenced = m_pData->fRefByUser;
  146. break;
  147. case OBO_COMPONENT:
  148. // Can't be referenced if there are no references.
  149. //
  150. if (m_pData->RefByComponents.Count() > 0)
  151. {
  152. pComponent = PComponentFromComInterface (pOboToken->pncc);
  153. fIsReferenced = m_pData->RefByComponents.FComponentInList (
  154. pComponent);
  155. }
  156. break;
  157. case OBO_SOFTWARE:
  158. // Can't be referenced if there are no references.
  159. //
  160. if (m_pData->RefBySoftware.size() > 0)
  161. {
  162. // Get the key for the software token, but don't register
  163. // the display name.
  164. //
  165. hr = HrGetSoftwareOboTokenKey (pOboToken, FALSE, &pszKey);
  166. if (S_OK == hr)
  167. {
  168. fIsReferenced =
  169. find (m_pData->RefBySoftware.begin(),
  170. m_pData->RefBySoftware.end(), pszKey) !=
  171. m_pData->RefBySoftware.end();
  172. MemFree (pszKey);
  173. }
  174. }
  175. break;
  176. default:
  177. AssertSz (FALSE, "Invalid obo token");
  178. }
  179. return fIsReferenced;
  180. }
  181. VOID
  182. CComponentReferences::GetReferenceDescriptionsAsMultiSz (
  183. IN BYTE* pbBuf OPTIONAL,
  184. OUT ULONG* pcbBuf) const
  185. {
  186. ULONG cbBuf;
  187. ULONG cbBufIn;
  188. ULONG cb;
  189. CComponentList::const_iterator iter;
  190. const CComponent* pComponent;
  191. vector<CWideString>::const_iterator pStr;
  192. Assert (this);
  193. Assert (m_pData);
  194. Assert (pcbBuf);
  195. cbBufIn = *pcbBuf;
  196. cbBuf = 0;
  197. // Get/Size the component descriptions.
  198. //
  199. for (iter = m_pData->RefByComponents.begin();
  200. iter != m_pData->RefByComponents.end();
  201. iter++)
  202. {
  203. pComponent = *iter;
  204. Assert (pComponent);
  205. cb = CbOfSzAndTermSafe(pComponent->Ext.PszDescription());
  206. cbBuf += cb;
  207. if (pbBuf && (cbBuf <= cbBufIn))
  208. {
  209. wcscpy ((PWSTR)pbBuf, pComponent->Ext.PszDescription());
  210. pbBuf += cb;
  211. }
  212. }
  213. // Get/Size the software descriptions.
  214. //
  215. if (!m_pData->RefBySoftware.empty())
  216. {
  217. HRESULT hr;
  218. HKEY hkeyRefNames;
  219. hr = HrRegOpenKeyEx (
  220. HKEY_LOCAL_MACHINE,
  221. REGSTR_KEY_REFNAMES,
  222. KEY_READ,
  223. &hkeyRefNames);
  224. if (S_OK == hr)
  225. {
  226. for (pStr = m_pData->RefBySoftware.begin();
  227. pStr != m_pData->RefBySoftware.end();
  228. pStr++)
  229. {
  230. cb = cbBufIn - cbBuf;
  231. hr = HrRegQuerySzBuffer (hkeyRefNames, pStr->c_str(),
  232. (PWSTR)pbBuf, &cb);
  233. if (S_OK == hr)
  234. {
  235. cbBuf += cb;
  236. if (pbBuf)
  237. {
  238. pbBuf += cb;
  239. }
  240. }
  241. }
  242. RegCloseKey (hkeyRefNames);
  243. }
  244. }
  245. // Terminate the multi-sz.
  246. //
  247. cbBuf += sizeof(WCHAR);
  248. if (pbBuf && (cbBuf <= cbBufIn))
  249. {
  250. *(PWSTR)pbBuf = 0;
  251. }
  252. // Return the size of the buffer required.
  253. //
  254. *pcbBuf = cbBuf;
  255. }
  256. BOOL
  257. CComponentReferences::FIsReferencedByOthers () const
  258. {
  259. Assert (this);
  260. if (!m_pData)
  261. {
  262. return FALSE;
  263. }
  264. return m_pData->fRefByUser ||
  265. !m_pData->RefByComponents.empty() ||
  266. !m_pData->RefBySoftware.empty();
  267. }
  268. CComponent*
  269. CComponentReferences::PComponentReferencedByAtIndex (
  270. IN UINT unIndex) const
  271. {
  272. Assert (this);
  273. if (!m_pData)
  274. {
  275. return NULL;
  276. }
  277. return m_pData->RefByComponents.PGetComponentAtIndex (unIndex);
  278. }
  279. const CWideString*
  280. CComponentReferences::PSoftwareReferencedByAtIndex (
  281. IN UINT unIndex) const
  282. {
  283. Assert (this);
  284. if (!m_pData)
  285. {
  286. return NULL;
  287. }
  288. return &m_pData->RefBySoftware[unIndex];
  289. }
  290. HRESULT
  291. CComponentReferences::HrEnsureAllocated ()
  292. {
  293. Assert (this);
  294. if (m_pData)
  295. {
  296. return S_OK;
  297. }
  298. HRESULT hr;
  299. hr = E_OUTOFMEMORY;
  300. m_pData = new COMPONENT_REFERENCE_DATA;
  301. if (m_pData)
  302. {
  303. ZeroMemory (m_pData, sizeof(COMPONENT_REFERENCE_DATA));
  304. hr = S_OK;
  305. }
  306. TraceHr (ttidError, FAL, hr, FALSE,
  307. "CComponentReferences::HrEnsureAllocated");
  308. return hr;
  309. }
  310. HRESULT
  311. CComponentReferences::HrAddReferenceByUser ()
  312. {
  313. HRESULT hr;
  314. Assert (this);
  315. hr = HrEnsureAllocated ();
  316. if (S_OK == hr)
  317. {
  318. m_pData->fRefByUser = TRUE;
  319. }
  320. TraceHr (ttidError, FAL, hr, FALSE,
  321. "CComponentReferences::AddReferenceByUser");
  322. return hr;
  323. }
  324. HRESULT
  325. CComponentReferences::HrAddReferenceByComponent (
  326. IN const CComponent* pComponent)
  327. {
  328. HRESULT hr;
  329. Assert (this);
  330. Assert (pComponent);
  331. hr = HrEnsureAllocated ();
  332. if (S_OK == hr)
  333. {
  334. // If someone wants to add a reference by the same component
  335. // multiple times, we'll allow it. The component only goes in the
  336. // list once.
  337. //
  338. hr = m_pData->RefByComponents.HrInsertComponent (
  339. pComponent, INS_IGNORE_IF_DUP | INS_NON_SORTED);
  340. }
  341. TraceHr (ttidError, FAL, hr, FALSE,
  342. "CComponentReferences::HrAddReferenceByComponent");
  343. return hr;
  344. }
  345. HRESULT
  346. CComponentReferences::HrAddReferenceByOboToken (
  347. IN const OBO_TOKEN* pOboToken)
  348. {
  349. Assert (pOboToken);
  350. HRESULT hr;
  351. CComponent* pComponent;
  352. PWSTR pszKey;
  353. switch (pOboToken->Type)
  354. {
  355. case OBO_USER:
  356. hr = HrAddReferenceByUser ();
  357. break;
  358. case OBO_COMPONENT:
  359. pComponent = PComponentFromComInterface (pOboToken->pncc);
  360. hr = HrAddReferenceByComponent (pComponent);
  361. break;
  362. case OBO_SOFTWARE:
  363. // Register the display name of the obo token.
  364. //
  365. hr = HrGetSoftwareOboTokenKey (pOboToken, TRUE, &pszKey);
  366. if (S_OK == hr)
  367. {
  368. hr = HrAddReferenceBySoftware (pszKey);
  369. MemFree (pszKey);
  370. }
  371. break;
  372. default:
  373. AssertSz (FALSE, "Invalid obo token");
  374. hr = E_FAIL;
  375. }
  376. TraceHr (ttidError, FAL, hr, FALSE,
  377. "CComponentReferences::HrAddReferenceByOboToken");
  378. return hr;
  379. }
  380. HRESULT
  381. CComponentReferences::HrAddReferenceBySoftware (
  382. IN PCWSTR pszKey)
  383. {
  384. HRESULT hr;
  385. Assert (this);
  386. Assert (pszKey && *pszKey);
  387. hr = HrEnsureAllocated ();
  388. if (S_OK == hr)
  389. {
  390. // If the key is not in the list, add it.
  391. //
  392. if (find (m_pData->RefBySoftware.begin(),
  393. m_pData->RefBySoftware.end(), pszKey) ==
  394. m_pData->RefBySoftware.end())
  395. {
  396. NC_TRY
  397. {
  398. m_pData->RefBySoftware.push_back (pszKey);
  399. Assert (S_OK == hr);
  400. }
  401. NC_CATCH_BAD_ALLOC
  402. {
  403. hr = E_OUTOFMEMORY;
  404. }
  405. }
  406. }
  407. TraceHr (ttidError, FAL, hr, FALSE,
  408. "CComponentReferences::HrAddReferenceBySoftware");
  409. return hr;
  410. }
  411. VOID
  412. CComponentReferences::RemoveAllReferences()
  413. {
  414. Assert (this);
  415. if (m_pData)
  416. {
  417. m_pData->fRefByUser = FALSE;
  418. m_pData->RefByComponents.Clear();
  419. m_pData->RefBySoftware.clear();
  420. }
  421. }
  422. HRESULT
  423. CComponentReferences::HrRemoveReferenceByOboToken (
  424. IN const OBO_TOKEN* pOboToken)
  425. {
  426. Assert (pOboToken);
  427. HRESULT hr;
  428. CComponent* pComponent;
  429. PWSTR pszKey;
  430. if (!m_pData)
  431. {
  432. return S_OK;
  433. }
  434. hr = S_OK;
  435. switch (pOboToken->Type)
  436. {
  437. case OBO_USER:
  438. // Don't allow the user's reference to be removed until all
  439. // other references are. This is to prevent the case where
  440. // the user wants to remove IPX, but it is still referenced by
  441. // SAP. If we remove the user's reference to IPX, then we will
  442. // report that it was not removed. If the user then removes
  443. // SAP, both SAP and IPX will be removed. While this will
  444. // certainly work, to end users, they feel that if we tell them
  445. // we can't remove IPX because it is still referenced, then they
  446. // believe we have left IPX untouched and they should first remove
  447. // SAP and then come back and remove IPX.
  448. //
  449. if (m_pData->RefByComponents.empty() &&
  450. m_pData->RefBySoftware.empty())
  451. {
  452. m_pData->fRefByUser = FALSE;
  453. }
  454. break;
  455. case OBO_COMPONENT:
  456. pComponent = PComponentFromComInterface (pOboToken->pncc);
  457. m_pData->RefByComponents.RemoveComponent(pComponent);
  458. break;
  459. case OBO_SOFTWARE:
  460. // Register the display name of the obo token.
  461. //
  462. hr = HrGetSoftwareOboTokenKey (pOboToken, TRUE, &pszKey);
  463. if (S_OK == hr)
  464. {
  465. vector<CWideString>::iterator iter;
  466. iter = find (m_pData->RefBySoftware.begin(),
  467. m_pData->RefBySoftware.end(), pszKey);
  468. Assert (m_pData->RefBySoftware.end() != iter);
  469. m_pData->RefBySoftware.erase (iter);
  470. Assert (m_pData->RefBySoftware.end() ==
  471. find (m_pData->RefBySoftware.begin(),
  472. m_pData->RefBySoftware.end(), pszKey));
  473. MemFree (pszKey);
  474. }
  475. break;
  476. default:
  477. AssertSz (FALSE, "Invalid obo token");
  478. hr = E_FAIL;
  479. }
  480. TraceHr (ttidError, FAL, hr, FALSE,
  481. "CComponentReferences::HrRemoveReferenceByOboToken");
  482. return hr;
  483. }