Source code of Windows XP (NT5)
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.

454 lines
11 KiB

  1. // File: wab.cpp
  2. #include "precomp.h"
  3. #include "resource.h"
  4. #include "dirutil.h"
  5. #include "wab.h"
  6. #include "wabtags.h"
  7. #include "wabiab.h"
  8. #include "lst.h"
  9. #include "fnobjs.h"
  10. static const int _rgIdMenu[] = {
  11. IDM_DLGCALL_SPEEDDIAL,
  12. 0
  13. };
  14. // As of VC 6.0 on the Alpha, FreePsz couldn't be passed to a
  15. // template taking an F&. There is an internal compiler error
  16. // One day, this will be fixed. For now, this call should be
  17. // identical
  18. class FreePszFunctor
  19. {public:
  20. void operator()( LPTSTR sz ) { FreePsz( sz ); }
  21. };
  22. // There is only one instance of this object (for CreateWabEntry)
  23. CWAB * CWAB::m_spThis = NULL;
  24. /* C W A B */
  25. /*-------------------------------------------------------------------------
  26. %%Function: CWAB
  27. -------------------------------------------------------------------------*/
  28. CWAB::CWAB() :
  29. CALV(IDS_DLGCALL_WAB, II_WAB, _rgIdMenu)
  30. {
  31. DbgMsg(iZONE_OBJECTS, "CWAB - Constructed(%08X)", this);
  32. ASSERT(NULL == m_spThis);
  33. m_spThis = this;
  34. SetAvailable(NULL != m_pAdrBook);
  35. }
  36. CWAB::~CWAB()
  37. {
  38. m_spThis = NULL;
  39. DbgMsg(iZONE_OBJECTS, "CWAB - Destroyed(%08X)", this);
  40. }
  41. ///////////////////////////////////////////////////////////////////////////
  42. // CALV methods
  43. /* S H O W I T E M S */
  44. /*-------------------------------------------------------------------------
  45. %%Function: ShowItems
  46. -------------------------------------------------------------------------*/
  47. VOID CWAB::ShowItems(HWND hwnd)
  48. {
  49. CALV::SetHeader(hwnd, IDS_ADDRESS);
  50. ShowNmEntires(hwnd);
  51. }
  52. HRESULT CWAB::ShowNmEntires(HWND hwnd)
  53. {
  54. HRESULT hr;
  55. if (!FAvailable())
  56. return S_FALSE; // nothing to show
  57. hr = GetContainer();
  58. if (FAILED(hr))
  59. return hr;
  60. hr = EnsurePropTags();
  61. if (FAILED(hr))
  62. return hr;
  63. LPMAPITABLE pAB = NULL;
  64. hr = m_pContainer->GetContentsTable(0, &pAB);
  65. if (FAILED(hr) || (NULL == pAB))
  66. return hr;
  67. // reset the system to use the correct properties
  68. ASSERT(NULL != m_pPropTags);
  69. hr = pAB->SetColumns(GetTags(), 0);
  70. if (SUCCEEDED(hr))
  71. {
  72. // Read all the rows of the table one by one
  73. hr = pAB->SeekRow(BOOKMARK_BEGINNING, 0, NULL);
  74. }
  75. while (S_OK == hr)
  76. {
  77. LPSRowSet pRowAB = NULL;
  78. hr = pAB->QueryRows(1, 0, &pRowAB);
  79. if (FAILED(hr) || (NULL == pRowAB))
  80. break;
  81. int cNumRows = pRowAB->cRows;
  82. hr = (0 != cNumRows) ? S_OK : S_FALSE;
  83. if (S_OK == hr)
  84. {
  85. LPSPropValue lpProp = &(pRowAB->aRow[0].lpProps[ieidPR_NM_ADDRESS]);
  86. if (Get_PR_NM_ADDRESS() == lpProp->ulPropTag)
  87. {
  88. LPSTR pszName = pRowAB->aRow[0].lpProps[ieidPR_DISPLAY_NAME].Value.lpszA;
  89. SLPSTRArray * pMVszA = &(lpProp->Value.MVszA);
  90. if (0 != pMVszA->cValues)
  91. {
  92. // Find the default entry
  93. LPSPropValue lpPropDefault = &(pRowAB->aRow[0].lpProps[ieidPR_NM_DEFAULT]);
  94. ULONG iDefault = (Get_PR_NM_DEFAULT() == lpPropDefault->ulPropTag)
  95. ? lpPropDefault->Value.ul : 0;
  96. ASSERT(iDefault <= pMVszA->cValues);
  97. LPCTSTR pszAddr = pMVszA->lppszA[iDefault];
  98. pszAddr = PszSkipCallTo(pszAddr);
  99. // This trick will only work if the sizeof(LPARAM) == sizeof(LPENTRYID)
  100. LPARAM lParam;
  101. if (sizeof(LPARAM) == pRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.cb)
  102. {
  103. lParam = * (LPARAM *) pRowAB->aRow[0].lpProps[ieidPR_ENTRYID].Value.bin.lpb;
  104. }
  105. else
  106. {
  107. lParam = 0;
  108. }
  109. DlgCallAddItem(hwnd, pszName, pszAddr, II_WAB_CARD, lParam);
  110. }
  111. }
  112. }
  113. FreeProws(pRowAB);
  114. }
  115. pAB->Release();
  116. return hr;
  117. }
  118. /* C M D P R O P E R T I E S */
  119. /*-------------------------------------------------------------------------
  120. %%Function: CmdProperties
  121. -------------------------------------------------------------------------*/
  122. VOID CWAB::CmdProperties(void)
  123. {
  124. int iItem = GetSelection();
  125. if (-1 == iItem)
  126. return;
  127. LV_ITEM lvi;
  128. ClearStruct(&lvi);
  129. lvi.iItem = iItem;
  130. lvi.mask = LVIF_PARAM;
  131. if (!ListView_GetItem(GetHwnd(), &lvi))
  132. return;
  133. HWND hwnd = GetParent(GetHwnd());
  134. m_pAdrBook->Details((LPULONG) &hwnd, NULL, NULL,
  135. sizeof(LPARAM), (LPENTRYID) &lvi.lParam,
  136. NULL, NULL, NULL, 0);
  137. // this is because we may have changed something in the Details dlg.
  138. CmdRefresh();
  139. ListView_SetItemState(GetHwnd(), iItem,
  140. LVIS_FOCUSED | LVIS_SELECTED, LVIS_FOCUSED | LVIS_SELECTED);
  141. }
  142. /* G E T A D D R I N F O */
  143. /*-------------------------------------------------------------------------
  144. %%Function: GetAddrInfo
  145. -------------------------------------------------------------------------*/
  146. RAI * CWAB::GetAddrInfo(void)
  147. {
  148. RAI* pRai = NULL;
  149. lst<LPTSTR> PhoneNums;
  150. lst<LPTSTR> EmailNames;
  151. lst<LPTSTR> ILSServers;
  152. int iItem = GetSelection();
  153. if (-1 != iItem)
  154. {
  155. LV_ITEM lvi;
  156. ClearStruct(&lvi);
  157. lvi.iItem = iItem;
  158. lvi.mask = LVIF_PARAM;
  159. if (ListView_GetItem(GetHwnd(), &lvi))
  160. {
  161. LPMAPIPROP pMapiProp = NULL;
  162. ULONG ulObjType = 0;
  163. HRESULT hr = m_pContainer->OpenEntry( sizeof(LPARAM),
  164. reinterpret_cast<LPENTRYID>(&lvi.lParam),
  165. NULL,
  166. 0,
  167. &ulObjType,
  168. reinterpret_cast<LPUNKNOWN*>(&pMapiProp)
  169. );
  170. if (SUCCEEDED(hr))
  171. {
  172. // Email Name
  173. if (FEnabledNmAddr(NM_ADDR_ALIAS_ID))
  174. {
  175. ULONG PropTags[] = { PR_EMAIL_ADDRESS };
  176. _GetLPSTRProps( EmailNames, PropTags, pMapiProp, ARRAY_ELEMENTS( PropTags ) );
  177. }
  178. // Phone number
  179. if (FEnabledNmAddr(NM_ADDR_ALIAS_E164) || FEnabledNmAddr(NM_ADDR_H323_GATEWAY))
  180. {
  181. ULONG PhoneNumPropTags[] = {
  182. PR_BUSINESS_TELEPHONE_NUMBER,
  183. PR_HOME_TELEPHONE_NUMBER,
  184. PR_PRIMARY_TELEPHONE_NUMBER,
  185. PR_BUSINESS2_TELEPHONE_NUMBER,
  186. PR_CELLULAR_TELEPHONE_NUMBER,
  187. PR_RADIO_TELEPHONE_NUMBER,
  188. PR_CAR_TELEPHONE_NUMBER,
  189. PR_OTHER_TELEPHONE_NUMBER,
  190. PR_PAGER_TELEPHONE_NUMBER
  191. };
  192. _GetLPSTRProps( PhoneNums, PhoneNumPropTags, pMapiProp, ARRAY_ELEMENTS( PhoneNumPropTags ) );
  193. }
  194. if (FEnabledNmAddr(NM_ADDR_ULS))
  195. {
  196. enum { iPrNmAddress = 0, iDefaultServer = 1 };
  197. ULONG PropTags[2];
  198. PropTags[iPrNmAddress] = Get_PR_NM_ADDRESS();
  199. PropTags[iDefaultServer] = Get_PR_NM_DEFAULT();
  200. if( m_pWabObject )
  201. {
  202. BYTE* pb = new BYTE[ sizeof( SPropTagArray ) + sizeof( ULONG ) * ARRAY_ELEMENTS( PropTags ) ];
  203. if( pb )
  204. {
  205. // Fill in the prop tags that we are interested in...
  206. SPropTagArray* pProps = reinterpret_cast<SPropTagArray*>(pb);
  207. pProps->cValues = ARRAY_ELEMENTS(PropTags);
  208. for( UINT iCur = 0; iCur < pProps->cValues; iCur++ )
  209. {
  210. pProps->aulPropTag[iCur] = PropTags[iCur];
  211. }
  212. LPSPropValue pData = NULL;
  213. ULONG cValues = ARRAY_ELEMENTS(PropTags);
  214. if( SUCCEEDED( hr = pMapiProp->GetProps( pProps, 0, &cValues, &pData ) ) && pData )
  215. {
  216. // Get teh ILS Servers
  217. if( LOWORD( pData[iPrNmAddress].ulPropTag ) != PT_ERROR )
  218. {
  219. for( ULONG iCurVal = 0; iCurVal < pData[iPrNmAddress].Value.MVszA.cValues; ++iCurVal )
  220. {
  221. LPSTR pStr = pData[iPrNmAddress].Value.MVszA.lppszA[iCurVal];
  222. // Skip the callto://
  223. pStr = const_cast<LPSTR>(PszSkipCallTo(pStr));
  224. // Skip duplicate server names...
  225. if( !FEmptySz(pStr) && ( ILSServers.end() == find( ILSServers, IsEqLPTSTR( pStr ) ) ) )
  226. {
  227. ILSServers.push_back( PszAlloc( pStr ) );
  228. }
  229. }
  230. }
  231. // Get the default Server
  232. if( LOWORD( pData[iDefaultServer].ulPropTag ) != PT_ERROR )
  233. {
  234. // If the default server is not already in the front, put it there...
  235. if( pData[iDefaultServer].Value.l != 0 )
  236. {
  237. // Find the default server in the list
  238. lst<LPTSTR>::iterator I = ILSServers.begin();
  239. for( long lCur = 0; ( I != ILSServers.end() ) && ( lCur != pData[iDefaultServer].Value.l ); ++I, ++lCur )
  240. { ; }
  241. ASSERT( I != ILSServers.end() );
  242. LPTSTR pszDefault = *I;
  243. ILSServers.erase(I);
  244. ILSServers.push_front( pszDefault );
  245. }
  246. }
  247. m_pWabObject->FreeBuffer(pData);
  248. }
  249. delete [] pb;
  250. }
  251. else
  252. {
  253. hr = E_OUTOFMEMORY;
  254. }
  255. }
  256. else
  257. {
  258. hr = E_FAIL;
  259. }
  260. }
  261. if( PhoneNums.size() || EmailNames.size() || ILSServers.size() )
  262. {
  263. // Initialize the RAI struct
  264. int nItems = PhoneNums.size() + EmailNames.size() + ILSServers.size();
  265. DWORD cbLen = sizeof(RAI) + sizeof(DWSTR)* nItems;
  266. pRai = reinterpret_cast<RAI*>(new BYTE[ cbLen ]);
  267. ZeroMemory(pRai, cbLen);
  268. pRai->cItems = nItems;
  269. // This is the display name...
  270. GetSzName(pRai->szName, CCHMAX(pRai->szName), iItem);
  271. int iCur = 0;
  272. // First copy the e-mail names
  273. for( lst<LPTSTR>::iterator I = EmailNames.begin(); I != EmailNames.end(); ++I, ++iCur )
  274. {
  275. pRai->rgDwStr[iCur].dw = NM_ADDR_ALIAS_ID;
  276. pRai->rgDwStr[iCur].psz = PszAlloc(*I);
  277. }
  278. for_each( EmailNames, FreePszFunctor() );
  279. // Copy the phone numbirs
  280. for( I = PhoneNums.begin(); I != PhoneNums.end(); ++I, ++iCur )
  281. {
  282. pRai->rgDwStr[iCur].dw = g_fGkEnabled ? NM_ADDR_ALIAS_E164 : NM_ADDR_H323_GATEWAY;
  283. pRai->rgDwStr[iCur].psz = PszAlloc(*I);
  284. }
  285. for_each( PhoneNums, FreePszFunctor() );
  286. // Copy the ils servers
  287. for( I = ILSServers.begin(); I != ILSServers.end(); ++I, ++iCur )
  288. {
  289. pRai->rgDwStr[iCur].dw = NM_ADDR_ULS;
  290. pRai->rgDwStr[iCur].psz = PszAlloc(*I);
  291. }
  292. for_each( ILSServers, FreePszFunctor() );
  293. }
  294. pMapiProp->Release();
  295. }
  296. }
  297. }
  298. return pRai;
  299. }
  300. HRESULT CWAB::_GetLPSTRProps( lst<LPSTR>& rLst, ULONG* paPropTags, LPMAPIPROP pMapiProp, int nProps )
  301. {
  302. HRESULT hr = S_OK;
  303. if( m_pWabObject )
  304. {
  305. BYTE* pb = new BYTE[ sizeof( SPropTagArray ) + sizeof( ULONG ) * nProps ];
  306. if( pb )
  307. {
  308. // Fill in the prop tags that we are interested in...
  309. SPropTagArray* pProps = reinterpret_cast<SPropTagArray*>(pb);
  310. pProps->cValues = nProps;
  311. for( UINT iCur = 0; iCur < pProps->cValues; iCur++ )
  312. {
  313. pProps->aulPropTag[iCur] = paPropTags[iCur];
  314. }
  315. LPSPropValue pData = NULL;
  316. ULONG cValues = nProps;
  317. // Get the props
  318. if( SUCCEEDED( hr = pMapiProp->GetProps( pProps, 0, &cValues, &pData ) ) && pData )
  319. {
  320. // Extract thet props
  321. for( ULONG iCurVal = 0; iCurVal < cValues; ++iCurVal )
  322. {
  323. if( LOWORD( pData[iCurVal].ulPropTag ) != PT_ERROR )
  324. {
  325. if( !FEmptySz(pData[iCurVal].Value.lpszA) && ( rLst.end() == find( rLst, IsEqLPTSTR(
  326. #ifdef UNICODE
  327. pData[iCurVal].Value.lpszW
  328. #else
  329. pData[iCurVal].Value.lpszA
  330. #endif
  331. ) ) ) )
  332. {
  333. rLst.push_back( PszAlloc( pData[iCurVal].Value.lpszA ) );
  334. }
  335. }
  336. }
  337. m_pWabObject->FreeBuffer(pData);
  338. }
  339. delete [] pb;
  340. }
  341. else
  342. {
  343. hr = E_OUTOFMEMORY;
  344. }
  345. }
  346. else
  347. {
  348. hr = E_FAIL;
  349. }
  350. return hr;
  351. }
  352. /* C R E A T E W A B E N T R Y */
  353. /*-------------------------------------------------------------------------
  354. %%Function: CreateWabEntry
  355. -------------------------------------------------------------------------*/
  356. HRESULT CreateWabEntry(LPTSTR pszDisplay, LPTSTR pszFirst, LPTSTR pszLast,
  357. LPTSTR pszEmail, LPTSTR pszLocation, LPTSTR pszPhoneNumber, LPTSTR pszComments,
  358. LPTSTR pszServer)
  359. {
  360. CWAB * pWab = CWAB::GetInstance();
  361. if (NULL == pWab)
  362. return E_FAIL;
  363. HWND hwnd = GetParent(pWab->GetHwnd());
  364. return pWab->CreateWabEntry(hwnd, pszDisplay, pszFirst, pszLast, pszEmail,
  365. pszLocation, pszPhoneNumber, pszComments, pszServer);
  366. }