|
|
#define _OLEAUT32_ // get DECLSPEC_IMPORT stuff right for oleaut32.h, we are defing these
#define _WINMM_ // get DECLSPEC_IMPORT stuff right for mmsystem.h, we are defing these
#define _INTSHCUT_ // get DECLSPEC_IMPORT stuff right for intshcut.h, we are defing these
#define _WINX32_ // get DECLSPEC_IMPORT stuff right for wininet.h, we are defing these
#define _URLCACHEAPI_ // get DECLSPEC_IMPORT stuff right for wininet.h, we are defing these
#define INC_OLE2
#include <windows.h>
#include <windowsx.h>
#include <stdio.h>
#include <ccstock.h>
#include <ole2.h>
#include <ole2ver.h>
#include <oleauto.h>
#include <docobj.h>
#include <shlwapi.h>
#include <wininet.h> // INTERNET_MAX_URL_LENGTH. Must be before shlobjp.h!
#include <shlobj.h>
#include <shlobjp.h>
#include <msxml.h>
#include <subsmgr.h>
#include <webcheck.h>
#include "iimgctx.h"
#ifdef _DEBUG
#ifdef _X86_
// Use int 3 so we stop immediately in the source
#define DEBUG_BREAK do { _try { _asm int 3 } _except (EXCEPTION_EXECUTE_HANDLER) {;} } while (0)
#else
#define DEBUG_BREAK do { _try { DebugBreak(); } _except (EXCEPTION_EXECUTE_HANDLER) {;} } while (0)
#endif
#define ASSERT(exp) \
if(!exp) \ { \ printf("ASSERT: %s %s (%s) failed\r\n", __FILE__, __LINE__, TEXT(#exp)); \ DEBUG_BREAK; \ } \
#else
#define ASSERT(exp)
#endif
#define DBGOUT(s) printf("%s\r\n", s)
#ifndef SAFERELEASE
#define SAFERELEASE(p) if ((p) != NULL) { (p)->Release(); (p) = NULL; } else
#endif
#ifndef SAFEFREEBSTR
#define SAFEFREEBSTR(p) if ((p) != NULL) { SysFreeString(p); (p) = NULL; } else
#endif
#ifndef SAFEFREEOLESTR
#define SAFEFREEOLESTR(p) if ((p) != NULL) { CoTaskMemFree(p); (p) = NULL; } else
#endif
#ifndef SAFELOCALFREE
#define SAFELOCALFREE(p) if ((p) != NULL) { LocalFree(p); (p) = NULL; } else
#endif
#ifndef SAFEDELETE
#define SAFEDELETE(p) if ((p) != NULL) { delete (p); (p) = NULL; } else
#endif
#define ON_FAILURE_RETURN(HR) {if(FAILED(HR)) return (HR);}
#define MAX_RES_STRING_LEN 128 // max resource string len for WriteStringRes
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// Notification property names
// Agent Start
extern const WCHAR c_szPropURL[] = L"URL"; extern const WCHAR c_szPropBaseURL[] = L"BaseURL"; extern const WCHAR c_szPropName[] = L"Name"; extern const WCHAR c_szPropPriority[] = L"Priority"; // FEATURE: remove this soon
extern const WCHAR c_szPropAgentFlags[] = L"AgentFlags"; extern const WCHAR c_szPropCrawlLevels[] = L"RecurseLevels"; extern const WCHAR c_szPropCrawlFlags[] = L"RecurseFlags"; extern const WCHAR c_szPropCrawlMaxSize[] = L"MaxSizeKB"; extern const WCHAR c_szPropCrawlChangesOnly[] = L"CheckChangesOnly"; extern const WCHAR c_szPropCrawlExemptPeriod[] = L"ExemptPeriod"; extern const WCHAR c_szPropCrawlUsername[] = L"Username"; extern const WCHAR c_szPropCrawlPassword[] = L"Password"; extern const WCHAR c_szPropEmailNotf[] = L"EmailNotification"; extern const WCHAR c_szPropCrawlLocalDest[] = L"LocalDest"; extern const WCHAR c_szPropCrawlGroupID[] = L"GroupID"; extern const WCHAR c_szPropCrawlActualSize[] = L"ActualSizeKB"; extern const WCHAR c_szPropEnableShortcutGleam[] = L"EnableShortcutGleam"; extern const WCHAR c_szPropCDFStartCookie[] = L"CDFStartCookie"; extern const WCHAR c_szPropChannelFlags[] = L"ChannelFlags"; extern const WCHAR c_szPropAuthMethod[] = L"AuthMethod"; extern const WCHAR c_szPropAuthDomain[] = L"AuthDomain"; extern const WCHAR c_szPropChannel[] = L"Channel"; extern const WCHAR c_szPropDesktopComponent[] = L"DesktopComponent";
// Agent Control
extern const WCHAR c_szPropControlType[] = L"ControlType"; // Progress Report
extern const WCHAR c_szPropProgress[] = L"Progress"; extern const WCHAR c_szPropProgressMax[] = L"ProgressMax"; extern const WCHAR c_szPropCurrentURL[] = L"CurrentURL"; // End Report
extern const WCHAR c_szPropStatusCode[] = L"StatusCode"; extern const WCHAR c_szPropStatusString[] = L"StatusString"; extern const WCHAR c_szPropCompletionTime[] = L"CompletionTime"; extern const WCHAR c_szPropEmailURL[] = L"EmailURL";
// Tray Agent Properties
extern const WCHAR c_szPropGuidsArr[] = L"Guids Array";
// Update Agent Properties
extern const WCHAR c_szTimeStamp[] = L"Update TS";
// Tracking Properties
extern const WCHAR c_szTrackingCookie[] = L"LogGroupID"; extern const WCHAR c_szTrackingPostURL[] = L"PostURL"; extern const WCHAR c_szPostingRetry[] = L"PostFailureRetry"; extern const WCHAR c_szPostHeader[] = L"PostHeader";
// Delivery Agent Properties
extern const WCHAR c_szStartCookie[] = L"StartCookie";
// Initial cookie in AGENT_INIT
extern const WCHAR c_szInitCookie[] = L"InitCookie";
// Helper function protos
int MyOleStrToStrN(LPSTR psz, int cchMultiByte, LPCOLESTR pwsz); int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCSTR psz); HRESULT ReadBSTR(ISubscriptionItem *pItem, LPCWSTR szName, BSTR *bstrRet); HRESULT ReadOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPWSTR *ppszRet); HRESULT ReadAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPSTR *ppszRet); HRESULT ReadBool(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT_BOOL *pBoolRet); HRESULT ReadSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE *pscRet); HRESULT WriteEMPTY(ISubscriptionItem *pItem, LPCWSTR szName); HRESULT WriteSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE scVal); HRESULT ReadDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD *pdwRet); HRESULT ReadLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG *pllRet); HRESULT ReadGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid); HRESULT WriteGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid); HRESULT WriteLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG llVal); HRESULT WriteDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD dwVal); HRESULT ReadDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal); HRESULT WriteDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal); HRESULT ReadVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarRet); HRESULT WriteVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarVal); HRESULT WriteOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCWSTR szVal); HRESULT WriteAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCSTR szVal);
///////////////////////////////////////////////////////////////////////
// CLASSSES
///////////////////////////////////////////////////////////////////////
#if 0
class CConApp;
//////////////////////////////////////////////////////////////////////////
class CRunDeliveryAgentSink { private: int m_iActive; public: CRunDeliveryAgentSink() { m_iActive = 0; }
virtual HRESULT OnAgentBegin() { m_iActive++; return S_OK; }
// OnAgentProgress not currently called
virtual HRESULT OnAgentProgress() { return E_NOTIMPL; } // OnAgentEnd called when agent is complete. fSynchronous means that StartAgent call
// has not yet returned; hrResult will be returned from StartAgent
virtual HRESULT OnAgentEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult, BOOL fSynchronous) { m_iActive--; return S_OK; }
virtual int AgentActive() { return m_iActive; } }; #endif
//////////////////////////////////////////////////////////////////////////
//
// CRunDeliveryAgent object
// Will run a delivery agent and host it for you
// Create, call Init, then call StartAgent
// Use static function SafeRelease to safely release this class.
//
//////////////////////////////////////////////////////////////////////////
class CConApp;
class CRunDeliveryAgent : public ISubscriptionAgentEvents { protected: virtual ~CRunDeliveryAgent();
/// CRunDeliveryAgentSink *m_pParent;
CConApp* m_pParent;
ULONG m_cRef;
ISubscriptionItem *m_pItem; ISubscriptionAgentControl *m_pAgent;
HRESULT m_hrResult; BOOL m_fInStartAgent;
CLSID m_clsidDest; void CleanUp();
public: CRunDeliveryAgent();
HRESULT Init(CConApp *pParent, ISubscriptionItem *pItem, REFCLSID rclsidDest);
inline static void SafeRelease(CRunDeliveryAgent * &pThis) { if (pThis) { pThis->m_pParent=NULL; pThis->Release(); pThis=NULL; } }
HRESULT CreateNewItem(ISubscriptionItem **ppItem, REFCLSID rclsidAgent);
// StartAgent will return E_PENDING if agent is running. Otherwise it will return
// synchronous result code from agent.
HRESULT StartAgent();
HRESULT AgentPause(DWORD dwFlags); HRESULT AgentResume(DWORD dwFlags); HRESULT AgentAbort(DWORD dwFlags);
// IUnknown members
STDMETHODIMP QueryInterface(REFIID riid, void **ppunk); STDMETHODIMP_(ULONG) AddRef(); STDMETHODIMP_(ULONG) Release();
// ISubscriptionAgentEvents members
STDMETHODIMP UpdateBegin(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie); STDMETHODIMP UpdateProgress(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, long lSizeDownloaded, long lProgressCurrent, long lProgressMax, HRESULT hrStatus, LPCWSTR wszStatus); STDMETHODIMP UpdateEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult); STDMETHODIMP ReportError(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, HRESULT hrError, LPCWSTR wszError); };
//---------------------------------------------------------------------
class CConApp { private: int m_argc; char **m_argv; char *m_pszURL; char *m_pRunStr; char *m_pTestName; char m_CmdLine[1024]; int m_iActive; DWORD m_dwTime; // Download time
DWORD m_dwFlags; DWORD m_dwLevels; DWORD m_dwChannel; DWORD m_dwChannelFlags; BOOL m_bVerbose; BOOL m_bPreLoad; BOOL m_bChannelAgent; public: CConApp(int argc, char **argv); ~CConApp(); HRESULT Init(); HRESULT Download(); BOOL PrintResults(); BOOL ParseCommandLine(); void Display_Usage(); BOOL Verbose(); HRESULT MessageLoop();
// Delivery agent events
virtual HRESULT OnAgentBegin(); virtual HRESULT OnAgentProgress(); virtual HRESULT OnAgentEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult, BOOL fSynchronous); };
///////////////////////////////////////////////////////////////////////
// HELPER FUNCTIONS
///////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------
int MyOleStrToStrN(LPSTR psz, int cchMultiByte, LPCOLESTR pwsz) { int i; i=WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz, cchMultiByte, NULL, NULL); if (!i) { DBGOUT("MyOleStrToStrN string too long; truncated"); psz[cchMultiByte-1]=0; } #ifdef DEBUG
else ZeroMemory(psz+i, sizeof(TCHAR)*(cchMultiByte-i)); #endif
return i; }
//---------------------------------------------------------------------
int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCSTR psz) { int i; i=MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cchWideChar); if (!i) { DBGOUT("MyStrToOleStrN string too long; truncated"); pwsz[cchWideChar-1]=0; } #ifdef DEBUG
else ZeroMemory(pwsz+i, sizeof(OLECHAR)*(cchWideChar-i)); #endif
return i; }
//---------------------------------------------------------------------
// Can return S_OK with NULL bstr
HRESULT ReadBSTR(ISubscriptionItem *pItem, LPCWSTR szName, BSTR *bstrRet) { ASSERT(pItem && bstrRet);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_BSTR)) { *bstrRet = Val.bstrVal; return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
*bstrRet = NULL; return E_INVALIDARG; } }
//---------------------------------------------------------------------
// Cannot return S_OK with emptry string
HRESULT ReadOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPWSTR *ppszRet) { HRESULT hr; BSTR bstrRet = NULL; *ppszRet = NULL; hr = ReadBSTR(pItem, szName, &bstrRet); if (SUCCEEDED(hr) && bstrRet && bstrRet[0]) { int len = (lstrlenW(bstrRet) + 1) * sizeof(WCHAR); *ppszRet = (LPWSTR) CoTaskMemAlloc(len); if (*ppszRet) { CopyMemory(*ppszRet, bstrRet, len); } } SAFEFREEBSTR(bstrRet); if (*ppszRet) return S_OK; else return E_FAIL; }
//---------------------------------------------------------------------
HRESULT ReadAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPSTR *ppszRet) { HRESULT hr; BSTR bstrRet = NULL; *ppszRet = NULL; hr = ReadBSTR(pItem, szName, &bstrRet); if (SUCCEEDED(hr) && bstrRet && bstrRet[0]) { // Don't forget to allocate a long string for DBCS.
int len = (lstrlenW(bstrRet) + 1) * sizeof(CHAR) * 2; *ppszRet = (LPSTR) LocalAlloc(NULL, len); if (*ppszRet) { MyOleStrToStrN(*ppszRet, len, bstrRet); } } SAFEFREEBSTR(bstrRet); if (*ppszRet) return S_OK; else return E_FAIL; }
//---------------------------------------------------------------------
HRESULT ReadBool(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT_BOOL *pBoolRet) { ASSERT(pItem && pBoolRet);
VARIANT Val; Val.vt = VT_EMPTY;
// accept VT_I4 or VT_BOOL
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_BOOL || Val.vt==VT_I4)) { if (Val.vt==VT_I4) { if (Val.lVal) *pBoolRet = VARIANT_TRUE; else *pBoolRet = VARIANT_FALSE; } else *pBoolRet = Val.boolVal; return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } }
//---------------------------------------------------------------------
HRESULT ReadSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE *pscRet) { ASSERT(pItem && pscRet);
VARIANT Val;
Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && Val.vt == VT_ERROR) { *pscRet = Val.scode; return S_OK; } else { VariantClear(&Val); return E_INVALIDARG; } }
//---------------------------------------------------------------------
HRESULT WriteEMPTY(ISubscriptionItem *pItem, LPCWSTR szName) { ASSERT(pItem);
VARIANT Val;
Val.vt = VT_EMPTY; return pItem->WriteProperties(1, &szName, &Val); }
//---------------------------------------------------------------------
HRESULT WriteSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE scVal) { ASSERT(pItem);
VARIANT Val;
Val.vt = VT_ERROR; Val.scode = scVal;
return pItem->WriteProperties(1, &szName, &Val); } //---------------------------------------------------------------------
HRESULT ReadDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD *pdwRet) { ASSERT(pItem && pdwRet);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_I4 || Val.vt==VT_I2)) { if (Val.vt==VT_I4) *pdwRet = (DWORD) Val.lVal; else *pdwRet = (DWORD) Val.iVal;
return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } }
//---------------------------------------------------------------------
HRESULT ReadLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG *pllRet) { ASSERT(pItem && pllRet);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_CY)) { *pllRet = *((LONGLONG *) &(Val.cyVal));
return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } } //---------------------------------------------------------------------
HRESULT ReadGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid) { ASSERT(pItem && pGuid);
BSTR bstrGUID = NULL; HRESULT hr = E_INVALIDARG; if (SUCCEEDED(ReadBSTR(pItem, szName, &bstrGUID)) && SUCCEEDED(CLSIDFromString(bstrGUID, pGuid))) { hr = NOERROR; } SAFEFREEBSTR(bstrGUID);
return hr; }
//---------------------------------------------------------------------
HRESULT WriteGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid) { ASSERT(pItem && pGuid); WCHAR wszCookie[GUIDSTR_MAX];
#ifdef DEBUG
int len = #endif
StringFromGUID2(*pGuid, wszCookie, sizeof(wszCookie)); ASSERT(GUIDSTR_MAX == len); return WriteOLESTR(pItem, szName, wszCookie); }
//---------------------------------------------------------------------
HRESULT WriteLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG llVal) { VARIANT Val;
Val.vt = VT_CY; Val.cyVal = *((CY *) &llVal);
return pItem->WriteProperties(1, &szName, &Val); }
//---------------------------------------------------------------------
HRESULT WriteDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD dwVal) { VARIANT Val;
Val.vt = VT_I4; Val.lVal = dwVal;
return pItem->WriteProperties(1, &szName, &Val); }
//---------------------------------------------------------------------
HRESULT ReadDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal) { ASSERT(pItem && dtVal);
VARIANT Val; Val.vt = VT_EMPTY;
if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_DATE)) { *dtVal = Val.date; return S_OK; } else { VariantClear(&Val); // free any return value of wrong type
return E_INVALIDARG; } }
//---------------------------------------------------------------------
HRESULT WriteDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal) { VARIANT Val;
Val.vt = VT_DATE; Val.date= *dtVal;
return pItem->WriteProperties(1, &szName, &Val); }
//---------------------------------------------------------------------
HRESULT ReadVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarRet) { ASSERT(pvarRet->vt == VT_EMPTY); return pItem->ReadProperties(1, &szName, pvarRet); }
//---------------------------------------------------------------------
HRESULT WriteVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarVal) { return pItem->WriteProperties(1, &szName, pvarVal); }
//---------------------------------------------------------------------
HRESULT WriteOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCWSTR szVal) { VARIANT Val;
Val.vt = VT_BSTR; Val.bstrVal = SysAllocString(szVal);
HRESULT hr = pItem->WriteProperties(1, &szName, &Val);
SysFreeString(Val.bstrVal);
return hr; }
//---------------------------------------------------------------------
HRESULT WriteAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCSTR szVal) { VARIANT Val; BSTR bstrVal; int iLen; HRESULT hr;
iLen = lstrlen(szVal); bstrVal = SysAllocStringLen(NULL, iLen); if (bstrVal) { MyStrToOleStrN(bstrVal, iLen + 1, szVal);
Val.vt = VT_BSTR; Val.bstrVal = bstrVal;
hr = pItem->WriteProperties(1, &szName, &Val);
SysFreeString(bstrVal); }
return hr; }
//==============================================================================
// CRunDeliveryAgent provides generic support for synchronous operation of a
// delivery agent
// It is aggregatable so that you can add more interfaces to the callback
//
// Taken from webcheck\cdfagent.cpp
//==============================================================================
CRunDeliveryAgent::CRunDeliveryAgent() { m_cRef = 1; }
//---------------------------------------------------------------------
HRESULT CRunDeliveryAgent::Init(CConApp* pParent, ISubscriptionItem *pItem, REFCLSID rclsidDest) { ASSERT(pParent && pItem);
if (m_pParent || m_pItem) return E_FAIL; // already initialized. can't reuse an instance.
if (!pParent || !pItem) return E_FAIL;
m_pParent = pParent; m_clsidDest = rclsidDest;
m_pItem = pItem; pItem->AddRef();
return S_OK; }
//---------------------------------------------------------------------
CRunDeliveryAgent::~CRunDeliveryAgent() { CleanUp(); }
//
// IUnknown members
//
//---------------------------------------------------------------------
STDMETHODIMP_(ULONG) CRunDeliveryAgent::AddRef(void) { return ++m_cRef; }
//---------------------------------------------------------------------
STDMETHODIMP_(ULONG) CRunDeliveryAgent::Release(void) { if( 0L != --m_cRef ) return m_cRef;
delete this; return 0L; }
//---------------------------------------------------------------------
STDMETHODIMP CRunDeliveryAgent::QueryInterface(REFIID riid, void ** ppv) { *ppv=NULL;
// Validate requested interface
if ((IID_IUnknown == riid) || (IID_ISubscriptionAgentEvents == riid)) { *ppv=(ISubscriptionAgentEvents *)this; } else return E_NOINTERFACE;
// Addref through the interface
((LPUNKNOWN)*ppv)->AddRef();
return S_OK; }
//
// ISubscriptionAgentEvents members
//
//---------------------------------------------------------------------
STDMETHODIMP CRunDeliveryAgent::UpdateBegin(const SUBSCRIPTIONCOOKIE *) { if (m_pParent) m_pParent->OnAgentBegin(); return S_OK; }
//---------------------------------------------------------------------
STDMETHODIMP CRunDeliveryAgent::UpdateProgress( const SUBSCRIPTIONCOOKIE *, long lSizeDownloaded, long lProgressCurrent, long lProgressMax, HRESULT hrStatus, LPCWSTR wszStatus) { if (m_pParent) m_pParent->OnAgentProgress(); return S_OK; }
//---------------------------------------------------------------------
#define INET_S_AGENT_BASIC_SUCCESS _HRESULT_TYPEDEF_(0x000C0F8FL) // From webcheck/delagent.h
STDMETHODIMP CRunDeliveryAgent::UpdateEnd(const SUBSCRIPTIONCOOKIE *pCookie, long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult) { ASSERT((hrResult != INET_S_AGENT_BASIC_SUCCESS) && (hrResult != E_PENDING));
m_hrResult = hrResult; if (hrResult == INET_S_AGENT_BASIC_SUCCESS || hrResult == E_PENDING) { // Shouldn't happen; let's be robust anyway.
m_hrResult = S_OK; }
if (m_pParent) { m_pParent->OnAgentEnd(pCookie, lSizeDownloaded, hrResult, wszResult, m_fInStartAgent); }
CleanUp();
return S_OK; }
//---------------------------------------------------------------------
STDMETHODIMP CRunDeliveryAgent::ReportError( const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, HRESULT hrError, LPCWSTR wszError) { return S_FALSE; }
//---------------------------------------------------------------------
HRESULT CRunDeliveryAgent::StartAgent() { HRESULT hr;
if (!m_pParent || !m_pItem || m_pAgent) return E_FAIL;
AddRef(); // Release before we return from this function
m_fInStartAgent = TRUE;
m_hrResult = INET_S_AGENT_BASIC_SUCCESS;
if(m_pParent->Verbose()) DBGOUT("Using new interfaces to host agent");
ASSERT(!m_pAgent);
hr = CoCreateInstance(m_clsidDest, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionAgentControl, (void **)&m_pAgent);
if (m_pAgent) { hr = m_pAgent->StartUpdate(m_pItem, (ISubscriptionAgentEvents *)this); }
hr = m_hrResult;
m_fInStartAgent = FALSE; Release();
if (hr != INET_S_AGENT_BASIC_SUCCESS) { return hr; }
return E_PENDING; };
//---------------------------------------------------------------------
HRESULT CRunDeliveryAgent::AgentPause(DWORD dwFlags) { if (m_pAgent) return m_pAgent->PauseUpdate(0);
if(m_pParent->Verbose()) DBGOUT("CRunDeliveryAgent::AgentPause with no running agent!!"); return S_FALSE; }
//---------------------------------------------------------------------
HRESULT CRunDeliveryAgent::AgentResume(DWORD dwFlags) { if (m_pAgent) return m_pAgent->ResumeUpdate(0);
if(m_pParent->Verbose()) DBGOUT("CRunDeliveryAgent::AgentResume with no running agent!!");
return E_FAIL; }
//---------------------------------------------------------------------
HRESULT CRunDeliveryAgent::AgentAbort(DWORD dwFlags) { if (m_pAgent) return m_pAgent->AbortUpdate(0);
if(m_pParent->Verbose()) DBGOUT("CRunDeliveryAgent::AgentAbort with no running agent!!"); return S_FALSE; }
//---------------------------------------------------------------------
void CRunDeliveryAgent::CleanUp() { SAFERELEASE(m_pItem); SAFERELEASE(m_pAgent); m_pParent = NULL; }
//---------------------------------------------------------------------
HRESULT CRunDeliveryAgent::CreateNewItem(ISubscriptionItem **ppItem, REFCLSID rclsidAgent) { ISubscriptionMgrPriv *pSubsMgrPriv=NULL; SUBSCRIPTIONITEMINFO info;
*ppItem = NULL;
HRESULT hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgrPriv, (void**)&pSubsMgrPriv);
if (pSubsMgrPriv) { SUBSCRIPTIONCOOKIE cookie;
info.cbSize = sizeof(info); info.dwFlags = SI_TEMPORARY; info.dwPriority = 0; info.ScheduleGroup = GUID_NULL; info.clsidAgent = rclsidAgent;
pSubsMgrPriv->CreateSubscriptionItem(&info, &cookie, ppItem);
pSubsMgrPriv->Release(); } else { printf("CoCreateInstance IID_ISubscriptionMgrPriv failed. hr=0x%x\r\n", hr); }
return (*ppItem) ? S_OK : E_FAIL; }
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
//---------------------------------------------------------------------
CConApp::CConApp(int argc, char **argv) { m_argc = argc; m_argv = argv; m_dwTime = 0; m_pszURL = NULL; m_bVerbose = FALSE; m_bPreLoad = FALSE; m_bChannelAgent = FALSE; m_dwFlags = 3; m_dwLevels = 0; m_dwChannel = 1; m_dwChannelFlags = CHANNEL_AGENT_PRECACHE_ALL; m_pRunStr = NULL; m_pTestName = NULL; m_iActive = 0; }
//---------------------------------------------------------------------
CConApp::~CConApp() { CoUninitialize(); }
//---------------------------------------------------------------------
HRESULT CConApp::Init() { HRESULT hr = CoInitialize(NULL); ON_FAILURE_RETURN(hr); if(!ParseCommandLine()) return(E_FAIL);
return(S_OK); }
//---------------------------------------------------------------------
HRESULT CConApp::Download() { ISubscriptionItem *pSubscriptItem = NULL; IImgCtx *pImgCtx = NULL; IClassFactory *pImageCF = NULL;
if(m_bVerbose) { printf("URL=%s\r\n", m_pszURL); if(m_bPreLoad) printf("Preloading Mshtml\r\n"); if(m_bChannelAgent) printf("ChannelAgent: Channel=%d Flags=0x%x\r\n", m_dwChannel, m_dwChannelFlags); else printf("WebCrawlerAgent: Levels=%d Flags=0x%x\r\n", m_dwFlags, m_dwLevels); } HRESULT hr = S_OK; CLSID clsid;
if (m_bChannelAgent) clsid = CLSID_ChannelAgent; else clsid = CLSID_WebCrawlerAgent;
CRunDeliveryAgent *prda = new CRunDeliveryAgent; hr = prda->CreateNewItem(&pSubscriptItem, clsid); if (FAILED(hr) || !pSubscriptItem) { printf("prda->CreateNewItem failed.\r\n"); return E_FAIL; }
if (!prda || FAILED(prda->Init((CConApp *)this, pSubscriptItem, clsid))) { if (prda) prda->Release(); else printf("new CRunDeliveryAgent failed.\r\n"); return E_FAIL; }
// Preload mshtml
if (m_bPreLoad) { if (FAILED(hr = CoGetClassObject(CLSID_IImgCtx, CLSCTX_SERVER, NULL, IID_IClassFactory, (void **)&pImageCF))) { printf("CoGetClassObject(CLSID_IImgCtx...) failed hr=%x\r\n", hr); return E_FAIL; }
if (FAILED(hr = pImageCF->CreateInstance(NULL, IID_IImgCtx, (void **)&pImgCtx))) { printf("CreateInstance(IID_IImgCtx...) failed hr=%x\r\n", hr); return E_FAIL; } }
// Set properties
if (m_bChannelAgent) { WriteDWORD(pSubscriptItem, c_szPropChannel, m_dwChannel); WriteDWORD(pSubscriptItem, c_szPropChannelFlags, m_dwChannelFlags); } else { WriteDWORD(pSubscriptItem, c_szPropCrawlFlags, m_dwFlags); WriteDWORD(pSubscriptItem, c_szPropCrawlLevels, m_dwLevels); }
// Set url property and start the download
WCHAR wszURL[INTERNET_MAX_URL_LENGTH]; MyStrToOleStrN(wszURL, INTERNET_MAX_URL_LENGTH, m_pszURL); WriteOLESTR(pSubscriptItem, c_szPropURL, wszURL); m_dwTime = GetTickCount(); // Start time
hr = prda->StartAgent(); if (hr == E_PENDING) { hr = S_OK; if (Verbose()) DBGOUT("CRunDeliveryAgent StartAgent succeeded"); MessageLoop(); }
m_dwTime = GetTickCount() - m_dwTime; // End time
// Clean up
if (pSubscriptItem) { pSubscriptItem->Release(); pSubscriptItem = NULL; }
if (pImgCtx) { pImgCtx->Release(); pImgCtx = NULL; }
if (pImageCF) { pImageCF->Release(); pImageCF = NULL; } if (prda) { prda->Release(); prda = NULL; } if (FAILED(hr)) return E_FAIL;
return S_OK; }
//---------------------------------------------------------------------
HRESULT CConApp::MessageLoop() { MSG msg; BOOL dw; // Yield and wait for "UpdateEnd" notification
while (m_iActive > 0 && (dw = ::GetMessage(&msg, NULL, 0, 0))) { ::TranslateMessage(&msg); ::DispatchMessage(&msg); }
if(dw == 0) printf("GetMessage = 0, GLE=%d\r\n", GetLastError());
return S_OK; }
//---------------------------------------------------------------------
BOOL CConApp::PrintResults() { printf("%s, %s, %ld, %ld, %ld %s\r\n", m_pTestName ?m_pTestName :(m_bChannelAgent) ?"Webcheck ChannelAgent" :"Webcheck WebCrawlAgent", m_pRunStr ?m_pRunStr :"1", m_dwTime, 0, // bytes read - future use, matches other tests
0, // kb/sec - future use
m_CmdLine ); return(TRUE); }
//---------------------------------------------------------------------
BOOL CConApp::ParseCommandLine() { BOOL bRC = TRUE; int argc = m_argc; char **argv = m_argv; DWORD dwLen = 0;
*m_CmdLine = '\0';
argv++; argc--; while( argc > 0 && argv[0][0] == '-' ) { switch (argv[0][1]) { case 'c': m_bChannelAgent = TRUE; break; case 'f': m_dwFlags = atoi(&argv[0][2]); break; case 'l': m_dwLevels = atoi(&argv[0][2]); break; case 'p': m_bPreLoad = TRUE; break; case 'r': m_pRunStr = &argv[0][2]; break; case 't': m_pTestName = &argv[0][2]; break; case 'u': m_pszURL = &argv[0][2]; break; case 'v': m_bVerbose = TRUE; break; default: bRC = FALSE; break; } if(bRC) { dwLen += lstrlen(argv[0]) + 1; // length of arg and space
if(dwLen < ((sizeof(m_CmdLine)/sizeof(m_CmdLine[0]))-1)) { lstrcat(m_CmdLine, ","); lstrcat(m_CmdLine, argv[0]); } } argv++; argc--; }
if(!m_pszURL || (bRC == FALSE)) { Display_Usage(); bRC = FALSE; }
return(bRC);
}
//---------------------------------------------------------------------
void CConApp::Display_Usage() { printf("Usage: %s -uURL [Options]\r\n\n", m_argv[0]); printf("Options:\r\n"); printf("\t-c Run ChannelAgent instead of WebCrawl.\r\n"); printf("\t-f# Webcrawl agent flags.\r\n"); printf("\t-l# Delivery agent levels to crawl.\r\n"); printf("\t-p Preload Mshtml.\r\n"); printf("\t-v Turn on verbose output.\r\n"); printf("\t-tStr test name string (used in results output)\n"); printf("\t-rStr run# string (used in results output)\n"); }
//---------------------------------------------------------------------
inline BOOL CConApp::Verbose() { return(m_bVerbose); }
//---------------------------------------------------------------------
HRESULT CConApp::OnAgentBegin() { m_iActive++; return S_OK; }
//---------------------------------------------------------------------
// OnAgentProgress not currently called
HRESULT CConApp::OnAgentProgress() { return E_NOTIMPL; }
//---------------------------------------------------------------------
// OnAgentEnd called when agent is complete. fSynchronous means that StartAgent call
// has not yet returned; hrResult will be returned from StartAgent
HRESULT CConApp::OnAgentEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie, long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult, BOOL fSynchronous) { m_iActive--; return S_OK; }
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
int __cdecl main(int argc, char **argv) { HRESULT hr = S_OK; CConApp App(argc, argv); hr = App.Init(); if(!FAILED(hr)) { hr = App.Download(); App.PrintResults(); }
return((int)hr); }
|