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.

1472 lines
42 KiB

  1. // badata.cpp: implementation of the CAddressBook class.
  2. // WAB & Messenger integration to OE
  3. // Created 04/20/98 by YST
  4. //
  5. //////////////////////////////////////////////////////////////////////
  6. #include "pch.hxx"
  7. #include <shfusion.h>
  8. #include "bactrl.h"
  9. #include "badata.h"
  10. #include "baui.h"
  11. #include "baprop.h"
  12. #include "ourguid.h"
  13. #include "mapiguid.h"
  14. #include "shlwapip.h"
  15. #include "ipab.h"
  16. #include "multiusr.h"
  17. #include "demand.h"
  18. #include "secutil.h"
  19. #ifdef _DEBUG
  20. #undef THIS_FILE
  21. static char THIS_FILE[]=__FILE__;
  22. #define new DEBUG_NEW
  23. #endif
  24. //////////////////////////////////////////////////////////////////////
  25. // Defines for the various MAPI Tables we request from the WAB
  26. //////////////////////////////////////////////////////////////////////
  27. #define MAX_QUERY_SIZE 1000
  28. // Here are some private properties that the WAB stores. If WAB ever
  29. // changes any of these we're in trouble.
  30. #define WAB_INTERNAL_BASE 0x6600
  31. #define PR_WAB_LDAP_SERVER PROP_TAG(PT_TSTRING, WAB_INTERNAL_BASE + 1)
  32. #define PR_WAB_RESOLVE_FLAG PROP_TAG(PT_BOOLEAN, WAB_INTERNAL_BASE + 2)
  33. // This BA's private GUID:
  34. // {2BAD7EE0-36AB-11d1-9BAC-00A0C91F9C8B}
  35. static const GUID WAB_ExtBAGuid =
  36. { 0x2bad7ee0, 0x36ab, 0x11d1, { 0x9b, 0xac, 0x0, 0xa0, 0xc9, 0x1f, 0x9c, 0x8b } };
  37. static const LPTSTR lpMsgrPropNames[] =
  38. {
  39. "MsgrID"
  40. };
  41. enum _MsgrTags
  42. {
  43. MsgrID = 0,
  44. msgrMax
  45. };
  46. ULONG MsgrPropTags[msgrMax];
  47. ULONG PR_MSGR_DEF_ID = 0;
  48. // These two define the table we request from the WAB when showing the
  49. // contents of the local address book.
  50. enum {
  51. ieidPR_DISPLAY_NAME = 0,
  52. ieidPR_ENTRYID,
  53. ieidPR_OBJECT_TYPE,
  54. ieidPR_MSGR_DEF_ID,
  55. // ieidPR_BUSINESS_TELEPHONE_NUMBER,
  56. ieidPR_EMAIL_ADDRESS,
  57. ieidPR_USER_X509_CERTIFICATE,
  58. ieidPR_RECORD_KEY,
  59. ieidMax
  60. };
  61. static SizedSPropTagArray(ieidMax, ptaEid)=
  62. {
  63. ieidMax,
  64. {
  65. PR_DISPLAY_NAME,
  66. PR_ENTRYID,
  67. PR_OBJECT_TYPE,
  68. PR_MSGR_DEF_ID,
  69. // PR_BUSINESS_TELEPHONE_NUMBER,
  70. PR_EMAIL_ADDRESS,
  71. PR_USER_X509_CERTIFICATE,
  72. PR_RECORD_KEY
  73. }
  74. };
  75. // These two define the table we request to see which LDAP servers should
  76. // be resolved against.
  77. enum {
  78. irnPR_OBJECT_TYPE = 0,
  79. irnPR_WAB_RESOLVE_FLAG,
  80. irnPR_ENTRYID,
  81. irnPR_DISPLAY_NAME,
  82. irnMax
  83. };
  84. static const SizedSPropTagArray(irnMax, irnColumns) =
  85. {
  86. irnMax,
  87. {
  88. PR_OBJECT_TYPE,
  89. PR_WAB_RESOLVE_FLAG,
  90. PR_ENTRYID,
  91. PR_DISPLAY_NAME,
  92. }
  93. };
  94. enum {
  95. icrPR_DEF_CREATE_MAILUSER = 0,
  96. icrPR_DEF_CREATE_DL,
  97. icrMax
  98. };
  99. const SizedSPropTagArray(icrMax, ptaCreate)=
  100. {
  101. icrMax,
  102. {
  103. PR_DEF_CREATE_MAILUSER,
  104. PR_DEF_CREATE_DL,
  105. }
  106. };
  107. //////////////////////////////////////////////////////////////////////
  108. // Construction/Destruction
  109. //////////////////////////////////////////////////////////////////////
  110. CAddressBookData::CAddressBookData()
  111. {
  112. m_pWABObject = NULL;
  113. m_hInstWAB = NULL;
  114. m_pAdrBook = NULL;
  115. m_ulConnection = 0;
  116. }
  117. CAddressBookData::~CAddressBookData()
  118. {
  119. // Release the Address Book pointer
  120. if (m_pAdrBook)
  121. m_pAdrBook->Release();
  122. // Release the WAB object
  123. if (m_pWABObject)
  124. m_pWABObject->Release();
  125. if (m_hInstWAB)
  126. FreeLibrary(m_hInstWAB);
  127. }
  128. //
  129. // FUNCTION: CAddressBookData::OpenWabFile()
  130. //
  131. // PURPOSE: Finds the WAB DLL, loads the DLL, and opens the WAB.
  132. //
  133. HRESULT CAddressBookData::OpenWabFile(void)
  134. {
  135. TCHAR szDll[MAX_PATH];
  136. TCHAR szExpanded[MAX_PATH];
  137. DWORD dwType = 0;
  138. LPTSTR psz = szDll;
  139. ULONG cbData = sizeof(szDll);
  140. HKEY hKey = NULL;
  141. HRESULT hr = E_FAIL;
  142. LPWABOPEN lpfnWABOpen;
  143. // Initialize the path string
  144. *szDll = '\0';
  145. // First look under the default WAB DLL path location in the Registry.
  146. // WAB_DLL_PATH_KEY is defined in wabapi.h
  147. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, WAB_DLL_PATH_KEY, 0, KEY_READ, &hKey))
  148. {
  149. if (ERROR_SUCCESS == RegQueryValueEx(hKey, _T(""), NULL, &dwType, (LPBYTE) szDll, &cbData))
  150. if (REG_EXPAND_SZ == dwType)
  151. {
  152. ExpandEnvironmentStrings(szDll, szExpanded, ARRAYSIZE(szExpanded));
  153. psz = szExpanded;
  154. }
  155. RegCloseKey(hKey);
  156. }
  157. // If the registry thing came up blank, then do a LoadLibrary on wab32.dll
  158. m_hInstWAB = LoadLibrary((lstrlen(psz)) ? (LPCTSTR) psz : (LPCTSTR) WAB_DLL_NAME);
  159. if (m_hInstWAB)
  160. {
  161. // If we've got the DLL, then get the entry point
  162. lpfnWABOpen = (LPWABOPEN) GetProcAddress(m_hInstWAB, "WABOpen");
  163. if (lpfnWABOpen)
  164. {
  165. WAB_PARAM wp = {0};
  166. wp.cbSize = sizeof(WAB_PARAM);
  167. wp.guidPSExt = CLSID_OEBAControl;
  168. wp.ulFlags = (g_dwAthenaMode & MODE_NEWSONLY) ? WAB_ENABLE_PROFILES : WAB_ENABLE_PROFILES | WAB_USE_OE_SENDMAIL;
  169. hr = lpfnWABOpen(&m_pAdrBook, &m_pWABObject, &wp, 0);
  170. }
  171. }
  172. return (hr);
  173. }
  174. //
  175. // FUNCTION: CAddressBookData::LoadWabContents()
  176. //
  177. // PURPOSE: Loads the contents of the WAB into the provided ListView control.
  178. //
  179. // PARAMETERS:
  180. // [in] ctlList - Pointer to the ListView control to load the WAB into.
  181. //
  182. HRESULT CAddressBookData::LoadWabContents(CContainedWindow& ctlList, CMsgrAb *pSink)
  183. {
  184. ULONG ulObjType = 0;
  185. LPMAPITABLE lpAB = NULL;
  186. LPTSTR *lppszArray = NULL;
  187. ULONG cRows = 0;
  188. LPSRowSet lpRow = NULL;
  189. LPSRowSet lpRowAB = NULL;
  190. LPABCONT lpContainer = NULL;
  191. int cNumRows = 0;
  192. int nRows = 0;
  193. HRESULT hr = E_FAIL;
  194. ULONG lpcbEID;
  195. LPENTRYID lpEID = NULL;
  196. LPSRowSet pSRowSet = NULL;
  197. Assert(m_pAdrBook);
  198. if (!m_pAdrBook)
  199. return E_UNEXPECTED;
  200. // Get the entryid of the root PAB container
  201. hr = m_pAdrBook->GetPAB(&lpcbEID, &lpEID);
  202. if(!PR_MSGR_DEF_ID)
  203. InitNamedProps();
  204. // Open the root PAB container. This is where all the WAB contents reside.
  205. ulObjType = 0;
  206. hr = m_pAdrBook->OpenEntry(lpcbEID,
  207. (LPENTRYID)lpEID,
  208. NULL,
  209. 0,
  210. &ulObjType,
  211. (LPUNKNOWN *) &lpContainer);
  212. if(HR_FAILED(hr))
  213. goto exit;
  214. if(pSink)
  215. m_pAB = pSink;
  216. if (pSink && !m_ulConnection)
  217. m_pAdrBook->Advise(lpcbEID, lpEID, fnevObjectModified, (IMAPIAdviseSink *) pSink, &m_ulConnection);
  218. // Get a contents table of all the contents in the WABs root container.
  219. hr = lpContainer->GetContentsTable(WAB_PROFILE_CONTENTS /*0*/, &lpAB);
  220. if(HR_FAILED(hr))
  221. goto exit;
  222. // Order the columns in the ContentsTable to conform to the ones we want
  223. // - which are mainly DisplayName, EntryID and ObjectType. The table is
  224. // guaranteed to set the columns in the order requested.
  225. Assert(PR_MSGR_DEF_ID);
  226. ptaEid.aulPropTag[ieidPR_MSGR_DEF_ID] = PR_MSGR_DEF_ID;
  227. hr = lpAB->SetColumns((LPSPropTagArray) &ptaEid, 0);
  228. if(HR_FAILED(hr))
  229. goto exit;
  230. // Reset to the beginning of the table
  231. hr = lpAB->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
  232. if(HR_FAILED(hr))
  233. goto exit;
  234. // If we got this far, we have a populated table. We can query the rows
  235. // now.
  236. hr = _QueryAllRows(lpAB, NULL, NULL, NULL, MAX_QUERY_SIZE, &pSRowSet);
  237. if (FAILED(hr) || !pSRowSet)
  238. goto exit;
  239. // Fill the provided ListView with this table
  240. _FillListFromTable(ctlList, pSRowSet);
  241. exit:
  242. if (lpEID)
  243. m_pWABObject->FreeBuffer(lpEID);
  244. if (pSRowSet)
  245. _FreeProws(pSRowSet);
  246. if (lpContainer)
  247. lpContainer->Release();
  248. if (lpAB)
  249. lpAB->Release();
  250. return hr;
  251. }
  252. HRESULT CAddressBookData::DoLDAPSearch(LPTSTR pszText, CContainedWindow& ctlList)
  253. {
  254. // Build a restriction based on the given text
  255. SRestriction SRes;
  256. if (SUCCEEDED(_GetLDAPSearchRestriction(pszText, &SRes)))
  257. {
  258. // Figure out what the entry ID is for the LDAP container
  259. ULONG cbEntryID = 0;
  260. LPENTRYID pEntryID = 0;
  261. if (SUCCEEDED(_GetLDAPContainer(&cbEntryID, &pEntryID)))
  262. {
  263. // Perform the search
  264. SORT_INFO si = {0, 0};
  265. _GetLDAPContentsList(cbEntryID, pEntryID, si, &SRes, ctlList);
  266. if (pEntryID)
  267. m_pWABObject->FreeBuffer(pEntryID);
  268. }
  269. if (SRes.res.resAnd.lpRes)
  270. m_pWABObject->FreeBuffer(SRes.res.resAnd.lpRes);
  271. }
  272. return (S_OK);
  273. }
  274. void CAddressBookData::_FreeProws(LPSRowSet prows)
  275. {
  276. if (prows)
  277. {
  278. for (ULONG irow = 0; irow < prows->cRows; ++irow)
  279. m_pWABObject->FreeBuffer(prows->aRow[irow].lpProps);
  280. m_pWABObject->FreeBuffer(prows);
  281. }
  282. }
  283. //
  284. // FUNCTION: CAddressBookData::_MergeRowSets()
  285. //
  286. // PURPOSE: Merges prows with *pprowsDst, reallocating *pprowsDst if
  287. // necessary. Destroys the container portion of prows (but not
  288. // the individual rows it contains).
  289. //
  290. // PARAMETERS:
  291. // [in] prows - source set of rows
  292. // [in, out] *pprowsDst - set of rows to merge the prows into
  293. //
  294. // RETURN VALUE:
  295. // HRESULT
  296. //
  297. HRESULT CAddressBookData::_MergeRowSets(LPSRowSet prows, LPSRowSet FAR *pprowsDst)
  298. {
  299. SCODE sc = S_OK;
  300. LPSRowSet prowsT;
  301. UINT crowsSrc;
  302. UINT crowsDst;
  303. _ASSERTE(!IsBadWritePtr(pprowsDst, sizeof(LPSRowSet)));
  304. _ASSERTE(prows);
  305. // If the table is completely empty we want to return this.
  306. if (!*pprowsDst || (*pprowsDst)->cRows == 0)
  307. {
  308. m_pWABObject->FreeBuffer(*pprowsDst);
  309. *pprowsDst = prows;
  310. prows = NULL; // Don't free it!
  311. goto exit;
  312. }
  313. if (prows->cRows == 0)
  314. {
  315. goto exit;
  316. }
  317. // OK, now we know there are rows in both rowsets, we have to do a real
  318. // merge.
  319. crowsSrc = (UINT) prows->cRows;
  320. crowsDst = (UINT) (*pprowsDst)->cRows; // handle 0
  321. if (FAILED(sc = m_pWABObject->AllocateBuffer(CbNewSRowSet(crowsSrc + crowsDst), (LPVOID*) &prowsT)))
  322. goto exit;
  323. if (crowsDst)
  324. CopyMemory(prowsT->aRow, (*pprowsDst)->aRow, crowsDst * sizeof(SRow));
  325. CopyMemory(&prowsT->aRow[crowsDst], prows->aRow, crowsSrc * sizeof(SRow));
  326. prowsT->cRows = crowsSrc + crowsDst;
  327. m_pWABObject->FreeBuffer(*pprowsDst);
  328. *pprowsDst = prowsT;
  329. exit:
  330. // if (prows)
  331. // m_pWABObject->FreeBuffer(&prows);
  332. return ResultFromScode(sc);
  333. }
  334. /*
  335. - HrQueryAllRows
  336. -
  337. * Purpose:
  338. * Retrieves all rows from an IMAPITable interface up to a set
  339. * maximum. It will optionally set the column set, sort order,
  340. * and restriction on the table before querying.
  341. *
  342. * If the table is empty, an SRowSet with zero rows is
  343. * returned (just like QueryRows).
  344. *
  345. * The seek position of the table is undefined both before and
  346. * after this call.
  347. *
  348. * If the function fails with an error other than
  349. * MAPI_E_NOT_ENOUGH_MEMORY, extended error information is
  350. * available through the table interface.
  351. *
  352. * Arguments:
  353. * ptable in the table interface to query
  354. * ptaga in if not NULL, column set for the table
  355. * pres in if not NULL, restriction to be applied
  356. * psos in if not NULL, sort order to be applied
  357. * crowsMax in if nonzero, limits the number of rows
  358. * to be returned.
  359. * pprows out all rows of the table
  360. *
  361. * Returns:
  362. * HRESULT. Extended error information normally is in the
  363. * table.
  364. *
  365. * Side effects:
  366. * Seek position of table is undefined.
  367. *
  368. * Errors:
  369. * MAPI_E_TABLE_TOO_BIG if the table contains more than
  370. * cRowsMax rows.
  371. */
  372. HRESULT CAddressBookData::_QueryAllRows(LPMAPITABLE ptable,
  373. LPSPropTagArray ptaga,
  374. LPSRestriction pres,
  375. LPSSortOrderSet psos,
  376. LONG crowsMax,
  377. LPSRowSet FAR *pprows)
  378. {
  379. HRESULT hr;
  380. LPSRowSet prows = NULL;
  381. UINT crows = 0;
  382. LPSRowSet prowsT=NULL;
  383. UINT crowsT;
  384. *pprows = NULL;
  385. // Set up the table, if the corresponding setup parameter is present.
  386. if (ptaga && FAILED(hr = ptable->SetColumns(ptaga, TBL_BATCH)))
  387. goto exit;
  388. if (pres && FAILED(hr = ptable->Restrict(pres, TBL_BATCH)))
  389. goto exit;
  390. if (psos && FAILED(hr = ptable->SortTable(psos, TBL_BATCH)))
  391. goto exit;
  392. // Set position to beginning of the table.
  393. if (FAILED(hr = ptable->SeekRow(BOOKMARK_BEGINNING, 0, NULL)))
  394. goto exit;
  395. if (crowsMax == 0)
  396. crowsMax = 0xffffffff;
  397. for (;;)
  398. {
  399. prowsT = NULL;
  400. // Retrieve some rows. Ask for the limit.
  401. hr = ptable->QueryRows(crowsMax, 0, &prowsT);
  402. if (FAILED(hr))
  403. {
  404. // Note: the failure may actually have happened during one of the
  405. // setup calls, since we set TBL_BATCH.
  406. goto exit;
  407. }
  408. _ASSERTE(prowsT->cRows <= 0xFFFFFFFF);
  409. crowsT = (UINT) prowsT->cRows;
  410. // Did we get more rows than caller can handle?
  411. if ((LONG) (crowsT + (prows ? prows->cRows : 0)) > crowsMax)
  412. {
  413. hr = ResultFromScode(MAPI_E_TABLE_TOO_BIG);
  414. //_FreeProws(prowsT);
  415. goto exit;
  416. }
  417. // Add the rows just retrieved into the set we're building.
  418. //
  419. // NOTE: this handles boundary conditions including either row set is
  420. // empty.
  421. //
  422. // NOTE: the merge destroys prowsT.
  423. if (FAILED(hr = _MergeRowSets(prowsT, &prows)))
  424. goto exit;
  425. // Did we hit the end of the table? Unfortunately, we have to ask twice
  426. // before we know.
  427. if (crowsT == 0)
  428. break;
  429. }
  430. if(prows->cRows != 0)
  431. *pprows = prows;
  432. exit:
  433. if (prowsT)
  434. _FreeProws(prowsT);
  435. if (FAILED(hr))
  436. _FreeProws(prows);
  437. return hr;
  438. }
  439. HRESULT CAddressBookData::_GetLDAPContainer(ULONG *pcbEntryID, LPENTRYID *ppEntryID)
  440. {
  441. ULONG ulObjectType = 0;
  442. IABContainer *pRoot = 0;
  443. LPMAPITABLE pRootTable = 0;
  444. HRESULT hr = S_OK;
  445. // Get the root Address Book container
  446. hr = m_pAdrBook->OpenEntry(0, NULL, NULL, 0, &ulObjectType, (LPUNKNOWN *) &pRoot);
  447. if (FAILED(hr))
  448. goto exit;
  449. // From the address book container, get a table of it's contents
  450. hr = pRoot->GetContentsTable(0, &pRootTable);
  451. if (FAILED(hr))
  452. goto exit;
  453. // Set the columns
  454. pRootTable->SetColumns((LPSPropTagArray) &irnColumns, 0);
  455. // Build a restriction to only display LDAP servers that we're supposed
  456. // to resolve against.
  457. SRestriction resAnd[2]; // 0 = LDAP, 1 = ResolveFlag
  458. SRestriction resLDAPResolve;
  459. SPropValue ResolveFlag;
  460. // Restrict: Only show LDAP containers with Resolve TRUE
  461. resAnd[0].rt = RES_EXIST;
  462. resAnd[0].res.resExist.ulReserved1 = 0;
  463. resAnd[0].res.resExist.ulReserved2 = 0;
  464. resAnd[0].res.resExist.ulPropTag = PR_WAB_LDAP_SERVER;
  465. ResolveFlag.ulPropTag = PR_WAB_RESOLVE_FLAG;
  466. ResolveFlag.Value.b = TRUE;
  467. resAnd[1].rt = RES_PROPERTY;
  468. resAnd[1].res.resProperty.relop = RELOP_EQ;
  469. resAnd[1].res.resProperty.ulPropTag = PR_WAB_RESOLVE_FLAG;
  470. resAnd[1].res.resProperty.lpProp = &ResolveFlag;
  471. resLDAPResolve.rt = RES_AND;
  472. resLDAPResolve.res.resAnd.cRes = 2;
  473. resLDAPResolve.res.resAnd.lpRes = resAnd;
  474. // Apply the restruction
  475. hr = pRootTable->Restrict(&resLDAPResolve, 0);
  476. if (HR_FAILED(hr))
  477. goto exit;
  478. // We're going to just blindly grab the first item in this table as the
  479. // LDAP container we're going to use.
  480. LPSRowSet pRowSet;
  481. hr = pRootTable->QueryRows(1, 0, &pRowSet);
  482. if (FAILED(hr))
  483. goto exit;
  484. // Grab the size of the entry id
  485. *pcbEntryID = pRowSet->aRow[0].lpProps[irnPR_ENTRYID].Value.bin.cb;
  486. // Make a copy of the entry id
  487. hr = m_pWABObject->AllocateBuffer(*pcbEntryID, (LPVOID *) ppEntryID);
  488. if (FAILED(hr))
  489. goto exit;
  490. CopyMemory(*ppEntryID, pRowSet->aRow[0].lpProps[irnPR_ENTRYID].Value.bin.lpb,
  491. *pcbEntryID);
  492. exit:
  493. if (pRootTable)
  494. pRootTable->Release();
  495. if (pRoot)
  496. pRoot->Release();
  497. if (pRowSet)
  498. _FreeProws(pRowSet);
  499. return (hr);
  500. }
  501. HRESULT CAddressBookData::_GetLDAPSearchRestriction(LPTSTR pszText, LPSRestriction lpSRes)
  502. {
  503. SRestriction SRes = { 0 };
  504. LPSRestriction lpPropRes = NULL;
  505. ULONG ulcPropCount = 0;
  506. HRESULT hr = E_FAIL;
  507. ULONG i = 0;
  508. SCODE sc = ERROR_SUCCESS;
  509. LPSPropValue lpPropArray = NULL;
  510. if (!lstrlen(pszText))
  511. {
  512. ATLTRACE(_T("No Search Props"));
  513. goto exit;
  514. }
  515. lpSRes->rt = RES_AND;
  516. lpSRes->res.resAnd.cRes = 1;
  517. // Allocate a buffer for the restriction
  518. lpSRes->res.resAnd.lpRes = NULL;
  519. sc = m_pWABObject->AllocateBuffer(1 * sizeof(SRestriction),
  520. (LPVOID *) &(lpSRes->res.resAnd.lpRes));
  521. if (S_OK != sc || !(lpSRes->res.resAnd.lpRes))
  522. {
  523. ATLTRACE("MAPIAllocateBuffer Failed");
  524. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  525. goto exit;
  526. }
  527. lpPropRes = lpSRes->res.resAnd.lpRes;
  528. // Create the first part of the OR clause
  529. lpPropRes[0].rt = RES_PROPERTY;
  530. lpPropRes[0].res.resProperty.relop = RELOP_EQ;
  531. lpPropRes[0].res.resProperty.ulPropTag = PR_EMAIL_ADDRESS;
  532. lpPropRes[0].res.resProperty.lpProp = NULL;
  533. m_pWABObject->AllocateMore(sizeof(SPropValue), lpPropRes, (LPVOID*) &(lpPropRes[0].res.resProperty.lpProp));
  534. lpPropArray = lpPropRes[0].res.resProperty.lpProp;
  535. if (!lpPropArray)
  536. {
  537. ATLTRACE("MAPIAllocateBuffer Failed");
  538. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  539. goto exit;
  540. }
  541. lpPropArray->ulPropTag = PR_EMAIL_ADDRESS;
  542. lpPropArray->Value.LPSZ = NULL;
  543. m_pWABObject->AllocateMore(lstrlen(pszText) + 1, lpPropRes, (LPVOID *) &(lpPropArray->Value.LPSZ));
  544. if (!lpPropArray->Value.LPSZ)
  545. {
  546. ATLTRACE("MAPIAllocateBuffer Failed");
  547. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  548. goto exit;
  549. }
  550. StrCpyN(lpPropArray->Value.LPSZ, pszText, lstrlen(pszText) + 1);
  551. #if 0
  552. // Add the second OR clause
  553. lpPropRes[1].rt = RES_PROPERTY;
  554. lpPropRes[1].res.resProperty.relop = RELOP_EQ;
  555. lpPropRes[1].res.resProperty.ulPropTag = PR_DISPLAY_NAME;
  556. lpPropRes[1].res.resProperty.lpProp = NULL;
  557. m_pWABObject->AllocateMore(sizeof(SPropValue), lpPropRes, (LPVOID*) &(lpPropRes[1].res.resProperty.lpProp));
  558. lpPropArray = lpPropRes[1].res.resProperty.lpProp;
  559. if (!lpPropArray)
  560. {
  561. ATLTRACE("MAPIAllocateBuffer Failed");
  562. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  563. goto exit;
  564. }
  565. lpPropArray->ulPropTag = PR_DISPLAY_NAME;
  566. lpPropArray->Value.LPSZ = NULL;
  567. m_pWABObject->AllocateMore(lstrlen(pszText) + 1, lpPropRes, (LPVOID *) &(lpPropArray->Value.LPSZ));
  568. if (!lpPropArray->Value.LPSZ)
  569. {
  570. ATLTRACE("MAPIAllocateBuffer Failed");
  571. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  572. goto exit;
  573. }
  574. StrCpyN(lpPropArray->Value.LPSZ, pszText, lstrlen(pszText) + 1);
  575. #endif
  576. hr = S_OK;
  577. exit:
  578. return hr;
  579. }
  580. HRESULT CAddressBookData::_GetLDAPContentsList(ULONG cbContainerEID,
  581. LPENTRYID pContainerEID,
  582. SORT_INFO rSortInfo,
  583. LPSRestriction pPropRes,
  584. CContainedWindow& ctlList)
  585. {
  586. HRESULT hr = S_OK;
  587. HRESULT hrTemp;
  588. ULONG ulObjectType = 0;
  589. LPMAPICONTAINER pContainer = NULL;
  590. LPMAPITABLE pContentsTable = NULL;
  591. LPSRowSet pSRowSet = NULL;
  592. // Open the container object corresponding to pContainerEID
  593. hr = m_pAdrBook->OpenEntry(cbContainerEID, pContainerEID, NULL, 0,
  594. &ulObjectType, (LPUNKNOWN *) &pContainer);
  595. if (FAILED(hr))
  596. goto exit;
  597. // Get the contents table from this container
  598. hr = pContainer->GetContentsTable(0, &pContentsTable);
  599. if (FAILED(hr))
  600. goto exit;
  601. // Order the columns in the ContentsTable to conform to the ones we want
  602. // - which are mainly DisplayName, EntryID and ObjectType. The table is
  603. // guaranteed to set the columns in the order requested.
  604. Assert(PR_MSGR_DEF_ID);
  605. ptaEid.aulPropTag[ieidPR_MSGR_DEF_ID] = PR_MSGR_DEF_ID;
  606. hr = pContentsTable->SetColumns((LPSPropTagArray) &ptaEid, 0);
  607. if(HR_FAILED(hr))
  608. goto exit;
  609. // Do the find
  610. hr = pContentsTable->FindRow(pPropRes, BOOKMARK_BEGINNING, 0);
  611. if (FAILED(hr))
  612. goto exit;
  613. // If this was a partial completion error, we want to continue but also
  614. // return this information to the caller
  615. if (MAPI_W_PARTIAL_COMPLETION == hr)
  616. hrTemp = hr;
  617. // If we got this far, we have a populated table. We can query the rows
  618. // now.
  619. hr = _QueryAllRows(pContentsTable, NULL, NULL, NULL, MAX_QUERY_SIZE, &pSRowSet);
  620. if (FAILED(hr) || !pSRowSet)
  621. goto exit;
  622. // Fill in the ListView from the table
  623. _FillListFromTable(ctlList, pSRowSet, TRUE);
  624. exit:
  625. if (pSRowSet)
  626. _FreeProws(pSRowSet);
  627. if (pContentsTable)
  628. pContentsTable->Release();
  629. if (pContainer)
  630. pContainer->Release();
  631. return (hr);
  632. }
  633. HRESULT CAddressBookData::_FillListFromTable(CContainedWindow& ctlList, LPSRowSet pSRowSet, BOOL bLDAP)
  634. {
  635. LPSBinary lpSB;
  636. // Make sure the caller passed us a rowset
  637. Assert(pSRowSet);
  638. Assert(PR_MSGR_DEF_ID);
  639. // Loop through the rows in the rowset
  640. for (ULONG i = 0; i < pSRowSet->cRows; i++)
  641. {
  642. // Get the information out of the table that we need. Right now we're
  643. // grabbing the entry ID, the display name, and the business phone number.
  644. LPENTRYID lpEID = (LPENTRYID) pSRowSet->aRow[i].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
  645. ULONG cbEID = pSRowSet->aRow[i].lpProps[ieidPR_ENTRYID].Value.bin.cb;
  646. DWORD nFlag = (pSRowSet->aRow[i].lpProps[ieidPR_OBJECT_TYPE].Value.l == MAPI_DISTLIST) ? MAB_GROUP : MAB_CONTACT;
  647. LPTSTR lpszID = NULL;
  648. LPTSTR lpszName = NULL;
  649. if(nFlag == MAB_CONTACT)
  650. {
  651. if(pSRowSet->aRow[i].lpProps[ieidPR_USER_X509_CERTIFICATE].ulPropTag == PR_USER_X509_CERTIFICATE)
  652. nFlag |= MAB_CERT;
  653. }
  654. if(PROP_TYPE(pSRowSet->aRow[i].lpProps[ieidPR_MSGR_DEF_ID/*ieidPR_EMAIL_ADDRESS*/].ulPropTag) == PT_TSTRING )
  655. {
  656. nFlag = nFlag | MAB_BUDDY;
  657. lpszID = pSRowSet->aRow[i].lpProps[ieidPR_MSGR_DEF_ID/*ieidPR_EMAIL_ADDRESS*/].Value.lpszA;
  658. }
  659. else if(PROP_TYPE(pSRowSet->aRow[i].lpProps[ieidPR_EMAIL_ADDRESS].ulPropTag) == PT_TSTRING )
  660. lpszID = pSRowSet->aRow[i].lpProps[ieidPR_EMAIL_ADDRESS].Value.lpszA;
  661. else
  662. lpszID = NULL;
  663. if(PROP_TYPE(pSRowSet->aRow[i].lpProps[ieidPR_DISPLAY_NAME].ulPropTag) == PT_TSTRING )
  664. lpszName = pSRowSet->aRow[i].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
  665. else
  666. lpszName = lpszID;
  667. // LPTSTR lpszPhone = pSRowSet->aRow[i].lpProps[ieidPR_BUSINESS_TELEPHONE_NUMBER].Value.lpszA;
  668. // Allocate an ITEMINFO struct to store this information
  669. lpSB = NULL;
  670. m_pWABObject->AllocateBuffer(sizeof(SBinary), (LPVOID *) &lpSB);
  671. if (lpSB)
  672. {
  673. // Save the information we'll need later
  674. m_pWABObject->AllocateMore(cbEID, lpSB, (LPVOID *) &(lpSB->lpb));
  675. if (!lpSB->lpb)
  676. {
  677. m_pWABObject->FreeBuffer(lpSB);
  678. continue;
  679. }
  680. CopyMemory(lpSB->lpb, lpEID, cbEID);
  681. lpSB->cb = cbEID;
  682. // Create an item to add to the list
  683. m_pAB->CheckAndAddAbEntry(lpSB, lpszID, lpszName, nFlag);
  684. }
  685. }
  686. // Let's make sure the first item is selected
  687. // ListView_SetItemState(ctlList, 0, LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
  688. return (S_OK);
  689. }
  690. HRESULT CAddressBookData::NewContact(HWND hwndParent)
  691. {
  692. HRESULT hr;
  693. ULONG cbNewEntry;
  694. LPENTRYID pNewEntry;
  695. ULONG cbContainerID;
  696. LPENTRYID pContainerID = 0;
  697. if(!m_pAdrBook)
  698. return E_FAIL;
  699. hr = m_pAdrBook->GetPAB(&cbContainerID, &pContainerID);
  700. if (FAILED(hr))
  701. return(hr);
  702. hr = m_pAdrBook->NewEntry((ULONG_PTR) hwndParent, /*CREATE_CHECK_DUP_STRICT*/ 0, cbContainerID, pContainerID, 0, NULL,
  703. &cbNewEntry, &pNewEntry);
  704. return (hr);
  705. }
  706. // Add new (Msgr) contact to address book
  707. HRESULT CAddressBookData::AutoAddContact(TCHAR * pchName, TCHAR * pchID)
  708. {
  709. LPMAILUSER lpMailUser = NULL;
  710. ULONG ulcPropCount = 1;
  711. ULONG ulIndex = 0;
  712. LPSPropValue lpPropArray = NULL;
  713. SCODE sc;
  714. LPWSTR pwszName = NULL,
  715. pwszID = NULL;
  716. HRESULT hr = S_OK;
  717. if(!m_pAdrBook || !m_pWABObject)
  718. return(S_FALSE);
  719. // 1. Add entry to Address book
  720. pwszName = PszToUnicode(CP_ACP, pchName);
  721. if (!pwszName && (pchName && *pchName))
  722. {
  723. hr = E_OUTOFMEMORY;
  724. goto out;
  725. }
  726. pwszID = PszToUnicode(CP_ACP, pchID);
  727. if (!pwszID && (pchID && *pchID))
  728. {
  729. hr = E_OUTOFMEMORY;
  730. goto out;
  731. }
  732. hr = HrWABCreateEntry(m_pAdrBook,
  733. m_pWABObject,
  734. pwszName,
  735. pwszID,
  736. CREATE_CHECK_DUP_STRICT,
  737. &lpMailUser, KEEP_OPEN_READWRITE);
  738. if(SUCCEEDED(hr))
  739. {
  740. // 2. Set custom property: default address for buddy
  741. // Create a return prop array to pass back to the WAB
  742. sc = m_pWABObject->AllocateBuffer(sizeof(SPropValue),
  743. (LPVOID *)&lpPropArray);
  744. if (sc!=S_OK)
  745. goto out;
  746. int nLen = lstrlen(pchID);
  747. if(nLen)
  748. {
  749. lpPropArray[0].ulPropTag = MsgrPropTags[0];
  750. sc = m_pWABObject->AllocateMore(nLen+1, lpPropArray,
  751. (LPVOID *)&(lpPropArray[0].Value.LPSZ));
  752. if (sc!=S_OK)
  753. goto out;
  754. StrCpyN(lpPropArray[0].Value.LPSZ, pchID, nLen+1);
  755. }
  756. // Set this new data on the object
  757. //
  758. if(lpMailUser)
  759. {
  760. hr = lpMailUser->SetProps(1, lpPropArray, NULL);
  761. if(SUCCEEDED(hr))
  762. hr = lpMailUser->SaveChanges(FORCE_SAVE);
  763. }
  764. }
  765. out:
  766. MemFree(pwszName);
  767. MemFree(pwszID);
  768. if(lpPropArray)
  769. m_pWABObject->FreeBuffer(lpPropArray);
  770. if(lpMailUser)
  771. ReleaseObj(lpMailUser);
  772. return(hr);
  773. }
  774. // Unicode string property version of template array
  775. SizedSPropTagArray(6, ptaAddr_W) =
  776. {
  777. 6,
  778. {
  779. PR_ADDRTYPE_W,
  780. PR_DISPLAY_NAME_W,
  781. PR_EMAIL_ADDRESS_W,
  782. PR_ENTRYID,
  783. PR_CONTACT_EMAIL_ADDRESSES_W, //4
  784. PR_SEARCH_KEY
  785. }
  786. };
  787. // ANSI string property version of template array
  788. SizedSPropTagArray(6, ptaAddr_A) =
  789. {
  790. 6,
  791. {
  792. PR_ADDRTYPE_A,
  793. PR_DISPLAY_NAME_A,
  794. PR_EMAIL_ADDRESS_A,
  795. PR_ENTRYID,
  796. PR_CONTACT_EMAIL_ADDRESSES_A,
  797. PR_SEARCH_KEY
  798. }
  799. };
  800. HRESULT CAddressBookData::AddRecipient(LPMIMEADDRESSTABLEW pAddrTable, LPSBinary pSB, BOOL fGroup)
  801. {
  802. HRESULT hr;
  803. ULONG ulType = 0;
  804. IMailUser *pMailUser = 0;
  805. ULONG cValues;
  806. SPropValue *pPropArray = 0;
  807. ULONG ulObjType = 0;
  808. LPMAPITABLE lpAB = NULL;
  809. LPABCONT lpContainer = NULL;
  810. ULONG lpcbEID;
  811. LPENTRYID lpEID = NULL;
  812. // Retrieve the item from the wab
  813. hr = m_pAdrBook->OpenEntry(pSB->cb, (LPENTRYID) pSB->lpb, NULL,
  814. MAPI_BEST_ACCESS, &ulType, (IUnknown **) &pMailUser);
  815. if (FAILED(hr))
  816. goto exit;
  817. // Get the appropriate properties from the object
  818. hr = pMailUser->GetProps((SPropTagArray *) &ptaAddr_W, 0, &cValues, &pPropArray);
  819. if (FAILED(hr))
  820. goto exit;
  821. // Set those badboys on the address table
  822. if(pPropArray[2].ulPropTag == PR_EMAIL_ADDRESS_W)
  823. pAddrTable->AppendW(IAT_TO, IET_DECODED, pPropArray[2].Value.lpszW, NULL , NULL);
  824. else if(pPropArray[4].ulPropTag == PR_CONTACT_EMAIL_ADDRESSES_W)
  825. pAddrTable->AppendW(IAT_TO, IET_DECODED, pPropArray[4].Value.MVszW.lppszW[0], NULL , NULL);
  826. else if((pPropArray[1].ulPropTag == PR_DISPLAY_NAME_W) && fGroup)
  827. pAddrTable->AppendW(IAT_TO, IET_DECODED, pPropArray[1].Value.lpszW, NULL , NULL);
  828. // Bug 34077 - they don't want to have a display name...
  829. /* else if(pPropArray[1].ulPropTag == PR_DISPLAY_NAME)
  830. pAddrTable->Append(IAT_TO, IET_DECODED, pPropArray[1].Value.lpszA, NULL , NULL);
  831. else
  832. Assert(FALSE); */
  833. exit:
  834. if (pPropArray)
  835. m_pWABObject->FreeBuffer(pPropArray);
  836. SafeRelease(pMailUser);
  837. return (hr);
  838. }
  839. HRESULT CAddressBookData::SetDefaultMsgrID(LPSBinary pSB, LPTSTR pchID)
  840. {
  841. ULONG ulType = 0;
  842. IMailUser *lpMailUser = 0;
  843. LPSPropValue lpPropArray = NULL;
  844. SCODE sc;
  845. HRESULT hr = m_pAdrBook->OpenEntry(pSB->cb, (LPENTRYID) pSB->lpb, NULL,
  846. MAPI_BEST_ACCESS, &ulType, (IUnknown **) &lpMailUser);
  847. if (FAILED(hr))
  848. goto exit;
  849. if(SUCCEEDED(hr))
  850. {
  851. // 2. Set custom property: default address for buddy
  852. // Create a return prop array to pass back to the WAB
  853. sc = m_pWABObject->AllocateBuffer(sizeof(SPropValue),
  854. (LPVOID *)&lpPropArray);
  855. if (sc!=S_OK)
  856. goto exit;
  857. int nLen = lstrlen(pchID);
  858. if(nLen)
  859. {
  860. lpPropArray[0].ulPropTag = MsgrPropTags[0];
  861. sc = m_pWABObject->AllocateMore(nLen+1, lpPropArray,
  862. (LPVOID *)&(lpPropArray[0].Value.LPSZ));
  863. if (sc!=S_OK)
  864. goto exit;
  865. StrCpyN(lpPropArray[0].Value.LPSZ, pchID, nLen+1);
  866. }
  867. // Set this new data on the object
  868. //
  869. if(lpMailUser)
  870. {
  871. hr = lpMailUser->SetProps(1, lpPropArray, NULL);
  872. if(SUCCEEDED(hr))
  873. hr = lpMailUser->SaveChanges(FORCE_SAVE);
  874. }
  875. }
  876. exit:
  877. if(lpPropArray)
  878. m_pWABObject->FreeBuffer(lpPropArray);
  879. SafeRelease(lpMailUser);
  880. return (hr);
  881. }
  882. HRESULT CAddressBookData::GetDisplayName(LPSBinary pSB, LPTSTR szDisplayName, int nMax)
  883. {
  884. ULONG ulType = 0;
  885. IMailUser *pMailUser = 0;
  886. ULONG cValues;
  887. SPropValue *pPropArray = 0;
  888. HRESULT hr = m_pAdrBook->OpenEntry(pSB->cb, (LPENTRYID) pSB->lpb, NULL,
  889. MAPI_BEST_ACCESS, &ulType, (IUnknown **) &pMailUser);
  890. if (FAILED(hr))
  891. goto exit;
  892. // Get the appropriate properties from the object
  893. hr = pMailUser->GetProps((SPropTagArray *) &ptaAddr_A, 0, &cValues, &pPropArray);
  894. if (FAILED(hr))
  895. goto exit;
  896. StrCpyN(szDisplayName, pPropArray[1].Value.lpszA, nMax);
  897. szDisplayName[nMax - 1] = _T('\0');
  898. exit:
  899. if (pPropArray)
  900. m_pWABObject->FreeBuffer(pPropArray);
  901. SafeRelease(pMailUser);
  902. return (hr);
  903. }
  904. BOOL CAddressBookData::CheckEmailAddr(LPSBinary pSB, LPTSTR szEmail)
  905. {
  906. ULONG ulType = 0;
  907. IMailUser *pMailUser = 0;
  908. ULONG cValues;
  909. SPropValue *pPropArray = 0;
  910. LPSPropValue lpPropMVEmail = NULL;
  911. UINT i = 0;
  912. BOOL fRet = FALSE;
  913. HRESULT hr = m_pAdrBook->OpenEntry(pSB->cb, (LPENTRYID) pSB->lpb, NULL,
  914. MAPI_BEST_ACCESS, &ulType, (IUnknown **) &pMailUser);
  915. if (FAILED(hr))
  916. goto exit;
  917. // Get the appropriate properties from the object
  918. hr = pMailUser->GetProps((SPropTagArray *) &ptaAddr_A, 0, &cValues, &pPropArray);
  919. if (FAILED(hr))
  920. goto exit;
  921. // 4 element is PR_CONTACT_EMAIL_ADDRESSES in ptaAddr
  922. lpPropMVEmail = &(pPropArray[4]);
  923. if(lpPropMVEmail && (lpPropMVEmail->ulPropTag == PR_CONTACT_EMAIL_ADDRESSES))
  924. {
  925. // we have a multiple emails
  926. //Assume, if this is present, so is MVAddrType, and defaultindex
  927. for(i = 0; i < lpPropMVEmail->Value.MVszA.cValues; i++)
  928. {
  929. if(!lstrcmpi(lpPropMVEmail->Value.MVszA.lppszA[i], szEmail))
  930. fRet = TRUE;
  931. }
  932. }
  933. exit:
  934. if (pPropArray)
  935. m_pWABObject->FreeBuffer(pPropArray);
  936. SafeRelease(pMailUser);
  937. return (fRet);
  938. }
  939. HRESULT CAddressBookData::FreeListViewItem(LPSBinary pSB)
  940. {
  941. if (pSB)
  942. m_pWABObject->FreeBuffer(pSB);
  943. return (S_OK);
  944. }
  945. HRESULT CAddressBookData::ShowDetails(HWND hwndParent, LPSBinary pSB)
  946. {
  947. HRESULT hr;
  948. ULONG_PTR ulUIParam = (ULONG_PTR) hwndParent;
  949. hr = m_pAdrBook->Details(&ulUIParam, NULL, NULL, pSB->cb, (LPENTRYID) pSB->lpb,
  950. NULL, NULL, NULL, 0);
  951. return (hr);
  952. }
  953. HRESULT CAddressBookData::AddAddress(LPWSTR pwszDisplay, LPSTR pszAddress)
  954. {
  955. HRESULT hr;
  956. LPABCONT pABContainer = NULL;
  957. ULONG cbContainerID,
  958. ul;
  959. LPENTRYID pContainerID = 0;
  960. LPMAPIPROP lpProps = 0;
  961. SPropValue rgpv[3];
  962. SPropTagArray ptaEID = { 1, { PR_ENTRYID } };
  963. LPSPropValue ppvDefMailUser=0;
  964. SizedSPropTagArray(1, ptaDefMailUser) =
  965. { 1, { PR_DEF_CREATE_MAILUSER } };
  966. DWORD cUsedValues;
  967. // Get the entry ID for the PAB
  968. hr = m_pAdrBook->GetPAB(&cbContainerID, &pContainerID);
  969. if (FAILED(hr))
  970. goto error;
  971. // Request the container
  972. hr = m_pAdrBook->OpenEntry(cbContainerID, pContainerID, NULL,
  973. 0, &ul, (LPUNKNOWN *) &pABContainer);
  974. Assert(ul == MAPI_ABCONT);
  975. if (FAILED(hr))
  976. goto error;
  977. // Free the entry ID
  978. m_pWABObject->FreeBuffer(pContainerID);
  979. // Get the properties for the default mail template
  980. hr = pABContainer->GetProps((LPSPropTagArray) &ptaDefMailUser, 0, &ul, &ppvDefMailUser);
  981. if (FAILED(hr) || !ppvDefMailUser || ppvDefMailUser->ulPropTag != PR_DEF_CREATE_MAILUSER)
  982. goto error;
  983. // Create a new entry
  984. hr=pABContainer->CreateEntry(ppvDefMailUser->Value.bin.cb,
  985. (LPENTRYID) ppvDefMailUser->Value.bin.lpb,
  986. CREATE_CHECK_DUP_STRICT, &lpProps);
  987. if (FAILED(hr))
  988. goto error;
  989. // Fill in the properties for the display name and address
  990. rgpv[0].ulPropTag = PR_DISPLAY_NAME_W;
  991. rgpv[0].Value.lpszW = pwszDisplay;
  992. rgpv[1].ulPropTag = PR_EMAIL_ADDRESS;
  993. rgpv[1].Value.lpszA = pszAddress;
  994. cUsedValues = 2;
  995. // Set those props on the entry
  996. hr = lpProps->SetProps(cUsedValues, rgpv, NULL);
  997. if (FAILED(hr))
  998. goto error;
  999. // Save 'em
  1000. hr = lpProps->SaveChanges(KEEP_OPEN_READONLY);
  1001. if (FAILED(hr))
  1002. goto error;
  1003. error:
  1004. ReleaseObj(lpProps);
  1005. ReleaseObj(pABContainer);
  1006. if (ppvDefMailUser)
  1007. m_pWABObject->FreeBuffer(ppvDefMailUser);
  1008. return hr;
  1009. }
  1010. HRESULT CAddressBookData::DeleteItems(ENTRYLIST *pList)
  1011. {
  1012. ULONG ulObjType = 0;
  1013. LPABCONT lpContainer = NULL;
  1014. HRESULT hr = E_FAIL;
  1015. ULONG lpcbEID;
  1016. LPENTRYID lpEID = NULL;
  1017. // Get the entryid of the root PAB container
  1018. hr = m_pAdrBook->GetPAB(&lpcbEID, &lpEID);
  1019. // Open the root PAB container. This is where all the WAB contents reside.
  1020. ulObjType = 0;
  1021. hr = m_pAdrBook->OpenEntry(lpcbEID,
  1022. (LPENTRYID)lpEID,
  1023. NULL,
  1024. 0,
  1025. &ulObjType,
  1026. (LPUNKNOWN *) &lpContainer);
  1027. m_pWABObject->FreeBuffer(lpEID);
  1028. lpEID = NULL;
  1029. // Delete those items
  1030. lpContainer->DeleteEntries(pList, 0);
  1031. lpContainer->Release();
  1032. return (S_OK);
  1033. }
  1034. HRESULT CAddressBookData::Find(HWND hwndParent)
  1035. {
  1036. m_pWABObject->Find(m_pAdrBook, hwndParent);
  1037. return (S_OK);
  1038. }
  1039. HRESULT CAddressBookData::NewGroup(HWND hwndParent)
  1040. {
  1041. HRESULT hr;
  1042. ULONG cbNewEntry = 0;
  1043. LPENTRYID pNewEntry = 0;
  1044. LPENTRYID pTplEid;
  1045. ULONG cbTplEid;
  1046. hr = _GetWABTemplateID(MAPI_DISTLIST, &cbTplEid, &pTplEid);
  1047. if (SUCCEEDED(hr))
  1048. {
  1049. hr = m_pAdrBook->NewEntry((ULONG_PTR) hwndParent, 0, 0, NULL, cbTplEid, pTplEid, &cbNewEntry, &pNewEntry);
  1050. Assert(pTplEid);
  1051. m_pWABObject->FreeBuffer(pTplEid);
  1052. }
  1053. return (hr);
  1054. }
  1055. HRESULT CAddressBookData::AddressBook(HWND hwndParent)
  1056. {
  1057. CWab *pWab = NULL;
  1058. if (SUCCEEDED(HrCreateWabObject(&pWab)))
  1059. {
  1060. pWab->HrBrowse(hwndParent);
  1061. pWab->Release();
  1062. }
  1063. else
  1064. {
  1065. AthMessageBoxW(hwndParent, MAKEINTRESOURCEW(idsAthena), MAKEINTRESOURCEW(idsGeneralWabError),
  1066. NULL, MB_OK | MB_ICONEXCLAMATION);
  1067. }
  1068. return (S_OK);
  1069. }
  1070. HRESULT CAddressBookData::_GetWABTemplateID(ULONG ulObjectType, ULONG *lpcbEID, LPENTRYID *lppEID)
  1071. {
  1072. LPABCONT lpContainer = NULL;
  1073. HRESULT hr = S_OK;
  1074. SCODE sc = ERROR_SUCCESS;
  1075. ULONG ulObjType = 0;
  1076. ULONG cbWABEID = 0;
  1077. LPENTRYID lpWABEID = NULL;
  1078. LPSPropValue lpCreateEIDs = NULL;
  1079. LPSPropValue lpNewProps = NULL;
  1080. ULONG cNewProps;
  1081. ULONG nIndex;
  1082. if ((!m_pAdrBook) || ((ulObjectType != MAPI_MAILUSER) && (ulObjectType != MAPI_DISTLIST)) )
  1083. {
  1084. hr = MAPI_E_INVALID_PARAMETER;
  1085. goto out;
  1086. }
  1087. *lpcbEID = 0;
  1088. *lppEID = NULL;
  1089. if (FAILED(hr = m_pAdrBook->GetPAB(&cbWABEID, &lpWABEID)))
  1090. {
  1091. goto out;
  1092. }
  1093. if (HR_FAILED(hr = m_pAdrBook->OpenEntry(cbWABEID, // size of EntryID to open
  1094. lpWABEID, // EntryID to open
  1095. NULL, // interface
  1096. 0, // flags
  1097. &ulObjType,
  1098. (LPUNKNOWN *) &lpContainer)))
  1099. {
  1100. goto out;
  1101. }
  1102. // Get us the default creation entryids
  1103. if (FAILED(hr = lpContainer->GetProps((LPSPropTagArray) &ptaCreate,
  1104. 0, &cNewProps, &lpCreateEIDs)))
  1105. {
  1106. goto out;
  1107. }
  1108. // Validate the properites
  1109. if (lpCreateEIDs[icrPR_DEF_CREATE_MAILUSER].ulPropTag != PR_DEF_CREATE_MAILUSER ||
  1110. lpCreateEIDs[icrPR_DEF_CREATE_DL].ulPropTag != PR_DEF_CREATE_DL)
  1111. {
  1112. goto out;
  1113. }
  1114. if (ulObjectType == MAPI_DISTLIST)
  1115. nIndex = icrPR_DEF_CREATE_DL;
  1116. else
  1117. nIndex = icrPR_DEF_CREATE_MAILUSER;
  1118. *lpcbEID = lpCreateEIDs[nIndex].Value.bin.cb;
  1119. m_pWABObject->AllocateBuffer(*lpcbEID, (LPVOID *) lppEID);
  1120. if (sc != S_OK)
  1121. {
  1122. hr = MAPI_E_NOT_ENOUGH_MEMORY;
  1123. goto out;
  1124. }
  1125. CopyMemory(*lppEID,lpCreateEIDs[nIndex].Value.bin.lpb,*lpcbEID);
  1126. out:
  1127. if (lpCreateEIDs)
  1128. m_pWABObject->FreeBuffer(lpCreateEIDs);
  1129. if (lpContainer)
  1130. lpContainer->Release();
  1131. if (lpWABEID)
  1132. m_pWABObject->FreeBuffer(lpWABEID);
  1133. return hr;
  1134. }
  1135. /*//$$****************************************************************
  1136. //
  1137. // InitNamedProps
  1138. //
  1139. // Gets the PropTags for the Named Props this app is interested in
  1140. //
  1141. //********************************************************************/
  1142. HRESULT CAddressBookData::InitNamedProps(/*LPWABEXTDISPLAY lpWED*/)
  1143. {
  1144. ULONG i;
  1145. HRESULT hr = E_FAIL;
  1146. LPSPropTagArray lptaMsgrProps = NULL;
  1147. LPMAPINAMEID * lppMsgrPropNames;
  1148. SCODE sc;
  1149. // LPMAILUSER lpMailUser = NULL;
  1150. WCHAR szBuf[msgrMax][MAX_PATH];
  1151. /* if(!lpWED)
  1152. goto err;
  1153. lpMailUser = (LPMAILUSER) lpWED->lpPropObj;
  1154. if(!lpMailUser)
  1155. goto err; */
  1156. sc = m_pWABObject->AllocateBuffer(sizeof(LPMAPINAMEID) * msgrMax,
  1157. (LPVOID *) &lppMsgrPropNames);
  1158. if(sc)
  1159. {
  1160. hr = ResultFromScode(sc);
  1161. goto err;
  1162. }
  1163. for(i=0;i<msgrMax;i++)
  1164. {
  1165. sc = m_pWABObject->AllocateMore(sizeof(MAPINAMEID),
  1166. lppMsgrPropNames,
  1167. (LPVOID *)&(lppMsgrPropNames[i]));
  1168. if(sc)
  1169. {
  1170. hr = ResultFromScode(sc);
  1171. goto err;
  1172. }
  1173. lppMsgrPropNames[i]->lpguid = (LPGUID) &WAB_ExtBAGuid;
  1174. lppMsgrPropNames[i]->ulKind = MNID_STRING;
  1175. *(szBuf[i]) = '\0';
  1176. // Convert prop name to wide-char
  1177. if ( !MultiByteToWideChar( GetACP(), 0, lpMsgrPropNames[i], -1, szBuf[i], ARRAYSIZE(szBuf[i]) ))
  1178. {
  1179. continue;
  1180. }
  1181. lppMsgrPropNames[i]->Kind.lpwstrName = (LPWSTR) szBuf[i];
  1182. }
  1183. hr = m_pAdrBook->GetIDsFromNames( msgrMax,
  1184. lppMsgrPropNames,
  1185. MAPI_CREATE,
  1186. &lptaMsgrProps);
  1187. if(HR_FAILED(hr))
  1188. goto err;
  1189. if(lptaMsgrProps)
  1190. {
  1191. // Set the property types on the returned props
  1192. MsgrPropTags[MsgrID] = PR_MSGR_DEF_ID = CHANGE_PROP_TYPE(lptaMsgrProps->aulPropTag[MsgrID], PT_TSTRING);
  1193. }
  1194. err:
  1195. if(lptaMsgrProps)
  1196. m_pWABObject->FreeBuffer( lptaMsgrProps);
  1197. if(lppMsgrPropNames)
  1198. m_pWABObject->FreeBuffer( lppMsgrPropNames);
  1199. return hr;
  1200. }