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.

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