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.
810 lines
21 KiB
810 lines
21 KiB
#include "pch.hxx"
|
|
#include <progress.h>
|
|
#include "store.h"
|
|
#include "storutil.h"
|
|
#include "storsync.h"
|
|
#include "syncop.h"
|
|
#include "sync.h"
|
|
#include "shlwapip.h"
|
|
#include "enumsync.h"
|
|
#include "playback.h"
|
|
|
|
#define WM_NEXT_OPERATION (WM_USER + 69)
|
|
|
|
HRESULT OpenErrorsFolder(IMessageFolder **ppFolder);
|
|
|
|
COfflinePlayback::COfflinePlayback()
|
|
{
|
|
m_cRef = 1;
|
|
m_hr = E_FAIL;
|
|
m_hwndDlg = NULL;
|
|
m_fComplete = TRUE;
|
|
m_type = SOT_INVALID;
|
|
m_pCancel = NULL;
|
|
m_hTimeout = NULL;
|
|
|
|
m_cMovedToErrors = 0;
|
|
m_cFailures = 0;
|
|
|
|
m_pDB = NULL;
|
|
|
|
m_pid = NULL;
|
|
m_iid = 0;
|
|
m_cid = 0;
|
|
|
|
m_idServer = FOLDERID_INVALID;
|
|
m_idFolder = FOLDERID_INVALID;
|
|
m_idFolderSel = FOLDERID_INVALID;
|
|
m_fSyncSel = FALSE;
|
|
m_pServer = NULL;
|
|
m_pLocalFolder = NULL;
|
|
m_iOps = 0;
|
|
m_cOps = 0;
|
|
m_pEnum = NULL;
|
|
|
|
m_pFolderDest = NULL;
|
|
}
|
|
|
|
COfflinePlayback::~COfflinePlayback()
|
|
{
|
|
Assert(m_pFolderDest == NULL);
|
|
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
if (m_pCancel != NULL)
|
|
m_pCancel->Release();
|
|
if (m_pDB != NULL)
|
|
m_pDB->Release();
|
|
if (m_pid != NULL)
|
|
MemFree(m_pid);
|
|
if (m_pLocalFolder != NULL)
|
|
m_pLocalFolder->Release();
|
|
if (m_pServer != NULL)
|
|
{
|
|
m_pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
|
|
m_pServer->Release();
|
|
}
|
|
if (m_pEnum != NULL)
|
|
m_pEnum->Release();
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE COfflinePlayback::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 if (IsEqualIID(riid, IID_ITimeoutCallback))
|
|
*ppvObj = (void*) (ITimeoutCallback *)this;
|
|
else
|
|
{
|
|
*ppvObj = NULL;
|
|
return E_NOINTERFACE;
|
|
}
|
|
|
|
AddRef();
|
|
return S_OK;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE COfflinePlayback::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
ULONG STDMETHODCALLTYPE COfflinePlayback::Release()
|
|
{
|
|
if (--m_cRef == 0)
|
|
{
|
|
delete this;
|
|
return 0;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
HRESULT COfflinePlayback::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo, 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 COfflinePlayback::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
|
|
{
|
|
Assert(m_hwndDlg != NULL);
|
|
Assert(!m_fComplete);
|
|
|
|
// Close any timeout dialog, if present
|
|
CallbackCloseTimeout(&m_hTimeout);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE COfflinePlayback::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
|
|
{
|
|
// Display a timeout dialog
|
|
return CallbackOnTimeout(pServer, ixpServerType, *pdwTimeout, (ITimeoutCallback *)this, &m_hTimeout);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE COfflinePlayback::OnTimeoutResponse(TIMEOUTRESPONSE eResponse)
|
|
{
|
|
// Call into general timeout response utility
|
|
return CallbackOnTimeoutResponse(eResponse, m_pCancel, &m_hTimeout);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE COfflinePlayback::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
|
|
{
|
|
return CallbackCanConnect(pszAccountId, m_hwndDlg, FALSE);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE COfflinePlayback::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 COfflinePlayback::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
|
|
{
|
|
HRESULT hr;
|
|
SYNCOPINFO info;
|
|
|
|
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 (m_idOperation == SYNCOPID_INVALID)
|
|
{
|
|
m_idFolderSel = FOLDERID_INVALID;
|
|
}
|
|
else
|
|
{
|
|
ZeroMemory(&info, sizeof(SYNCOPINFO));
|
|
|
|
info.idOperation = m_idOperation;
|
|
hr = m_pDB->FindRecord(IINDEX_PRIMARY, 1, &info, NULL);
|
|
if (hr == DB_S_FOUND)
|
|
{
|
|
switch (info.tyOperation)
|
|
{
|
|
case SYNC_DELETE_MSG:
|
|
hr = _HandleDeleteComplete(hrComplete, &info);
|
|
break;
|
|
|
|
case SYNC_SETPROP_MSG:
|
|
hr = _HandleSetPropComplete(hrComplete, &info);
|
|
break;
|
|
|
|
case SYNC_CREATE_MSG:
|
|
hr = _HandleCreateComplete(hrComplete, &info);
|
|
break;
|
|
|
|
case SYNC_COPY_MSG:
|
|
case SYNC_MOVE_MSG:
|
|
hr = _HandleCopyComplete(hrComplete, &info);
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE);
|
|
break;
|
|
}
|
|
|
|
m_pDB->DeleteRecord(&info);
|
|
m_pDB->FreeRecord(&info);
|
|
}
|
|
}
|
|
|
|
PostMessage(m_hwndDlg, WM_NEXT_OPERATION, 0, 0);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT STDMETHODCALLTYPE COfflinePlayback::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 COfflinePlayback::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
|
|
{
|
|
Assert(m_hwndDlg != NULL);
|
|
|
|
*phwndParent = m_hwndDlg;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::DoPlayback(HWND hwnd, IDatabase *pDB, FOLDERID *pid, DWORD cid, FOLDERID idFolderSel)
|
|
{
|
|
FOLDERTYPE type;
|
|
int iRet;
|
|
char szStoreDir[MAX_PATH + MAX_PATH];
|
|
|
|
Assert(pDB != NULL);
|
|
Assert(pid != NULL);
|
|
Assert(cid > 0);
|
|
|
|
m_pDB = pDB;
|
|
m_pDB->AddRef();
|
|
|
|
m_pEnum = new CEnumerateSyncOps;
|
|
if (m_pEnum == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
if (!MemAlloc((void **)&m_pid, cid * sizeof(FOLDERID)))
|
|
return(E_OUTOFMEMORY);
|
|
|
|
CopyMemory(m_pid, pid, cid * sizeof(FOLDERID));
|
|
m_cid = cid;
|
|
type = GetFolderType(idFolderSel);
|
|
if (type == FOLDER_IMAP || type == FOLDER_HTTPMAIL)
|
|
m_idFolderSel = idFolderSel;
|
|
|
|
iRet = (int) DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(IDD_PLAYBACK), hwnd, PlaybackDlgProc, (LPARAM)this);
|
|
|
|
if (m_cFailures > 0)
|
|
{
|
|
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsOfflineTransactionsFailed),
|
|
(m_cMovedToErrors > 0) ? MAKEINTRESOURCEW(idsMovedToOfflineErrors) : NULL, MB_OK | MB_ICONEXCLAMATION);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
INT_PTR CALLBACK COfflinePlayback::PlaybackDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BOOL fRet;
|
|
HRESULT hr;
|
|
COfflinePlayback *pThis;
|
|
|
|
fRet = TRUE;
|
|
|
|
switch (msg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
pThis = (COfflinePlayback *)lParam;
|
|
Assert(pThis != NULL);
|
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
|
|
|
|
pThis->m_hwndDlg = hwnd;
|
|
|
|
CenterDialog(hwnd);
|
|
|
|
Animate_OpenEx(GetDlgItem(hwnd, idcANI), g_hLocRes, MAKEINTRESOURCE(idanOutbox));
|
|
PostMessage(hwnd, WM_NEXT_OPERATION, 0, 0);
|
|
break;
|
|
|
|
case WM_NEXT_OPERATION:
|
|
pThis = (COfflinePlayback *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
|
Assert(pThis != NULL);
|
|
hr = pThis->_DoNextOperation();
|
|
if (hr != S_OK)
|
|
EndDialog(hwnd, 0);
|
|
break;
|
|
|
|
default:
|
|
fRet = FALSE;
|
|
break;
|
|
}
|
|
|
|
return(fRet);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_DoNextOperation()
|
|
{
|
|
HRESULT hr;
|
|
char sz[CCHMAX_STRINGRES], szT[CCHMAX_STRINGRES];
|
|
SYNCOPINFO info;
|
|
FOLDERINFO Folder;
|
|
|
|
Assert(m_pEnum != NULL);
|
|
Assert(g_pLocalStore != NULL);
|
|
|
|
if (m_iOps == m_cOps)
|
|
{
|
|
m_iOps = 0;
|
|
m_idServer = FOLDERID_INVALID;
|
|
m_idFolder = FOLDERID_INVALID;
|
|
if (m_pServer != NULL)
|
|
{
|
|
m_pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
|
|
m_pServer->Release();
|
|
m_pServer = NULL;
|
|
}
|
|
|
|
if (m_pLocalFolder != NULL)
|
|
{
|
|
m_pLocalFolder->Release();
|
|
m_pLocalFolder = NULL;
|
|
}
|
|
|
|
while (TRUE)
|
|
{
|
|
if (m_iid == m_cid)
|
|
{
|
|
hr = S_FALSE;
|
|
|
|
if (m_idFolderSel != FOLDERID_INVALID &&
|
|
m_fSyncSel)
|
|
{
|
|
if (SUCCEEDED(g_pLocalStore->GetFolderInfo(m_idFolderSel, &Folder)))
|
|
{
|
|
if (SUCCEEDED(CreateMessageServerType(Folder.tyFolder, &m_pServer)) &&
|
|
SUCCEEDED(g_pLocalStore->OpenFolder(m_idFolderSel, NULL, NOFLAGS, &m_pLocalFolder)) &&
|
|
SUCCEEDED(GetFolderServerId(m_idFolderSel, &m_idServer)) &&
|
|
SUCCEEDED(m_pServer->Initialize(g_pLocalStore, m_idServer, m_pLocalFolder, m_idFolderSel)))
|
|
{
|
|
if (E_PENDING == m_pServer->SynchronizeFolder(SYNC_FOLDER_CACHED_HEADERS | SYNC_FOLDER_NEW_HEADERS, 0, this))
|
|
{
|
|
m_idOperation = SYNCOPID_INVALID;
|
|
|
|
hr = S_OK;
|
|
}
|
|
}
|
|
|
|
g_pLocalStore->FreeRecord(&Folder);
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
m_idServer = m_pid[m_iid++];
|
|
hr = m_pEnum->Initialize(m_pDB, m_idServer);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
hr = m_pEnum->Count(&m_cOps);
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
if (m_cOps > 0)
|
|
{
|
|
if (SUCCEEDED(g_pLocalStore->GetFolderInfo(m_idServer, &Folder)))
|
|
{
|
|
AthLoadString(idsAccountLabelFmt, szT, ARRAYSIZE(szT));
|
|
wnsprintf(sz, ARRAYSIZE(sz), szT, Folder.pszName);
|
|
SetDlgItemText(m_hwndDlg, IDC_ACCOUNT_STATIC, sz);
|
|
g_pLocalStore->FreeRecord(&Folder);
|
|
}
|
|
|
|
SendDlgItemMessage(m_hwndDlg, idcProgBar, PBM_SETRANGE, 0, MAKELPARAM(0, m_cOps));
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
Assert(m_pEnum != NULL);
|
|
|
|
hr = m_pEnum->Next(&info);
|
|
if (hr != S_OK)
|
|
return(hr);
|
|
m_iOps++;
|
|
|
|
if (info.idFolder != m_idFolder)
|
|
{
|
|
if (m_pServer != NULL)
|
|
{
|
|
m_pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
|
|
m_pServer->Release();
|
|
m_pServer = NULL;
|
|
}
|
|
|
|
if (m_pLocalFolder != NULL)
|
|
{
|
|
m_pLocalFolder->Release();
|
|
m_pLocalFolder = NULL;
|
|
}
|
|
|
|
m_idFolder = info.idFolder;
|
|
|
|
hr = g_pLocalStore->GetFolderInfo(m_idFolder, &Folder);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CreateMessageServerType(Folder.tyFolder, &m_pServer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = g_pLocalStore->OpenFolder(m_idFolder, NULL, NOFLAGS, &m_pLocalFolder);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pServer->Initialize(g_pLocalStore, m_idServer, m_pLocalFolder, m_idFolder);
|
|
}
|
|
}
|
|
AthLoadString(idsFolderLabelFmt, szT, ARRAYSIZE(szT));
|
|
wnsprintf(sz, ARRAYSIZE(sz), szT, Folder.pszName);
|
|
SetDlgItemText(m_hwndDlg, IDC_FOO_STATIC, sz);
|
|
|
|
g_pLocalStore->FreeRecord(&Folder);
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
m_pDB->FreeRecord(&info);
|
|
return(hr);
|
|
}
|
|
}
|
|
|
|
SendDlgItemMessage(m_hwndDlg, idcProgBar, PBM_SETPOS, m_iOps, 0);
|
|
|
|
switch (info.tyOperation)
|
|
{
|
|
case SYNC_DELETE_MSG:
|
|
hr = _DoDeleteOp(&info);
|
|
break;
|
|
|
|
case SYNC_SETPROP_MSG:
|
|
hr = _DoSetPropOp(&info);
|
|
break;
|
|
|
|
case SYNC_CREATE_MSG:
|
|
hr = _DoCreateOp(&info);
|
|
break;
|
|
|
|
case SYNC_COPY_MSG:
|
|
case SYNC_MOVE_MSG:
|
|
hr = _DoCopyOp(&info);
|
|
break;
|
|
|
|
default:
|
|
Assert(FALSE);
|
|
break;
|
|
}
|
|
|
|
if (FAILED(hr))
|
|
{
|
|
Assert(hr != E_PENDING);
|
|
m_pDB->DeleteRecord(&info);
|
|
|
|
PostMessage(m_hwndDlg, WM_NEXT_OPERATION, 0, 0);
|
|
}
|
|
else
|
|
{
|
|
m_idOperation = info.idOperation;
|
|
}
|
|
m_pDB->FreeRecord(&info);
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_DoDeleteOp(SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
MESSAGEIDLIST list;
|
|
|
|
Assert(pInfo != NULL);
|
|
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessage;
|
|
|
|
hr = m_pServer->DeleteMessages(pInfo->dwFlags, &list, this);
|
|
if (hr == E_PENDING)
|
|
hr = S_OK;
|
|
else
|
|
Assert(FAILED(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_DoSetPropOp(SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
MESSAGEIDLIST list;
|
|
ADJUSTFLAGS flags;
|
|
|
|
Assert(pInfo != NULL);
|
|
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessage;
|
|
|
|
flags.dwRemove = pInfo->dwRemove;
|
|
flags.dwAdd = pInfo->dwAdd;
|
|
|
|
hr = m_pServer->SetMessageFlags(&list, &flags, SET_MESSAGE_FLAGS_FORCE, this);
|
|
if (hr == E_PENDING)
|
|
hr = S_OK;
|
|
else
|
|
Assert(FAILED(hr));
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_DoCreateOp(SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
IMimeMessage *pMessage;
|
|
IStream *pStream;
|
|
MESSAGEINFO Message;
|
|
PROPVARIANT rVariant;
|
|
LPFILETIME pftRecv;
|
|
DWORD dwFlags;
|
|
|
|
Assert(pInfo != NULL);
|
|
|
|
hr = m_pLocalFolder->OpenMessage(pInfo->idMessage, 0, &pMessage, NULL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
dwFlags = 0;
|
|
ZeroMemory(&Message, sizeof(MESSAGEINFO));
|
|
Message.idMessage = pInfo->idMessage;
|
|
if (DB_S_FOUND == m_pLocalFolder->FindRecord(IINDEX_PRIMARY, COLUMNS_ALL, &Message, NULL))
|
|
{
|
|
dwFlags = Message.dwFlags;
|
|
|
|
m_pLocalFolder->FreeRecord(&Message);
|
|
}
|
|
|
|
hr = pMessage->GetMessageSource(&pStream, 0);
|
|
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, this);
|
|
if (hr == E_PENDING)
|
|
hr = S_OK;
|
|
else
|
|
Assert(FAILED(hr));
|
|
|
|
pStream->Release();
|
|
}
|
|
|
|
pMessage->Release();
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_DoCopyOp(SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
MESSAGEIDLIST list;
|
|
MESSAGEINFO infoSrc, infoDest;
|
|
ADJUSTFLAGS flags, *pFlags;
|
|
|
|
Assert(pInfo != NULL);
|
|
Assert(pInfo->tyOperation == SYNC_COPY_MSG || pInfo->tyOperation == SYNC_MOVE_MSG);
|
|
Assert(m_pFolderDest == NULL);
|
|
|
|
hr = g_pLocalStore->OpenFolder(pInfo->idFolderDest, NULL, NOFLAGS, &m_pFolderDest);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessage;
|
|
|
|
if (pInfo->dwRemove != 0 || pInfo->dwAdd != 0)
|
|
{
|
|
flags.dwRemove = pInfo->dwRemove;
|
|
flags.dwAdd = pInfo->dwAdd;
|
|
pFlags = &flags;
|
|
}
|
|
else
|
|
{
|
|
pFlags = NULL;
|
|
}
|
|
|
|
hr = m_pServer->CopyMessages(m_pFolderDest, pInfo->tyOperation == SYNC_MOVE_MSG ? COPY_MESSAGE_MOVE : NOFLAGS,
|
|
&list, pFlags, this);
|
|
if (hr == E_PENDING)
|
|
{
|
|
hr = S_OK;
|
|
}
|
|
else
|
|
{
|
|
Assert(FAILED(hr));
|
|
|
|
m_pFolderDest->Release();
|
|
m_pFolderDest = NULL;
|
|
}
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_HandleSetPropComplete(HRESULT hrOperation, SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
MESSAGEIDLIST list;
|
|
ADJUSTFLAGS flags;
|
|
|
|
Assert(pInfo != NULL);
|
|
Assert(pInfo->tyOperation == SYNC_SETPROP_MSG);
|
|
Assert(m_pLocalFolder != NULL);
|
|
|
|
if (FAILED(hrOperation))
|
|
{
|
|
m_cFailures++;
|
|
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessage;
|
|
|
|
flags.dwAdd = pInfo->dwRemove;
|
|
flags.dwRemove = pInfo->dwAdd;
|
|
|
|
hr = m_pLocalFolder->SetMessageFlags(&list, &flags, NULL, NULL);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_HandleCreateComplete(HRESULT hrOperation, SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERINFO Folder;
|
|
MESSAGEIDLIST list;
|
|
IMessageFolder *pErrorFolder;
|
|
|
|
Assert(pInfo != NULL);
|
|
Assert(pInfo->tyOperation == SYNC_CREATE_MSG);
|
|
Assert(m_pLocalFolder != NULL);
|
|
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessage;
|
|
|
|
if (FAILED(hrOperation))
|
|
{
|
|
m_cFailures++;
|
|
|
|
hr = OpenErrorsFolder(&pErrorFolder);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = m_pLocalFolder->CopyMessages(pErrorFolder, NOFLAGS, &list, NULL, NULL, NULL);
|
|
if (SUCCEEDED(hr))
|
|
m_cMovedToErrors++;
|
|
|
|
pErrorFolder->Release();
|
|
}
|
|
}
|
|
|
|
// get rid of the temp offline msg
|
|
hr = m_pLocalFolder->DeleteMessages(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT, &list, NULL, NULL);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
if (pInfo->idFolder == m_idFolderSel)
|
|
m_fSyncSel = TRUE;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_HandleDeleteComplete(HRESULT hrOperation, SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
MESSAGEIDLIST list;
|
|
ADJUSTFLAGS flags;
|
|
|
|
Assert(pInfo != NULL);
|
|
Assert(pInfo->tyOperation == SYNC_DELETE_MSG);
|
|
Assert(m_pLocalFolder != NULL);
|
|
|
|
if (FAILED(hrOperation))
|
|
{
|
|
m_cFailures++;
|
|
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessage;
|
|
|
|
flags.dwAdd = 0;
|
|
flags.dwRemove = ARF_DELETED_OFFLINE;
|
|
|
|
hr = m_pLocalFolder->SetMessageFlags(&list, &flags, NULL, NULL);
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT COfflinePlayback::_HandleCopyComplete(HRESULT hrOperation, SYNCOPINFO *pInfo)
|
|
{
|
|
HRESULT hr;
|
|
MESSAGEIDLIST list;
|
|
ADJUSTFLAGS flags;
|
|
|
|
Assert(pInfo != NULL);
|
|
Assert(pInfo->tyOperation == SYNC_COPY_MSG || pInfo->tyOperation == SYNC_MOVE_MSG);
|
|
Assert(m_pLocalFolder != NULL);
|
|
|
|
if (pInfo->tyOperation == SYNC_MOVE_MSG && FAILED(hrOperation))
|
|
{
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessage;
|
|
|
|
flags.dwAdd = 0;
|
|
flags.dwRemove = ARF_DELETED_OFFLINE;
|
|
|
|
hr = m_pLocalFolder->SetMessageFlags(&list, &flags, NULL, NULL);
|
|
}
|
|
|
|
if (FAILED(hrOperation))
|
|
{
|
|
m_cFailures++;
|
|
|
|
// TODO: we need more robust error handling in here
|
|
}
|
|
|
|
list.cAllocated = 0;
|
|
list.cMsgs = 1;
|
|
list.prgidMsg = &pInfo->idMessageDest;
|
|
|
|
// get rid of the temp offline msg
|
|
hr = m_pFolderDest->DeleteMessages(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT, &list, NULL, NULL);
|
|
Assert(SUCCEEDED(hr));
|
|
|
|
if (pInfo->idFolderDest == m_idFolderSel)
|
|
m_fSyncSel = TRUE;
|
|
|
|
m_pFolderDest->Release();
|
|
m_pFolderDest = NULL;
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT OpenErrorsFolder(IMessageFolder **ppFolder)
|
|
{
|
|
FOLDERINFO Folder;
|
|
HRESULT hr;
|
|
char szFolder[CCHMAX_FOLDER_NAME];
|
|
|
|
Assert(g_pLocalStore != NULL);
|
|
Assert(ppFolder != NULL);
|
|
|
|
hr = g_pLocalStore->GetSpecialFolderInfo(FOLDERID_LOCAL_STORE, FOLDER_ERRORS, &Folder);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = g_pLocalStore->OpenFolder(Folder.idFolder, NULL, NOFLAGS, ppFolder);
|
|
|
|
g_pLocalStore->FreeRecord(&Folder);
|
|
}
|
|
else if (hr == DB_E_NOTFOUND)
|
|
{
|
|
LoadString(g_hLocRes, idsOfflineErrors, szFolder, ARRAYSIZE(szFolder));
|
|
|
|
// Fill the Folder Info
|
|
ZeroMemory(&Folder, sizeof(FOLDERINFO));
|
|
Folder.idParent = FOLDERID_LOCAL_STORE;
|
|
Folder.tySpecial = FOLDER_ERRORS;
|
|
Folder.pszName = szFolder;
|
|
Folder.dwFlags = FOLDER_SUBSCRIBED;
|
|
|
|
// Create the Folder
|
|
hr = g_pLocalStore->CreateFolder(NOFLAGS, &Folder, NOSTORECALLBACK);
|
|
if (SUCCEEDED(hr))
|
|
hr = g_pLocalStore->OpenFolder(Folder.idFolder, NULL, NOFLAGS, ppFolder);
|
|
}
|
|
|
|
return(hr);
|
|
}
|