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.

811 lines
23 KiB

  1. #include "pch.hxx"
  2. #include "storutil.h"
  3. #include <mailutil.h>
  4. #include "range.h"
  5. #include "shlwapip.h"
  6. #include <xpcomm.h>
  7. #include <subscr.h>
  8. #include "newsstor.h"
  9. #include <storecb.h>
  10. #include "newsutil.h"
  11. ASSERTDATA
  12. static const char c_szCancelFmt[] = "cancel %s";
  13. //
  14. // FUNCTION: NewsUtil_FCanCancel
  15. //
  16. // PURPOSE: This function determines whether cancel should be allowed
  17. //
  18. // PARAMETERS: szDisplayFrom - the display portion of the From: field
  19. // szEmailFrom - the address portion of the From: field
  20. //
  21. // RETURN VALUE: TRUE if cancel should be allowed
  22. //
  23. BOOL NewsUtil_FCanCancel(FOLDERID idFolder, LPMESSAGEINFO pInfo)
  24. {
  25. HRESULT hr;
  26. BOOL fRet;
  27. FOLDERINFO info;
  28. char sz[CCHMAX_DISPLAY_NAME];
  29. IImnAccount *pAcct;
  30. Assert(pInfo != NULL);
  31. Assert(CCHMAX_EMAIL_ADDRESS <= CCHMAX_DISPLAY_NAME);
  32. fRet = FALSE;
  33. hr = g_pStore->GetFolderInfo(idFolder, &info);
  34. if (SUCCEEDED(hr))
  35. {
  36. if (info.tyFolder == FOLDER_NEWS &&
  37. 0 == (pInfo->dwFlags & ARF_ARTICLE_EXPIRED) &&
  38. pInfo->pszAcctId != NULL &&
  39. pInfo->pszDisplayFrom != NULL &&
  40. pInfo->pszEmailFrom != NULL)
  41. {
  42. hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pInfo->pszAcctId, &pAcct);
  43. if (SUCCEEDED(hr))
  44. {
  45. // make sure the display name and the email address match
  46. if (SUCCEEDED(pAcct->GetPropSz(AP_NNTP_DISPLAY_NAME, sz, ARRAYSIZE(sz))))
  47. {
  48. if (!lstrcmp(pInfo->pszDisplayFrom, sz))
  49. {
  50. if (SUCCEEDED(pAcct->GetPropSz(AP_NNTP_EMAIL_ADDRESS, sz, ARRAYSIZE(sz))))
  51. fRet = (0 == lstrcmp(pInfo->pszEmailFrom, sz));
  52. }
  53. }
  54. pAcct->Release();
  55. }
  56. }
  57. g_pStore->FreeRecord(&info);
  58. }
  59. return(fRet);
  60. }
  61. //
  62. // FUNCTION: NewsUtil_HrCancelPost
  63. //
  64. // PURPOSE: This function cancels the specified article
  65. //
  66. // PARAMETERS: hwnd - the hwnd for ui
  67. // pszAccount - the account to use to cancel the article
  68. // szMsgId - the Message-ID: of the article to cancel
  69. // szFrom - the From: of the article to cancel
  70. // szSubj - the Subject: of the article to cancel
  71. // szGroups - the Newsgroups: of the article to cancel
  72. // szDistrib - the Distribution: of the article to cancel
  73. //
  74. // RETURN VALUE: HRESULT
  75. //
  76. HRESULT NewsUtil_HrCancelPost(HWND hwnd, FOLDERID idGroup, LPMESSAGEINFO pInfo)
  77. {
  78. HRESULT hr;
  79. FOLDERINFO info;
  80. LPMIMEMESSAGE pMsg;
  81. LPSTR pszCancel;
  82. IImnAccount *pAcct;
  83. Assert(pInfo != NULL);
  84. if (!NewsUtil_FCanCancel(idGroup, pInfo) && DwGetOption(OPT_CANCEL_ALL_NEWS))
  85. {
  86. if (AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
  87. MAKEINTRESOURCEW(idsVerifyCancel),
  88. NULL,
  89. MB_YESNO) == IDNO)
  90. {
  91. return (FALSE);
  92. }
  93. }
  94. hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pInfo->pszAcctId, &pAcct);
  95. if (FAILED(hr))
  96. return(hr);
  97. int cch = lstrlen(pInfo->pszMessageId) + 20;
  98. if (!MemAlloc((void **)&pszCancel, cch))
  99. {
  100. hr = E_OUTOFMEMORY;
  101. }
  102. else
  103. {
  104. hr = g_pStore->GetFolderInfo(idGroup, &info);
  105. if (SUCCEEDED(hr))
  106. {
  107. hr = HrCreateMessage(&pMsg);
  108. if (SUCCEEDED(hr))
  109. {
  110. wnsprintf(pszCancel, cch, c_szCancelFmt, pInfo->pszMessageId);
  111. MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_CONTROL), NOFLAGS, pszCancel);
  112. MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FROM), PDF_ENCODED | PDF_SAVENOENCODE, pInfo->pszFromHeader);
  113. MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, pInfo->pszSubject);
  114. MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_NEWSGROUPS), NOFLAGS, info.pszName);
  115. HrSetAccountByAccount(pMsg, pAcct);
  116. hr = pMsg->Commit(0);
  117. if (SUCCEEDED(hr))
  118. {
  119. hr = HrSendMailToOutBox(hwnd, pMsg, TRUE, FALSE, FALSE);
  120. if (SUCCEEDED(hr))
  121. {
  122. DoDontShowMeAgainDlg(hwnd, c_szDSCancelNews,
  123. MAKEINTRESOURCE(idsAthena),
  124. MAKEINTRESOURCE(idsDelSentToServer),
  125. MB_OK);
  126. }
  127. else
  128. {
  129. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
  130. MAKEINTRESOURCEW(idsCancelFailed), NULL, MB_OK);
  131. }
  132. }
  133. pMsg->Release();
  134. }
  135. g_pStore->FreeRecord(&info);
  136. }
  137. MemFree(pszCancel);
  138. }
  139. pAcct->Release();
  140. return(hr);
  141. }
  142. DWORD NewsUtil_GetNotDownloadCount(FOLDERINFO *pInfo)
  143. {
  144. DWORD dw, curr, cOverlap, dwMax;
  145. CRangeList *pRange;
  146. Assert(pInfo != NULL);
  147. dw = 0;
  148. if (pInfo->dwServerHigh != 0 &&
  149. pInfo->dwServerLow <= pInfo->dwServerHigh)
  150. {
  151. pRange = new CRangeList;
  152. if (pRange != NULL)
  153. {
  154. dw = pInfo->dwServerCount;
  155. if (pInfo->Requested.cbSize > 0)
  156. {
  157. pRange->Load(pInfo->Requested.pBlobData, pInfo->Requested.cbSize);
  158. dwMax = pRange->Max();
  159. Assert(pInfo->dwServerHigh >= dwMax);
  160. if ((pInfo->dwServerHigh - dwMax) >= dw)
  161. {
  162. dw = 0;
  163. }
  164. else
  165. {
  166. dw -= pInfo->dwServerHigh - dwMax;
  167. curr = pInfo->dwServerLow - 1;
  168. cOverlap = 0;
  169. while (-1 != (curr = pRange->Next(curr)))
  170. cOverlap++;
  171. if (cOverlap < dw)
  172. dw -= cOverlap;
  173. else
  174. dw = 0;
  175. }
  176. Assert(dwMax >= pInfo->dwClientHigh);
  177. if (pInfo->dwServerHigh > dwMax)
  178. dw += pInfo->dwServerHigh - dwMax;
  179. }
  180. pRange->Release();
  181. }
  182. }
  183. return(dw);
  184. }
  185. HRESULT NewsUtil_CheckForNewGroups(HWND hwnd, FOLDERID idFolder, CGetNewGroups **ppGroups)
  186. {
  187. HRESULT hr;
  188. FILETIME ftLast;
  189. FILETIME ftNow;
  190. SYSTEMTIME stNow, stLast;
  191. BOOL fUpdate;
  192. IImnAccount *pAcct;
  193. DWORD dwSize;
  194. FOLDERINFO info;
  195. CGetNewGroups *pGroups;
  196. Assert(ppGroups != NULL);
  197. Assert(*ppGroups == NULL);
  198. hr = GetFolderServer(idFolder, &info);
  199. if (FAILED(hr))
  200. return(hr);
  201. Assert(info.tyFolder == FOLDER_NEWS);
  202. if (FHasChildren(&info, FALSE))
  203. {
  204. fUpdate = FALSE;
  205. // Get the current time
  206. GetSystemTime(&stNow);
  207. SystemTimeToFileTime(&stNow, &ftNow);
  208. // Get the account object for this server
  209. if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, info.pszAccountId, &pAcct)))
  210. {
  211. dwSize = sizeof(ftLast);
  212. if (SUCCEEDED(pAcct->GetProp(AP_LAST_UPDATED, (LPBYTE)&ftLast, &dwSize)))
  213. {
  214. FileTimeToSystemTime(&ftLast, &stLast);
  215. fUpdate = (stNow.wYear > stLast.wYear ||
  216. stNow.wMonth > stLast.wMonth ||
  217. stNow.wDay > stLast.wDay);
  218. }
  219. else
  220. {
  221. pAcct->SetProp(AP_LAST_UPDATED, (LPBYTE)&ftNow, sizeof(ftNow));
  222. pAcct->SaveChanges();
  223. }
  224. pAcct->Release();
  225. }
  226. if (fUpdate)
  227. {
  228. pGroups = new CGetNewGroups(hwnd, info.idFolder, info.pszAccountId, &ftNow);
  229. if (pGroups == NULL)
  230. {
  231. hr = E_OUTOFMEMORY;
  232. }
  233. else
  234. {
  235. hr = g_pStore->GetNewGroups(info.idFolder, &stLast, (IStoreCallback *)pGroups);
  236. if (hr == E_PENDING)
  237. {
  238. hr = S_OK;
  239. }
  240. else
  241. {
  242. pGroups->Release();
  243. pGroups = NULL;
  244. }
  245. }
  246. *ppGroups = pGroups;
  247. }
  248. }
  249. g_pStore->FreeRecord(&info);
  250. return(hr);
  251. }
  252. CGetNewGroups::CGetNewGroups(HWND hwnd, FOLDERID idFolder, LPCSTR pszAcctId, FILETIME *pft)
  253. {
  254. Assert(hwnd != NULL);
  255. Assert(idFolder != FOLDERID_INVALID);
  256. Assert(pszAcctId != NULL);
  257. Assert(pft != NULL);
  258. m_cRef = 1;
  259. m_hr = E_FAIL;
  260. m_fComplete = FALSE;
  261. m_type = SOT_INVALID;
  262. m_pCancel = NULL;
  263. m_hwnd = hwnd;
  264. m_idFolder = idFolder;
  265. StrCpyN(m_szAcctId, pszAcctId, ARRAYSIZE(m_szAcctId));
  266. m_ft = *pft;
  267. }
  268. CGetNewGroups::~CGetNewGroups()
  269. {
  270. if (m_pCancel != NULL)
  271. {
  272. m_pCancel->Cancel(CT_ABORT);
  273. m_pCancel->Release();
  274. }
  275. }
  276. HRESULT STDMETHODCALLTYPE CGetNewGroups::QueryInterface(REFIID riid, void **ppvObj)
  277. {
  278. if (IsEqualIID(riid, IID_IUnknown))
  279. *ppvObj = (void*) (IUnknown *)(IStoreCallback *)this;
  280. else if (IsEqualIID(riid, IID_IStoreCallback))
  281. *ppvObj = (void*) (IStoreCallback *) this;
  282. else
  283. {
  284. *ppvObj = NULL;
  285. return E_NOINTERFACE;
  286. }
  287. AddRef();
  288. return S_OK;
  289. }
  290. ULONG STDMETHODCALLTYPE CGetNewGroups::AddRef()
  291. {
  292. return ++m_cRef;
  293. }
  294. ULONG STDMETHODCALLTYPE CGetNewGroups::Release()
  295. {
  296. if (--m_cRef == 0)
  297. {
  298. delete this;
  299. return 0;
  300. }
  301. return m_cRef;
  302. }
  303. HRESULT CGetNewGroups::Close()
  304. {
  305. if (m_pCancel != NULL)
  306. m_pCancel->Cancel(CT_ABORT);
  307. return(S_OK);
  308. }
  309. HRESULT CGetNewGroups::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pInfo, IOperationCancel *pCancel)
  310. {
  311. Assert(tyOperation == SOT_GET_NEW_GROUPS);
  312. Assert(m_pCancel == NULL);
  313. m_type = tyOperation;
  314. m_fComplete = FALSE;
  315. if (pCancel != NULL)
  316. {
  317. m_pCancel = pCancel;
  318. m_pCancel->AddRef();
  319. }
  320. return(S_OK);
  321. }
  322. HRESULT STDMETHODCALLTYPE CGetNewGroups::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
  323. {
  324. Assert(!m_fComplete);
  325. return(S_OK);
  326. }
  327. HRESULT STDMETHODCALLTYPE CGetNewGroups::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
  328. {
  329. return(E_NOTIMPL);
  330. }
  331. HRESULT STDMETHODCALLTYPE CGetNewGroups::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
  332. {
  333. return CallbackCanConnect(pszAccountId, m_hwnd, FALSE);
  334. }
  335. HRESULT STDMETHODCALLTYPE CGetNewGroups::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
  336. {
  337. // Call into general OnLogonPrompt Utility
  338. return(S_FALSE);
  339. }
  340. HRESULT STDMETHODCALLTYPE CGetNewGroups::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
  341. {
  342. Assert(m_hwnd != NULL);
  343. AssertSz(m_type != SOT_INVALID, "somebody isn't calling OnBegin");
  344. if (m_type != tyOperation)
  345. return(S_OK);
  346. m_fComplete = TRUE;
  347. m_hr = hrComplete;
  348. if (m_pCancel != NULL)
  349. {
  350. m_pCancel->Release();
  351. m_pCancel = NULL;
  352. }
  353. PostMessage(m_hwnd, NVM_GETNEWGROUPS, 0, 0);
  354. return(S_OK);
  355. }
  356. HRESULT STDMETHODCALLTYPE CGetNewGroups::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
  357. {
  358. return(E_NOTIMPL);
  359. }
  360. HRESULT STDMETHODCALLTYPE CGetNewGroups::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
  361. {
  362. Assert(m_hwnd != NULL);
  363. *phwndParent = m_hwnd;
  364. return(S_OK);
  365. }
  366. HRESULT CGetNewGroups::HandleGetNewGroups()
  367. {
  368. FOLDERINFO info;
  369. IImnAccount *pAcct;
  370. HRESULT hr;
  371. Assert(m_fComplete);
  372. if (m_hr == S_OK)
  373. {
  374. if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, m_szAcctId, &pAcct)))
  375. {
  376. pAcct->SetProp(AP_LAST_UPDATED, (LPBYTE)&m_ft, sizeof(m_ft));
  377. pAcct->SaveChanges();
  378. pAcct->Release();
  379. if (DwGetOption(OPT_NOTIFYGROUPS))
  380. {
  381. hr = g_pStore->GetFolderInfo(m_idFolder, &info);
  382. if (FAILED(hr))
  383. return(hr);
  384. if (!!(info.dwFlags & FOLDER_HASNEWGROUPS))
  385. {
  386. // If there are new groups, ask the user if they care.
  387. if (IDYES == AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
  388. MAKEINTRESOURCEW(idsNewGroups), 0,
  389. MB_ICONINFORMATION | MB_YESNO))
  390. {
  391. DoSubscriptionDialog(m_hwnd, TRUE, m_idFolder, TRUE);
  392. }
  393. }
  394. g_pStore->FreeRecord(&info);
  395. }
  396. }
  397. }
  398. return(S_OK);
  399. }
  400. class CDownloadArticleCB : public IStoreCallback, public ITimeoutCallback
  401. {
  402. public:
  403. // IUnknown
  404. virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
  405. virtual ULONG STDMETHODCALLTYPE AddRef(void);
  406. virtual ULONG STDMETHODCALLTYPE Release(void);
  407. // IStoreCallback
  408. HRESULT STDMETHODCALLTYPE OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pInfo, IOperationCancel *pCancel);
  409. HRESULT STDMETHODCALLTYPE OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus);
  410. HRESULT STDMETHODCALLTYPE OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType);
  411. HRESULT STDMETHODCALLTYPE CanConnect(LPCSTR pszAccountId, DWORD dwFlags);
  412. HRESULT STDMETHODCALLTYPE OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType);
  413. HRESULT STDMETHODCALLTYPE OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo);
  414. HRESULT STDMETHODCALLTYPE OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse);
  415. HRESULT STDMETHODCALLTYPE GetParentWindow(DWORD dwReserved, HWND *phwndParent);
  416. // ITimeoutCallback
  417. HRESULT STDMETHODCALLTYPE OnTimeoutResponse(TIMEOUTRESPONSE eResponse);
  418. CDownloadArticleCB(void);
  419. ~CDownloadArticleCB(void);
  420. HRESULT Download(LPCSTR pszAccountId, LPCSTR pszArticle, LPMIMEMESSAGE *ppMsg);
  421. static INT_PTR CALLBACK DownloadArticleDlg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  422. private:
  423. ULONG m_cRef;
  424. HRESULT m_hr;
  425. HWND m_hwndDlg;
  426. BOOL m_fComplete;
  427. STOREOPERATIONTYPE m_type;
  428. IOperationCancel *m_pCancel;
  429. HTIMEOUT m_hTimeout;
  430. LPCSTR m_pszArticle;
  431. LPSTREAM m_pStream;
  432. CNewsStore *m_pNewsStore;
  433. };
  434. INT_PTR CALLBACK CDownloadArticleCB::DownloadArticleDlg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  435. {
  436. HRESULT hr;
  437. TCHAR szBuffer[CCHMAX_STRINGRES];
  438. TCHAR szRes[CCHMAX_STRINGRES];
  439. CDownloadArticleCB *pThis = (CDownloadArticleCB *)GetWindowLongPtr(hwnd, DWLP_USER);
  440. switch (msg)
  441. {
  442. case WM_INITDIALOG:
  443. // replace some strings in the group download dialog
  444. AthLoadString(idsDownloadArtTitle, szRes, sizeof(szRes));
  445. SetWindowText(hwnd, szRes);
  446. AthLoadString(idsDownloadArtMsg, szRes, sizeof(szRes));
  447. SetDlgItemText(hwnd, idcStatic1, szRes);
  448. CenterDialog(hwnd);
  449. Assert(lParam);
  450. pThis = (CDownloadArticleCB *)lParam;
  451. SetWindowLongPtr(hwnd, DWLP_USER, lParam);
  452. pThis->m_hwndDlg = hwnd;
  453. Animate_Open(GetDlgItem(hwnd, idcAnimation), idanCopyMsgs);
  454. Animate_Play(GetDlgItem(hwnd, idcAnimation), 0, -1, -1);
  455. AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes));
  456. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szRes, 0);
  457. SetDlgItemText(hwnd, idcProgText, szBuffer);
  458. hr = pThis->m_pNewsStore->GetArticle(pThis->m_pszArticle, pThis->m_pStream, (IStoreCallback *)pThis);
  459. if (hr == E_PENDING)
  460. SetForegroundWindow(hwnd);
  461. else
  462. EndDialog(hwnd, 0);
  463. return (TRUE);
  464. case WM_COMMAND:
  465. if (GET_WM_COMMAND_ID(wParam, lParam) == IDCANCEL)
  466. {
  467. Animate_Stop(GetDlgItem(hwnd, idcAnimation));
  468. if (pThis->m_pCancel != NULL)
  469. pThis->m_pCancel->Cancel(CT_ABORT);
  470. return TRUE;
  471. }
  472. break;
  473. case WM_STORE_COMPLETE:
  474. EndDialog(hwnd, 0);
  475. return(0);
  476. }
  477. return FALSE;
  478. }
  479. CDownloadArticleCB::CDownloadArticleCB()
  480. {
  481. m_cRef = 1;
  482. m_hr = E_FAIL;
  483. m_hwndDlg = NULL;
  484. m_fComplete = FALSE;
  485. m_type = SOT_INVALID;
  486. m_pCancel = NULL;
  487. m_hTimeout = NULL;
  488. m_pszArticle = NULL;
  489. m_pNewsStore = NULL;
  490. m_pStream = NULL;
  491. }
  492. CDownloadArticleCB::~CDownloadArticleCB()
  493. {
  494. CallbackCloseTimeout(&m_hTimeout);
  495. if (m_pCancel != NULL)
  496. m_pCancel->Release();
  497. }
  498. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::QueryInterface(REFIID riid, void **ppvObj)
  499. {
  500. if (IsEqualIID(riid, IID_IUnknown))
  501. *ppvObj = (void*) (IUnknown *)(IStoreCallback *)this;
  502. else if (IsEqualIID(riid, IID_IStoreCallback))
  503. *ppvObj = (void*) (IStoreCallback *) this;
  504. else
  505. {
  506. *ppvObj = NULL;
  507. return E_NOINTERFACE;
  508. }
  509. AddRef();
  510. return S_OK;
  511. }
  512. ULONG STDMETHODCALLTYPE CDownloadArticleCB::AddRef()
  513. {
  514. return ++m_cRef;
  515. }
  516. ULONG STDMETHODCALLTYPE CDownloadArticleCB::Release()
  517. {
  518. if (--m_cRef == 0)
  519. {
  520. delete this;
  521. return 0;
  522. }
  523. return m_cRef;
  524. }
  525. HRESULT CDownloadArticleCB::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pInfo, IOperationCancel *pCancel)
  526. {
  527. Assert(tyOperation != SOT_INVALID);
  528. Assert(m_pCancel == NULL);
  529. m_type = tyOperation;
  530. m_fComplete = FALSE;
  531. if (pCancel != NULL)
  532. {
  533. m_pCancel = pCancel;
  534. m_pCancel->AddRef();
  535. }
  536. return(S_OK);
  537. }
  538. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
  539. {
  540. TCHAR szBuffer[CCHMAX_STRINGRES];
  541. TCHAR szRes[CCHMAX_STRINGRES];
  542. Assert(m_hwndDlg != NULL);
  543. Assert(!m_fComplete);
  544. // Close any timeout dialog, if present
  545. CallbackCloseTimeout(&m_hTimeout);
  546. if (tyOperation == SOT_GET_MESSAGE)
  547. {
  548. AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes));
  549. wnsprintf(szBuffer, ARRAYSIZE(szBuffer),szRes, dwCurrent);
  550. SetDlgItemText(m_hwndDlg, idcProgText, szBuffer);
  551. }
  552. return(S_OK);
  553. }
  554. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
  555. {
  556. // Display a timeout dialog
  557. return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
  558. }
  559. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
  560. {
  561. // Call into general timeout response utility
  562. return CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
  563. }
  564. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
  565. {
  566. return CallbackCanConnect(pszAccountId, m_hwndDlg,
  567. (dwFlags & CC_FLAG_DONTPROMPT) ? FALSE : TRUE);
  568. }
  569. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
  570. {
  571. // Close any timeout dialog, if present
  572. CallbackCloseTimeout(&m_hTimeout);
  573. // Call into general OnLogonPrompt Utility
  574. return CallbackOnLogonPrompt(m_hwndDlg, pServer, ixpServerType);
  575. }
  576. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
  577. {
  578. Assert(m_hwndDlg != NULL);
  579. AssertSz(m_type != SOT_INVALID, "somebody isn't calling OnBegin");
  580. // Close any timeout dialog, if present
  581. CallbackCloseTimeout(&m_hTimeout);
  582. if (m_type != tyOperation)
  583. return(S_OK);
  584. m_fComplete = TRUE;
  585. m_hr = hrComplete;
  586. if (m_pCancel != NULL)
  587. {
  588. m_pCancel->Release();
  589. m_pCancel = NULL;
  590. }
  591. // If error occurred, display the error
  592. if (FAILED(hrComplete))
  593. {
  594. // Call into my swanky utility
  595. CallbackDisplayError(m_hwndDlg, hrComplete, pErrorInfo);
  596. }
  597. PostMessage(m_hwndDlg, WM_STORE_COMPLETE, 0, 0);
  598. return(S_OK);
  599. }
  600. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
  601. {
  602. // Close any timeout dialog, if present
  603. CallbackCloseTimeout(&m_hTimeout);
  604. // Call into my swanky utility
  605. return CallbackOnPrompt(m_hwndDlg, hrError, pszText, pszCaption, uType, piUserResponse);
  606. }
  607. HRESULT STDMETHODCALLTYPE CDownloadArticleCB::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
  608. {
  609. Assert(m_hwndDlg != NULL);
  610. *phwndParent = m_hwndDlg;
  611. return(S_OK);
  612. }
  613. HRESULT CDownloadArticleCB::Download(LPCSTR pszAccountId, LPCSTR pszArticle, LPMIMEMESSAGE *ppMsg)
  614. {
  615. FOLDERID idServer;
  616. HRESULT hr;
  617. LPMIMEMESSAGE pMsg;
  618. Assert(pszAccountId != NULL);
  619. Assert(pszArticle != NULL);
  620. Assert(ppMsg != NULL);
  621. hr = g_pStore->FindServerId(pszAccountId, &idServer);
  622. if (FAILED(hr))
  623. return(hr);
  624. m_pNewsStore = new CNewsStore;
  625. if (m_pNewsStore == NULL)
  626. return(E_OUTOFMEMORY);
  627. hr = m_pNewsStore->Initialize(idServer, pszAccountId);
  628. if (SUCCEEDED(hr))
  629. {
  630. if (SUCCEEDED(hr = HrCreateMessage(&pMsg)))
  631. {
  632. if (SUCCEEDED(hr = MimeOleCreateVirtualStream(&m_pStream)))
  633. {
  634. m_pszArticle = pszArticle;
  635. DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddDownloadGroups), NULL,
  636. DownloadArticleDlg, (LPARAM)this);
  637. if (m_hr == S_OK)
  638. {
  639. pMsg->Load(m_pStream);
  640. *ppMsg = pMsg;
  641. (*ppMsg)->AddRef();
  642. }
  643. hr = m_hr;
  644. m_pStream->Release();
  645. }
  646. pMsg->Release();
  647. }
  648. m_pNewsStore->Close(MSGSVRF_HANDS_OFF_SERVER);
  649. }
  650. m_pNewsStore->Release();
  651. return hr;
  652. }
  653. HRESULT HrDownloadArticleDialog(LPCSTR pszAccountId, LPCSTR pszArticle, LPMIMEMESSAGE *ppMsg)
  654. {
  655. CDownloadArticleCB *pCB;
  656. HRESULT hr;
  657. pCB = new CDownloadArticleCB;
  658. if (pCB == NULL)
  659. return(E_OUTOFMEMORY);
  660. hr = pCB->Download(pszAccountId, pszArticle, ppMsg);
  661. pCB->Release();
  662. return hr;
  663. }