windows-nt/Source/XPSP1/NT/shell/ext/webcheck/perf/webckdn/webckdn.cpp

1261 lines
34 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
#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);
}