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.

921 lines
24 KiB

  1. #include "private.h"
  2. #include "subsmgrp.h"
  3. #include "subitem.h"
  4. // Contains implementations of IEnumSubscription and ISubscriptionMgr2
  5. HRESULT SubscriptionItemFromCookie(BOOL fCreateNew, const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie,
  6. ISubscriptionItem **ppSubscriptionItem);
  7. HRESULT DoGetItemFromURL(LPCTSTR pszURL, ISubscriptionItem **ppSubscriptionItem)
  8. {
  9. HRESULT hr;
  10. SUBSCRIPTIONCOOKIE cookie;
  11. if ((NULL == pszURL) ||
  12. (NULL == ppSubscriptionItem))
  13. {
  14. return E_INVALIDARG;
  15. }
  16. hr = ReadCookieFromInetDB(pszURL, &cookie);
  17. if (SUCCEEDED(hr))
  18. {
  19. hr = SubscriptionItemFromCookie(FALSE, &cookie, ppSubscriptionItem);
  20. }
  21. return hr;
  22. }
  23. HRESULT DoGetItemFromURLW(LPCWSTR pwszURL, ISubscriptionItem **ppSubscriptionItem)
  24. {
  25. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  26. if ((NULL == pwszURL) ||
  27. (NULL == ppSubscriptionItem))
  28. {
  29. return E_INVALIDARG;
  30. }
  31. StrCpyN(szURL, pwszURL, ARRAYSIZE(szURL));
  32. return DoGetItemFromURL(szURL, ppSubscriptionItem);
  33. }
  34. HRESULT DoAbortItems(
  35. /* [in] */ DWORD dwNumCookies,
  36. /* [size_is][in] */ const SUBSCRIPTIONCOOKIE *pCookies)
  37. {
  38. HRESULT hr;
  39. if ((0 == dwNumCookies) || (NULL == pCookies))
  40. {
  41. return E_INVALIDARG;
  42. }
  43. ISubscriptionThrottler *pst;
  44. hr = CoCreateInstance(CLSID_SubscriptionThrottler, NULL,
  45. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  46. IID_ISubscriptionThrottler, (void **)&pst);
  47. if (SUCCEEDED(hr))
  48. {
  49. hr = pst->AbortItems(dwNumCookies, pCookies);
  50. pst->Release();
  51. }
  52. else
  53. {
  54. hr = S_FALSE;
  55. }
  56. return hr;
  57. }
  58. HRESULT DoCreateSubscriptionItem(
  59. /* [in] */ const SUBSCRIPTIONITEMINFO *pSubscriptionItemInfo,
  60. /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie,
  61. /* [out] */ ISubscriptionItem **ppSubscriptionItem)
  62. {
  63. HRESULT hr;
  64. ISubscriptionItem *psi;
  65. if ((NULL == pSubscriptionItemInfo) ||
  66. (NULL == pNewCookie) ||
  67. (NULL == ppSubscriptionItem))
  68. {
  69. return E_INVALIDARG;
  70. }
  71. *ppSubscriptionItem = NULL;
  72. CreateCookie(pNewCookie);
  73. hr = SubscriptionItemFromCookie(TRUE, pNewCookie, &psi);
  74. if (SUCCEEDED(hr))
  75. {
  76. ASSERT(NULL != psi);
  77. hr = psi->SetSubscriptionItemInfo(pSubscriptionItemInfo);
  78. if (SUCCEEDED(hr))
  79. {
  80. *ppSubscriptionItem = psi;
  81. }
  82. else
  83. {
  84. // Don't leak or leave slop hanging around
  85. psi->Release();
  86. DoDeleteSubscriptionItem(pNewCookie, FALSE);
  87. }
  88. }
  89. return hr;
  90. }
  91. HRESULT DoCloneSubscriptionItem(
  92. /* [in] */ ISubscriptionItem *pSubscriptionItem,
  93. /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie,
  94. /* [out] */ ISubscriptionItem **ppSubscriptionItem)
  95. {
  96. HRESULT hr;
  97. SUBSCRIPTIONCOOKIE NewCookie;
  98. if ((NULL == pSubscriptionItem) ||
  99. (NULL == ppSubscriptionItem))
  100. {
  101. return E_INVALIDARG;
  102. }
  103. IEnumItemProperties *peip;
  104. SUBSCRIPTIONITEMINFO sii;
  105. *ppSubscriptionItem = NULL;
  106. // First get existing subscription details
  107. sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  108. hr = pSubscriptionItem->GetSubscriptionItemInfo(&sii);
  109. if (SUCCEEDED(hr))
  110. {
  111. ISubscriptionItem *psi;
  112. // Mark as temp and create a new subscription item
  113. sii.dwFlags |= SI_TEMPORARY;
  114. hr = DoCreateSubscriptionItem(&sii, &NewCookie, &psi);
  115. if (SUCCEEDED(hr))
  116. {
  117. if (pNewCookie)
  118. *pNewCookie = NewCookie;
  119. // Get properties from existing item
  120. hr = pSubscriptionItem->EnumProperties(&peip);
  121. if (SUCCEEDED(hr))
  122. {
  123. ULONG count;
  124. ASSERT(NULL != peip);
  125. hr = peip->GetCount(&count);
  126. if (SUCCEEDED(hr))
  127. {
  128. ITEMPROP *pProps = new ITEMPROP[count];
  129. LPWSTR *pNames = new LPWSTR[count];
  130. VARIANT *pVars = new VARIANT[count];
  131. if ((NULL != pProps) && (NULL != pNames) && (NULL != pVars))
  132. {
  133. hr = peip->Next(count, pProps, &count);
  134. if (SUCCEEDED(hr))
  135. {
  136. ULONG i;
  137. for (i = 0; i < count; i++)
  138. {
  139. pNames[i] = pProps[i].pwszName;
  140. pVars[i] = pProps[i].variantValue;
  141. }
  142. hr = psi->WriteProperties(count, pNames, pVars);
  143. // clean up from enum
  144. for (i = 0; i < count; i++)
  145. {
  146. if (pProps[i].pwszName)
  147. {
  148. CoTaskMemFree(pProps[i].pwszName);
  149. }
  150. VariantClear(&pProps[i].variantValue);
  151. }
  152. }
  153. }
  154. else
  155. {
  156. hr = E_OUTOFMEMORY;
  157. }
  158. SAFEDELETE(pProps);
  159. SAFEDELETE(pNames);
  160. SAFEDELETE(pVars);
  161. }
  162. peip->Release();
  163. }
  164. if (SUCCEEDED(hr))
  165. {
  166. *ppSubscriptionItem = psi;
  167. }
  168. else
  169. {
  170. psi->Release();
  171. }
  172. }
  173. }
  174. return hr;
  175. }
  176. HRESULT DoDeleteSubscriptionItem(
  177. /* [in] */ const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua,
  178. /* [in] */ BOOL fAbortItem)
  179. {
  180. HRESULT hr;
  181. TCHAR szKey[MAX_PATH];
  182. SUBSCRIPTIONCOOKIE cookie_buf;
  183. SUBSCRIPTIONCOOKIE *pCookie;
  184. //
  185. // Make an aligned copy of pCookie_ua and set a pointer to it.
  186. //
  187. if (pCookie_ua != NULL) {
  188. cookie_buf = *pCookie_ua;
  189. pCookie = &cookie_buf;
  190. } else {
  191. pCookie = NULL;
  192. }
  193. if (NULL == pCookie)
  194. {
  195. return E_INVALIDARG;
  196. }
  197. if (fAbortItem)
  198. {
  199. DoAbortItems(1, pCookie);
  200. }
  201. if (ItemKeyNameFromCookie(pCookie, szKey, ARRAYSIZE(szKey)))
  202. {
  203. // Notify the agent that it is about to get deleted.
  204. ISubscriptionItem *pItem=NULL;
  205. if (SUCCEEDED(SubscriptionItemFromCookie(FALSE, pCookie, &pItem)))
  206. {
  207. SUBSCRIPTIONITEMINFO sii = { sizeof(SUBSCRIPTIONITEMINFO) };
  208. if (SUCCEEDED(pItem->GetSubscriptionItemInfo(&sii)))
  209. {
  210. ASSERT(!(sii.dwFlags & SI_TEMPORARY));
  211. ISubscriptionAgentControl *psac=NULL;
  212. if (SUCCEEDED(
  213. CoCreateInstance(sii.clsidAgent,
  214. NULL,
  215. CLSCTX_INPROC_SERVER,
  216. IID_ISubscriptionAgentControl,
  217. (void**)&psac)))
  218. {
  219. psac->SubscriptionControl(pItem, SUBSCRIPTION_AGENT_DELETE);
  220. psac->Release();
  221. }
  222. FireSubscriptionEvent(SUBSNOTF_DELETE, pCookie);
  223. if (GUID_NULL != sii.ScheduleGroup)
  224. {
  225. ISyncScheduleMgr *pSyncScheduleMgr;
  226. hr = CoCreateInstance(CLSID_SyncMgr, NULL, CLSCTX_ALL,
  227. IID_ISyncScheduleMgr, (void **)&pSyncScheduleMgr);
  228. if (SUCCEEDED(hr))
  229. {
  230. pSyncScheduleMgr->RemoveSchedule(&sii.ScheduleGroup);
  231. pSyncScheduleMgr->Release();
  232. }
  233. }
  234. }
  235. pItem->Release();
  236. }
  237. hr = (SHDeleteKey(HKEY_CURRENT_USER, szKey) == ERROR_SUCCESS) ? S_OK : E_FAIL;
  238. }
  239. else
  240. {
  241. TraceMsg(TF_ALWAYS, "Failed to delete subscription item.");
  242. hr = E_FAIL;
  243. }
  244. return hr;
  245. }
  246. HRESULT AddUpdateSubscription(SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua,
  247. SUBSCRIPTIONITEMINFO *psii,
  248. LPCWSTR pwszURL,
  249. ULONG nProps,
  250. const LPWSTR rgwszName[],
  251. VARIANT rgValue[])
  252. {
  253. HRESULT hr = S_OK;
  254. SUBSCRIPTIONCOOKIE cookie_buf;
  255. SUBSCRIPTIONCOOKIE *pCookie;
  256. //
  257. // Make an aligned copy of pCookie_ua and set a pointer to it.
  258. //
  259. cookie_buf = *pCookie_ua;
  260. pCookie = &cookie_buf;
  261. ASSERT((0 == nProps) || ((NULL != rgwszName) && (NULL != rgValue)));
  262. TCHAR szURL[INTERNET_MAX_URL_LENGTH];
  263. ISubscriptionItem *psi = NULL;
  264. SUBSCRIPTIONCOOKIE cookie;
  265. StrCpyNW(szURL, pwszURL, ARRAYSIZE(szURL));
  266. // Try and get the cookie from the inet db otherwise
  267. // create a new one.
  268. if (*pCookie == CLSID_NULL)
  269. {
  270. CreateCookie(&cookie);
  271. }
  272. else
  273. {
  274. cookie = *pCookie;
  275. }
  276. // Update the inet db
  277. WriteCookieToInetDB(szURL, &cookie, FALSE);
  278. hr = SubscriptionItemFromCookie(TRUE, &cookie, &psi);
  279. if (SUCCEEDED(hr))
  280. {
  281. hr = psi->SetSubscriptionItemInfo(psii);
  282. if (SUCCEEDED(hr) && (nProps > 0))
  283. {
  284. ASSERT(NULL != psi);
  285. hr = psi->WriteProperties(nProps, rgwszName, rgValue);
  286. }
  287. psi->Release();
  288. if (FAILED(hr))
  289. {
  290. DoDeleteSubscriptionItem(&cookie, TRUE);
  291. }
  292. }
  293. *pCookie_ua = cookie_buf;
  294. return hr;
  295. }
  296. HRESULT SubscriptionItemFromCookie(BOOL fCreateNew, const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua,
  297. ISubscriptionItem **ppSubscriptionItem)
  298. {
  299. HRESULT hr;
  300. SUBSCRIPTIONCOOKIE cookie_buf;
  301. SUBSCRIPTIONCOOKIE *pCookie;
  302. //
  303. // Make an aligned copy of pCookie_ua and set a pointer to it.
  304. //
  305. if (pCookie_ua != NULL) {
  306. cookie_buf = *pCookie_ua;
  307. pCookie = &cookie_buf;
  308. } else {
  309. pCookie = NULL;
  310. }
  311. ASSERT((NULL != pCookie) && (NULL != ppSubscriptionItem));
  312. HKEY hkey;
  313. if (OpenItemKey(pCookie, fCreateNew ? TRUE : FALSE, KEY_READ | KEY_WRITE, &hkey))
  314. {
  315. *ppSubscriptionItem = new CSubscriptionItem(pCookie, hkey);
  316. if (NULL != *ppSubscriptionItem)
  317. {
  318. hr = S_OK;
  319. }
  320. else
  321. {
  322. hr = E_OUTOFMEMORY;
  323. }
  324. RegCloseKey(hkey);
  325. }
  326. else
  327. {
  328. *ppSubscriptionItem = NULL;
  329. hr = E_FAIL;
  330. }
  331. return hr;
  332. }
  333. BOOL ItemKeyNameFromCookie(const SUBSCRIPTIONCOOKIE *pCookie,
  334. TCHAR *pszKeyName, DWORD cchKeyName)
  335. {
  336. WCHAR wszGuid[GUIDSTR_MAX];
  337. ASSERT((NULL != pCookie) &&
  338. (NULL != pszKeyName) &&
  339. (cchKeyName >= ARRAYSIZE(WEBCHECK_REGKEY_STORE) + GUIDSTR_MAX));
  340. if (StringFromGUID2(*pCookie, wszGuid, ARRAYSIZE(wszGuid)))
  341. {
  342. wnsprintfW(pszKeyName, cchKeyName, L"%s\\%s", c_szRegKeyStore, wszGuid);
  343. return TRUE;
  344. }
  345. return FALSE;
  346. }
  347. BOOL OpenItemKey(const SUBSCRIPTIONCOOKIE *pCookie, BOOL fCreateNew, REGSAM samDesired, HKEY *phkey)
  348. {
  349. TCHAR szKeyName[MAX_PATH];
  350. ASSERT((NULL != pCookie) && (NULL != phkey));
  351. if (ItemKeyNameFromCookie(pCookie, szKeyName, ARRAYSIZE(szKeyName)))
  352. {
  353. if (fCreateNew)
  354. {
  355. DWORD dwDisposition;
  356. return RegCreateKeyEx(HKEY_CURRENT_USER, szKeyName, 0, NULL, REG_OPTION_NON_VOLATILE,
  357. samDesired, NULL, phkey, &dwDisposition) == ERROR_SUCCESS;
  358. }
  359. else
  360. {
  361. return RegOpenKeyEx(HKEY_CURRENT_USER, szKeyName, 0, samDesired, phkey) == ERROR_SUCCESS;
  362. }
  363. }
  364. return FALSE;
  365. }
  366. // ISubscriptionMgr2 members
  367. STDMETHODIMP CSubscriptionMgr::GetItemFromURL(
  368. /* [in] */ LPCWSTR pwszURL,
  369. /* [out] */ ISubscriptionItem **ppSubscriptionItem)
  370. {
  371. return DoGetItemFromURLW(pwszURL, ppSubscriptionItem);
  372. }
  373. STDMETHODIMP CSubscriptionMgr::GetItemFromCookie(
  374. /* [in] */ const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  375. /* [out] */ ISubscriptionItem **ppSubscriptionItem)
  376. {
  377. if ((NULL == pSubscriptionCookie) ||
  378. (NULL == ppSubscriptionItem))
  379. {
  380. return E_INVALIDARG;
  381. }
  382. return SubscriptionItemFromCookie(FALSE, pSubscriptionCookie, ppSubscriptionItem);
  383. }
  384. STDMETHODIMP CSubscriptionMgr::GetSubscriptionRunState(
  385. /* [in] */ DWORD dwNumCookies,
  386. /* [in] */ const SUBSCRIPTIONCOOKIE *pSubscriptionCookies,
  387. /* [out] */ DWORD *pdwRunState)
  388. {
  389. HRESULT hr;
  390. if ((0 == dwNumCookies) ||
  391. (NULL == pSubscriptionCookies) ||
  392. (NULL == pdwRunState))
  393. {
  394. return E_INVALIDARG;
  395. }
  396. ISubscriptionThrottler *pst;
  397. hr = CoCreateInstance(CLSID_SubscriptionThrottler, NULL,
  398. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  399. IID_ISubscriptionThrottler, (void **)&pst);
  400. if (SUCCEEDED(hr))
  401. {
  402. hr = pst->GetSubscriptionRunState(dwNumCookies, pSubscriptionCookies, pdwRunState);
  403. pst->Release();
  404. }
  405. else
  406. {
  407. // Couldn't connect to a running throttler so assume nothing
  408. // is running.
  409. for (DWORD i = 0; i < dwNumCookies; i++)
  410. {
  411. *pdwRunState++ = 0;
  412. }
  413. hr = S_FALSE;
  414. }
  415. return hr;
  416. }
  417. STDMETHODIMP CSubscriptionMgr::EnumSubscriptions(
  418. /* [in] */ DWORD dwFlags,
  419. /* [out] */ IEnumSubscription **ppEnumSubscriptions)
  420. {
  421. HRESULT hr;
  422. if ((dwFlags & ~SUBSMGRENUM_MASK) || (NULL == ppEnumSubscriptions))
  423. {
  424. return E_INVALIDARG;
  425. }
  426. CEnumSubscription *pes = new CEnumSubscription;
  427. *ppEnumSubscriptions = NULL;
  428. if (NULL != pes)
  429. {
  430. hr = pes->Initialize(dwFlags);
  431. if (SUCCEEDED(hr))
  432. {
  433. hr = pes->QueryInterface(IID_IEnumSubscription, (void **)ppEnumSubscriptions);
  434. }
  435. pes->Release();
  436. }
  437. else
  438. {
  439. hr = E_OUTOFMEMORY;
  440. }
  441. return hr;
  442. }
  443. STDMETHODIMP CSubscriptionMgr::UpdateItems(
  444. /* [in] */ DWORD dwFlags,
  445. /* [in] */ DWORD dwNumCookies,
  446. /* [size_is][in] */ const SUBSCRIPTIONCOOKIE *pCookies)
  447. {
  448. HRESULT hr;
  449. if ((dwFlags & ~SUBSMGRUPDATE_MASK) || (0 == dwNumCookies) || (NULL == pCookies))
  450. {
  451. return E_INVALIDARG;
  452. }
  453. //
  454. // Fail if restrictions are in place.
  455. // FEATURE: Should we have a flag parameter to override this?
  456. //
  457. if (SHRestricted2W(REST_NoManualUpdates, NULL, 0))
  458. {
  459. SGMessageBox(NULL, IDS_RESTRICTED, MB_OK);
  460. return E_ACCESSDENIED;
  461. }
  462. ISyncMgrSynchronizeInvoke *pSyncMgrInvoke;
  463. hr = CoCreateInstance(CLSID_SyncMgr,
  464. NULL,
  465. CLSCTX_ALL,
  466. IID_ISyncMgrSynchronizeInvoke,
  467. (void **)&pSyncMgrInvoke);
  468. if (SUCCEEDED(hr))
  469. {
  470. DWORD dwInvokeFlags = SYNCMGRINVOKE_STARTSYNC;
  471. if (dwFlags & SUBSMGRUPDATE_MINIMIZE)
  472. {
  473. dwInvokeFlags |= SYNCMGRINVOKE_MINIMIZED;
  474. }
  475. hr = pSyncMgrInvoke->UpdateItems(dwInvokeFlags, CLSID_WebCheckOfflineSync,
  476. dwNumCookies * sizeof(SUBSCRIPTIONCOOKIE),
  477. (const BYTE *)pCookies);
  478. pSyncMgrInvoke->Release();
  479. }
  480. return hr;
  481. }
  482. STDMETHODIMP CSubscriptionMgr::AbortItems(
  483. /* [in] */ DWORD dwNumCookies,
  484. /* [size_is][in] */ const SUBSCRIPTIONCOOKIE *pCookies)
  485. {
  486. return DoAbortItems(dwNumCookies, pCookies);
  487. }
  488. STDMETHODIMP CSubscriptionMgr::AbortAll()
  489. {
  490. HRESULT hr;
  491. ISubscriptionThrottler *pst;
  492. hr = CoCreateInstance(CLSID_SubscriptionThrottler, NULL,
  493. CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER,
  494. IID_ISubscriptionThrottler, (void **)&pst);
  495. if (SUCCEEDED(hr))
  496. {
  497. hr = pst->AbortAll();
  498. pst->Release();
  499. }
  500. else
  501. {
  502. hr = S_FALSE;
  503. }
  504. return hr;
  505. }
  506. // ISubscriptionMgrPriv
  507. STDMETHODIMP CSubscriptionMgr::CreateSubscriptionItem(
  508. /* [in] */ const SUBSCRIPTIONITEMINFO *pSubscriptionItemInfo,
  509. /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie,
  510. /* [out] */ ISubscriptionItem **ppSubscriptionItem)
  511. {
  512. return DoCreateSubscriptionItem(pSubscriptionItemInfo, pNewCookie, ppSubscriptionItem);
  513. }
  514. STDMETHODIMP CSubscriptionMgr::CloneSubscriptionItem(
  515. /* [in] */ ISubscriptionItem *pSubscriptionItem,
  516. /* [out] */ SUBSCRIPTIONCOOKIE *pNewCookie,
  517. /* [out] */ ISubscriptionItem **ppSubscriptionItem)
  518. {
  519. return DoCloneSubscriptionItem(pSubscriptionItem, pNewCookie, ppSubscriptionItem);
  520. }
  521. STDMETHODIMP CSubscriptionMgr::DeleteSubscriptionItem(
  522. /* [in] */ const SUBSCRIPTIONCOOKIE *pCookie)
  523. {
  524. return DoDeleteSubscriptionItem(pCookie, TRUE);
  525. }
  526. // ** CEnumSubscription **
  527. CEnumSubscription::CEnumSubscription()
  528. {
  529. ASSERT(NULL == m_pCookies);
  530. ASSERT(0 == m_nCurrent);
  531. ASSERT(0 == m_nCount);
  532. m_cRef = 1;
  533. DllAddRef();
  534. }
  535. CEnumSubscription::~CEnumSubscription()
  536. {
  537. if (NULL != m_pCookies)
  538. {
  539. delete [] m_pCookies;
  540. }
  541. DllRelease();
  542. }
  543. HRESULT CEnumSubscription::Initialize(DWORD dwFlags)
  544. {
  545. HRESULT hr = E_FAIL;
  546. HKEY hkey = NULL;
  547. DWORD dwDisposition;
  548. ASSERT(0 == m_nCount);
  549. if (RegCreateKeyEx(HKEY_CURRENT_USER, c_szRegKeyStore, 0, NULL, REG_OPTION_NON_VOLATILE,
  550. KEY_READ | KEY_WRITE, NULL, &hkey, &dwDisposition) == ERROR_SUCCESS)
  551. {
  552. DWORD nCount;
  553. if (RegQueryInfoKey(hkey,
  554. NULL, // address of buffer for class string
  555. NULL, // address of size of class string buffer
  556. NULL, // reserved
  557. &nCount, // address of buffer for number of subkeys
  558. NULL, // address of buffer for longest subkey name length
  559. NULL, // address of buffer for longest class string length
  560. NULL, // address of buffer for number of value entries
  561. NULL, // address of buffer for longest value name length
  562. NULL, // address of buffer for longest value data length
  563. NULL, // address of buffer for security descriptor length
  564. NULL // address of buffer for last write time
  565. ) == ERROR_SUCCESS)
  566. {
  567. SUBSCRIPTIONCOOKIE Cookie;
  568. m_pCookies = new SUBSCRIPTIONCOOKIE[nCount];
  569. if (NULL != m_pCookies)
  570. {
  571. TCHAR szKeyName[GUIDSTR_MAX];
  572. hr = S_OK;
  573. for (ULONG i = 0; (i < nCount) && (S_OK == hr); i++)
  574. {
  575. if (RegEnumKey(hkey, i, szKeyName, ARRAYSIZE(szKeyName)) ==
  576. ERROR_SUCCESS)
  577. {
  578. HRESULT hrConvert;
  579. hrConvert = CLSIDFromString(szKeyName, &Cookie);
  580. if (SUCCEEDED(hrConvert))
  581. {
  582. ISubscriptionItem *psi;
  583. m_pCookies[m_nCount] = Cookie;
  584. hr = SubscriptionItemFromCookie(FALSE, &Cookie, &psi);
  585. if (SUCCEEDED(hr))
  586. {
  587. SUBSCRIPTIONITEMINFO sii;
  588. sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
  589. if (SUCCEEDED(psi->GetSubscriptionItemInfo(&sii)))
  590. {
  591. // Only count this if it's not a temporary
  592. // or the caller asked for temporary items.
  593. if ((!(sii.dwFlags & SI_TEMPORARY)) ||
  594. (dwFlags & SUBSMGRENUM_TEMP))
  595. {
  596. m_nCount++;
  597. }
  598. }
  599. psi->Release();
  600. }
  601. }
  602. }
  603. }
  604. }
  605. else
  606. {
  607. hr = E_OUTOFMEMORY;
  608. }
  609. }
  610. RegCloseKey(hkey);
  611. }
  612. return hr;
  613. }
  614. // IUnknown members
  615. STDMETHODIMP CEnumSubscription::QueryInterface(REFIID riid, void **ppv)
  616. {
  617. HRESULT hr;
  618. if (NULL == ppv)
  619. {
  620. return E_INVALIDARG;
  621. }
  622. if ((IID_IUnknown == riid) || (IID_IEnumSubscription == riid))
  623. {
  624. *ppv = (IEnumSubscription *)this;
  625. AddRef();
  626. hr = S_OK;
  627. }
  628. else
  629. {
  630. *ppv = NULL;
  631. hr = E_NOINTERFACE;
  632. }
  633. return hr;
  634. }
  635. STDMETHODIMP_(ULONG) CEnumSubscription::AddRef()
  636. {
  637. return ++m_cRef;
  638. }
  639. STDMETHODIMP_(ULONG) CEnumSubscription::Release()
  640. {
  641. if (--m_cRef == 0)
  642. {
  643. delete this;
  644. return 0;
  645. }
  646. return m_cRef;
  647. }
  648. HRESULT CEnumSubscription::CopyRange(ULONG nStart, ULONG nCount,
  649. SUBSCRIPTIONCOOKIE *pCookies, ULONG *pnCopied)
  650. {
  651. ULONG nCopied = 0;
  652. ASSERT((NULL != pCookies) && (NULL != pnCopied));
  653. if (m_nCurrent < m_nCount)
  654. {
  655. ULONG nRemaining = m_nCount - m_nCurrent;
  656. nCopied = min(nRemaining, nCount);
  657. memcpy(pCookies, m_pCookies + m_nCurrent, nCopied * sizeof(SUBSCRIPTIONCOOKIE));
  658. }
  659. *pnCopied = nCopied;
  660. return (nCopied == nCount) ? S_OK : S_FALSE;
  661. }
  662. // IEnumSubscription
  663. STDMETHODIMP CEnumSubscription::Next(
  664. /* [in] */ ULONG celt,
  665. /* [length_is][size_is][out] */ SUBSCRIPTIONCOOKIE *rgelt,
  666. /* [out] */ ULONG *pceltFetched)
  667. {
  668. HRESULT hr;
  669. if ((0 == celt) ||
  670. ((celt > 1) && (NULL == pceltFetched)) ||
  671. (NULL == rgelt))
  672. {
  673. return E_INVALIDARG;
  674. }
  675. DWORD nFetched;
  676. hr = CopyRange(m_nCurrent, celt, rgelt, &nFetched);
  677. m_nCurrent += nFetched;
  678. if (pceltFetched)
  679. {
  680. *pceltFetched = nFetched;
  681. }
  682. return hr;
  683. }
  684. STDMETHODIMP CEnumSubscription::Skip(
  685. /* [in] */ ULONG celt)
  686. {
  687. HRESULT hr;
  688. m_nCurrent += celt;
  689. if (m_nCurrent > (m_nCount - 1))
  690. {
  691. m_nCurrent = m_nCount; // Passed the last one
  692. hr = S_FALSE;
  693. }
  694. else
  695. {
  696. hr = S_OK;
  697. }
  698. return hr;
  699. }
  700. STDMETHODIMP CEnumSubscription::Reset()
  701. {
  702. m_nCurrent = 0;
  703. return S_OK;
  704. }
  705. STDMETHODIMP CEnumSubscription::Clone(
  706. /* [out] */ IEnumSubscription **ppenum)
  707. {
  708. HRESULT hr = E_OUTOFMEMORY;
  709. *ppenum = NULL;
  710. CEnumSubscription *pes = new CEnumSubscription;
  711. if (NULL != pes)
  712. {
  713. pes->m_pCookies = new SUBSCRIPTIONCOOKIE[m_nCount];
  714. if (NULL != pes->m_pCookies)
  715. {
  716. ULONG nFetched;
  717. hr = E_FAIL;
  718. pes->m_nCount = m_nCount;
  719. CopyRange(0, m_nCount, pes->m_pCookies, &nFetched);
  720. ASSERT(m_nCount == nFetched);
  721. if (m_nCount == nFetched)
  722. {
  723. hr = pes->QueryInterface(IID_IEnumSubscription, (void **)ppenum);
  724. }
  725. }
  726. pes->Release();
  727. }
  728. return hr;
  729. }
  730. STDMETHODIMP CEnumSubscription::GetCount(
  731. /* [out] */ ULONG *pnCount)
  732. {
  733. if (NULL == pnCount)
  734. {
  735. return E_INVALIDARG;
  736. }
  737. *pnCount = m_nCount;
  738. return S_OK;
  739. }