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.

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