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
811 lines
23 KiB
#include "pch.hxx"
|
|
#include "storutil.h"
|
|
#include <mailutil.h>
|
|
#include "range.h"
|
|
#include "shlwapip.h"
|
|
#include <xpcomm.h>
|
|
#include <subscr.h>
|
|
#include "newsstor.h"
|
|
#include <storecb.h>
|
|
#include "newsutil.h"
|
|
|
|
ASSERTDATA
|
|
|
|
static const char c_szCancelFmt[] = "cancel %s";
|
|
|
|
//
|
|
// FUNCTION: NewsUtil_FCanCancel
|
|
//
|
|
// PURPOSE: This function determines whether cancel should be allowed
|
|
//
|
|
// PARAMETERS: szDisplayFrom - the display portion of the From: field
|
|
// szEmailFrom - the address portion of the From: field
|
|
//
|
|
// RETURN VALUE: TRUE if cancel should be allowed
|
|
//
|
|
BOOL NewsUtil_FCanCancel(FOLDERID idFolder, LPMESSAGEINFO pInfo)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fRet;
|
|
FOLDERINFO info;
|
|
char sz[CCHMAX_DISPLAY_NAME];
|
|
IImnAccount *pAcct;
|
|
|
|
Assert(pInfo != NULL);
|
|
Assert(CCHMAX_EMAIL_ADDRESS <= CCHMAX_DISPLAY_NAME);
|
|
|
|
fRet = FALSE;
|
|
|
|
hr = g_pStore->GetFolderInfo(idFolder, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (info.tyFolder == FOLDER_NEWS &&
|
|
0 == (pInfo->dwFlags & ARF_ARTICLE_EXPIRED) &&
|
|
pInfo->pszAcctId != NULL &&
|
|
pInfo->pszDisplayFrom != NULL &&
|
|
pInfo->pszEmailFrom != NULL)
|
|
{
|
|
hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pInfo->pszAcctId, &pAcct);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
// make sure the display name and the email address match
|
|
if (SUCCEEDED(pAcct->GetPropSz(AP_NNTP_DISPLAY_NAME, sz, ARRAYSIZE(sz))))
|
|
{
|
|
if (!lstrcmp(pInfo->pszDisplayFrom, sz))
|
|
{
|
|
if (SUCCEEDED(pAcct->GetPropSz(AP_NNTP_EMAIL_ADDRESS, sz, ARRAYSIZE(sz))))
|
|
fRet = (0 == lstrcmp(pInfo->pszEmailFrom, sz));
|
|
}
|
|
}
|
|
|
|
pAcct->Release();
|
|
}
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(fRet);
|
|
}
|
|
|
|
//
|
|
// FUNCTION: NewsUtil_HrCancelPost
|
|
//
|
|
// PURPOSE: This function cancels the specified article
|
|
//
|
|
// PARAMETERS: hwnd - the hwnd for ui
|
|
// pszAccount - the account to use to cancel the article
|
|
// szMsgId - the Message-ID: of the article to cancel
|
|
// szFrom - the From: of the article to cancel
|
|
// szSubj - the Subject: of the article to cancel
|
|
// szGroups - the Newsgroups: of the article to cancel
|
|
// szDistrib - the Distribution: of the article to cancel
|
|
//
|
|
// RETURN VALUE: HRESULT
|
|
//
|
|
HRESULT NewsUtil_HrCancelPost(HWND hwnd, FOLDERID idGroup, LPMESSAGEINFO pInfo)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERINFO info;
|
|
LPMIMEMESSAGE pMsg;
|
|
LPSTR pszCancel;
|
|
IImnAccount *pAcct;
|
|
|
|
Assert(pInfo != NULL);
|
|
|
|
if (!NewsUtil_FCanCancel(idGroup, pInfo) && DwGetOption(OPT_CANCEL_ALL_NEWS))
|
|
{
|
|
if (AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
|
|
MAKEINTRESOURCEW(idsVerifyCancel),
|
|
NULL,
|
|
MB_YESNO) == IDNO)
|
|
{
|
|
return (FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
hr = g_pAcctMan->FindAccount(AP_ACCOUNT_ID, pInfo->pszAcctId, &pAcct);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
int cch = lstrlen(pInfo->pszMessageId) + 20;
|
|
if (!MemAlloc((void **)&pszCancel, cch))
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = g_pStore->GetFolderInfo(idGroup, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrCreateMessage(&pMsg);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
wnsprintf(pszCancel, cch, c_szCancelFmt, pInfo->pszMessageId);
|
|
MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_CONTROL), NOFLAGS, pszCancel);
|
|
|
|
MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_FROM), PDF_ENCODED | PDF_SAVENOENCODE, pInfo->pszFromHeader);
|
|
MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_SUBJECT), NOFLAGS, pInfo->pszSubject);
|
|
MimeOleSetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_NEWSGROUPS), NOFLAGS, info.pszName);
|
|
|
|
HrSetAccountByAccount(pMsg, pAcct);
|
|
|
|
hr = pMsg->Commit(0);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = HrSendMailToOutBox(hwnd, pMsg, TRUE, FALSE, FALSE);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
DoDontShowMeAgainDlg(hwnd, c_szDSCancelNews,
|
|
MAKEINTRESOURCE(idsAthena),
|
|
MAKEINTRESOURCE(idsDelSentToServer),
|
|
MB_OK);
|
|
}
|
|
else
|
|
{
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews),
|
|
MAKEINTRESOURCEW(idsCancelFailed), NULL, MB_OK);
|
|
}
|
|
}
|
|
|
|
pMsg->Release();
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
|
|
MemFree(pszCancel);
|
|
}
|
|
|
|
pAcct->Release();
|
|
|
|
return(hr);
|
|
}
|
|
|
|
DWORD NewsUtil_GetNotDownloadCount(FOLDERINFO *pInfo)
|
|
{
|
|
DWORD dw, curr, cOverlap, dwMax;
|
|
CRangeList *pRange;
|
|
|
|
Assert(pInfo != NULL);
|
|
|
|
dw = 0;
|
|
|
|
if (pInfo->dwServerHigh != 0 &&
|
|
pInfo->dwServerLow <= pInfo->dwServerHigh)
|
|
{
|
|
pRange = new CRangeList;
|
|
if (pRange != NULL)
|
|
{
|
|
dw = pInfo->dwServerCount;
|
|
|
|
if (pInfo->Requested.cbSize > 0)
|
|
{
|
|
pRange->Load(pInfo->Requested.pBlobData, pInfo->Requested.cbSize);
|
|
|
|
dwMax = pRange->Max();
|
|
|
|
Assert(pInfo->dwServerHigh >= dwMax);
|
|
if ((pInfo->dwServerHigh - dwMax) >= dw)
|
|
{
|
|
dw = 0;
|
|
}
|
|
else
|
|
{
|
|
dw -= pInfo->dwServerHigh - dwMax;
|
|
|
|
curr = pInfo->dwServerLow - 1;
|
|
cOverlap = 0;
|
|
|
|
while (-1 != (curr = pRange->Next(curr)))
|
|
cOverlap++;
|
|
if (cOverlap < dw)
|
|
dw -= cOverlap;
|
|
else
|
|
dw = 0;
|
|
}
|
|
|
|
Assert(dwMax >= pInfo->dwClientHigh);
|
|
if (pInfo->dwServerHigh > dwMax)
|
|
dw += pInfo->dwServerHigh - dwMax;
|
|
}
|
|
|
|
pRange->Release();
|
|
}
|
|
}
|
|
|
|
return(dw);
|
|
}
|
|
|
|
HRESULT NewsUtil_CheckForNewGroups(HWND hwnd, FOLDERID idFolder, CGetNewGroups **ppGroups)
|
|
{
|
|
HRESULT hr;
|
|
FILETIME ftLast;
|
|
FILETIME ftNow;
|
|
SYSTEMTIME stNow, stLast;
|
|
BOOL fUpdate;
|
|
IImnAccount *pAcct;
|
|
DWORD dwSize;
|
|
FOLDERINFO info;
|
|
CGetNewGroups *pGroups;
|
|
|
|
Assert(ppGroups != NULL);
|
|
Assert(*ppGroups == NULL);
|
|
|
|
hr = GetFolderServer(idFolder, &info);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
Assert(info.tyFolder == FOLDER_NEWS);
|
|
if (FHasChildren(&info, FALSE))
|
|
{
|
|
fUpdate = FALSE;
|
|
|
|
// Get the current time
|
|
GetSystemTime(&stNow);
|
|
SystemTimeToFileTime(&stNow, &ftNow);
|
|
|
|
// Get the account object for this server
|
|
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, info.pszAccountId, &pAcct)))
|
|
{
|
|
dwSize = sizeof(ftLast);
|
|
if (SUCCEEDED(pAcct->GetProp(AP_LAST_UPDATED, (LPBYTE)&ftLast, &dwSize)))
|
|
{
|
|
FileTimeToSystemTime(&ftLast, &stLast);
|
|
fUpdate = (stNow.wYear > stLast.wYear ||
|
|
stNow.wMonth > stLast.wMonth ||
|
|
stNow.wDay > stLast.wDay);
|
|
}
|
|
else
|
|
{
|
|
pAcct->SetProp(AP_LAST_UPDATED, (LPBYTE)&ftNow, sizeof(ftNow));
|
|
pAcct->SaveChanges();
|
|
}
|
|
|
|
pAcct->Release();
|
|
}
|
|
|
|
if (fUpdate)
|
|
{
|
|
pGroups = new CGetNewGroups(hwnd, info.idFolder, info.pszAccountId, &ftNow);
|
|
if (pGroups == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = g_pStore->GetNewGroups(info.idFolder, &stLast, (IStoreCallback *)pGroups);
|
|
if (hr == E_PENDING)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
pGroups->Release();
|
|
pGroups = NULL;
|
|
}
|
|
}
|
|
|
|
*ppGroups = pGroups;
|
|
}
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
CGetNewGroups::CGetNewGroups(HWND hwnd, FOLDERID idFolder, LPCSTR pszAcctId, FILETIME *pft)
|
|
{
|
|
Assert(hwnd != NULL);
|
|
Assert(idFolder != FOLDERID_INVALID);
|
|
Assert(pszAcctId != NULL);
|
|
Assert(pft != NULL);
|
|
|
|
m_cRef = 1;
|
|
m_hr = E_FAIL;
|
|
m_fComplete = FALSE;
|
|
m_type = SOT_INVALID;
|
|
m_pCancel = NULL;
|
|
|
|
m_hwnd = hwnd;
|
|
m_idFolder = idFolder;
|
|
StrCpyN(m_szAcctId, pszAcctId, ARRAYSIZE(m_szAcctId));
|
|
m_ft = *pft;
|
|
}
|
|
|
|
CGetNewGroups::~CGetNewGroups()
|
|
{
|
|
if (m_pCancel != NULL)
|
|
{
|
|
m_pCancel->Cancel(CT_ABORT);
|
|
m_pCancel->Release();
|
|
}
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppvObj = (void*) (IUnknown *)(IStoreCallback *)this;
|
|
else if (IsEqualIID(riid, IID_IStoreCallback))
|
|
*ppvObj = (void*) (IStoreCallback *) this;
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CGetNewGroups::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CGetNewGroups::Release()
|
|
{
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
HRESULT CGetNewGroups::Close()
|
|
{
|
|
if (m_pCancel != NULL)
|
|
m_pCancel->Cancel(CT_ABORT);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CGetNewGroups::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pInfo, IOperationCancel *pCancel)
|
|
{
|
|
Assert(tyOperation == SOT_GET_NEW_GROUPS);
|
|
Assert(m_pCancel == NULL);
|
|
|
|
m_type = tyOperation;
|
|
m_fComplete = FALSE;
|
|
|
|
if (pCancel != NULL)
|
|
{
|
|
m_pCancel = pCancel;
|
|
m_pCancel->AddRef();
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
|
|
{
|
|
Assert(!m_fComplete);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
|
|
{
|
|
return CallbackCanConnect(pszAccountId, m_hwnd, FALSE);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
|
|
{
|
|
// Call into general OnLogonPrompt Utility
|
|
return(S_FALSE);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
|
|
{
|
|
Assert(m_hwnd != NULL);
|
|
AssertSz(m_type != SOT_INVALID, "somebody isn't calling OnBegin");
|
|
|
|
if (m_type != tyOperation)
|
|
return(S_OK);
|
|
|
|
m_fComplete = TRUE;
|
|
m_hr = hrComplete;
|
|
|
|
if (m_pCancel != NULL)
|
|
{
|
|
m_pCancel->Release();
|
|
m_pCancel = NULL;
|
|
}
|
|
|
|
PostMessage(m_hwnd, NVM_GETNEWGROUPS, 0, 0);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
|
|
{
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CGetNewGroups::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
|
|
{
|
|
Assert(m_hwnd != NULL);
|
|
|
|
*phwndParent = m_hwnd;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CGetNewGroups::HandleGetNewGroups()
|
|
{
|
|
FOLDERINFO info;
|
|
IImnAccount *pAcct;
|
|
HRESULT hr;
|
|
|
|
Assert(m_fComplete);
|
|
|
|
if (m_hr == S_OK)
|
|
{
|
|
if (SUCCEEDED(g_pAcctMan->FindAccount(AP_ACCOUNT_ID, m_szAcctId, &pAcct)))
|
|
{
|
|
pAcct->SetProp(AP_LAST_UPDATED, (LPBYTE)&m_ft, sizeof(m_ft));
|
|
pAcct->SaveChanges();
|
|
pAcct->Release();
|
|
|
|
if (DwGetOption(OPT_NOTIFYGROUPS))
|
|
{
|
|
hr = g_pStore->GetFolderInfo(m_idFolder, &info);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
if (!!(info.dwFlags & FOLDER_HASNEWGROUPS))
|
|
{
|
|
// If there are new groups, ask the user if they care.
|
|
if (IDYES == AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
|
|
MAKEINTRESOURCEW(idsNewGroups), 0,
|
|
MB_ICONINFORMATION | MB_YESNO))
|
|
{
|
|
DoSubscriptionDialog(m_hwnd, TRUE, m_idFolder, TRUE);
|
|
}
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
class CDownloadArticleCB : public IStoreCallback, public ITimeoutCallback
|
|
{
|
|
public:
|
|
// IUnknown
|
|
virtual HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
|
|
virtual ULONG STDMETHODCALLTYPE AddRef(void);
|
|
virtual ULONG STDMETHODCALLTYPE Release(void);
|
|
|
|
// IStoreCallback
|
|
HRESULT STDMETHODCALLTYPE OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pInfo, IOperationCancel *pCancel);
|
|
HRESULT STDMETHODCALLTYPE OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus);
|
|
HRESULT STDMETHODCALLTYPE OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType);
|
|
HRESULT STDMETHODCALLTYPE CanConnect(LPCSTR pszAccountId, DWORD dwFlags);
|
|
HRESULT STDMETHODCALLTYPE OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType);
|
|
HRESULT STDMETHODCALLTYPE OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo);
|
|
HRESULT STDMETHODCALLTYPE OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse);
|
|
HRESULT STDMETHODCALLTYPE GetParentWindow(DWORD dwReserved, HWND *phwndParent);
|
|
|
|
// ITimeoutCallback
|
|
HRESULT STDMETHODCALLTYPE OnTimeoutResponse(TIMEOUTRESPONSE eResponse);
|
|
|
|
CDownloadArticleCB(void);
|
|
~CDownloadArticleCB(void);
|
|
|
|
HRESULT Download(LPCSTR pszAccountId, LPCSTR pszArticle, LPMIMEMESSAGE *ppMsg);
|
|
|
|
static INT_PTR CALLBACK DownloadArticleDlg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
|
|
|
private:
|
|
ULONG m_cRef;
|
|
HRESULT m_hr;
|
|
HWND m_hwndDlg;
|
|
BOOL m_fComplete;
|
|
STOREOPERATIONTYPE m_type;
|
|
IOperationCancel *m_pCancel;
|
|
HTIMEOUT m_hTimeout;
|
|
LPCSTR m_pszArticle;
|
|
LPSTREAM m_pStream;
|
|
CNewsStore *m_pNewsStore;
|
|
};
|
|
|
|
INT_PTR CALLBACK CDownloadArticleCB::DownloadArticleDlg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HRESULT hr;
|
|
TCHAR szBuffer[CCHMAX_STRINGRES];
|
|
TCHAR szRes[CCHMAX_STRINGRES];
|
|
CDownloadArticleCB *pThis = (CDownloadArticleCB *)GetWindowLongPtr(hwnd, DWLP_USER);
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
// replace some strings in the group download dialog
|
|
AthLoadString(idsDownloadArtTitle, szRes, sizeof(szRes));
|
|
SetWindowText(hwnd, szRes);
|
|
AthLoadString(idsDownloadArtMsg, szRes, sizeof(szRes));
|
|
SetDlgItemText(hwnd, idcStatic1, szRes);
|
|
|
|
CenterDialog(hwnd);
|
|
Assert(lParam);
|
|
pThis = (CDownloadArticleCB *)lParam;
|
|
SetWindowLongPtr(hwnd, DWLP_USER, lParam);
|
|
|
|
pThis->m_hwndDlg = hwnd;
|
|
|
|
Animate_Open(GetDlgItem(hwnd, idcAnimation), idanCopyMsgs);
|
|
Animate_Play(GetDlgItem(hwnd, idcAnimation), 0, -1, -1);
|
|
AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes));
|
|
wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szRes, 0);
|
|
SetDlgItemText(hwnd, idcProgText, szBuffer);
|
|
|
|
hr = pThis->m_pNewsStore->GetArticle(pThis->m_pszArticle, pThis->m_pStream, (IStoreCallback *)pThis);
|
|
if (hr == E_PENDING)
|
|
SetForegroundWindow(hwnd);
|
|
else
|
|
EndDialog(hwnd, 0);
|
|
return (TRUE);
|
|
|
|
case WM_COMMAND:
|
|
if (GET_WM_COMMAND_ID(wParam, lParam) == IDCANCEL)
|
|
{
|
|
Animate_Stop(GetDlgItem(hwnd, idcAnimation));
|
|
if (pThis->m_pCancel != NULL)
|
|
pThis->m_pCancel->Cancel(CT_ABORT);
|
|
return TRUE;
|
|
}
|
|
break;
|
|
|
|
case WM_STORE_COMPLETE:
|
|
EndDialog(hwnd, 0);
|
|
return(0);
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
CDownloadArticleCB::CDownloadArticleCB()
|
|
{
|
|
m_cRef = 1;
|
|
m_hr = E_FAIL;
|
|
m_hwndDlg = NULL;
|
|
m_fComplete = FALSE;
|
|
m_type = SOT_INVALID;
|
|
m_pCancel = NULL;
|
|
m_hTimeout = NULL;
|
|
m_pszArticle = NULL;
|
|
m_pNewsStore = NULL;
|
|
m_pStream = NULL;
|
|
}
|
|
|
|
CDownloadArticleCB::~CDownloadArticleCB()
|
|
{
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
if (m_pCancel != NULL)
|
|
m_pCancel->Release();
|
|
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::QueryInterface(REFIID riid, void **ppvObj)
|
|
{
|
|
if (IsEqualIID(riid, IID_IUnknown))
|
|
*ppvObj = (void*) (IUnknown *)(IStoreCallback *)this;
|
|
else if (IsEqualIID(riid, IID_IStoreCallback))
|
|
*ppvObj = (void*) (IStoreCallback *) this;
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CDownloadArticleCB::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE CDownloadArticleCB::Release()
|
|
{
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
HRESULT CDownloadArticleCB::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pInfo, IOperationCancel *pCancel)
|
|
{
|
|
Assert(tyOperation != SOT_INVALID);
|
|
Assert(m_pCancel == NULL);
|
|
|
|
m_type = tyOperation;
|
|
m_fComplete = FALSE;
|
|
|
|
if (pCancel != NULL)
|
|
{
|
|
m_pCancel = pCancel;
|
|
m_pCancel->AddRef();
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
|
|
{
|
|
TCHAR szBuffer[CCHMAX_STRINGRES];
|
|
TCHAR szRes[CCHMAX_STRINGRES];
|
|
|
|
Assert(m_hwndDlg != NULL);
|
|
Assert(!m_fComplete);
|
|
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
if (tyOperation == SOT_GET_MESSAGE)
|
|
{
|
|
AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes));
|
|
wnsprintf(szBuffer, ARRAYSIZE(szBuffer),szRes, dwCurrent);
|
|
SetDlgItemText(m_hwndDlg, idcProgText, szBuffer);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
|
|
{
|
|
// Display a timeout dialog
|
|
return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
|
|
{
|
|
// Call into general timeout response utility
|
|
return CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
|
|
{
|
|
return CallbackCanConnect(pszAccountId, m_hwndDlg,
|
|
(dwFlags & CC_FLAG_DONTPROMPT) ? FALSE : TRUE);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
|
|
{
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Call into general OnLogonPrompt Utility
|
|
return CallbackOnLogonPrompt(m_hwndDlg, pServer, ixpServerType);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
|
|
{
|
|
Assert(m_hwndDlg != NULL);
|
|
AssertSz(m_type != SOT_INVALID, "somebody isn't calling OnBegin");
|
|
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
if (m_type != tyOperation)
|
|
return(S_OK);
|
|
|
|
m_fComplete = TRUE;
|
|
m_hr = hrComplete;
|
|
|
|
if (m_pCancel != NULL)
|
|
{
|
|
m_pCancel->Release();
|
|
m_pCancel = NULL;
|
|
}
|
|
|
|
// If error occurred, display the error
|
|
if (FAILED(hrComplete))
|
|
{
|
|
// Call into my swanky utility
|
|
CallbackDisplayError(m_hwndDlg, hrComplete, pErrorInfo);
|
|
}
|
|
|
|
PostMessage(m_hwndDlg, WM_STORE_COMPLETE, 0, 0);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
|
|
{
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
// Call into my swanky utility
|
|
return CallbackOnPrompt(m_hwndDlg, hrError, pszText, pszCaption, uType, piUserResponse);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE CDownloadArticleCB::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
|
|
{
|
|
Assert(m_hwndDlg != NULL);
|
|
|
|
*phwndParent = m_hwndDlg;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CDownloadArticleCB::Download(LPCSTR pszAccountId, LPCSTR pszArticle, LPMIMEMESSAGE *ppMsg)
|
|
{
|
|
FOLDERID idServer;
|
|
HRESULT hr;
|
|
LPMIMEMESSAGE pMsg;
|
|
|
|
Assert(pszAccountId != NULL);
|
|
Assert(pszArticle != NULL);
|
|
Assert(ppMsg != NULL);
|
|
|
|
hr = g_pStore->FindServerId(pszAccountId, &idServer);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
m_pNewsStore = new CNewsStore;
|
|
if (m_pNewsStore == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
hr = m_pNewsStore->Initialize(idServer, pszAccountId);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (SUCCEEDED(hr = HrCreateMessage(&pMsg)))
|
|
{
|
|
if (SUCCEEDED(hr = MimeOleCreateVirtualStream(&m_pStream)))
|
|
{
|
|
m_pszArticle = pszArticle;
|
|
DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddDownloadGroups), NULL,
|
|
DownloadArticleDlg, (LPARAM)this);
|
|
if (m_hr == S_OK)
|
|
{
|
|
pMsg->Load(m_pStream);
|
|
*ppMsg = pMsg;
|
|
(*ppMsg)->AddRef();
|
|
}
|
|
|
|
hr = m_hr;
|
|
|
|
m_pStream->Release();
|
|
}
|
|
|
|
pMsg->Release();
|
|
}
|
|
|
|
m_pNewsStore->Close(MSGSVRF_HANDS_OFF_SERVER);
|
|
}
|
|
|
|
m_pNewsStore->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT HrDownloadArticleDialog(LPCSTR pszAccountId, LPCSTR pszArticle, LPMIMEMESSAGE *ppMsg)
|
|
{
|
|
CDownloadArticleCB *pCB;
|
|
HRESULT hr;
|
|
|
|
pCB = new CDownloadArticleCB;
|
|
if (pCB == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
hr = pCB->Download(pszAccountId, pszArticle, ppMsg);
|
|
|
|
pCB->Release();
|
|
|
|
return hr;
|
|
}
|