Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1260 lines
34 KiB

  1. #define _OLEAUT32_ // get DECLSPEC_IMPORT stuff right for oleaut32.h, we are defing these
  2. #define _WINMM_ // get DECLSPEC_IMPORT stuff right for mmsystem.h, we are defing these
  3. #define _INTSHCUT_ // get DECLSPEC_IMPORT stuff right for intshcut.h, we are defing these
  4. #define _WINX32_ // get DECLSPEC_IMPORT stuff right for wininet.h, we are defing these
  5. #define _URLCACHEAPI_ // get DECLSPEC_IMPORT stuff right for wininet.h, we are defing these
  6. #define INC_OLE2
  7. #include <windows.h>
  8. #include <windowsx.h>
  9. #include <stdio.h>
  10. #include <ccstock.h>
  11. #include <ole2.h>
  12. #include <ole2ver.h>
  13. #include <oleauto.h>
  14. #include <docobj.h>
  15. #include <shlwapi.h>
  16. #include <wininet.h> // INTERNET_MAX_URL_LENGTH. Must be before shlobjp.h!
  17. #include <shlobj.h>
  18. #include <shlobjp.h>
  19. #include <msxml.h>
  20. #include <subsmgr.h>
  21. #include <webcheck.h>
  22. #include "iimgctx.h"
  23. #ifdef _DEBUG
  24. #ifdef _X86_
  25. // Use int 3 so we stop immediately in the source
  26. #define DEBUG_BREAK do { _try { _asm int 3 } _except (EXCEPTION_EXECUTE_HANDLER) {;} } while (0)
  27. #else
  28. #define DEBUG_BREAK do { _try { DebugBreak(); } _except (EXCEPTION_EXECUTE_HANDLER) {;} } while (0)
  29. #endif
  30. #define ASSERT(exp) \
  31. if(!exp) \
  32. { \
  33. printf("ASSERT: %s %s (%s) failed\r\n", __FILE__, __LINE__, TEXT(#exp)); \
  34. DEBUG_BREAK; \
  35. } \
  36. #else
  37. #define ASSERT(exp)
  38. #endif
  39. #define DBGOUT(s) printf("%s\r\n", s)
  40. #ifndef SAFERELEASE
  41. #define SAFERELEASE(p) if ((p) != NULL) { (p)->Release(); (p) = NULL; } else
  42. #endif
  43. #ifndef SAFEFREEBSTR
  44. #define SAFEFREEBSTR(p) if ((p) != NULL) { SysFreeString(p); (p) = NULL; } else
  45. #endif
  46. #ifndef SAFEFREEOLESTR
  47. #define SAFEFREEOLESTR(p) if ((p) != NULL) { CoTaskMemFree(p); (p) = NULL; } else
  48. #endif
  49. #ifndef SAFELOCALFREE
  50. #define SAFELOCALFREE(p) if ((p) != NULL) { LocalFree(p); (p) = NULL; } else
  51. #endif
  52. #ifndef SAFEDELETE
  53. #define SAFEDELETE(p) if ((p) != NULL) { delete (p); (p) = NULL; } else
  54. #endif
  55. #define ON_FAILURE_RETURN(HR) {if(FAILED(HR)) return (HR);}
  56. #define MAX_RES_STRING_LEN 128 // max resource string len for WriteStringRes
  57. ///////////////////////////////////////////////////////////////////////
  58. ///////////////////////////////////////////////////////////////////////
  59. // Notification property names
  60. // Agent Start
  61. extern const WCHAR c_szPropURL[] = L"URL";
  62. extern const WCHAR c_szPropBaseURL[] = L"BaseURL";
  63. extern const WCHAR c_szPropName[] = L"Name";
  64. extern const WCHAR c_szPropPriority[] = L"Priority"; // FEATURE: remove this soon
  65. extern const WCHAR c_szPropAgentFlags[] = L"AgentFlags";
  66. extern const WCHAR c_szPropCrawlLevels[] = L"RecurseLevels";
  67. extern const WCHAR c_szPropCrawlFlags[] = L"RecurseFlags";
  68. extern const WCHAR c_szPropCrawlMaxSize[] = L"MaxSizeKB";
  69. extern const WCHAR c_szPropCrawlChangesOnly[] = L"CheckChangesOnly";
  70. extern const WCHAR c_szPropCrawlExemptPeriod[] = L"ExemptPeriod";
  71. extern const WCHAR c_szPropCrawlUsername[] = L"Username";
  72. extern const WCHAR c_szPropCrawlPassword[] = L"Password";
  73. extern const WCHAR c_szPropEmailNotf[] = L"EmailNotification";
  74. extern const WCHAR c_szPropCrawlLocalDest[] = L"LocalDest";
  75. extern const WCHAR c_szPropCrawlGroupID[] = L"GroupID";
  76. extern const WCHAR c_szPropCrawlActualSize[] = L"ActualSizeKB";
  77. extern const WCHAR c_szPropEnableShortcutGleam[] = L"EnableShortcutGleam";
  78. extern const WCHAR c_szPropCDFStartCookie[] = L"CDFStartCookie";
  79. extern const WCHAR c_szPropChannelFlags[] = L"ChannelFlags";
  80. extern const WCHAR c_szPropAuthMethod[] = L"AuthMethod";
  81. extern const WCHAR c_szPropAuthDomain[] = L"AuthDomain";
  82. extern const WCHAR c_szPropChannel[] = L"Channel";
  83. extern const WCHAR c_szPropDesktopComponent[] = L"DesktopComponent";
  84. // Agent Control
  85. extern const WCHAR c_szPropControlType[] = L"ControlType";
  86. // Progress Report
  87. extern const WCHAR c_szPropProgress[] = L"Progress";
  88. extern const WCHAR c_szPropProgressMax[] = L"ProgressMax";
  89. extern const WCHAR c_szPropCurrentURL[] = L"CurrentURL";
  90. // End Report
  91. extern const WCHAR c_szPropStatusCode[] = L"StatusCode";
  92. extern const WCHAR c_szPropStatusString[] = L"StatusString";
  93. extern const WCHAR c_szPropCompletionTime[] = L"CompletionTime";
  94. extern const WCHAR c_szPropEmailURL[] = L"EmailURL";
  95. // Tray Agent Properties
  96. extern const WCHAR c_szPropGuidsArr[] = L"Guids Array";
  97. // Update Agent Properties
  98. extern const WCHAR c_szTimeStamp[] = L"Update TS";
  99. // Tracking Properties
  100. extern const WCHAR c_szTrackingCookie[] = L"LogGroupID";
  101. extern const WCHAR c_szTrackingPostURL[] = L"PostURL";
  102. extern const WCHAR c_szPostingRetry[] = L"PostFailureRetry";
  103. extern const WCHAR c_szPostHeader[] = L"PostHeader";
  104. // Delivery Agent Properties
  105. extern const WCHAR c_szStartCookie[] = L"StartCookie";
  106. // Initial cookie in AGENT_INIT
  107. extern const WCHAR c_szInitCookie[] = L"InitCookie";
  108. // Helper function protos
  109. int MyOleStrToStrN(LPSTR psz, int cchMultiByte, LPCOLESTR pwsz);
  110. int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCSTR psz);
  111. HRESULT ReadBSTR(ISubscriptionItem *pItem, LPCWSTR szName, BSTR *bstrRet);
  112. HRESULT ReadOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPWSTR *ppszRet);
  113. HRESULT ReadAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPSTR *ppszRet);
  114. HRESULT ReadBool(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT_BOOL *pBoolRet);
  115. HRESULT ReadSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE *pscRet);
  116. HRESULT WriteEMPTY(ISubscriptionItem *pItem, LPCWSTR szName);
  117. HRESULT WriteSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE scVal);
  118. HRESULT ReadDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD *pdwRet);
  119. HRESULT ReadLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG *pllRet);
  120. HRESULT ReadGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid);
  121. HRESULT WriteGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid);
  122. HRESULT WriteLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG llVal);
  123. HRESULT WriteDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD dwVal);
  124. HRESULT ReadDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal);
  125. HRESULT WriteDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal);
  126. HRESULT ReadVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarRet);
  127. HRESULT WriteVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarVal);
  128. HRESULT WriteOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCWSTR szVal);
  129. HRESULT WriteAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCSTR szVal);
  130. ///////////////////////////////////////////////////////////////////////
  131. // CLASSSES
  132. ///////////////////////////////////////////////////////////////////////
  133. #if 0
  134. class CConApp;
  135. //////////////////////////////////////////////////////////////////////////
  136. class CRunDeliveryAgentSink
  137. {
  138. private:
  139. int m_iActive;
  140. public:
  141. CRunDeliveryAgentSink()
  142. {
  143. m_iActive = 0;
  144. }
  145. virtual HRESULT OnAgentBegin()
  146. {
  147. m_iActive++;
  148. return S_OK;
  149. }
  150. // OnAgentProgress not currently called
  151. virtual HRESULT OnAgentProgress()
  152. {
  153. return E_NOTIMPL;
  154. }
  155. // OnAgentEnd called when agent is complete. fSynchronous means that StartAgent call
  156. // has not yet returned; hrResult will be returned from StartAgent
  157. virtual HRESULT OnAgentEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  158. long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult,
  159. BOOL fSynchronous)
  160. {
  161. m_iActive--;
  162. return S_OK;
  163. }
  164. virtual int AgentActive()
  165. {
  166. return m_iActive;
  167. }
  168. };
  169. #endif
  170. //////////////////////////////////////////////////////////////////////////
  171. //
  172. // CRunDeliveryAgent object
  173. // Will run a delivery agent and host it for you
  174. // Create, call Init, then call StartAgent
  175. // Use static function SafeRelease to safely release this class.
  176. //
  177. //////////////////////////////////////////////////////////////////////////
  178. class CConApp;
  179. class CRunDeliveryAgent : public ISubscriptionAgentEvents
  180. {
  181. protected:
  182. virtual ~CRunDeliveryAgent();
  183. /// CRunDeliveryAgentSink *m_pParent;
  184. CConApp* m_pParent;
  185. ULONG m_cRef;
  186. ISubscriptionItem *m_pItem;
  187. ISubscriptionAgentControl *m_pAgent;
  188. HRESULT m_hrResult;
  189. BOOL m_fInStartAgent;
  190. CLSID m_clsidDest;
  191. void CleanUp();
  192. public:
  193. CRunDeliveryAgent();
  194. HRESULT Init(CConApp *pParent, ISubscriptionItem *pItem, REFCLSID rclsidDest);
  195. inline static void SafeRelease(CRunDeliveryAgent * &pThis)
  196. {
  197. if (pThis)
  198. {
  199. pThis->m_pParent=NULL; pThis->Release(); pThis=NULL;
  200. }
  201. }
  202. HRESULT CreateNewItem(ISubscriptionItem **ppItem, REFCLSID rclsidAgent);
  203. // StartAgent will return E_PENDING if agent is running. Otherwise it will return
  204. // synchronous result code from agent.
  205. HRESULT StartAgent();
  206. HRESULT AgentPause(DWORD dwFlags);
  207. HRESULT AgentResume(DWORD dwFlags);
  208. HRESULT AgentAbort(DWORD dwFlags);
  209. // IUnknown members
  210. STDMETHODIMP QueryInterface(REFIID riid, void **ppunk);
  211. STDMETHODIMP_(ULONG) AddRef();
  212. STDMETHODIMP_(ULONG) Release();
  213. // ISubscriptionAgentEvents members
  214. STDMETHODIMP UpdateBegin(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie);
  215. STDMETHODIMP UpdateProgress(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  216. long lSizeDownloaded, long lProgressCurrent, long lProgressMax,
  217. HRESULT hrStatus, LPCWSTR wszStatus);
  218. STDMETHODIMP UpdateEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  219. long lSizeDownloaded,
  220. HRESULT hrResult, LPCWSTR wszResult);
  221. STDMETHODIMP ReportError(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  222. HRESULT hrError, LPCWSTR wszError);
  223. };
  224. //---------------------------------------------------------------------
  225. class CConApp
  226. {
  227. private:
  228. int m_argc;
  229. char **m_argv;
  230. char *m_pszURL;
  231. char *m_pRunStr;
  232. char *m_pTestName;
  233. char m_CmdLine[1024];
  234. int m_iActive;
  235. DWORD m_dwTime; // Download time
  236. DWORD m_dwFlags;
  237. DWORD m_dwLevels;
  238. DWORD m_dwChannel;
  239. DWORD m_dwChannelFlags;
  240. BOOL m_bVerbose;
  241. BOOL m_bPreLoad;
  242. BOOL m_bChannelAgent;
  243. public:
  244. CConApp(int argc, char **argv);
  245. ~CConApp();
  246. HRESULT Init();
  247. HRESULT Download();
  248. BOOL PrintResults();
  249. BOOL ParseCommandLine();
  250. void Display_Usage();
  251. BOOL Verbose();
  252. HRESULT MessageLoop();
  253. // Delivery agent events
  254. virtual HRESULT OnAgentBegin();
  255. virtual HRESULT OnAgentProgress();
  256. virtual HRESULT OnAgentEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  257. long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult,
  258. BOOL fSynchronous);
  259. };
  260. ///////////////////////////////////////////////////////////////////////
  261. // HELPER FUNCTIONS
  262. ///////////////////////////////////////////////////////////////////////
  263. //---------------------------------------------------------------------
  264. int MyOleStrToStrN(LPSTR psz, int cchMultiByte, LPCOLESTR pwsz)
  265. {
  266. int i;
  267. i=WideCharToMultiByte(CP_ACP, 0, pwsz, -1, psz,
  268. cchMultiByte, NULL, NULL);
  269. if (!i)
  270. {
  271. DBGOUT("MyOleStrToStrN string too long; truncated");
  272. psz[cchMultiByte-1]=0;
  273. }
  274. #ifdef DEBUG
  275. else
  276. ZeroMemory(psz+i, sizeof(TCHAR)*(cchMultiByte-i));
  277. #endif
  278. return i;
  279. }
  280. //---------------------------------------------------------------------
  281. int MyStrToOleStrN(LPOLESTR pwsz, int cchWideChar, LPCSTR psz)
  282. {
  283. int i;
  284. i=MultiByteToWideChar(CP_ACP, 0, psz, -1, pwsz, cchWideChar);
  285. if (!i)
  286. {
  287. DBGOUT("MyStrToOleStrN string too long; truncated");
  288. pwsz[cchWideChar-1]=0;
  289. }
  290. #ifdef DEBUG
  291. else
  292. ZeroMemory(pwsz+i, sizeof(OLECHAR)*(cchWideChar-i));
  293. #endif
  294. return i;
  295. }
  296. //---------------------------------------------------------------------
  297. // Can return S_OK with NULL bstr
  298. HRESULT ReadBSTR(ISubscriptionItem *pItem, LPCWSTR szName, BSTR *bstrRet)
  299. {
  300. ASSERT(pItem && bstrRet);
  301. VARIANT Val;
  302. Val.vt = VT_EMPTY;
  303. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  304. (Val.vt==VT_BSTR))
  305. {
  306. *bstrRet = Val.bstrVal;
  307. return S_OK;
  308. }
  309. else
  310. {
  311. VariantClear(&Val); // free any return value of wrong type
  312. *bstrRet = NULL;
  313. return E_INVALIDARG;
  314. }
  315. }
  316. //---------------------------------------------------------------------
  317. // Cannot return S_OK with emptry string
  318. HRESULT ReadOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPWSTR *ppszRet)
  319. {
  320. HRESULT hr;
  321. BSTR bstrRet = NULL;
  322. *ppszRet = NULL;
  323. hr = ReadBSTR(pItem, szName, &bstrRet);
  324. if (SUCCEEDED(hr) && bstrRet && bstrRet[0])
  325. {
  326. int len = (lstrlenW(bstrRet) + 1) * sizeof(WCHAR);
  327. *ppszRet = (LPWSTR) CoTaskMemAlloc(len);
  328. if (*ppszRet)
  329. {
  330. CopyMemory(*ppszRet, bstrRet, len);
  331. }
  332. }
  333. SAFEFREEBSTR(bstrRet);
  334. if (*ppszRet)
  335. return S_OK;
  336. else
  337. return E_FAIL;
  338. }
  339. //---------------------------------------------------------------------
  340. HRESULT ReadAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPSTR *ppszRet)
  341. {
  342. HRESULT hr;
  343. BSTR bstrRet = NULL;
  344. *ppszRet = NULL;
  345. hr = ReadBSTR(pItem, szName, &bstrRet);
  346. if (SUCCEEDED(hr) && bstrRet && bstrRet[0])
  347. {
  348. // Don't forget to allocate a long string for DBCS.
  349. int len = (lstrlenW(bstrRet) + 1) * sizeof(CHAR) * 2;
  350. *ppszRet = (LPSTR) LocalAlloc(NULL, len);
  351. if (*ppszRet)
  352. {
  353. MyOleStrToStrN(*ppszRet, len, bstrRet);
  354. }
  355. }
  356. SAFEFREEBSTR(bstrRet);
  357. if (*ppszRet)
  358. return S_OK;
  359. else
  360. return E_FAIL;
  361. }
  362. //---------------------------------------------------------------------
  363. HRESULT ReadBool(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT_BOOL *pBoolRet)
  364. {
  365. ASSERT(pItem && pBoolRet);
  366. VARIANT Val;
  367. Val.vt = VT_EMPTY;
  368. // accept VT_I4 or VT_BOOL
  369. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  370. (Val.vt==VT_BOOL || Val.vt==VT_I4))
  371. {
  372. if (Val.vt==VT_I4)
  373. {
  374. if (Val.lVal)
  375. *pBoolRet = VARIANT_TRUE;
  376. else
  377. *pBoolRet = VARIANT_FALSE;
  378. }
  379. else
  380. *pBoolRet = Val.boolVal;
  381. return S_OK;
  382. }
  383. else
  384. {
  385. VariantClear(&Val); // free any return value of wrong type
  386. return E_INVALIDARG;
  387. }
  388. }
  389. //---------------------------------------------------------------------
  390. HRESULT ReadSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE *pscRet)
  391. {
  392. ASSERT(pItem && pscRet);
  393. VARIANT Val;
  394. Val.vt = VT_EMPTY;
  395. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && Val.vt == VT_ERROR)
  396. {
  397. *pscRet = Val.scode;
  398. return S_OK;
  399. }
  400. else
  401. {
  402. VariantClear(&Val);
  403. return E_INVALIDARG;
  404. }
  405. }
  406. //---------------------------------------------------------------------
  407. HRESULT WriteEMPTY(ISubscriptionItem *pItem, LPCWSTR szName)
  408. {
  409. ASSERT(pItem);
  410. VARIANT Val;
  411. Val.vt = VT_EMPTY;
  412. return pItem->WriteProperties(1, &szName, &Val);
  413. }
  414. //---------------------------------------------------------------------
  415. HRESULT WriteSCODE(ISubscriptionItem *pItem, LPCWSTR szName, SCODE scVal)
  416. {
  417. ASSERT(pItem);
  418. VARIANT Val;
  419. Val.vt = VT_ERROR;
  420. Val.scode = scVal;
  421. return pItem->WriteProperties(1, &szName, &Val);
  422. }
  423. //---------------------------------------------------------------------
  424. HRESULT ReadDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD *pdwRet)
  425. {
  426. ASSERT(pItem && pdwRet);
  427. VARIANT Val;
  428. Val.vt = VT_EMPTY;
  429. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  430. (Val.vt==VT_I4 || Val.vt==VT_I2))
  431. {
  432. if (Val.vt==VT_I4)
  433. *pdwRet = (DWORD) Val.lVal;
  434. else
  435. *pdwRet = (DWORD) Val.iVal;
  436. return S_OK;
  437. }
  438. else
  439. {
  440. VariantClear(&Val); // free any return value of wrong type
  441. return E_INVALIDARG;
  442. }
  443. }
  444. //---------------------------------------------------------------------
  445. HRESULT ReadLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG *pllRet)
  446. {
  447. ASSERT(pItem && pllRet);
  448. VARIANT Val;
  449. Val.vt = VT_EMPTY;
  450. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) &&
  451. (Val.vt==VT_CY))
  452. {
  453. *pllRet = *((LONGLONG *) &(Val.cyVal));
  454. return S_OK;
  455. }
  456. else
  457. {
  458. VariantClear(&Val); // free any return value of wrong type
  459. return E_INVALIDARG;
  460. }
  461. }
  462. //---------------------------------------------------------------------
  463. HRESULT ReadGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid)
  464. {
  465. ASSERT(pItem && pGuid);
  466. BSTR bstrGUID = NULL;
  467. HRESULT hr = E_INVALIDARG;
  468. if (SUCCEEDED(ReadBSTR(pItem, szName, &bstrGUID)) &&
  469. SUCCEEDED(CLSIDFromString(bstrGUID, pGuid)))
  470. {
  471. hr = NOERROR;
  472. }
  473. SAFEFREEBSTR(bstrGUID);
  474. return hr;
  475. }
  476. //---------------------------------------------------------------------
  477. HRESULT WriteGUID(ISubscriptionItem *pItem, LPCWSTR szName, GUID *pGuid)
  478. {
  479. ASSERT(pItem && pGuid);
  480. WCHAR wszCookie[GUIDSTR_MAX];
  481. #ifdef DEBUG
  482. int len =
  483. #endif
  484. StringFromGUID2(*pGuid, wszCookie, sizeof(wszCookie));
  485. ASSERT(GUIDSTR_MAX == len);
  486. return WriteOLESTR(pItem, szName, wszCookie);
  487. }
  488. //---------------------------------------------------------------------
  489. HRESULT WriteLONGLONG(ISubscriptionItem *pItem, LPCWSTR szName, LONGLONG llVal)
  490. {
  491. VARIANT Val;
  492. Val.vt = VT_CY;
  493. Val.cyVal = *((CY *) &llVal);
  494. return pItem->WriteProperties(1, &szName, &Val);
  495. }
  496. //---------------------------------------------------------------------
  497. HRESULT WriteDWORD(ISubscriptionItem *pItem, LPCWSTR szName, DWORD dwVal)
  498. {
  499. VARIANT Val;
  500. Val.vt = VT_I4;
  501. Val.lVal = dwVal;
  502. return pItem->WriteProperties(1, &szName, &Val);
  503. }
  504. //---------------------------------------------------------------------
  505. HRESULT ReadDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal)
  506. {
  507. ASSERT(pItem && dtVal);
  508. VARIANT Val;
  509. Val.vt = VT_EMPTY;
  510. if (SUCCEEDED(pItem->ReadProperties(1, &szName, &Val)) && (Val.vt==VT_DATE))
  511. {
  512. *dtVal = Val.date;
  513. return S_OK;
  514. }
  515. else
  516. {
  517. VariantClear(&Val); // free any return value of wrong type
  518. return E_INVALIDARG;
  519. }
  520. }
  521. //---------------------------------------------------------------------
  522. HRESULT WriteDATE(ISubscriptionItem *pItem, LPCWSTR szName, DATE *dtVal)
  523. {
  524. VARIANT Val;
  525. Val.vt = VT_DATE;
  526. Val.date= *dtVal;
  527. return pItem->WriteProperties(1, &szName, &Val);
  528. }
  529. //---------------------------------------------------------------------
  530. HRESULT ReadVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarRet)
  531. {
  532. ASSERT(pvarRet->vt == VT_EMPTY);
  533. return pItem->ReadProperties(1, &szName, pvarRet);
  534. }
  535. //---------------------------------------------------------------------
  536. HRESULT WriteVariant(ISubscriptionItem *pItem, LPCWSTR szName, VARIANT *pvarVal)
  537. {
  538. return pItem->WriteProperties(1, &szName, pvarVal);
  539. }
  540. //---------------------------------------------------------------------
  541. HRESULT WriteOLESTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCWSTR szVal)
  542. {
  543. VARIANT Val;
  544. Val.vt = VT_BSTR;
  545. Val.bstrVal = SysAllocString(szVal);
  546. HRESULT hr = pItem->WriteProperties(1, &szName, &Val);
  547. SysFreeString(Val.bstrVal);
  548. return hr;
  549. }
  550. //---------------------------------------------------------------------
  551. HRESULT WriteAnsiSTR(ISubscriptionItem *pItem, LPCWSTR szName, LPCSTR szVal)
  552. {
  553. VARIANT Val;
  554. BSTR bstrVal;
  555. int iLen;
  556. HRESULT hr;
  557. iLen = lstrlen(szVal);
  558. bstrVal = SysAllocStringLen(NULL, iLen);
  559. if (bstrVal)
  560. {
  561. MyStrToOleStrN(bstrVal, iLen + 1, szVal);
  562. Val.vt = VT_BSTR;
  563. Val.bstrVal = bstrVal;
  564. hr = pItem->WriteProperties(1, &szName, &Val);
  565. SysFreeString(bstrVal);
  566. }
  567. return hr;
  568. }
  569. //==============================================================================
  570. // CRunDeliveryAgent provides generic support for synchronous operation of a
  571. // delivery agent
  572. // It is aggregatable so that you can add more interfaces to the callback
  573. //
  574. // Taken from webcheck\cdfagent.cpp
  575. //==============================================================================
  576. CRunDeliveryAgent::CRunDeliveryAgent()
  577. {
  578. m_cRef = 1;
  579. }
  580. //---------------------------------------------------------------------
  581. HRESULT CRunDeliveryAgent::Init(CConApp* pParent,
  582. ISubscriptionItem *pItem,
  583. REFCLSID rclsidDest)
  584. {
  585. ASSERT(pParent && pItem);
  586. if (m_pParent || m_pItem)
  587. return E_FAIL; // already initialized. can't reuse an instance.
  588. if (!pParent || !pItem)
  589. return E_FAIL;
  590. m_pParent = pParent;
  591. m_clsidDest = rclsidDest;
  592. m_pItem = pItem;
  593. pItem->AddRef();
  594. return S_OK;
  595. }
  596. //---------------------------------------------------------------------
  597. CRunDeliveryAgent::~CRunDeliveryAgent()
  598. {
  599. CleanUp();
  600. }
  601. //
  602. // IUnknown members
  603. //
  604. //---------------------------------------------------------------------
  605. STDMETHODIMP_(ULONG) CRunDeliveryAgent::AddRef(void)
  606. {
  607. return ++m_cRef;
  608. }
  609. //---------------------------------------------------------------------
  610. STDMETHODIMP_(ULONG) CRunDeliveryAgent::Release(void)
  611. {
  612. if( 0L != --m_cRef )
  613. return m_cRef;
  614. delete this;
  615. return 0L;
  616. }
  617. //---------------------------------------------------------------------
  618. STDMETHODIMP CRunDeliveryAgent::QueryInterface(REFIID riid, void ** ppv)
  619. {
  620. *ppv=NULL;
  621. // Validate requested interface
  622. if ((IID_IUnknown == riid) ||
  623. (IID_ISubscriptionAgentEvents == riid))
  624. {
  625. *ppv=(ISubscriptionAgentEvents *)this;
  626. }
  627. else
  628. return E_NOINTERFACE;
  629. // Addref through the interface
  630. ((LPUNKNOWN)*ppv)->AddRef();
  631. return S_OK;
  632. }
  633. //
  634. // ISubscriptionAgentEvents members
  635. //
  636. //---------------------------------------------------------------------
  637. STDMETHODIMP CRunDeliveryAgent::UpdateBegin(const SUBSCRIPTIONCOOKIE *)
  638. {
  639. if (m_pParent)
  640. m_pParent->OnAgentBegin();
  641. return S_OK;
  642. }
  643. //---------------------------------------------------------------------
  644. STDMETHODIMP CRunDeliveryAgent::UpdateProgress(
  645. const SUBSCRIPTIONCOOKIE *,
  646. long lSizeDownloaded,
  647. long lProgressCurrent,
  648. long lProgressMax,
  649. HRESULT hrStatus,
  650. LPCWSTR wszStatus)
  651. {
  652. if (m_pParent)
  653. m_pParent->OnAgentProgress();
  654. return S_OK;
  655. }
  656. //---------------------------------------------------------------------
  657. #define INET_S_AGENT_BASIC_SUCCESS _HRESULT_TYPEDEF_(0x000C0F8FL) // From webcheck/delagent.h
  658. STDMETHODIMP CRunDeliveryAgent::UpdateEnd(const SUBSCRIPTIONCOOKIE *pCookie,
  659. long lSizeDownloaded,
  660. HRESULT hrResult,
  661. LPCWSTR wszResult)
  662. {
  663. ASSERT((hrResult != INET_S_AGENT_BASIC_SUCCESS) && (hrResult != E_PENDING));
  664. m_hrResult = hrResult;
  665. if (hrResult == INET_S_AGENT_BASIC_SUCCESS || hrResult == E_PENDING)
  666. {
  667. // Shouldn't happen; let's be robust anyway.
  668. m_hrResult = S_OK;
  669. }
  670. if (m_pParent)
  671. {
  672. m_pParent->OnAgentEnd(pCookie, lSizeDownloaded, hrResult, wszResult, m_fInStartAgent);
  673. }
  674. CleanUp();
  675. return S_OK;
  676. }
  677. //---------------------------------------------------------------------
  678. STDMETHODIMP CRunDeliveryAgent::ReportError(
  679. const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  680. HRESULT hrError,
  681. LPCWSTR wszError)
  682. {
  683. return S_FALSE;
  684. }
  685. //---------------------------------------------------------------------
  686. HRESULT CRunDeliveryAgent::StartAgent()
  687. {
  688. HRESULT hr;
  689. if (!m_pParent || !m_pItem || m_pAgent)
  690. return E_FAIL;
  691. AddRef(); // Release before we return from this function
  692. m_fInStartAgent = TRUE;
  693. m_hrResult = INET_S_AGENT_BASIC_SUCCESS;
  694. if(m_pParent->Verbose())
  695. DBGOUT("Using new interfaces to host agent");
  696. ASSERT(!m_pAgent);
  697. hr = CoCreateInstance(m_clsidDest, NULL, CLSCTX_INPROC_SERVER,
  698. IID_ISubscriptionAgentControl, (void **)&m_pAgent);
  699. if (m_pAgent)
  700. {
  701. hr = m_pAgent->StartUpdate(m_pItem, (ISubscriptionAgentEvents *)this);
  702. }
  703. hr = m_hrResult;
  704. m_fInStartAgent = FALSE;
  705. Release();
  706. if (hr != INET_S_AGENT_BASIC_SUCCESS)
  707. {
  708. return hr;
  709. }
  710. return E_PENDING;
  711. };
  712. //---------------------------------------------------------------------
  713. HRESULT CRunDeliveryAgent::AgentPause(DWORD dwFlags)
  714. {
  715. if (m_pAgent)
  716. return m_pAgent->PauseUpdate(0);
  717. if(m_pParent->Verbose())
  718. DBGOUT("CRunDeliveryAgent::AgentPause with no running agent!!");
  719. return S_FALSE;
  720. }
  721. //---------------------------------------------------------------------
  722. HRESULT CRunDeliveryAgent::AgentResume(DWORD dwFlags)
  723. {
  724. if (m_pAgent)
  725. return m_pAgent->ResumeUpdate(0);
  726. if(m_pParent->Verbose())
  727. DBGOUT("CRunDeliveryAgent::AgentResume with no running agent!!");
  728. return E_FAIL;
  729. }
  730. //---------------------------------------------------------------------
  731. HRESULT CRunDeliveryAgent::AgentAbort(DWORD dwFlags)
  732. {
  733. if (m_pAgent)
  734. return m_pAgent->AbortUpdate(0);
  735. if(m_pParent->Verbose())
  736. DBGOUT("CRunDeliveryAgent::AgentAbort with no running agent!!");
  737. return S_FALSE;
  738. }
  739. //---------------------------------------------------------------------
  740. void CRunDeliveryAgent::CleanUp()
  741. {
  742. SAFERELEASE(m_pItem);
  743. SAFERELEASE(m_pAgent);
  744. m_pParent = NULL;
  745. }
  746. //---------------------------------------------------------------------
  747. HRESULT CRunDeliveryAgent::CreateNewItem(ISubscriptionItem **ppItem, REFCLSID rclsidAgent)
  748. {
  749. ISubscriptionMgrPriv *pSubsMgrPriv=NULL;
  750. SUBSCRIPTIONITEMINFO info;
  751. *ppItem = NULL;
  752. HRESULT hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
  753. IID_ISubscriptionMgrPriv, (void**)&pSubsMgrPriv);
  754. if (pSubsMgrPriv)
  755. {
  756. SUBSCRIPTIONCOOKIE cookie;
  757. info.cbSize = sizeof(info);
  758. info.dwFlags = SI_TEMPORARY;
  759. info.dwPriority = 0;
  760. info.ScheduleGroup = GUID_NULL;
  761. info.clsidAgent = rclsidAgent;
  762. pSubsMgrPriv->CreateSubscriptionItem(&info, &cookie, ppItem);
  763. pSubsMgrPriv->Release();
  764. }
  765. else
  766. {
  767. printf("CoCreateInstance IID_ISubscriptionMgrPriv failed. hr=0x%x\r\n", hr);
  768. }
  769. return (*ppItem) ? S_OK : E_FAIL;
  770. }
  771. ///////////////////////////////////////////////////////////////////////
  772. ///////////////////////////////////////////////////////////////////////
  773. //---------------------------------------------------------------------
  774. CConApp::CConApp(int argc, char **argv)
  775. {
  776. m_argc = argc;
  777. m_argv = argv;
  778. m_dwTime = 0;
  779. m_pszURL = NULL;
  780. m_bVerbose = FALSE;
  781. m_bPreLoad = FALSE;
  782. m_bChannelAgent = FALSE;
  783. m_dwFlags = 3;
  784. m_dwLevels = 0;
  785. m_dwChannel = 1;
  786. m_dwChannelFlags = CHANNEL_AGENT_PRECACHE_ALL;
  787. m_pRunStr = NULL;
  788. m_pTestName = NULL;
  789. m_iActive = 0;
  790. }
  791. //---------------------------------------------------------------------
  792. CConApp::~CConApp()
  793. {
  794. CoUninitialize();
  795. }
  796. //---------------------------------------------------------------------
  797. HRESULT CConApp::Init()
  798. {
  799. HRESULT hr = CoInitialize(NULL);
  800. ON_FAILURE_RETURN(hr);
  801. if(!ParseCommandLine())
  802. return(E_FAIL);
  803. return(S_OK);
  804. }
  805. //---------------------------------------------------------------------
  806. HRESULT CConApp::Download()
  807. {
  808. ISubscriptionItem *pSubscriptItem = NULL;
  809. IImgCtx *pImgCtx = NULL;
  810. IClassFactory *pImageCF = NULL;
  811. if(m_bVerbose)
  812. {
  813. printf("URL=%s\r\n", m_pszURL);
  814. if(m_bPreLoad)
  815. printf("Preloading Mshtml\r\n");
  816. if(m_bChannelAgent)
  817. printf("ChannelAgent: Channel=%d Flags=0x%x\r\n", m_dwChannel, m_dwChannelFlags);
  818. else
  819. printf("WebCrawlerAgent: Levels=%d Flags=0x%x\r\n", m_dwFlags, m_dwLevels);
  820. }
  821. HRESULT hr = S_OK;
  822. CLSID clsid;
  823. if (m_bChannelAgent)
  824. clsid = CLSID_ChannelAgent;
  825. else
  826. clsid = CLSID_WebCrawlerAgent;
  827. CRunDeliveryAgent *prda = new CRunDeliveryAgent;
  828. hr = prda->CreateNewItem(&pSubscriptItem, clsid);
  829. if (FAILED(hr) || !pSubscriptItem)
  830. {
  831. printf("prda->CreateNewItem failed.\r\n");
  832. return E_FAIL;
  833. }
  834. if (!prda || FAILED(prda->Init((CConApp *)this, pSubscriptItem, clsid)))
  835. {
  836. if (prda)
  837. prda->Release();
  838. else
  839. printf("new CRunDeliveryAgent failed.\r\n");
  840. return E_FAIL;
  841. }
  842. // Preload mshtml
  843. if (m_bPreLoad)
  844. {
  845. if (FAILED(hr = CoGetClassObject(CLSID_IImgCtx, CLSCTX_SERVER, NULL, IID_IClassFactory, (void **)&pImageCF)))
  846. {
  847. printf("CoGetClassObject(CLSID_IImgCtx...) failed hr=%x\r\n", hr);
  848. return E_FAIL;
  849. }
  850. if (FAILED(hr = pImageCF->CreateInstance(NULL, IID_IImgCtx, (void **)&pImgCtx)))
  851. {
  852. printf("CreateInstance(IID_IImgCtx...) failed hr=%x\r\n", hr);
  853. return E_FAIL;
  854. }
  855. }
  856. // Set properties
  857. if (m_bChannelAgent)
  858. {
  859. WriteDWORD(pSubscriptItem, c_szPropChannel, m_dwChannel);
  860. WriteDWORD(pSubscriptItem, c_szPropChannelFlags, m_dwChannelFlags);
  861. }
  862. else
  863. {
  864. WriteDWORD(pSubscriptItem, c_szPropCrawlFlags, m_dwFlags);
  865. WriteDWORD(pSubscriptItem, c_szPropCrawlLevels, m_dwLevels);
  866. }
  867. // Set url property and start the download
  868. WCHAR wszURL[INTERNET_MAX_URL_LENGTH];
  869. MyStrToOleStrN(wszURL, INTERNET_MAX_URL_LENGTH, m_pszURL);
  870. WriteOLESTR(pSubscriptItem, c_szPropURL, wszURL);
  871. m_dwTime = GetTickCount(); // Start time
  872. hr = prda->StartAgent();
  873. if (hr == E_PENDING)
  874. {
  875. hr = S_OK;
  876. if (Verbose())
  877. DBGOUT("CRunDeliveryAgent StartAgent succeeded");
  878. MessageLoop();
  879. }
  880. m_dwTime = GetTickCount() - m_dwTime; // End time
  881. // Clean up
  882. if (pSubscriptItem)
  883. {
  884. pSubscriptItem->Release();
  885. pSubscriptItem = NULL;
  886. }
  887. if (pImgCtx)
  888. {
  889. pImgCtx->Release();
  890. pImgCtx = NULL;
  891. }
  892. if (pImageCF)
  893. {
  894. pImageCF->Release();
  895. pImageCF = NULL;
  896. }
  897. if (prda)
  898. {
  899. prda->Release();
  900. prda = NULL;
  901. }
  902. if (FAILED(hr))
  903. return E_FAIL;
  904. return S_OK;
  905. }
  906. //---------------------------------------------------------------------
  907. HRESULT CConApp::MessageLoop()
  908. {
  909. MSG msg;
  910. BOOL dw;
  911. // Yield and wait for "UpdateEnd" notification
  912. while (m_iActive > 0 && (dw = ::GetMessage(&msg, NULL, 0, 0)))
  913. {
  914. ::TranslateMessage(&msg);
  915. ::DispatchMessage(&msg);
  916. }
  917. if(dw == 0)
  918. printf("GetMessage = 0, GLE=%d\r\n", GetLastError());
  919. return S_OK;
  920. }
  921. //---------------------------------------------------------------------
  922. BOOL CConApp::PrintResults()
  923. {
  924. printf("%s, %s, %ld, %ld, %ld %s\r\n",
  925. m_pTestName ?m_pTestName :(m_bChannelAgent) ?"Webcheck ChannelAgent" :"Webcheck WebCrawlAgent",
  926. m_pRunStr ?m_pRunStr :"1",
  927. m_dwTime,
  928. 0, // bytes read - future use, matches other tests
  929. 0, // kb/sec - future use
  930. m_CmdLine
  931. );
  932. return(TRUE);
  933. }
  934. //---------------------------------------------------------------------
  935. BOOL CConApp::ParseCommandLine()
  936. {
  937. BOOL bRC = TRUE;
  938. int argc = m_argc;
  939. char **argv = m_argv;
  940. DWORD dwLen = 0;
  941. *m_CmdLine = '\0';
  942. argv++; argc--;
  943. while( argc > 0 && argv[0][0] == '-' )
  944. {
  945. switch (argv[0][1])
  946. {
  947. case 'c':
  948. m_bChannelAgent = TRUE;
  949. break;
  950. case 'f':
  951. m_dwFlags = atoi(&argv[0][2]);
  952. break;
  953. case 'l':
  954. m_dwLevels = atoi(&argv[0][2]);
  955. break;
  956. case 'p':
  957. m_bPreLoad = TRUE;
  958. break;
  959. case 'r':
  960. m_pRunStr = &argv[0][2];
  961. break;
  962. case 't':
  963. m_pTestName = &argv[0][2];
  964. break;
  965. case 'u':
  966. m_pszURL = &argv[0][2];
  967. break;
  968. case 'v':
  969. m_bVerbose = TRUE;
  970. break;
  971. default:
  972. bRC = FALSE;
  973. break;
  974. }
  975. if(bRC)
  976. {
  977. dwLen += lstrlen(argv[0]) + 1; // length of arg and space
  978. if(dwLen < ((sizeof(m_CmdLine)/sizeof(m_CmdLine[0]))-1))
  979. {
  980. lstrcat(m_CmdLine, ",");
  981. lstrcat(m_CmdLine, argv[0]);
  982. }
  983. }
  984. argv++; argc--;
  985. }
  986. if(!m_pszURL || (bRC == FALSE))
  987. {
  988. Display_Usage();
  989. bRC = FALSE;
  990. }
  991. return(bRC);
  992. }
  993. //---------------------------------------------------------------------
  994. void CConApp::Display_Usage()
  995. {
  996. printf("Usage: %s -uURL [Options]\r\n\n", m_argv[0]);
  997. printf("Options:\r\n");
  998. printf("\t-c Run ChannelAgent instead of WebCrawl.\r\n");
  999. printf("\t-f# Webcrawl agent flags.\r\n");
  1000. printf("\t-l# Delivery agent levels to crawl.\r\n");
  1001. printf("\t-p Preload Mshtml.\r\n");
  1002. printf("\t-v Turn on verbose output.\r\n");
  1003. printf("\t-tStr test name string (used in results output)\n");
  1004. printf("\t-rStr run# string (used in results output)\n");
  1005. }
  1006. //---------------------------------------------------------------------
  1007. inline BOOL CConApp::Verbose()
  1008. {
  1009. return(m_bVerbose);
  1010. }
  1011. //---------------------------------------------------------------------
  1012. HRESULT CConApp::OnAgentBegin()
  1013. {
  1014. m_iActive++;
  1015. return S_OK;
  1016. }
  1017. //---------------------------------------------------------------------
  1018. // OnAgentProgress not currently called
  1019. HRESULT CConApp::OnAgentProgress()
  1020. {
  1021. return E_NOTIMPL;
  1022. }
  1023. //---------------------------------------------------------------------
  1024. // OnAgentEnd called when agent is complete. fSynchronous means that StartAgent call
  1025. // has not yet returned; hrResult will be returned from StartAgent
  1026. HRESULT CConApp::OnAgentEnd(const SUBSCRIPTIONCOOKIE *pSubscriptionCookie,
  1027. long lSizeDownloaded, HRESULT hrResult, LPCWSTR wszResult,
  1028. BOOL fSynchronous)
  1029. {
  1030. m_iActive--;
  1031. return S_OK;
  1032. }
  1033. ///////////////////////////////////////////////////////////////////////
  1034. ///////////////////////////////////////////////////////////////////////
  1035. int __cdecl main(int argc, char **argv)
  1036. {
  1037. HRESULT hr = S_OK;
  1038. CConApp App(argc, argv);
  1039. hr = App.Init();
  1040. if(!FAILED(hr))
  1041. {
  1042. hr = App.Download();
  1043. App.PrintResults();
  1044. }
  1045. return((int)hr);
  1046. }