873 lines
23 KiB
C++
873 lines
23 KiB
C++
#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;
|
|
}
|
|
#ifdef UNICODE
|
|
else if (IID_IExtractIconA == riid)
|
|
{
|
|
*ppv=(IExtractIconA *)this;
|
|
}
|
|
#endif
|
|
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;
|
|
}
|
|
|
|
#ifdef UNICODE
|
|
// 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);
|
|
}
|
|
#endif
|
|
|
|
// 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();
|
|
}
|