|
|
#include "private.h"
#include "subsmgrp.h"
#include <mluisupp.h>
// These next three are just so we can set the gleam on the channel bar
#include "chanmgr.h"
#include "chanmgrp.h"
#include "shguidp.h" // IID_IChannelMgrPriv
//
#include "helper.h"
#include "propshts.h"
#include "apithk.h"
#define TF_THISMODULE TF_DELAGENT
CDeliveryAgent::CDeliveryAgent() { // Maintain global count of objects
DllAddRef();
// Initialize object
m_cRef = 1;
#ifdef AGENT_AUTODIAL
m_iDialerStatus = DIALER_OFFLINE; #endif
SetEndStatus(INET_S_AGENT_BASIC_SUCCESS); }
CDeliveryAgent::~CDeliveryAgent() { DllRelease();
CleanUp(); }
//
// IUnknown members
//
STDMETHODIMP_(ULONG) CDeliveryAgent::AddRef(void) { return ++m_cRef; }
STDMETHODIMP_(ULONG) CDeliveryAgent::Release(void) { if( 0L != --m_cRef ) return m_cRef;
delete this; return 0L; }
STDMETHODIMP CDeliveryAgent::QueryInterface(REFIID riid, void ** ppv) {
*ppv=NULL;
// Validate requested interface
if ((IID_IUnknown == riid) || (IID_ISubscriptionAgentControl == riid)) { *ppv=(ISubscriptionAgentControl *)this; } else if (IID_IShellPropSheetExt == riid) { *ppv=(IShellPropSheetExt *)this; } else if (IID_IExtractIconA == riid) { *ppv=(IExtractIconA *)this; } else if (IID_IExtractIcon == riid) { *ppv=(IExtractIcon *)this; } else if (IID_ISubscriptionAgentShellExt == riid) { *ppv=(ISubscriptionAgentShellExt *)this; } else { return E_NOINTERFACE; }
// Addref through the interface
((LPUNKNOWN)*ppv)->AddRef();
return S_OK; }
// IShellPropSheetExt members
HRESULT CDeliveryAgent::RemovePages(HWND hdlg) { HRESULT hr = S_OK;
for (int i = 0; i < ARRAYSIZE(m_hPage); i++) { if (NULL != m_hPage[i]) { PropSheet_RemovePage(hdlg, 0, m_hPage[i]); m_hPage[i] = NULL; } } return hr; }
HRESULT CDeliveryAgent::SaveSubscription() { return SaveBufferChange(m_pBuf, TRUE); }
HRESULT CDeliveryAgent::URLChange(LPCWSTR pwszNewURL) { return E_NOTIMPL; }
HRESULT CDeliveryAgent::AddPages(LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam) { HRESULT hr = S_OK; // optimistic
PROPSHEETPAGE psp;
// initialize propsheet page.
psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT; psp.hInstance = MLGetHinst(); psp.pszIcon = NULL; psp.pszTitle = NULL; psp.lParam = (LPARAM)m_pBuf;
psp.pszTemplate = MAKEINTRESOURCE(IDD_SUBSPROPS_SCHEDULE); psp.pfnDlgProc = SchedulePropDlgProc;
m_hPage[0] = Whistler_CreatePropertySheetPageW(&psp);
psp.pszTemplate = MAKEINTRESOURCE((m_pBuf->clsidDest == CLSID_ChannelAgent) ? IDD_SUBSPROPS_DOWNLOAD_CHANNEL : IDD_SUBSPROPS_DOWNLOAD_URL); psp.pfnDlgProc = DownloadPropDlgProc; m_hPage[1] = Whistler_CreatePropertySheetPageW(&psp);
if ((NULL != m_hPage[0]) && (NULL != m_hPage[1])) { for (int i = 0; i < ARRAYSIZE(m_hPage); i++) { if (!lpfn(m_hPage[i], lParam)) { hr = E_FAIL; break; } } } else { hr = E_FAIL; }
if (FAILED(hr)) { for (int i = 0; i < ARRAYSIZE(m_hPage); i++) { if (NULL != m_hPage[i]) { DestroyPropertySheetPage(m_hPage[i]); m_hPage[i] = NULL; } } }
return hr; }
HRESULT CDeliveryAgent::ReplacePage(UINT pgId, LPFNADDPROPSHEETPAGE lpfn, LPARAM lParam) { return E_NOTIMPL; }
// IExtractIconA members
HRESULT CDeliveryAgent::GetIconLocation(UINT uFlags, LPSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags) { return IExtractIcon_GetIconLocationThunk((IExtractIconW *)this, uFlags, szIconFile, cchMax, piIndex, pwFlags); }
HRESULT CDeliveryAgent::Extract(LPCSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize) { return IExtractIcon_ExtractThunk((IExtractIconW *)this, pszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize); }
// IExtractIconT members
HRESULT CDeliveryAgent::GetIconLocation(UINT uFlags, LPTSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags) { return E_NOTIMPL; }
HRESULT CDeliveryAgent::Extract(LPCTSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize) { return E_NOTIMPL; }
HRESULT CDeliveryAgent::Initialize(SUBSCRIPTIONCOOKIE *pSubscriptionCookie, LPCWSTR pwszURL, LPCWSTR pwszName, SUBSCRIPTIONTYPE subsType) { HRESULT hr;
ASSERT(NULL == m_pBuf);
m_pBuf = (POOEBuf)MemAlloc(LPTR, sizeof(OOEBuf));
if (NULL != m_pBuf) { ISubscriptionItem *psi;
hr = SubscriptionItemFromCookie(FALSE, pSubscriptionCookie, &psi); if (SUCCEEDED(hr)) { DWORD dwSize;
m_SubscriptionCookie = *pSubscriptionCookie;
hr = LoadWithCookie(NULL, m_pBuf, &dwSize, pSubscriptionCookie); psi->Release(); } else { hr = GetDefaultOOEBuf(m_pBuf, subsType); MyOleStrToStrN(m_pBuf->m_URL, ARRAYSIZE(m_pBuf->m_URL), pwszURL); MyOleStrToStrN(m_pBuf->m_Name, ARRAYSIZE(m_pBuf->m_Name), pwszName); m_pBuf->m_Cookie = *pSubscriptionCookie; } } else { hr = E_OUTOFMEMORY; }
return hr; }
// ISubscriptionAgentControl members
STDMETHODIMP CDeliveryAgent::StartUpdate(IUnknown *pItem, IUnknown *punkAdvise) { HRESULT hr; DWORD dwTemp; VARIANT_BOOL fTemp;
m_lSizeDownloadedKB = -1;
SAFERELEASE(m_pAgentEvents); punkAdvise->QueryInterface(IID_ISubscriptionAgentEvents, (void **)&m_pAgentEvents);
// For now detect either notification or subscription item
if (FAILED(pItem->QueryInterface(IID_ISubscriptionItem, (void **)&m_pSubscriptionItem))) { DBG_WARN("CDeliveryAgent::StartUpdate not an ISubscriptionItem!"); return E_FAIL; }
// We have a subscription item! Use it.
TraceMsg(TF_THISMODULE, "CDeliveryAgent::StartUpdate at thread 0x%08x", GetCurrentThreadId());
ASSERT(!IsAgentFlagSet(FLAG_BUSY)); if (IsAgentFlagSet(FLAG_BUSY)) return E_FAIL;
ASSERT(m_pSubscriptionItem);
SetEndStatus(INET_S_AGENT_BASIC_SUCCESS); m_dwAgentFlags = 0;
m_pSubscriptionItem->GetCookie(&m_SubscriptionCookie);
if (SUCCEEDED(ReadDWORD(m_pSubscriptionItem, c_szPropAgentFlags, &dwTemp))) { ASSERT(!(dwTemp & 0xFFFF0000)); dwTemp &= 0xFFFF; // only let them set lower 16 bits
m_dwAgentFlags |= dwTemp; // set flags client specifies
}
fTemp=FALSE; ReadBool(m_pSubscriptionItem, c_szPropCrawlChangesOnly, &fTemp); if (fTemp) { SetAgentFlag(FLAG_CHANGESONLY); }
SetAgentFlag(FLAG_OPSTARTED); hr = StartOperation();
return hr; }
STDMETHODIMP CDeliveryAgent::PauseUpdate(DWORD dwFlags) { DBG("CDeliveryAgent::PauseUpdate");
if (!IsAgentFlagSet(FLAG_PAUSED | FLAG_WAITING_FOR_INCREASED_CACHE)) { SetAgentFlag(FLAG_PAUSED); return AgentPause(dwFlags); }
return S_FALSE; }
HRESULT CDeliveryAgent::AgentPause(DWORD dwFlags) { return S_OK; }
STDMETHODIMP CDeliveryAgent::ResumeUpdate(DWORD dwFlags) { DBG("CDeliveryAgent::ResumeUpdate");
if (IsAgentFlagSet(FLAG_PAUSED | FLAG_WAITING_FOR_INCREASED_CACHE)) { if (IsAgentFlagSet(FLAG_WAITING_FOR_INCREASED_CACHE)) dwFlags |= SUBSCRIPTION_AGENT_RESUME_INCREASED_CACHE;
ClearAgentFlag(FLAG_PAUSED | FLAG_WAITING_FOR_INCREASED_CACHE); return AgentResume(dwFlags); }
return S_FALSE; }
HRESULT CDeliveryAgent::AgentResume(DWORD dwFlags) { return S_OK; }
STDMETHODIMP CDeliveryAgent::AbortUpdate(DWORD dwFlags) { TraceMsg(TF_THISMODULE, "AbortUpdate at Thread %d", GetCurrentThreadId());
// Fill in status code if someone else hasn't already
if (INET_S_AGENT_BASIC_SUCCESS == GetEndStatus()) { if (IsAgentFlagSet(FLAG_WAITING_FOR_INCREASED_CACHE)) { SetEndStatus(INET_E_AGENT_CACHE_SIZE_EXCEEDED); } else { SetEndStatus(E_ABORT); } }
AddRef();
// This may release us if the agent cleans itself up
if (E_PENDING != AgentAbort(dwFlags)) { // Will call "UpdateEnd" if necessary
CleanUp(); }
Release();
return S_OK; }
HRESULT CDeliveryAgent::AgentAbort(DWORD dwFlags) { return S_OK; }
HRESULT CDeliveryAgent::SubscriptionControl(IUnknown *pItem, DWORD dwControl) { if (dwControl & SUBSCRIPTION_AGENT_DELETE) { // Clean up our cache group
GROUPID llGroupID; ISubscriptionItem *psi=NULL;
pItem->QueryInterface(IID_ISubscriptionItem, (void **)&psi); if (psi) { if (SUCCEEDED(ReadLONGLONG(psi, c_szPropCrawlGroupID, &llGroupID)) && (0 != llGroupID)) { if (ERROR_SUCCESS != DeleteUrlCacheGroup(llGroupID, 0, 0)) { DBG_WARN("Failed to delete subscription cache group!"); } }
psi->Release(); } }
return S_OK; }
#ifdef AGENT_AUTODIAL
HRESULT CDeliveryAgent::OnInetOnline() { HRESULT hr=S_OK;
if (m_iDialerStatus == DIALER_CONNECTING) { DBG("Delivery Agent: connection successful, beginning download");
m_iDialerStatus=DIALER_ONLINE;
hr = DoStartDownload(); }
return hr; } #endif
HRESULT CDeliveryAgent::DoStartDownload() { HRESULT hr;
// Always reset cache browser session. Webcrawler will avoid downloading dups.
// Reset the cache session to hit the net on urls
// CUrlDownload will use RESYNCHRONIZE flag if SYNC_MODE is Never
InternetSetOption(NULL, INTERNET_OPTION_RESET_URLCACHE_SESSION, NULL, 0);
// Refcount just in case our derived class cleans itself up synchronously, yet
// returns failure (cdlagent)
AddRef(); hr = StartDownload();
if (FAILED(hr)) { DBG_WARN("DeliveryAgent: StartDownload failed"); if (GetEndStatus() == INET_S_AGENT_BASIC_SUCCESS) SetEndStatus(hr); CleanUp(); }
Release();
return hr; }
#ifdef AGENT_AUTODIAL
HRESULT CDeliveryAgent::OnInetOffline() { DBG("DeliveryAgent: received InetOffline, aborting");
m_iDialerStatus=DIALER_OFFLINE;
ASSERT(IsAgentFlagSet(FLAG_BUSY)); // we have send update begin
SetEndStatus(INET_E_AGENT_CONNECTION_FAILED);
// we can look at Status from dialer notification here
AbortUpdate(0);
return S_OK; } #endif // AGENT_AUTODIAL
void CDeliveryAgent::SendUpdateBegin() { ASSERT(!IsAgentFlagSet(FLAG_BUSY)); ASSERT(m_pAgentEvents);
if (!IsAgentFlagSet(FLAG_BUSY)) { SetAgentFlag(FLAG_BUSY);
AddRef(); // Keep an additional reference while "busy"
}
// New interface way
m_pAgentEvents->UpdateBegin(&m_SubscriptionCookie); }
void CDeliveryAgent::SendUpdateProgress(LPCWSTR pwszURL, long lCurrent, long lMax, long lCurSizeKB) { ASSERT(IsAgentFlagSet(FLAG_BUSY));
// New interface way
m_pAgentEvents->UpdateProgress(&m_SubscriptionCookie, lCurSizeKB, lCurrent, lMax, S_OK, pwszURL); }
void CDeliveryAgent::SendUpdateEnd() { ASSERT(m_pSubscriptionItem); ASSERT(m_pAgentEvents);
UINT uiRes; ISubscriptionItem *pEndItem=NULL; LPWSTR pwszEndStatus=NULL; TCHAR szEndStatus[MAX_RES_STRING_LEN]; WCHAR wszEndStatus[MAX_RES_STRING_LEN];
WriteSCODE(m_pSubscriptionItem, c_szPropStatusCode, GetEndStatus());
if (SUCCEEDED(GetEndStatus())) { // Put in end time.
SYSTEMTIME st; DATE dt;
GetLocalTime(&st); if (SystemTimeToVariantTime(&st, &dt)) { // there was no error in GetLocalTime or SystemTimeToVariantTime
WriteDATE(m_pSubscriptionItem, c_szPropCompletionTime, &dt); } else { SetEndStatus(E_FAIL); } }
if (GetEndStatus() == INET_S_AGENT_BASIC_SUCCESS) SetEndStatus(S_OK);
switch (GetEndStatus()) { case INET_E_AGENT_MAX_SIZE_EXCEEDED : uiRes = IDS_AGNT_STATUS_SIZELIMIT; break; case INET_E_AGENT_CACHE_SIZE_EXCEEDED : uiRes = IDS_AGNT_STATUS_CACHELIMIT; break; case INET_E_AUTHENTICATION_REQUIRED : uiRes = IDS_STATUS_AUTHFAILED; break; case INET_E_AGENT_CONNECTION_FAILED : uiRes = IDS_STATUS_DIAL_FAIL; break; case E_OUTOFMEMORY : uiRes = IDS_STATUS_OUTOFMEMORY; break; case E_INVALIDARG : uiRes = IDS_STATUS_BAD_URL; break; case E_ABORT : uiRes = IDS_STATUS_ABORTED; break; case S_FALSE : uiRes = IDS_STATUS_UNCHANGED; break; default: if (FAILED(GetEndStatus())) uiRes = IDS_STATUS_NOT_OK; else uiRes = IDS_STATUS_OK; break; } DoCloneSubscriptionItem(m_pSubscriptionItem, NULL, &pEndItem);
ModifyUpdateEnd(pEndItem, &uiRes);
// Write returned uiRes string into end report (returned -1 means don't touch it)
if (uiRes != (UINT)-1) { if (MLLoadString(uiRes, szEndStatus, ARRAYSIZE(szEndStatus))) { MyStrToOleStrN(wszEndStatus, ARRAYSIZE(wszEndStatus), szEndStatus); if (pEndItem) WriteOLESTR(pEndItem, c_szPropStatusString, wszEndStatus); WriteOLESTR(m_pSubscriptionItem, c_szPropStatusString, wszEndStatus); pwszEndStatus = wszEndStatus; } else WriteEMPTY(m_pSubscriptionItem, c_szPropStatusString); }
// ReportError if our end status is an error
if (FAILED(GetEndStatus())) { m_pAgentEvents->ReportError(&m_SubscriptionCookie, GetEndStatus(), pwszEndStatus); }
m_pAgentEvents->UpdateEnd(&m_SubscriptionCookie, m_lSizeDownloadedKB, GetEndStatus(), pwszEndStatus);
#ifdef AGENTS_AUTODIAL
// Tell the dialer it can hang up now
if (m_pConnAgent != NULL) NotifyAutoDialer(DIALER_HANGUP);
m_iDialerStatus = DIALER_OFFLINE; #endif
// Check for appropriate behavior on end item. Don't do anything if we're
// not a subscription in our own right.
if (!IsAgentFlagSet(DELIVERY_AGENT_FLAG_NO_BROADCAST)) { if (pEndItem) ProcessEndItem(pEndItem); else ProcessEndItem(m_pSubscriptionItem); }
if (!IsAgentFlagSet(FLAG_HOSTED)) { m_pSubscriptionItem->NotifyChanged(); }
SAFERELEASE(pEndItem);
if (IsAgentFlagSet(FLAG_BUSY)) { ClearAgentFlag(FLAG_BUSY);
// Release the reference we had to ourself
Release(); } }
// This calls callback and cleans everything up properly
void CDeliveryAgent::SendUpdateNone() { ASSERT(FAILED(GetEndStatus())); // set this before calling
ASSERT(!IsAgentFlagSet(FLAG_BUSY));// shouldn't call here if busy
AddRef();
if (!IsAgentFlagSet(FLAG_BUSY)) SendUpdateEnd();
CleanUp();
Release(); }
// Process the End Item including all stuff set by the base class
// This has functionality previously in the Tray Agent
// Send email, set gleam, refresh desktop, etc.
HRESULT CDeliveryAgent::ProcessEndItem(ISubscriptionItem *pEndItem) { HRESULT hr;
if (SUCCEEDED(GetEndStatus())) { //
// Special feature for desktop HTML:
// If we receive an end report with "DesktopComponent=1" in it,
// let the desktop know that it needs to refresh itself. We always
// do this instead of only on "changes detected" because desktop
// component authors don't want to change their CDFs.
//
DWORD dwRet; HRESULT hr2 = ReadDWORD(pEndItem, c_szPropDesktopComponent, &dwRet); if (SUCCEEDED(hr2) && (dwRet == 1)) { IActiveDesktop *pAD = NULL; hr2 = CoCreateInstance(CLSID_ActiveDesktop, NULL, CLSCTX_INPROC_SERVER, IID_IActiveDesktop, (void**)&pAD); DBGASSERT(SUCCEEDED(hr2), "Unable to create ActiveDesktop in order to refresh desktop component"); if (SUCCEEDED(hr2)) { ASSERT(pAD); pAD->ApplyChanges(AD_APPLY_FORCE | AD_APPLY_REFRESH | AD_APPLY_BUFFERED_REFRESH); pAD->Release(); } } }
//
// Gleam the Internet Shortcut for the URL if requested. (EnableShortcutGleam=1)
// Filter End Reports without changes (S_FALSE)
//
if (SUCCEEDED(GetEndStatus()) && (S_FALSE != GetEndStatus())) { DWORD dwRet; hr = ReadDWORD(pEndItem, c_szPropEnableShortcutGleam, &dwRet); if (SUCCEEDED(hr) && dwRet) { LPTSTR strURL = NULL; hr = ReadTSTR(pEndItem, c_szPropURL, &strURL); if (SUCCEEDED(hr)) { PROPVARIANT propvar; PropVariantInit(&propvar); hr = IntSiteHelper(strURL, &c_rgPropRead[PROP_FLAGS], &propvar, 1, FALSE); if (SUCCEEDED(hr) && (VT_UI4 == propvar.vt)) { // Set our flag without disturbing the others.
propvar.ulVal |= PIDISF_RECENTLYCHANGED; } else { // Be sure to clear the variant if it wasn't a DWORD.
PropVariantClear(&propvar); propvar.vt = VT_UI4; propvar.ulVal = PIDISF_RECENTLYCHANGED; }
//
// Update channels (painful).
//
hr = ReadDWORD(pEndItem, c_szPropChannel, &dwRet); BOOL bChannel = SUCCEEDED(hr) && dwRet;
// REARCHITECT - Once cdfview is fixed, we can fix this.
TCHAR tszChanImgPath[MAX_PATH]; CHAR szChanImgPath[MAX_PATH]; CHAR szChanImgHash[MAX_PATH]; int iChanImgIndex = 0; // init to keep compiler happy
UINT uChanImgFlags = 0; // init to keep compiler happy
int iChanImgImageIndex = 0; // init to keep compiler happy
IChannelMgrPriv* pIChannelMgrPriv = NULL; HRESULT hr2 = E_FAIL;
if (bChannel) { hr2 = GetChannelPath(strURL, tszChanImgPath, ARRAYSIZE(tszChanImgPath), &pIChannelMgrPriv); if (SUCCEEDED(hr2)) { SHTCharToAnsi(tszChanImgPath, szChanImgPath, ARRAYSIZE(szChanImgPath)); hr2 = (pIChannelMgrPriv)->PreUpdateChannelImage( szChanImgPath, szChanImgHash, &iChanImgIndex, &uChanImgFlags, &iChanImgImageIndex); } }
// Set the gleam in the intsite database
hr = IntSiteHelper(strURL, &c_rgPropRead[PROP_FLAGS], &propvar, 1, TRUE); DBGASSERT(SUCCEEDED(hr), "CTrayAgent::OnNotification - failed to set gleam.");
if (bChannel && SUCCEEDED(hr2)) { ASSERT(pIChannelMgrPriv);
pIChannelMgrPriv->InvalidateCdfCache(); // brilliant - the api requires us to convert their own return value
WCHAR wszHash[MAX_PATH]; SHAnsiToUnicode(szChanImgHash, wszHash, ARRAYSIZE(wszHash));
pIChannelMgrPriv->UpdateChannelImage( wszHash, iChanImgIndex, uChanImgFlags, iChanImgImageIndex); } if (pIChannelMgrPriv) pIChannelMgrPriv->Release(); } MemFree(strURL); // Free the string allocated by ReadAnsiSTR().
}// end setting gleam
//
// Send Email to notify the user if requested (EmailNotification=1)
// NOTE: Updates without changes (S_FALSE) were filtered above.
//
hr = ReadDWORD(pEndItem, c_szPropEmailNotf, &dwRet); if (SUCCEEDED(hr) && dwRet) { hr = SendEmailFromItem(pEndItem); } }
return S_OK; }
// Checks the status code after all actions such as authentication and redirections
// have taken place.
HRESULT CDeliveryAgent::CheckResponseCode(DWORD dwHttpResponseCode) { TraceMsg(TF_THISMODULE, "CDeliveryAgent processing HTTP status code %d", dwHttpResponseCode);
switch (dwHttpResponseCode / 100) { case 1 : DBG("HTTP 1xx response?!?"); case 2 : return S_OK; // Success
case 3 : if (dwHttpResponseCode == 304) return S_OK; // Not Modified
SetEndStatus(E_INVALIDARG); return E_ABORT; // Redirection
case 4 : if (dwHttpResponseCode == 401) { SetEndStatus(INET_E_AUTHENTICATION_REQUIRED); return E_ABORT; } SetEndStatus(E_INVALIDARG); return E_ABORT;
case 5 : default: SetEndStatus(E_INVALIDARG); return E_ABORT; }
/*
// Unreachable code
SetEndStatus(E_FAIL); return E_FAIL;
*/ }
//============================================================
// virtual functions designed to be overridden as necessary
//============================================================
HRESULT CDeliveryAgent::StartOperation() { HRESULT hr = S_OK;
#ifdef AGENT_AUTODIAL
// We are ready to go. Now we make sure we're actually connected to
// the internet and then go for it.
if (IsAgentFlagSet(DELIVERY_AGENT_FLAG_SILENT_DIAL)) { m_iDialerStatus = DIALER_CONNECTING;
hr = NotifyAutoDialer(DIALER_START); }
if (SUCCEEDED(hr)) { // Send this whether we're 'dialing' or not
SendUpdateBegin(); } else { DBG("NotifyAutoDialer failed, delivery agent aborting."); SetEndStatus(E_ACCESSDENIED); SendUpdateNone(); return E_FAIL; }
if (IsAgentFlagSet(DELIVERY_AGENT_FLAG_SILENT_DIAL)) { hr = DoStartDownload(); } #else
SendUpdateBegin(); hr = DoStartDownload(); #endif
return hr; }
HRESULT CDeliveryAgent::ModifyUpdateEnd(ISubscriptionItem *pEndItem, UINT *puiRes) { return S_OK; }
void CDeliveryAgent::CleanUp() { BOOL fAdded=FALSE;
if (m_cRef > 0) { fAdded = TRUE; AddRef(); }
if (IsAgentFlagSet(FLAG_BUSY)) SendUpdateEnd();
SAFERELEASE(m_pAgentEvents); SAFERELEASE(m_pSubscriptionItem);
if (fAdded) Release(); }
|