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.

998 lines
26 KiB

  1. #include "pch.hxx"
  2. #include "strconst.h"
  3. #include "mimeole.h"
  4. #include "mimeutil.h"
  5. #include <error.h>
  6. #include <imnapi.h>
  7. #include "goptions.h"
  8. #include <resource.h>
  9. #include <mso.h>
  10. #include <envelope.h>
  11. #include "ipab.h"
  12. #define NO_IMPORT_ERROR
  13. #include <newimp.h>
  14. #include <impapi.h>
  15. #include "storutil.h"
  16. #include "demand.h"
  17. #include "msgfldr.h"
  18. #include "store.h"
  19. class CMailImporter : public IMailImporter
  20. {
  21. private:
  22. ULONG m_cRef;
  23. public:
  24. CMailImporter(void);
  25. ~CMailImporter(void);
  26. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
  27. ULONG STDMETHODCALLTYPE AddRef(void);
  28. ULONG STDMETHODCALLTYPE Release(void);
  29. HRESULT Initialize(HWND hwnd);
  30. STDMETHODIMP OpenFolder(DWORD_PTR dwCookie, const TCHAR *szFolder, IMPORTFOLDERTYPE type, DWORD dwFlags, IFolderImport **ppFldrImp, DWORD_PTR *pdwCookie);
  31. };
  32. class CFolderImport : public IFolderImport
  33. {
  34. private:
  35. ULONG m_cRef;
  36. IMessageFolder *m_pFolder;
  37. STDMETHODIMP ImportMessage(MSGTYPE type, DWORD dwState, LPSTREAM pstm);
  38. public:
  39. CFolderImport(void);
  40. ~CFolderImport(void);
  41. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppvObject);
  42. ULONG STDMETHODCALLTYPE AddRef(void);
  43. ULONG STDMETHODCALLTYPE Release(void);
  44. HRESULT Initialize(IMessageFolder *pFolder);
  45. STDMETHODIMP SetMessageCount(ULONG cMsg);
  46. STDMETHODIMP ImportMessage(MSGTYPE type, DWORD dwState, LPSTREAM pstm, const TCHAR **rgszAttach, DWORD cAttach);
  47. STDMETHODIMP ImportMessage(IMSG *pimsg);
  48. };
  49. HRESULT GetImsgFromFolder(IMessageFolder *pfldr, LPMESSAGEINFO pMsgInfo, IMSG *pimsg);
  50. CFolderImport::CFolderImport()
  51. {
  52. m_cRef = 1;
  53. m_pFolder = NULL;
  54. }
  55. CFolderImport::~CFolderImport()
  56. {
  57. SafeRelease(m_pFolder);
  58. }
  59. ULONG CFolderImport::AddRef()
  60. {
  61. m_cRef++;
  62. return(m_cRef);
  63. }
  64. ULONG CFolderImport::Release()
  65. {
  66. ULONG cRef;
  67. cRef = --m_cRef;
  68. if (cRef == 0)
  69. delete this;
  70. return(cRef);
  71. }
  72. HRESULT CFolderImport::QueryInterface(REFIID riid, LPVOID *ppv)
  73. {
  74. HRESULT hr = S_OK;
  75. if (ppv == NULL)
  76. return(E_INVALIDARG);
  77. *ppv = NULL;
  78. if (IID_IFolderImport == riid)
  79. *ppv = (IFolderImport *)this;
  80. else if (IID_IUnknown == riid)
  81. *ppv = (IFolderImport *)this;
  82. else
  83. hr = E_NOINTERFACE;
  84. if (*ppv != NULL)
  85. ((LPUNKNOWN)*ppv)->AddRef();
  86. return(hr);
  87. }
  88. HRESULT CFolderImport::Initialize(IMessageFolder *pFolder)
  89. {
  90. Assert(pFolder != NULL);
  91. m_pFolder = pFolder;
  92. m_pFolder->AddRef();
  93. return(S_OK);
  94. }
  95. HRESULT CFolderImport::SetMessageCount(ULONG cMsg)
  96. {
  97. return(S_OK);
  98. }
  99. HRESULT CFolderImport::ImportMessage(MSGTYPE type, DWORD dwState, LPSTREAM pstm, const TCHAR **rgszAttach, DWORD cAttach)
  100. {
  101. IMimeMessage *pMsg;
  102. HRESULT hr;
  103. DWORD iAttach, dwPri;
  104. PROPVARIANT rVariant;
  105. DWORD dwMsgFlags;
  106. Assert(pstm != NULL);
  107. Assert(m_pFolder != NULL);
  108. if (rgszAttach == NULL)
  109. {
  110. Assert(cAttach == 0);
  111. return(ImportMessage(type, dwState, pstm));
  112. }
  113. Assert(cAttach > 0);
  114. hr = HrRewindStream(pstm);
  115. if (FAILED(hr))
  116. return(hr);
  117. hr = HrCreateMessage(&pMsg);
  118. if (SUCCEEDED(hr))
  119. {
  120. hr = pMsg->Load(pstm);
  121. if (SUCCEEDED(hr))
  122. {
  123. for (iAttach = 0; iAttach < cAttach; iAttach++)
  124. {
  125. Assert(rgszAttach[iAttach] != NULL);
  126. pMsg->AttachFile(rgszAttach[iAttach], NULL, NULL);
  127. }
  128. dwPri = dwState & MSG_PRI_MASK;
  129. if (dwPri != 0)
  130. {
  131. if (dwPri == MSG_PRI_HIGH)
  132. rVariant.ulVal = IMSG_PRI_HIGH;
  133. else if (dwPri == MSG_PRI_LOW)
  134. rVariant.ulVal = IMSG_PRI_LOW;
  135. else
  136. rVariant.ulVal = IMSG_PRI_NORMAL;
  137. rVariant.vt = VT_UI4;
  138. pMsg->SetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant);
  139. }
  140. // Compute the Default arf flags
  141. dwMsgFlags = 0;
  142. // Is the Message Read ?
  143. if (FALSE == ISFLAGSET(dwState, MSG_STATE_UNREAD))
  144. FLAGSET(dwMsgFlags, ARF_READ);
  145. // Unsent
  146. if (ISFLAGSET(dwState, MSG_STATE_UNSENT))
  147. FLAGSET(dwMsgFlags, ARF_UNSENT);
  148. // Submitted
  149. // if (ISFLAGSET(dwState, MSG_STATE_SUBMITTED))
  150. // FLAGSET(dwMsgFlags, ARF_SUBMITTED);
  151. if (type == MSG_TYPE_NEWS)
  152. FLAGSET(dwMsgFlags, ARF_NEWSMSG);
  153. // Insert the message
  154. hr = m_pFolder->SaveMessage(NULL, SAVE_MESSAGE_GENID, dwMsgFlags, 0, pMsg, NOSTORECALLBACK);
  155. Assert(hr != E_PENDING);
  156. }
  157. pMsg->Release();
  158. }
  159. return(hr);
  160. }
  161. HRESULT CFolderImport::ImportMessage(MSGTYPE type, DWORD dwState, LPSTREAM pstm)
  162. {
  163. WORD pri;
  164. IMimeMessage *pMsg;
  165. HRESULT hr;
  166. DWORD dwPri;
  167. PROPVARIANT rVariant;
  168. DWORD dwMsgFlags;
  169. Assert(pstm != NULL);
  170. Assert(m_pFolder != NULL);
  171. hr = HrRewindStream(pstm);
  172. if (FAILED(hr))
  173. return(hr);
  174. hr = HrCreateMessage(&pMsg);
  175. if (SUCCEEDED(hr))
  176. {
  177. if (SUCCEEDED(hr = pMsg->Load(pstm)))
  178. {
  179. dwPri = dwState & MSG_PRI_MASK;
  180. if (dwPri != 0)
  181. {
  182. if (dwPri == MSG_PRI_HIGH)
  183. rVariant.ulVal = IMSG_PRI_HIGH;
  184. else if (dwPri == MSG_PRI_LOW)
  185. rVariant.ulVal = IMSG_PRI_LOW;
  186. else
  187. rVariant.ulVal = IMSG_PRI_NORMAL;
  188. rVariant.vt = VT_UI4;
  189. pMsg->SetProp(PIDTOSTR(PID_ATT_PRIORITY), 0, &rVariant);
  190. }
  191. // Compute the Default arf flags
  192. dwMsgFlags = 0;
  193. // Is the Message Read ?
  194. if (FALSE == ISFLAGSET(dwState, MSG_STATE_UNREAD))
  195. FLAGSET(dwMsgFlags, ARF_READ);
  196. // Unsent
  197. if (ISFLAGSET(dwState, MSG_STATE_UNSENT))
  198. FLAGSET(dwMsgFlags, ARF_UNSENT);
  199. // Submitted
  200. // if (ISFLAGSET(dwState, MSG_STATE_SUBMITTED))
  201. // FLAGSET(dwMsgFlags, ARF_SUBMITTED);
  202. if (type == MSG_TYPE_NEWS)
  203. FLAGSET(dwMsgFlags, ARF_NEWSMSG);
  204. // Insert the message
  205. hr = m_pFolder->SaveMessage(NULL, SAVE_MESSAGE_GENID, dwMsgFlags, 0, pMsg, NOSTORECALLBACK);
  206. Assert(hr != E_PENDING);
  207. }
  208. pMsg->Release();
  209. }
  210. return(hr);
  211. }
  212. HRESULT CFolderImport::ImportMessage(IMSG *pimsg)
  213. {
  214. HRESULT hr;
  215. MESSAGEID id;
  216. MESSAGEINFO info;
  217. LPMIMEMESSAGE pMsg;
  218. Assert(pimsg != NULL);
  219. hr = HrImsgToMailMsg(pimsg, &pMsg, NULL);
  220. if (!FAILED(hr))
  221. {
  222. hr = m_pFolder->SaveMessage(&id, SAVE_MESSAGE_GENID, ISFLAGSET(pimsg->uFlags, MSGFLAG_READ) ? ARF_READ : 0, 0, pMsg, NOSTORECALLBACK);
  223. Assert(hr != E_PENDING);
  224. if (SUCCEEDED(hr))
  225. {
  226. // handle receive time
  227. ZeroMemory(&info, sizeof(MESSAGEINFO));
  228. info.idMessage = id;
  229. if (DB_S_FOUND == m_pFolder->FindRecord(IINDEX_PRIMARY, COLUMNS_ALL, &info, NULL))
  230. {
  231. Assert(pimsg->ftReceive.dwLowDateTime != 0 || pimsg->ftReceive.dwHighDateTime != 0);
  232. CopyMemory(&info.ftReceived, &pimsg->ftReceive, sizeof(FILETIME));
  233. m_pFolder->UpdateRecord(&info);
  234. m_pFolder->FreeRecord(&info);
  235. }
  236. }
  237. pMsg->Release();
  238. }
  239. return(hr);
  240. }
  241. CMailImporter::CMailImporter()
  242. {
  243. m_cRef = 1;
  244. }
  245. CMailImporter::~CMailImporter()
  246. {
  247. }
  248. HRESULT CMailImporter::QueryInterface(REFIID riid, LPVOID *ppv)
  249. {
  250. HRESULT hr = S_OK;
  251. if (ppv == NULL)
  252. return(E_INVALIDARG);
  253. *ppv = NULL;
  254. if (IID_IMailImporter == riid)
  255. *ppv = (IMailImporter *)this;
  256. else if (IID_IUnknown == riid)
  257. *ppv = (IMailImporter *)this;
  258. else
  259. hr = E_NOINTERFACE;
  260. if (*ppv != NULL)
  261. ((LPUNKNOWN)*ppv)->AddRef();
  262. return(hr);
  263. }
  264. ULONG CMailImporter::AddRef()
  265. {
  266. m_cRef++;
  267. return(m_cRef);
  268. }
  269. ULONG CMailImporter::Release()
  270. {
  271. ULONG cRef;
  272. cRef = --m_cRef;
  273. if (cRef == 0)
  274. delete this;
  275. return(cRef);
  276. }
  277. HRESULT CMailImporter::Initialize(HWND hwnd)
  278. {
  279. return S_OK;
  280. }
  281. HRESULT CMailImporter::OpenFolder(DWORD_PTR dwCookie, const TCHAR *szFolder, IMPORTFOLDERTYPE type, DWORD dwFlags, IFolderImport **ppFldrImp, DWORD_PTR *pdwCookie)
  282. {
  283. HRESULT hr;
  284. FOLDERID idFolder, idFolderNew;
  285. CFolderImport *pFldrImp;
  286. IMessageFolder *pFolder;
  287. TCHAR sz[CCHMAX_FOLDER_NAME + 1];
  288. Assert(szFolder != NULL);
  289. Assert(ppFldrImp != NULL);
  290. Assert(dwFlags == 0);
  291. *ppFldrImp = NULL;
  292. if (dwCookie == COOKIE_ROOT)
  293. idFolder = FOLDERID_LOCAL_STORE;
  294. else
  295. idFolder = (FOLDERID)dwCookie;
  296. idFolderNew = FOLDERID_INVALID;
  297. if (type != FOLDER_TYPE_NORMAL)
  298. {
  299. LoadString(g_hLocRes, idsInbox + (type - FOLDER_TYPE_INBOX), sz, ARRAYSIZE(sz));
  300. szFolder = sz;
  301. }
  302. if (FAILED(GetFolderIdFromName(g_pStore, szFolder, idFolder, &idFolderNew)))
  303. {
  304. FOLDERINFO Folder={0};
  305. Folder.idParent = idFolder;
  306. Folder.tySpecial = FOLDER_NOTSPECIAL;
  307. Folder.pszName = (LPSTR)szFolder;
  308. Folder.dwFlags = FOLDER_SUBSCRIBED;
  309. hr = g_pStore->CreateFolder(NOFLAGS, &Folder, NOSTORECALLBACK);
  310. Assert(hr != E_PENDING);
  311. if (FAILED(hr))
  312. return(hr);
  313. idFolderNew = Folder.idFolder;
  314. }
  315. hr = g_pStore->OpenFolder(idFolderNew, NULL, NOFLAGS, &pFolder);
  316. if (FAILED(hr))
  317. return(hr);
  318. pFldrImp = new CFolderImport;
  319. if (pFldrImp == NULL)
  320. {
  321. hr = E_OUTOFMEMORY;
  322. }
  323. else
  324. {
  325. hr = pFldrImp->Initialize(pFolder);
  326. if (FAILED(hr))
  327. {
  328. pFldrImp->Release();
  329. pFldrImp = NULL;
  330. }
  331. }
  332. pFolder->Release();
  333. *ppFldrImp = pFldrImp;
  334. *pdwCookie = (DWORD_PTR)idFolderNew;
  335. return(S_OK);
  336. }
  337. void DoImport(HWND hwnd)
  338. {
  339. HRESULT hr;
  340. HMODULE hlibImport;
  341. PFNPERFORMIMPORT lpfnPerformImport;
  342. CMailImporter *pImp;
  343. hr = hrImportLoad;
  344. hlibImport = LoadLibrary(c_szImnimpDll);
  345. if (hlibImport != NULL)
  346. {
  347. lpfnPerformImport = (PFNPERFORMIMPORT)GetProcAddress(hlibImport, achPerformImport);
  348. if (lpfnPerformImport != NULL)
  349. {
  350. pImp = new CMailImporter;
  351. if (pImp == NULL)
  352. {
  353. hr = E_OUTOFMEMORY;
  354. }
  355. else
  356. {
  357. hr = pImp->Initialize(hwnd);
  358. if (SUCCEEDED(hr))
  359. lpfnPerformImport(hwnd, pImp, 0);
  360. pImp->Release();
  361. }
  362. }
  363. FreeLibrary(hlibImport);
  364. }
  365. if (FAILED(hr))
  366. {
  367. AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrImport), hr);
  368. }
  369. }
  370. // EXPORT STUFF
  371. IMPFOLDERNODE *InsertFolderNode(IMPFOLDERNODE *plist, IMPFOLDERNODE *pnode)
  372. {
  373. BOOL fNodeNormal, fCurrNormal;
  374. IMPFOLDERNODE *pprev, *pcurr;
  375. Assert(pnode != NULL);
  376. pnode->pnext = NULL;
  377. if (plist == NULL)
  378. return(pnode);
  379. pprev = NULL;
  380. pcurr = plist;
  381. while (pcurr != NULL)
  382. {
  383. fNodeNormal = pnode->type == FOLDER_TYPE_NORMAL;
  384. fCurrNormal = pcurr->type == FOLDER_TYPE_NORMAL;
  385. if (!fNodeNormal &&
  386. fCurrNormal)
  387. break;
  388. if (fNodeNormal == fCurrNormal &&
  389. lstrcmpi(pnode->szName, pcurr->szName) <= 0)
  390. break;
  391. pprev = pcurr;
  392. pcurr = pcurr->pnext;
  393. }
  394. if (pcurr == NULL)
  395. {
  396. // insert at end of list
  397. Assert(pprev != NULL);
  398. pprev->pnext = pnode;
  399. }
  400. else if (pprev == NULL)
  401. {
  402. // insert at beginning of list
  403. pnode->pnext = plist;
  404. plist = pnode;
  405. }
  406. else
  407. {
  408. pprev->pnext = pnode;
  409. pnode->pnext = pcurr;
  410. }
  411. return(plist);
  412. }
  413. HRESULT ExpGetSubFolders(IMPFOLDERNODE *pparent, FOLDERID idParent, IMPFOLDERNODE **pplist)
  414. {
  415. HRESULT hr;
  416. TCHAR *sz;
  417. IMPFOLDERNODE *pnode, *plist;
  418. HANDLE_16 hnd;
  419. FOLDERINFO Folder={0};
  420. IEnumerateFolders *pEnum;
  421. Assert(pplist != NULL);
  422. Assert(idParent != FOLDERID_INVALID);
  423. *pplist = NULL;
  424. plist = NULL;
  425. hr = g_pStore->EnumChildren(idParent, FALSE, &pEnum);
  426. if (SUCCEEDED(hr))
  427. {
  428. while (S_OK == pEnum->Next(1, &Folder, NULL))
  429. {
  430. if (!MemAlloc((void **)&pnode, sizeof(IMPFOLDERNODE) + CCHMAX_FOLDER_NAME * sizeof(TCHAR)))
  431. {
  432. hr = E_OUTOFMEMORY;
  433. break;
  434. }
  435. ZeroMemory(pnode, sizeof(IMPFOLDERNODE));
  436. sz = (TCHAR *)((BYTE *)pnode + sizeof(IMPFOLDERNODE));
  437. pnode->pparent = pparent;
  438. pnode->depth = (pparent != NULL) ? (pparent->depth + 1) : 0;
  439. pnode->szName = sz;
  440. StrCpyN(sz, Folder.pszName, CCHMAX_FOLDER_NAME);
  441. pnode->lparam = (LPARAM)Folder.idFolder;
  442. pnode->cMsg = Folder.cMessages;
  443. if (Folder.tySpecial == FOLDER_INBOX)
  444. pnode->type = FOLDER_TYPE_INBOX;
  445. else if (Folder.tySpecial == FOLDER_OUTBOX)
  446. pnode->type = FOLDER_TYPE_OUTBOX;
  447. else if (Folder.tySpecial == FOLDER_SENT)
  448. pnode->type = FOLDER_TYPE_SENT;
  449. else if (Folder.tySpecial == FOLDER_DELETED)
  450. pnode->type = FOLDER_TYPE_DELETED;
  451. else if (Folder.tySpecial == FOLDER_DRAFT)
  452. pnode->type = FOLDER_TYPE_DRAFT;
  453. plist = InsertFolderNode(plist, pnode);
  454. hr = ExpGetSubFolders(pnode, Folder.idFolder, &pnode->pchild);
  455. if (FAILED(hr))
  456. break;
  457. g_pStore->FreeRecord(&Folder);
  458. }
  459. pEnum->Release();
  460. }
  461. *pplist = plist;
  462. g_pStore->FreeRecord(&Folder);
  463. return(hr);
  464. }
  465. HRESULT WINAPI_16 ExpGetFolderList(IMPFOLDERNODE **pplist)
  466. {
  467. IMPFOLDERNODE *plist;
  468. HRESULT hr;
  469. if (pplist == NULL)
  470. return(E_INVALIDARG);
  471. plist = NULL;
  472. hr = ExpGetSubFolders(NULL, FOLDERID_LOCAL_STORE, &plist);
  473. if (FAILED(hr))
  474. {
  475. ExpFreeFolderList(plist);
  476. plist = NULL;
  477. }
  478. *pplist = plist;
  479. return(hr);
  480. }
  481. void WINAPI_16 ExpFreeFolderList(IMPFOLDERNODE *plist)
  482. {
  483. IMPFOLDERNODE *pnode;
  484. while (plist != NULL)
  485. {
  486. if (plist->pchild != NULL)
  487. ExpFreeFolderList(plist->pchild);
  488. pnode = plist;
  489. plist = plist->pnext;
  490. MemFree(pnode);
  491. }
  492. }
  493. void DoExport(HWND hwnd)
  494. {
  495. HRESULT hr;
  496. HMODULE hlibImport;
  497. PFNEXPMSGS lpfnExportMessages;
  498. hr = hrImportLoad;
  499. hlibImport = LoadLibrary(c_szImnimpDll);
  500. if (hlibImport != NULL)
  501. {
  502. lpfnExportMessages = (PFNEXPMSGS)GetProcAddress(hlibImport, MAKEINTRESOURCE(MAKELONG(3, 0)));
  503. if (lpfnExportMessages != NULL)
  504. {
  505. lpfnExportMessages(hwnd);
  506. hr = S_OK;
  507. }
  508. FreeLibrary(hlibImport);
  509. }
  510. if (FAILED(hr))
  511. {
  512. AthErrorMessageW(hwnd, MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErrExport), hr);
  513. }
  514. }
  515. typedef struct tagEXPENUM
  516. {
  517. IMessageFolder *pFolder;
  518. HROWSET hRowset;
  519. } EXPENUM;
  520. HRESULT WINAPI_16 ExpGetFirstImsg(HANDLE idFolder, IMSG *pimsg, HANDLE_16 *phnd)
  521. {
  522. EXPENUM *penum;
  523. HRESULT hr;
  524. MESSAGEINFO MsgInfo;
  525. Assert(pimsg != NULL);
  526. Assert(phnd != NULL);
  527. *phnd = NULL;
  528. hr = E_FAIL;
  529. penum = NULL;
  530. if (!MemAlloc((void **)&penum, sizeof(EXPENUM)))
  531. {
  532. hr = E_OUTOFMEMORY;
  533. }
  534. else
  535. {
  536. ZeroMemory(penum, sizeof(EXPENUM));
  537. hr = g_pStore->OpenFolder((FOLDERID)idFolder, NULL, NOFLAGS, &penum->pFolder);
  538. if (!FAILED(hr))
  539. {
  540. hr = penum->pFolder->CreateRowset(IINDEX_PRIMARY, NOFLAGS, &penum->hRowset);
  541. if (!FAILED(hr))
  542. {
  543. hr = penum->pFolder->QueryRowset(penum->hRowset, 1, (LPVOID *)&MsgInfo, NULL);
  544. if (!FAILED(hr))
  545. {
  546. if (S_OK == hr)
  547. {
  548. hr = GetImsgFromFolder(penum->pFolder, &MsgInfo, pimsg);
  549. penum->pFolder->FreeRecord(&MsgInfo);
  550. }
  551. else
  552. Assert(S_FALSE == hr);
  553. }
  554. }
  555. }
  556. }
  557. if (hr != S_OK)
  558. {
  559. ExpGetImsgClose((HANDLE_16)penum);
  560. penum = NULL;
  561. }
  562. *phnd = (HANDLE_16)penum;
  563. return(hr);
  564. }
  565. HRESULT WINAPI_16 ExpGetNextImsg(IMSG *pimsg, HANDLE_16 hnd)
  566. {
  567. HRESULT hr;
  568. EXPENUM *pee;
  569. MESSAGEINFO MsgInfo;
  570. Assert(pimsg != NULL);
  571. Assert(hnd != NULL);
  572. pee = (EXPENUM *)hnd;
  573. hr = pee->pFolder->QueryRowset(pee->hRowset, 1, (LPVOID *)&MsgInfo, NULL);
  574. if (hr == S_OK)
  575. {
  576. hr = GetImsgFromFolder(pee->pFolder, &MsgInfo, pimsg);
  577. pee->pFolder->FreeRecord(&MsgInfo);
  578. }
  579. return(hr);
  580. }
  581. void WINAPI_16 ExpGetImsgClose(HANDLE_16 hnd)
  582. {
  583. EXPENUM *pee;
  584. pee = (EXPENUM *)hnd;
  585. if (pee != NULL)
  586. {
  587. if (pee->pFolder != NULL)
  588. {
  589. pee->pFolder->CloseRowset(&pee->hRowset);
  590. pee->pFolder->Release();
  591. }
  592. MemFree(pee);
  593. }
  594. }
  595. HRESULT GetImsgFromFolder(IMessageFolder *pfldr, LPMESSAGEINFO pMsgInfo, IMSG *pimsg)
  596. {
  597. LPMIMEMESSAGE pMsg;
  598. HRESULT hr = E_OUTOFMEMORY;
  599. // for import/export we want the secure message, so pass TRUE
  600. hr = pfldr->OpenMessage(pMsgInfo->idMessage, OPEN_MESSAGE_SECURE, &pMsg, NOSTORECALLBACK);
  601. if (SUCCEEDED(hr))
  602. {
  603. hr = HrMailMsgToImsg(pMsg, pMsgInfo, pimsg);
  604. pMsg->Release();
  605. }
  606. return(hr);
  607. }
  608. void DoMigration(HWND hwnd)
  609. {
  610. HMODULE hlibImport;
  611. PFNPERFORMMIGRATION lpfnPerformMigration;
  612. CMailImporter *pImp;
  613. if (!!DwGetOption(OPT_MIGRATION_PERFORMED))
  614. return;
  615. hlibImport = LoadLibrary(c_szImnimpDll);
  616. if (hlibImport != NULL)
  617. {
  618. lpfnPerformMigration = (PFNPERFORMMIGRATION)GetProcAddress(hlibImport, achPerformMigration);
  619. if (lpfnPerformMigration != NULL)
  620. {
  621. pImp = new CMailImporter;
  622. if (pImp != NULL)
  623. {
  624. if (SUCCEEDED(pImp->Initialize(hwnd)) &&
  625. SUCCEEDED(lpfnPerformMigration(hwnd, pImp, 0)))
  626. {
  627. SetDwOption(OPT_MIGRATION_PERFORMED, TRUE, NULL, 0);
  628. }
  629. pImp->Release();
  630. }
  631. }
  632. FreeLibrary(hlibImport);
  633. }
  634. }
  635. HRESULT SimpleImportMailFolders(
  636. IMailImporter *pMailImporter,
  637. IMailImport *pMailImport,
  638. DWORD_PTR dwSourceCookie,
  639. DWORD_PTR dwParentDestCookie)
  640. {
  641. HRESULT hr = S_OK;
  642. DWORD_PTR cookie;
  643. IMPORTFOLDER folder;
  644. IFolderImport *pFolderImport = NULL;
  645. IEnumFOLDERS *pFolderEnum = NULL;
  646. // Enumerate source folders
  647. IF_FAILEXIT(hr = pMailImport->EnumerateFolders(dwSourceCookie, &pFolderEnum));
  648. do {
  649. // Get next source folder
  650. hr = pFolderEnum->Next(&folder);
  651. if (hr == S_OK) {
  652. // Open the destination folder by this name in this hierarchy position
  653. hr = pMailImporter->OpenFolder(dwParentDestCookie,
  654. folder.szName,
  655. FOLDER_TYPE_NORMAL,
  656. 0,
  657. &pFolderImport,
  658. &cookie);
  659. if (!FAILED(hr)) {
  660. // Import the enumerated source folder into the opened destination folder
  661. pMailImport->ImportFolder(folder.dwCookie, pFolderImport);
  662. // Close the destination folder
  663. SafeRelease(pFolderImport);
  664. if (folder.fSubFolders > 0) {
  665. // Recursively import subfolders
  666. SimpleImportMailFolders(pMailImporter, pMailImport, folder.dwCookie, cookie);
  667. }
  668. }
  669. }
  670. } while (hr == S_OK);
  671. exit:
  672. SafeRelease(pFolderImport);
  673. SafeRelease(pFolderEnum);
  674. return hr;
  675. }
  676. HRESULT SimpleImportNewsList(CMessageStore *pSrcStore)
  677. {
  678. HRESULT hr = S_OK;
  679. IEnumerateFolders *pEnum = NULL;
  680. FOLDERINFO info;
  681. IF_FAILEXIT(hr = pSrcStore->EnumChildren(FOLDERID_ROOT, TRUE, &pEnum));
  682. while (S_OK == pEnum->Next(1, &info, NULL)) {
  683. // info.pszName is the server/account name
  684. // info.pszAccountId is the source's account ID
  685. // info.idFolder is this account's folder ID
  686. // info.dwFlags contains FOLDER_HASCHILDREN
  687. // info.tyFolder specifies FOLDER_NEWS
  688. if ((info.tyFolder == FOLDER_NEWS) &&
  689. (info.dwFlags & FOLDER_HASCHILDREN)) {
  690. IImnAccount *pAccount = NULL;
  691. // Match this account to the destination
  692. hr = g_pAcctMan->FindAccount(AP_ACCOUNT_NAME, info.pszName, &pAccount);
  693. if ((hr == S_OK) && (pAccount != NULL)) {
  694. TCHAR szID[CCHMAX_ACCOUNT_NAME];
  695. hr = pAccount->GetPropSz(AP_ACCOUNT_ID, szID, ARRAYSIZE(szID));
  696. if (hr == S_OK) {
  697. IEnumerateFolders *pEnumDest = NULL;
  698. IEnumerateFolders *pEnumChild = NULL;
  699. FOLDERID destFolderID = 0;
  700. // Lookup destination folder id for this account name
  701. hr = g_pStore->EnumChildren(FOLDERID_ROOT, TRUE, &pEnumDest);
  702. if ((hr == S_OK) && (pEnumDest != NULL)) {
  703. FOLDERINFO infoDest;
  704. while (S_OK == pEnumDest->Next(1, &infoDest, NULL)) {
  705. if ((destFolderID == 0) &&
  706. (_tcscmp(info.pszName, infoDest.pszName) == 0)) {
  707. destFolderID = infoDest.idFolder;
  708. }
  709. g_pStore->FreeRecord(&infoDest);
  710. }
  711. }
  712. SafeRelease(pEnumDest);
  713. // Read in source newsgroups
  714. hr = pSrcStore->EnumChildren(info.idFolder, TRUE, &pEnumChild);
  715. if ((hr == S_OK) && (pEnumChild != NULL)) {
  716. FOLDERINFO infoChild;
  717. // Add folders to destination account
  718. while(S_OK == pEnumChild->Next(1, &infoChild, NULL)) {
  719. LPSTR oldID;
  720. // infoChild.idParent needs to be the dest server folder ID
  721. oldID = infoChild.pszAccountId;
  722. infoChild.pszAccountId = szID;
  723. infoChild.idParent = destFolderID;
  724. hr = g_pStore->CreateFolder(CREATE_FOLDER_LOCALONLY, &infoChild, NOSTORECALLBACK);
  725. if (SUCCEEDED(hr)) {
  726. hr = g_pStore->SubscribeToFolder(infoChild.idFolder, TRUE, NULL);
  727. }
  728. infoChild.pszAccountId = oldID;
  729. pSrcStore->FreeRecord(&infoChild);
  730. }
  731. }
  732. SafeRelease(pEnumChild);
  733. }
  734. }
  735. SafeRelease(pAccount);
  736. }
  737. pSrcStore->FreeRecord(&info);
  738. }
  739. exit:
  740. SafeRelease(pEnum);
  741. return hr;
  742. }
  743. HRESULT ImportMailStoreToGUID(IMailImport *pMailImport, GUID *pDestUUID, LPCSTR pszDestStoreDir)
  744. {
  745. HRESULT hr = S_OK;
  746. CMailImporter *pNew=NULL;
  747. pNew = new CMailImporter;
  748. IF_NULLEXIT(pNew);
  749. // Sometimes during the SimpleStoreInit, Wab is initialized as well.
  750. // Since it is never terminated, some registry key will remain opened.
  751. // The consumer of this function will not be able to unload a mapped user
  752. // hive because of this. To fix this problem, we added the Wab init here
  753. // and an corresponding Wab done later on.
  754. HrInitWab (TRUE);
  755. IF_FAILEXIT(SimpleStoreInit(pDestUUID, pszDestStoreDir));
  756. IF_FAILEXIT(SimpleImportMailFolders(pNew, pMailImport, COOKIE_ROOT, COOKIE_ROOT));
  757. exit:
  758. SimpleStoreRelease();
  759. HrInitWab (FALSE);
  760. SafeRelease(pNew);
  761. return hr;
  762. }
  763. HRESULT ImportNewsListToGUID(LPCSTR pszSrcPath, GUID *pDestUUID, LPCSTR pszDestStoreDir)
  764. {
  765. HRESULT hr = S_OK;
  766. CMessageStore *pSrcStore=NULL;
  767. pSrcStore = new CMessageStore(FALSE);
  768. IF_NULLEXIT(pSrcStore);
  769. IF_FAILEXIT(pSrcStore->Initialize(pszSrcPath));
  770. // Sometimes during the SimpleStoreInit, Wab is initialized as well.
  771. // Since it is never terminated, some registry key will remain opened.
  772. // The consumer of this function will not be able to unload a mapped user
  773. // hive because of this. To fix this problem, we added the Wab init here
  774. // and an corresponding Wab done later on.
  775. HrInitWab (TRUE);
  776. IF_FAILEXIT(SimpleStoreInit(pDestUUID, pszDestStoreDir));
  777. IF_FAILEXIT(SimpleImportNewsList(pSrcStore));
  778. exit:
  779. SimpleStoreRelease();
  780. HrInitWab (FALSE);
  781. SafeRelease(pSrcStore);
  782. return hr;
  783. }