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.

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