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.
1010 lines
28 KiB
1010 lines
28 KiB
#include "pch.hxx"
|
|
#include "instance.h"
|
|
#include "storsync.h"
|
|
#include "msgfldr.h"
|
|
#include "storutil.h"
|
|
#include "store.h"
|
|
#include "fldrsync.h"
|
|
#include <conman.h>
|
|
|
|
IMessageStore *g_pLocalStore = NULL;
|
|
|
|
HRESULT InitializeStore(DWORD dwFlags /* MSOEAPI_xxx Flags from msoeapi.idl */)
|
|
{
|
|
HRESULT hr;
|
|
CStoreSync *pStore;
|
|
char szStoreDir[MAX_PATH + MAX_PATH];
|
|
|
|
hr = S_OK;
|
|
|
|
if (g_pStore == NULL)
|
|
{
|
|
Assert(g_pLocalStore == NULL);
|
|
|
|
hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
|
|
if (FAILED(hr))
|
|
return(hr);
|
|
|
|
g_pLocalStore = new CMessageStore(FALSE);
|
|
if (g_pLocalStore == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
hr = g_pLocalStore->Initialize(szStoreDir);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pStore = new CStoreSync;
|
|
if (pStore == NULL)
|
|
{
|
|
hr = E_OUTOFMEMORY;
|
|
}
|
|
else
|
|
{
|
|
hr = pStore->Initialize(g_pLocalStore);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
g_pStore = pStore;
|
|
hr = g_pLocalStore->Validate(ISFLAGSET(dwFlags, MSOEAPI_START_STOREVALIDNODELETE) ? STORE_VALIDATE_DONTSYNCWITHACCOUNTS : 0);
|
|
}
|
|
else
|
|
{
|
|
pStore->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
hr = ((CMessageStore *)g_pLocalStore)->MigrateToDBX();
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::CStoreSync
|
|
//--------------------------------------------------------------------------
|
|
CStoreSync::CStoreSync(void)
|
|
{
|
|
g_pInstance->DllAddRef();
|
|
m_cRef = 1;
|
|
m_pLocalStore = NULL;
|
|
m_fConManAdvise = FALSE;
|
|
ZeroMemory(m_rgts, sizeof(m_rgts));
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::~CStoreSync
|
|
//--------------------------------------------------------------------------
|
|
CStoreSync::~CStoreSync(void)
|
|
{
|
|
DWORD i, j;
|
|
|
|
SafeRelease(m_pLocalStore);
|
|
|
|
if (m_fConManAdvise && g_pConMan != NULL)
|
|
g_pConMan->Unadvise((IConnectionNotify *)this);
|
|
|
|
for (j = 0; j < CMAXTHREADS; j++)
|
|
{
|
|
if (m_rgts[j].pEntry != NULL)
|
|
{
|
|
for (i = 0; i < m_rgts[j].cEntry; i++)
|
|
{
|
|
if (m_rgts[j].pEntry[i].pServer != NULL)
|
|
{
|
|
m_rgts[j].pEntry[i].pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
|
|
m_rgts[j].pEntry[i].pServer->Release();
|
|
}
|
|
}
|
|
|
|
MemFree(m_rgts[j].pEntry);
|
|
}
|
|
}
|
|
|
|
g_pInstance->DllRelease();
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::QueryInterface
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::QueryInterface(REFIID riid, LPVOID *ppv)
|
|
{
|
|
if (IID_IUnknown == riid)
|
|
*ppv = (IMessageStore *)this;
|
|
else if (IID_IMessageStore == riid)
|
|
*ppv = (IMessageStore *)this;
|
|
else if (IID_IDatabase == riid)
|
|
*ppv = (IDatabase *)this;
|
|
else if (IID_IConnectionNotify == riid)
|
|
*ppv = (IConnectionNotify *)this;
|
|
else
|
|
{
|
|
*ppv = NULL;
|
|
return(E_NOINTERFACE);
|
|
}
|
|
|
|
((IUnknown *)*ppv)->AddRef();
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::AddRef
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CStoreSync::AddRef(void)
|
|
{
|
|
return InterlockedIncrement(&m_cRef);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::Release
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP_(ULONG) CStoreSync::Release(void)
|
|
{
|
|
LONG cRef = InterlockedDecrement(&m_cRef);
|
|
if (0 == cRef)
|
|
delete this;
|
|
return (ULONG)cRef;
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::Initialize
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::Initialize(LPCSTR pszDirectory)
|
|
{
|
|
Assert(FALSE);
|
|
return(E_NOTIMPL);
|
|
}
|
|
|
|
HRESULT CStoreSync::Initialize(IMessageStore *pLocalStore)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(pLocalStore != NULL);
|
|
Assert(g_pConMan != NULL);
|
|
Assert(g_pAcctMan != NULL);
|
|
|
|
// local store operation only
|
|
|
|
m_pLocalStore = pLocalStore;
|
|
m_pLocalStore->AddRef();
|
|
|
|
hr = g_pConMan->Advise((IConnectionNotify *)this);
|
|
m_fConManAdvise = SUCCEEDED(hr);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::Validate
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::Validate(DWORD dwReserved)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// local store operation only
|
|
|
|
hr = m_pLocalStore->Validate(dwReserved);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::GetDirectory
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::GetDirectory(LPSTR pszDir, DWORD cchMaxDir)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(NULL != pszDir);
|
|
|
|
// local store operation only
|
|
|
|
hr = m_pLocalStore->GetDirectory(pszDir, cchMaxDir);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::Synchronize
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::Synchronize(FOLDERID idFolder,
|
|
SYNCSTOREFLAGS dwFlags, IStoreCallback *pCallback)
|
|
{
|
|
BOOL fOffline;
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
IMessageServer *pServer;
|
|
|
|
Assert(FOLDERID_ROOT != idFolder);
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
// if online, sync folder list
|
|
// if offline, no op (fail)
|
|
|
|
hr = _GetFolderInfo(idFolder, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(!!(info.dwFlags & FOLDER_SERVER));
|
|
|
|
if (info.tyFolder != FOLDER_LOCAL)
|
|
{
|
|
if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->SynchronizeStore(idFolder, dwFlags, pCallback);
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::CreateServer
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::CreateServer(IImnAccount *pAcct, FLDRFLAGS dwFlags,
|
|
LPFOLDERID pidFolder)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// local store operation only
|
|
// create node in local store for server
|
|
|
|
hr = m_pLocalStore->CreateServer(pAcct, dwFlags, pidFolder);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::CreateFolder
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::CreateFolder(CREATEFOLDERFLAGS dwCreateFlags,
|
|
LPFOLDERINFO pInfo, IStoreCallback *pCallback)
|
|
{
|
|
FOLDERINFO info;
|
|
FOLDERID idFolder;
|
|
DWORD dwFlags;
|
|
HRESULT hr;
|
|
BOOL fOffline;
|
|
IMessageServer *pServer;
|
|
|
|
Assert(NULL != pInfo);
|
|
Assert(NULL != pInfo->pszName);
|
|
Assert(0 == (pInfo->dwFlags & FOLDER_SERVER));
|
|
|
|
if (NULL == pInfo->pszName || FIsEmpty(pInfo->pszName))
|
|
return(STORE_E_BADFOLDERNAME);
|
|
|
|
// if online, create folder on server and then create one in local store
|
|
// if offline, not supported (fail)
|
|
|
|
GetFolderServerId(pInfo->idParent, &idFolder);
|
|
|
|
hr = _GetFolderInfo(idFolder, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (info.tyFolder == FOLDER_LOCAL ||
|
|
dwCreateFlags == CREATE_FOLDER_LOCALONLY)
|
|
{
|
|
dwFlags = pInfo->dwFlags;
|
|
|
|
if (pInfo->tySpecial == FOLDER_NOTSPECIAL && info.tyFolder == FOLDER_LOCAL)
|
|
pInfo->dwFlags |= FOLDER_CANRENAME | FOLDER_CANDELETE;
|
|
|
|
hr = m_pLocalStore->CreateFolder(dwCreateFlags, pInfo, NOSTORECALLBACK);
|
|
|
|
pInfo->dwFlags = dwFlags;
|
|
}
|
|
else
|
|
{
|
|
Assert(info.tyFolder != FOLDER_NEWS);
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pServer->CreateFolder(pInfo->idParent, pInfo->tySpecial, pInfo->pszName, pInfo->dwFlags, pCallback);
|
|
}
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::OpenSpecialFolder
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::OpenSpecialFolder(FOLDERID idStore, IMessageServer *pServer,
|
|
SPECIALFOLDER tySpecial, IMessageFolder **ppFolder)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERINFO Folder;
|
|
|
|
// local store operation only
|
|
|
|
hr = GetSpecialFolderInfo(idStore, tySpecial, &Folder);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = OpenFolder(Folder.idFolder, pServer, NOFLAGS, ppFolder);
|
|
|
|
m_pLocalStore->FreeRecord(&Folder);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::OpenFolder
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::OpenFolder(FOLDERID idFolder, IMessageServer *pServerUseMeIfYouCan,
|
|
OPENFOLDERFLAGS dwFlags, IMessageFolder **ppFolder)
|
|
{
|
|
char sz[CCHMAX_ACCOUNT_NAME];
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
CFolderSync *pFolder;
|
|
CMessageFolder *pMsgFolder;
|
|
IMessageServer *pServer;
|
|
IMessageFolder *pLocalFolder=NULL;
|
|
FOLDERTYPE tyFolder;
|
|
FOLDERID idParent;
|
|
BOOL fFind;
|
|
|
|
Assert(NULL != ppFolder);
|
|
|
|
// local store operation only
|
|
|
|
pServer = NULL;
|
|
*ppFolder = NULL;
|
|
|
|
hr = GetFolderServerId(idFolder, &idParent);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
hr = m_pLocalStore->GetFolderInfo(idFolder, &info);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
tyFolder = info.tyFolder;
|
|
fFind = !!(info.dwFlags & FOLDER_FINDRESULTS);
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
|
|
if (fFind)
|
|
{
|
|
hr = m_pLocalStore->OpenFolder(idFolder, NULL, dwFlags, &pLocalFolder);
|
|
if (SUCCEEDED(hr))
|
|
*ppFolder = pLocalFolder;
|
|
return(hr);
|
|
}
|
|
|
|
pFolder = new CFolderSync;
|
|
if (pFolder == NULL)
|
|
return(E_OUTOFMEMORY);
|
|
|
|
Assert(hr == S_OK);
|
|
if (tyFolder != FOLDER_LOCAL)
|
|
{
|
|
hr = m_pLocalStore->OpenFolder(idFolder, NULL, dwFlags, &pLocalFolder);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (pServerUseMeIfYouCan != NULL)
|
|
{
|
|
hr = pServerUseMeIfYouCan->ResetFolder(pLocalFolder, idFolder);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pServer = pServerUseMeIfYouCan;
|
|
pServer->AddRef();
|
|
}
|
|
}
|
|
|
|
if (pServer == NULL)
|
|
{
|
|
hr = CreateMessageServerType(tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->Initialize(m_pLocalStore, idParent, pLocalFolder, idFolder);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
hr = pFolder->Initialize((IMessageStore *)m_pLocalStore, pLocalFolder, pServer, dwFlags, tyFolder, idFolder, idParent);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
*ppFolder = (IMessageFolder *)pFolder;
|
|
pFolder->AddRef();
|
|
}
|
|
|
|
if (pServer != NULL)
|
|
pServer->Release();
|
|
pFolder->Release();
|
|
if (pLocalFolder)
|
|
pLocalFolder->Release();
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::MoveFolder
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::MoveFolder(FOLDERID idFolder, FOLDERID idParentNew,
|
|
MOVEFOLDERFLAGS dwFlags, IStoreCallback *pCallback)
|
|
{
|
|
FOLDERINFO info;
|
|
FOLDERID idAcct, idAcctNew;
|
|
HRESULT hr;
|
|
IMessageServer *pServer;
|
|
BOOL fOffline;
|
|
|
|
// if online, move folder on server and then move folder in local store
|
|
// if offline, not supported (fail)
|
|
|
|
if (idFolder == idParentNew)
|
|
return(S_OK);
|
|
|
|
hr = GetFolderServerId(idParentNew, &idAcctNew);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
hr = GetFolderServerId(idFolder, &idAcct);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
// can't move between servers...
|
|
if (idAcct != idAcctNew)
|
|
return(hrCantMoveFolderBetweenServers);
|
|
|
|
hr = IsSubFolder(idParentNew, idFolder);
|
|
if (hr == S_OK)
|
|
return(hrCantMoveIntoSubfolder);
|
|
else if (FAILED(hr))
|
|
return(hr);
|
|
|
|
hr = _GetFolderInfo(idFolder, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(info.tyFolder != FOLDER_NEWS);
|
|
|
|
if (info.tyFolder == FOLDER_LOCAL)
|
|
{
|
|
hr = m_pLocalStore->MoveFolder(idFolder, idParentNew, dwFlags, NULL);
|
|
}
|
|
else
|
|
{
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->MoveFolder(idFolder, idParentNew, pCallback);
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::RenameFolder
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::RenameFolder(FOLDERID idFolder, LPCSTR pszName,
|
|
RENAMEFOLDERFLAGS dwFlags, IStoreCallback *pCallback)
|
|
{
|
|
FOLDERINFO info;
|
|
FOLDERID idParent;
|
|
HRESULT hr;
|
|
BOOL fOffline;
|
|
IMessageServer *pServer;
|
|
|
|
Assert(NULL != pszName);
|
|
|
|
// if online, rename folder on server and then rename folder in local store
|
|
// if offline, not supported (fail)
|
|
|
|
if (FIsEmpty(pszName))
|
|
return(STORE_E_BADFOLDERNAME);
|
|
|
|
hr = GetFolderServerId(idFolder, &idParent);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
if (idParent == idFolder)
|
|
{
|
|
// this is a server node, so we just handle it in the local store
|
|
hr = m_pLocalStore->RenameFolder(idFolder, pszName, dwFlags, NULL);
|
|
return(hr);
|
|
}
|
|
|
|
hr = _GetFolderInfo(idParent, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(info.tyFolder != FOLDER_NEWS);
|
|
|
|
if (info.tyFolder == FOLDER_LOCAL)
|
|
{
|
|
hr = m_pLocalStore->RenameFolder(idFolder, pszName, dwFlags, NULL);
|
|
}
|
|
else
|
|
{
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->RenameFolder(idFolder, pszName, pCallback);
|
|
}
|
|
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::DeleteFolder
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::DeleteFolder(FOLDERID idFolder,
|
|
DELETEFOLDERFLAGS dwFlags, IStoreCallback *pCallback)
|
|
{
|
|
FOLDERINFO info;
|
|
FOLDERID idParent;
|
|
HRESULT hr;
|
|
BOOL fOffline;
|
|
IMessageServer *pServer;
|
|
|
|
Assert(FOLDERID_ROOT != idFolder);
|
|
Assert(FOLDERID_INVALID != idFolder);
|
|
|
|
// if online, delete folder on server and then delete folder in local store
|
|
// if offline, not supported (fail)
|
|
|
|
hr = GetFolderServerId(idFolder, &idParent);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
if (idParent == idFolder)
|
|
{
|
|
// this is a server node, so we just handle it in the local store
|
|
hr = m_pLocalStore->DeleteFolder(idFolder, dwFlags, pCallback);
|
|
return(hr);
|
|
}
|
|
|
|
hr = _GetFolderInfo(idParent, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(info.tyFolder != FOLDER_NEWS);
|
|
|
|
if (info.tyFolder == FOLDER_LOCAL)
|
|
{
|
|
hr = m_pLocalStore->DeleteFolder(idFolder, dwFlags, NULL);
|
|
}
|
|
else
|
|
{
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->DeleteFolder(idFolder, dwFlags, pCallback);
|
|
}
|
|
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::FindServerId
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::FindServerId(LPCSTR pszAcctId, LPFOLDERID pidServer)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(pszAcctId != NULL);
|
|
Assert(pidServer != NULL);
|
|
|
|
// local store operation only
|
|
|
|
hr = m_pLocalStore->FindServerId(pszAcctId, pidServer);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// GetFolderInfo
|
|
//--------------------------------------------------------------------------
|
|
HRESULT CStoreSync::GetFolderInfo(FOLDERID idFolder, LPFOLDERINFO pInfo)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(pInfo != NULL);
|
|
|
|
// local store operation only
|
|
|
|
hr = m_pLocalStore->GetFolderInfo(idFolder, pInfo);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::EnumChildren
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::EnumChildren(FOLDERID idParent, BOOL fSubscribed,
|
|
IEnumerateFolders **ppEnum)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(ppEnum != NULL);
|
|
|
|
// local store operation only
|
|
|
|
hr = m_pLocalStore->EnumChildren(idParent, fSubscribed, ppEnum);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::GetSpecialFolderInfo
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::GetSpecialFolderInfo(FOLDERID idStore,
|
|
SPECIALFOLDER tySpecial, LPFOLDERINFO pInfo)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(NULL != pInfo);
|
|
Assert(FOLDER_NOTSPECIAL != tySpecial);
|
|
|
|
// local store operation only
|
|
|
|
hr = m_pLocalStore->GetSpecialFolderInfo(idStore, tySpecial, pInfo);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::SubscribeToFolder
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::SubscribeToFolder(FOLDERID idFolder,
|
|
BOOL fSubscribed, IStoreCallback *pCallback)
|
|
{
|
|
FOLDERINFO info;
|
|
FOLDERID idParent;
|
|
HRESULT hr;
|
|
BOOL fOffline;
|
|
IMessageServer *pServer;
|
|
|
|
Assert(NULL != m_pLocalStore);
|
|
|
|
// if imap and online, subscribe to folder on server and then in local store
|
|
// otherwise, subscribe to folder in local store
|
|
|
|
hr = GetFolderServerId(idFolder, &idParent);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
hr = _GetFolderInfo(idParent, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
Assert(info.tyFolder != FOLDER_LOCAL);
|
|
|
|
if (info.tyFolder == FOLDER_NEWS)
|
|
{
|
|
hr = m_pLocalStore->SubscribeToFolder(idFolder, fSubscribed, NULL);
|
|
}
|
|
else
|
|
{
|
|
Assert(info.tyFolder == FOLDER_IMAP);
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->SubscribeToFolder(idFolder, fSubscribed, pCallback);
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CStoreSync::GetNewGroups(FOLDERID idFolder, LPSYSTEMTIME pSysTime, IStoreCallback *pCallback)
|
|
{
|
|
FOLDERINFO info;
|
|
HRESULT hr;
|
|
BOOL fOffline;
|
|
IMessageServer *pServer;
|
|
|
|
Assert(m_pLocalStore != NULL);
|
|
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
return(E_INVALIDARG);
|
|
|
|
// if news server and online, get new groups on server
|
|
|
|
hr = _GetFolderInfo(idFolder, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (info.tyFolder != FOLDER_NEWS ||
|
|
0 == (info.dwFlags & FOLDER_SERVER))
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->GetNewGroups(pSysTime, pCallback);
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::GetFolderCounts
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::GetFolderCounts(FOLDERID idFolder, IStoreCallback *pCallback)
|
|
{
|
|
HRESULT hr;
|
|
FOLDERINFO info;
|
|
FOLDERID idParent;
|
|
BOOL fOffline;
|
|
IMessageServer *pServer;
|
|
|
|
Assert(NULL != m_pLocalStore);
|
|
|
|
// if imap or news, pass GetFolderCounts call through to server obj
|
|
// otherwise, this function should not have been called so returns error
|
|
|
|
hr = GetFolderServerId(idFolder, &idParent);
|
|
if (hr != S_OK)
|
|
return(E_FAIL);
|
|
|
|
hr = _GetFolderInfo(idParent, &info, &fOffline);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (info.tyFolder != FOLDER_LOCAL)
|
|
{
|
|
Assert(pCallback != NULL);
|
|
if (pCallback == NULL)
|
|
{
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else if (fOffline)
|
|
{
|
|
hr = E_NOT_ONLINE;
|
|
}
|
|
else
|
|
{
|
|
hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
hr = pServer->GetFolderCounts(idFolder, pCallback);
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
//--------------------------------------------------------------------------
|
|
// CStoreSync::UpdateFolderCounts
|
|
//--------------------------------------------------------------------------
|
|
STDMETHODIMP CStoreSync::UpdateFolderCounts(FOLDERID idFolder, LONG lMessages,
|
|
LONG lUnread, LONG lWatchedUnread, LONG lWatched)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(NULL != m_pLocalStore);
|
|
|
|
// local store operation only
|
|
|
|
hr = m_pLocalStore->UpdateFolderCounts(idFolder, lMessages, lUnread, lWatchedUnread, lWatched);
|
|
|
|
return(hr);
|
|
}
|
|
|
|
STDMETHODIMP CStoreSync::OnConnectionNotify(CONNNOTIFY nCode, LPVOID pvData, CConnectionManager *pConMan)
|
|
{
|
|
if (nCode == CONNNOTIFY_CONNECTED)
|
|
{
|
|
|
|
}
|
|
else if (((nCode == CONNNOTIFY_WORKOFFLINE) && (pvData)) ||
|
|
(nCode == CONNNOTIFY_DISCONNECTED))
|
|
{
|
|
DWORD i, j;
|
|
|
|
for (j = 0; j < CMAXTHREADS; j++)
|
|
{
|
|
if (m_rgts[j].pEntry != NULL)
|
|
{
|
|
for (i = 0; i < m_rgts[j].cEntry; i++)
|
|
{
|
|
if (m_rgts[j].pEntry[i].pServer != NULL)
|
|
{
|
|
m_rgts[j].pEntry[i].pServer->Close(MSGSVRF_DROP_CONNECTION);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(S_OK);
|
|
}
|
|
|
|
HRESULT CStoreSync::_GetFolderInfo(FOLDERID id, FOLDERINFO *pInfo, BOOL *pfOffline)
|
|
{
|
|
HRESULT hr;
|
|
|
|
Assert(pInfo != NULL);
|
|
Assert(pfOffline != NULL);
|
|
|
|
hr = m_pLocalStore->GetFolderInfo(id, pInfo);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//*pfOffline = g_pConMan->IsGlobalOffline();
|
|
*pfOffline = FALSE;
|
|
}
|
|
|
|
return(hr);
|
|
}
|
|
|
|
HRESULT CStoreSync::_GetServer(FOLDERID idServer, FOLDERID idFolder, FOLDERTYPE tyFolder, IMessageServer **ppServer)
|
|
{
|
|
HRESULT hr;
|
|
IMessageServer *pServer;
|
|
DWORD i;
|
|
FOLDERINFO info;
|
|
SERVERENTRY *pEntry;
|
|
DWORD dwThreadId;
|
|
THREADSERVERS *pts;
|
|
|
|
Assert(FOLDER_LOCAL != tyFolder);
|
|
Assert(FOLDER_ROOTNODE != tyFolder);
|
|
Assert(ppServer != NULL);
|
|
Assert(idServer == idFolder);
|
|
|
|
// TODO: figure out a way not to hold onto these IMessageServer objects...
|
|
|
|
*ppServer = NULL;
|
|
|
|
dwThreadId = GetCurrentThreadId();
|
|
Assert(dwThreadId != 0);
|
|
|
|
for (i = 0, pts = m_rgts; i < CMAXTHREADS; i++, pts++)
|
|
{
|
|
if (dwThreadId == pts->dwThreadId)
|
|
{
|
|
break;
|
|
}
|
|
else if (pts->dwThreadId == 0)
|
|
{
|
|
pts->dwThreadId = dwThreadId;
|
|
break;
|
|
}
|
|
}
|
|
Assert(i != CMAXTHREADS);
|
|
|
|
for (i = 0, pEntry = pts->pEntry; i < pts->cEntry; i++, pEntry++)
|
|
{
|
|
if (pEntry->idFolder == idFolder)
|
|
{
|
|
Assert(pEntry->idServer == idServer);
|
|
*ppServer = pEntry->pServer;
|
|
return(S_OK);
|
|
}
|
|
}
|
|
|
|
if (pts->cEntry == pts->cEntryBuf)
|
|
{
|
|
i = pts->cEntryBuf + 16;
|
|
if (!MemRealloc((void **)&pts->pEntry, i * sizeof(SERVERENTRY)))
|
|
return(E_OUTOFMEMORY);
|
|
pts->cEntryBuf = i;
|
|
}
|
|
|
|
hr = m_pLocalStore->GetFolderInfo(idServer, &info);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = CreateMessageServerType(tyFolder, &pServer);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pServer->Initialize(m_pLocalStore, idServer, NULL, FOLDERID_INVALID);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pEntry = &pts->pEntry[pts->cEntry];
|
|
pEntry->pServer = pServer;
|
|
pEntry->idServer = idServer;
|
|
pEntry->idFolder = idFolder;
|
|
pts->cEntry++;
|
|
|
|
*ppServer = pServer;
|
|
}
|
|
else
|
|
{
|
|
pServer->Release();
|
|
}
|
|
}
|
|
|
|
m_pLocalStore->FreeRecord(&info);
|
|
}
|
|
|
|
return(hr);
|
|
}
|