#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 #include #include #include #include #include #include #include #include #include // INTERNET_MAX_URL_LENGTH. Must be before shlobjp.h! #include #include #include #include #include #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); }