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.

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