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.

872 lines
23 KiB

  1. #include "private.h"
  2. #include "subsmgrp.h"
  3. #include <mluisupp.h>
  4. // These next three are just so we can set the gleam on the channel bar
  5. #include "chanmgr.h"
  6. #include "chanmgrp.h"
  7. #include "shguidp.h" // IID_IChannelMgrPriv
  8. //
  9. #include "helper.h"
  10. #include "propshts.h"
  11. #include "apithk.h"
  12. #define TF_THISMODULE TF_DELAGENT
  13. CDeliveryAgent::CDeliveryAgent()
  14. {
  15. // Maintain global count of objects
  16. DllAddRef();
  17. // Initialize object
  18. m_cRef = 1;
  19. #ifdef AGENT_AUTODIAL
  20. m_iDialerStatus = DIALER_OFFLINE;
  21. #endif
  22. SetEndStatus(INET_S_AGENT_BASIC_SUCCESS);
  23. }
  24. CDeliveryAgent::~CDeliveryAgent()
  25. {
  26. DllRelease();
  27. CleanUp();
  28. }
  29. //
  30. // IUnknown members
  31. //
  32. STDMETHODIMP_(ULONG) CDeliveryAgent::AddRef(void)
  33. {
  34. return ++m_cRef;
  35. }
  36. STDMETHODIMP_(ULONG) CDeliveryAgent::Release(void)
  37. {
  38. if( 0L != --m_cRef )
  39. return m_cRef;
  40. delete this;
  41. return 0L;
  42. }
  43. STDMETHODIMP CDeliveryAgent::QueryInterface(REFIID riid, void ** ppv)
  44. {
  45. *ppv=NULL;
  46. // Validate requested interface
  47. if ((IID_IUnknown == riid) ||
  48. (IID_ISubscriptionAgentControl == riid))
  49. {
  50. *ppv=(ISubscriptionAgentControl *)this;
  51. }
  52. else if (IID_IShellPropSheetExt == riid)
  53. {
  54. *ppv=(IShellPropSheetExt *)this;
  55. }
  56. #ifdef UNICODE
  57. else if (IID_IExtractIconA == riid)
  58. {
  59. *ppv=(IExtractIconA *)this;
  60. }
  61. #endif
  62. else if (IID_IExtractIcon == riid)
  63. {
  64. *ppv=(IExtractIcon *)this;
  65. }
  66. else if (IID_ISubscriptionAgentShellExt == riid)
  67. {
  68. *ppv=(ISubscriptionAgentShellExt *)this;
  69. }
  70. else
  71. {
  72. return E_NOINTERFACE;
  73. }
  74. // Addref through the interface
  75. ((LPUNKNOWN)*ppv)->AddRef();
  76. return S_OK;
  77. }
  78. // IShellPropSheetExt members
  79. HRESULT CDeliveryAgent::RemovePages(HWND hdlg)
  80. {
  81. HRESULT hr = S_OK;
  82. for (int i = 0; i < ARRAYSIZE(m_hPage); i++)
  83. {
  84. if (NULL != m_hPage[i])
  85. {
  86. PropSheet_RemovePage(hdlg, 0, m_hPage[i]);
  87. m_hPage[i] = NULL;
  88. }
  89. }
  90. return hr;
  91. }
  92. HRESULT CDeliveryAgent::SaveSubscription()
  93. {
  94. return SaveBufferChange(m_pBuf, TRUE);
  95. }
  96. HRESULT CDeliveryAgent::URLChange(LPCWSTR pwszNewURL)
  97. {
  98. return E_NOTIMPL;
  99. }
  100. HRESULT CDeliveryAgent::AddPages(LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam)
  101. {
  102. HRESULT hr = S_OK; // optimistic
  103. PROPSHEETPAGE psp;
  104. // initialize propsheet page.
  105. psp.dwSize = sizeof(PROPSHEETPAGE);
  106. psp.dwFlags = PSP_DEFAULT;
  107. psp.hInstance = MLGetHinst();
  108. psp.pszIcon = NULL;
  109. psp.pszTitle = NULL;
  110. psp.lParam = (LPARAM)m_pBuf;
  111. psp.pszTemplate = MAKEINTRESOURCE(IDD_SUBSPROPS_SCHEDULE);
  112. psp.pfnDlgProc = SchedulePropDlgProc;
  113. m_hPage[0] = Whistler_CreatePropertySheetPageW(&psp);
  114. psp.pszTemplate = MAKEINTRESOURCE((m_pBuf->clsidDest == CLSID_ChannelAgent) ?
  115. IDD_SUBSPROPS_DOWNLOAD_CHANNEL :
  116. IDD_SUBSPROPS_DOWNLOAD_URL);
  117. psp.pfnDlgProc = DownloadPropDlgProc;
  118. m_hPage[1] = Whistler_CreatePropertySheetPageW(&psp);
  119. if ((NULL != m_hPage[0]) && (NULL != m_hPage[1]))
  120. {
  121. for (int i = 0; i < ARRAYSIZE(m_hPage); i++)
  122. {
  123. if (!lpfn(m_hPage[i], lParam))
  124. {
  125. hr = E_FAIL;
  126. break;
  127. }
  128. }
  129. }
  130. else
  131. {
  132. hr = E_FAIL;
  133. }
  134. if (FAILED(hr))
  135. {
  136. for (int i = 0; i < ARRAYSIZE(m_hPage); i++)
  137. {
  138. if (NULL != m_hPage[i])
  139. {
  140. DestroyPropertySheetPage(m_hPage[i]);
  141. m_hPage[i] = NULL;
  142. }
  143. }
  144. }
  145. return hr;
  146. }
  147. HRESULT CDeliveryAgent::ReplacePage(UINT pgId, LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam)
  148. {
  149. return E_NOTIMPL;
  150. }
  151. #ifdef UNICODE
  152. // IExtractIconA members
  153. HRESULT CDeliveryAgent::GetIconLocation(UINT uFlags, LPSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags)
  154. {
  155. return IExtractIcon_GetIconLocationThunk((IExtractIconW *)this, uFlags, szIconFile, cchMax, piIndex, pwFlags);
  156. }
  157. HRESULT CDeliveryAgent::Extract(LPCSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize)
  158. {
  159. return IExtractIcon_ExtractThunk((IExtractIconW *)this, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
  160. }
  161. #endif
  162. // IExtractIconT members
  163. HRESULT CDeliveryAgent::GetIconLocation(UINT uFlags, LPTSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags)
  164. {
  165. return E_NOTIMPL;
  166. }
  167. HRESULT CDeliveryAgent::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize)
  168. {
  169. return E_NOTIMPL;
  170. }
  171. HRESULT CDeliveryAgent::Initialize(SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  172. LPCWSTR pwszURL, LPCWSTR pwszName,
  173. SUBSCRIPTIONTYPE subsType)
  174. {
  175. HRESULT hr;
  176. ASSERT(NULL == m_pBuf);
  177. m_pBuf = (POOEBuf)MemAlloc(LPTR, sizeof(OOEBuf));
  178. if (NULL != m_pBuf)
  179. {
  180. ISubscriptionItem *psi;
  181. hr = SubscriptionItemFromCookie(FALSE, pSubscriptionCookie, &psi);
  182. if (SUCCEEDED(hr))
  183. {
  184. DWORD dwSize;
  185. m_SubscriptionCookie = *pSubscriptionCookie;
  186. hr = LoadWithCookie(NULL, m_pBuf, &dwSize, pSubscriptionCookie);
  187. psi->Release();
  188. }
  189. else
  190. {
  191. hr = GetDefaultOOEBuf(m_pBuf, subsType);
  192. MyOleStrToStrN(m_pBuf->m_URL, ARRAYSIZE(m_pBuf->m_URL), pwszURL);
  193. MyOleStrToStrN(m_pBuf->m_Name, ARRAYSIZE(m_pBuf->m_Name), pwszName);
  194. m_pBuf->m_Cookie = *pSubscriptionCookie;
  195. }
  196. }
  197. else
  198. {
  199. hr = E_OUTOFMEMORY;
  200. }
  201. return hr;
  202. }
  203. // ISubscriptionAgentControl members
  204. STDMETHODIMP CDeliveryAgent::StartUpdate(IUnknown *pItem, IUnknown *punkAdvise)
  205. {
  206. HRESULT hr;
  207. DWORD dwTemp;
  208. VARIANT_BOOL fTemp;
  209. m_lSizeDownloadedKB = -1;
  210. SAFERELEASE(m_pAgentEvents);
  211. punkAdvise->QueryInterface(IID_ISubscriptionAgentEvents, (void **)&m_pAgentEvents);
  212. // For now detect either notification or subscription item
  213. if (FAILED(pItem->QueryInterface(IID_ISubscriptionItem, (void **)&m_pSubscriptionItem)))
  214. {
  215. DBG_WARN("CDeliveryAgent::StartUpdate not an ISubscriptionItem!");
  216. return E_FAIL;
  217. }
  218. // We have a subscription item! Use it.
  219. TraceMsg(TF_THISMODULE, "CDeliveryAgent::StartUpdate at thread 0x%08x", GetCurrentThreadId());
  220. ASSERT(!IsAgentFlagSet(FLAG_BUSY));
  221. if (IsAgentFlagSet(FLAG_BUSY))
  222. return E_FAIL;
  223. ASSERT(m_pSubscriptionItem);
  224. SetEndStatus(INET_S_AGENT_BASIC_SUCCESS);
  225. m_dwAgentFlags = 0;
  226. m_pSubscriptionItem->GetCookie(&m_SubscriptionCookie);
  227. if (SUCCEEDED(ReadDWORD(m_pSubscriptionItem, c_szPropAgentFlags, &dwTemp)))
  228. {
  229. ASSERT(!(dwTemp & 0xFFFF0000));
  230. dwTemp &= 0xFFFF; // only let them set lower 16 bits
  231. m_dwAgentFlags |= dwTemp; // set flags client specifies
  232. }
  233. fTemp=FALSE;
  234. ReadBool(m_pSubscriptionItem, c_szPropCrawlChangesOnly, &fTemp);
  235. if (fTemp)
  236. {
  237. SetAgentFlag(FLAG_CHANGESONLY);
  238. }
  239. SetAgentFlag(FLAG_OPSTARTED);
  240. hr = StartOperation();
  241. return hr;
  242. }
  243. STDMETHODIMP CDeliveryAgent::PauseUpdate(DWORD dwFlags)
  244. {
  245. DBG("CDeliveryAgent::PauseUpdate");
  246. if (!IsAgentFlagSet(FLAG_PAUSED | FLAG_WAITING_FOR_INCREASED_CACHE))
  247. {
  248. SetAgentFlag(FLAG_PAUSED);
  249. return AgentPause(dwFlags);
  250. }
  251. return S_FALSE;
  252. }
  253. HRESULT CDeliveryAgent::AgentPause(DWORD dwFlags)
  254. {
  255. return S_OK;
  256. }
  257. STDMETHODIMP CDeliveryAgent::ResumeUpdate(DWORD dwFlags)
  258. {
  259. DBG("CDeliveryAgent::ResumeUpdate");
  260. if (IsAgentFlagSet(FLAG_PAUSED | FLAG_WAITING_FOR_INCREASED_CACHE))
  261. {
  262. if (IsAgentFlagSet(FLAG_WAITING_FOR_INCREASED_CACHE))
  263. dwFlags |= SUBSCRIPTION_AGENT_RESUME_INCREASED_CACHE;
  264. ClearAgentFlag(FLAG_PAUSED | FLAG_WAITING_FOR_INCREASED_CACHE);
  265. return AgentResume(dwFlags);
  266. }
  267. return S_FALSE;
  268. }
  269. HRESULT CDeliveryAgent::AgentResume(DWORD dwFlags)
  270. {
  271. return S_OK;
  272. }
  273. STDMETHODIMP CDeliveryAgent::AbortUpdate(DWORD dwFlags)
  274. {
  275. TraceMsg(TF_THISMODULE, "AbortUpdate at Thread %d", GetCurrentThreadId());
  276. // Fill in status code if someone else hasn't already
  277. if (INET_S_AGENT_BASIC_SUCCESS == GetEndStatus())
  278. {
  279. if (IsAgentFlagSet(FLAG_WAITING_FOR_INCREASED_CACHE))
  280. {
  281. SetEndStatus(INET_E_AGENT_CACHE_SIZE_EXCEEDED);
  282. }
  283. else
  284. {
  285. SetEndStatus(E_ABORT);
  286. }
  287. }
  288. AddRef();
  289. // This may release us if the agent cleans itself up
  290. if (E_PENDING != AgentAbort(dwFlags))
  291. {
  292. // Will call "UpdateEnd" if necessary
  293. CleanUp();
  294. }
  295. Release();
  296. return S_OK;
  297. }
  298. HRESULT CDeliveryAgent::AgentAbort(DWORD dwFlags)
  299. {
  300. return S_OK;
  301. }
  302. HRESULT CDeliveryAgent::SubscriptionControl(IUnknown *pItem, DWORD dwControl)
  303. {
  304. if (dwControl & SUBSCRIPTION_AGENT_DELETE)
  305. {
  306. // Clean up our cache group
  307. GROUPID llGroupID;
  308. ISubscriptionItem *psi=NULL;
  309. pItem->QueryInterface(IID_ISubscriptionItem, (void **)&psi);
  310. if (psi)
  311. {
  312. if (SUCCEEDED(ReadLONGLONG(psi, c_szPropCrawlGroupID, &llGroupID))
  313. && (0 != llGroupID))
  314. {
  315. if (ERROR_SUCCESS != DeleteUrlCacheGroup(llGroupID, 0, 0))
  316. {
  317. DBG_WARN("Failed to delete subscription cache group!");
  318. }
  319. }
  320. psi->Release();
  321. }
  322. }
  323. return S_OK;
  324. }
  325. #ifdef AGENT_AUTODIAL
  326. HRESULT CDeliveryAgent::OnInetOnline()
  327. {
  328. HRESULT hr=S_OK;
  329. if (m_iDialerStatus == DIALER_CONNECTING)
  330. {
  331. DBG("Delivery Agent: connection successful, beginning download");
  332. m_iDialerStatus=DIALER_ONLINE;
  333. hr = DoStartDownload();
  334. }
  335. return hr;
  336. }
  337. #endif
  338. HRESULT CDeliveryAgent::DoStartDownload()
  339. {
  340. HRESULT hr;
  341. // Always reset cache browser session. Webcrawler will avoid downloading dups.
  342. // Reset the cache session to hit the net on urls
  343. // CUrlDownload will use RESYNCHRONIZE flag if SYNC_MODE is Never
  344. InternetSetOption(NULL, INTERNET_OPTION_RESET_URLCACHE_SESSION, NULL, 0);
  345. // Refcount just in case our derived class cleans itself up synchronously, yet
  346. // returns failure (cdlagent)
  347. AddRef();
  348. hr = StartDownload();
  349. if (FAILED(hr))
  350. {
  351. DBG_WARN("DeliveryAgent: StartDownload failed");
  352. if (GetEndStatus() == INET_S_AGENT_BASIC_SUCCESS)
  353. SetEndStatus(hr);
  354. CleanUp();
  355. }
  356. Release();
  357. return hr;
  358. }
  359. #ifdef AGENT_AUTODIAL
  360. HRESULT CDeliveryAgent::OnInetOffline()
  361. {
  362. DBG("DeliveryAgent: received InetOffline, aborting");
  363. m_iDialerStatus=DIALER_OFFLINE;
  364. ASSERT(IsAgentFlagSet(FLAG_BUSY)); // we have send update begin
  365. SetEndStatus(INET_E_AGENT_CONNECTION_FAILED);
  366. // we can look at Status from dialer notification here
  367. AbortUpdate(0);
  368. return S_OK;
  369. }
  370. #endif // AGENT_AUTODIAL
  371. void CDeliveryAgent::SendUpdateBegin()
  372. {
  373. ASSERT(!IsAgentFlagSet(FLAG_BUSY));
  374. ASSERT(m_pAgentEvents);
  375. if (!IsAgentFlagSet(FLAG_BUSY))
  376. {
  377. SetAgentFlag(FLAG_BUSY);
  378. AddRef(); // Keep an additional reference while "busy"
  379. }
  380. // New interface way
  381. m_pAgentEvents->UpdateBegin(&m_SubscriptionCookie);
  382. }
  383. void CDeliveryAgent::SendUpdateProgress(LPCWSTR pwszURL, long lCurrent, long lMax, long lCurSizeKB)
  384. {
  385. ASSERT(IsAgentFlagSet(FLAG_BUSY));
  386. // New interface way
  387. m_pAgentEvents->UpdateProgress(&m_SubscriptionCookie, lCurSizeKB,
  388. lCurrent, lMax, S_OK, pwszURL);
  389. }
  390. void CDeliveryAgent::SendUpdateEnd()
  391. {
  392. ASSERT(m_pSubscriptionItem);
  393. ASSERT(m_pAgentEvents);
  394. UINT uiRes;
  395. ISubscriptionItem *pEndItem=NULL;
  396. LPWSTR pwszEndStatus=NULL;
  397. TCHAR szEndStatus[MAX_RES_STRING_LEN];
  398. WCHAR wszEndStatus[MAX_RES_STRING_LEN];
  399. WriteSCODE(m_pSubscriptionItem, c_szPropStatusCode, GetEndStatus());
  400. if (SUCCEEDED(GetEndStatus()))
  401. {
  402. // Put in end time.
  403. SYSTEMTIME st;
  404. DATE dt;
  405. GetLocalTime(&st);
  406. if (SystemTimeToVariantTime(&st, &dt))
  407. {
  408. // there was no error in GetLocalTime or SystemTimeToVariantTime
  409. WriteDATE(m_pSubscriptionItem, c_szPropCompletionTime, &dt);
  410. }
  411. else
  412. {
  413. SetEndStatus(E_FAIL);
  414. }
  415. }
  416. if (GetEndStatus() == INET_S_AGENT_BASIC_SUCCESS)
  417. SetEndStatus(S_OK);
  418. switch (GetEndStatus())
  419. {
  420. case INET_E_AGENT_MAX_SIZE_EXCEEDED : uiRes = IDS_AGNT_STATUS_SIZELIMIT; break;
  421. case INET_E_AGENT_CACHE_SIZE_EXCEEDED : uiRes = IDS_AGNT_STATUS_CACHELIMIT; break;
  422. case INET_E_AUTHENTICATION_REQUIRED : uiRes = IDS_STATUS_AUTHFAILED; break;
  423. case INET_E_AGENT_CONNECTION_FAILED : uiRes = IDS_STATUS_DIAL_FAIL; break;
  424. case E_OUTOFMEMORY : uiRes = IDS_STATUS_OUTOFMEMORY; break;
  425. case E_INVALIDARG : uiRes = IDS_STATUS_BAD_URL; break;
  426. case E_ABORT : uiRes = IDS_STATUS_ABORTED; break;
  427. case S_FALSE : uiRes = IDS_STATUS_UNCHANGED; break;
  428. default:
  429. if (FAILED(GetEndStatus()))
  430. uiRes = IDS_STATUS_NOT_OK;
  431. else
  432. uiRes = IDS_STATUS_OK;
  433. break;
  434. }
  435. DoCloneSubscriptionItem(m_pSubscriptionItem, NULL, &pEndItem);
  436. ModifyUpdateEnd(pEndItem, &uiRes);
  437. // Write returned uiRes string into end report (returned -1 means don't touch it)
  438. if (uiRes != (UINT)-1)
  439. {
  440. if (MLLoadString(uiRes, szEndStatus, ARRAYSIZE(szEndStatus)))
  441. {
  442. MyStrToOleStrN(wszEndStatus, ARRAYSIZE(wszEndStatus), szEndStatus);
  443. if (pEndItem)
  444. WriteOLESTR(pEndItem, c_szPropStatusString, wszEndStatus);
  445. WriteOLESTR(m_pSubscriptionItem, c_szPropStatusString, wszEndStatus);
  446. pwszEndStatus = wszEndStatus;
  447. }
  448. else
  449. WriteEMPTY(m_pSubscriptionItem, c_szPropStatusString);
  450. }
  451. // ReportError if our end status is an error
  452. if (FAILED(GetEndStatus()))
  453. {
  454. m_pAgentEvents->ReportError(&m_SubscriptionCookie, GetEndStatus(), pwszEndStatus);
  455. }
  456. m_pAgentEvents->UpdateEnd(&m_SubscriptionCookie,
  457. m_lSizeDownloadedKB, GetEndStatus(), pwszEndStatus);
  458. #ifdef AGENTS_AUTODIAL
  459. // Tell the dialer it can hang up now
  460. if (m_pConnAgent != NULL)
  461. NotifyAutoDialer(DIALER_HANGUP);
  462. m_iDialerStatus = DIALER_OFFLINE;
  463. #endif
  464. // Check for appropriate behavior on end item. Don't do anything if we're
  465. // not a subscription in our own right.
  466. if (!IsAgentFlagSet(DELIVERY_AGENT_FLAG_NO_BROADCAST))
  467. {
  468. if (pEndItem)
  469. ProcessEndItem(pEndItem);
  470. else
  471. ProcessEndItem(m_pSubscriptionItem);
  472. }
  473. if (!IsAgentFlagSet(FLAG_HOSTED))
  474. {
  475. m_pSubscriptionItem->NotifyChanged();
  476. }
  477. SAFERELEASE(pEndItem);
  478. if (IsAgentFlagSet(FLAG_BUSY))
  479. {
  480. ClearAgentFlag(FLAG_BUSY);
  481. // Release the reference we had to ourself
  482. Release();
  483. }
  484. }
  485. // This calls callback and cleans everything up properly
  486. void CDeliveryAgent::SendUpdateNone()
  487. {
  488. ASSERT(FAILED(GetEndStatus())); // set this before calling
  489. ASSERT(!IsAgentFlagSet(FLAG_BUSY));// shouldn't call here if busy
  490. AddRef();
  491. if (!IsAgentFlagSet(FLAG_BUSY))
  492. SendUpdateEnd();
  493. CleanUp();
  494. Release();
  495. }
  496. // Process the End Item including all stuff set by the base class
  497. // This has functionality previously in the Tray Agent
  498. // Send email, set gleam, refresh desktop, etc.
  499. HRESULT CDeliveryAgent::ProcessEndItem(ISubscriptionItem *pEndItem)
  500. {
  501. HRESULT hr;
  502. if (SUCCEEDED(GetEndStatus()))
  503. {
  504. //
  505. // Special feature for desktop HTML:
  506. // If we receive an end report with "DesktopComponent=1" in it,
  507. // let the desktop know that it needs to refresh itself. We always
  508. // do this instead of only on "changes detected" because desktop
  509. // component authors don't want to change their CDFs.
  510. //
  511. DWORD dwRet;
  512. HRESULT hr2 = ReadDWORD(pEndItem, c_szPropDesktopComponent, &dwRet);
  513. if (SUCCEEDED(hr2) && (dwRet == 1))
  514. {
  515. IActiveDesktop *pAD = NULL;
  516. hr2 = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pAD);
  517. DBGASSERT(SUCCEEDED(hr2), "Unable to create ActiveDesktop in order to refresh desktop component");
  518. if (SUCCEEDED(hr2))
  519. {
  520. ASSERT(pAD);
  521. pAD->ApplyChanges(AD_APPLY_FORCE | AD_APPLY_REFRESH | AD_APPLY_BUFFERED_REFRESH);
  522. pAD->Release();
  523. }
  524. }
  525. }
  526. //
  527. // Gleam the Internet Shortcut for the URL if requested. (EnableShortcutGleam=1)
  528. // Filter End Reports without changes (S_FALSE)
  529. //
  530. if (SUCCEEDED(GetEndStatus()) && (S_FALSE != GetEndStatus()))
  531. {
  532. DWORD dwRet;
  533. hr = ReadDWORD(pEndItem, c_szPropEnableShortcutGleam, &dwRet);
  534. if (SUCCEEDED(hr) && dwRet)
  535. {
  536. LPTSTR strURL = NULL;
  537. hr = ReadTSTR(pEndItem, c_szPropURL, &strURL);
  538. if (SUCCEEDED(hr))
  539. {
  540. PROPVARIANT propvar;
  541. PropVariantInit(&propvar);
  542. hr = IntSiteHelper(strURL, &c_rgPropRead[PROP_FLAGS], &propvar, 1, FALSE);
  543. if (SUCCEEDED(hr) && (VT_UI4 == propvar.vt))
  544. {
  545. // Set our flag without disturbing the others.
  546. propvar.ulVal |= PIDISF_RECENTLYCHANGED;
  547. }
  548. else
  549. {
  550. // Be sure to clear the variant if it wasn't a DWORD.
  551. PropVariantClear(&propvar);
  552. propvar.vt = VT_UI4;
  553. propvar.ulVal = PIDISF_RECENTLYCHANGED;
  554. }
  555. //
  556. // Update channels (painful).
  557. //
  558. hr = ReadDWORD(pEndItem, c_szPropChannel, &dwRet);
  559. BOOL bChannel = SUCCEEDED(hr) && dwRet;
  560. // REARCHITECT - Once cdfview is fixed, we can fix this.
  561. TCHAR tszChanImgPath[MAX_PATH];
  562. CHAR szChanImgPath[MAX_PATH];
  563. CHAR szChanImgHash[MAX_PATH];
  564. int iChanImgIndex = 0; // init to keep compiler happy
  565. UINT uChanImgFlags = 0; // init to keep compiler happy
  566. int iChanImgImageIndex = 0; // init to keep compiler happy
  567. IChannelMgrPriv* pIChannelMgrPriv = NULL;
  568. HRESULT hr2 = E_FAIL;
  569. if (bChannel)
  570. {
  571. hr2 = GetChannelPath(strURL, tszChanImgPath,
  572. ARRAYSIZE(tszChanImgPath),
  573. &pIChannelMgrPriv);
  574. if (SUCCEEDED(hr2))
  575. {
  576. SHTCharToAnsi(tszChanImgPath, szChanImgPath, ARRAYSIZE(szChanImgPath));
  577. hr2 = (pIChannelMgrPriv)->PreUpdateChannelImage(
  578. szChanImgPath,
  579. szChanImgHash,
  580. &iChanImgIndex,
  581. &uChanImgFlags,
  582. &iChanImgImageIndex);
  583. }
  584. }
  585. // Set the gleam in the intsite database
  586. hr = IntSiteHelper(strURL, &c_rgPropRead[PROP_FLAGS], &propvar, 1, TRUE);
  587. DBGASSERT(SUCCEEDED(hr), "CTrayAgent::OnNotification - failed to set gleam.");
  588. if (bChannel && SUCCEEDED(hr2))
  589. {
  590. ASSERT(pIChannelMgrPriv);
  591. pIChannelMgrPriv->InvalidateCdfCache();
  592. // brilliant - the api requires us to convert their own return value
  593. WCHAR wszHash[MAX_PATH];
  594. SHAnsiToUnicode(szChanImgHash, wszHash, ARRAYSIZE(wszHash));
  595. pIChannelMgrPriv->UpdateChannelImage(
  596. wszHash,
  597. iChanImgIndex,
  598. uChanImgFlags,
  599. iChanImgImageIndex);
  600. }
  601. if (pIChannelMgrPriv)
  602. pIChannelMgrPriv->Release();
  603. }
  604. MemFree(strURL); // Free the string allocated by ReadAnsiSTR().
  605. }// end setting gleam
  606. //
  607. // Send Email to notify the user if requested (EmailNotification=1)
  608. // NOTE: Updates without changes (S_FALSE) were filtered above.
  609. //
  610. hr = ReadDWORD(pEndItem, c_szPropEmailNotf, &dwRet);
  611. if (SUCCEEDED(hr) && dwRet)
  612. {
  613. hr = SendEmailFromItem(pEndItem);
  614. }
  615. }
  616. return S_OK;
  617. }
  618. // Checks the status code after all actions such as authentication and redirections
  619. // have taken place.
  620. HRESULT CDeliveryAgent::CheckResponseCode(DWORD dwHttpResponseCode)
  621. {
  622. TraceMsg(TF_THISMODULE, "CDeliveryAgent processing HTTP status code %d", dwHttpResponseCode);
  623. switch (dwHttpResponseCode / 100)
  624. {
  625. case 1 : DBG("HTTP 1xx response?!?");
  626. case 2 :
  627. return S_OK; // Success
  628. case 3 :
  629. if (dwHttpResponseCode == 304)
  630. return S_OK; // Not Modified
  631. SetEndStatus(E_INVALIDARG);
  632. return E_ABORT; // Redirection
  633. case 4 :
  634. if (dwHttpResponseCode == 401)
  635. {
  636. SetEndStatus(INET_E_AUTHENTICATION_REQUIRED);
  637. return E_ABORT;
  638. }
  639. SetEndStatus(E_INVALIDARG);
  640. return E_ABORT;
  641. case 5 :
  642. default:
  643. SetEndStatus(E_INVALIDARG);
  644. return E_ABORT;
  645. }
  646. /*
  647. // Unreachable code
  648. SetEndStatus(E_FAIL);
  649. return E_FAIL;
  650. */
  651. }
  652. //============================================================
  653. // virtual functions designed to be overridden as necessary
  654. //============================================================
  655. HRESULT CDeliveryAgent::StartOperation()
  656. {
  657. HRESULT hr = S_OK;
  658. #ifdef AGENT_AUTODIAL
  659. // We are ready to go. Now we make sure we're actually connected to
  660. // the internet and then go for it.
  661. if (IsAgentFlagSet(DELIVERY_AGENT_FLAG_SILENT_DIAL))
  662. {
  663. m_iDialerStatus = DIALER_CONNECTING;
  664. hr = NotifyAutoDialer(DIALER_START);
  665. }
  666. if (SUCCEEDED(hr))
  667. {
  668. // Send this whether we're 'dialing' or not
  669. SendUpdateBegin();
  670. }
  671. else
  672. {
  673. DBG("NotifyAutoDialer failed, delivery agent aborting.");
  674. SetEndStatus(E_ACCESSDENIED);
  675. SendUpdateNone();
  676. return E_FAIL;
  677. }
  678. if (IsAgentFlagSet(DELIVERY_AGENT_FLAG_SILENT_DIAL))
  679. {
  680. hr = DoStartDownload();
  681. }
  682. #else
  683. SendUpdateBegin();
  684. hr = DoStartDownload();
  685. #endif
  686. return hr;
  687. }
  688. HRESULT CDeliveryAgent::ModifyUpdateEnd(ISubscriptionItem *pEndItem, UINT *puiRes)
  689. {
  690. return S_OK;
  691. }
  692. void CDeliveryAgent::CleanUp()
  693. {
  694. BOOL fAdded=FALSE;
  695. if (m_cRef > 0)
  696. {
  697. fAdded = TRUE;
  698. AddRef();
  699. }
  700. if (IsAgentFlagSet(FLAG_BUSY))
  701. SendUpdateEnd();
  702. SAFERELEASE(m_pAgentEvents);
  703. SAFERELEASE(m_pSubscriptionItem);
  704. if (fAdded)
  705. Release();
  706. }