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.

953 lines
21 KiB

  1. #include "private.h"
  2. #include "offsync.h"
  3. #include "throttle.h"
  4. #include "helper.h"
  5. #include "subsmgrp.h"
  6. #include <mluisupp.h>
  7. #define TF_THISMODULE TF_DELAGENT
  8. COfflineSync::COfflineSync()
  9. {
  10. // Maintain global count of objects
  11. DllAddRef();
  12. ASSERT(NULL == m_pThrottler);
  13. ASSERT(FALSE == m_fCookiesSpecified);
  14. // Initialize object
  15. m_cRef = 1;
  16. DBG("Creating COfflineSync object");
  17. }
  18. COfflineSync::~COfflineSync()
  19. {
  20. DllRelease();
  21. Cleanup();
  22. DBG("Destroying COfflineSync object");
  23. if (m_pSyncCallback)
  24. {
  25. m_pSyncCallback->Release();
  26. }
  27. SAFERELEASE(m_pSubsMgr2);
  28. }
  29. void COfflineSync::Cleanup()
  30. {
  31. if (NULL != m_pThrottler)
  32. {
  33. m_pThrottler->Unadvise(this);
  34. m_pThrottler->Release();
  35. m_pThrottler = NULL;
  36. }
  37. m_hWndParent = NULL;
  38. if (NULL != m_pSyncCallback)
  39. {
  40. m_pSyncCallback->SynchronizeCompleted(m_hrResult);
  41. }
  42. m_nItemsToRun = 0;
  43. SAFEDELETE(m_pItems);
  44. }
  45. //
  46. // IUnknown members
  47. //
  48. STDMETHODIMP_(ULONG) COfflineSync::AddRef(void)
  49. {
  50. return ++m_cRef;
  51. }
  52. STDMETHODIMP_(ULONG) COfflineSync::Release(void)
  53. {
  54. if( 0L != --m_cRef )
  55. return m_cRef;
  56. delete this;
  57. return 0L;
  58. }
  59. STDMETHODIMP COfflineSync::QueryInterface(REFIID riid, void ** ppv)
  60. {
  61. *ppv=NULL;
  62. // Validate requested interface
  63. if ((IID_IUnknown == riid) ||
  64. (IID_ISyncMgrSynchronize == riid))
  65. {
  66. *ppv = (ISyncMgrSynchronize *)this;
  67. }
  68. else
  69. {
  70. return E_NOINTERFACE;
  71. }
  72. // Addref through the interface
  73. ((LPUNKNOWN)*ppv)->AddRef();
  74. return S_OK;
  75. }
  76. //
  77. // IOfflineSynchronize members
  78. //
  79. HRESULT COfflineSync::Initialize(DWORD dwReserved, DWORD dwSyncFlags,
  80. DWORD cbCookie, const BYTE *lpCookie)
  81. {
  82. HRESULT hr = S_OK;
  83. if (SYNCMGRFLAG_INVOKE == (dwSyncFlags & SYNCMGRFLAG_EVENTMASK) )
  84. {
  85. ASSERT((0 == cbCookie) || (0 == cbCookie % sizeof(SUBSCRIPTIONCOOKIE)));
  86. if ((cbCookie != 0) &&
  87. ((0 != (cbCookie % sizeof(SUBSCRIPTIONCOOKIE))) || (NULL == lpCookie)))
  88. {
  89. return E_INVALIDARG;
  90. }
  91. if (cbCookie > 0)
  92. {
  93. hr = DupItems(cbCookie / sizeof(SUBSCRIPTIONCOOKIE), (SUBSCRIPTIONCOOKIE *)lpCookie);
  94. if (SUCCEEDED(hr))
  95. {
  96. m_fCookiesSpecified = TRUE;
  97. }
  98. }
  99. }
  100. m_dwSyncFlags = dwSyncFlags;
  101. return hr;
  102. }
  103. HRESULT COfflineSync::GetHandlerInfo(LPSYNCMGRHANDLERINFO *ppSyncMgrHandlerInfo)
  104. {
  105. HRESULT hr;
  106. if (NULL == ppSyncMgrHandlerInfo)
  107. {
  108. return E_INVALIDARG;
  109. }
  110. *ppSyncMgrHandlerInfo = (SYNCMGRHANDLERINFO *)CoTaskMemAlloc(sizeof(SYNCMGRHANDLERINFO));
  111. if (NULL != *ppSyncMgrHandlerInfo)
  112. {
  113. (*ppSyncMgrHandlerInfo)->cbSize = sizeof(SYNCMGRHANDLERINFO);
  114. (*ppSyncMgrHandlerInfo)->hIcon = LoadIcon(g_hInst, MAKEINTRESOURCE(IDI_WEBCHECK));
  115. (*ppSyncMgrHandlerInfo)->SyncMgrHandlerFlags = 0; //SYNCMGRHANDLER_HASPROPERTIES
  116. #ifdef UNICODE
  117. MLLoadStringW(IDS_SYNCMGR_NAME,
  118. (*ppSyncMgrHandlerInfo)->wszHandlerName,
  119. ARRAYSIZE((*ppSyncMgrHandlerInfo)->wszHandlerName));
  120. #else
  121. CHAR szHandlerName[sizeof((*ppSyncMgrHandlerInfo)->wszHandlerName)];
  122. MLLoadStringA(IDS_SYNCMGR_NAME, szHandlerName, sizeof(szHandlerName));
  123. MultiByteToWideChar(CP_ACP, 0, szHandlerName, -1,
  124. (*ppSyncMgrHandlerInfo)->wszHandlerName,
  125. ARRAYSIZE((*ppSyncMgrHandlerInfo)->wszHandlerName));
  126. #endif
  127. hr = S_OK;
  128. }
  129. else
  130. {
  131. hr = E_OUTOFMEMORY;
  132. }
  133. return hr;
  134. }
  135. HRESULT COfflineSync::EnumSyncMgrItems(ISyncMgrEnumItems **ppSyncMgrEnumItems)
  136. {
  137. HRESULT hr;
  138. if (NULL == ppSyncMgrEnumItems)
  139. {
  140. return E_INVALIDARG;
  141. }
  142. hr = GetSubsMgr2();
  143. if (SUCCEEDED(hr))
  144. {
  145. COfflineEnum *pEnum = new COfflineEnum();
  146. if (NULL != pEnum)
  147. {
  148. ASSERT(((TRUE == m_fCookiesSpecified) && ((m_nItemsToRun > 0) && (NULL != m_pItems))) ||
  149. ((FALSE == m_fCookiesSpecified) && ((m_nItemsToRun == 0) && (NULL == m_pItems))))
  150. hr = pEnum->Init(m_pSubsMgr2, m_nItemsToRun, m_pItems, ppSyncMgrEnumItems, m_dwSyncFlags);
  151. pEnum->Release();
  152. }
  153. else
  154. {
  155. hr = E_OUTOFMEMORY;
  156. }
  157. }
  158. return hr;
  159. }
  160. HRESULT COfflineSync::GetItemObject(REFSYNCMGRITEMID ItemID, REFIID riid, void **ppv)
  161. {
  162. return E_NOTIMPL;
  163. }
  164. HRESULT COfflineSync::ShowProperties(HWND hWndParent, REFSYNCMGRITEMID ItemID)
  165. {
  166. HRESULT hr = S_OK;
  167. HRESULT hrTmp;
  168. ISubscriptionItem *pSubsItem;
  169. hrTmp = SubscriptionItemFromCookie(FALSE, &ItemID, &pSubsItem);
  170. if (SUCCEEDED(hrTmp))
  171. {
  172. BSTR bstrURL;
  173. hrTmp = ReadBSTR(pSubsItem, c_szPropURL, &bstrURL);
  174. if (SUCCEEDED(hrTmp))
  175. {
  176. ISubscriptionMgr2 *pSubsMgr2;
  177. hrTmp = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  178. IID_ISubscriptionMgr2, (void **)&pSubsMgr2);
  179. if (SUCCEEDED(hrTmp))
  180. {
  181. BOOL bIsSubscribed;
  182. hrTmp = pSubsMgr2->ShowSubscriptionProperties(bstrURL, hWndParent);
  183. if (FAILED(pSubsMgr2->IsSubscribed(bstrURL, &bIsSubscribed)) || !bIsSubscribed)
  184. {
  185. hr = S_SYNCMGR_ITEMDELETED;
  186. }
  187. pSubsMgr2->Release();
  188. }
  189. SysFreeString(bstrURL);
  190. }
  191. pSubsItem->Release();
  192. }
  193. if (NULL != m_pSyncCallback)
  194. {
  195. m_pSyncCallback->ShowPropertiesCompleted(hr);
  196. }
  197. return hr;
  198. }
  199. HRESULT COfflineSync::SetProgressCallback(ISyncMgrSynchronizeCallback *lpCallBack)
  200. {
  201. SAFERELEASE(m_pSyncCallback);
  202. m_pSyncCallback = lpCallBack;
  203. if (m_pSyncCallback)
  204. {
  205. m_pSyncCallback->AddRef();
  206. }
  207. return S_OK;
  208. }
  209. HRESULT COfflineSync::PrepareForSync(ULONG cbNumItems, SYNCMGRITEMID *pItemIDs,
  210. HWND hWndParent, DWORD dwReserved)
  211. {
  212. HRESULT hr;
  213. DBG("PrepareForSync");
  214. if ((0 == cbNumItems) ||
  215. (NULL == pItemIDs))
  216. {
  217. hr = E_INVALIDARG;
  218. }
  219. if (NULL == m_pSyncCallback)
  220. {
  221. return E_UNEXPECTED;
  222. }
  223. hr = DupItems(cbNumItems, pItemIDs);
  224. m_pSyncCallback->PrepareForSyncCompleted(hr);
  225. return hr;
  226. }
  227. HRESULT COfflineSync::Synchronize(HWND hWndParent)
  228. {
  229. HRESULT hr;
  230. m_hrResult = E_FAIL;
  231. m_hWndParent = hWndParent;
  232. hr = CThrottler::GetThrottler(&m_pThrottler);
  233. if (SUCCEEDED(hr))
  234. {
  235. ASSERT(NULL != m_pThrottler);
  236. hr = m_pThrottler->Advise(this);
  237. if (SUCCEEDED(hr))
  238. {
  239. hr = m_pThrottler->RunCookies(m_nItemsToRun, m_pItems, m_dwSyncFlags);
  240. }
  241. // ************************************************************************
  242. // Don't access m_pThrottler after this without checking for NULL since
  243. // we could have released it during the call to RunCookies!
  244. // ************************************************************************
  245. }
  246. if (FAILED(hr))
  247. {
  248. Cleanup();
  249. }
  250. return hr;
  251. }
  252. HRESULT COfflineSync::SetItemStatus(REFSYNCMGRITEMID ItemID, DWORD dwSyncMgrStatus)
  253. {
  254. HRESULT hr = S_OK;
  255. if (NULL != m_pThrottler)
  256. {
  257. switch (dwSyncMgrStatus)
  258. {
  259. case SYNCMGRSTATUS_SKIPPED:
  260. hr = m_pThrottler->AbortItems(1, &ItemID);
  261. break;
  262. case SYNCMGRSTATUS_STOPPED:
  263. hr = m_pThrottler->AbortItems(m_nItemsToRun, m_pItems);
  264. break;
  265. }
  266. }
  267. else
  268. {
  269. ULONG i;
  270. // This means we are getting called before Synchronize is called
  271. switch (dwSyncMgrStatus)
  272. {
  273. case SYNCMGRSTATUS_SKIPPED:
  274. for (i = 0; i < m_nItemsToRun; i++)
  275. {
  276. if (ItemID == m_pItems[i])
  277. {
  278. m_pItems[i] = GUID_NULL;
  279. }
  280. }
  281. break;
  282. case SYNCMGRSTATUS_STOPPED:
  283. m_nItemsToRun = 0;
  284. break;
  285. }
  286. }
  287. return hr;
  288. }
  289. HRESULT COfflineSync::ShowError(HWND hWndParent,REFSYNCMGRERRORID ErrorID)
  290. {
  291. return E_NOTIMPL;
  292. }
  293. HRESULT COfflineSync::UpdateBegin(
  294. const SUBSCRIPTIONCOOKIE *pSubscriptionCookie)
  295. {
  296. UpdateProgress(pSubscriptionCookie, -1, -1, -1, S_OK, NULL);
  297. return S_OK;
  298. }
  299. HRESULT COfflineSync::UpdateProgress(
  300. const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  301. long lSizeDownloaded,
  302. long lProgressCurrent,
  303. long lProgressMax,
  304. HRESULT hrStatus,
  305. LPCWSTR wszStatus)
  306. {
  307. HRESULT hr;
  308. ASSERT(NULL != m_pSyncCallback);
  309. ASSERT(NULL != m_pThrottler);
  310. if ((FindCookie(pSubscriptionCookie) != -1) &&
  311. (NULL != m_pSyncCallback))
  312. {
  313. int iProgValue;
  314. switch (hrStatus)
  315. {
  316. case WC_INTERNAL_S_PAUSED:
  317. iProgValue = SYNCMGRSTATUS_PAUSED;
  318. break;
  319. case WC_INTERNAL_S_RESUMING:
  320. iProgValue = SYNCMGRSTATUS_RESUMING;
  321. break;
  322. case WC_INTERNAL_S_PENDING:
  323. iProgValue = SYNCMGRSTATUS_PENDING;
  324. break;
  325. default:
  326. iProgValue = SYNCMGRSTATUS_UPDATING;
  327. break;
  328. }
  329. CallSyncMgrProgress(pSubscriptionCookie, wszStatus, iProgValue,
  330. lProgressCurrent, lProgressMax);
  331. hr = S_OK;
  332. }
  333. else
  334. {
  335. hr = S_FALSE;
  336. }
  337. return hr;
  338. }
  339. HRESULT COfflineSync::UpdateEnd(
  340. const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  341. long lSizeDownloaded,
  342. HRESULT hrResult,
  343. LPCWSTR wszResult)
  344. {
  345. HRESULT hr;
  346. int index = FindCookie(pSubscriptionCookie);
  347. if (index != -1)
  348. {
  349. DWORD dwStatus;
  350. m_pItems[index] = CLSID_NULL; // Forget about it
  351. m_nItemsCompleted++;
  352. if (SUCCEEDED(hrResult))
  353. {
  354. dwStatus = SYNCMGRSTATUS_SUCCEEDED;
  355. }
  356. else if (E_ABORT == hrResult)
  357. {
  358. dwStatus = SYNCMGRSTATUS_SKIPPED;
  359. }
  360. else
  361. {
  362. dwStatus = SYNCMGRSTATUS_FAILED;
  363. }
  364. CallSyncMgrProgress(pSubscriptionCookie, wszResult, dwStatus, 100, 100);
  365. AreWeDoneYet();
  366. hr = S_OK;
  367. }
  368. else
  369. {
  370. hr = S_FALSE;
  371. }
  372. return hr;
  373. }
  374. STDMETHODIMP COfflineSync::ReportError(
  375. const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  376. HRESULT hrError,
  377. LPCWSTR wszError)
  378. {
  379. HRESULT hr;
  380. if ((FindCookie(pSubscriptionCookie) != -1) &&
  381. (NULL != m_pSyncCallback))
  382. {
  383. DWORD dwErrorLevel;
  384. switch (hrError)
  385. {
  386. case E_ABORT:
  387. dwErrorLevel = SYNCMGRLOGLEVEL_INFORMATION;
  388. break;
  389. case INET_E_AGENT_MAX_SIZE_EXCEEDED:
  390. case INET_E_SCHEDULED_UPDATES_DISABLED:
  391. case INET_E_SCHEDULED_UPDATES_RESTRICTED:
  392. case INET_E_SCHEDULED_UPDATE_INTERVAL:
  393. case INET_E_SCHEDULED_EXCLUDE_RANGE:
  394. case INET_E_AGENT_WARNING:
  395. dwErrorLevel = SYNCMGRLOGLEVEL_WARNING;
  396. break;
  397. default:
  398. dwErrorLevel = FAILED(hrError) ? SYNCMGRLOGLEVEL_ERROR : SYNCMGRLOGLEVEL_INFORMATION;
  399. break;
  400. }
  401. SYNCMGRLOGERRORINFO errInfo;
  402. errInfo.cbSize = sizeof(SYNCMGRLOGERRORINFO);
  403. errInfo.mask = SYNCMGRLOGERROR_ITEMID;
  404. errInfo.ItemID = *pSubscriptionCookie;
  405. m_pSyncCallback->LogError(dwErrorLevel, wszError, &errInfo);
  406. hr = S_OK;
  407. }
  408. else
  409. {
  410. hr = S_FALSE;
  411. }
  412. return hr;
  413. }
  414. HRESULT COfflineSync::CallSyncMgrProgress(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  415. const WCHAR *lpcStatusText, DWORD dwStatusType, INT iProgValue, INT iMaxValue)
  416. {
  417. HRESULT hr = S_OK;
  418. SYNCMGRPROGRESSITEM smpi;
  419. ASSERT(NULL != m_pSyncCallback);
  420. smpi.cbSize = sizeof(SYNCMGRPROGRESSITEM);
  421. smpi.mask = 0;
  422. if (NULL != lpcStatusText)
  423. {
  424. smpi.mask |= SYNCMGRPROGRESSITEM_STATUSTEXT;
  425. smpi.lpcStatusText = lpcStatusText;
  426. }
  427. if ((DWORD)(-1) != dwStatusType)
  428. {
  429. smpi.mask |= SYNCMGRPROGRESSITEM_STATUSTYPE;
  430. smpi.dwStatusType = dwStatusType;
  431. }
  432. if (iProgValue >= 0)
  433. {
  434. smpi.mask |= SYNCMGRPROGRESSITEM_PROGVALUE;
  435. smpi.iProgValue = iProgValue;
  436. }
  437. if (iMaxValue >= 0)
  438. {
  439. smpi.mask |= SYNCMGRPROGRESSITEM_MAXVALUE;
  440. smpi.iMaxValue = iMaxValue;
  441. }
  442. // We still call progress even if smpi.mask is 0 just in case we should
  443. // respond to a cancel.
  444. HRESULT hrProgress = m_pSyncCallback->Progress(*pSubscriptionCookie, &smpi);
  445. switch(hrProgress)
  446. {
  447. case S_SYNCMGR_CANCELITEM:
  448. m_pThrottler->AbortItems(1, pSubscriptionCookie);
  449. break;
  450. case S_SYNCMGR_CANCELALL:
  451. m_pThrottler->AbortAll();
  452. break;
  453. }
  454. return hr;
  455. }
  456. HRESULT COfflineSync::UpdateSyncMgrStatus(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  457. LPCWSTR wszStatusMsg, DWORD dwStatus)
  458. {
  459. HRESULT hr;
  460. if ((FindCookie(pSubscriptionCookie) != -1) &&
  461. (NULL != m_pSyncCallback))
  462. {
  463. CallSyncMgrProgress(pSubscriptionCookie, wszStatusMsg, dwStatus, -1, -1);
  464. hr = S_OK;
  465. }
  466. else
  467. {
  468. hr = S_FALSE;
  469. }
  470. return hr;
  471. }
  472. HRESULT COfflineSync::DupItems(ULONG cbNumItems, SUBSCRIPTIONCOOKIE *pItemIDs)
  473. {
  474. HRESULT hr;
  475. ASSERT(0 != cbNumItems);
  476. ASSERT(NULL != pItemIDs);
  477. ASSERT((0 == m_nItemsToRun) || (TRUE == m_fCookiesSpecified));
  478. if (NULL != m_pItems)
  479. {
  480. delete [] m_pItems;
  481. }
  482. m_pItems = new SUBSCRIPTIONCOOKIE[cbNumItems];
  483. if (NULL != m_pItems)
  484. {
  485. memcpy(m_pItems, pItemIDs, cbNumItems * sizeof(SUBSCRIPTIONCOOKIE));
  486. m_nItemsToRun = cbNumItems;
  487. hr = S_OK;
  488. }
  489. else
  490. {
  491. hr = E_OUTOFMEMORY;
  492. }
  493. return hr;
  494. }
  495. BOOL COfflineSync::AreWeDoneYet()
  496. {
  497. BOOL rc;
  498. if (m_nItemsCompleted != m_nItemsToRun)
  499. {
  500. rc = FALSE;
  501. }
  502. else
  503. {
  504. Cleanup();
  505. rc = TRUE;
  506. }
  507. return rc;
  508. }
  509. HRESULT COfflineSync::GetSubsMgr2()
  510. {
  511. HRESULT hr = S_FALSE;
  512. if (NULL == m_pSubsMgr2)
  513. {
  514. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  515. IID_ISubscriptionMgr2, (void**)&m_pSubsMgr2);
  516. if (FAILED(hr))
  517. {
  518. DBG_WARN("Failed to allocate subscription store (aborting)");
  519. }
  520. }
  521. return hr;
  522. }
  523. // returns index into m_pItems on success, -1 on failure
  524. int COfflineSync::FindCookie(const SUBSCRIPTIONCOOKIE *pCookie)
  525. {
  526. int index = -1;
  527. if (NULL != m_pItems)
  528. {
  529. for (ULONG i = 0; i < m_nItemsToRun; i++)
  530. {
  531. if (m_pItems[i] == *pCookie)
  532. {
  533. index = i;
  534. break;
  535. }
  536. }
  537. }
  538. return index;
  539. }
  540. COfflineEnum::COfflineEnum()
  541. {
  542. ASSERT(NULL == m_pItems);
  543. ASSERT(0 == m_iNumItems);
  544. // Maintain global count of objects
  545. DllAddRef();
  546. // Initialize object
  547. m_cRef = 1;
  548. }
  549. COfflineEnum::~COfflineEnum()
  550. {
  551. DllRelease();
  552. SAFELOCALFREE(m_pItems);
  553. }
  554. HRESULT COfflineEnum::LoadItem(ISubscriptionMgr2 *pSubsMgr2,
  555. const SUBSCRIPTIONCOOKIE *pCookie, SYNCMGRITEM *pItem, DWORD dwItemState)
  556. {
  557. HRESULT hr;
  558. ISubscriptionItem *pSubItem;
  559. ASSERT(NULL != pSubsMgr2);
  560. hr = pSubsMgr2->GetItemFromCookie(pCookie, &pSubItem);
  561. if (SUCCEEDED(hr))
  562. {
  563. BSTR bstrName;
  564. pItem->cbSize = sizeof(SYNCMGRITEM);
  565. pItem->dwFlags = SYNCMGRITEM_HASPROPERTIES;
  566. pItem->ItemID = *pCookie;
  567. pItem->dwItemState = dwItemState;
  568. DATE dt;
  569. if (SUCCEEDED(ReadDATE(pSubItem, c_szPropCompletionTime, &dt)))
  570. {
  571. FILETIME ft;
  572. pItem->dwFlags |= SYNCMGRITEM_LASTUPDATETIME;
  573. VariantTimeToFileTime(dt, ft);
  574. LocalFileTimeToFileTime(&ft, &pItem->ftLastUpdate);
  575. }
  576. ReadBSTR(pSubItem, c_szPropName, &bstrName);
  577. if (NULL != bstrName)
  578. {
  579. StrCpyNW(pItem->wszItemName, bstrName, ARRAYSIZE(pItem->wszItemName));
  580. SysFreeString(bstrName);
  581. }
  582. else
  583. {
  584. ASSERT(L'\0' == pItem->wszItemName[0]);
  585. }
  586. pItem->hIcon = LoadItemIcon(pSubItem, FALSE);
  587. pSubItem->Release();
  588. }
  589. return hr;
  590. }
  591. HRESULT COfflineEnum::Init(ISubscriptionMgr2 *pSubsMgr2, ULONG nItems,
  592. SUBSCRIPTIONCOOKIE *pInitCookies, ISyncMgrEnumItems **ppenum, DWORD dwSyncFlags)
  593. {
  594. HRESULT hr = E_FAIL;
  595. DWORD dwCheckState;
  596. ASSERT(NULL != ppenum);
  597. if ((NULL == pSubsMgr2) ||
  598. (NULL == ppenum) ||
  599. ((nItems > 0) && (pInitCookies == NULL)))
  600. {
  601. return E_UNEXPECTED;
  602. }
  603. switch (dwSyncFlags & SYNCMGRFLAG_EVENTMASK)
  604. {
  605. case SYNCMGRFLAG_CONNECT: // Sync was invoked by a network connect
  606. case SYNCMGRFLAG_PENDINGDISCONNECT: // Sync was invoked by a pending network disconnect
  607. case SYNCMGRFLAG_MANUAL: // Sync was invoked manually
  608. case SYNCMGRFLAG_IDLE: // Sync was programmatically invokd
  609. case SYNCMGRFLAG_INVOKE: // Sync was programmatically invokd
  610. case SYNCMGRFLAG_SCHEDULED: // Sync was invoked by a scheduled update
  611. dwCheckState = SYNCMGRITEMSTATE_CHECKED;
  612. break;
  613. default:
  614. dwCheckState = SYNCMGRITEMSTATE_UNCHECKED;
  615. break;
  616. }
  617. // Enumerate cookies
  618. m_iEnumPtr = 0;
  619. if (0 == nItems)
  620. {
  621. IEnumSubscription *pEnumSubscriptions;
  622. hr = pSubsMgr2->EnumSubscriptions(0, &pEnumSubscriptions);
  623. if (SUCCEEDED(hr))
  624. {
  625. ASSERT(NULL != pEnumSubscriptions);
  626. pEnumSubscriptions->GetCount(&m_iNumItems);
  627. SUBSCRIPTIONCOOKIE *pCookies = (SUBSCRIPTIONCOOKIE *)MemAlloc(LMEM_FIXED,
  628. m_iNumItems * sizeof(SUBSCRIPTIONCOOKIE));
  629. m_pItems = (SYNCMGRITEM *)MemAlloc(LMEM_FIXED, m_iNumItems * sizeof(SYNCMGRITEM));
  630. if ((NULL != m_pItems) && (NULL != pCookies))
  631. {
  632. hr = pEnumSubscriptions->Next(m_iNumItems, pCookies, &m_iNumItems);
  633. SYNCMGRITEM *pItem = m_pItems;
  634. for (ULONG i = 0; i < m_iNumItems; i++, pItem++)
  635. {
  636. hr = LoadItem(pSubsMgr2, &pCookies[i], pItem,
  637. dwCheckState);
  638. if (FAILED(hr))
  639. {
  640. break;
  641. }
  642. }
  643. }
  644. else
  645. {
  646. hr = E_OUTOFMEMORY;
  647. }
  648. SAFELOCALFREE(pCookies);
  649. pEnumSubscriptions->Release();
  650. }
  651. }
  652. else
  653. {
  654. m_pItems = (SYNCMGRITEM *)MemAlloc(LMEM_FIXED, nItems * sizeof(SYNCMGRITEM));
  655. if (NULL != m_pItems)
  656. {
  657. SYNCMGRITEM *pItem = m_pItems;
  658. SUBSCRIPTIONCOOKIE *pCurCookie = pInitCookies;
  659. m_iNumItems = nItems;
  660. for (ULONG i = 0; i < m_iNumItems; i++, pCurCookie++, pItem++)
  661. {
  662. hr = LoadItem(pSubsMgr2, pCurCookie, pItem, dwCheckState);
  663. if (FAILED(hr))
  664. {
  665. break;
  666. }
  667. }
  668. }
  669. else
  670. {
  671. hr = E_OUTOFMEMORY;
  672. }
  673. }
  674. if (SUCCEEDED(hr))
  675. {
  676. // If we were invoked programatically, then tell syncmgr to leave
  677. // item preferences alone.
  678. hr = (nItems == 0) ? S_OK : S_OK; // TODO: S_SYNCMGR_MISSINGITEMS;
  679. *ppenum = this;
  680. AddRef();
  681. }
  682. return hr;
  683. }
  684. //
  685. // IUnknown members
  686. //
  687. STDMETHODIMP_(ULONG) COfflineEnum::AddRef(void)
  688. {
  689. return ++m_cRef;
  690. }
  691. STDMETHODIMP_(ULONG) COfflineEnum::Release(void)
  692. {
  693. if( 0L != --m_cRef )
  694. return m_cRef;
  695. delete this;
  696. return 0L;
  697. }
  698. STDMETHODIMP COfflineEnum::QueryInterface(REFIID riid, void ** ppv)
  699. {
  700. *ppv=NULL;
  701. // Validate requested interface
  702. if ((IID_IUnknown == riid) ||
  703. (IID_ISyncMgrEnumItems == riid))
  704. {
  705. *ppv = (ISyncMgrEnumItems *)this;
  706. }
  707. else
  708. {
  709. return E_NOINTERFACE;
  710. }
  711. // Addref through the interface
  712. ((LPUNKNOWN)*ppv)->AddRef();
  713. return S_OK;
  714. }
  715. // IEnumOfflineItems members
  716. STDMETHODIMP COfflineEnum::Next(ULONG celt, LPSYNCMGRITEM rgelt, ULONG *pceltFetched)
  717. {
  718. if ((0 == celt) ||
  719. ((celt > 1) && (NULL == pceltFetched)) ||
  720. (NULL == rgelt))
  721. {
  722. return E_INVALIDARG;
  723. }
  724. if (!m_pItems)
  725. {
  726. return E_FAIL;
  727. }
  728. *pceltFetched = 0;
  729. ULONG ul;
  730. for (ul=0; (ul<celt) && (m_iEnumPtr<m_iNumItems); m_iEnumPtr++)
  731. {
  732. *rgelt = m_pItems[m_iEnumPtr];
  733. rgelt ++; ul++;
  734. }
  735. *pceltFetched = ul;
  736. return (ul == celt) ? S_OK : S_FALSE;
  737. }
  738. STDMETHODIMP COfflineEnum::Skip(ULONG celt)
  739. {
  740. m_iEnumPtr += celt;
  741. if (m_iEnumPtr > m_iNumItems)
  742. {
  743. m_iEnumPtr = m_iNumItems;
  744. return S_FALSE;
  745. }
  746. return S_OK;
  747. }
  748. STDMETHODIMP COfflineEnum::Reset(void)
  749. {
  750. m_iEnumPtr = 0;
  751. return S_OK;
  752. }
  753. STDMETHODIMP COfflineEnum::Clone(ISyncMgrEnumItems **ppenum)
  754. {
  755. return E_NOTIMPL;
  756. }