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.
1438 lines
42 KiB
1438 lines
42 KiB
#include "pch.hxx"
|
|
#include "store.h"
|
|
#include "instance.h"
|
|
#include "msgfldr.h"
|
|
#include "secutil.h"
|
|
#include "storutil.h"
|
|
#include "fldrsync.h"
|
|
#include <conman.h>
|
|
#include "shlwapip.h"
|
|
#include "sync.h"
|
|
|
|
static char c_szFolderSyncWndClass[] = "Outlook Express FolderSync Window Class";
|
|
|
|
static const PFNCOPYFUNC c_rgpfnCopyMsgs[] =
|
|
{
|
|
&CFolderSync::CopyOpen,
|
|
&CFolderSync::CopySave,
|
|
&CFolderSync::CopySave2,
|
|
&CFolderSync::CopyDelete,
|
|
&CFolderSync::CopyDelete2,
|
|
};
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::CFolderSync
|
|
//--------------------------------------------------------------------------
|
|
CFolderSync::CFolderSync(void)
|
|
{
|
|
g_pInstance->DllAddRef();
|
|
m_cRef = 1;
|
|
m_pLocalStore = NULL;
|
|
m_pFldr = NULL;
|
|
m_tyFolder = FOLDER_INVALID;
|
|
m_idFolder = FOLDERID_INVALID;
|
|
m_idServer = FOLDERID_INVALID;
|
|
m_szAcctId[0] = 0;
|
|
m_pServer = NULL;
|
|
m_fConManAdvise = FALSE;
|
|
m_hwnd = NULL;
|
|
m_pCopy = NULL;
|
|
m_fImap = FALSE;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::~CFolderSync
|
|
//--------------------------------------------------------------------------
|
|
CFolderSync::~CFolderSync(void)
|
|
{
|
|
Assert(m_pCopy == NULL);
|
|
|
|
if (m_fConManAdvise && g_pConMan != NULL)
|
|
g_pConMan->Unadvise((IConnectionNotify *)this);
|
|
|
|
if (m_hwnd != NULL)
|
|
{
|
|
if (GetWindowThreadProcessId(m_hwnd, NULL) == GetCurrentThreadId())
|
|
{
|
|
DestroyWindow(m_hwnd);
|
|
}
|
|
else
|
|
{
|
|
SetWindowLongPtr(m_hwnd, GWLP_USERDATA, NULL);
|
|
PostMessage(m_hwnd, WM_CLOSE, 0, 0L);
|
|
}
|
|
}
|
|
|
|
if (m_pServer)
|
|
{
|
|
m_pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
|
|
m_pServer->Release();
|
|
m_pServer = NULL;
|
|
}
|
|
|
|
SafeRelease(m_pLocalStore);
|
|
SafeRelease(m_pFldr);
|
|
|
|
// Release the Dll
|
|
g_pInstance->DllRelease();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::QueryInterface
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
if (IID_IUnknown == riid)
|
|
*ppv = (IMessageFolder *)this;
|
|
else if (IID_IMessageFolder == riid)
|
|
*ppv = (IMessageFolder *)this;
|
|
else if (IID_IDatabase == riid)
|
|
*ppv = (IDatabase *)this;
|
|
else if (IID_IServiceProvider == riid)
|
|
*ppv = (IServiceProvider *)this;
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return(E_NOINTERFACE);
|
|
}
|
|
|
|
// AddRef It
|
|
((IUnknown *)*ppv)->AddRef();
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::AddRef
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CFolderSync::AddRef(void)
|
|
{
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::Release
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CFolderSync::Release(void)
|
|
{
|
|
LONG cRef = InterlockedDecrement(&m_cRef);
|
|
if (0 == cRef)
|
|
delete this;
|
|
return (ULONG)cRef;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::Initialize
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::Initialize(IMessageStore *pStore, IMessageServer *pServer,
|
|
OPENFOLDERFLAGS dwFlags, FOLDERID idFolder)
|
|
{
|
|
Assert(FALSE);
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::SetOwner
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::SetOwner(IStoreCallback *pDefaultCallback)
|
|
{
|
|
HRESULT hrResult;
|
|
|
|
TraceCall("CFolderSync::SetOwner");
|
|
|
|
if (NULL == m_pServer)
|
|
{
|
|
hrResult = E_FAIL;
|
|
goto exit;
|
|
}
|
|
|
|
hrResult = m_pServer->SetIdleCallback(pDefaultCallback);
|
|
if (FAILED(hrResult))
|
|
{
|
|
TraceResult(hrResult);
|
|
goto exit;
|
|
}
|
|
|
|
exit:
|
|
return hrResult;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::Synchronize
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::Synchronize(SYNCFOLDERFLAGS dwFlags, DWORD cHeaders, IStoreCallback *pCallback)
|
|
{
|
|
BOOL fOffline;
|
|
HRESULT hr;
|
|
|
|
// async
|
|
// if online, then synchronize folder
|
|
// if offline, no op (fail)
|
|
|
|
if (m_pServer == NULL)
|
|
{
|
|
// local folders don't sync.
|
|
// NOTE - This isn't failure - there's just nothing to do.
|
|
return (S_FALSE);
|
|
}
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
if(g_pConMan->IsAccountDisabled((LPSTR)m_szAcctId))
|
|
hr = S_FALSE;
|
|
else
|
|
hr = m_pServer->SynchronizeFolder(dwFlags, cHeaders, pCallback);
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::GetFolderId
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::GetFolderId(LPFOLDERID pidFolder)
|
|
{
|
|
Assert(NULL != pidFolder);
|
|
|
|
// local store operation only
|
|
|
|
*pidFolder = m_idFolder;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::GetMessageFolderId
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::GetMessageFolderId(MESSAGEID idMessage, LPFOLDERID pidFolder)
|
|
{
|
|
return(m_pFldr->GetMessageFolderId(idMessage, pidFolder));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::OpenMessage
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::OpenMessage(MESSAGEID idMessage,
|
|
OPENMESSAGEFLAGS dwFlags, IMimeMessage **ppMessage,
|
|
IStoreCallback *pCallback)
|
|
{
|
|
HRESULT hr;
|
|
BOOL fOffline;
|
|
FILEADDRESS faStart;
|
|
|
|
Assert(NULL != ppMessage);
|
|
|
|
// async
|
|
// if message is already downloaded
|
|
// open message in local store
|
|
// else
|
|
// if online, download message
|
|
// if offline, fail
|
|
|
|
hr = m_pFldr->OpenMessage(idMessage, dwFlags, ppMessage, NULL);
|
|
if (SUCCEEDED(hr))
|
|
return(hr);
|
|
|
|
if (hr == STORE_E_NOBODY && m_pServer != NULL && !ISFLAGSET(dwFlags, OPEN_MESSAGE_CACHEDONLY))
|
|
{
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
hr = m_pServer->GetMessage(idMessage, pCallback);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::SaveMessage
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::SaveMessage(LPMESSAGEID pidMessage,
|
|
SAVEMESSAGEFLAGS dwOptions, MESSAGEFLAGS dwFlags,
|
|
IStream *pStreamIn, IMimeMessage *pMessage, IStoreCallback *pCallback)
|
|
{
|
|
HRESULT hr;
|
|
IStream *pStream;
|
|
DWORD dwOffline;
|
|
LPFILETIME pftRecv;
|
|
PROPVARIANT rVariant;
|
|
|
|
Assert(NULL != pMessage);
|
|
|
|
// save message to local store
|
|
// if online, upload message
|
|
// if offline, log transaction
|
|
|
|
if (m_pServer == NULL)
|
|
{
|
|
hr = m_pFldr->SaveMessage(pidMessage, dwOptions, dwFlags, pStreamIn, pMessage, NULL);
|
|
return(hr);
|
|
}
|
|
|
|
hr = _Offline(&dwOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (dwOffline == CONN_STATE_NOT_CONNECTED)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else if (dwOffline == CONN_STATE_OFFLINE)
|
|
{
|
|
hr = g_pSync->CreateMessage(m_pFldr, pidMessage, dwOptions, dwFlags, pStreamIn, pMessage);
|
|
}
|
|
else
|
|
{
|
|
Assert(dwOffline == CONN_STATE_CONNECTED);
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
// the idStream can legally by null in the case of saving a draft
|
|
if (NULL == pStreamIn)
|
|
hr = pMessage->GetMessageSource(&pStream, COMMIT_ONLYIFDIRTY);
|
|
else
|
|
{
|
|
pStream = pStreamIn;
|
|
pStream->AddRef();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
rVariant.vt = VT_FILETIME;
|
|
if (SUCCEEDED(pMessage->GetProp(PIDTOSTR(PID_ATT_RECVTIME), 0, &rVariant)))
|
|
pftRecv = &rVariant.filetime;
|
|
else
|
|
pftRecv = NULL;
|
|
|
|
hr = m_pServer->PutMessage(m_idFolder, dwFlags, pftRecv, pStream, pCallback);
|
|
pStream->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::SetMessageStream
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::SetMessageStream(MESSAGEID idMessage,
|
|
IStream *pStream)
|
|
{
|
|
// pass through to the local store
|
|
Assert (NULL != m_pFldr);
|
|
Assert(NULL != pStream);
|
|
|
|
if (NULL == pStream)
|
|
return E_INVALIDARG;
|
|
|
|
return m_pFldr->SetMessageStream(idMessage, pStream);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::SetMessageFlags
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::SetMessageFlags(LPMESSAGEIDLIST pList,
|
|
LPADJUSTFLAGS pFlags, LPRESULTLIST pResults,
|
|
IStoreCallback *pCallback)
|
|
{
|
|
INewsStore *pNewsStore;
|
|
ADJUSTFLAGS localFlags, svrFlags;
|
|
MESSAGEFLAGS flags;
|
|
DWORD dwOffline;
|
|
HRESULT hr;
|
|
|
|
Assert(NULL != pFlags);
|
|
Assert(NULL == pList || 0 != pList->cMsgs);
|
|
|
|
// async
|
|
// save message flags to local store
|
|
// if online, upload message flags if necessary (some flags are irrelevant to server)
|
|
// if offline, log transaction if necessary
|
|
|
|
if (m_pServer == NULL)
|
|
return(m_pFldr->SetMessageFlags(pList, pFlags, pResults, NULL));
|
|
|
|
hr = _Offline(&dwOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pServer->GetServerMessageFlags(&flags);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(hr == S_OK || hr == S_FALSE);
|
|
|
|
// hr == S_FALSE
|
|
// this server doesn't have any flags that need to hit the server
|
|
|
|
localFlags = *pFlags;
|
|
|
|
if (hr == S_OK)
|
|
{
|
|
svrFlags = *pFlags;
|
|
svrFlags.dwAdd &= flags;
|
|
svrFlags.dwRemove &= flags;
|
|
|
|
localFlags.dwAdd &= ~flags;
|
|
localFlags.dwRemove &= ~flags;
|
|
|
|
if (0 != svrFlags.dwAdd ||
|
|
0 != svrFlags.dwRemove)
|
|
{
|
|
if (dwOffline == CONN_STATE_NOT_CONNECTED)
|
|
{
|
|
return(E_NOT_ONLINE);
|
|
}
|
|
else if (dwOffline == CONN_STATE_OFFLINE)
|
|
{
|
|
hr = g_pSync->SetMessageFlags(m_pFldr, pList, &svrFlags);
|
|
}
|
|
else
|
|
{
|
|
Assert(dwOffline == CONN_STATE_CONNECTED);
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
hr = m_pServer->SetMessageFlags(pList, &svrFlags, 0, pCallback);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (0 != localFlags.dwAdd ||
|
|
0 != localFlags.dwRemove)
|
|
{
|
|
hr = m_pFldr->SetMessageFlags(pList, &localFlags, pResults, NULL);
|
|
|
|
// mark news crossposts as read
|
|
if (m_tyFolder == FOLDER_NEWS &&
|
|
(!!(localFlags.dwAdd & ARF_READ) || !!(localFlags.dwRemove & ARF_READ)))
|
|
{
|
|
IServiceProvider *pService;
|
|
|
|
if (SUCCEEDED(m_pServer->QueryInterface(IID_IServiceProvider, (void **)&pService)))
|
|
{
|
|
if (SUCCEEDED(pService->QueryService(SID_MessageServer, IID_INewsStore, (void **)&pNewsStore)))
|
|
{
|
|
pNewsStore->MarkCrossposts(pList, !!(localFlags.dwAdd & ARF_READ));
|
|
|
|
pNewsStore->Release();
|
|
}
|
|
|
|
pService->Release();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::DeleteMessages
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::DeleteMessages(DELETEMESSAGEFLAGS dwOptions,
|
|
LPMESSAGEIDLIST pList, LPRESULTLIST pResults,
|
|
IStoreCallback *pCallback)
|
|
{
|
|
ADJUSTFLAGS afFlags;
|
|
DWORD dwOffline;
|
|
HRESULT hr;
|
|
|
|
Assert(NULL == pList || pList->cMsgs > 0);
|
|
|
|
// if online, delete messages from server and local store
|
|
// if offline, log transaction
|
|
|
|
if (m_pServer == NULL || m_tyFolder == FOLDER_NEWS)
|
|
return(m_pFldr->DeleteMessages(dwOptions, pList, pResults, pCallback));
|
|
|
|
hr = _Offline(&dwOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (dwOffline == CONN_STATE_NOT_CONNECTED)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else if (dwOffline == CONN_STATE_OFFLINE)
|
|
{
|
|
// [PaulHi] 4/8/99 Raid 63339
|
|
// Deleting from an HTTP folder (other than the 'deleted' folder)
|
|
// translates into a message move from the source folder to the
|
|
// 'deleted' folder. If offline we want the message copy to take
|
|
// place and then cache the message 'copy' just as would happen with
|
|
// an offline drag/drop copy operation.
|
|
FOLDERINFO fldrinfo;
|
|
BOOL bHMOffLineCopy = FALSE;
|
|
|
|
hr = m_pLocalStore->GetFolderInfo(m_idFolder, &fldrinfo);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if ( (fldrinfo.tyFolder == FOLDER_HTTPMAIL) && (fldrinfo.tySpecial != FOLDER_DELETED) &&
|
|
(fldrinfo.tySpecial != FOLDER_MSNPROMO) )
|
|
{
|
|
// Code stolen from CFolderSync::CopyMessages
|
|
IMessageFolder * pDeletedItems = NULL;
|
|
IMessageFolder * pDestLocal = NULL;
|
|
IServiceProvider * pService = NULL;
|
|
|
|
hr = g_pStore->OpenSpecialFolder(m_idServer, NULL, FOLDER_DELETED, &pDeletedItems);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pDeletedItems->QueryInterface(IID_IServiceProvider, (void **)&pService);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pService->QueryService(SID_LocalMessageFolder, IID_IMessageFolder, (void **)&pDestLocal);
|
|
pService->Release();
|
|
}
|
|
|
|
pDeletedItems->Release();
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(pDestLocal != NULL);
|
|
|
|
afFlags.dwAdd = 0;
|
|
afFlags.dwRemove = 0;
|
|
hr = g_pSync->CopyMessages(m_pFldr, pDestLocal, COPY_MESSAGE_MOVE, pList, &afFlags);
|
|
bHMOffLineCopy = TRUE;
|
|
|
|
pDestLocal->Release();
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&fldrinfo);
|
|
}
|
|
}
|
|
|
|
// If the HM offline copy didn't occur, for whatever reason, revert to the original
|
|
// off line delete.
|
|
if (!bHMOffLineCopy)
|
|
hr = g_pSync->DeleteMessages(m_pFldr, dwOptions, pList);
|
|
}
|
|
else
|
|
{
|
|
Assert(dwOffline == CONN_STATE_CONNECTED);
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
hr = m_pServer->DeleteMessages(dwOptions, pList, pCallback);
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CFolderSync::Initialize(IMessageStore *pStore, IMessageFolder *pLocalFolder,
|
|
IMessageServer *pServer, OPENFOLDERFLAGS dwFlags, FOLDERTYPE tyFolder,
|
|
FOLDERID idFolder, FOLDERID idServer)
|
|
{
|
|
WNDCLASSEX wc;
|
|
HRESULT hr;
|
|
FOLDERINFO info;
|
|
|
|
Assert(NULL != pStore);
|
|
|
|
// Save the Folder Type
|
|
m_tyFolder = tyFolder;
|
|
|
|
// Save the FolderId
|
|
m_idFolder = idFolder;
|
|
|
|
m_idServer = idServer;
|
|
|
|
// Save pStore
|
|
m_pLocalStore = pStore;
|
|
m_pLocalStore->AddRef();
|
|
|
|
if (pServer != NULL)
|
|
{
|
|
hr = m_pLocalStore->GetFolderInfo(m_idServer, &info);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
StrCpyN(m_szAcctId, info.pszAccountId, ARRAYSIZE(m_szAcctId));
|
|
m_fImap = (info.tyFolder == FOLDER_IMAP);
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
|
|
m_pServer = pServer;
|
|
m_pServer->AddRef();
|
|
|
|
hr = g_pConMan->Advise((IConnectionNotify *)this);
|
|
m_fConManAdvise = SUCCEEDED(hr);
|
|
}
|
|
|
|
if (pLocalFolder)
|
|
{
|
|
m_pFldr = pLocalFolder;
|
|
m_pFldr->AddRef();
|
|
}
|
|
else
|
|
{
|
|
hr = m_pLocalStore->OpenFolder(m_idFolder, NULL, dwFlags, &m_pFldr);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
}
|
|
|
|
wc.cbSize = sizeof(WNDCLASSEX);
|
|
if (!GetClassInfoEx(g_hInst, c_szFolderSyncWndClass, &wc))
|
|
{
|
|
wc.style = 0;
|
|
wc.lpfnWndProc = FolderSyncWndProc;
|
|
wc.cbClsExtra = 0;
|
|
wc.cbWndExtra = 0;
|
|
wc.hInstance = g_hInst;
|
|
wc.hIcon = NULL;
|
|
wc.hCursor = NULL;
|
|
wc.hbrBackground = NULL;
|
|
wc.lpszMenuName = NULL;
|
|
wc.lpszClassName = c_szFolderSyncWndClass;
|
|
wc.hIconSm = NULL;
|
|
if (RegisterClassEx(&wc) == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
|
|
return E_FAIL;
|
|
}
|
|
|
|
m_hwnd = CreateWindowEx(WS_EX_TOPMOST, c_szFolderSyncWndClass,
|
|
c_szFolderSyncWndClass, WS_POPUP, 1, 1, 1, 1, NULL,
|
|
NULL, g_hInst, (LPVOID)this);
|
|
if (m_hwnd == NULL)
|
|
return(E_FAIL);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::Close()
|
|
{
|
|
HRESULT hr = S_OK;
|
|
if (m_pServer)
|
|
hr = m_pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFolderSync::_Offline(DWORD *pdwOffline)
|
|
{
|
|
BOOL fOffline;
|
|
HRESULT hr;
|
|
|
|
Assert(pdwOffline != NULL);
|
|
Assert(m_szAcctId[0] != 0);
|
|
|
|
fOffline = g_pConMan->IsGlobalOffline();
|
|
if (fOffline)
|
|
{
|
|
*pdwOffline = CONN_STATE_OFFLINE;
|
|
}
|
|
else
|
|
{
|
|
//Bug# 39337. We just give the operation to the sync object even if we are not connected.
|
|
//The sync object in turn figures out whether it needs to dial or not
|
|
|
|
/*
|
|
hr = g_pConMan->CanConnect(m_szAcctId);
|
|
|
|
*pdwOffline = (hr == S_OK) ? CONN_STATE_CONNECTED : CONN_STATE_NOT_CONNECTED;
|
|
*/
|
|
*pdwOffline = CONN_STATE_CONNECTED;
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::_OfflineServer(FOLDERID idServer, DWORD *pdwOffline)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERINFO info;
|
|
BOOL fOffline;
|
|
|
|
Assert(pdwOffline != NULL);
|
|
|
|
hr = m_pLocalStore->GetFolderInfo(idServer, &info);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
if (info.tyFolder == FOLDER_LOCAL)
|
|
{
|
|
*pdwOffline = CONN_STATE_CONNECTED;
|
|
}
|
|
else
|
|
{
|
|
fOffline = g_pConMan->IsGlobalOffline();
|
|
if (fOffline)
|
|
{
|
|
*pdwOffline = CONN_STATE_OFFLINE;
|
|
}
|
|
else
|
|
{
|
|
/*
|
|
hr = g_pConMan->CanConnect(info.pszAccountId);
|
|
|
|
*pdwOffline = (hr == S_OK) ? CONN_STATE_CONNECTED : CONN_STATE_NOT_CONNECTED;
|
|
*/
|
|
*pdwOffline = CONN_STATE_CONNECTED;
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
|
|
{
|
|
IServiceProvider *pSP;
|
|
HRESULT hr = E_NOINTERFACE;
|
|
|
|
if (guidService == SID_LocalMessageFolder)
|
|
{
|
|
if (m_pFldr != NULL)
|
|
hr = m_pFldr->QueryInterface(riid, ppvObject);
|
|
}
|
|
else if (m_pServer && m_pServer->QueryInterface(IID_IServiceProvider, (LPVOID *)&pSP)==S_OK)
|
|
{
|
|
hr = pSP->QueryService(guidService, riid, ppvObject);
|
|
pSP->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CFolderSync::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo, IOperationCancel *pCancel)
|
|
{
|
|
Assert(m_pCopy->type == SOT_INVALID);
|
|
Assert(m_pCopy->fAsync);
|
|
|
|
m_pCopy->type = tyOperation;
|
|
|
|
if (!m_pCopy->fBegin)
|
|
{
|
|
Assert(m_pCopy->pCallback != NULL);
|
|
m_pCopy->pCallback->OnBegin(SOT_COPYMOVE_MESSAGE, pOpInfo, (IOperationCancel *)this);
|
|
|
|
m_pCopy->fBegin = TRUE;
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
|
|
{
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
return(m_pCopy->pCallback->OnTimeout(pServer, pdwTimeout, ixpServerType));
|
|
}
|
|
|
|
HRESULT CFolderSync::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
return(m_pCopy->pCallback->CanConnect(pszAccountId, dwFlags));
|
|
}
|
|
|
|
HRESULT CFolderSync::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
return(m_pCopy->pCallback->OnLogonPrompt(pServer, ixpServerType));
|
|
}
|
|
|
|
HRESULT CFolderSync::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
if (m_pCopy->type != tyOperation ||
|
|
m_pCopy->hr != S_FALSE)
|
|
return(S_OK);
|
|
|
|
Assert(hrComplete != S_FALSE);
|
|
|
|
m_pCopy->hr = hrComplete;
|
|
|
|
if (NULL != pErrorInfo)
|
|
{
|
|
BOOL fResult;
|
|
|
|
fResult = MemAlloc((void **)&m_pCopy->pErrorInfo, sizeof(STOREERROR));
|
|
if (FALSE == fResult)
|
|
{
|
|
TraceResult(E_OUTOFMEMORY);
|
|
}
|
|
else
|
|
{
|
|
// Make a copy of the STOREERROR so we can display rich errors to user
|
|
m_pCopy->pErrorInfo->hrResult = pErrorInfo->hrResult;
|
|
m_pCopy->pErrorInfo->uiServerError = pErrorInfo->uiServerError;
|
|
m_pCopy->pErrorInfo->hrServerError = pErrorInfo->hrServerError;
|
|
m_pCopy->pErrorInfo->dwSocketError = pErrorInfo->dwSocketError;
|
|
m_pCopy->pErrorInfo->pszProblem = PszDupA(pErrorInfo->pszProblem);
|
|
m_pCopy->pErrorInfo->pszDetails = PszDupA(pErrorInfo->pszDetails);
|
|
m_pCopy->pErrorInfo->pszAccount = PszDupA(pErrorInfo->pszAccount);
|
|
m_pCopy->pErrorInfo->pszServer = PszDupA(pErrorInfo->pszServer);
|
|
m_pCopy->pErrorInfo->pszFolder = PszDupA(pErrorInfo->pszFolder);
|
|
m_pCopy->pErrorInfo->pszUserName = PszDupA(pErrorInfo->pszUserName);
|
|
m_pCopy->pErrorInfo->pszProtocol = PszDupA(pErrorInfo->pszProtocol);
|
|
m_pCopy->pErrorInfo->ixpType = pErrorInfo->ixpType;
|
|
m_pCopy->pErrorInfo->dwPort = pErrorInfo->dwPort;
|
|
m_pCopy->pErrorInfo->fSSL = pErrorInfo->fSSL;
|
|
m_pCopy->pErrorInfo->dwFlags = pErrorInfo->dwFlags;
|
|
}
|
|
}
|
|
|
|
PostMessage(m_hwnd, WM_USER, 0, 0);
|
|
|
|
m_pCopy->type = SOT_INVALID;
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFolderSync::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
return(m_pCopy->pCallback->OnPrompt(hrError, pszText, pszCaption, uType, piUserResponse));
|
|
}
|
|
|
|
HRESULT CFolderSync::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
return(m_pCopy->pCallback->GetParentWindow(dwReserved, phwndParent));
|
|
}
|
|
|
|
HRESULT CFolderSync::Cancel(CANCELTYPE tyCancel)
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
Assert(tyCancel != CT_INVALID);
|
|
|
|
m_pCopy->tyCancel = tyCancel;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::OnConnectionNotify(CONNNOTIFY nCode, LPVOID pvData, CConnectionManager *pConMan)
|
|
{
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
|
|
Assert(m_pServer != NULL);
|
|
|
|
if (nCode == CONNNOTIFY_CONNECTED)
|
|
{
|
|
|
|
}
|
|
else if (nCode == CONNNOTIFY_WORKOFFLINE && pvData)
|
|
{
|
|
m_pServer->Close(MSGSVRF_DROP_CONNECTION);
|
|
}
|
|
else if (nCode == CONNNOTIFY_DISCONNECTED)
|
|
{
|
|
hr = g_pStore->GetFolderInfo(m_idServer, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
CHAR szAccountId[CCHMAX_ACCOUNT_NAME];
|
|
|
|
if (SUCCEEDED(GetFolderAccountId(&info, szAccountId, ARRAYSIZE(szAccountId))))
|
|
{
|
|
if (!g_pConMan->CanConnect(szAccountId))
|
|
m_pServer->Close(MSGSVRF_DROP_CONNECTION);
|
|
}
|
|
|
|
g_pStore->FreeRecord(&info);
|
|
}
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
void CFolderSync::_FreeCopyInfo()
|
|
{
|
|
Assert(m_pCopy != NULL);
|
|
|
|
if (m_pCopy->pDest != NULL)
|
|
m_pCopy->pDest->Release();
|
|
if (m_pCopy->pDestLocal != NULL)
|
|
m_pCopy->pDestLocal->Release();
|
|
if (m_pCopy->pList != NULL)
|
|
MemFree(m_pCopy->pList);
|
|
|
|
if (m_pCopy->pErrorInfo != NULL)
|
|
{
|
|
SafeMemFree(m_pCopy->pErrorInfo->pszProblem);
|
|
SafeMemFree(m_pCopy->pErrorInfo->pszDetails);
|
|
SafeMemFree(m_pCopy->pErrorInfo->pszAccount);
|
|
SafeMemFree(m_pCopy->pErrorInfo->pszServer);
|
|
SafeMemFree(m_pCopy->pErrorInfo->pszFolder);
|
|
SafeMemFree(m_pCopy->pErrorInfo->pszUserName);
|
|
SafeMemFree(m_pCopy->pErrorInfo->pszProtocol);
|
|
MemFree(m_pCopy->pErrorInfo);
|
|
}
|
|
|
|
MemFree(m_pCopy);
|
|
m_pCopy = NULL;
|
|
}
|
|
|
|
HRESULT AllBodiesDownloaded(IMessageFolder *pFldr, LPMESSAGEIDLIST pList)
|
|
{
|
|
MESSAGEINFO Message;
|
|
DWORD iMsg;
|
|
HRESULT hr;
|
|
|
|
Assert(pFldr != NULL);
|
|
Assert(pList != NULL);
|
|
|
|
hr = S_OK;
|
|
|
|
for (iMsg = 0; iMsg < pList->cMsgs; iMsg++)
|
|
{
|
|
ZeroMemory(&Message, sizeof(MESSAGEINFO));
|
|
Message.idMessage = pList->prgidMsg[iMsg];
|
|
if (DB_S_FOUND == pFldr->FindRecord(IINDEX_PRIMARY, COLUMNS_ALL, &Message, NULL))
|
|
{
|
|
if (0 == (Message.dwFlags & ARF_HASBODY))
|
|
hr = S_FALSE;
|
|
|
|
pFldr->FreeRecord(&Message);
|
|
}
|
|
|
|
if (hr != S_OK)
|
|
break;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::CopyMessages
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CFolderSync::CopyMessages(IMessageFolder *pDest,
|
|
COPYMESSAGEFLAGS dwOptions,
|
|
LPMESSAGEIDLIST pList,
|
|
LPADJUSTFLAGS pFlags,
|
|
LPRESULTLIST pResults,
|
|
IStoreCallback *pCallback)
|
|
{
|
|
HWND hwnd;
|
|
DWORD dwOfflineSrc, dwOfflineDst;
|
|
HRESULT hr;
|
|
IMessageFolder *pDestLocal;
|
|
ADJUSTFLAGS aflags;
|
|
FOLDERID idDst, idServerDst;
|
|
IServiceProvider *pService;
|
|
FOLDERINFO fiSource = {0};
|
|
|
|
Assert(pDest != NULL);
|
|
Assert(pList != NULL);
|
|
|
|
hr = pDest->GetFolderId(&idDst);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
hr = GetFolderServerId(idDst, &idServerDst);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
if (m_pServer == NULL)
|
|
{
|
|
dwOfflineSrc = CONN_STATE_CONNECTED;
|
|
}
|
|
else
|
|
{
|
|
hr = _Offline(&dwOfflineSrc);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
}
|
|
|
|
if (m_tyFolder == FOLDER_IMAP)
|
|
{
|
|
if (pFlags != NULL)
|
|
{
|
|
aflags = *pFlags;
|
|
}
|
|
else
|
|
{
|
|
aflags.dwAdd = 0;
|
|
aflags.dwRemove = 0;
|
|
}
|
|
aflags.dwRemove |= ARF_ENDANGERED;
|
|
pFlags = &aflags;
|
|
}
|
|
|
|
if (m_idServer == idServerDst)
|
|
{
|
|
if (m_pServer == NULL)
|
|
{
|
|
hr = m_pFldr->CopyMessages(pDest, dwOptions, pList, pFlags, pResults, pCallback);
|
|
}
|
|
else if (dwOfflineSrc == CONN_STATE_NOT_CONNECTED)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else if (dwOfflineSrc == CONN_STATE_CONNECTED)
|
|
{
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
hr = m_pServer->CopyMessages(pDest, dwOptions, pList, pFlags, pCallback);
|
|
}
|
|
else
|
|
{
|
|
Assert(dwOfflineSrc == CONN_STATE_OFFLINE);
|
|
|
|
pDestLocal = NULL;
|
|
|
|
hr = pDest->QueryInterface(IID_IServiceProvider, (void **)&pService);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pService->QueryService(SID_LocalMessageFolder, IID_IMessageFolder, (void **)&pDestLocal);
|
|
|
|
pService->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
Assert(pDestLocal != NULL);
|
|
hr = g_pSync->CopyMessages(m_pFldr, pDestLocal, dwOptions, pList, pFlags);
|
|
|
|
pDestLocal->Release();
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
hr = _OfflineServer(idServerDst, &dwOfflineDst);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
if (dwOfflineDst == CONN_STATE_NOT_CONNECTED)
|
|
return(E_NOT_ONLINE);
|
|
|
|
Assert(m_pCopy == NULL);
|
|
if (m_pCopy != NULL)
|
|
return(E_FAIL);
|
|
|
|
if (dwOfflineSrc != CONN_STATE_CONNECTED)
|
|
{
|
|
hr = AllBodiesDownloaded(m_pFldr, pList);
|
|
if (FAILED(hr))
|
|
{
|
|
return(hr);
|
|
}
|
|
else if (hr == S_FALSE)
|
|
{
|
|
pCallback->GetParentWindow(0, &hwnd);
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena),
|
|
!!(COPY_MESSAGE_MOVE & dwOptions) ? MAKEINTRESOURCEW(idsCantMoveNotDownloaded) : MAKEINTRESOURCEW(idsCantCopyNotDownloaded),
|
|
0, MB_OK | MB_ICONEXCLAMATION);
|
|
|
|
return(E_NOT_ONLINE);
|
|
}
|
|
}
|
|
|
|
// Bug# 94639
|
|
// If the src and dest servers are not the same, and if the source is Hotmail Deleted Items folder
|
|
// disallow move.
|
|
// For Hotmail accounts Deleted Items folder is managed by the Hotmail servers.
|
|
// So the users cannot manually delete or move messages.
|
|
// Hence, disallow moving from Deleted Items.
|
|
// Instead ask if the user wants to copy the message
|
|
if ((m_idServer != idServerDst) && (FOLDER_HTTPMAIL == m_tyFolder))
|
|
{
|
|
IF_FAILEXIT(hr = m_pLocalStore->GetFolderInfo(m_idFolder, &fiSource));
|
|
if (FOLDER_DELETED == fiSource.tySpecial)
|
|
{
|
|
if (IDNO == AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
|
|
MAKEINTRESOURCEW(idsHttpNoMoveCopy), 0, MB_YESNO))
|
|
{
|
|
// Just return S_OK;
|
|
hr = S_OK;
|
|
goto exit;
|
|
}
|
|
else
|
|
{
|
|
// Change the move flags to copy.
|
|
dwOptions = (dwOptions & ~COPY_MESSAGE_MOVE);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!MemAlloc((void **)&m_pCopy, sizeof(COPYINFO)))
|
|
return(E_OUTOFMEMORY);
|
|
|
|
ZeroMemory(m_pCopy, sizeof(COPYINFO));
|
|
m_pCopy->fSrcOffline = (dwOfflineSrc != CONN_STATE_CONNECTED);
|
|
m_pCopy->fDestOffline = (dwOfflineDst != CONN_STATE_CONNECTED);
|
|
m_pCopy->hr = S_OK;
|
|
m_pCopy->pDest = pDest;
|
|
pDest->AddRef();
|
|
m_pCopy->fMove = !!(COPY_MESSAGE_MOVE & dwOptions);
|
|
hr = CloneMessageIDList(pList, &m_pCopy->pList);
|
|
if (FAILED(hr))
|
|
{
|
|
_FreeCopyInfo();
|
|
return(hr);
|
|
}
|
|
|
|
if (m_pCopy->fDestOffline)
|
|
{
|
|
hr = m_pCopy->pDest->QueryInterface(IID_IServiceProvider, (void **)&pService);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pService->QueryService(SID_LocalMessageFolder, IID_IMessageFolder, (void **)&m_pCopy->pDestLocal);
|
|
|
|
pService->Release();
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
_FreeCopyInfo();
|
|
return(E_INVALIDARG);
|
|
}
|
|
}
|
|
|
|
if (pFlags != NULL)
|
|
m_pCopy->AdjustFlags = *pFlags;
|
|
|
|
m_pCopy->pCallback = pCallback;
|
|
|
|
hr = _CopyMessageState();
|
|
|
|
exit:
|
|
m_pLocalStore->FreeRecord(&fiSource);
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CFolderSync::CopyOpen()
|
|
{
|
|
HRESULT hr;
|
|
MESSAGEINFO mi = {0};
|
|
LPMESSAGEINFO pmi = NULL;
|
|
|
|
if (m_pCopy->iMsg >= m_pCopy->pList->cMsgs)
|
|
{
|
|
m_pCopy->state = COPY_STATE_DONE;
|
|
return(S_OK);
|
|
}
|
|
|
|
Assert(m_pCopy->pStream == NULL);
|
|
|
|
// initialize message info with the message id
|
|
mi.idMessage = m_pCopy->pList->prgidMsg[m_pCopy->iMsg];
|
|
|
|
// find the row
|
|
hr = GetMessageInfo(m_pFldr, m_pCopy->pList->prgidMsg[m_pCopy->iMsg], &mi);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
pmi = &mi;
|
|
|
|
if (0 == mi.faStream || !!(mi.dwFlags & ARF_ARTICLE_EXPIRED))
|
|
{
|
|
// if the server is NULL and we don't have a body stream,
|
|
// then something is wrong with the message. we skip the
|
|
// bad message and move onto the next one.
|
|
if (NULL == m_pServer || m_pCopy->fSrcOffline)
|
|
{
|
|
m_pCopy->state = COPY_STATE_DELETE2;
|
|
hr = S_OK;
|
|
}
|
|
else if (!m_pCopy->fSrcRequested)
|
|
{
|
|
Assert(m_pServer != NULL);
|
|
|
|
hr = m_pServer->GetMessage(m_pCopy->pList->prgidMsg[m_pCopy->iMsg], (IStoreCallback *)this);
|
|
if (hr == E_PENDING)
|
|
m_pCopy->fSrcRequested = TRUE;
|
|
Assert(FAILED(hr));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = m_pFldr->OpenStream(ACCESS_READ, mi.faStream, &m_pCopy->pStream);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
m_pCopy->state = COPY_STATE_SAVE;
|
|
}
|
|
|
|
exit:
|
|
if (NULL != pmi)
|
|
m_pFldr->FreeRecord(pmi);
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CFolderSync::CopySave()
|
|
{
|
|
DWORD dwFlags;
|
|
HRESULT hr;
|
|
MESSAGEINFO Message;
|
|
MESSAGEID id;
|
|
IMimeMessage *pMessage = NULL;
|
|
|
|
Assert(m_pCopy->pStream != NULL);
|
|
|
|
dwFlags = 0;
|
|
|
|
ZeroMemory(&Message, sizeof(MESSAGEINFO));
|
|
Message.idMessage = m_pCopy->pList->prgidMsg[m_pCopy->iMsg];
|
|
if (DB_S_FOUND == m_pFldr->FindRecord(IINDEX_PRIMARY, COLUMNS_ALL, &Message, NULL))
|
|
{
|
|
dwFlags = Message.dwFlags;
|
|
m_pFldr->FreeRecord(&Message);
|
|
}
|
|
|
|
if (m_pCopy->AdjustFlags.dwRemove != 0)
|
|
dwFlags &= ~m_pCopy->AdjustFlags.dwRemove;
|
|
if (m_pCopy->AdjustFlags.dwAdd != 0)
|
|
dwFlags |= m_pCopy->AdjustFlags.dwAdd;
|
|
|
|
// create a mime message
|
|
hr = m_pFldr->OpenMessage(m_pCopy->pList->prgidMsg[m_pCopy->iMsg], OPEN_MESSAGE_SECURE, &pMessage, NOSTORECALLBACK);
|
|
if (FAILED(hr))
|
|
goto exit;
|
|
|
|
if (m_pCopy->fDestOffline)
|
|
{
|
|
Assert(m_pCopy->pDestLocal != NULL);
|
|
hr = g_pSync->CreateMessage(m_pCopy->pDestLocal, &id, SAVE_MESSAGE_GENID, dwFlags, m_pCopy->pStream, pMessage);
|
|
}
|
|
else
|
|
{
|
|
hr = m_pCopy->pDest->SaveMessage(&id, SAVE_MESSAGE_GENID, dwFlags, m_pCopy->pStream, pMessage, (IStoreCallback *)this);
|
|
}
|
|
|
|
if (hr == E_PENDING || SUCCEEDED(hr))
|
|
m_pCopy->state = COPY_STATE_SAVE2;
|
|
|
|
exit:
|
|
if (NULL != pMessage)
|
|
pMessage->Release();
|
|
|
|
m_pCopy->pStream->Release();
|
|
m_pCopy->pStream = NULL;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CFolderSync::CopySave2()
|
|
{
|
|
if (m_pCopy->fMove)
|
|
{
|
|
m_pCopy->state = COPY_STATE_DELETE;
|
|
}
|
|
else
|
|
{
|
|
m_pCopy->state = COPY_STATE_OPEN;
|
|
m_pCopy->iMsg++;
|
|
m_pCopy->fSrcRequested = FALSE;
|
|
|
|
m_pCopy->pCallback->OnProgress(SOT_COPYMOVE_MESSAGE, m_pCopy->iMsg, m_pCopy->pList->cMsgs, NULL);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::CopyDelete()
|
|
{
|
|
MESSAGEIDLIST list;
|
|
HRESULT hr;
|
|
MESSAGEID id;
|
|
ADJUSTFLAGS afFlags;
|
|
|
|
list.cMsgs = 1;
|
|
id = m_pCopy->pList->prgidMsg[m_pCopy->iMsg];
|
|
list.prgidMsg = &id;
|
|
|
|
if (m_pServer != NULL)
|
|
{
|
|
if (m_pCopy->fSrcOffline)
|
|
{
|
|
if (m_fImap)
|
|
{
|
|
afFlags.dwAdd = ARF_ENDANGERED;
|
|
afFlags.dwRemove = 0;
|
|
hr = g_pSync->SetMessageFlags(m_pFldr, &list, &afFlags);
|
|
}
|
|
else
|
|
{
|
|
#ifdef DEAD
|
|
hr = g_pSync->DeleteMessages(m_pFldr, DELETE_MESSAGE_NOTRASHCAN, &list);
|
|
#endif // DEAD
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = m_pServer->DeleteMessages(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT | DELETE_MESSAGE_MAYIGNORENOTRASH, &list, (IStoreCallback *)this);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = m_pFldr->DeleteMessages(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT, &list, NULL, NOSTORECALLBACK);
|
|
}
|
|
|
|
if (hr == E_PENDING || SUCCEEDED(hr))
|
|
m_pCopy->state = COPY_STATE_DELETE2;
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CFolderSync::CopyDelete2()
|
|
{
|
|
m_pCopy->state = COPY_STATE_OPEN;
|
|
m_pCopy->iMsg++;
|
|
m_pCopy->fSrcRequested = FALSE;
|
|
|
|
m_pCopy->pCallback->OnProgress(SOT_COPYMOVE_MESSAGE, m_pCopy->iMsg, m_pCopy->pList->cMsgs, NULL);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CFolderSync::_CopyMessageState()
|
|
{
|
|
BOOL fBegin;
|
|
HRESULT hr;
|
|
HWND hwnd;
|
|
IStoreCallback *pCallback;
|
|
|
|
Assert(m_pCopy != NULL);
|
|
Assert(m_pCopy->hr != S_FALSE);
|
|
Assert(m_pCopy->hr != E_PENDING);
|
|
|
|
if (FAILED(m_pCopy->hr) && m_pCopy->state == COPY_STATE_OPEN && m_pCopy->fSrcRequested)
|
|
{
|
|
m_pCopy->fDownloadFail = TRUE;
|
|
m_pCopy->hr = S_OK;
|
|
m_pCopy->iMsg++;
|
|
m_pCopy->fSrcRequested = FALSE;
|
|
}
|
|
|
|
if (FAILED(m_pCopy->hr))
|
|
{
|
|
hr = m_pCopy->hr;
|
|
}
|
|
else
|
|
{
|
|
while (TRUE)
|
|
{
|
|
if (m_pCopy->tyCancel != CT_INVALID)
|
|
{
|
|
m_pCopy->state = COPY_STATE_DONE;
|
|
hr = S_FALSE;
|
|
break;
|
|
}
|
|
|
|
hr = (this->*(c_rgpfnCopyMsgs[m_pCopy->state]))();
|
|
|
|
if (FAILED(hr) || m_pCopy->state == COPY_STATE_DONE)
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (hr == E_PENDING)
|
|
{
|
|
Assert(m_pCopy->type == SOT_INVALID);
|
|
m_pCopy->fAsync = TRUE;
|
|
m_pCopy->hr = S_FALSE;
|
|
}
|
|
else if (FAILED(hr) || m_pCopy->state == COPY_STATE_DONE)
|
|
{
|
|
fBegin = m_pCopy->fBegin;
|
|
#ifdef DEBUG
|
|
if (fBegin)
|
|
Assert(m_pCopy->fAsync);
|
|
#endif // DEBUG
|
|
pCallback = m_pCopy->pCallback;
|
|
|
|
if (fBegin)
|
|
{
|
|
if (m_pCopy->fDownloadFail && SUCCEEDED(hr))
|
|
{
|
|
if (SUCCEEDED(pCallback->GetParentWindow(0, &hwnd)))
|
|
{
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena),
|
|
m_pCopy->fMove ? MAKEINTRESOURCEW(idsMoveDownloadFail) : MAKEINTRESOURCEW(idsCopyDownloadFail),
|
|
NULL, MB_ICONEXCLAMATION | MB_OK);
|
|
}
|
|
}
|
|
|
|
pCallback->OnComplete(SOT_COPYMOVE_MESSAGE, hr, NULL, m_pCopy->pErrorInfo);
|
|
}
|
|
|
|
_FreeCopyInfo();
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
LRESULT CALLBACK CFolderSync::FolderSyncWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
HRESULT hr;
|
|
CFolderSync *pThis;
|
|
|
|
pThis = (CFolderSync *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
if (NULL == pThis && msg != WM_CREATE)
|
|
return DefWindowProc(hwnd, msg, wParam, lParam);
|
|
|
|
switch(msg)
|
|
{
|
|
case WM_CREATE:
|
|
Assert(pThis == NULL);
|
|
pThis = (CFolderSync *)((CREATESTRUCT *)lParam)->lpCreateParams;
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
|
|
break;
|
|
|
|
case WM_USER:
|
|
pThis->_CopyMessageState();
|
|
break;
|
|
}
|
|
|
|
return(DefWindowProc(hwnd, msg, wParam, lParam));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::ConnectionAddRef
|
|
//
|
|
// Purpose: users of IMessageFolder need to keep alive the underlying server
|
|
// object if they plan of re-using the same server connection as
|
|
// another user of the same IMessageTable. eg. a note and a view window
|
|
// This allows us to not have to re-auth for operations that could
|
|
// be potentially expensive
|
|
//--------------------------------------------------------------------------
|
|
HRESULT CFolderSync::ConnectionAddRef()
|
|
{
|
|
if (m_pServer)
|
|
m_pServer->ConnectionAddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CFolderSync::ConnectionRelease
|
|
//
|
|
// Purpose: figure it out
|
|
//--------------------------------------------------------------------------
|
|
HRESULT CFolderSync::ConnectionRelease()
|
|
{
|
|
if (m_pServer)
|
|
m_pServer->ConnectionRelease();
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CFolderSync::GetAdBarUrl(IStoreCallback *pCallback)
|
|
{
|
|
HRESULT hr = E_FAIL;
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
if (m_pServer)
|
|
hr = m_pServer->GetAdBarUrl(pCallback);
|
|
|
|
return(hr);
|
|
}
|