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.

1813 lines
50 KiB

  1. /***********************************************************************
  2. *
  3. * ABLOGON.C
  4. *
  5. *
  6. * The Microsoft At Work Fax Address Book Provider.
  7. *
  8. * This file has the code to implement the Microsoft At Work Fax Address Book's logon
  9. * object.
  10. *
  11. * The following routines are implemented in this file:
  12. *
  13. * ABPLOGON_QueryInterface
  14. * ABPLOGON_Release
  15. * ABPLOGON_Logoff
  16. * ABPLOGON_OpenEntry
  17. * ABPLOGON_CompareEntryIDs
  18. * ABPLOGON_Advise
  19. * ABPLOGON_Unadvise
  20. * ABPLOGON_OpenStatusEntry
  21. * ABPLOGON_OpenTemplateID
  22. * ABPLOGON_GetOneOffTable
  23. * ABPLOGON_PrepareRecips
  24. *
  25. * LpMuidFromLogon
  26. * HrLpszGetCurrentFileName
  27. * HrReplaceCurrentfileName
  28. * GenerateContainerDN
  29. * HrBuildRootHier
  30. *
  31. *
  32. * Copyright 1992, 1993, 1994 Microsoft Corporation. All Rights Reserved.
  33. *
  34. * Revision History:
  35. *
  36. * When Who What
  37. * -------- ------------------ ---------------------------------------
  38. * 8.3.94 MAPI Original source from MAPI sample ABP build 304
  39. * 8.3.94 Yoram Yaacovi Moved code from the FAX ABP original abp.c to here
  40. * 11.11.94 Yoram Yaacovi Upgrade to MAPI 318 (PR_INSTANCE_KEY)
  41. *
  42. ***********************************************************************/
  43. #include "faxab.h"
  44. ABPLOGON_Vtbl vtblABPLOGON =
  45. {
  46. ABPLOGON_QueryInterface,
  47. (ABPLOGON_AddRef_METHOD *) ROOT_AddRef,
  48. ABPLOGON_Release,
  49. (ABPLOGON_GetLastError_METHOD *) ROOT_GetLastError,
  50. ABPLOGON_Logoff,
  51. ABPLOGON_OpenEntry,
  52. ABPLOGON_CompareEntryIDs,
  53. ABPLOGON_Advise,
  54. ABPLOGON_Unadvise,
  55. ABPLOGON_OpenStatusEntry,
  56. ABPLOGON_OpenTemplateID,
  57. ABPLOGON_GetOneOffTable,
  58. ABPLOGON_PrepareRecips
  59. };
  60. /*
  61. - HrNewABLogon
  62. -
  63. *
  64. * Creates a new Microsoft At Work Fax AB Logon object.
  65. */
  66. HRESULT
  67. HrNewABLogon( LPABLOGON * lppABLogon,
  68. LPABPROVIDER lpABP,
  69. LPMAPISUP lpMAPISup,
  70. LPTSTR lpszFABFile,
  71. LPMAPIUID lpmuid,
  72. HINSTANCE hLibrary,
  73. LPALLOCATEBUFFER lpAllocBuff,
  74. LPALLOCATEMORE lpAllocMore,
  75. LPFREEBUFFER lpFreeBuff,
  76. LPMALLOC lpMalloc
  77. )
  78. {
  79. SCODE sc;
  80. HRESULT hResult = hrSuccess;
  81. SPropValue rgSPVStat[6];
  82. LPABPLOGON lpABPLogon = NULL;
  83. #ifdef UNICODE
  84. CHAR szFileName[ MAX_PATH ];
  85. #endif
  86. /*
  87. * Allocate space for the lpABPLogon object
  88. */
  89. sc = lpAllocBuff(SIZEOF(ABPLOGON), &lpABPLogon);
  90. if (FAILED(sc))
  91. {
  92. hResult = ResultFromScode(sc);
  93. goto out;
  94. }
  95. /*
  96. * Initialize the ABPLogon object
  97. */
  98. lpABPLogon->lpVtbl = &vtblABPLOGON;
  99. lpABPLogon->lcInit = 1;
  100. lpABPLogon->hResult = hrSuccess;
  101. lpABPLogon->idsLastError = 0;
  102. lpABPLogon->hLibrary = hLibrary;
  103. lpABPLogon->lpMalloc = lpMalloc;
  104. lpABPLogon->lpAllocBuff = lpAllocBuff;
  105. lpABPLogon->lpAllocMore = lpAllocMore;
  106. lpABPLogon->lpFreeBuff = lpFreeBuff;
  107. lpABPLogon->lpMapiSup = lpMAPISup;
  108. lpABPLogon->lpABP = (LPABPROVIDER) lpABP;
  109. lpABPLogon->lpszFileName = lpszFABFile;
  110. lpABPLogon->muidID = *lpmuid;
  111. lpABPLogon->lpTDatRoot = NULL;
  112. lpABPLogon->lpTDatOO = NULL;
  113. /*
  114. * Register my status row...
  115. */
  116. // MAPI doesn't use UNICODE for this one...
  117. rgSPVStat[0].ulPropTag = PR_DISPLAY_NAME_A;
  118. #ifdef UNICODE
  119. szFileName[0] = 0;
  120. WideCharToMultiByte( CP_ACP, 0, lpszFABFile, -1, szFileName, ARRAYSIZE(szFileName), NULL, NULL );
  121. rgSPVStat[0].Value.lpszA = szFileName;
  122. #else
  123. rgSPVStat[0].Value.lpszA = lpszFABFile;
  124. #endif
  125. rgSPVStat[1].ulPropTag = PR_RESOURCE_METHODS;
  126. rgSPVStat[1].Value.l = 0;
  127. rgSPVStat[2].ulPropTag = PR_RESOURCE_FLAGS;
  128. rgSPVStat[2].Value.l = 0;
  129. rgSPVStat[3].ulPropTag = PR_STATUS_CODE;
  130. rgSPVStat[3].Value.l = STATUS_AVAILABLE;
  131. // MAPI doesn't use UNICODE for this one
  132. rgSPVStat[4].ulPropTag = PR_STATUS_STRING_A;
  133. rgSPVStat[4].Value.lpszA = "Available";
  134. // MAPI doesn't use UNICODE for this one
  135. rgSPVStat[5].ulPropTag = PR_PROVIDER_DISPLAY_A;
  136. rgSPVStat[5].Value.lpszA = "Microsoft Fax Address Book Provider";
  137. /*
  138. * Set the Status Row for this provider,
  139. * but do not allow an error from setting the
  140. * status row to cause failure to Logon.
  141. */
  142. (void)lpMAPISup->lpVtbl->ModifyStatusRow(lpMAPISup,
  143. ARRAYSIZE(rgSPVStat), rgSPVStat, 0);
  144. /*
  145. * AddRef the support object, because we're keeping
  146. * a pointer to it in our Logon object.
  147. */
  148. lpMAPISup->lpVtbl->AddRef(lpMAPISup);
  149. /*
  150. * AddRef our parent ABInit object
  151. */
  152. lpABP->lpVtbl->AddRef(lpABP);
  153. InitializeCriticalSection(&lpABPLogon->cs);
  154. *lppABLogon = (LPABLOGON) lpABPLogon;
  155. out:
  156. DebugTraceResult(HrNewABPLogon, hResult);
  157. return hResult;
  158. }
  159. /*************************************************************************
  160. *
  161. - ABPLOGON_QueryInterface
  162. -
  163. */
  164. STDMETHODIMP
  165. ABPLOGON_QueryInterface( LPABPLOGON lpABPLogon,
  166. REFIID lpiid,
  167. LPVOID * ppvObj
  168. )
  169. {
  170. if ( IsBadReadPtr(lpiid, SIZEOF(IID)) ||
  171. IsBadWritePtr(ppvObj, SIZEOF(LPVOID))
  172. )
  173. {
  174. DebugTraceSc(ABPLOGON_QueryInterface, E_INVALIDARG);
  175. return ResultFromScode(E_INVALIDARG);
  176. }
  177. /* See if the requested interface is one of ours */
  178. if ( memcmp(lpiid, &IID_IUnknown, SIZEOF(IID)) &&
  179. memcmp(lpiid, &IID_IABLogon, SIZEOF(IID))
  180. )
  181. {
  182. *ppvObj = NULL; /* OLE requires zeroing [out] parameter on error */
  183. DebugTraceSc(ABPLOGON_QueryInterface, E_NOINTERFACE);
  184. return ResultFromScode(E_NOINTERFACE);
  185. }
  186. /* We'll do this one. Bump the usage count and return a new pointer. */
  187. EnterCriticalSection(&lpABPLogon->cs);
  188. ++lpABPLogon->lcInit;
  189. LeaveCriticalSection(&lpABPLogon->cs);
  190. *ppvObj = lpABPLogon;
  191. return hrSuccess;
  192. }
  193. /*
  194. * Use ROOTs AddRef
  195. */
  196. /*************************************************************************
  197. *
  198. - ABPLOGON_Release
  199. -
  200. */
  201. STDMETHODIMP_(ULONG)
  202. ABPLOGON_Release(LPABPLOGON lpABPLogon)
  203. {
  204. LONG lcInit;
  205. EnterCriticalSection(&lpABPLogon->cs);
  206. lcInit = --lpABPLogon->lcInit;
  207. LeaveCriticalSection(&lpABPLogon->cs);
  208. if (lcInit == 0)
  209. {
  210. DeleteCriticalSection(&lpABPLogon->cs);
  211. lpABPLogon->lpVtbl = NULL;
  212. lpABPLogon->lpFreeBuff(lpABPLogon);
  213. return (0);
  214. }
  215. return lcInit;
  216. }
  217. /*************************************************************************
  218. *
  219. - ABPLOGON_Logoff
  220. -
  221. * Logoff from this logon object. Clean up any resources/objects that
  222. * our logon object has accumulated.
  223. *
  224. *
  225. */
  226. STDMETHODIMP
  227. ABPLOGON_Logoff(LPABPLOGON lpABPLogon, ULONG ulFlags)
  228. {
  229. DebugTrace("AWFXAB32(ABPLOGON_Logoff): entering\n");
  230. #ifdef DO_WE_REALLY_NEED_TAPI
  231. /*
  232. * Let TAPI go
  233. */
  234. DeinitTAPI();
  235. #endif
  236. /*
  237. * Remove this logon object from the list of known
  238. * logon objects associated with this initialization
  239. * of this provider.
  240. */
  241. (void) RemoveLogonObject(lpABPLogon->lpABP, lpABPLogon, lpABPLogon->lpFreeBuff);
  242. /*
  243. * No longer need to be holding on to our parent
  244. */
  245. lpABPLogon->lpABP->lpVtbl->Release(lpABPLogon->lpABP);
  246. /*
  247. * Free up the file
  248. */
  249. lpABPLogon->lpFreeBuff(lpABPLogon->lpszFileName);
  250. if (lpABPLogon->lpTDatRoot)
  251. lpABPLogon->lpTDatRoot->lpVtbl->Release(lpABPLogon->lpTDatRoot);
  252. if (lpABPLogon->lpTDatOO)
  253. lpABPLogon->lpTDatOO->lpVtbl->Release(lpABPLogon->lpTDatOO);
  254. /*
  255. * very last thing I should do is release the support object
  256. */
  257. lpABPLogon->lpMapiSup->lpVtbl->Release(lpABPLogon->lpMapiSup);
  258. DebugTrace("AWFXAB32(ABPLOGON_Logoff): leaving\n");
  259. return hrSuccess;
  260. }
  261. /*************************************************************************
  262. *
  263. - ABPLOGON_OpenEntry
  264. -
  265. * Creates an object with (at least) the IMAPIProp interface from an
  266. * entryID.
  267. *
  268. * There are four valid types of entryIDs handled:
  269. *
  270. * NULL <- return back the root container object
  271. * DIR_ENTRYID <- return back the directory container object
  272. * USR_ENTRYID <- return back the MAILUSER object
  273. * OOUSER_ENTRYID <- return back the OneOff MAILUSER object
  274. *
  275. * Note: This call is reused for all other internal objects that support OpenEntry().
  276. * Those other calls *must* check their parameters before calling this method.
  277. * The only other way this method is called is via MAPI which does parameter checking
  278. * for us. The most we'll do here is assert our parameters.
  279. */
  280. STDMETHODIMP
  281. ABPLOGON_OpenEntry( LPABPLOGON lpABPLogon,
  282. ULONG cbEntryID,
  283. LPENTRYID lpEntryID,
  284. LPCIID lpInterface,
  285. ULONG ulFlags,
  286. ULONG * lpulObjType,
  287. LPUNKNOWN * lppUnk
  288. )
  289. {
  290. LPDIR_ENTRYID lpEID = (LPDIR_ENTRYID) lpEntryID;
  291. HRESULT hResult = hrSuccess;
  292. LPTSTR lpszFileName;
  293. /*
  294. * Check the EntryID
  295. */
  296. // used to be: if (!lpEntryID)
  297. if (!cbEntryID)
  298. {
  299. LPABCONT lpABCont = NULL;
  300. /*
  301. * Special case: the root level object
  302. */
  303. NFAssertSz(!lpEntryID, "Non-NULL entry id passed with 0 cb to OpenEntry()\n");
  304. /* Make this new object */
  305. /*
  306. * Get the current .FAB file name from our logon object
  307. */
  308. hResult = HrLpszGetCurrentFileName((LPABLOGON) lpABPLogon, &lpszFileName);
  309. if (HR_FAILED(hResult))
  310. goto out;
  311. // If there is a real Fax AB
  312. if ((fExposeFaxAB) &&
  313. (lpszFileName[0] != 0))
  314. hResult = HrNewROOT((LPABCONT *) lppUnk,
  315. lpulObjType,
  316. (LPABLOGON) lpABPLogon,
  317. lpInterface,
  318. lpABPLogon->hLibrary,
  319. lpABPLogon->lpAllocBuff,
  320. lpABPLogon->lpAllocMore,
  321. lpABPLogon->lpFreeBuff,
  322. lpABPLogon->lpMalloc);
  323. else
  324. // No Fax AB container
  325. return ResultFromScode (MAPI_E_INTERFACE_NOT_SUPPORTED);
  326. lpABPLogon->lpFreeBuff(lpszFileName);
  327. goto out;
  328. }
  329. /*
  330. * There's an entryID there, is it mine??
  331. * I need to check because I'm reusing this routine for
  332. * my Container->OpenEntry call, and I can't be sure the
  333. * client will always be well behaved.
  334. *
  335. * When this routine is called from MAPI, this call is redundant. But
  336. * because I'm reusing this routine, I gotta check.
  337. */
  338. /* Compare MAPIUIDs */
  339. if (memcmp(&(((LPDIR_ENTRYID) lpEntryID)->muid), &muidABMAWF,
  340. SIZEOF(MAPIUID)))
  341. {
  342. /*
  343. * Not mine!
  344. */
  345. hResult = ResultFromScode(MAPI_E_INVALID_ENTRYID);
  346. DebugTraceResult(ABPLOGON_OpenEntry, hResult);
  347. goto out;
  348. }
  349. /*
  350. * What object does this correspond to??
  351. */
  352. /* I've only got two types: containers and users */
  353. if (lpEID->ulType == MAWF_DIRECTORY)
  354. {
  355. LPABLOGON lpABPLogonT = NULL;
  356. /* entry id must have the same verson number */
  357. if (lpEID->ulVersion != MAWF_VERSION)
  358. {
  359. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  360. SetErrorIDS(lpABPLogon, hResult, IDS_OLD_EID);
  361. goto out;
  362. }
  363. /*
  364. * find the correct logon object for this entryid
  365. */
  366. (void) FindLogonObject(lpABPLogon->lpABP, &lpEID->muidID, &lpABPLogonT);
  367. /* did we find the corresponding logon object */
  368. if (!lpABPLogonT)
  369. {
  370. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  371. goto out;
  372. }
  373. // If I don't have a fab file at this point, I can't open the AB container
  374. HrLpszGetCurrentFileName((LPABLOGON) lpABPLogonT, &lpszFileName);
  375. if (lpszFileName[0] == 0)
  376. {
  377. hResult = ResultFromScode (MAPI_E_NO_SUPPORT);
  378. DebugTraceResult(ABPLOGON_OpenEntry, hResult);
  379. goto out;
  380. }
  381. hResult = HrNewFaxDirectory( (LPABCONT *) lppUnk,
  382. lpulObjType,
  383. (LPABLOGON) lpABPLogonT,
  384. lpInterface,
  385. lpABPLogon->hLibrary,
  386. lpABPLogon->lpAllocBuff,
  387. lpABPLogon->lpAllocMore,
  388. lpABPLogon->lpFreeBuff,
  389. lpABPLogon->lpMalloc);
  390. goto out;
  391. }
  392. if (lpEID->ulType == MAWF_USER)
  393. {
  394. if (cbEntryID == (ULONG) sizeof(USR_ENTRYID))
  395. {
  396. hResult = HrNewFaxUser( (LPMAILUSER *) lppUnk,
  397. lpulObjType,
  398. cbEntryID,
  399. lpEntryID,
  400. (LPABLOGON) lpABPLogon,
  401. lpInterface,
  402. lpABPLogon->hLibrary,
  403. lpABPLogon->lpAllocBuff,
  404. lpABPLogon->lpAllocMore,
  405. lpABPLogon->lpFreeBuff,
  406. lpABPLogon->lpMalloc);
  407. goto out;
  408. }
  409. }
  410. if (lpEID->ulType == MAWF_ONEOFF)
  411. {
  412. if (cbEntryID == (ULONG) sizeof(OOUSER_ENTRYID))
  413. {
  414. hResult = HrNewFaxOOUser( (LPMAILUSER *) lppUnk,
  415. lpulObjType,
  416. cbEntryID,
  417. lpEntryID,
  418. (LPABLOGON) lpABPLogon,
  419. lpInterface,
  420. lpABPLogon->hLibrary,
  421. lpABPLogon->lpAllocBuff,
  422. lpABPLogon->lpAllocMore,
  423. lpABPLogon->lpFreeBuff,
  424. lpABPLogon->lpMalloc);
  425. goto out;
  426. }
  427. }
  428. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  429. out:
  430. DebugTraceResult(ABPLOGON_OpenEntry, hResult);
  431. return hResult;
  432. }
  433. /*************************************************************************
  434. *
  435. - ABPLOGON_CompareEntryIDs
  436. -
  437. * If the two entryids are mine and they're of the same type, then
  438. * just do a binary comparison to see if they're equal.
  439. *
  440. */
  441. STDMETHODIMP
  442. ABPLOGON_CompareEntryIDs( LPABPLOGON lpABPLogon,
  443. ULONG cbEntryID1,
  444. LPENTRYID lpEntryID1,
  445. ULONG cbEntryID2,
  446. LPENTRYID lpEntryID2,
  447. ULONG ulFlags,
  448. ULONG * lpulResult
  449. )
  450. {
  451. LPDIR_ENTRYID lpEID1 = (LPDIR_ENTRYID) lpEntryID1;
  452. LPDIR_ENTRYID lpEID2 = (LPDIR_ENTRYID) lpEntryID2;
  453. HRESULT hResult = hrSuccess;
  454. /*
  455. * Check to see if their MUID is mine
  456. */
  457. if ( memcmp(&(lpEID1->muid), &muidABMAWF, SIZEOF(MAPIUID)) ||
  458. memcmp(&(lpEID2->muid), &muidABMAWF, SIZEOF(MAPIUID))
  459. )
  460. {
  461. /*
  462. * No recognition of these entryids.
  463. */
  464. *lpulResult = (ULONG) FALSE;
  465. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  466. goto out;
  467. }
  468. /*
  469. * See if the type of entryids are the same
  470. */
  471. if (lpEID1->ulType != lpEID2->ulType)
  472. {
  473. /*
  474. * They're not, so they don't match
  475. */
  476. *lpulResult = (ULONG) FALSE;
  477. goto out;
  478. }
  479. /*
  480. * See if the entryids are the same size. They'd better be
  481. * if they're the same type.
  482. */
  483. if (cbEntryID1 != cbEntryID2)
  484. {
  485. /*
  486. * They're not?!? Then I don't know these...
  487. */
  488. *lpulResult = (ULONG) FALSE;
  489. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  490. goto out;
  491. }
  492. /*
  493. * Check for Directory entryids
  494. */
  495. if (lpEID1->ulType == MAWF_DIRECTORY)
  496. {
  497. /*
  498. * Ok, I'm dealing with directory entryids
  499. */
  500. /*
  501. * Better make sure it's the right size
  502. */
  503. if (cbEntryID1 != sizeof(DIR_ENTRYID))
  504. {
  505. /*
  506. * This doesn't make sense. I don't recognize this entryid.
  507. */
  508. *lpulResult = (ULONG) FALSE;
  509. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  510. goto out;
  511. }
  512. /*
  513. * At this point it's just a memcmp
  514. */
  515. if (memcmp(lpEID1, lpEID2, SIZEOF(DIR_ENTRYID)))
  516. {
  517. /*
  518. * They're not equal
  519. */
  520. *lpulResult = (ULONG) FALSE;
  521. goto out;
  522. }
  523. /*
  524. * They must be the same
  525. */
  526. *lpulResult = (ULONG) TRUE;
  527. goto out;
  528. }
  529. if (lpEID1->ulType == MAWF_USER)
  530. {
  531. /*
  532. * Ok, I'm dealing with user entryids
  533. */
  534. /*
  535. * Better make sure it's the right size
  536. */
  537. if (cbEntryID1 != sizeof(USR_ENTRYID))
  538. {
  539. /*
  540. * This doesn't make sense. I don't recognize this entryid.
  541. */
  542. *lpulResult = (ULONG) FALSE;
  543. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  544. goto out;
  545. }
  546. /*
  547. * At this point it's just a memcmp
  548. */
  549. if (memcmp(lpEID1, lpEID2, SIZEOF(USR_ENTRYID)))
  550. {
  551. /*
  552. * They're not equal
  553. */
  554. *lpulResult = (ULONG) FALSE;
  555. goto out;
  556. }
  557. /*
  558. * They must be the same
  559. */
  560. *lpulResult = (ULONG) TRUE;
  561. goto out;
  562. }
  563. if (lpEID1->ulType == MAWF_ONEOFF)
  564. {
  565. /*
  566. * Ok, I'm dealing with oneoff user entryids
  567. */
  568. /*
  569. * Better make sure it's the right size
  570. */
  571. if (cbEntryID1 != SIZEOF(OOUSER_ENTRYID))
  572. {
  573. /*
  574. * This doesn't make sense. I don't recognize this entryid.
  575. */
  576. *lpulResult = (ULONG) FALSE;
  577. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  578. goto out;
  579. }
  580. /*
  581. * At this point it's just a memcmp
  582. */
  583. if (memcmp(lpEID1, lpEID2, SIZEOF(OOUSER_ENTRYID)))
  584. {
  585. /*
  586. * They're not equal
  587. */
  588. *lpulResult = (ULONG) FALSE;
  589. goto out;
  590. }
  591. /*
  592. * They must be the same
  593. */
  594. *lpulResult = (ULONG) TRUE;
  595. goto out;
  596. }
  597. /*
  598. * It's no entryid I know of
  599. */
  600. *lpulResult = (ULONG) FALSE;
  601. hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  602. out:
  603. DebugTraceResult(ABPLOGON_CompareEntryIDs, hResult);
  604. return hResult;
  605. }
  606. /*************************************************************************
  607. *
  608. - ABPLOGON_OpenStatusEntry
  609. -
  610. *
  611. *
  612. *
  613. */
  614. STDMETHODIMP
  615. ABPLOGON_OpenStatusEntry( LPABPLOGON lpABPLogon,
  616. LPCIID lpIID,
  617. ULONG ulFlags,
  618. ULONG FAR * lpulObjType,
  619. LPMAPISTATUS FAR * lppEntry
  620. )
  621. {
  622. HRESULT hr;
  623. /*
  624. * Validate Parameters
  625. */
  626. if ( IsBadReadPtr(lpABPLogon, (UINT) SIZEOF(ABPLOGON)) ||
  627. (lpIID && IsBadReadPtr(lpIID, (UINT) SIZEOF(IID))) ||
  628. IsBadWritePtr(lpulObjType, (UINT) SIZEOF(ULONG FAR *)) ||
  629. IsBadWritePtr(lppEntry, (UINT) SIZEOF(LPMAPISTATUS))
  630. )
  631. {
  632. DebugTraceSc(ABPLogon_OpenStatusEntry, E_INVALIDARG);
  633. return ResultFromScode(E_INVALIDARG);
  634. }
  635. hr = HrNewStatusObject( lppEntry,
  636. lpulObjType,
  637. ulFlags,
  638. (LPABLOGON) lpABPLogon,
  639. lpIID,
  640. lpABPLogon->hLibrary,
  641. lpABPLogon->lpAllocBuff,
  642. lpABPLogon->lpAllocMore,
  643. lpABPLogon->lpFreeBuff,
  644. lpABPLogon->lpMalloc);
  645. DebugTraceResult(ABPLOGON_OpenStatusEntry, hr);
  646. return hr;
  647. }
  648. /*************************************************************************
  649. *
  650. - ABPLOGON_OpenTemplateID
  651. -
  652. *
  653. *
  654. *
  655. */
  656. STDMETHODIMP
  657. ABPLOGON_OpenTemplateID( LPABPLOGON lpABPLogon,
  658. ULONG cbTemplateId,
  659. LPENTRYID lpTemplateId,
  660. ULONG ulTemplateFlags,
  661. LPMAPIPROP lpMAPIPropData,
  662. LPCIID lpInterface,
  663. LPMAPIPROP * lppMAPIPropNew,
  664. LPMAPIPROP lpMAPIPropSibling
  665. )
  666. {
  667. HRESULT hResult;
  668. /*
  669. * Validate Parameters
  670. */
  671. if ( IsBadReadPtr(lpABPLogon, (UINT) SIZEOF(ABPLOGON)) ||
  672. IsBadReadPtr(lpTemplateId, (UINT) cbTemplateId) ||
  673. IsBadReadPtr(lpMAPIPropData, (UINT) SIZEOF(LPVOID)) ||
  674. (lpInterface && IsBadReadPtr(lpInterface, (UINT) sizeof(IID))) ||
  675. IsBadWritePtr(lppMAPIPropNew, (UINT) SIZEOF(LPMAPIPROP)) ||
  676. (lpMAPIPropSibling && IsBadReadPtr(lpMAPIPropSibling, (UINT) SIZEOF(LPVOID)))
  677. )
  678. {
  679. DebugTraceSc(ABPLogon_OpenTemplateID, E_INVALIDARG);
  680. return ResultFromScode(E_INVALIDARG);
  681. }
  682. /* //$ need stronger checking here... */
  683. /* entryid better be right size */
  684. if (cbTemplateId != sizeof(OOUSER_ENTRYID) && cbTemplateId != sizeof(USR_ENTRYID))
  685. {
  686. hResult = ResultFromScode(MAPI_E_INVALID_ENTRYID);
  687. goto out;
  688. }
  689. /* is it my entry id compare MAPIUIDs */
  690. if (memcmp(&(((LPUSR_ENTRYID) lpTemplateId)->muid), &muidABMAWF, SIZEOF(MAPIUID)))
  691. {
  692. /*
  693. * Not mine!
  694. */
  695. hResult = ResultFromScode( MAPI_E_INVALID_ENTRYID );
  696. goto out;
  697. }
  698. /* better be a oneoff user entryid or a user entry id */
  699. if (((LPUSR_ENTRYID) lpTemplateId)->ulType == MAWF_ONEOFF)
  700. {
  701. hResult = HrNewOOTID( lppMAPIPropNew,
  702. cbTemplateId,
  703. lpTemplateId,
  704. ulTemplateFlags,
  705. lpMAPIPropData,
  706. (LPABLOGON) lpABPLogon,
  707. lpInterface,
  708. lpABPLogon->hLibrary,
  709. lpABPLogon->lpAllocBuff,
  710. lpABPLogon->lpAllocMore,
  711. lpABPLogon->lpFreeBuff,
  712. lpABPLogon->lpMalloc
  713. );
  714. }
  715. else if (((LPUSR_ENTRYID) lpTemplateId)->ulType == MAWF_USER)
  716. {
  717. hResult = HrNewTID( lppMAPIPropNew,
  718. cbTemplateId,
  719. lpTemplateId,
  720. ulTemplateFlags,
  721. lpMAPIPropData,
  722. (LPABLOGON) lpABPLogon,
  723. lpInterface,
  724. lpABPLogon->hLibrary,
  725. lpABPLogon->lpAllocBuff,
  726. lpABPLogon->lpAllocMore,
  727. lpABPLogon->lpFreeBuff,
  728. lpABPLogon->lpMalloc
  729. );
  730. }
  731. else
  732. {
  733. hResult = MakeResult(MAPI_E_INVALID_ENTRYID);
  734. }
  735. out:
  736. DebugTraceResult(ABPLOGON_OpenTemplateID, hResult);
  737. return hResult;
  738. }
  739. /*
  740. - ABPLOGON_GetOneOffTable
  741. -
  742. * Returns the lists of one-offs that this providers can support creation of.
  743. * This list is added to the entries gathered from all the other AB logon objects
  744. * and exposed to the user as the list of things that can be created on a
  745. * message. Also this total list is available to other providers through the
  746. * support method GetOneOffTable().
  747. *
  748. * Note: There's a bug here that if there are more than one Microsoft At Work Fax Address Books
  749. * installed on a particular profile, then there will be multiple entries in the
  750. * one-off table from this provider. This can be changed to only have one one-off
  751. * entry, no matter how many FABs are configured in a profile, if the one-off table
  752. * was associated with the ABInit object.
  753. */
  754. /*
  755. * Column set for the oneoff table
  756. */
  757. enum { ivalootPR_DISPLAY_NAME = 0,
  758. ivalootPR_ENTRYID,
  759. ivalootPR_DEPTH,
  760. ivalootPR_SELECTABLE,
  761. ivalootPR_ADDRTYPE,
  762. ivalootPR_DISPLAY_TYPE,
  763. ivalootPR_INSTANCE_KEY,
  764. ivalootMax };
  765. static const SizedSPropTagArray(ivalootMax, tagaColSetOOTable) =
  766. {
  767. ivalootMax,
  768. {
  769. PR_DISPLAY_NAME_A,
  770. PR_ENTRYID,
  771. PR_DEPTH,
  772. PR_SELECTABLE,
  773. PR_ADDRTYPE_A,
  774. PR_DISPLAY_TYPE,
  775. PR_INSTANCE_KEY
  776. }
  777. };
  778. STDMETHODIMP
  779. ABPLOGON_GetOneOffTable( LPABPLOGON lpABPLogon,
  780. ULONG ulFlags,
  781. LPMAPITABLE * lppTable
  782. )
  783. {
  784. SCODE sc;
  785. HRESULT hResult;
  786. SRow sRow;
  787. SPropValue rgsPropValue[ivalootMax];
  788. CHAR displayNameString[MAX_DISPLAY_NAME];
  789. ULONG ulInstanceKey = 1;
  790. HINSTANCE hInst;
  791. #ifdef UNICODE
  792. CHAR szEMT[ MAX_PATH ];
  793. #endif
  794. /*
  795. * Validate Parameters
  796. */
  797. if ( ulFlags & ~(MAPI_UNICODE) )
  798. {
  799. DebugTraceArg( APBLOGON_GetOneOffTable, "Unknown Flags" );
  800. return ResultFromScode( MAPI_E_UNKNOWN_FLAGS );
  801. }
  802. if ( ulFlags & MAPI_UNICODE )
  803. {
  804. DebugTraceArg( APBLOGON_GetOneOffTable, "UNICODE not supported" );
  805. return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  806. }
  807. if ( IsBadReadPtr(lpABPLogon, (UINT) SIZEOF(ABPLOGON))
  808. || IsBadWritePtr(lppTable, (UINT) SIZEOF(LPMAPITABLE))
  809. )
  810. {
  811. DebugTraceSc(ABPLogon_GetOneOffTable, E_INVALIDARG);
  812. return ResultFromScode(E_INVALIDARG);
  813. }
  814. EnterCriticalSection(&lpABPLogon->cs);
  815. /*
  816. * If there's not one already associated with this logon object,
  817. * then create one.
  818. */
  819. if (!lpABPLogon->lpTDatOO)
  820. {
  821. /* Create a Table data object */
  822. sc = CreateTable(
  823. (LPIID) &IID_IMAPITableData,
  824. lpABPLogon->lpAllocBuff,
  825. lpABPLogon->lpAllocMore,
  826. lpABPLogon->lpFreeBuff,
  827. lpABPLogon->lpMalloc,
  828. 0,
  829. PR_DISPLAY_NAME_A,
  830. (LPSPropTagArray) &tagaColSetOOTable,
  831. &(lpABPLogon->lpTDatOO));
  832. if (FAILED(sc))
  833. {
  834. hResult = ResultFromScode(sc);
  835. goto out;
  836. }
  837. // Get the instance handle, so that I can get the display strings off the resource file
  838. hInst = lpABPLogon->hLibrary;
  839. // Initialize the row
  840. sRow.cValues = ivalootMax;
  841. sRow.lpProps = rgsPropValue;
  842. /*
  843. * Fill the table
  844. *
  845. * we want to add two entries to the one-off table, so that we'll get:
  846. *
  847. * Microsoft Fax
  848. * Fax
  849. */
  850. // First do the 'Microsoft Fax'
  851. // Name of the One-Off
  852. rgsPropValue[ivalootPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
  853. LoadStringA( hInst, IDS_MAWF_NAME, displayNameString, ARRAYSIZE(displayNameString));
  854. rgsPropValue[ivalootPR_DISPLAY_NAME].Value.lpszA = displayNameString;
  855. rgsPropValue[ivalootPR_ENTRYID].ulPropTag = PR_ENTRYID;
  856. rgsPropValue[ivalootPR_ENTRYID].Value.bin.cb = SIZEOF(OOUSER_ENTRYID);
  857. rgsPropValue[ivalootPR_ENTRYID].Value.bin.lpb = (LPVOID) &ONEOFF_EID;
  858. // the hierarcy level (how far to indent a display name). I choose not to indent
  859. rgsPropValue[ivalootPR_DEPTH].ulPropTag = PR_DEPTH;
  860. rgsPropValue[ivalootPR_DEPTH].Value.l = 0;
  861. // Selection flags. TRUE indicates this entry ID can be used in CreateEntry() call.
  862. rgsPropValue[ivalootPR_SELECTABLE].ulPropTag = PR_SELECTABLE;
  863. rgsPropValue[ivalootPR_SELECTABLE].Value.b = TRUE;
  864. // The address type that would be generated by an entry
  865. // created from this template
  866. rgsPropValue[ivalootPR_ADDRTYPE].ulPropTag = PR_ADDRTYPE_A;
  867. #ifdef UNICODE
  868. szEMT[0] = 0;
  869. WideCharToMultiByte( CP_ACP, 0, lpszEMT, -1, szEMT, ARRAYSIZE(szEMT), NULL, NULL );
  870. rgsPropValue[ivalootPR_ADDRTYPE].Value.lpszA = szEMT;
  871. #else
  872. rgsPropValue[ivalootPR_ADDRTYPE].Value.LPSZ = lpszEMT;
  873. #endif
  874. /*
  875. * The display type associated with a recipient built with this template
  876. */
  877. rgsPropValue[ivalootPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  878. rgsPropValue[ivalootPR_DISPLAY_TYPE].Value.lpszA = DT_MAILUSER;
  879. /*
  880. * The instance key of this row in this one-off table.
  881. * using 1 for this row
  882. */
  883. ulInstanceKey = 1;
  884. rgsPropValue[ivalootPR_INSTANCE_KEY].ulPropTag = PR_INSTANCE_KEY;
  885. rgsPropValue[ivalootPR_INSTANCE_KEY].Value.bin.cb = SIZEOF(ULONG);
  886. rgsPropValue[ivalootPR_INSTANCE_KEY].Value.bin.lpb = (LPBYTE) &ulInstanceKey;
  887. (void) lpABPLogon->lpTDatOO->lpVtbl->HrModifyRow(
  888. lpABPLogon->lpTDatOO,
  889. &sRow);
  890. #ifdef DO_MULTI_LEVEL_ADDRESS_BOOK_STUFF
  891. // Now do the 'Fax'
  892. // Name of the One-Off
  893. rgsPropValue[ivalootPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
  894. LoadStringA(hInst, IDS_FAX_NAME, displayNameString, ARRAYSIZE(displayNameString));
  895. rgsPropValue[ivalootPR_DISPLAY_NAME].Value.lpszA = displayNameString;
  896. // The entry ID for this template. MAPI will call OpenEntry() with this entry ID
  897. // RtlZeroMemory(&EntryID, sizeof(OOUSER_ENTRYID));
  898. rgsPropValue[ivalootPR_ENTRYID].ulPropTag = PR_ENTRYID;
  899. rgsPropValue[ivalootPR_ENTRYID].Value.bin.cb = SIZEOF(OOUSER_ENTRYID);
  900. rgsPropValue[ivalootPR_ENTRYID].Value.bin.lpb = (LPVOID) &ONEOFF_EID;
  901. // the hierarcy level (how far to indent a display name). I choose not to indent
  902. rgsPropValue[ivalootPR_DEPTH].ulPropTag = PR_DEPTH;
  903. rgsPropValue[ivalootPR_DEPTH].Value.l = 1;
  904. // Selection flags. TRUE indicates this entry ID can be used in CreateEntry() call.
  905. rgsPropValue[ivalootPR_SELECTABLE].ulPropTag = PR_SELECTABLE;
  906. rgsPropValue[ivalootPR_SELECTABLE].Value.b = TRUE;
  907. // The address type that would be generated by an entry
  908. // created from this template
  909. rgsPropValue[ivalootPR_ADDRTYPE].ulPropTag = PR_ADDRTYPE_A;
  910. #ifdef UNICODE
  911. rgsPropValue[ivalootPR_ADDRTYPE].Value.lpszA = szEMT;
  912. #else
  913. rgsPropValue[ivalootPR_ADDRTYPE].Value.LPSZ = lpszEMT;
  914. #endif
  915. /*
  916. * The display type associated with a recipient built with this template
  917. */
  918. rgsPropValue[ivalootPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  919. rgsPropValue[ivalootPR_DISPLAY_TYPE].Value.lpszA = DT_MAILUSER;
  920. /*
  921. * The instance key of this row in this one-off table.
  922. * using 2 for this row
  923. */
  924. ulInstanceKey = 2;
  925. rgsPropValue[ivalootPR_INSTANCE_KEY].ulPropTag = PR_INSTANCE_KEY;
  926. rgsPropValue[ivalootPR_INSTANCE_KEY].Value.bin.cb = SIZEOF(ULONG);
  927. rgsPropValue[ivalootPR_INSTANCE_KEY].Value.bin.lpb = (LPBYTE) &ulInstanceKey;
  928. (void) lpABPLogon->lpTDatOO->lpVtbl->HrModifyRow(
  929. lpABPLogon->lpTDatOO,
  930. &sRow);
  931. #endif
  932. }
  933. /*
  934. * Get a view to return to the caller
  935. */
  936. hResult = lpABPLogon->lpTDatOO->lpVtbl->HrGetView(
  937. lpABPLogon->lpTDatOO,
  938. NULL,
  939. NULL,
  940. 0,
  941. (LPMAPITABLE *) lppTable);
  942. out:
  943. LeaveCriticalSection(&lpABPLogon->cs);
  944. DebugTraceResult(ABPLogon_GetOneOffTable, hResult);
  945. return hResult;
  946. }
  947. /*************************************************************************
  948. *
  949. - ABPLOGON_Advise
  950. -
  951. * NYI
  952. *
  953. *
  954. */
  955. STDMETHODIMP
  956. ABPLOGON_Advise( LPABPLOGON lpABPLogon,
  957. ULONG cbEntryID,
  958. LPENTRYID lpEntryID,
  959. ULONG ulEventMask,
  960. LPMAPIADVISESINK lpAdviseSink,
  961. ULONG FAR * lpulConnection
  962. )
  963. {
  964. DebugTraceSc(ABPLOGON_Advise, MAPI_E_NO_SUPPORT);
  965. return ResultFromScode(MAPI_E_NO_SUPPORT);
  966. }
  967. /*************************************************************************
  968. *
  969. - ABPLOGON_Unadvise
  970. -
  971. * NYI
  972. *
  973. *
  974. */
  975. STDMETHODIMP
  976. ABPLOGON_Unadvise(LPABPLOGON lpABPLogon, ULONG ulConnection)
  977. {
  978. DebugTraceSc(ABPLOGON_Unadvise, MAPI_E_NO_SUPPORT);
  979. return ResultFromScode(MAPI_E_NO_SUPPORT);
  980. }
  981. /*************************************************************************
  982. *
  983. - ABPLOGON_PrepareRecips
  984. -
  985. * Takes a list of recipients and sets values for a requested list of
  986. * properties (lpPropTagArray) on each of the recipients, from the respective
  987. * address book entry of the recipient. If the recipient already has
  988. * some properties set on it, those that exist on the address book entry
  989. * will override the one that are on the recipient. Those that do NOT
  990. * exist in the address book entry will stay.
  991. *
  992. *
  993. */
  994. STDMETHODIMP
  995. ABPLOGON_PrepareRecips( LPABPLOGON lpABPLogon,
  996. ULONG ulFlags,
  997. LPSPropTagArray lpPropTagArray,
  998. LPADRLIST lpRecipList
  999. )
  1000. {
  1001. HRESULT hResult = hrSuccess;
  1002. UINT iRecip;
  1003. UINT iProp;
  1004. ULONG cValues;
  1005. LPSPropValue lpspvUser = NULL;
  1006. LPSPropValue lpNewRecip = NULL;
  1007. LPMAPIPROP lpMAPIPropEntry = NULL;
  1008. SCODE sc = S_OK;
  1009. ULONG ulObjType;
  1010. BOOL fUselpspvUser;
  1011. if (!lpPropTagArray)
  1012. {
  1013. /*
  1014. * They only want us to update our entryID from ephemeral to
  1015. * permanent. Since ours are already permanent, we don't need to
  1016. * do anything.
  1017. */
  1018. goto out;
  1019. }
  1020. /* loop through all the recipients */
  1021. for (iRecip = 0; iRecip < lpRecipList->cEntries; iRecip++)
  1022. {
  1023. LPUSR_ENTRYID lpEntryID = NULL;
  1024. ULONG cbEntryID;
  1025. LPSPropValue lpPropVal = NULL;
  1026. LPSPropValue rgpropvalsRecip = lpRecipList->aEntries[iRecip].rgPropVals;
  1027. ULONG cPropsRecip = lpRecipList->aEntries[iRecip].cValues;
  1028. /* For each recipient, find its entryid */
  1029. lpPropVal = PpropFindProp( rgpropvalsRecip, cPropsRecip, PR_ENTRYID );
  1030. if ( lpPropVal )
  1031. {
  1032. lpEntryID = (LPUSR_ENTRYID)lpPropVal->Value.bin.lpb;
  1033. cbEntryID = lpPropVal->Value.bin.cb;
  1034. }
  1035. else
  1036. continue;
  1037. /* Is it one of ours? */
  1038. if ( cbEntryID < CbNewENTRYID(0)
  1039. || IsBadReadPtr( (LPVOID) lpEntryID, (UINT) cbEntryID ) )
  1040. {
  1041. continue; /* no, keep looking */
  1042. }
  1043. if ( memcmp( &(lpEntryID->muid), &muidABMAWF, SIZEOF(MAPIUID) ) )
  1044. continue; /* no, keep looking */
  1045. /* Try and open it. */
  1046. hResult = HrNewFaxUser( (LPMAILUSER *)&lpMAPIPropEntry,
  1047. &ulObjType,
  1048. cbEntryID,
  1049. (LPENTRYID) lpEntryID,
  1050. (LPABLOGON) lpABPLogon,
  1051. NULL,
  1052. lpABPLogon->hLibrary,
  1053. lpABPLogon->lpAllocBuff,
  1054. lpABPLogon->lpAllocMore,
  1055. lpABPLogon->lpFreeBuff,
  1056. lpABPLogon->lpMalloc
  1057. );
  1058. if ( HR_FAILED(hResult) )
  1059. {
  1060. /* Couldn't open it...; Ignore it and keep looking */
  1061. hResult = hrSuccess;
  1062. DebugTrace( "ABPLOGON_PrepareRecips sees a bad user entry ID\n" );
  1063. continue;
  1064. }
  1065. /* Get the properties requested */
  1066. hResult = lpMAPIPropEntry->lpVtbl->GetProps( lpMAPIPropEntry,
  1067. lpPropTagArray,
  1068. 0, /* ansi */
  1069. &cValues, &lpspvUser );
  1070. /* No longer need lpMAPIPropEntry */
  1071. lpMAPIPropEntry->lpVtbl->Release(lpMAPIPropEntry);
  1072. lpMAPIPropEntry = NULL;
  1073. if (HR_FAILED(hResult))
  1074. {
  1075. /* Failed getting properties. Cleanup and ignore this entry */
  1076. hResult = hrSuccess;
  1077. continue;
  1078. }
  1079. hResult = hrSuccess;
  1080. Assert(cValues == lpPropTagArray->cValues);
  1081. /*
  1082. * This is the hard part.
  1083. * Merge the two property sets: lpspvUser and lpsPropVal. Note that
  1084. * both of these sets may have the same property - chances are they do.
  1085. * for these conflicts, lpspvUser should be the one we get the property
  1086. * from.
  1087. *
  1088. * Guess how big the resultant SPropValue array is, and allocate one of that
  1089. * size.
  1090. */
  1091. sc = lpABPLogon->lpAllocBuff( (cValues + cPropsRecip) * SIZEOF( SPropValue ),
  1092. &lpNewRecip);
  1093. if (FAILED(sc))
  1094. {
  1095. /*
  1096. * Ok, to fail the call here. If we're running into out of memory conditions
  1097. * we're all in trouble.
  1098. */
  1099. hResult = ResultFromScode( sc );
  1100. goto err;
  1101. }
  1102. /*
  1103. * Copy lpspvUser properties over to lpNewRecip
  1104. * Check each property in lpsvUser to ensure that it isn't PT_ERROR, if so
  1105. * find the propval in rgpropvalsRecip ( the [in] recip prop val array ),
  1106. * if it exists and use that property.
  1107. */
  1108. for (iProp = 0; iProp < cValues; iProp++)
  1109. {
  1110. fUselpspvUser = TRUE;
  1111. if ( PROP_TYPE( lpspvUser[iProp].ulPropTag ) == PT_ERROR )
  1112. {
  1113. lpPropVal = PpropFindProp( rgpropvalsRecip, cPropsRecip,
  1114. lpPropTagArray->aulPropTag[iProp] );
  1115. if ( lpPropVal )
  1116. {
  1117. sc = PropCopyMore( lpNewRecip + iProp, lpPropVal,
  1118. lpABPLogon->lpAllocMore, lpNewRecip );
  1119. fUselpspvUser = FALSE;
  1120. }
  1121. }
  1122. if ( fUselpspvUser )
  1123. {
  1124. sc = PropCopyMore( lpNewRecip + iProp, lpspvUser + iProp,
  1125. lpABPLogon->lpAllocMore, lpNewRecip );
  1126. }
  1127. if (FAILED(sc))
  1128. {
  1129. if (sc == MAPI_E_NOT_ENOUGH_MEMORY)
  1130. {
  1131. hResult = MakeResult(sc);
  1132. goto err;
  1133. }
  1134. /*
  1135. * Otherwise we've run into something wierd in the prop value array
  1136. * like PT_UNSPECIFIED, PT_NULL, or PT_OBJECT. In which case continue
  1137. * on.
  1138. */
  1139. }
  1140. }
  1141. /* Done with lpspvUser */
  1142. lpABPLogon->lpFreeBuff( lpspvUser );
  1143. lpspvUser = NULL;
  1144. /*
  1145. * Copy those properties that aren't already in lpNewRecip
  1146. * from rgpropvalsRecip. Don't copy over the PT_ERROR prop vals
  1147. */
  1148. for ( iProp = 0; iProp < cPropsRecip; iProp++ )
  1149. {
  1150. if ( PpropFindProp( lpNewRecip, cValues, rgpropvalsRecip[iProp].ulPropTag )
  1151. || PROP_TYPE( rgpropvalsRecip[iProp].ulPropTag ) == PT_ERROR )
  1152. continue;
  1153. sc = PropCopyMore( lpNewRecip + cValues, rgpropvalsRecip + iProp,
  1154. lpABPLogon->lpAllocMore, lpNewRecip );
  1155. if ( FAILED( sc ) )
  1156. {
  1157. if (sc == MAPI_E_NOT_ENOUGH_MEMORY)
  1158. {
  1159. hResult = ResultFromScode( sc );
  1160. goto err;
  1161. }
  1162. /*
  1163. * Otherwise we've run into something wierd in the prop value array
  1164. * like PT_UNSPECIFIED, PT_NULL, or PT_OBJECT. In which case continue
  1165. * on.
  1166. */
  1167. }
  1168. cValues++;
  1169. }
  1170. /*
  1171. * Replace the AdrEntry in the AdrList with this new lpNewRecip. And
  1172. * don't forget the cValues!
  1173. */
  1174. lpRecipList->aEntries[iRecip].rgPropVals = lpNewRecip;
  1175. lpRecipList->aEntries[iRecip].cValues = cValues;
  1176. /* Finally, free up the old AdrEntry. */
  1177. lpABPLogon->lpFreeBuff( rgpropvalsRecip );
  1178. }
  1179. out:
  1180. DebugTraceResult( ABPLOGON_PrepareRecips, hResult );
  1181. return hResult;
  1182. err:
  1183. lpABPLogon->lpFreeBuff( lpspvUser );
  1184. goto out;
  1185. }
  1186. /*************************************************************************
  1187. * LpMuidFromLogon -
  1188. * Returns the particular ABPLOGON object's unique identifier.
  1189. *
  1190. */
  1191. LPMAPIUID
  1192. LpMuidFromLogon(LPABLOGON lpABLogon)
  1193. {
  1194. LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1195. AssertSz(!IsBadReadPtr(lpABPLogon, SIZEOF(ABPLOGON)), "Bad logon object!\n");
  1196. return (&(lpABPLogon->muidID));
  1197. }
  1198. /*************************************************************************
  1199. * HrLpszGetCurrentFileName -
  1200. * Returns a copy of the current .FAB file pointed to by this logon object.
  1201. *
  1202. */
  1203. HRESULT
  1204. HrLpszGetCurrentFileName(LPABLOGON lpABLogon, LPTSTR * lppszFileName)
  1205. {
  1206. LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1207. SCODE sc;
  1208. HRESULT hResult = hrSuccess;
  1209. AssertSz(!IsBadReadPtr(lpABPLogon, SIZEOF(ABPLOGON)), "FAB: Bad logon object!\n");
  1210. AssertSz(!IsBadWritePtr(lppszFileName, SIZEOF(LPTSTR)), "FAB: Bad dest string!\n");
  1211. EnterCriticalSection(&lpABPLogon->cs);
  1212. sc = lpABPLogon->lpAllocBuff( (lstrlen(lpABPLogon->lpszFileName)+1)*SIZEOF(TCHAR), lppszFileName);
  1213. if (FAILED(sc))
  1214. {
  1215. hResult = ResultFromScode(sc);
  1216. goto ret;
  1217. }
  1218. lstrcpy( *lppszFileName, lpABPLogon->lpszFileName);
  1219. ret:
  1220. LeaveCriticalSection(&lpABPLogon->cs);
  1221. DebugTraceResult(HrLpszGetCurrentFileName, hResult);
  1222. return hResult;
  1223. }
  1224. /*
  1225. * HrReplaceCurrentFileName -
  1226. * Replaces the current file name associated with this logon object and tries
  1227. * to save it all away in the profile.
  1228. */
  1229. HRESULT
  1230. HrReplaceCurrentFileName(LPABLOGON lpABLogon, LPTSTR lpszNewFile)
  1231. {
  1232. LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1233. HRESULT hResult = hrSuccess;
  1234. LPPROFSECT lpProfSect = NULL;
  1235. LPTSTR lpstrT;
  1236. SCODE sc;
  1237. SPropValue rgspv[1];
  1238. #ifdef UNICODE
  1239. CHAR szAnsiFileName[ MAX_PATH ];
  1240. #endif
  1241. AssertSz(!IsBadReadPtr(lpABPLogon, SIZEOF(ABPLOGON)), "Bad logon object!\n");
  1242. EnterCriticalSection(&lpABPLogon->cs);
  1243. /*
  1244. * FAB file name has changed have to update profile and objects
  1245. */
  1246. if (lstrcmp(lpszNewFile, lpABPLogon->lpszFileName))
  1247. {
  1248. /*
  1249. * Open the private profile section...
  1250. */
  1251. hResult = lpABPLogon->lpMapiSup->lpVtbl->OpenProfileSection(
  1252. lpABPLogon->lpMapiSup,
  1253. NULL,
  1254. MAPI_MODIFY,
  1255. &lpProfSect);
  1256. if (HR_FAILED(hResult))
  1257. {
  1258. /*
  1259. * Shouldn't get here, but in case I do, just...
  1260. */
  1261. goto ret;
  1262. }
  1263. /*
  1264. * Save the new name back into the profile
  1265. */
  1266. rgspv[0].ulPropTag = PR_FAB_FILE_A;
  1267. #ifdef UNICODE
  1268. szAnsiFileName[0] = 0;
  1269. WideCharToMultiByte( CP_ACP, 0, lpszNewFile, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
  1270. rgspv[0].Value.lpszA = szAnsiFileName;
  1271. #else
  1272. rgspv[0].Value.LPSZ = lpszNewFile;
  1273. #endif
  1274. /*
  1275. * Don't care if I can save it in the profile or not.
  1276. * Saving it's a nice to have, but absolutely required
  1277. * for operation of this particular provider.
  1278. */
  1279. (void) lpProfSect->lpVtbl->SetProps(
  1280. lpProfSect,
  1281. 1, // ansi
  1282. rgspv,
  1283. NULL);
  1284. lpProfSect->lpVtbl->Release(lpProfSect);
  1285. /*
  1286. * Allocate and copy this new one
  1287. */
  1288. sc = lpABPLogon->lpAllocBuff( (lstrlen(lpszNewFile)+1)*SIZEOF(TCHAR), &lpstrT);
  1289. if (FAILED(sc))
  1290. {
  1291. hResult = ResultFromScode(sc);
  1292. goto ret;
  1293. }
  1294. lstrcpy( lpstrT, lpszNewFile );
  1295. /*
  1296. * Free up the old one...
  1297. */
  1298. lpABPLogon->lpFreeBuff(lpABPLogon->lpszFileName);
  1299. /*
  1300. * Put in the new one.
  1301. */
  1302. lpABPLogon->lpszFileName = lpstrT;
  1303. /*
  1304. * Update the hierarchy table
  1305. */
  1306. hResult = HrBuildRootHier((LPABLOGON)lpABPLogon, NULL);
  1307. }
  1308. ret:
  1309. LeaveCriticalSection(&lpABPLogon->cs);
  1310. DebugTraceResult(HrReplaceCurrentFileName, hResult);
  1311. return hResult;
  1312. }
  1313. /*
  1314. * GenerateContainerDN -
  1315. * Common code for generating the display name of the single
  1316. * container exposed from this logon object.
  1317. */
  1318. #ifdef SAB // from sample AB
  1319. void
  1320. GenerateContainerDN(LPABLOGON lpABLogon, LPTSTR lpszName)
  1321. {
  1322. LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1323. LPTSTR lpszFileName;
  1324. int ich;
  1325. AssertSz(!IsBadReadPtr(lpABPLogon, SIZEOF(ABPLOGON)), "Bad logon object!\n");
  1326. EnterCriticalSection(&lpABPLogon->cs);
  1327. lpszFileName = lpABPLogon->lpszFileName;
  1328. // get the filename without the path
  1329. for (ich = lstrlen(lpszFileName) - 1; ich >= 0; ich--)
  1330. {
  1331. if (lpszFileName[ich] == TEXT('\\'))
  1332. break;
  1333. }
  1334. // skip past the backslash
  1335. ich++;
  1336. wsprintf(lpszName, TEXT("FAB using %s"), lpszFileName + ich);
  1337. LeaveCriticalSection(&lpABPLogon->cs);
  1338. }
  1339. #else // Fax AB
  1340. void
  1341. GenerateContainerDN(HINSTANCE hInst, LPTSTR lpszName)
  1342. {
  1343. LoadString (hInst, IDS_ADDRESS_BOOK_ROOT_CONT, lpszName, MAX_DISPLAY_NAME);
  1344. }
  1345. #endif
  1346. /*
  1347. - HrBuildRootHier
  1348. -
  1349. *
  1350. * Builds up the root hierarchy for the Microsoft At Work Fax Address Book.
  1351. *
  1352. *
  1353. */
  1354. enum { ivalPR_DISPLAY_NAME = 0,
  1355. ivalPR_ENTRYID,
  1356. ivalPR_DEPTH,
  1357. ivalPR_OBJECT_TYPE,
  1358. ivalPR_DISPLAY_TYPE,
  1359. ivalPR_CONTAINER_FLAGS,
  1360. ivalPR_INSTANCE_KEY,
  1361. ivalPR_AB_PROVIDER_ID,
  1362. cvalMax };
  1363. static const SizedSPropTagArray(cvalMax, tagaRootColSet) =
  1364. {
  1365. cvalMax,
  1366. {
  1367. PR_DISPLAY_NAME_A,
  1368. PR_ENTRYID,
  1369. PR_DEPTH,
  1370. PR_OBJECT_TYPE,
  1371. PR_DISPLAY_TYPE,
  1372. PR_CONTAINER_FLAGS,
  1373. PR_INSTANCE_KEY,
  1374. PR_AB_PROVIDER_ID
  1375. }
  1376. };
  1377. HRESULT
  1378. HrBuildRootHier(LPABLOGON lpABLogon, LPMAPITABLE * lppMAPITable)
  1379. {
  1380. HRESULT hResult;
  1381. SCODE sc;
  1382. SRow sRow;
  1383. SPropValue rgsPropValue[cvalMax];
  1384. ULONG ulInstanceKey = 1;
  1385. TCHAR szBuf[MAX_PATH];
  1386. #ifdef UNICODE
  1387. CHAR szAnsiBuf[MAX_PATH];
  1388. #endif
  1389. HINSTANCE hInst;
  1390. LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1391. DIR_ENTRYID eidRoot = { {0, 0, 0, 0},
  1392. MUIDABMAWF,
  1393. MAWF_VERSION,
  1394. MAWF_DIRECTORY };
  1395. EnterCriticalSection(&lpABPLogon->cs);
  1396. hInst = lpABPLogon->hLibrary;
  1397. /*
  1398. * See if we have a TaD yet
  1399. */
  1400. if (!lpABPLogon->lpTDatRoot)
  1401. {
  1402. /* Create a Table Data object */
  1403. if ( sc = CreateTable((LPIID) &IID_IMAPITableData,
  1404. lpABPLogon->lpAllocBuff,
  1405. lpABPLogon->lpAllocMore,
  1406. lpABPLogon->lpFreeBuff,
  1407. lpABPLogon->lpMalloc,
  1408. 0,
  1409. PR_ENTRYID,
  1410. (LPSPropTagArray) &tagaRootColSet,
  1411. &(lpABPLogon->lpTDatRoot))
  1412. )
  1413. {
  1414. hResult = ResultFromScode(sc);
  1415. goto out;
  1416. }
  1417. }
  1418. /* Constants */
  1419. sRow.cValues = cvalMax;
  1420. sRow.lpProps = rgsPropValue;
  1421. /* First, the Display Name stuff*/
  1422. rgsPropValue[ivalPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
  1423. #ifdef SAB
  1424. GenerateContainerDN((LPABLOGON) lpABPLogon, szBuf);
  1425. #else
  1426. GenerateContainerDN(hInst, szBuf);
  1427. #endif
  1428. #ifdef UNICODE
  1429. szAnsiBuf[0] = 0;
  1430. WideCharToMultiByte( CP_ACP, 0, szBuf, -1, szAnsiBuf, ARRAYSIZE(szAnsiBuf), NULL, NULL );
  1431. rgsPropValue[ivalPR_DISPLAY_NAME].Value.lpszA = szAnsiBuf;
  1432. #else
  1433. rgsPropValue[ivalPR_DISPLAY_NAME].Value.lpszA = szBuf;
  1434. #endif
  1435. /*
  1436. * For each FAB logon object associated with it's init object,
  1437. * we have a unique MAPIUID. It's the only thing that distinguishes
  1438. * one FAB entryid from another in the merged hierarchy table that
  1439. * MAPI generates.
  1440. */
  1441. rgsPropValue[ivalPR_ENTRYID].ulPropTag = PR_ENTRYID;
  1442. eidRoot.muidID = lpABPLogon->muidID;
  1443. rgsPropValue[ivalPR_ENTRYID].Value.bin.cb = SIZEOF(DIR_ENTRYID);
  1444. rgsPropValue[ivalPR_ENTRYID].Value.bin.lpb = (LPVOID) &eidRoot;
  1445. rgsPropValue[ivalPR_DEPTH].ulPropTag = PR_DEPTH;
  1446. rgsPropValue[ivalPR_DEPTH].Value.l = 0;
  1447. rgsPropValue[ivalPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  1448. rgsPropValue[ivalPR_OBJECT_TYPE].Value.l = MAPI_ABCONT;
  1449. rgsPropValue[ivalPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  1450. rgsPropValue[ivalPR_DISPLAY_TYPE].Value.l = DT_NOT_SPECIFIC;
  1451. rgsPropValue[ivalPR_CONTAINER_FLAGS].ulPropTag = PR_CONTAINER_FLAGS;
  1452. rgsPropValue[ivalPR_CONTAINER_FLAGS].Value.l = AB_RECIPIENTS | AB_UNMODIFIABLE;
  1453. rgsPropValue[ivalPR_INSTANCE_KEY].ulPropTag = PR_INSTANCE_KEY;
  1454. rgsPropValue[ivalPR_INSTANCE_KEY].Value.bin.cb = SIZEOF(ULONG);
  1455. rgsPropValue[ivalPR_INSTANCE_KEY].Value.bin.lpb = (LPBYTE) &ulInstanceKey;
  1456. rgsPropValue[ivalPR_AB_PROVIDER_ID].ulPropTag = PR_AB_PROVIDER_ID;
  1457. rgsPropValue[ivalPR_AB_PROVIDER_ID].Value.bin.cb = SIZEOF(MAPIUID);
  1458. rgsPropValue[ivalPR_AB_PROVIDER_ID].Value.bin.lpb = (LPBYTE) &muidABMAWF;
  1459. hResult = lpABPLogon->lpTDatRoot->lpVtbl->HrModifyRow( lpABPLogon->lpTDatRoot, &sRow );
  1460. if (HR_FAILED(hResult))
  1461. goto out;
  1462. /*
  1463. * Check to see if they want a view returned as well
  1464. */
  1465. if (lppMAPITable)
  1466. {
  1467. /* Get a view from the Table data object */
  1468. hResult =
  1469. lpABPLogon->lpTDatRoot->lpVtbl->HrGetView(
  1470. lpABPLogon->lpTDatRoot,
  1471. NULL,
  1472. NULL,
  1473. 0,
  1474. lppMAPITable);
  1475. }
  1476. out:
  1477. LeaveCriticalSection(&lpABPLogon->cs);
  1478. DebugTraceResult(HrBuildRootHier, hResult);
  1479. return hResult;
  1480. }
  1481. /*
  1482. * Checks to see if the file passed in is still the actual file that
  1483. * should be browsed.
  1484. */
  1485. BOOL
  1486. FEqualFABFiles( LPABLOGON lpABLogon,
  1487. LPTSTR lpszFileName)
  1488. {
  1489. LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1490. BOOL fEqual;
  1491. AssertSz(!IsBadReadPtr(lpABPLogon, SIZEOF(ABPLOGON)), "Bad logon object!\n");
  1492. EnterCriticalSection(&lpABPLogon->cs);
  1493. fEqual = !lstrcmp( lpszFileName, lpABPLogon->lpszFileName );
  1494. LeaveCriticalSection(&lpABPLogon->cs);
  1495. return fEqual;
  1496. }