Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1010 lines
28 KiB

  1. #include "pch.hxx"
  2. #include "instance.h"
  3. #include "storsync.h"
  4. #include "msgfldr.h"
  5. #include "storutil.h"
  6. #include "store.h"
  7. #include "fldrsync.h"
  8. #include <conman.h>
  9. IMessageStore *g_pLocalStore = NULL;
  10. HRESULT InitializeStore(DWORD dwFlags /* MSOEAPI_xxx Flags from msoeapi.idl */)
  11. {
  12. HRESULT hr;
  13. CStoreSync *pStore;
  14. char szStoreDir[MAX_PATH + MAX_PATH];
  15. hr = S_OK;
  16. if (g_pStore == NULL)
  17. {
  18. Assert(g_pLocalStore == NULL);
  19. hr = GetStoreRootDirectory(szStoreDir, ARRAYSIZE(szStoreDir));
  20. if (FAILED(hr))
  21. return(hr);
  22. g_pLocalStore = new CMessageStore(FALSE);
  23. if (g_pLocalStore == NULL)
  24. return(E_OUTOFMEMORY);
  25. hr = g_pLocalStore->Initialize(szStoreDir);
  26. if (SUCCEEDED(hr))
  27. {
  28. pStore = new CStoreSync;
  29. if (pStore == NULL)
  30. {
  31. hr = E_OUTOFMEMORY;
  32. }
  33. else
  34. {
  35. hr = pStore->Initialize(g_pLocalStore);
  36. if (SUCCEEDED(hr))
  37. {
  38. g_pStore = pStore;
  39. hr = g_pLocalStore->Validate(ISFLAGSET(dwFlags, MSOEAPI_START_STOREVALIDNODELETE) ? STORE_VALIDATE_DONTSYNCWITHACCOUNTS : 0);
  40. }
  41. else
  42. {
  43. pStore->Release();
  44. }
  45. }
  46. }
  47. hr = ((CMessageStore *)g_pLocalStore)->MigrateToDBX();
  48. }
  49. return(hr);
  50. }
  51. //--------------------------------------------------------------------------
  52. // CStoreSync::CStoreSync
  53. //--------------------------------------------------------------------------
  54. CStoreSync::CStoreSync(void)
  55. {
  56. g_pInstance->DllAddRef();
  57. m_cRef = 1;
  58. m_pLocalStore = NULL;
  59. m_fConManAdvise = FALSE;
  60. ZeroMemory(m_rgts, sizeof(m_rgts));
  61. }
  62. //--------------------------------------------------------------------------
  63. // CStoreSync::~CStoreSync
  64. //--------------------------------------------------------------------------
  65. CStoreSync::~CStoreSync(void)
  66. {
  67. DWORD i, j;
  68. SafeRelease(m_pLocalStore);
  69. if (m_fConManAdvise && g_pConMan != NULL)
  70. g_pConMan->Unadvise((IConnectionNotify *)this);
  71. for (j = 0; j < CMAXTHREADS; j++)
  72. {
  73. if (m_rgts[j].pEntry != NULL)
  74. {
  75. for (i = 0; i < m_rgts[j].cEntry; i++)
  76. {
  77. if (m_rgts[j].pEntry[i].pServer != NULL)
  78. {
  79. m_rgts[j].pEntry[i].pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
  80. m_rgts[j].pEntry[i].pServer->Release();
  81. }
  82. }
  83. MemFree(m_rgts[j].pEntry);
  84. }
  85. }
  86. g_pInstance->DllRelease();
  87. }
  88. //--------------------------------------------------------------------------
  89. // CStoreSync::QueryInterface
  90. //--------------------------------------------------------------------------
  91. STDMETHODIMP CStoreSync::QueryInterface(REFIID riid, LPVOID *ppv)
  92. {
  93. if (IID_IUnknown == riid)
  94. *ppv = (IMessageStore *)this;
  95. else if (IID_IMessageStore == riid)
  96. *ppv = (IMessageStore *)this;
  97. else if (IID_IDatabase == riid)
  98. *ppv = (IDatabase *)this;
  99. else if (IID_IConnectionNotify == riid)
  100. *ppv = (IConnectionNotify *)this;
  101. else
  102. {
  103. *ppv = NULL;
  104. return(E_NOINTERFACE);
  105. }
  106. ((IUnknown *)*ppv)->AddRef();
  107. return(S_OK);
  108. }
  109. //--------------------------------------------------------------------------
  110. // CStoreSync::AddRef
  111. //--------------------------------------------------------------------------
  112. STDMETHODIMP_(ULONG) CStoreSync::AddRef(void)
  113. {
  114. return InterlockedIncrement(&m_cRef);
  115. }
  116. //--------------------------------------------------------------------------
  117. // CStoreSync::Release
  118. //--------------------------------------------------------------------------
  119. STDMETHODIMP_(ULONG) CStoreSync::Release(void)
  120. {
  121. LONG cRef = InterlockedDecrement(&m_cRef);
  122. if (0 == cRef)
  123. delete this;
  124. return (ULONG)cRef;
  125. }
  126. //--------------------------------------------------------------------------
  127. // CStoreSync::Initialize
  128. //--------------------------------------------------------------------------
  129. STDMETHODIMP CStoreSync::Initialize(LPCSTR pszDirectory)
  130. {
  131. Assert(FALSE);
  132. return(E_NOTIMPL);
  133. }
  134. HRESULT CStoreSync::Initialize(IMessageStore *pLocalStore)
  135. {
  136. HRESULT hr;
  137. Assert(pLocalStore != NULL);
  138. Assert(g_pConMan != NULL);
  139. Assert(g_pAcctMan != NULL);
  140. // local store operation only
  141. m_pLocalStore = pLocalStore;
  142. m_pLocalStore->AddRef();
  143. hr = g_pConMan->Advise((IConnectionNotify *)this);
  144. m_fConManAdvise = SUCCEEDED(hr);
  145. return(hr);
  146. }
  147. //--------------------------------------------------------------------------
  148. // CStoreSync::Validate
  149. //--------------------------------------------------------------------------
  150. STDMETHODIMP CStoreSync::Validate(DWORD dwReserved)
  151. {
  152. HRESULT hr;
  153. // local store operation only
  154. hr = m_pLocalStore->Validate(dwReserved);
  155. return(hr);
  156. }
  157. //--------------------------------------------------------------------------
  158. // CStoreSync::GetDirectory
  159. //--------------------------------------------------------------------------
  160. STDMETHODIMP CStoreSync::GetDirectory(LPSTR pszDir, DWORD cchMaxDir)
  161. {
  162. HRESULT hr;
  163. Assert(NULL != pszDir);
  164. // local store operation only
  165. hr = m_pLocalStore->GetDirectory(pszDir, cchMaxDir);
  166. return(hr);
  167. }
  168. //--------------------------------------------------------------------------
  169. // CStoreSync::Synchronize
  170. //--------------------------------------------------------------------------
  171. STDMETHODIMP CStoreSync::Synchronize(FOLDERID idFolder,
  172. SYNCSTOREFLAGS dwFlags, IStoreCallback *pCallback)
  173. {
  174. BOOL fOffline;
  175. FOLDERINFO info;
  176. HRESULT hr;
  177. IMessageServer *pServer;
  178. Assert(FOLDERID_ROOT != idFolder);
  179. Assert(pCallback != NULL);
  180. if (pCallback == NULL)
  181. return(E_INVALIDARG);
  182. // if online, sync folder list
  183. // if offline, no op (fail)
  184. hr = _GetFolderInfo(idFolder, &info, &fOffline);
  185. if (SUCCEEDED(hr))
  186. {
  187. Assert(!!(info.dwFlags & FOLDER_SERVER));
  188. if (info.tyFolder != FOLDER_LOCAL)
  189. {
  190. if (fOffline)
  191. {
  192. hr = E_NOT_ONLINE;
  193. }
  194. else
  195. {
  196. hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
  197. if (SUCCEEDED(hr))
  198. hr = pServer->SynchronizeStore(idFolder, dwFlags, pCallback);
  199. }
  200. }
  201. m_pLocalStore->FreeRecord(&info);
  202. }
  203. return(hr);
  204. }
  205. //--------------------------------------------------------------------------
  206. // CStoreSync::CreateServer
  207. //--------------------------------------------------------------------------
  208. STDMETHODIMP CStoreSync::CreateServer(IImnAccount *pAcct, FLDRFLAGS dwFlags,
  209. LPFOLDERID pidFolder)
  210. {
  211. HRESULT hr;
  212. // local store operation only
  213. // create node in local store for server
  214. hr = m_pLocalStore->CreateServer(pAcct, dwFlags, pidFolder);
  215. return(hr);
  216. }
  217. //--------------------------------------------------------------------------
  218. // CStoreSync::CreateFolder
  219. //--------------------------------------------------------------------------
  220. STDMETHODIMP CStoreSync::CreateFolder(CREATEFOLDERFLAGS dwCreateFlags,
  221. LPFOLDERINFO pInfo, IStoreCallback *pCallback)
  222. {
  223. FOLDERINFO info;
  224. FOLDERID idFolder;
  225. DWORD dwFlags;
  226. HRESULT hr;
  227. BOOL fOffline;
  228. IMessageServer *pServer;
  229. Assert(NULL != pInfo);
  230. Assert(NULL != pInfo->pszName);
  231. Assert(0 == (pInfo->dwFlags & FOLDER_SERVER));
  232. if (NULL == pInfo->pszName || FIsEmpty(pInfo->pszName))
  233. return(STORE_E_BADFOLDERNAME);
  234. // if online, create folder on server and then create one in local store
  235. // if offline, not supported (fail)
  236. GetFolderServerId(pInfo->idParent, &idFolder);
  237. hr = _GetFolderInfo(idFolder, &info, &fOffline);
  238. if (SUCCEEDED(hr))
  239. {
  240. if (info.tyFolder == FOLDER_LOCAL ||
  241. dwCreateFlags == CREATE_FOLDER_LOCALONLY)
  242. {
  243. dwFlags = pInfo->dwFlags;
  244. if (pInfo->tySpecial == FOLDER_NOTSPECIAL && info.tyFolder == FOLDER_LOCAL)
  245. pInfo->dwFlags |= FOLDER_CANRENAME | FOLDER_CANDELETE;
  246. hr = m_pLocalStore->CreateFolder(dwCreateFlags, pInfo, NOSTORECALLBACK);
  247. pInfo->dwFlags = dwFlags;
  248. }
  249. else
  250. {
  251. Assert(info.tyFolder != FOLDER_NEWS);
  252. Assert(pCallback != NULL);
  253. if (pCallback == NULL)
  254. {
  255. hr = E_INVALIDARG;
  256. }
  257. else if (fOffline)
  258. {
  259. hr = E_NOT_ONLINE;
  260. }
  261. else
  262. {
  263. hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
  264. if (SUCCEEDED(hr))
  265. {
  266. hr = pServer->CreateFolder(pInfo->idParent, pInfo->tySpecial, pInfo->pszName, pInfo->dwFlags, pCallback);
  267. }
  268. }
  269. }
  270. m_pLocalStore->FreeRecord(&info);
  271. }
  272. return(hr);
  273. }
  274. //--------------------------------------------------------------------------
  275. // CStoreSync::OpenSpecialFolder
  276. //--------------------------------------------------------------------------
  277. STDMETHODIMP CStoreSync::OpenSpecialFolder(FOLDERID idStore, IMessageServer *pServer,
  278. SPECIALFOLDER tySpecial, IMessageFolder **ppFolder)
  279. {
  280. HRESULT hr;
  281. FOLDERINFO Folder;
  282. // local store operation only
  283. hr = GetSpecialFolderInfo(idStore, tySpecial, &Folder);
  284. if (SUCCEEDED(hr))
  285. {
  286. hr = OpenFolder(Folder.idFolder, pServer, NOFLAGS, ppFolder);
  287. m_pLocalStore->FreeRecord(&Folder);
  288. }
  289. return(hr);
  290. }
  291. //--------------------------------------------------------------------------
  292. // CStoreSync::OpenFolder
  293. //--------------------------------------------------------------------------
  294. STDMETHODIMP CStoreSync::OpenFolder(FOLDERID idFolder, IMessageServer *pServerUseMeIfYouCan,
  295. OPENFOLDERFLAGS dwFlags, IMessageFolder **ppFolder)
  296. {
  297. char sz[CCHMAX_ACCOUNT_NAME];
  298. FOLDERINFO info;
  299. HRESULT hr;
  300. CFolderSync *pFolder;
  301. CMessageFolder *pMsgFolder;
  302. IMessageServer *pServer;
  303. IMessageFolder *pLocalFolder=NULL;
  304. FOLDERTYPE tyFolder;
  305. FOLDERID idParent;
  306. BOOL fFind;
  307. Assert(NULL != ppFolder);
  308. // local store operation only
  309. pServer = NULL;
  310. *ppFolder = NULL;
  311. hr = GetFolderServerId(idFolder, &idParent);
  312. if (hr != S_OK)
  313. return(E_FAIL);
  314. hr = m_pLocalStore->GetFolderInfo(idFolder, &info);
  315. if (hr != S_OK)
  316. return(E_FAIL);
  317. tyFolder = info.tyFolder;
  318. fFind = !!(info.dwFlags & FOLDER_FINDRESULTS);
  319. m_pLocalStore->FreeRecord(&info);
  320. if (fFind)
  321. {
  322. hr = m_pLocalStore->OpenFolder(idFolder, NULL, dwFlags, &pLocalFolder);
  323. if (SUCCEEDED(hr))
  324. *ppFolder = pLocalFolder;
  325. return(hr);
  326. }
  327. pFolder = new CFolderSync;
  328. if (pFolder == NULL)
  329. return(E_OUTOFMEMORY);
  330. Assert(hr == S_OK);
  331. if (tyFolder != FOLDER_LOCAL)
  332. {
  333. hr = m_pLocalStore->OpenFolder(idFolder, NULL, dwFlags, &pLocalFolder);
  334. if (SUCCEEDED(hr))
  335. {
  336. if (pServerUseMeIfYouCan != NULL)
  337. {
  338. hr = pServerUseMeIfYouCan->ResetFolder(pLocalFolder, idFolder);
  339. if (SUCCEEDED(hr))
  340. {
  341. pServer = pServerUseMeIfYouCan;
  342. pServer->AddRef();
  343. }
  344. }
  345. if (pServer == NULL)
  346. {
  347. hr = CreateMessageServerType(tyFolder, &pServer);
  348. if (SUCCEEDED(hr))
  349. hr = pServer->Initialize(m_pLocalStore, idParent, pLocalFolder, idFolder);
  350. }
  351. }
  352. }
  353. if (SUCCEEDED(hr))
  354. hr = pFolder->Initialize((IMessageStore *)m_pLocalStore, pLocalFolder, pServer, dwFlags, tyFolder, idFolder, idParent);
  355. if (SUCCEEDED(hr))
  356. {
  357. *ppFolder = (IMessageFolder *)pFolder;
  358. pFolder->AddRef();
  359. }
  360. if (pServer != NULL)
  361. pServer->Release();
  362. pFolder->Release();
  363. if (pLocalFolder)
  364. pLocalFolder->Release();
  365. return(hr);
  366. }
  367. //--------------------------------------------------------------------------
  368. // CStoreSync::MoveFolder
  369. //--------------------------------------------------------------------------
  370. STDMETHODIMP CStoreSync::MoveFolder(FOLDERID idFolder, FOLDERID idParentNew,
  371. MOVEFOLDERFLAGS dwFlags, IStoreCallback *pCallback)
  372. {
  373. FOLDERINFO info;
  374. FOLDERID idAcct, idAcctNew;
  375. HRESULT hr;
  376. IMessageServer *pServer;
  377. BOOL fOffline;
  378. // if online, move folder on server and then move folder in local store
  379. // if offline, not supported (fail)
  380. if (idFolder == idParentNew)
  381. return(S_OK);
  382. hr = GetFolderServerId(idParentNew, &idAcctNew);
  383. if (hr != S_OK)
  384. return(E_FAIL);
  385. hr = GetFolderServerId(idFolder, &idAcct);
  386. if (hr != S_OK)
  387. return(E_FAIL);
  388. // can't move between servers...
  389. if (idAcct != idAcctNew)
  390. return(hrCantMoveFolderBetweenServers);
  391. hr = IsSubFolder(idParentNew, idFolder);
  392. if (hr == S_OK)
  393. return(hrCantMoveIntoSubfolder);
  394. else if (FAILED(hr))
  395. return(hr);
  396. hr = _GetFolderInfo(idFolder, &info, &fOffline);
  397. if (SUCCEEDED(hr))
  398. {
  399. Assert(info.tyFolder != FOLDER_NEWS);
  400. if (info.tyFolder == FOLDER_LOCAL)
  401. {
  402. hr = m_pLocalStore->MoveFolder(idFolder, idParentNew, dwFlags, NULL);
  403. }
  404. else
  405. {
  406. Assert(pCallback != NULL);
  407. if (pCallback == NULL)
  408. {
  409. hr = E_INVALIDARG;
  410. }
  411. else if (fOffline)
  412. {
  413. hr = E_NOT_ONLINE;
  414. }
  415. else
  416. {
  417. hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
  418. if (SUCCEEDED(hr))
  419. hr = pServer->MoveFolder(idFolder, idParentNew, pCallback);
  420. }
  421. }
  422. m_pLocalStore->FreeRecord(&info);
  423. }
  424. return(hr);
  425. }
  426. //--------------------------------------------------------------------------
  427. // CStoreSync::RenameFolder
  428. //--------------------------------------------------------------------------
  429. STDMETHODIMP CStoreSync::RenameFolder(FOLDERID idFolder, LPCSTR pszName,
  430. RENAMEFOLDERFLAGS dwFlags, IStoreCallback *pCallback)
  431. {
  432. FOLDERINFO info;
  433. FOLDERID idParent;
  434. HRESULT hr;
  435. BOOL fOffline;
  436. IMessageServer *pServer;
  437. Assert(NULL != pszName);
  438. // if online, rename folder on server and then rename folder in local store
  439. // if offline, not supported (fail)
  440. if (FIsEmpty(pszName))
  441. return(STORE_E_BADFOLDERNAME);
  442. hr = GetFolderServerId(idFolder, &idParent);
  443. if (hr != S_OK)
  444. return(E_FAIL);
  445. if (idParent == idFolder)
  446. {
  447. // this is a server node, so we just handle it in the local store
  448. hr = m_pLocalStore->RenameFolder(idFolder, pszName, dwFlags, NULL);
  449. return(hr);
  450. }
  451. hr = _GetFolderInfo(idParent, &info, &fOffline);
  452. if (SUCCEEDED(hr))
  453. {
  454. Assert(info.tyFolder != FOLDER_NEWS);
  455. if (info.tyFolder == FOLDER_LOCAL)
  456. {
  457. hr = m_pLocalStore->RenameFolder(idFolder, pszName, dwFlags, NULL);
  458. }
  459. else
  460. {
  461. Assert(pCallback != NULL);
  462. if (pCallback == NULL)
  463. {
  464. hr = E_INVALIDARG;
  465. }
  466. else if (fOffline)
  467. {
  468. hr = E_NOT_ONLINE;
  469. }
  470. else
  471. {
  472. hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
  473. if (SUCCEEDED(hr))
  474. hr = pServer->RenameFolder(idFolder, pszName, pCallback);
  475. }
  476. }
  477. m_pLocalStore->FreeRecord(&info);
  478. }
  479. return(hr);
  480. }
  481. //--------------------------------------------------------------------------
  482. // CStoreSync::DeleteFolder
  483. //--------------------------------------------------------------------------
  484. STDMETHODIMP CStoreSync::DeleteFolder(FOLDERID idFolder,
  485. DELETEFOLDERFLAGS dwFlags, IStoreCallback *pCallback)
  486. {
  487. FOLDERINFO info;
  488. FOLDERID idParent;
  489. HRESULT hr;
  490. BOOL fOffline;
  491. IMessageServer *pServer;
  492. Assert(FOLDERID_ROOT != idFolder);
  493. Assert(FOLDERID_INVALID != idFolder);
  494. // if online, delete folder on server and then delete folder in local store
  495. // if offline, not supported (fail)
  496. hr = GetFolderServerId(idFolder, &idParent);
  497. if (hr != S_OK)
  498. return(E_FAIL);
  499. if (idParent == idFolder)
  500. {
  501. // this is a server node, so we just handle it in the local store
  502. hr = m_pLocalStore->DeleteFolder(idFolder, dwFlags, pCallback);
  503. return(hr);
  504. }
  505. hr = _GetFolderInfo(idParent, &info, &fOffline);
  506. if (SUCCEEDED(hr))
  507. {
  508. Assert(info.tyFolder != FOLDER_NEWS);
  509. if (info.tyFolder == FOLDER_LOCAL)
  510. {
  511. hr = m_pLocalStore->DeleteFolder(idFolder, dwFlags, NULL);
  512. }
  513. else
  514. {
  515. Assert(pCallback != NULL);
  516. if (pCallback == NULL)
  517. {
  518. hr = E_INVALIDARG;
  519. }
  520. else if (fOffline)
  521. {
  522. hr = E_NOT_ONLINE;
  523. }
  524. else
  525. {
  526. hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
  527. if (SUCCEEDED(hr))
  528. hr = pServer->DeleteFolder(idFolder, dwFlags, pCallback);
  529. }
  530. }
  531. m_pLocalStore->FreeRecord(&info);
  532. }
  533. return(hr);
  534. }
  535. //--------------------------------------------------------------------------
  536. // CStoreSync::FindServerId
  537. //--------------------------------------------------------------------------
  538. STDMETHODIMP CStoreSync::FindServerId(LPCSTR pszAcctId, LPFOLDERID pidServer)
  539. {
  540. HRESULT hr;
  541. Assert(pszAcctId != NULL);
  542. Assert(pidServer != NULL);
  543. // local store operation only
  544. hr = m_pLocalStore->FindServerId(pszAcctId, pidServer);
  545. return(hr);
  546. }
  547. //--------------------------------------------------------------------------
  548. // GetFolderInfo
  549. //--------------------------------------------------------------------------
  550. HRESULT CStoreSync::GetFolderInfo(FOLDERID idFolder, LPFOLDERINFO pInfo)
  551. {
  552. HRESULT hr;
  553. Assert(pInfo != NULL);
  554. // local store operation only
  555. hr = m_pLocalStore->GetFolderInfo(idFolder, pInfo);
  556. return(hr);
  557. }
  558. //--------------------------------------------------------------------------
  559. // CStoreSync::EnumChildren
  560. //--------------------------------------------------------------------------
  561. STDMETHODIMP CStoreSync::EnumChildren(FOLDERID idParent, BOOL fSubscribed,
  562. IEnumerateFolders **ppEnum)
  563. {
  564. HRESULT hr;
  565. Assert(ppEnum != NULL);
  566. // local store operation only
  567. hr = m_pLocalStore->EnumChildren(idParent, fSubscribed, ppEnum);
  568. return(hr);
  569. }
  570. //--------------------------------------------------------------------------
  571. // CStoreSync::GetSpecialFolderInfo
  572. //--------------------------------------------------------------------------
  573. STDMETHODIMP CStoreSync::GetSpecialFolderInfo(FOLDERID idStore,
  574. SPECIALFOLDER tySpecial, LPFOLDERINFO pInfo)
  575. {
  576. HRESULT hr;
  577. Assert(NULL != pInfo);
  578. Assert(FOLDER_NOTSPECIAL != tySpecial);
  579. // local store operation only
  580. hr = m_pLocalStore->GetSpecialFolderInfo(idStore, tySpecial, pInfo);
  581. return(hr);
  582. }
  583. //--------------------------------------------------------------------------
  584. // CStoreSync::SubscribeToFolder
  585. //--------------------------------------------------------------------------
  586. STDMETHODIMP CStoreSync::SubscribeToFolder(FOLDERID idFolder,
  587. BOOL fSubscribed, IStoreCallback *pCallback)
  588. {
  589. FOLDERINFO info;
  590. FOLDERID idParent;
  591. HRESULT hr;
  592. BOOL fOffline;
  593. IMessageServer *pServer;
  594. Assert(NULL != m_pLocalStore);
  595. // if imap and online, subscribe to folder on server and then in local store
  596. // otherwise, subscribe to folder in local store
  597. hr = GetFolderServerId(idFolder, &idParent);
  598. if (hr != S_OK)
  599. return(E_FAIL);
  600. hr = _GetFolderInfo(idParent, &info, &fOffline);
  601. if (SUCCEEDED(hr))
  602. {
  603. Assert(info.tyFolder != FOLDER_LOCAL);
  604. if (info.tyFolder == FOLDER_NEWS)
  605. {
  606. hr = m_pLocalStore->SubscribeToFolder(idFolder, fSubscribed, NULL);
  607. }
  608. else
  609. {
  610. Assert(info.tyFolder == FOLDER_IMAP);
  611. Assert(pCallback != NULL);
  612. if (pCallback == NULL)
  613. {
  614. hr = E_INVALIDARG;
  615. }
  616. else if (fOffline)
  617. {
  618. hr = E_NOT_ONLINE;
  619. }
  620. else
  621. {
  622. hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
  623. if (SUCCEEDED(hr))
  624. hr = pServer->SubscribeToFolder(idFolder, fSubscribed, pCallback);
  625. }
  626. }
  627. m_pLocalStore->FreeRecord(&info);
  628. }
  629. return(hr);
  630. }
  631. STDMETHODIMP CStoreSync::GetNewGroups(FOLDERID idFolder, LPSYSTEMTIME pSysTime, IStoreCallback *pCallback)
  632. {
  633. FOLDERINFO info;
  634. HRESULT hr;
  635. BOOL fOffline;
  636. IMessageServer *pServer;
  637. Assert(m_pLocalStore != NULL);
  638. Assert(pCallback != NULL);
  639. if (pCallback == NULL)
  640. return(E_INVALIDARG);
  641. // if news server and online, get new groups on server
  642. hr = _GetFolderInfo(idFolder, &info, &fOffline);
  643. if (SUCCEEDED(hr))
  644. {
  645. if (info.tyFolder != FOLDER_NEWS ||
  646. 0 == (info.dwFlags & FOLDER_SERVER))
  647. {
  648. hr = E_INVALIDARG;
  649. }
  650. else
  651. {
  652. if (fOffline)
  653. {
  654. hr = E_NOT_ONLINE;
  655. }
  656. else
  657. {
  658. hr = _GetServer(idFolder, idFolder, info.tyFolder, &pServer);
  659. if (SUCCEEDED(hr))
  660. hr = pServer->GetNewGroups(pSysTime, pCallback);
  661. }
  662. }
  663. m_pLocalStore->FreeRecord(&info);
  664. }
  665. return(hr);
  666. }
  667. //--------------------------------------------------------------------------
  668. // CStoreSync::GetFolderCounts
  669. //--------------------------------------------------------------------------
  670. STDMETHODIMP CStoreSync::GetFolderCounts(FOLDERID idFolder, IStoreCallback *pCallback)
  671. {
  672. HRESULT hr;
  673. FOLDERINFO info;
  674. FOLDERID idParent;
  675. BOOL fOffline;
  676. IMessageServer *pServer;
  677. Assert(NULL != m_pLocalStore);
  678. // if imap or news, pass GetFolderCounts call through to server obj
  679. // otherwise, this function should not have been called so returns error
  680. hr = GetFolderServerId(idFolder, &idParent);
  681. if (hr != S_OK)
  682. return(E_FAIL);
  683. hr = _GetFolderInfo(idParent, &info, &fOffline);
  684. if (SUCCEEDED(hr))
  685. {
  686. if (info.tyFolder != FOLDER_LOCAL)
  687. {
  688. Assert(pCallback != NULL);
  689. if (pCallback == NULL)
  690. {
  691. hr = E_INVALIDARG;
  692. }
  693. else if (fOffline)
  694. {
  695. hr = E_NOT_ONLINE;
  696. }
  697. else
  698. {
  699. hr = _GetServer(idParent, idParent, info.tyFolder, &pServer);
  700. if (SUCCEEDED(hr))
  701. hr = pServer->GetFolderCounts(idFolder, pCallback);
  702. }
  703. }
  704. m_pLocalStore->FreeRecord(&info);
  705. }
  706. return(hr);
  707. }
  708. //--------------------------------------------------------------------------
  709. // CStoreSync::UpdateFolderCounts
  710. //--------------------------------------------------------------------------
  711. STDMETHODIMP CStoreSync::UpdateFolderCounts(FOLDERID idFolder, LONG lMessages,
  712. LONG lUnread, LONG lWatchedUnread, LONG lWatched)
  713. {
  714. HRESULT hr;
  715. Assert(NULL != m_pLocalStore);
  716. // local store operation only
  717. hr = m_pLocalStore->UpdateFolderCounts(idFolder, lMessages, lUnread, lWatchedUnread, lWatched);
  718. return(hr);
  719. }
  720. STDMETHODIMP CStoreSync::OnConnectionNotify(CONNNOTIFY nCode, LPVOID pvData, CConnectionManager *pConMan)
  721. {
  722. if (nCode == CONNNOTIFY_CONNECTED)
  723. {
  724. }
  725. else if (((nCode == CONNNOTIFY_WORKOFFLINE) && (pvData)) ||
  726. (nCode == CONNNOTIFY_DISCONNECTED))
  727. {
  728. DWORD i, j;
  729. for (j = 0; j < CMAXTHREADS; j++)
  730. {
  731. if (m_rgts[j].pEntry != NULL)
  732. {
  733. for (i = 0; i < m_rgts[j].cEntry; i++)
  734. {
  735. if (m_rgts[j].pEntry[i].pServer != NULL)
  736. {
  737. m_rgts[j].pEntry[i].pServer->Close(MSGSVRF_DROP_CONNECTION);
  738. }
  739. }
  740. }
  741. }
  742. }
  743. return(S_OK);
  744. }
  745. HRESULT CStoreSync::_GetFolderInfo(FOLDERID id, FOLDERINFO *pInfo, BOOL *pfOffline)
  746. {
  747. HRESULT hr;
  748. Assert(pInfo != NULL);
  749. Assert(pfOffline != NULL);
  750. hr = m_pLocalStore->GetFolderInfo(id, pInfo);
  751. if (SUCCEEDED(hr))
  752. {
  753. //*pfOffline = g_pConMan->IsGlobalOffline();
  754. *pfOffline = FALSE;
  755. }
  756. return(hr);
  757. }
  758. HRESULT CStoreSync::_GetServer(FOLDERID idServer, FOLDERID idFolder, FOLDERTYPE tyFolder, IMessageServer **ppServer)
  759. {
  760. HRESULT hr;
  761. IMessageServer *pServer;
  762. DWORD i;
  763. FOLDERINFO info;
  764. SERVERENTRY *pEntry;
  765. DWORD dwThreadId;
  766. THREADSERVERS *pts;
  767. Assert(FOLDER_LOCAL != tyFolder);
  768. Assert(FOLDER_ROOTNODE != tyFolder);
  769. Assert(ppServer != NULL);
  770. Assert(idServer == idFolder);
  771. // TODO: figure out a way not to hold onto these IMessageServer objects...
  772. *ppServer = NULL;
  773. dwThreadId = GetCurrentThreadId();
  774. Assert(dwThreadId != 0);
  775. for (i = 0, pts = m_rgts; i < CMAXTHREADS; i++, pts++)
  776. {
  777. if (dwThreadId == pts->dwThreadId)
  778. {
  779. break;
  780. }
  781. else if (pts->dwThreadId == 0)
  782. {
  783. pts->dwThreadId = dwThreadId;
  784. break;
  785. }
  786. }
  787. Assert(i != CMAXTHREADS);
  788. for (i = 0, pEntry = pts->pEntry; i < pts->cEntry; i++, pEntry++)
  789. {
  790. if (pEntry->idFolder == idFolder)
  791. {
  792. Assert(pEntry->idServer == idServer);
  793. *ppServer = pEntry->pServer;
  794. return(S_OK);
  795. }
  796. }
  797. if (pts->cEntry == pts->cEntryBuf)
  798. {
  799. i = pts->cEntryBuf + 16;
  800. if (!MemRealloc((void **)&pts->pEntry, i * sizeof(SERVERENTRY)))
  801. return(E_OUTOFMEMORY);
  802. pts->cEntryBuf = i;
  803. }
  804. hr = m_pLocalStore->GetFolderInfo(idServer, &info);
  805. if (SUCCEEDED(hr))
  806. {
  807. hr = CreateMessageServerType(tyFolder, &pServer);
  808. if (SUCCEEDED(hr))
  809. {
  810. hr = pServer->Initialize(m_pLocalStore, idServer, NULL, FOLDERID_INVALID);
  811. if (SUCCEEDED(hr))
  812. {
  813. pEntry = &pts->pEntry[pts->cEntry];
  814. pEntry->pServer = pServer;
  815. pEntry->idServer = idServer;
  816. pEntry->idFolder = idFolder;
  817. pts->cEntry++;
  818. *ppServer = pServer;
  819. }
  820. else
  821. {
  822. pServer->Release();
  823. }
  824. }
  825. m_pLocalStore->FreeRecord(&info);
  826. }
  827. return(hr);
  828. }