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.

1438 lines
42 KiB

  1. #include "pch.hxx"
  2. #include "store.h"
  3. #include "instance.h"
  4. #include "msgfldr.h"
  5. #include "secutil.h"
  6. #include "storutil.h"
  7. #include "fldrsync.h"
  8. #include <conman.h>
  9. #include "shlwapip.h"
  10. #include "sync.h"
  11. static char c_szFolderSyncWndClass[] = "Outlook Express FolderSync Window Class";
  12. static const PFNCOPYFUNC c_rgpfnCopyMsgs[] =
  13. {
  14. &CFolderSync::CopyOpen,
  15. &CFolderSync::CopySave,
  16. &CFolderSync::CopySave2,
  17. &CFolderSync::CopyDelete,
  18. &CFolderSync::CopyDelete2,
  19. };
  20. //--------------------------------------------------------------------------
  21. // CFolderSync::CFolderSync
  22. //--------------------------------------------------------------------------
  23. CFolderSync::CFolderSync(void)
  24. {
  25. g_pInstance->DllAddRef();
  26. m_cRef = 1;
  27. m_pLocalStore = NULL;
  28. m_pFldr = NULL;
  29. m_tyFolder = FOLDER_INVALID;
  30. m_idFolder = FOLDERID_INVALID;
  31. m_idServer = FOLDERID_INVALID;
  32. m_szAcctId[0] = 0;
  33. m_pServer = NULL;
  34. m_fConManAdvise = FALSE;
  35. m_hwnd = NULL;
  36. m_pCopy = NULL;
  37. m_fImap = FALSE;
  38. }
  39. //--------------------------------------------------------------------------
  40. // CFolderSync::~CFolderSync
  41. //--------------------------------------------------------------------------
  42. CFolderSync::~CFolderSync(void)
  43. {
  44. Assert(m_pCopy == NULL);
  45. if (m_fConManAdvise && g_pConMan != NULL)
  46. g_pConMan->Unadvise((IConnectionNotify *)this);
  47. if (m_hwnd != NULL)
  48. {
  49. if (GetWindowThreadProcessId(m_hwnd, NULL) == GetCurrentThreadId())
  50. {
  51. DestroyWindow(m_hwnd);
  52. }
  53. else
  54. {
  55. SetWindowLongPtr(m_hwnd, GWLP_USERDATA, NULL);
  56. PostMessage(m_hwnd, WM_CLOSE, 0, 0L);
  57. }
  58. }
  59. if (m_pServer)
  60. {
  61. m_pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
  62. m_pServer->Release();
  63. m_pServer = NULL;
  64. }
  65. SafeRelease(m_pLocalStore);
  66. SafeRelease(m_pFldr);
  67. // Release the Dll
  68. g_pInstance->DllRelease();
  69. }
  70. //--------------------------------------------------------------------------
  71. // CFolderSync::QueryInterface
  72. //--------------------------------------------------------------------------
  73. STDMETHODIMP CFolderSync::QueryInterface(REFIID riid, LPVOID *ppv)
  74. {
  75. if (IID_IUnknown == riid)
  76. *ppv = (IMessageFolder *)this;
  77. else if (IID_IMessageFolder == riid)
  78. *ppv = (IMessageFolder *)this;
  79. else if (IID_IDatabase == riid)
  80. *ppv = (IDatabase *)this;
  81. else if (IID_IServiceProvider == riid)
  82. *ppv = (IServiceProvider *)this;
  83. else
  84. {
  85. *ppv = NULL;
  86. return(E_NOINTERFACE);
  87. }
  88. // AddRef It
  89. ((IUnknown *)*ppv)->AddRef();
  90. return(S_OK);
  91. }
  92. //--------------------------------------------------------------------------
  93. // CFolderSync::AddRef
  94. //--------------------------------------------------------------------------
  95. STDMETHODIMP_(ULONG) CFolderSync::AddRef(void)
  96. {
  97. return InterlockedIncrement(&m_cRef);
  98. }
  99. //--------------------------------------------------------------------------
  100. // CFolderSync::Release
  101. //--------------------------------------------------------------------------
  102. STDMETHODIMP_(ULONG) CFolderSync::Release(void)
  103. {
  104. LONG cRef = InterlockedDecrement(&m_cRef);
  105. if (0 == cRef)
  106. delete this;
  107. return (ULONG)cRef;
  108. }
  109. //--------------------------------------------------------------------------
  110. // CFolderSync::Initialize
  111. //--------------------------------------------------------------------------
  112. STDMETHODIMP CFolderSync::Initialize(IMessageStore *pStore, IMessageServer *pServer,
  113. OPENFOLDERFLAGS dwFlags, FOLDERID idFolder)
  114. {
  115. Assert(FALSE);
  116. return(E_NOTIMPL);
  117. }
  118. //--------------------------------------------------------------------------
  119. // CFolderSync::SetOwner
  120. //--------------------------------------------------------------------------
  121. STDMETHODIMP CFolderSync::SetOwner(IStoreCallback *pDefaultCallback)
  122. {
  123. HRESULT hrResult;
  124. TraceCall("CFolderSync::SetOwner");
  125. if (NULL == m_pServer)
  126. {
  127. hrResult = E_FAIL;
  128. goto exit;
  129. }
  130. hrResult = m_pServer->SetIdleCallback(pDefaultCallback);
  131. if (FAILED(hrResult))
  132. {
  133. TraceResult(hrResult);
  134. goto exit;
  135. }
  136. exit:
  137. return hrResult;
  138. }
  139. //--------------------------------------------------------------------------
  140. // CFolderSync::Synchronize
  141. //--------------------------------------------------------------------------
  142. STDMETHODIMP CFolderSync::Synchronize(SYNCFOLDERFLAGS dwFlags, DWORD cHeaders, IStoreCallback *pCallback)
  143. {
  144. BOOL fOffline;
  145. HRESULT hr;
  146. // async
  147. // if online, then synchronize folder
  148. // if offline, no op (fail)
  149. if (m_pServer == NULL)
  150. {
  151. // local folders don't sync.
  152. // NOTE - This isn't failure - there's just nothing to do.
  153. return (S_FALSE);
  154. }
  155. Assert(pCallback != NULL);
  156. if (pCallback == NULL)
  157. return(E_INVALIDARG);
  158. if(g_pConMan->IsAccountDisabled((LPSTR)m_szAcctId))
  159. hr = S_FALSE;
  160. else
  161. hr = m_pServer->SynchronizeFolder(dwFlags, cHeaders, pCallback);
  162. return(hr);
  163. }
  164. //--------------------------------------------------------------------------
  165. // CFolderSync::GetFolderId
  166. //--------------------------------------------------------------------------
  167. STDMETHODIMP CFolderSync::GetFolderId(LPFOLDERID pidFolder)
  168. {
  169. Assert(NULL != pidFolder);
  170. // local store operation only
  171. *pidFolder = m_idFolder;
  172. return(S_OK);
  173. }
  174. //--------------------------------------------------------------------------
  175. // CFolderSync::GetMessageFolderId
  176. //--------------------------------------------------------------------------
  177. STDMETHODIMP CFolderSync::GetMessageFolderId(MESSAGEID idMessage, LPFOLDERID pidFolder)
  178. {
  179. return(m_pFldr->GetMessageFolderId(idMessage, pidFolder));
  180. }
  181. //--------------------------------------------------------------------------
  182. // CFolderSync::OpenMessage
  183. //--------------------------------------------------------------------------
  184. STDMETHODIMP CFolderSync::OpenMessage(MESSAGEID idMessage,
  185. OPENMESSAGEFLAGS dwFlags, IMimeMessage **ppMessage,
  186. IStoreCallback *pCallback)
  187. {
  188. HRESULT hr;
  189. BOOL fOffline;
  190. FILEADDRESS faStart;
  191. Assert(NULL != ppMessage);
  192. // async
  193. // if message is already downloaded
  194. // open message in local store
  195. // else
  196. // if online, download message
  197. // if offline, fail
  198. hr = m_pFldr->OpenMessage(idMessage, dwFlags, ppMessage, NULL);
  199. if (SUCCEEDED(hr))
  200. return(hr);
  201. if (hr == STORE_E_NOBODY && m_pServer != NULL && !ISFLAGSET(dwFlags, OPEN_MESSAGE_CACHEDONLY))
  202. {
  203. Assert(pCallback != NULL);
  204. if (pCallback == NULL)
  205. return(E_INVALIDARG);
  206. hr = m_pServer->GetMessage(idMessage, pCallback);
  207. }
  208. return(hr);
  209. }
  210. //--------------------------------------------------------------------------
  211. // CFolderSync::SaveMessage
  212. //--------------------------------------------------------------------------
  213. STDMETHODIMP CFolderSync::SaveMessage(LPMESSAGEID pidMessage,
  214. SAVEMESSAGEFLAGS dwOptions, MESSAGEFLAGS dwFlags,
  215. IStream *pStreamIn, IMimeMessage *pMessage, IStoreCallback *pCallback)
  216. {
  217. HRESULT hr;
  218. IStream *pStream;
  219. DWORD dwOffline;
  220. LPFILETIME pftRecv;
  221. PROPVARIANT rVariant;
  222. Assert(NULL != pMessage);
  223. // save message to local store
  224. // if online, upload message
  225. // if offline, log transaction
  226. if (m_pServer == NULL)
  227. {
  228. hr = m_pFldr->SaveMessage(pidMessage, dwOptions, dwFlags, pStreamIn, pMessage, NULL);
  229. return(hr);
  230. }
  231. hr = _Offline(&dwOffline);
  232. if (SUCCEEDED(hr))
  233. {
  234. if (dwOffline == CONN_STATE_NOT_CONNECTED)
  235. {
  236. hr = E_NOT_ONLINE;
  237. }
  238. else if (dwOffline == CONN_STATE_OFFLINE)
  239. {
  240. hr = g_pSync->CreateMessage(m_pFldr, pidMessage, dwOptions, dwFlags, pStreamIn, pMessage);
  241. }
  242. else
  243. {
  244. Assert(dwOffline == CONN_STATE_CONNECTED);
  245. Assert(pCallback != NULL);
  246. if (pCallback == NULL)
  247. return(E_INVALIDARG);
  248. // the idStream can legally by null in the case of saving a draft
  249. if (NULL == pStreamIn)
  250. hr = pMessage->GetMessageSource(&pStream, COMMIT_ONLYIFDIRTY);
  251. else
  252. {
  253. pStream = pStreamIn;
  254. pStream->AddRef();
  255. }
  256. if (SUCCEEDED(hr))
  257. {
  258. rVariant.vt = VT_FILETIME;
  259. if (SUCCEEDED(pMessage->GetProp(PIDTOSTR(PID_ATT_RECVTIME), 0, &rVariant)))
  260. pftRecv = &rVariant.filetime;
  261. else
  262. pftRecv = NULL;
  263. hr = m_pServer->PutMessage(m_idFolder, dwFlags, pftRecv, pStream, pCallback);
  264. pStream->Release();
  265. }
  266. }
  267. }
  268. return(hr);
  269. }
  270. //--------------------------------------------------------------------------
  271. // CFolderSync::SetMessageStream
  272. //--------------------------------------------------------------------------
  273. STDMETHODIMP CFolderSync::SetMessageStream(MESSAGEID idMessage,
  274. IStream *pStream)
  275. {
  276. // pass through to the local store
  277. Assert (NULL != m_pFldr);
  278. Assert(NULL != pStream);
  279. if (NULL == pStream)
  280. return E_INVALIDARG;
  281. return m_pFldr->SetMessageStream(idMessage, pStream);
  282. }
  283. //--------------------------------------------------------------------------
  284. // CFolderSync::SetMessageFlags
  285. //--------------------------------------------------------------------------
  286. STDMETHODIMP CFolderSync::SetMessageFlags(LPMESSAGEIDLIST pList,
  287. LPADJUSTFLAGS pFlags, LPRESULTLIST pResults,
  288. IStoreCallback *pCallback)
  289. {
  290. INewsStore *pNewsStore;
  291. ADJUSTFLAGS localFlags, svrFlags;
  292. MESSAGEFLAGS flags;
  293. DWORD dwOffline;
  294. HRESULT hr;
  295. Assert(NULL != pFlags);
  296. Assert(NULL == pList || 0 != pList->cMsgs);
  297. // async
  298. // save message flags to local store
  299. // if online, upload message flags if necessary (some flags are irrelevant to server)
  300. // if offline, log transaction if necessary
  301. if (m_pServer == NULL)
  302. return(m_pFldr->SetMessageFlags(pList, pFlags, pResults, NULL));
  303. hr = _Offline(&dwOffline);
  304. if (SUCCEEDED(hr))
  305. {
  306. hr = m_pServer->GetServerMessageFlags(&flags);
  307. if (SUCCEEDED(hr))
  308. {
  309. Assert(hr == S_OK || hr == S_FALSE);
  310. // hr == S_FALSE
  311. // this server doesn't have any flags that need to hit the server
  312. localFlags = *pFlags;
  313. if (hr == S_OK)
  314. {
  315. svrFlags = *pFlags;
  316. svrFlags.dwAdd &= flags;
  317. svrFlags.dwRemove &= flags;
  318. localFlags.dwAdd &= ~flags;
  319. localFlags.dwRemove &= ~flags;
  320. if (0 != svrFlags.dwAdd ||
  321. 0 != svrFlags.dwRemove)
  322. {
  323. if (dwOffline == CONN_STATE_NOT_CONNECTED)
  324. {
  325. return(E_NOT_ONLINE);
  326. }
  327. else if (dwOffline == CONN_STATE_OFFLINE)
  328. {
  329. hr = g_pSync->SetMessageFlags(m_pFldr, pList, &svrFlags);
  330. }
  331. else
  332. {
  333. Assert(dwOffline == CONN_STATE_CONNECTED);
  334. Assert(pCallback != NULL);
  335. if (pCallback == NULL)
  336. return(E_INVALIDARG);
  337. hr = m_pServer->SetMessageFlags(pList, &svrFlags, 0, pCallback);
  338. }
  339. }
  340. }
  341. if (0 != localFlags.dwAdd ||
  342. 0 != localFlags.dwRemove)
  343. {
  344. hr = m_pFldr->SetMessageFlags(pList, &localFlags, pResults, NULL);
  345. // mark news crossposts as read
  346. if (m_tyFolder == FOLDER_NEWS &&
  347. (!!(localFlags.dwAdd & ARF_READ) || !!(localFlags.dwRemove & ARF_READ)))
  348. {
  349. IServiceProvider *pService;
  350. if (SUCCEEDED(m_pServer->QueryInterface(IID_IServiceProvider, (void **)&pService)))
  351. {
  352. if (SUCCEEDED(pService->QueryService(SID_MessageServer, IID_INewsStore, (void **)&pNewsStore)))
  353. {
  354. pNewsStore->MarkCrossposts(pList, !!(localFlags.dwAdd & ARF_READ));
  355. pNewsStore->Release();
  356. }
  357. pService->Release();
  358. }
  359. }
  360. }
  361. }
  362. }
  363. return(hr);
  364. }
  365. //--------------------------------------------------------------------------
  366. // CFolderSync::DeleteMessages
  367. //--------------------------------------------------------------------------
  368. STDMETHODIMP CFolderSync::DeleteMessages(DELETEMESSAGEFLAGS dwOptions,
  369. LPMESSAGEIDLIST pList, LPRESULTLIST pResults,
  370. IStoreCallback *pCallback)
  371. {
  372. ADJUSTFLAGS afFlags;
  373. DWORD dwOffline;
  374. HRESULT hr;
  375. Assert(NULL == pList || pList->cMsgs > 0);
  376. // if online, delete messages from server and local store
  377. // if offline, log transaction
  378. if (m_pServer == NULL || m_tyFolder == FOLDER_NEWS)
  379. return(m_pFldr->DeleteMessages(dwOptions, pList, pResults, pCallback));
  380. hr = _Offline(&dwOffline);
  381. if (SUCCEEDED(hr))
  382. {
  383. if (dwOffline == CONN_STATE_NOT_CONNECTED)
  384. {
  385. hr = E_NOT_ONLINE;
  386. }
  387. else if (dwOffline == CONN_STATE_OFFLINE)
  388. {
  389. // [PaulHi] 4/8/99 Raid 63339
  390. // Deleting from an HTTP folder (other than the 'deleted' folder)
  391. // translates into a message move from the source folder to the
  392. // 'deleted' folder. If offline we want the message copy to take
  393. // place and then cache the message 'copy' just as would happen with
  394. // an offline drag/drop copy operation.
  395. FOLDERINFO fldrinfo;
  396. BOOL bHMOffLineCopy = FALSE;
  397. hr = m_pLocalStore->GetFolderInfo(m_idFolder, &fldrinfo);
  398. if (SUCCEEDED(hr))
  399. {
  400. if ( (fldrinfo.tyFolder == FOLDER_HTTPMAIL) && (fldrinfo.tySpecial != FOLDER_DELETED) &&
  401. (fldrinfo.tySpecial != FOLDER_MSNPROMO) )
  402. {
  403. // Code stolen from CFolderSync::CopyMessages
  404. IMessageFolder * pDeletedItems = NULL;
  405. IMessageFolder * pDestLocal = NULL;
  406. IServiceProvider * pService = NULL;
  407. hr = g_pStore->OpenSpecialFolder(m_idServer, NULL, FOLDER_DELETED, &pDeletedItems);
  408. if (SUCCEEDED(hr))
  409. {
  410. hr = pDeletedItems->QueryInterface(IID_IServiceProvider, (void **)&pService);
  411. if (SUCCEEDED(hr))
  412. {
  413. hr = pService->QueryService(SID_LocalMessageFolder, IID_IMessageFolder, (void **)&pDestLocal);
  414. pService->Release();
  415. }
  416. pDeletedItems->Release();
  417. }
  418. if (SUCCEEDED(hr))
  419. {
  420. Assert(pDestLocal != NULL);
  421. afFlags.dwAdd = 0;
  422. afFlags.dwRemove = 0;
  423. hr = g_pSync->CopyMessages(m_pFldr, pDestLocal, COPY_MESSAGE_MOVE, pList, &afFlags);
  424. bHMOffLineCopy = TRUE;
  425. pDestLocal->Release();
  426. }
  427. m_pLocalStore->FreeRecord(&fldrinfo);
  428. }
  429. }
  430. // If the HM offline copy didn't occur, for whatever reason, revert to the original
  431. // off line delete.
  432. if (!bHMOffLineCopy)
  433. hr = g_pSync->DeleteMessages(m_pFldr, dwOptions, pList);
  434. }
  435. else
  436. {
  437. Assert(dwOffline == CONN_STATE_CONNECTED);
  438. Assert(pCallback != NULL);
  439. if (pCallback == NULL)
  440. return(E_INVALIDARG);
  441. hr = m_pServer->DeleteMessages(dwOptions, pList, pCallback);
  442. }
  443. }
  444. return(hr);
  445. }
  446. HRESULT CFolderSync::Initialize(IMessageStore *pStore, IMessageFolder *pLocalFolder,
  447. IMessageServer *pServer, OPENFOLDERFLAGS dwFlags, FOLDERTYPE tyFolder,
  448. FOLDERID idFolder, FOLDERID idServer)
  449. {
  450. WNDCLASSEX wc;
  451. HRESULT hr;
  452. FOLDERINFO info;
  453. Assert(NULL != pStore);
  454. // Save the Folder Type
  455. m_tyFolder = tyFolder;
  456. // Save the FolderId
  457. m_idFolder = idFolder;
  458. m_idServer = idServer;
  459. // Save pStore
  460. m_pLocalStore = pStore;
  461. m_pLocalStore->AddRef();
  462. if (pServer != NULL)
  463. {
  464. hr = m_pLocalStore->GetFolderInfo(m_idServer, &info);
  465. if (FAILED(hr))
  466. return(hr);
  467. StrCpyN(m_szAcctId, info.pszAccountId, ARRAYSIZE(m_szAcctId));
  468. m_fImap = (info.tyFolder == FOLDER_IMAP);
  469. m_pLocalStore->FreeRecord(&info);
  470. m_pServer = pServer;
  471. m_pServer->AddRef();
  472. hr = g_pConMan->Advise((IConnectionNotify *)this);
  473. m_fConManAdvise = SUCCEEDED(hr);
  474. }
  475. if (pLocalFolder)
  476. {
  477. m_pFldr = pLocalFolder;
  478. m_pFldr->AddRef();
  479. }
  480. else
  481. {
  482. hr = m_pLocalStore->OpenFolder(m_idFolder, NULL, dwFlags, &m_pFldr);
  483. if (FAILED(hr))
  484. return(hr);
  485. }
  486. wc.cbSize = sizeof(WNDCLASSEX);
  487. if (!GetClassInfoEx(g_hInst, c_szFolderSyncWndClass, &wc))
  488. {
  489. wc.style = 0;
  490. wc.lpfnWndProc = FolderSyncWndProc;
  491. wc.cbClsExtra = 0;
  492. wc.cbWndExtra = 0;
  493. wc.hInstance = g_hInst;
  494. wc.hIcon = NULL;
  495. wc.hCursor = NULL;
  496. wc.hbrBackground = NULL;
  497. wc.lpszMenuName = NULL;
  498. wc.lpszClassName = c_szFolderSyncWndClass;
  499. wc.hIconSm = NULL;
  500. if (RegisterClassEx(&wc) == 0 && GetLastError() != ERROR_CLASS_ALREADY_EXISTS)
  501. return E_FAIL;
  502. }
  503. m_hwnd = CreateWindowEx(WS_EX_TOPMOST, c_szFolderSyncWndClass,
  504. c_szFolderSyncWndClass, WS_POPUP, 1, 1, 1, 1, NULL,
  505. NULL, g_hInst, (LPVOID)this);
  506. if (m_hwnd == NULL)
  507. return(E_FAIL);
  508. return(S_OK);
  509. }
  510. HRESULT CFolderSync::Close()
  511. {
  512. HRESULT hr = S_OK;
  513. if (m_pServer)
  514. hr = m_pServer->Close(MSGSVRF_HANDS_OFF_SERVER);
  515. return hr;
  516. }
  517. HRESULT CFolderSync::_Offline(DWORD *pdwOffline)
  518. {
  519. BOOL fOffline;
  520. HRESULT hr;
  521. Assert(pdwOffline != NULL);
  522. Assert(m_szAcctId[0] != 0);
  523. fOffline = g_pConMan->IsGlobalOffline();
  524. if (fOffline)
  525. {
  526. *pdwOffline = CONN_STATE_OFFLINE;
  527. }
  528. else
  529. {
  530. //Bug# 39337. We just give the operation to the sync object even if we are not connected.
  531. //The sync object in turn figures out whether it needs to dial or not
  532. /*
  533. hr = g_pConMan->CanConnect(m_szAcctId);
  534. *pdwOffline = (hr == S_OK) ? CONN_STATE_CONNECTED : CONN_STATE_NOT_CONNECTED;
  535. */
  536. *pdwOffline = CONN_STATE_CONNECTED;
  537. }
  538. return(S_OK);
  539. }
  540. HRESULT CFolderSync::_OfflineServer(FOLDERID idServer, DWORD *pdwOffline)
  541. {
  542. HRESULT hr;
  543. FOLDERINFO info;
  544. BOOL fOffline;
  545. Assert(pdwOffline != NULL);
  546. hr = m_pLocalStore->GetFolderInfo(idServer, &info);
  547. if (FAILED(hr))
  548. return(hr);
  549. if (info.tyFolder == FOLDER_LOCAL)
  550. {
  551. *pdwOffline = CONN_STATE_CONNECTED;
  552. }
  553. else
  554. {
  555. fOffline = g_pConMan->IsGlobalOffline();
  556. if (fOffline)
  557. {
  558. *pdwOffline = CONN_STATE_OFFLINE;
  559. }
  560. else
  561. {
  562. /*
  563. hr = g_pConMan->CanConnect(info.pszAccountId);
  564. *pdwOffline = (hr == S_OK) ? CONN_STATE_CONNECTED : CONN_STATE_NOT_CONNECTED;
  565. */
  566. *pdwOffline = CONN_STATE_CONNECTED;
  567. }
  568. }
  569. m_pLocalStore->FreeRecord(&info);
  570. return(S_OK);
  571. }
  572. HRESULT CFolderSync::QueryService(REFGUID guidService, REFIID riid, LPVOID *ppvObject)
  573. {
  574. IServiceProvider *pSP;
  575. HRESULT hr = E_NOINTERFACE;
  576. if (guidService == SID_LocalMessageFolder)
  577. {
  578. if (m_pFldr != NULL)
  579. hr = m_pFldr->QueryInterface(riid, ppvObject);
  580. }
  581. else if (m_pServer && m_pServer->QueryInterface(IID_IServiceProvider, (LPVOID *)&pSP)==S_OK)
  582. {
  583. hr = pSP->QueryService(guidService, riid, ppvObject);
  584. pSP->Release();
  585. }
  586. return hr;
  587. }
  588. HRESULT CFolderSync::OnBegin(STOREOPERATIONTYPE tyOperation, STOREOPERATIONINFO *pOpInfo, IOperationCancel *pCancel)
  589. {
  590. Assert(m_pCopy->type == SOT_INVALID);
  591. Assert(m_pCopy->fAsync);
  592. m_pCopy->type = tyOperation;
  593. if (!m_pCopy->fBegin)
  594. {
  595. Assert(m_pCopy->pCallback != NULL);
  596. m_pCopy->pCallback->OnBegin(SOT_COPYMOVE_MESSAGE, pOpInfo, (IOperationCancel *)this);
  597. m_pCopy->fBegin = TRUE;
  598. }
  599. return(S_OK);
  600. }
  601. HRESULT CFolderSync::OnProgress(STOREOPERATIONTYPE tyOperation, DWORD dwCurrent, DWORD dwMax, LPCSTR pszStatus)
  602. {
  603. return(S_OK);
  604. }
  605. HRESULT CFolderSync::OnTimeout(LPINETSERVER pServer, LPDWORD pdwTimeout, IXPTYPE ixpServerType)
  606. {
  607. Assert(m_pCopy != NULL);
  608. return(m_pCopy->pCallback->OnTimeout(pServer, pdwTimeout, ixpServerType));
  609. }
  610. HRESULT CFolderSync::CanConnect(LPCSTR pszAccountId, DWORD dwFlags)
  611. {
  612. Assert(m_pCopy != NULL);
  613. return(m_pCopy->pCallback->CanConnect(pszAccountId, dwFlags));
  614. }
  615. HRESULT CFolderSync::OnLogonPrompt(LPINETSERVER pServer, IXPTYPE ixpServerType)
  616. {
  617. Assert(m_pCopy != NULL);
  618. return(m_pCopy->pCallback->OnLogonPrompt(pServer, ixpServerType));
  619. }
  620. HRESULT CFolderSync::OnComplete(STOREOPERATIONTYPE tyOperation, HRESULT hrComplete, LPSTOREOPERATIONINFO pOpInfo, LPSTOREERROR pErrorInfo)
  621. {
  622. Assert(m_pCopy != NULL);
  623. if (m_pCopy->type != tyOperation ||
  624. m_pCopy->hr != S_FALSE)
  625. return(S_OK);
  626. Assert(hrComplete != S_FALSE);
  627. m_pCopy->hr = hrComplete;
  628. if (NULL != pErrorInfo)
  629. {
  630. BOOL fResult;
  631. fResult = MemAlloc((void **)&m_pCopy->pErrorInfo, sizeof(STOREERROR));
  632. if (FALSE == fResult)
  633. {
  634. TraceResult(E_OUTOFMEMORY);
  635. }
  636. else
  637. {
  638. // Make a copy of the STOREERROR so we can display rich errors to user
  639. m_pCopy->pErrorInfo->hrResult = pErrorInfo->hrResult;
  640. m_pCopy->pErrorInfo->uiServerError = pErrorInfo->uiServerError;
  641. m_pCopy->pErrorInfo->hrServerError = pErrorInfo->hrServerError;
  642. m_pCopy->pErrorInfo->dwSocketError = pErrorInfo->dwSocketError;
  643. m_pCopy->pErrorInfo->pszProblem = PszDupA(pErrorInfo->pszProblem);
  644. m_pCopy->pErrorInfo->pszDetails = PszDupA(pErrorInfo->pszDetails);
  645. m_pCopy->pErrorInfo->pszAccount = PszDupA(pErrorInfo->pszAccount);
  646. m_pCopy->pErrorInfo->pszServer = PszDupA(pErrorInfo->pszServer);
  647. m_pCopy->pErrorInfo->pszFolder = PszDupA(pErrorInfo->pszFolder);
  648. m_pCopy->pErrorInfo->pszUserName = PszDupA(pErrorInfo->pszUserName);
  649. m_pCopy->pErrorInfo->pszProtocol = PszDupA(pErrorInfo->pszProtocol);
  650. m_pCopy->pErrorInfo->ixpType = pErrorInfo->ixpType;
  651. m_pCopy->pErrorInfo->dwPort = pErrorInfo->dwPort;
  652. m_pCopy->pErrorInfo->fSSL = pErrorInfo->fSSL;
  653. m_pCopy->pErrorInfo->dwFlags = pErrorInfo->dwFlags;
  654. }
  655. }
  656. PostMessage(m_hwnd, WM_USER, 0, 0);
  657. m_pCopy->type = SOT_INVALID;
  658. return S_OK;
  659. }
  660. HRESULT CFolderSync::OnPrompt(HRESULT hrError, LPCTSTR pszText, LPCTSTR pszCaption, UINT uType, INT *piUserResponse)
  661. {
  662. Assert(m_pCopy != NULL);
  663. return(m_pCopy->pCallback->OnPrompt(hrError, pszText, pszCaption, uType, piUserResponse));
  664. }
  665. HRESULT CFolderSync::GetParentWindow(DWORD dwReserved, HWND *phwndParent)
  666. {
  667. Assert(m_pCopy != NULL);
  668. return(m_pCopy->pCallback->GetParentWindow(dwReserved, phwndParent));
  669. }
  670. HRESULT CFolderSync::Cancel(CANCELTYPE tyCancel)
  671. {
  672. Assert(m_pCopy != NULL);
  673. Assert(tyCancel != CT_INVALID);
  674. m_pCopy->tyCancel = tyCancel;
  675. return(S_OK);
  676. }
  677. HRESULT CFolderSync::OnConnectionNotify(CONNNOTIFY nCode, LPVOID pvData, CConnectionManager *pConMan)
  678. {
  679. FOLDERINFO info;
  680. HRESULT hr;
  681. Assert(m_pServer != NULL);
  682. if (nCode == CONNNOTIFY_CONNECTED)
  683. {
  684. }
  685. else if (nCode == CONNNOTIFY_WORKOFFLINE && pvData)
  686. {
  687. m_pServer->Close(MSGSVRF_DROP_CONNECTION);
  688. }
  689. else if (nCode == CONNNOTIFY_DISCONNECTED)
  690. {
  691. hr = g_pStore->GetFolderInfo(m_idServer, &info);
  692. if (SUCCEEDED(hr))
  693. {
  694. CHAR szAccountId[CCHMAX_ACCOUNT_NAME];
  695. if (SUCCEEDED(GetFolderAccountId(&info, szAccountId, ARRAYSIZE(szAccountId))))
  696. {
  697. if (!g_pConMan->CanConnect(szAccountId))
  698. m_pServer->Close(MSGSVRF_DROP_CONNECTION);
  699. }
  700. g_pStore->FreeRecord(&info);
  701. }
  702. }
  703. return(S_OK);
  704. }
  705. void CFolderSync::_FreeCopyInfo()
  706. {
  707. Assert(m_pCopy != NULL);
  708. if (m_pCopy->pDest != NULL)
  709. m_pCopy->pDest->Release();
  710. if (m_pCopy->pDestLocal != NULL)
  711. m_pCopy->pDestLocal->Release();
  712. if (m_pCopy->pList != NULL)
  713. MemFree(m_pCopy->pList);
  714. if (m_pCopy->pErrorInfo != NULL)
  715. {
  716. SafeMemFree(m_pCopy->pErrorInfo->pszProblem);
  717. SafeMemFree(m_pCopy->pErrorInfo->pszDetails);
  718. SafeMemFree(m_pCopy->pErrorInfo->pszAccount);
  719. SafeMemFree(m_pCopy->pErrorInfo->pszServer);
  720. SafeMemFree(m_pCopy->pErrorInfo->pszFolder);
  721. SafeMemFree(m_pCopy->pErrorInfo->pszUserName);
  722. SafeMemFree(m_pCopy->pErrorInfo->pszProtocol);
  723. MemFree(m_pCopy->pErrorInfo);
  724. }
  725. MemFree(m_pCopy);
  726. m_pCopy = NULL;
  727. }
  728. HRESULT AllBodiesDownloaded(IMessageFolder *pFldr, LPMESSAGEIDLIST pList)
  729. {
  730. MESSAGEINFO Message;
  731. DWORD iMsg;
  732. HRESULT hr;
  733. Assert(pFldr != NULL);
  734. Assert(pList != NULL);
  735. hr = S_OK;
  736. for (iMsg = 0; iMsg < pList->cMsgs; iMsg++)
  737. {
  738. ZeroMemory(&Message, sizeof(MESSAGEINFO));
  739. Message.idMessage = pList->prgidMsg[iMsg];
  740. if (DB_S_FOUND == pFldr->FindRecord(IINDEX_PRIMARY, COLUMNS_ALL, &Message, NULL))
  741. {
  742. if (0 == (Message.dwFlags & ARF_HASBODY))
  743. hr = S_FALSE;
  744. pFldr->FreeRecord(&Message);
  745. }
  746. if (hr != S_OK)
  747. break;
  748. }
  749. return(hr);
  750. }
  751. //--------------------------------------------------------------------------
  752. // CFolderSync::CopyMessages
  753. //--------------------------------------------------------------------------
  754. STDMETHODIMP CFolderSync::CopyMessages(IMessageFolder *pDest,
  755. COPYMESSAGEFLAGS dwOptions,
  756. LPMESSAGEIDLIST pList,
  757. LPADJUSTFLAGS pFlags,
  758. LPRESULTLIST pResults,
  759. IStoreCallback *pCallback)
  760. {
  761. HWND hwnd;
  762. DWORD dwOfflineSrc, dwOfflineDst;
  763. HRESULT hr;
  764. IMessageFolder *pDestLocal;
  765. ADJUSTFLAGS aflags;
  766. FOLDERID idDst, idServerDst;
  767. IServiceProvider *pService;
  768. FOLDERINFO fiSource = {0};
  769. Assert(pDest != NULL);
  770. Assert(pList != NULL);
  771. hr = pDest->GetFolderId(&idDst);
  772. if (FAILED(hr))
  773. return(hr);
  774. hr = GetFolderServerId(idDst, &idServerDst);
  775. if (FAILED(hr))
  776. return(hr);
  777. if (m_pServer == NULL)
  778. {
  779. dwOfflineSrc = CONN_STATE_CONNECTED;
  780. }
  781. else
  782. {
  783. hr = _Offline(&dwOfflineSrc);
  784. if (FAILED(hr))
  785. return(hr);
  786. }
  787. if (m_tyFolder == FOLDER_IMAP)
  788. {
  789. if (pFlags != NULL)
  790. {
  791. aflags = *pFlags;
  792. }
  793. else
  794. {
  795. aflags.dwAdd = 0;
  796. aflags.dwRemove = 0;
  797. }
  798. aflags.dwRemove |= ARF_ENDANGERED;
  799. pFlags = &aflags;
  800. }
  801. if (m_idServer == idServerDst)
  802. {
  803. if (m_pServer == NULL)
  804. {
  805. hr = m_pFldr->CopyMessages(pDest, dwOptions, pList, pFlags, pResults, pCallback);
  806. }
  807. else if (dwOfflineSrc == CONN_STATE_NOT_CONNECTED)
  808. {
  809. hr = E_NOT_ONLINE;
  810. }
  811. else if (dwOfflineSrc == CONN_STATE_CONNECTED)
  812. {
  813. Assert(pCallback != NULL);
  814. if (pCallback == NULL)
  815. return(E_INVALIDARG);
  816. hr = m_pServer->CopyMessages(pDest, dwOptions, pList, pFlags, pCallback);
  817. }
  818. else
  819. {
  820. Assert(dwOfflineSrc == CONN_STATE_OFFLINE);
  821. pDestLocal = NULL;
  822. hr = pDest->QueryInterface(IID_IServiceProvider, (void **)&pService);
  823. if (SUCCEEDED(hr))
  824. {
  825. hr = pService->QueryService(SID_LocalMessageFolder, IID_IMessageFolder, (void **)&pDestLocal);
  826. pService->Release();
  827. }
  828. if (FAILED(hr))
  829. return(hr);
  830. Assert(pDestLocal != NULL);
  831. hr = g_pSync->CopyMessages(m_pFldr, pDestLocal, dwOptions, pList, pFlags);
  832. pDestLocal->Release();
  833. }
  834. return(hr);
  835. }
  836. hr = _OfflineServer(idServerDst, &dwOfflineDst);
  837. if (FAILED(hr))
  838. return(hr);
  839. if (dwOfflineDst == CONN_STATE_NOT_CONNECTED)
  840. return(E_NOT_ONLINE);
  841. Assert(m_pCopy == NULL);
  842. if (m_pCopy != NULL)
  843. return(E_FAIL);
  844. if (dwOfflineSrc != CONN_STATE_CONNECTED)
  845. {
  846. hr = AllBodiesDownloaded(m_pFldr, pList);
  847. if (FAILED(hr))
  848. {
  849. return(hr);
  850. }
  851. else if (hr == S_FALSE)
  852. {
  853. pCallback->GetParentWindow(0, &hwnd);
  854. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena),
  855. !!(COPY_MESSAGE_MOVE & dwOptions) ? MAKEINTRESOURCEW(idsCantMoveNotDownloaded) : MAKEINTRESOURCEW(idsCantCopyNotDownloaded),
  856. 0, MB_OK | MB_ICONEXCLAMATION);
  857. return(E_NOT_ONLINE);
  858. }
  859. }
  860. // Bug# 94639
  861. // If the src and dest servers are not the same, and if the source is Hotmail Deleted Items folder
  862. // disallow move.
  863. // For Hotmail accounts Deleted Items folder is managed by the Hotmail servers.
  864. // So the users cannot manually delete or move messages.
  865. // Hence, disallow moving from Deleted Items.
  866. // Instead ask if the user wants to copy the message
  867. if ((m_idServer != idServerDst) && (FOLDER_HTTPMAIL == m_tyFolder))
  868. {
  869. IF_FAILEXIT(hr = m_pLocalStore->GetFolderInfo(m_idFolder, &fiSource));
  870. if (FOLDER_DELETED == fiSource.tySpecial)
  871. {
  872. if (IDNO == AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsAthena),
  873. MAKEINTRESOURCEW(idsHttpNoMoveCopy), 0, MB_YESNO))
  874. {
  875. // Just return S_OK;
  876. hr = S_OK;
  877. goto exit;
  878. }
  879. else
  880. {
  881. // Change the move flags to copy.
  882. dwOptions = (dwOptions & ~COPY_MESSAGE_MOVE);
  883. }
  884. }
  885. }
  886. if (!MemAlloc((void **)&m_pCopy, sizeof(COPYINFO)))
  887. return(E_OUTOFMEMORY);
  888. ZeroMemory(m_pCopy, sizeof(COPYINFO));
  889. m_pCopy->fSrcOffline = (dwOfflineSrc != CONN_STATE_CONNECTED);
  890. m_pCopy->fDestOffline = (dwOfflineDst != CONN_STATE_CONNECTED);
  891. m_pCopy->hr = S_OK;
  892. m_pCopy->pDest = pDest;
  893. pDest->AddRef();
  894. m_pCopy->fMove = !!(COPY_MESSAGE_MOVE & dwOptions);
  895. hr = CloneMessageIDList(pList, &m_pCopy->pList);
  896. if (FAILED(hr))
  897. {
  898. _FreeCopyInfo();
  899. return(hr);
  900. }
  901. if (m_pCopy->fDestOffline)
  902. {
  903. hr = m_pCopy->pDest->QueryInterface(IID_IServiceProvider, (void **)&pService);
  904. if (SUCCEEDED(hr))
  905. {
  906. hr = pService->QueryService(SID_LocalMessageFolder, IID_IMessageFolder, (void **)&m_pCopy->pDestLocal);
  907. pService->Release();
  908. }
  909. if (FAILED(hr))
  910. {
  911. _FreeCopyInfo();
  912. return(E_INVALIDARG);
  913. }
  914. }
  915. if (pFlags != NULL)
  916. m_pCopy->AdjustFlags = *pFlags;
  917. m_pCopy->pCallback = pCallback;
  918. hr = _CopyMessageState();
  919. exit:
  920. m_pLocalStore->FreeRecord(&fiSource);
  921. return(hr);
  922. }
  923. HRESULT CFolderSync::CopyOpen()
  924. {
  925. HRESULT hr;
  926. MESSAGEINFO mi = {0};
  927. LPMESSAGEINFO pmi = NULL;
  928. if (m_pCopy->iMsg >= m_pCopy->pList->cMsgs)
  929. {
  930. m_pCopy->state = COPY_STATE_DONE;
  931. return(S_OK);
  932. }
  933. Assert(m_pCopy->pStream == NULL);
  934. // initialize message info with the message id
  935. mi.idMessage = m_pCopy->pList->prgidMsg[m_pCopy->iMsg];
  936. // find the row
  937. hr = GetMessageInfo(m_pFldr, m_pCopy->pList->prgidMsg[m_pCopy->iMsg], &mi);
  938. if (FAILED(hr))
  939. goto exit;
  940. pmi = &mi;
  941. if (0 == mi.faStream || !!(mi.dwFlags & ARF_ARTICLE_EXPIRED))
  942. {
  943. // if the server is NULL and we don't have a body stream,
  944. // then something is wrong with the message. we skip the
  945. // bad message and move onto the next one.
  946. if (NULL == m_pServer || m_pCopy->fSrcOffline)
  947. {
  948. m_pCopy->state = COPY_STATE_DELETE2;
  949. hr = S_OK;
  950. }
  951. else if (!m_pCopy->fSrcRequested)
  952. {
  953. Assert(m_pServer != NULL);
  954. hr = m_pServer->GetMessage(m_pCopy->pList->prgidMsg[m_pCopy->iMsg], (IStoreCallback *)this);
  955. if (hr == E_PENDING)
  956. m_pCopy->fSrcRequested = TRUE;
  957. Assert(FAILED(hr));
  958. }
  959. }
  960. else
  961. {
  962. hr = m_pFldr->OpenStream(ACCESS_READ, mi.faStream, &m_pCopy->pStream);
  963. if (FAILED(hr))
  964. goto exit;
  965. m_pCopy->state = COPY_STATE_SAVE;
  966. }
  967. exit:
  968. if (NULL != pmi)
  969. m_pFldr->FreeRecord(pmi);
  970. return(hr);
  971. }
  972. HRESULT CFolderSync::CopySave()
  973. {
  974. DWORD dwFlags;
  975. HRESULT hr;
  976. MESSAGEINFO Message;
  977. MESSAGEID id;
  978. IMimeMessage *pMessage = NULL;
  979. Assert(m_pCopy->pStream != NULL);
  980. dwFlags = 0;
  981. ZeroMemory(&Message, sizeof(MESSAGEINFO));
  982. Message.idMessage = m_pCopy->pList->prgidMsg[m_pCopy->iMsg];
  983. if (DB_S_FOUND == m_pFldr->FindRecord(IINDEX_PRIMARY, COLUMNS_ALL, &Message, NULL))
  984. {
  985. dwFlags = Message.dwFlags;
  986. m_pFldr->FreeRecord(&Message);
  987. }
  988. if (m_pCopy->AdjustFlags.dwRemove != 0)
  989. dwFlags &= ~m_pCopy->AdjustFlags.dwRemove;
  990. if (m_pCopy->AdjustFlags.dwAdd != 0)
  991. dwFlags |= m_pCopy->AdjustFlags.dwAdd;
  992. // create a mime message
  993. hr = m_pFldr->OpenMessage(m_pCopy->pList->prgidMsg[m_pCopy->iMsg], OPEN_MESSAGE_SECURE, &pMessage, NOSTORECALLBACK);
  994. if (FAILED(hr))
  995. goto exit;
  996. if (m_pCopy->fDestOffline)
  997. {
  998. Assert(m_pCopy->pDestLocal != NULL);
  999. hr = g_pSync->CreateMessage(m_pCopy->pDestLocal, &id, SAVE_MESSAGE_GENID, dwFlags, m_pCopy->pStream, pMessage);
  1000. }
  1001. else
  1002. {
  1003. hr = m_pCopy->pDest->SaveMessage(&id, SAVE_MESSAGE_GENID, dwFlags, m_pCopy->pStream, pMessage, (IStoreCallback *)this);
  1004. }
  1005. if (hr == E_PENDING || SUCCEEDED(hr))
  1006. m_pCopy->state = COPY_STATE_SAVE2;
  1007. exit:
  1008. if (NULL != pMessage)
  1009. pMessage->Release();
  1010. m_pCopy->pStream->Release();
  1011. m_pCopy->pStream = NULL;
  1012. return(hr);
  1013. }
  1014. HRESULT CFolderSync::CopySave2()
  1015. {
  1016. if (m_pCopy->fMove)
  1017. {
  1018. m_pCopy->state = COPY_STATE_DELETE;
  1019. }
  1020. else
  1021. {
  1022. m_pCopy->state = COPY_STATE_OPEN;
  1023. m_pCopy->iMsg++;
  1024. m_pCopy->fSrcRequested = FALSE;
  1025. m_pCopy->pCallback->OnProgress(SOT_COPYMOVE_MESSAGE, m_pCopy->iMsg, m_pCopy->pList->cMsgs, NULL);
  1026. }
  1027. return(S_OK);
  1028. }
  1029. HRESULT CFolderSync::CopyDelete()
  1030. {
  1031. MESSAGEIDLIST list;
  1032. HRESULT hr;
  1033. MESSAGEID id;
  1034. ADJUSTFLAGS afFlags;
  1035. list.cMsgs = 1;
  1036. id = m_pCopy->pList->prgidMsg[m_pCopy->iMsg];
  1037. list.prgidMsg = &id;
  1038. if (m_pServer != NULL)
  1039. {
  1040. if (m_pCopy->fSrcOffline)
  1041. {
  1042. if (m_fImap)
  1043. {
  1044. afFlags.dwAdd = ARF_ENDANGERED;
  1045. afFlags.dwRemove = 0;
  1046. hr = g_pSync->SetMessageFlags(m_pFldr, &list, &afFlags);
  1047. }
  1048. else
  1049. {
  1050. #ifdef DEAD
  1051. hr = g_pSync->DeleteMessages(m_pFldr, DELETE_MESSAGE_NOTRASHCAN, &list);
  1052. #endif // DEAD
  1053. hr = S_OK;
  1054. }
  1055. }
  1056. else
  1057. {
  1058. hr = m_pServer->DeleteMessages(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT | DELETE_MESSAGE_MAYIGNORENOTRASH, &list, (IStoreCallback *)this);
  1059. }
  1060. }
  1061. else
  1062. {
  1063. hr = m_pFldr->DeleteMessages(DELETE_MESSAGE_NOTRASHCAN | DELETE_MESSAGE_NOPROMPT, &list, NULL, NOSTORECALLBACK);
  1064. }
  1065. if (hr == E_PENDING || SUCCEEDED(hr))
  1066. m_pCopy->state = COPY_STATE_DELETE2;
  1067. return(hr);
  1068. }
  1069. HRESULT CFolderSync::CopyDelete2()
  1070. {
  1071. m_pCopy->state = COPY_STATE_OPEN;
  1072. m_pCopy->iMsg++;
  1073. m_pCopy->fSrcRequested = FALSE;
  1074. m_pCopy->pCallback->OnProgress(SOT_COPYMOVE_MESSAGE, m_pCopy->iMsg, m_pCopy->pList->cMsgs, NULL);
  1075. return(S_OK);
  1076. }
  1077. HRESULT CFolderSync::_CopyMessageState()
  1078. {
  1079. BOOL fBegin;
  1080. HRESULT hr;
  1081. HWND hwnd;
  1082. IStoreCallback *pCallback;
  1083. Assert(m_pCopy != NULL);
  1084. Assert(m_pCopy->hr != S_FALSE);
  1085. Assert(m_pCopy->hr != E_PENDING);
  1086. if (FAILED(m_pCopy->hr) && m_pCopy->state == COPY_STATE_OPEN && m_pCopy->fSrcRequested)
  1087. {
  1088. m_pCopy->fDownloadFail = TRUE;
  1089. m_pCopy->hr = S_OK;
  1090. m_pCopy->iMsg++;
  1091. m_pCopy->fSrcRequested = FALSE;
  1092. }
  1093. if (FAILED(m_pCopy->hr))
  1094. {
  1095. hr = m_pCopy->hr;
  1096. }
  1097. else
  1098. {
  1099. while (TRUE)
  1100. {
  1101. if (m_pCopy->tyCancel != CT_INVALID)
  1102. {
  1103. m_pCopy->state = COPY_STATE_DONE;
  1104. hr = S_FALSE;
  1105. break;
  1106. }
  1107. hr = (this->*(c_rgpfnCopyMsgs[m_pCopy->state]))();
  1108. if (FAILED(hr) || m_pCopy->state == COPY_STATE_DONE)
  1109. break;
  1110. }
  1111. }
  1112. if (hr == E_PENDING)
  1113. {
  1114. Assert(m_pCopy->type == SOT_INVALID);
  1115. m_pCopy->fAsync = TRUE;
  1116. m_pCopy->hr = S_FALSE;
  1117. }
  1118. else if (FAILED(hr) || m_pCopy->state == COPY_STATE_DONE)
  1119. {
  1120. fBegin = m_pCopy->fBegin;
  1121. #ifdef DEBUG
  1122. if (fBegin)
  1123. Assert(m_pCopy->fAsync);
  1124. #endif // DEBUG
  1125. pCallback = m_pCopy->pCallback;
  1126. if (fBegin)
  1127. {
  1128. if (m_pCopy->fDownloadFail && SUCCEEDED(hr))
  1129. {
  1130. if (SUCCEEDED(pCallback->GetParentWindow(0, &hwnd)))
  1131. {
  1132. AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthena),
  1133. m_pCopy->fMove ? MAKEINTRESOURCEW(idsMoveDownloadFail) : MAKEINTRESOURCEW(idsCopyDownloadFail),
  1134. NULL, MB_ICONEXCLAMATION | MB_OK);
  1135. }
  1136. }
  1137. pCallback->OnComplete(SOT_COPYMOVE_MESSAGE, hr, NULL, m_pCopy->pErrorInfo);
  1138. }
  1139. _FreeCopyInfo();
  1140. }
  1141. return(hr);
  1142. }
  1143. LRESULT CALLBACK CFolderSync::FolderSyncWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1144. {
  1145. HRESULT hr;
  1146. CFolderSync *pThis;
  1147. pThis = (CFolderSync *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1148. if (NULL == pThis && msg != WM_CREATE)
  1149. return DefWindowProc(hwnd, msg, wParam, lParam);
  1150. switch(msg)
  1151. {
  1152. case WM_CREATE:
  1153. Assert(pThis == NULL);
  1154. pThis = (CFolderSync *)((CREATESTRUCT *)lParam)->lpCreateParams;
  1155. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)pThis);
  1156. break;
  1157. case WM_USER:
  1158. pThis->_CopyMessageState();
  1159. break;
  1160. }
  1161. return(DefWindowProc(hwnd, msg, wParam, lParam));
  1162. }
  1163. //--------------------------------------------------------------------------
  1164. // CFolderSync::ConnectionAddRef
  1165. //
  1166. // Purpose: users of IMessageFolder need to keep alive the underlying server
  1167. // object if they plan of re-using the same server connection as
  1168. // another user of the same IMessageTable. eg. a note and a view window
  1169. // This allows us to not have to re-auth for operations that could
  1170. // be potentially expensive
  1171. //--------------------------------------------------------------------------
  1172. HRESULT CFolderSync::ConnectionAddRef()
  1173. {
  1174. if (m_pServer)
  1175. m_pServer->ConnectionAddRef();
  1176. return S_OK;
  1177. }
  1178. //--------------------------------------------------------------------------
  1179. // CFolderSync::ConnectionRelease
  1180. //
  1181. // Purpose: figure it out
  1182. //--------------------------------------------------------------------------
  1183. HRESULT CFolderSync::ConnectionRelease()
  1184. {
  1185. if (m_pServer)
  1186. m_pServer->ConnectionRelease();
  1187. return S_OK;
  1188. }
  1189. HRESULT CFolderSync::GetAdBarUrl(IStoreCallback *pCallback)
  1190. {
  1191. HRESULT hr = E_FAIL;
  1192. Assert(pCallback != NULL);
  1193. if (pCallback == NULL)
  1194. return(E_INVALIDARG);
  1195. if (m_pServer)
  1196. hr = m_pServer->GetAdBarUrl(pCallback);
  1197. return(hr);
  1198. }