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.

876 lines
22 KiB

  1. #include "pch.hxx"
  2. #include <mapi.h>
  3. #include <mapix.h>
  4. #include <imnapi.h>
  5. #include <newimp.h>
  6. #include <impapi.h>
  7. #include <import.h>
  8. #include "mapiconv.h"
  9. #include <dllmain.h>
  10. #include <shlwapi.h>
  11. #include <strconst.h>
  12. #define INITGUID
  13. #define USES_IID_IMessage
  14. #define USES_IID_IMAPIFolder
  15. #include <ole2.h>
  16. #include <initguid.h>
  17. #include <MAPIGUID.H>
  18. ASSERTDATA
  19. static const TCHAR c_szMapi32Dll[] = TEXT("mapi32.dll");
  20. const static TCHAR szMAPILogonEx[] = TEXT("MAPILogonEx");
  21. const static TCHAR szMAPIInitialize[] = TEXT("MAPIInitialize");
  22. const static TCHAR szMAPIUninitialize[] = TEXT("MAPIUninitialize");
  23. const static TCHAR szMAPIFreeBuffer[] = TEXT("MAPIFreeBuffer");
  24. const static TCHAR szMAPIAllocateBuffer[] = TEXT("MAPIAllocateBuffer");
  25. const static TCHAR szMAPIAllocateMore[] = TEXT("MAPIAllocateMore");
  26. const static TCHAR szMAPIAdminProfiles[] = TEXT("MAPIAdminProfiles");
  27. const static TCHAR szFreeProws[] = TEXT("FreeProws@4");
  28. const static TCHAR szHrQueryAllRows[] = TEXT("HrQueryAllRows@24");
  29. const static TCHAR szWrapCompressedRTFStream[] = TEXT("WrapCompressedRTFStream");
  30. static char g_szDefClient[MAX_PATH];
  31. HMODULE g_hlibMAPI = NULL;
  32. LPMAPILOGONEX lpMAPILogonEx = NULL;
  33. LPMAPIINITIALIZE lpMAPIInitialize = NULL;
  34. LPMAPIUNINITIALIZE lpMAPIUninitialize = NULL;
  35. LPMAPIFREEBUFFER lpMAPIFreeBuffer = NULL;
  36. LPMAPIALLOCATEBUFFER lpMAPIAllocateBuffer = NULL;
  37. LPMAPIALLOCATEMORE lpMAPIAllocateMore = NULL;
  38. LPMAPIADMINPROFILES lpMAPIAdminProfiles = NULL;
  39. LPFREEPROWS lpFreeProws = NULL;
  40. LPHRQUERYALLROWS lpHrQueryAllRows = NULL;
  41. LPWRAPCOMPRESSEDRTFSTREAM lpWrapCompressedRTFStream = NULL;
  42. HRESULT GetSubFolderList(LPMAPICONTAINER pcont, IMPFOLDERNODE **ppnode, IMPFOLDERNODE *pparent);
  43. HRESULT ExchGetFolderList(HWND hwnd, IMAPISession *pmapi, IMPFOLDERNODE **pplist);
  44. void ExchFreeFolderList(IMPFOLDERNODE *pnode);
  45. VOID ExchFreeImsg(LPIMSG lpImsg);
  46. static BOOL g_fMapiInit = FALSE;
  47. CExchImport::CExchImport()
  48. {
  49. DllAddRef();
  50. m_cRef = 1;
  51. m_plist = NULL;
  52. m_pmapi = NULL;
  53. }
  54. CExchImport::~CExchImport()
  55. {
  56. if (m_plist != NULL)
  57. ExchFreeFolderList(m_plist);
  58. if (m_pmapi != NULL)
  59. {
  60. m_pmapi->Logoff(NULL, 0, 0);
  61. SideAssert(0 == m_pmapi->Release());
  62. }
  63. DllRelease();
  64. }
  65. ULONG CExchImport::AddRef()
  66. {
  67. m_cRef++;
  68. return(m_cRef);
  69. }
  70. ULONG CExchImport::Release()
  71. {
  72. ULONG cRef;
  73. cRef = --m_cRef;
  74. if (cRef == 0)
  75. delete this;
  76. return(cRef);
  77. }
  78. HRESULT CExchImport::QueryInterface(REFIID riid, LPVOID *ppv)
  79. {
  80. HRESULT hr = S_OK;
  81. if (ppv == NULL)
  82. return(E_INVALIDARG);
  83. *ppv = NULL;
  84. if (IID_IMailImport == riid)
  85. *ppv = (IMailImport *)this;
  86. else if (IID_IUnknown == riid)
  87. *ppv = (IUnknown *)this;
  88. else
  89. hr = E_NOINTERFACE;
  90. if (*ppv != NULL)
  91. ((LPUNKNOWN)*ppv)->AddRef();
  92. return(hr);
  93. }
  94. HRESULT CExchImport::InitializeImport(HWND hwnd)
  95. {
  96. HRESULT hr;
  97. if (SUCCEEDED(hr = ExchInit()) && S_OK == (hr = MapiLogon(hwnd, &m_pmapi)))
  98. {
  99. Assert(m_pmapi != NULL);
  100. hr = ExchGetFolderList(hwnd, m_pmapi, &m_plist);
  101. }
  102. if (hr == hrMapiInitFail)
  103. {
  104. ImpMessageBox(hwnd, MAKEINTRESOURCE(idsImportTitle),
  105. MAKEINTRESOURCE(idsMapiImportFailed), MAKEINTRESOURCE(idsMapiInitError),
  106. MB_OK | MB_ICONSTOP);
  107. }
  108. else if (hr == hrNoProfilesFound)
  109. {
  110. ImpMessageBox(hwnd, MAKEINTRESOURCE(idsImportTitle),
  111. MAKEINTRESOURCE(idsMapiImportFailed), MAKEINTRESOURCE(idsNoMapiProfiles),
  112. MB_OK | MB_ICONSTOP);
  113. }
  114. else if (FAILED(hr) && hr != MAPI_E_USER_CANCEL)
  115. {
  116. ImpMessageBox(hwnd, MAKEINTRESOURCE(idsImportTitle),
  117. MAKEINTRESOURCE(idsMapiImportFailed), MAKEINTRESOURCE(idsGenericError),
  118. MB_OK | MB_ICONSTOP);
  119. }
  120. return(hr);
  121. }
  122. HRESULT CExchImport::GetDirectory(char *szDir, UINT cch)
  123. {
  124. return(S_FALSE);
  125. }
  126. HRESULT CExchImport::SetDirectory(char *szDir)
  127. {
  128. Assert(FALSE);
  129. return(E_FAIL);
  130. }
  131. HRESULT CExchImport::EnumerateFolders(DWORD_PTR dwCookie, IEnumFOLDERS **ppEnum)
  132. {
  133. CExchEnumFOLDERS *pEnum;
  134. IMPFOLDERNODE *pnode;
  135. Assert(ppEnum != NULL);
  136. *ppEnum = NULL;
  137. if (dwCookie == COOKIE_ROOT)
  138. pnode = m_plist;
  139. else
  140. pnode = ((IMPFOLDERNODE *)dwCookie)->pchild;
  141. if (pnode == NULL)
  142. return(S_FALSE);
  143. pEnum = new CExchEnumFOLDERS(pnode);
  144. if (pEnum == NULL)
  145. return(E_OUTOFMEMORY);
  146. *ppEnum = pEnum;
  147. return(S_OK);
  148. }
  149. static SizedSPropTagArray(1, s_taMessage) =
  150. {
  151. 1,
  152. {
  153. PR_ENTRYID,
  154. }
  155. };
  156. STDMETHODIMP CExchImport::ImportFolder(DWORD_PTR dwCookie, IFolderImport *pImport)
  157. {
  158. IMPFOLDERNODE *pnode;
  159. HRESULT hr;
  160. IMSG imsg;
  161. LPMAPITABLE ptbl;
  162. LPMAPICONTAINER pcont;
  163. ULONG cRow, i, ulObjType;
  164. LPSRow lprw;
  165. LPSPropValue lpProp;
  166. LPSRowSet prset;
  167. LPMESSAGE pmsg;
  168. Assert(pImport != NULL);
  169. pnode = (IMPFOLDERNODE *)dwCookie;
  170. Assert(pnode != NULL);
  171. hr = E_FAIL;
  172. pcont = (LPMAPICONTAINER)pnode->lparam;
  173. Assert(pcont != NULL);
  174. hr = pcont->GetContentsTable(0, &ptbl);
  175. if (FAILED(hr))
  176. {
  177. Assert(FALSE);
  178. return(hr);
  179. }
  180. if (!FAILED(hr = ptbl->SetColumns((LPSPropTagArray)&s_taMessage, 0)) &&
  181. !FAILED(hr = ptbl->GetRowCount(0, &cRow)) &&
  182. cRow > 0)
  183. {
  184. pImport->SetMessageCount(cRow);
  185. while (TRUE)
  186. {
  187. if(hr == hrUserCancel)
  188. break;
  189. if (cRow == 0)
  190. {
  191. hr = S_OK;
  192. break;
  193. }
  194. hr = ptbl->QueryRows(cRow, 0, &prset);
  195. if (FAILED(hr))
  196. break;
  197. if (prset->cRows == 0)
  198. {
  199. FreeSRowSet(prset);
  200. break;
  201. }
  202. for (i = 0, lprw = prset->aRow; i < prset->cRows; i++, lprw++)
  203. {
  204. if(hr == hrUserCancel)
  205. break;
  206. lpProp = lprw->lpProps;
  207. Assert(lpProp->ulPropTag == PR_ENTRYID);
  208. hr = pcont->OpenEntry(lpProp->Value.bin.cb,
  209. (LPENTRYID)lpProp->Value.bin.lpb, NULL, MAPI_BEST_ACCESS,
  210. &ulObjType, (LPUNKNOWN *)&pmsg);
  211. Assert(!FAILED(hr));
  212. if (!FAILED(hr))
  213. {
  214. hr = HrMapiToImsg(pmsg, &imsg);
  215. Assert(!FAILED(hr));
  216. if (!FAILED(hr))
  217. {
  218. hr = pImport->ImportMessage(&imsg);
  219. ExchFreeImsg(&imsg);
  220. }
  221. pmsg->Release();
  222. }
  223. }
  224. Assert(prset->cRows <= cRow);
  225. cRow -= prset->cRows;
  226. FreeSRowSet(prset);
  227. }
  228. }
  229. ptbl->Release();
  230. return(hr);
  231. }
  232. CExchEnumFOLDERS::CExchEnumFOLDERS(IMPFOLDERNODE *plist)
  233. {
  234. Assert(plist != NULL);
  235. m_cRef = 1;
  236. m_plist = plist;
  237. m_pnext = plist;
  238. }
  239. CExchEnumFOLDERS::~CExchEnumFOLDERS()
  240. {
  241. }
  242. ULONG CExchEnumFOLDERS::AddRef()
  243. {
  244. m_cRef++;
  245. return(m_cRef);
  246. }
  247. ULONG CExchEnumFOLDERS::Release()
  248. {
  249. ULONG cRef;
  250. cRef = --m_cRef;
  251. if (cRef == 0)
  252. delete this;
  253. return(cRef);
  254. }
  255. HRESULT CExchEnumFOLDERS::QueryInterface(REFIID riid, LPVOID *ppv)
  256. {
  257. HRESULT hr = S_OK;
  258. if (ppv == NULL)
  259. return(E_INVALIDARG);
  260. *ppv = NULL;
  261. if (IID_IEnumFOLDERS == riid)
  262. *ppv = (IEnumFOLDERS *)this;
  263. else if (IID_IUnknown == riid)
  264. *ppv = (IUnknown *)this;
  265. else
  266. hr = E_NOINTERFACE;
  267. if (*ppv != NULL)
  268. ((LPUNKNOWN)*ppv)->AddRef();
  269. return(hr);
  270. }
  271. HRESULT CExchEnumFOLDERS::Next(IMPORTFOLDER *pfldr)
  272. {
  273. Assert(pfldr != NULL);
  274. if (m_pnext == NULL)
  275. return(S_FALSE);
  276. ZeroMemory(pfldr, sizeof(IMPORTFOLDER));
  277. pfldr->dwCookie = (DWORD_PTR)m_pnext;
  278. StrCpyN(pfldr->szName, m_pnext->szName, ARRAYSIZE(pfldr->szName));
  279. // pfldr->type = 0;
  280. pfldr->fSubFolders = (m_pnext->pchild != NULL);
  281. m_pnext = m_pnext->pnext;
  282. return(S_OK);
  283. }
  284. HRESULT CExchEnumFOLDERS::Reset()
  285. {
  286. m_pnext = m_plist;
  287. return(S_OK);
  288. }
  289. HRESULT ExchInit(void)
  290. {
  291. HRESULT hr;
  292. DWORD cb, type;
  293. char sz[MAX_PATH];
  294. if (g_fMapiInit)
  295. return(S_OK);
  296. Assert(g_hlibMAPI == NULL);
  297. g_hlibMAPI = LoadLibrary(c_szMapi32Dll);
  298. if (g_hlibMAPI == NULL)
  299. return(hrMapiInitFail);
  300. lpMAPILogonEx = (LPMAPILOGONEX)GetProcAddress(g_hlibMAPI, szMAPILogonEx);
  301. lpMAPIInitialize = (LPMAPIINITIALIZE)GetProcAddress(g_hlibMAPI, szMAPIInitialize);
  302. lpMAPIUninitialize = (LPMAPIUNINITIALIZE)GetProcAddress(g_hlibMAPI, szMAPIUninitialize);
  303. lpMAPIFreeBuffer = (LPMAPIFREEBUFFER)GetProcAddress(g_hlibMAPI, szMAPIFreeBuffer);
  304. lpMAPIAllocateBuffer = (LPMAPIALLOCATEBUFFER)GetProcAddress(g_hlibMAPI, szMAPIAllocateBuffer);
  305. lpMAPIAllocateMore = (LPMAPIALLOCATEMORE)GetProcAddress(g_hlibMAPI, szMAPIAllocateMore);
  306. lpMAPIAdminProfiles = (LPMAPIADMINPROFILES)GetProcAddress(g_hlibMAPI, szMAPIAdminProfiles);
  307. lpFreeProws = (LPFREEPROWS)GetProcAddress(g_hlibMAPI, szFreeProws);
  308. lpHrQueryAllRows = (LPHRQUERYALLROWS)GetProcAddress(g_hlibMAPI, szHrQueryAllRows);
  309. lpWrapCompressedRTFStream = (LPWRAPCOMPRESSEDRTFSTREAM)GetProcAddress(g_hlibMAPI, szWrapCompressedRTFStream);
  310. if (lpMAPILogonEx == NULL ||
  311. lpMAPIInitialize == NULL ||
  312. lpMAPIUninitialize == NULL ||
  313. lpMAPIFreeBuffer == NULL ||
  314. lpFreeProws == NULL ||
  315. lpHrQueryAllRows == NULL ||
  316. lpWrapCompressedRTFStream == NULL ||
  317. lpMAPIAllocateBuffer == NULL ||
  318. lpMAPIAllocateMore == NULL)
  319. {
  320. hr = hrMapiInitFail;
  321. }
  322. else
  323. {
  324. *g_szDefClient = 0;
  325. cb = sizeof(sz);
  326. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, c_szRegOutlook, NULL, &type, (LPBYTE)sz, &cb))
  327. {
  328. cb = sizeof(g_szDefClient);
  329. if (ERROR_SUCCESS == SHGetValue(HKEY_LOCAL_MACHINE, c_szRegMail, NULL, &type, (LPBYTE)g_szDefClient, &cb))
  330. {
  331. if (0 != lstrcmpi(g_szDefClient, c_szMicrosoftOutlook))
  332. {
  333. if (ERROR_SUCCESS != SHSetValue(HKEY_LOCAL_MACHINE, c_szRegMail, NULL, REG_SZ, (LPBYTE)c_szMicrosoftOutlook, lstrlen(c_szMicrosoftOutlook) + 1))
  334. *g_szDefClient = 0;
  335. }
  336. else
  337. {
  338. *g_szDefClient = 0;
  339. }
  340. }
  341. }
  342. hr = lpMAPIInitialize(NULL);
  343. }
  344. if (SUCCEEDED(hr))
  345. {
  346. g_fMapiInit = TRUE;
  347. }
  348. else
  349. {
  350. FreeLibrary(g_hlibMAPI);
  351. g_hlibMAPI = NULL;
  352. }
  353. return(hr);
  354. }
  355. void ExchDeinit()
  356. {
  357. if (g_fMapiInit)
  358. {
  359. Assert(g_hlibMAPI != NULL);
  360. lpMAPIUninitialize();
  361. FreeLibrary(g_hlibMAPI);
  362. g_hlibMAPI = NULL;
  363. if (*g_szDefClient != 0)
  364. {
  365. SHSetValue(HKEY_LOCAL_MACHINE, c_szRegMail, NULL, REG_SZ, (LPBYTE)g_szDefClient, lstrlen(g_szDefClient) + 1);
  366. *g_szDefClient = 0;
  367. }
  368. g_fMapiInit = FALSE;
  369. }
  370. }
  371. HRESULT MapiLogon(HWND hwnd, IMAPISession **ppmapi)
  372. {
  373. HRESULT hr;
  374. LPPROFADMIN lpAdmin;
  375. LPMAPITABLE lpTable = NULL;
  376. ULONG ulCount = NULL;
  377. Assert(g_fMapiInit);
  378. if (ppmapi != NULL)
  379. *ppmapi = NULL;
  380. if (!FAILED(hr = lpMAPIAdminProfiles(0, &lpAdmin)))
  381. {
  382. Assert(lpAdmin != NULL);
  383. if (FAILED(hr = lpAdmin->GetProfileTable(0, &lpTable)) ||
  384. FAILED(hr = lpTable->GetRowCount(0, &ulCount)) ||
  385. !ulCount)
  386. {
  387. // could not find a valid profile
  388. hr = hrNoProfilesFound;
  389. }
  390. else
  391. {
  392. if (ppmapi != NULL)
  393. hr = lpMAPILogonEx((ULONG_PTR)hwnd, NULL, NULL, MAPI_EXTENDED | MAPI_LOGON_UI | MAPI_ALLOW_OTHERS, ppmapi);
  394. else
  395. hr = S_OK;
  396. }
  397. if (lpTable != NULL)
  398. lpTable->Release();
  399. lpAdmin->Release();
  400. }
  401. return(hr);
  402. }
  403. HRESULT ExchGetFolderList(HWND hwnd, IMAPISession *pmapi, IMPFOLDERNODE **pplist)
  404. {
  405. HRESULT hr;
  406. LPMAPICONTAINER pcont;
  407. IMPFOLDERNODE *plist;
  408. Assert(g_fMapiInit);
  409. Assert(pmapi != NULL);
  410. hr = E_FAIL;
  411. pcont = OpenDefaultStoreContainer(hwnd, pmapi);
  412. if (pcont != NULL)
  413. {
  414. plist = NULL;
  415. hr = GetSubFolderList(pcont, &plist, NULL);
  416. Assert(!FAILED(hr));
  417. Assert(plist != NULL);
  418. *pplist = plist;
  419. pcont->Release();
  420. }
  421. return(hr);
  422. }
  423. void ExchFreeFolderList(IMPFOLDERNODE *pnode)
  424. {
  425. Assert(pnode != NULL);
  426. if (pnode->pchild != NULL)
  427. ExchFreeFolderList(pnode->pchild);
  428. if (pnode->pnext != NULL)
  429. ExchFreeFolderList(pnode->pnext);
  430. if (pnode->szName != NULL)
  431. MemFree(pnode->szName);
  432. if (pnode->lparam != NULL)
  433. ((LPMAPICONTAINER)pnode->lparam)->Release();
  434. MemFree(pnode);
  435. }
  436. LPMAPICONTAINER OpenDefaultStoreContainer(HWND hwnd, IMAPISession *pmapi)
  437. {
  438. HRESULT hr;
  439. LPMDB pmdb;
  440. LPMAPITABLE ptbl;
  441. LPSRowSet lpsrw;
  442. LPSRow prw;
  443. ULONG cStores,
  444. cRows;
  445. LPSPropValue ppvDefStore;
  446. LPENTRYID lpEID;
  447. ULONG cbEID, ulObjType, ulValues;
  448. LPMAPICONTAINER pcont;
  449. LPSPropValue lpPropsIPM = NULL;
  450. ULONG ulPropTags[2] = {1, PR_IPM_SUBTREE_ENTRYID};
  451. SizedSPropTagArray(4, pta) =
  452. { 4, {PR_DEFAULT_STORE, PR_ENTRYID, PR_OBJECT_TYPE, PR_RESOURCE_FLAGS}};
  453. Assert(hwnd != NULL);
  454. Assert(pmapi != NULL);
  455. pmdb = NULL;
  456. ptbl = NULL;
  457. lpsrw = NULL;
  458. pcont = NULL;
  459. hr = pmapi->GetMsgStoresTable(0, &ptbl);
  460. if (HR_FAILED(hr))
  461. goto error;
  462. hr = lpHrQueryAllRows(ptbl,(LPSPropTagArray)&pta, NULL, NULL, 0, &lpsrw);
  463. if (HR_FAILED(hr))
  464. goto error;
  465. cRows = lpsrw->cRows;
  466. prw = &lpsrw->aRow[0];
  467. cStores = 0;
  468. ppvDefStore = NULL;
  469. while (cRows--)
  470. {
  471. if (prw->lpProps[2].ulPropTag == PR_OBJECT_TYPE && prw->lpProps[2].Value.l == MAPI_STORE)
  472. {
  473. if (prw->lpProps[3].ulPropTag != PR_RESOURCE_FLAGS ||
  474. !(prw->lpProps[3].Value.l & STATUS_NO_DEFAULT_STORE))
  475. cStores++;
  476. }
  477. if( prw->lpProps[0].ulPropTag == PR_DEFAULT_STORE &&
  478. prw->lpProps[0].Value.b)
  479. ppvDefStore=prw->lpProps;
  480. prw++;
  481. }
  482. if (!ppvDefStore || ppvDefStore[1].ulPropTag != PR_ENTRYID)
  483. goto error;
  484. hr = pmapi->OpenMsgStore((ULONG_PTR)hwnd, ppvDefStore[1].Value.bin.cb,
  485. (LPENTRYID)ppvDefStore[1].Value.bin.lpb,
  486. NULL, MAPI_BEST_ACCESS, &pmdb);
  487. if (!HR_FAILED(hr))
  488. {
  489. // Get the IPM_SUBTREE from the ROOT
  490. if (!FAILED(hr = pmdb->GetProps((LPSPropTagArray)&ulPropTags, 0, &ulValues, &lpPropsIPM)))
  491. {
  492. cbEID = lpPropsIPM->Value.bin.cb;
  493. lpEID = (LPENTRYID)lpPropsIPM->Value.bin.lpb;
  494. hr = pmdb->OpenEntry(cbEID, lpEID, NULL, MAPI_BEST_ACCESS,
  495. &ulObjType, (LPUNKNOWN *)&pcont);
  496. lpMAPIFreeBuffer(lpPropsIPM);
  497. }
  498. }
  499. error:
  500. if (lpsrw != NULL)
  501. FreeSRowSet(lpsrw);
  502. if (ptbl != NULL)
  503. ptbl->Release();
  504. if (pmdb != NULL)
  505. pmdb->Release();
  506. return(pcont);
  507. }
  508. /*
  509. * FreeSRowSet
  510. *
  511. * Purpose:
  512. * Frees an SRowSet structure and the rows therein
  513. *
  514. * Parameters:
  515. * LPSRowSet The row set to free
  516. */
  517. void FreeSRowSet(LPSRowSet prws)
  518. {
  519. ULONG irw;
  520. if (!prws)
  521. return;
  522. // Free each row
  523. for (irw = 0; irw < prws->cRows; irw++)
  524. lpMAPIFreeBuffer(prws->aRow[irw].lpProps);
  525. // Free the top level structure
  526. lpMAPIFreeBuffer(prws);
  527. }
  528. static SizedSPropTagArray(5, s_taFolder) =
  529. {
  530. 5,
  531. {
  532. PR_DISPLAY_NAME,
  533. PR_ENTRYID,
  534. PR_SUBFOLDERS,
  535. PR_OBJECT_TYPE,
  536. PR_CONTENT_COUNT
  537. }
  538. };
  539. enum
  540. {
  541. iDISPLAY_NAME = 0,
  542. iENTRYID,
  543. iSUBFOLDERS,
  544. iOBJECT_TYPE,
  545. iCONTENT_COUNT
  546. };
  547. HRESULT GetSubFolderList(LPMAPICONTAINER pcont, IMPFOLDERNODE **ppnode, IMPFOLDERNODE *pparent)
  548. {
  549. HRESULT hr;
  550. IMPFOLDERNODE *pnode, *pnew, *plast;
  551. ULONG i, cRow, ulObj;
  552. int cb;
  553. LPSRow lprw;
  554. LPSPropValue lpProp;
  555. LPMAPITABLE ptbl;
  556. LPSRowSet prset;
  557. *ppnode = NULL;
  558. hr = pcont->GetHierarchyTable(0, &ptbl);
  559. if (FAILED(hr))
  560. return(hr);
  561. pnode = NULL;
  562. if (!FAILED(hr = ptbl->SetColumns((LPSPropTagArray)&s_taFolder, 0)) &&
  563. !FAILED(hr = ptbl->GetRowCount(0, &cRow)) &&
  564. cRow > 0)
  565. {
  566. while (TRUE)
  567. {
  568. if (cRow == 0)
  569. {
  570. hr = S_OK;
  571. break;
  572. }
  573. hr = ptbl->QueryRows(cRow, 0, &prset);
  574. if (FAILED(hr))
  575. break;
  576. if (prset->cRows == 0)
  577. {
  578. FreeSRowSet(prset);
  579. break;
  580. }
  581. for (i = 0, lprw = prset->aRow; i < prset->cRows; i++, lprw++)
  582. {
  583. if (!MemAlloc((void **)&pnew, sizeof(IMPFOLDERNODE)))
  584. break;
  585. ZeroMemory(pnew, sizeof(IMPFOLDERNODE));
  586. lpProp = &lprw->lpProps[iENTRYID];
  587. Assert(lpProp->ulPropTag == PR_ENTRYID);
  588. hr = pcont->OpenEntry(lpProp->Value.bin.cb, (LPENTRYID)lpProp->Value.bin.lpb, NULL,
  589. MAPI_BEST_ACCESS, &ulObj, (LPUNKNOWN *)&pnew->lparam);
  590. if (FAILED(hr))
  591. {
  592. MemFree(pnew);
  593. continue;
  594. }
  595. lpProp = &lprw->lpProps[iCONTENT_COUNT];
  596. Assert(lpProp->ulPropTag == PR_CONTENT_COUNT);
  597. pnew->cMsg = lpProp->Value.l;
  598. lpProp = &lprw->lpProps[iDISPLAY_NAME];
  599. Assert(lpProp->ulPropTag == PR_DISPLAY_NAME);
  600. cb = (lstrlen(lpProp->Value.LPSZ) + 1) * sizeof(TCHAR);
  601. if (!MemAlloc((void **)&pnew->szName, cb))
  602. break;
  603. StrCpyN(pnew->szName, lpProp->Value.LPSZ, cb / sizeof(TCHAR));
  604. pnew->depth = (pparent != NULL) ? pparent->depth + 1 : 0;
  605. pnew->pparent = pparent;
  606. if (pnode == NULL)
  607. pnode = pnew;
  608. else
  609. plast->pnext = pnew;
  610. plast = pnew;
  611. lpProp = &lprw->lpProps[iSUBFOLDERS];
  612. Assert(lpProp->ulPropTag == PR_SUBFOLDERS);
  613. if (lpProp->Value.b)
  614. {
  615. hr = GetSubFolderList((LPMAPICONTAINER)pnew->lparam, &pnew->pchild, pnew);
  616. Assert(!FAILED(hr));
  617. }
  618. }
  619. Assert(prset->cRows <= cRow);
  620. cRow -= prset->cRows;
  621. FreeSRowSet(prset);
  622. }
  623. }
  624. ptbl->Release();
  625. *ppnode = pnode;
  626. return(hr);
  627. }
  628. LPSPropValue PvalFind(LPSRow prw, ULONG ulPropTag)
  629. {
  630. UINT ival = 0;
  631. LPSPropValue pval = NULL;
  632. if(!prw)
  633. return NULL;
  634. ival = (UINT) prw->cValues;
  635. pval = prw->lpProps;
  636. while (ival--)
  637. {
  638. if (pval->ulPropTag == ulPropTag)
  639. return pval;
  640. ++pval;
  641. }
  642. return NULL;
  643. }
  644. VOID ExchFreeImsg (LPIMSG lpImsg)
  645. {
  646. // Locals
  647. ULONG i;
  648. // Nothing
  649. if (lpImsg == NULL)
  650. return;
  651. // Free Stuff
  652. if (lpImsg->lpszSubject)
  653. MemFree(lpImsg->lpszSubject);
  654. lpImsg->lpszSubject = NULL;
  655. if (lpImsg->lpstmBody)
  656. lpImsg->lpstmBody->Release ();
  657. lpImsg->lpstmBody = NULL;
  658. if (lpImsg->lpstmHtml)
  659. lpImsg->lpstmHtml->Release ();
  660. lpImsg->lpstmHtml = NULL;
  661. // Walk Address list
  662. for (i=0; i<lpImsg->cAddress; i++)
  663. {
  664. if (lpImsg->lpIaddr[i].lpszAddress)
  665. MemFree(lpImsg->lpIaddr[i].lpszAddress);
  666. lpImsg->lpIaddr[i].lpszAddress = NULL;
  667. if (lpImsg->lpIaddr[i].lpszDisplay)
  668. MemFree(lpImsg->lpIaddr[i].lpszDisplay);
  669. lpImsg->lpIaddr[i].lpszDisplay = NULL;
  670. }
  671. // Free Address list
  672. if (lpImsg->lpIaddr)
  673. MemFree(lpImsg->lpIaddr);
  674. lpImsg->lpIaddr = NULL;
  675. // Walk Attachment list
  676. for (i=0; i<lpImsg->cAttach; i++)
  677. {
  678. if (lpImsg->lpIatt[i].lpszFileName)
  679. MemFree(lpImsg->lpIatt[i].lpszFileName);
  680. lpImsg->lpIatt[i].lpszFileName = NULL;
  681. if (lpImsg->lpIatt[i].lpszPathName)
  682. MemFree(lpImsg->lpIatt[i].lpszPathName);
  683. lpImsg->lpIatt[i].lpszPathName = NULL;
  684. if (lpImsg->lpIatt[i].lpszExt)
  685. MemFree(lpImsg->lpIatt[i].lpszExt);
  686. lpImsg->lpIatt[i].lpszExt = NULL;
  687. if (lpImsg->lpIatt[i].lpImsg)
  688. {
  689. ExchFreeImsg (lpImsg->lpIatt[i].lpImsg);
  690. MemFree(lpImsg->lpIatt[i].lpImsg);
  691. lpImsg->lpIatt[i].lpImsg = NULL;
  692. }
  693. if (lpImsg->lpIatt[i].lpstmAtt)
  694. lpImsg->lpIatt[i].lpstmAtt->Release ();
  695. lpImsg->lpIatt[i].lpstmAtt = NULL;
  696. }
  697. // Free the att list
  698. if (lpImsg->lpIatt)
  699. MemFree(lpImsg->lpIatt);
  700. }