Leaked source code of windows server 2003
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.

809 lines
26 KiB

  1. // --------------------------------------------------------------------------------
  2. // Trawler.cpp
  3. // --------------------------------------------------------------------------------
  4. #define INC_OLE2
  5. #include "windows.h"
  6. #include "main.h"
  7. #include "stdio.h"
  8. #include "shlwapi.h"
  9. #include "mimeole.h"
  10. #include "trawler.h"
  11. extern UINT g_msgNNTP;
  12. void WaitForCompletion(UINT uiMsg, DWORD wparam);
  13. HRESULT HrCreateTrawler(CTrawler **ppTrawler)
  14. {
  15. CTrawler *pTrawler;
  16. HRESULT hr;
  17. pTrawler = new CTrawler();
  18. if (!pTrawler)
  19. return E_OUTOFMEMORY;
  20. hr = pTrawler->Init();
  21. if (FAILED(hr))
  22. goto error;
  23. *ppTrawler = pTrawler;
  24. pTrawler->AddRef();
  25. error:
  26. pTrawler->Release();
  27. return hr;
  28. }
  29. // --------------------------------------------------------------------------------
  30. // CTrawler::CTrawler
  31. // --------------------------------------------------------------------------------
  32. CTrawler::CTrawler(void)
  33. {
  34. m_cRef = 1;
  35. m_pNNTP = NULL;
  36. m_pstm = NULL;
  37. }
  38. // --------------------------------------------------------------------------------
  39. // CTrawler::~CTrawler
  40. // --------------------------------------------------------------------------------
  41. CTrawler::~CTrawler(void)
  42. {
  43. }
  44. // --------------------------------------------------------------------------------
  45. // CTrawler::QueryInterface
  46. // --------------------------------------------------------------------------------
  47. STDMETHODIMP CTrawler::QueryInterface(REFIID riid, LPVOID *ppv)
  48. {
  49. // Locals
  50. HRESULT hr=S_OK;
  51. // Bad param
  52. if (ppv == NULL)
  53. {
  54. hr = E_INVALIDARG;
  55. goto exit;
  56. }
  57. // Init
  58. *ppv=NULL;
  59. // IID_IUnknown
  60. if (IID_IUnknown == riid)
  61. *ppv = (IUnknown *)this;
  62. // IID_INNTPCallback
  63. else if (IID_INNTPCallback == riid)
  64. *ppv = (INNTPCallback *)this;
  65. // If not null, addref it and return
  66. if (NULL != *ppv)
  67. {
  68. ((LPUNKNOWN)*ppv)->AddRef();
  69. goto exit;
  70. }
  71. // No Interface
  72. hr = E_NOINTERFACE;
  73. exit:
  74. // Done
  75. return hr;
  76. }
  77. // --------------------------------------------------------------------------------
  78. // CTrawler::AddRef
  79. // --------------------------------------------------------------------------------
  80. STDMETHODIMP_(ULONG) CTrawler::AddRef(void)
  81. {
  82. return ++m_cRef;
  83. }
  84. // --------------------------------------------------------------------------------
  85. // CTrawler::Release
  86. // --------------------------------------------------------------------------------
  87. STDMETHODIMP_(ULONG) CTrawler::Release(void)
  88. {
  89. if (0 != --m_cRef)
  90. return m_cRef;
  91. delete this;
  92. return 0;
  93. }
  94. // --------------------------------------------------------------------------------
  95. // CTrawler::Init
  96. // --------------------------------------------------------------------------------
  97. HRESULT CTrawler::Init()
  98. {
  99. HRESULT hr;
  100. // Load the NNTP Transport
  101. hr = CoCreateInstance(CLSID_INNTPTransport, NULL, CLSCTX_INPROC_SERVER,
  102. IID_INNTPTransport, (LPVOID*)&m_pNNTP);
  103. if (FAILED(hr))
  104. {
  105. Error("Failed to CoCreate Transport Object\n");
  106. return hr;
  107. }
  108. // Initialize the transport
  109. hr = m_pNNTP->InitNew(NULL, this);
  110. if (FAILED(hr))
  111. {
  112. Error("Unable to initialize the transport\n");
  113. m_pNNTP->Release();
  114. m_pNNTP=NULL;
  115. return hr;
  116. }
  117. return S_OK;
  118. }
  119. HRESULT CTrawler::Close()
  120. {
  121. if (m_pNNTP)
  122. {
  123. m_pNNTP->Disconnect();
  124. WaitForCompletion(g_msgNNTP, NS_DISCONNECTED);
  125. m_pNNTP->Release();
  126. m_pNNTP=NULL;
  127. }
  128. return S_OK;
  129. }
  130. HRESULT CTrawler::DoTrawl()
  131. {
  132. char *pszGroup;
  133. INETSERVER rServer={0};
  134. if (FAILED(LoadIniData()))
  135. {
  136. return E_FAIL;
  137. }
  138. lstrcpy(rServer.szServerName, m_szServer);
  139. rServer.dwPort = 119;
  140. rServer.dwTimeout = 30;
  141. if (FAILED(m_pNNTP->Connect(&rServer, 0, 0)))
  142. {
  143. Error("Cannot connect to server\n\r");
  144. return E_FAIL;
  145. }
  146. WaitForCompletion(g_msgNNTP, NS_CONNECT);
  147. pszGroup=m_szGroups;
  148. while (*pszGroup)
  149. {
  150. if (FAILED(SelectGroup(pszGroup)))
  151. {
  152. Error("failed to select group\n\r");
  153. continue;
  154. }
  155. DumpGroup(pszGroup);
  156. pszGroup+=lstrlen(pszGroup)+1;
  157. }
  158. return S_OK;
  159. }
  160. HRESULT CTrawler::SelectGroup(LPSTR lpszGroup)
  161. {
  162. HRESULT hr;
  163. hr = m_pNNTP->CommandGROUP(lpszGroup);
  164. if (FAILED(hr))
  165. goto error;
  166. // Wait for completion
  167. WaitForCompletion(g_msgNNTP, NS_GROUP);
  168. error:
  169. return hr;
  170. }
  171. HRESULT CTrawler::DumpGroup(LPSTR pszGroup)
  172. {
  173. ULONG c;
  174. ARTICLEID rArtId;
  175. ULONG uMin;
  176. char sz[256];
  177. uMin = GetPrivateProfileInt(pszGroup, "Last", m_uMin, "trawl.ini");
  178. for(c=uMin; c<m_uMax; c++)
  179. {
  180. printf("Downloading article %d...\n\r", c);
  181. rArtId.idType = AID_ARTICLENUM;
  182. rArtId.dwArticleNum = c;
  183. m_pNNTP->CommandARTICLE(&rArtId);
  184. WaitForCompletion(g_msgNNTP, NS_ARTICLE);
  185. }
  186. wsprintf(sz, "%d", m_uMax);
  187. WritePrivateProfileString(pszGroup, "Last", sz, "trawl.ini");
  188. printf("** GROUP DOWNLOAD COMPLETE ** (Last=%d)\n\r", m_uMax);
  189. return S_OK;
  190. }
  191. HRESULT CTrawler::LoadIniData()
  192. {
  193. char szDefault[MAX_PATH];
  194. if (GetPrivateProfileSection("groups", m_szGroups, sizeof(m_szGroups), "trawl.ini")==0)
  195. {
  196. Error("No group list found\n\rPlease add a [group] section to trawl.ini\n\r");
  197. return E_FAIL;
  198. }
  199. GetTempPath(MAX_PATH, szDefault);
  200. GetPrivateProfileString("setup", "path", szDefault, m_szPath, sizeof(m_szPath), "trawl.ini");
  201. if (m_szPath[lstrlen(m_szPath)-1]!='\\')
  202. m_szPath[lstrlen(m_szPath)-1]='\\';
  203. printf("using path=%s\n\r", m_szPath);
  204. GetPrivateProfileString("setup", "server", "newsvr", m_szServer, sizeof(m_szServer), "trawl.ini");
  205. printf("using server='%s'\n\r", m_szServer);
  206. if (GetPrivateProfileSection("types", m_szTypes, sizeof(m_szTypes), "trawl.ini")==0)
  207. {
  208. Error("No files types found to search for\n\rPlease add a [types] section to trawl.ini\n\r");
  209. return E_FAIL;
  210. }
  211. return S_OK;
  212. }
  213. HRESULT CTrawler::IsValidType(char *szExt)
  214. {
  215. char *pszTypes=m_szTypes;
  216. if (*szExt == '.')
  217. szExt++;
  218. while (*pszTypes)
  219. {
  220. if (lstrcmp(szExt, pszTypes)==0)
  221. {
  222. return S_OK;
  223. }
  224. pszTypes+=lstrlen(pszTypes)+1;
  225. }
  226. return S_FALSE;
  227. }
  228. // --------------------------------------------------------------------------------
  229. // CTrawler::OnLogonPrompt
  230. // --------------------------------------------------------------------------------
  231. STDMETHODIMP CTrawler::OnLogonPrompt(LPINETSERVER pInetServer,
  232. IInternetTransport *pTransport)
  233. {
  234. return S_OK;
  235. }
  236. // --------------------------------------------------------------------------------
  237. // CTrawler::OnPrompt
  238. // --------------------------------------------------------------------------------
  239. STDMETHODIMP_(INT) CTrawler::OnPrompt(HRESULT hrError, LPCTSTR pszText,
  240. LPCTSTR pszCaption, UINT uType,
  241. IInternetTransport *pTransport)
  242. {
  243. return S_OK;
  244. }
  245. // --------------------------------------------------------------------------------
  246. // CTrawler::OnError
  247. // --------------------------------------------------------------------------------
  248. STDMETHODIMP CTrawler::OnError(IXPSTATUS ixpstatus, LPIXPRESULT pIxpResult,
  249. IInternetTransport *pTransport)
  250. {
  251. char szBuffer[256];
  252. wsprintf(szBuffer, "CTrawler::OnError - Status: %d, hrResult: %08x\n", ixpstatus, pIxpResult->hrResult);
  253. Error(szBuffer);
  254. return S_OK;
  255. }
  256. // --------------------------------------------------------------------------------
  257. // CTrawler::OnStatus
  258. // --------------------------------------------------------------------------------
  259. STDMETHODIMP CTrawler::OnStatus(IXPSTATUS ixpstatus,
  260. IInternetTransport *pTransport)
  261. {
  262. INETSERVER rServer;
  263. char szBuffer[256];
  264. pTransport->GetServerInfo(&rServer);
  265. switch(ixpstatus)
  266. {
  267. case IXP_FINDINGHOST:
  268. wsprintf(szBuffer, "Finding '%s'...\n", rServer.szServerName);
  269. break;
  270. case IXP_CONNECTING:
  271. wsprintf(szBuffer, "Connecting '%s'...\n", rServer.szServerName);
  272. break;
  273. case IXP_SECURING:
  274. wsprintf(szBuffer, "Establishing secure connection to '%s'...\n", rServer.szServerName);
  275. break;
  276. case IXP_CONNECTED:
  277. wsprintf(szBuffer, "Connected '%s'\n", rServer.szServerName);
  278. break;
  279. case IXP_AUTHORIZING:
  280. wsprintf(szBuffer, "Authorizing '%s'...\n", rServer.szServerName);
  281. break;
  282. case IXP_AUTHRETRY:
  283. wsprintf(szBuffer, "Retrying Logon '%s'...\n", rServer.szServerName);
  284. break;
  285. case IXP_DISCONNECTING:
  286. wsprintf(szBuffer, "Disconnecting '%s'...\n", rServer.szServerName);
  287. break;
  288. case IXP_DISCONNECTED:
  289. wsprintf(szBuffer, "Disconnected '%s'\n", rServer.szServerName);
  290. break;
  291. }
  292. ShowMsg(szBuffer, FOREGROUND_GREEN);
  293. return S_OK;
  294. }
  295. // --------------------------------------------------------------------------------
  296. // CTrawler::OnProgress
  297. // --------------------------------------------------------------------------------
  298. STDMETHODIMP CTrawler::OnProgress(DWORD dwIncrement, DWORD dwCurrent,
  299. DWORD dwMaximum, IInternetTransport *pTransport)
  300. {
  301. return S_OK;
  302. }
  303. // --------------------------------------------------------------------------------
  304. // CTrawler::OnCommand
  305. // --------------------------------------------------------------------------------
  306. STDMETHODIMP CTrawler::OnCommand(CMDTYPE cmdtype, LPSTR pszLine,
  307. HRESULT hrResponse,
  308. IInternetTransport *pTransport)
  309. {
  310. return S_OK;
  311. }
  312. // --------------------------------------------------------------------------------
  313. // CTrawler::OnTimeout
  314. // --------------------------------------------------------------------------------
  315. STDMETHODIMP CTrawler::OnTimeout(DWORD *pdwTimeout,
  316. IInternetTransport *pTransport)
  317. {
  318. INETSERVER rServer;
  319. pTransport->GetServerInfo(&rServer);
  320. printf("Timeout '%s' !!!\n", rServer.szServerName);
  321. return S_OK;
  322. }
  323. // --------------------------------------------------------------------------------
  324. // CTrawler::OnResponse
  325. // --------------------------------------------------------------------------------
  326. STDMETHODIMP CTrawler::OnResponse(LPNNTPRESPONSE pResponse)
  327. {
  328. switch(pResponse->state)
  329. {
  330. case NS_DISCONNECTED:
  331. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, pResponse->state, 0);
  332. break;
  333. case NS_CONNECT:
  334. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, NS_CONNECT, 0);
  335. break;
  336. case NS_AUTHINFO:
  337. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  338. break;
  339. case NS_GROUP:
  340. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  341. {
  342. printf("\n"
  343. "NS_GROUP_RESP - rGroup.dwFirst = %d\n"
  344. " rGroup.dwLast = %d\n"
  345. " rGroup.dwCount = %d\n"
  346. " rGroup.pszGroup = %s\n\n",
  347. pResponse->rGroup.dwFirst, pResponse->rGroup.dwLast,
  348. pResponse->rGroup.dwCount, pResponse->rGroup.pszGroup);
  349. m_uMin = pResponse->rGroup.dwFirst;
  350. m_uMax = pResponse->rGroup.dwLast;
  351. }
  352. m_pNNTP->ReleaseResponse(pResponse);
  353. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, pResponse->state, 0);
  354. break;
  355. case NS_NEXT:
  356. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  357. {
  358. printf("\n"
  359. "NS_NEXT_RESP - rNext.dwArticleNum = %d\n"
  360. " - rNext.pszMessageId = %s\n\n",
  361. pResponse->rNext.dwArticleNum, pResponse->rNext.pszMessageId);
  362. pResponse->pTransport->ReleaseResponse(pResponse);
  363. }
  364. m_pNNTP->ReleaseResponse(pResponse);
  365. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, pResponse->state, 0);
  366. break;
  367. case NS_LAST:
  368. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  369. {
  370. printf("\n"
  371. "NS_LAST_RESP - rNext.dwArticleNum = %d\n"
  372. " - rNext.pszMessageId = %s\n\n",
  373. pResponse->rLast.dwArticleNum, pResponse->rLast.pszMessageId);
  374. pResponse->pTransport->ReleaseResponse(pResponse);
  375. }
  376. m_pNNTP->ReleaseResponse(pResponse);
  377. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, pResponse->state, 0);
  378. break;
  379. case NS_STAT:
  380. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  381. {
  382. printf("\n"
  383. "NS_STAT_RESP - rNext.dwArticleNum = %d\n"
  384. " - rNext.pszMessageId = %s\n\n",
  385. pResponse->rLast.dwArticleNum, pResponse->rLast.pszMessageId);
  386. pResponse->pTransport->ReleaseResponse(pResponse);
  387. }
  388. m_pNNTP->ReleaseResponse(pResponse);
  389. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, pResponse->state, 0);
  390. break;
  391. case NS_LIST:
  392. if (pResponse->rIxpResult.uiServerError != IXP_NNTP_LIST_DATA_FOLLOWS)
  393. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  394. else
  395. {
  396. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  397. {
  398. for (UINT i = 0; i < pResponse->rList.cLines; i++)
  399. printf("%s\n", pResponse->rList.rgszLines[i]);
  400. }
  401. m_pNNTP->ReleaseResponse(pResponse);
  402. if (pResponse->fDone)
  403. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  404. }
  405. break;
  406. case NS_LISTGROUP:
  407. if (pResponse->rIxpResult.uiServerError != IXP_NNTP_GROUP_SELECTED)
  408. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  409. else
  410. {
  411. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  412. {
  413. for (UINT i = 0; i < pResponse->rListGroup.cArticles; i++)
  414. printf("%d\n", pResponse->rListGroup.rgArticles[i]);
  415. }
  416. m_pNNTP->ReleaseResponse(pResponse);
  417. if (pResponse->fDone)
  418. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  419. }
  420. break;
  421. case NS_DATE:
  422. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  423. {
  424. printf("\nNS_DATE - %02d/%02d/%04d %02d:%02d:%02d\n\n",
  425. pResponse->rDate.wMonth, pResponse->rDate.wDay,
  426. pResponse->rDate.wYear, pResponse->rDate.wHour,
  427. pResponse->rDate.wMinute, pResponse->rDate.wSecond);
  428. }
  429. m_pNNTP->ReleaseResponse(pResponse);
  430. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, pResponse->state, 0);
  431. break;
  432. case NS_MODE:
  433. printf("\nNS_MODE\n\n");
  434. m_pNNTP->ReleaseResponse(pResponse);
  435. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, pResponse->state, 0);
  436. break;
  437. case NS_NEWGROUPS:
  438. if (pResponse->rIxpResult.uiServerError != IXP_NNTP_NEWNEWSGROUPS_FOLLOWS)
  439. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  440. else
  441. {
  442. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  443. {
  444. for (UINT i = 0; i < pResponse->rNewgroups.cLines; i++)
  445. printf("%s\n", pResponse->rNewgroups.rgszLines[i]);
  446. }
  447. m_pNNTP->ReleaseResponse(pResponse);
  448. if (pResponse->fDone)
  449. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  450. }
  451. break;
  452. case NS_ARTICLE:
  453. if (pResponse->rIxpResult.uiServerError != IXP_NNTP_ARTICLE_FOLLOWS)
  454. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, NS_ARTICLE, 0);
  455. else
  456. {
  457. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  458. {
  459. OnArticle(pResponse->rArticle.pszLines, pResponse->rArticle.cbLines, pResponse->fDone);
  460. }
  461. if (pResponse->fDone)
  462. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, NS_ARTICLE, 0);
  463. m_pNNTP->ReleaseResponse(pResponse);
  464. }
  465. break;
  466. case NS_HEAD:
  467. if (pResponse->rIxpResult.uiServerError != IXP_NNTP_HEAD_FOLLOWS)
  468. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  469. else
  470. {
  471. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  472. printf("%s", pResponse->rArticle.pszLines);
  473. m_pNNTP->ReleaseResponse(pResponse);
  474. if (pResponse->fDone)
  475. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  476. }
  477. break;
  478. case NS_BODY:
  479. if (pResponse->rIxpResult.uiServerError != IXP_NNTP_BODY_FOLLOWS)
  480. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  481. else
  482. {
  483. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  484. {
  485. printf("%s", pResponse->rArticle.pszLines);
  486. }
  487. m_pNNTP->ReleaseResponse(pResponse);
  488. if (pResponse->fDone)
  489. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  490. }
  491. break;
  492. case NS_IDLE:
  493. printf("NS_IDLE\n");
  494. printf("Why would we ever be here?");
  495. m_pNNTP->ReleaseResponse(pResponse);
  496. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  497. break;
  498. case NS_HEADERS:
  499. if ((pResponse->rIxpResult.uiServerError / 100) != 2)
  500. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  501. else
  502. {
  503. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  504. {
  505. for (UINT i = 0; i < pResponse->rHeaders.cHeaders; i++)
  506. {
  507. printf("%d\n", pResponse->rHeaders.rgHeaders[i].dwArticleNum);
  508. printf("%s\n", pResponse->rHeaders.rgHeaders[i].pszSubject);
  509. printf("%s\n", pResponse->rHeaders.rgHeaders[i].pszFrom);
  510. printf("%s\n", pResponse->rHeaders.rgHeaders[i].pszDate);
  511. printf("%s\n", pResponse->rHeaders.rgHeaders[i].pszMessageId);
  512. printf("%s\n", pResponse->rHeaders.rgHeaders[i].pszReferences);
  513. printf("%d\n", pResponse->rHeaders.rgHeaders[i].dwBytes);
  514. printf("%d\n", pResponse->rHeaders.rgHeaders[i].dwLines);
  515. if (pResponse->rHeaders.rgHeaders[i].pszXref)
  516. printf("%s\n", pResponse->rHeaders.rgHeaders[i].pszXref);
  517. printf("\n\n");
  518. }
  519. }
  520. m_pNNTP->ReleaseResponse(pResponse);
  521. if (pResponse->fDone)
  522. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  523. }
  524. break;
  525. case NS_XHDR:
  526. if ((pResponse->rIxpResult.uiServerError / 100) != 2)
  527. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  528. else
  529. {
  530. if (SUCCEEDED(pResponse->rIxpResult.hrResult))
  531. {
  532. for (UINT i = 0; i < pResponse->rXhdr.cHeaders; i++)
  533. {
  534. printf("%6d %s\n", pResponse->rXhdr.rgHeaders[i].dwArticleNum,
  535. pResponse->rXhdr.rgHeaders[i].pszHeader);
  536. }
  537. }
  538. m_pNNTP->ReleaseResponse(pResponse);
  539. if (pResponse->fDone)
  540. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  541. }
  542. break;
  543. case NS_POST:
  544. printf("%s\n", pResponse->rIxpResult.pszResponse);
  545. m_pNNTP->ReleaseResponse(pResponse);
  546. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP, 0, 0);
  547. break;
  548. case NS_QUIT:
  549. PostThreadMessage(GetCurrentThreadId(), g_msgNNTP,0, 0);
  550. break;
  551. }
  552. return S_OK;
  553. }
  554. HRESULT HrRewindStream(LPSTREAM pstm)
  555. {
  556. LARGE_INTEGER liOrigin = {0,0};
  557. return pstm->Seek(liOrigin, STREAM_SEEK_SET, NULL);
  558. }
  559. void CTrawler::DumpMsg(IMimeMessage *pMsg)
  560. {
  561. TCHAR *szExt;
  562. ULONG cAttach=0,
  563. uAttach;
  564. LPHBODY rghAttach=0;
  565. LPSTR lpszFile=0;
  566. HBODY hAttach=0;
  567. LPMIMEBODY pBody=0;
  568. TCHAR szTemp[MAX_PATH];
  569. if (FAILED(pMsg->GetAttachments(&cAttach, &rghAttach)))
  570. goto error;
  571. if (cAttach==0)
  572. goto error;
  573. for (uAttach = 0; uAttach < cAttach; uAttach++)
  574. {
  575. hAttach = rghAttach[uAttach];
  576. if (FAILED(MimeOleGetBodyPropA(pMsg, hAttach, STR_ATT_GENFNAME, NOFLAGS, &lpszFile)))
  577. continue; // can't inline this dude...
  578. szExt = PathFindExtension(lpszFile);
  579. if (IsValidType(szExt)==S_OK)
  580. {
  581. // we can inline
  582. lstrcpy(szTemp, m_szPath);
  583. lstrcat(szTemp, lpszFile);
  584. if (pMsg->BindToObject(hAttach, IID_IMimeBody, (LPVOID *)&pBody)==S_OK)
  585. {
  586. ShowMsg(szTemp, FOREGROUND_BLUE);
  587. if (FAILED(pBody->SaveToFile(IET_BINARY, szTemp)))
  588. Error("Error: could not create file on disk.");
  589. pBody->Release();
  590. }
  591. }
  592. // I'm being lazy, I can't be bother writing to code to get the mime allocator, so I'm just not going to
  593. // free this string...
  594. //SafeMimeOleFree(lpszFile);
  595. }
  596. error:
  597. return;
  598. }
  599. void CTrawler::OnArticle(LPSTR lpszLines, ULONG cbLines, BOOL fDone)
  600. {
  601. IMimeMessage *pMsg;
  602. if (!m_pstm)
  603. {
  604. // if we need a new stream let's create one
  605. MimeOleCreateVirtualStream(&m_pstm);
  606. }
  607. if (m_pstm)
  608. {
  609. if (!FAILED(m_pstm->Write(lpszLines, cbLines, NULL)))
  610. {
  611. if (fDone)
  612. {
  613. // if we're done, scan the msg and release and NULL the stream ready
  614. // for the next article
  615. if (!FAILED(MimeOleCreateMessage(NULL, &pMsg)))
  616. {
  617. HrRewindStream(m_pstm);
  618. if (!FAILED(pMsg->Load(m_pstm)))
  619. DumpMsg(pMsg);
  620. pMsg->Release();
  621. m_pstm->Release();
  622. m_pstm = NULL;
  623. }
  624. }
  625. }
  626. }
  627. }
  628. void CTrawler::ShowMsg(LPSTR psz, BYTE fgColor)
  629. {
  630. HANDLE hConsole = INVALID_HANDLE_VALUE;
  631. CONSOLE_SCREEN_BUFFER_INFO csbi;
  632. BOOL fChanged = FALSE;
  633. char szBuffer[256];
  634. DWORD dwWritten = 0;
  635. // Get a handle to the console window
  636. if (INVALID_HANDLE_VALUE != (hConsole = GetStdHandle(STD_OUTPUT_HANDLE)))
  637. {
  638. // Get the current attributes for the console
  639. if (GetConsoleScreenBufferInfo(hConsole, &csbi))
  640. {
  641. // Set the text color to be red on whatever background is currently
  642. // there
  643. fChanged = SetConsoleTextAttribute(hConsole,
  644. (csbi.wAttributes & 0xF0) | fgColor | FOREGROUND_INTENSITY);
  645. }
  646. }
  647. wsprintf(szBuffer, "%s\n\r", psz);
  648. WriteConsole(hConsole, szBuffer, lstrlen(szBuffer), &dwWritten, NULL);
  649. // If we changed the screen attributes, then change them back
  650. if (fChanged)
  651. SetConsoleTextAttribute(hConsole, csbi.wAttributes);
  652. }
  653. void CTrawler::Error(LPSTR psz)
  654. {
  655. ShowMsg(psz, FOREGROUND_RED);
  656. }
  657. void WaitForCompletion(UINT uiMsg, DWORD wparam)
  658. {
  659. MSG msg;
  660. while(GetMessage(&msg, NULL, 0, 0))
  661. {
  662. if (msg.message == uiMsg && msg.wParam == wparam || msg.wParam == IXP_DISCONNECTED)
  663. break;
  664. TranslateMessage(&msg);
  665. DispatchMessage(&msg);
  666. }
  667. }