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.

716 lines
24 KiB

  1. // File: wabutil.cpp
  2. //
  3. // Generic Windows Address Book utility functions
  4. #include "precomp.h"
  5. #include "wabutil.h"
  6. #include "wabtags.h"
  7. #include "wabiab.h"
  8. #include <confguid.h> // for CLSID_ConferenceManager
  9. static const TCHAR _szCallToWab[] = TEXT("callto://"); // the prefix for NM WAB entries
  10. static const TCHAR g_pcszSMTP[] = TEXT("SMTP"); // value for PR_ADDRTYPE
  11. // see rgData in CreateWabEntry
  12. static const int IENTRYPROP_NM_DEFAULT = 5;
  13. static const int IENTRYPROP_NM_ADDRESS = 6;
  14. // REVIEW: There should be an external header file for these.
  15. // They are documented in http://fbi/wabapi.htm
  16. // DEFINE_OLEGUID(PS_Conferencing, 0x00062004, 0, 0);
  17. static const GUID PS_Conferencing = {0x00062004, 0, 0, {0xC0,0,0,0,0,0,0,0x46} };
  18. /////////////////////////////////////////////////////////////////////
  19. static const SizedSPropTagArray(ieidMax, ptaEid)=
  20. {
  21. ieidMax,
  22. {
  23. PR_ENTRYID,
  24. PR_DISPLAY_NAME,
  25. PR_NM_ADDRESS,
  26. PR_NM_DEFAULT,
  27. PR_NM_CATEGORY
  28. }
  29. };
  30. static const SizedSPropTagArray(1, ptaEidOnly)=
  31. {
  32. 1, {PR_ENTRYID}
  33. };
  34. enum {
  35. icrPR_DEF_CREATE_MAILUSER = 0,
  36. icrMax
  37. };
  38. static const SizedSPropTagArray(icrMax, ptaCreate) =
  39. {
  40. icrMax,
  41. {
  42. PR_DEF_CREATE_MAILUSER,
  43. }
  44. };
  45. /////////////////////////////////////////////////////////////////////
  46. //
  47. // Dynamic WAB interface
  48. const static TCHAR _szWABRegPathKey[] = TEXT("Software\\Microsoft\\WAB\\DLLPath");
  49. const static TCHAR _szWABDll[] = TEXT("WAB32DLL.dll");
  50. const static char _szWABOpen[] = "WABOpen";
  51. class WABDLL
  52. {
  53. private:
  54. static HINSTANCE m_hInstLib;
  55. static LPWABOPEN m_pfnWABOpen;
  56. protected:
  57. WABDLL();
  58. ~WABDLL() {};
  59. public:
  60. static HRESULT WABOpen(LPADRBOOK FAR *, LPWABOBJECT FAR *, LPWAB_PARAM, DWORD);
  61. };
  62. LPWABOPEN WABDLL::m_pfnWABOpen = NULL;
  63. HINSTANCE WABDLL::m_hInstLib = NULL;
  64. HRESULT WABDLL::WABOpen(LPADRBOOK FAR * lppAdrBook, LPWABOBJECT FAR * lppWABObject,
  65. LPWAB_PARAM lpWP, DWORD dwReserved)
  66. {
  67. if (NULL == m_pfnWABOpen)
  68. {
  69. HKEY hKey;
  70. TCHAR szPath[MAX_PATH];
  71. if (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  72. _szWABRegPathKey, 0, KEY_READ, &hKey))
  73. {
  74. // Probably don't have IE4 installed
  75. lstrcpy(szPath, _szWABDll);
  76. }
  77. else
  78. {
  79. DWORD dwType = 0;
  80. DWORD cbData = sizeof(szPath); // the size in BYTES
  81. RegQueryValueEx(hKey, g_cszEmpty, NULL, &dwType, (LPBYTE) szPath, &cbData);
  82. RegCloseKey(hKey);
  83. if (FEmptySz(szPath))
  84. return E_NOINTERFACE;
  85. }
  86. m_hInstLib = LoadLibrary(szPath);
  87. if (NULL == m_hInstLib)
  88. return E_NOINTERFACE;
  89. m_pfnWABOpen = (LPWABOPEN) GetProcAddress(m_hInstLib, _szWABOpen);
  90. if (NULL == m_pfnWABOpen)
  91. {
  92. FreeLibrary(m_hInstLib);
  93. return E_NOINTERFACE;
  94. }
  95. }
  96. return m_pfnWABOpen(lppAdrBook, lppWABObject, lpWP, dwReserved);
  97. }
  98. ///////////////////////////////////////////////////////////////////////////
  99. /* C W A B U T I L */
  100. /*-------------------------------------------------------------------------
  101. %%Function: CWABUTIL
  102. -------------------------------------------------------------------------*/
  103. CWABUTIL::CWABUTIL() :
  104. m_pAdrBook(NULL),
  105. m_pWabObject(NULL),
  106. m_pContainer(NULL),
  107. m_pPropTags(NULL),
  108. m_fTranslatedTags(FALSE)
  109. {
  110. // Make a copy of the property data
  111. m_pPropTags = (LPSPropTagArray) new BYTE[sizeof(ptaEid)];
  112. if (NULL != m_pPropTags)
  113. {
  114. CopyMemory(m_pPropTags, &ptaEid, sizeof(ptaEid));
  115. WABDLL::WABOpen(&m_pAdrBook, &m_pWabObject, NULL, 0);
  116. }
  117. }
  118. CWABUTIL::~CWABUTIL()
  119. {
  120. delete m_pPropTags;
  121. if (NULL != m_pContainer)
  122. {
  123. m_pContainer->Release();
  124. }
  125. if (NULL != m_pWabObject)
  126. {
  127. m_pWabObject->Release();
  128. }
  129. if (NULL != m_pAdrBook)
  130. {
  131. m_pAdrBook->Release();
  132. }
  133. }
  134. /* P S Z S K I P C A L L T O */
  135. /*-------------------------------------------------------------------------
  136. %%Function: PszSkipCallTo
  137. Return a pointer after the "callto://" string.
  138. -------------------------------------------------------------------------*/
  139. LPCTSTR CWABUTIL::PszSkipCallTo(LPCTSTR psz)
  140. {
  141. ASSERT(!FEmptySz(psz));
  142. TCHAR szTemp[CCHMAX(_szCallToWab)];
  143. lstrcpyn(szTemp, psz, CCHMAX(szTemp)); // FUTURE: Use StrCmpNI
  144. if (0 == lstrcmpi(szTemp, _szCallToWab))
  145. {
  146. psz += CCHMAX(_szCallToWab)-1;
  147. }
  148. return psz;
  149. }
  150. BOOL CWABUTIL::FCreateCallToSz(LPCTSTR pszServer, LPCTSTR pszEmail, LPTSTR pszDest, UINT cchMax)
  151. {
  152. if ((lstrlen(pszServer) + lstrlen(pszEmail) + CCHMAX(_szCallToWab)) >= cchMax)
  153. return FALSE; // it won't fix
  154. // This has the format: "callto://server/[email protected]"
  155. wsprintf(pszDest, TEXT("%s%s/%s"), _szCallToWab, pszServer, pszEmail);
  156. ASSERT(lstrlen(pszDest) < (int) cchMax);
  157. return TRUE;
  158. }
  159. ULONG CWABUTIL::Get_PR_NM_ADDRESS(void)
  160. {
  161. ASSERT(m_fTranslatedTags);
  162. return m_pPropTags->aulPropTag[ieidPR_NM_ADDRESS];
  163. }
  164. ULONG CWABUTIL::Get_PR_NM_DEFAULT(void)
  165. {
  166. ASSERT(m_fTranslatedTags);
  167. return m_pPropTags->aulPropTag[ieidPR_NM_DEFAULT];
  168. }
  169. ULONG CWABUTIL::Get_PR_NM_CATEGORY(void)
  170. {
  171. ASSERT(m_fTranslatedTags);
  172. return m_pPropTags->aulPropTag[ieidPR_NM_CATEGORY];
  173. }
  174. /* F R E E P R O W S */
  175. /*-------------------------------------------------------------------------
  176. %%Function: FreeProws
  177. -------------------------------------------------------------------------*/
  178. VOID CWABUTIL::FreeProws(LPSRowSet prows)
  179. {
  180. if (NULL == prows)
  181. return;
  182. for (ULONG irow = 0; irow < prows->cRows; irow++)
  183. {
  184. m_pWabObject->FreeBuffer(prows->aRow[irow].lpProps);
  185. }
  186. m_pWabObject->FreeBuffer(prows);
  187. }
  188. /* G E T C O N T A I N E R */
  189. /*-------------------------------------------------------------------------
  190. %%Function: GetContainer
  191. -------------------------------------------------------------------------*/
  192. HRESULT CWABUTIL::GetContainer(void)
  193. {
  194. if (NULL != m_pContainer)
  195. return S_OK;
  196. ASSERT(NULL != m_pWabObject);
  197. ASSERT(NULL != m_pAdrBook);
  198. // get the entryid for the WAB
  199. ULONG cbEID;
  200. LPENTRYID lpEID;
  201. HRESULT hr = m_pAdrBook->GetPAB(&cbEID, &lpEID);
  202. if (SUCCEEDED(hr))
  203. {
  204. // use the entryid to get the container
  205. ULONG ulObjType = 0;
  206. hr = m_pAdrBook->OpenEntry(cbEID, lpEID, NULL, 0,
  207. &ulObjType, (LPUNKNOWN *)&m_pContainer);
  208. m_pWabObject->FreeBuffer(lpEID);
  209. }
  210. return hr;
  211. }
  212. /* E N S U R E P R O P T A G S */
  213. /*-------------------------------------------------------------------------
  214. %%Function: EnsurePropTags
  215. Ensure the special property tags are available.
  216. -------------------------------------------------------------------------*/
  217. HRESULT CWABUTIL::EnsurePropTags(void)
  218. {
  219. if (m_fTranslatedTags)
  220. return S_OK;
  221. ASSERT(NULL != m_pContainer);
  222. LPSRowSet pRowSet = NULL;
  223. LPMAPITABLE pAB = NULL;
  224. // get the WAB contents
  225. HRESULT hr = m_pContainer->GetContentsTable(0, &pAB);
  226. if (FAILED(hr))
  227. {
  228. return hr; // probably empty
  229. }
  230. if ((SUCCEEDED(hr = pAB->SetColumns((LPSPropTagArray)&ptaEidOnly, 0))) &&
  231. (SUCCEEDED(hr = pAB->SeekRow(BOOKMARK_BEGINNING, 0, NULL))) &&
  232. (SUCCEEDED(hr = pAB->QueryRows(1, 0, &pRowSet))) &&
  233. (NULL != pRowSet) )
  234. {
  235. if (0 != pRowSet->cRows)
  236. {
  237. LPMAPIPROP pMapiProp = NULL;
  238. ULONG ulObjType = 0;
  239. hr = m_pContainer->OpenEntry(pRowSet->aRow[0].lpProps[0].Value.bin.cb,
  240. (LPENTRYID) pRowSet->aRow[0].lpProps[0].Value.bin.lpb,
  241. NULL, // the object's standard i/f
  242. 0, // flags
  243. &ulObjType,
  244. (LPUNKNOWN *)&pMapiProp);
  245. if (SUCCEEDED(hr))
  246. {
  247. hr = GetNamedPropsTag(pMapiProp, m_pPropTags);
  248. }
  249. if (NULL != pMapiProp)
  250. {
  251. pMapiProp->Release();
  252. }
  253. }
  254. FreeProws(pRowSet);
  255. }
  256. if (NULL != pAB)
  257. {
  258. pAB->Release();
  259. }
  260. return hr;
  261. }
  262. // Use this version when no m_pContainer is available
  263. HRESULT CWABUTIL::EnsurePropTags(LPMAPIPROP pMapiProp)
  264. {
  265. if (m_fTranslatedTags)
  266. return S_OK;
  267. return GetNamedPropsTag(pMapiProp, m_pPropTags);
  268. }
  269. /* G E T N A M E D P R O P S T A G */
  270. /*-------------------------------------------------------------------------
  271. %%Function: GetNamedPropsTag
  272. Translate the named properties into their proper values
  273. -------------------------------------------------------------------------*/
  274. HRESULT CWABUTIL::GetNamedPropsTag(LPMAPIPROP pMapiProp, LPSPropTagArray pProps)
  275. {
  276. ASSERT(!m_fTranslatedTags);
  277. ASSERT(NULL != pMapiProp);
  278. ASSERT(NULL != pProps);
  279. int iProp;
  280. int cProps = pProps->cValues; // total number of property tags
  281. ASSERT(0 != cProps);
  282. int iName;
  283. int cNames = 0; // The number of named tags to translate
  284. for (iProp = 0; iProp < cProps; iProp++)
  285. {
  286. if (0 != (PROP_ID(pProps->aulPropTag[iProp]) & 0x8000))
  287. {
  288. cNames++;
  289. }
  290. }
  291. ASSERT(0 != cNames);
  292. // allocate memory for the named props pointers array
  293. int cb = sizeof(LPMAPINAMEID) * cNames;
  294. LPMAPINAMEID * pNameIds = (LPMAPINAMEID *) new BYTE[cb];
  295. if (NULL == pNameIds)
  296. return E_OUTOFMEMORY;
  297. ZeroMemory(pNameIds, cb);
  298. // run through the prop tag array and build a MAPINAMEID for each prop tag
  299. HRESULT hr = S_OK;
  300. iName = 0;
  301. for (iProp = 0; iProp < cProps; iProp++)
  302. {
  303. ULONG ulTag = pProps->aulPropTag[iProp];
  304. if (0 != (PROP_ID(ulTag) & 0x8000))
  305. {
  306. pNameIds[iName] = new MAPINAMEID;
  307. if (NULL == pNameIds[iName])
  308. {
  309. hr = E_OUTOFMEMORY;
  310. break;
  311. }
  312. // Either Outlook public or NetMeeting private tag
  313. BOOL fPrivate = 0 != (PROP_ID(ulTag) & NM_TAG_MASK);
  314. GUID * pGuid = (GUID *) (fPrivate ? &CLSID_ConferenceManager : &PS_Conferencing);
  315. pNameIds[iName]->lpguid = pGuid;
  316. pNameIds[iName]->ulKind = MNID_ID;
  317. pNameIds[iName]->Kind.lID = PROP_ID(ulTag);
  318. iName++;
  319. }
  320. }
  321. if (SUCCEEDED(hr))
  322. {
  323. LPSPropTagArray pta = NULL;
  324. // get the named props "real" tags
  325. hr = pMapiProp->GetIDsFromNames(cNames, pNameIds, MAPI_CREATE, &pta);
  326. if (SUCCEEDED(hr))
  327. {
  328. if (NULL == pta)
  329. {
  330. hr = E_FAIL;
  331. }
  332. else
  333. {
  334. // replace the named tags with the real tags in the passed in prop tag array,
  335. // maintaining the types.
  336. ULONG * pul = &pta->aulPropTag[0];
  337. for (iProp = 0; iProp < cProps; iProp++)
  338. {
  339. ULONG ulTag = pProps->aulPropTag[iProp];
  340. if (0 != (PROP_ID(ulTag) & 0x8000))
  341. {
  342. // set the property types on the returned props
  343. pProps->aulPropTag[iProp] = CHANGE_PROP_TYPE(*pul++, PROP_TYPE(ulTag));
  344. }
  345. }
  346. m_pWabObject->FreeBuffer(pta);
  347. }
  348. }
  349. }
  350. // Cleanup
  351. if (NULL != pNameIds)
  352. {
  353. for (iName = 0; iName < cNames; iName++)
  354. {
  355. delete pNameIds[iName];
  356. }
  357. delete [] pNameIds;
  358. }
  359. m_fTranslatedTags = SUCCEEDED(hr);
  360. return hr;
  361. }
  362. /* H R G E T W A B T E M P L A T E I D */
  363. /*-------------------------------------------------------------------------
  364. %%Function: HrGetWABTemplateID
  365. Gets the WABs default Template ID for MailUsers or DistLists.
  366. These Template IDs are needed for creating new mailusers and distlists.
  367. -------------------------------------------------------------------------*/
  368. HRESULT CWABUTIL::HrGetWABTemplateID(ULONG * lpcbEID, LPENTRYID * lppEID)
  369. {
  370. *lpcbEID = 0;
  371. *lppEID = NULL;
  372. if (NULL == m_pAdrBook)
  373. {
  374. return E_INVALIDARG;
  375. }
  376. ASSERT(NULL != m_pWabObject);
  377. ULONG cbWABEID;
  378. LPENTRYID lpWABEID;
  379. HRESULT hr = m_pAdrBook->GetPAB(&cbWABEID, &lpWABEID);
  380. if (FAILED(hr))
  381. return hr;
  382. LPABCONT lpContainer = NULL;
  383. ULONG ulObjectType = MAPI_MAILUSER;
  384. hr = m_pAdrBook->OpenEntry(cbWABEID, lpWABEID, NULL, 0,
  385. &ulObjectType, (LPUNKNOWN *)&lpContainer);
  386. if (SUCCEEDED(hr))
  387. {
  388. ULONG cNewProps;
  389. LPSPropValue lpCreateEIDs = NULL;
  390. // Get the default creation entryids
  391. hr = lpContainer->GetProps((LPSPropTagArray)&ptaCreate, 0, &cNewProps, &lpCreateEIDs);
  392. if (S_OK == hr)
  393. {
  394. // Validate the properites
  395. if (lpCreateEIDs[icrPR_DEF_CREATE_MAILUSER].ulPropTag == PR_DEF_CREATE_MAILUSER)
  396. {
  397. ULONG nIndex = icrPR_DEF_CREATE_MAILUSER;
  398. *lpcbEID = lpCreateEIDs[nIndex].Value.bin.cb;
  399. if (S_OK == m_pWabObject->AllocateBuffer(*lpcbEID, (LPVOID *) lppEID))
  400. {
  401. CopyMemory(*lppEID,lpCreateEIDs[nIndex].Value.bin.lpb,*lpcbEID);
  402. }
  403. }
  404. }
  405. if (NULL != lpCreateEIDs)
  406. {
  407. m_pWabObject->FreeBuffer(lpCreateEIDs);
  408. }
  409. }
  410. if (NULL != lpContainer)
  411. {
  412. lpContainer->Release();
  413. }
  414. if (NULL != lpWABEID)
  415. {
  416. m_pWabObject->FreeBuffer(lpWABEID);
  417. }
  418. return hr;
  419. }
  420. /* C R E A T E N E W E N T R Y */
  421. /*-------------------------------------------------------------------------
  422. %%Function: CreateNewEntry
  423. -------------------------------------------------------------------------*/
  424. HRESULT CWABUTIL::CreateNewEntry(HWND hwndParent, ULONG cProps, SPropValue * pProps)
  425. {
  426. ULONG cbEID;
  427. LPENTRYID lpEID;
  428. ULONG cbTplEID;
  429. LPENTRYID lpTplEID;
  430. // Get the template id which is needed to create the new object
  431. HRESULT hr = HrGetWABTemplateID(&cbTplEID, &lpTplEID);
  432. if (FAILED(hr))
  433. return hr;
  434. // get the entryid for the WAB
  435. hr = m_pAdrBook->GetPAB(&cbEID, &lpEID);
  436. if (FAILED(hr))
  437. return hr;
  438. // use the entryid to get the container
  439. ULONG ulObjType = 0;
  440. LPABCONT pContainer = NULL;
  441. hr = m_pAdrBook->OpenEntry(cbEID, lpEID, NULL, 0, &ulObjType, (LPUNKNOWN *)&pContainer);
  442. m_pWabObject->FreeBuffer(lpEID);
  443. if (SUCCEEDED(hr))
  444. {
  445. LPMAPIPROP pMapiProp = NULL;
  446. hr = pContainer->CreateEntry(cbTplEID, lpTplEID, CREATE_CHECK_DUP_LOOSE, &pMapiProp);
  447. if (SUCCEEDED(hr))
  448. {
  449. if (PR_NM_ADDRESS == m_pPropTags->aulPropTag[ieidPR_NM_ADDRESS])
  450. {
  451. GetNamedPropsTag(pMapiProp, m_pPropTags);
  452. }
  453. (pProps+IENTRYPROP_NM_DEFAULT)->ulPropTag = m_pPropTags->aulPropTag[ieidPR_NM_DEFAULT];
  454. (pProps+IENTRYPROP_NM_ADDRESS)->ulPropTag = m_pPropTags->aulPropTag[ieidPR_NM_ADDRESS];
  455. LPSPropProblemArray pErr = NULL;
  456. hr = pMapiProp->SetProps(cProps, pProps, &pErr);
  457. if (SUCCEEDED(hr))
  458. {
  459. hr = pMapiProp->SaveChanges(FORCE_SAVE);
  460. // Show the new entry
  461. if (SUCCEEDED(hr))
  462. {
  463. ULONG cProp1;
  464. LPSPropValue pPropEid;
  465. hr = pMapiProp->GetProps((LPSPropTagArray)&ptaEidOnly, 0, &cProp1, &pPropEid);
  466. if (S_OK == hr)
  467. {
  468. hr = m_pAdrBook->Details((LPULONG) &hwndParent, NULL, NULL,
  469. pPropEid->Value.bin.cb,
  470. (LPENTRYID) pPropEid->Value.bin.lpb,
  471. NULL, NULL, NULL, DIALOG_MODAL);
  472. }
  473. if (S_OK != hr)
  474. {
  475. // There was a problem, delete the entry
  476. ENTRYLIST eList;
  477. eList.cValues = 1;
  478. eList.lpbin = (LPSBinary) &pPropEid->Value.bin;
  479. pContainer->DeleteEntries(&eList, 0);
  480. }
  481. m_pWabObject->FreeBuffer(pPropEid);
  482. }
  483. }
  484. else
  485. {
  486. // How could this ever fail?
  487. m_pWabObject->FreeBuffer(pErr);
  488. }
  489. pMapiProp->Release();
  490. }
  491. }
  492. if (NULL != pContainer)
  493. {
  494. pContainer->Release();
  495. }
  496. return hr;
  497. }
  498. /* C R E A T E W A B E N T R Y */
  499. /*-------------------------------------------------------------------------
  500. %%Function: CreateWabEntry
  501. -------------------------------------------------------------------------*/
  502. HRESULT CWABUTIL::_CreateWabEntry(HWND hwndParent, LPCTSTR pszDisplay, LPCTSTR pszFirst, LPCTSTR pszLast,
  503. LPCTSTR pszEmail, LPCTSTR pszLocation, LPCTSTR pszPhoneNum, LPCTSTR pszComments,
  504. LPCTSTR pszCallTo)
  505. {
  506. // These must be non-null
  507. ASSERT(!FEmptySz(pszDisplay));
  508. ASSERT(!FEmptySz(pszEmail));
  509. SPropValue rgData[13]; // maximum number of properties
  510. ZeroMemory(rgData, sizeof(rgData));
  511. rgData[0].ulPropTag = PR_DISPLAY_NAME;
  512. rgData[0].Value.lpszA = const_cast<LPTSTR>(pszDisplay);
  513. rgData[1].ulPropTag = PR_GIVEN_NAME;
  514. rgData[1].Value.lpszA = const_cast<LPTSTR>(pszFirst);
  515. rgData[2].ulPropTag = PR_SURNAME;
  516. rgData[2].Value.lpszA = const_cast<LPTSTR>(pszLast);
  517. rgData[3].ulPropTag = PR_EMAIL_ADDRESS;
  518. rgData[3].Value.lpszA = const_cast<LPTSTR>(pszEmail);
  519. rgData[4].ulPropTag = PR_ADDRTYPE;
  520. rgData[4].Value.lpszA = (LPSTR) g_pcszSMTP;
  521. // There is only one default server
  522. ASSERT(5 == IENTRYPROP_NM_DEFAULT);
  523. // LPSPropTagArray pPropTags = pWab->GetTags(); // Translated tags
  524. //rgData[IENTRYPROP_NM_DEFAULT].ulPropTag = pPropTags->aulPropTag[ieidPR_NM_DEFAULT];
  525. rgData[IENTRYPROP_NM_DEFAULT].Value.ul = 0;
  526. ASSERT(6 == IENTRYPROP_NM_ADDRESS);
  527. //rgData[IENTRYPROP_NM_ADDRESS].ulPropTag = pPropTags->aulPropTag[ieidPR_NM_ADDRESS];
  528. rgData[IENTRYPROP_NM_ADDRESS].Value.MVszA.cValues = 1;
  529. rgData[IENTRYPROP_NM_ADDRESS].Value.MVszA.lppszA = const_cast<LPTSTR*>(&pszCallTo);
  530. // Add any other non-null properties
  531. SPropValue * pProp = &rgData[7];
  532. if (!FEmptySz(pszLocation))
  533. {
  534. pProp->ulPropTag = PR_LOCALITY;
  535. pProp->Value.lpszA = const_cast<LPTSTR>(pszLocation);
  536. pProp++;
  537. }
  538. if (!FEmptySz(pszPhoneNum))
  539. {
  540. pProp->ulPropTag = PR_BUSINESS_TELEPHONE_NUMBER;
  541. pProp->Value.lpszA = const_cast<LPTSTR>(pszPhoneNum);
  542. pProp++;
  543. }
  544. if (!FEmptySz(pszComments))
  545. {
  546. pProp->ulPropTag = PR_COMMENT;
  547. pProp->Value.lpszA = const_cast<LPTSTR>(pszComments);
  548. pProp++;
  549. }
  550. ULONG cProp = (ULONG)(pProp - rgData);
  551. ASSERT(cProp <= ARRAY_ELEMENTS(rgData));
  552. return CreateNewEntry(hwndParent, cProp, rgData);
  553. }
  554. /* C R E A T E W A B E N T R Y */
  555. /*-------------------------------------------------------------------------
  556. %%Function: CreateWabEntry
  557. -------------------------------------------------------------------------*/
  558. HRESULT CWABUTIL::CreateWabEntry(HWND hwndParent, LPCTSTR pszDisplay,
  559. LPCTSTR pszFirst, LPCTSTR pszLast, LPCTSTR pszEmail, LPCTSTR pszLocation,
  560. LPCTSTR pszPhoneNum, LPCTSTR pszComments, LPCTSTR pszServer)
  561. {
  562. // This has the format: "callto://server/[email protected]"
  563. TCHAR szCallTo[MAX_PATH*2];
  564. LPTSTR pszCallTo = szCallTo;
  565. if (!FCreateCallToSz(pszServer, pszEmail, szCallTo, CCHMAX(szCallTo)))
  566. return E_OUTOFMEMORY;
  567. return _CreateWabEntry(hwndParent, pszDisplay, pszFirst, pszLast,
  568. pszEmail, pszLocation, pszPhoneNum, pszComments, pszCallTo);
  569. }
  570. /* C R E A T E W A B E N T R Y */
  571. /*-------------------------------------------------------------------------
  572. %%Function: CreateWabEntry
  573. -------------------------------------------------------------------------*/
  574. HRESULT CWABUTIL::CreateWabEntry(HWND hwndParent,
  575. LPCTSTR pszDisplay, LPCTSTR pszEmail,
  576. LPCTSTR pszLocation, LPCTSTR pszPhoneNum, LPCTSTR pszULSAddress)
  577. {
  578. // This has the format: "callto://server/[email protected]"
  579. TCHAR szCallTo[MAX_PATH*2];
  580. LPTSTR pszCallTo = szCallTo;
  581. if ((lstrlen(pszULSAddress) + CCHMAX(_szCallToWab)) >= CCHMAX(szCallTo))
  582. return E_FAIL; // it won't fit
  583. wsprintf(szCallTo, TEXT("%s%s"), _szCallToWab, pszULSAddress);
  584. return _CreateWabEntry(hwndParent, pszDisplay, g_szEmpty, g_szEmpty,
  585. pszEmail, pszLocation, pszPhoneNum, g_szEmpty, pszCallTo);
  586. }