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.

899 lines
29 KiB

  1. /***********************************************************************
  2. *
  3. * OOTID.C
  4. *
  5. * Microsoft At Work Fax Address Book OneOff Template ID object
  6. * This file contains the code for implementing the Microsoft At Work Fax AB
  7. * TID object.
  8. *
  9. * Copyright 1992, 1993 Microsoft Corporation. All Rights Reserved.
  10. *
  11. * Revision History:
  12. *
  13. * When Who What
  14. * -------- ------------------ ---------------------------------------
  15. * MAPI Original source from MAPI(154) sample AB Provider
  16. * 3.7.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
  17. * 4.2.94 Yoram Yaacovi Update to MAPI and sample AB 157
  18. * 8.7.94 Yoram Yaacovi Update to MAPI and sample AB 304
  19. * 8.24.94 Yoram Yaacovi Added OpenProperty and Release to support ddlbx and buttons in the one-off template
  20. *
  21. ***********************************************************************/
  22. #include "faxab.h"
  23. /*
  24. * External functions
  25. */
  26. HRESULT
  27. NewABUserButton(LPROOT, ULONG, ULONG, ULONG, LPMAPICONTROL FAR *);
  28. void LoadIniParams(void);
  29. /*
  30. * OOTID jump table is defined here...
  31. */
  32. static const OOTID_Vtbl vtblOOTID =
  33. {
  34. (OOTID_QueryInterface_METHOD *) ABU_QueryInterface,
  35. (OOTID_AddRef_METHOD *) WRAP_AddRef,
  36. OOTID_Release,
  37. (OOTID_GetLastError_METHOD *) WRAP_GetLastError,
  38. OOTID_SaveChanges,
  39. (OOTID_GetProps_METHOD *) WRAP_GetProps,
  40. (OOTID_GetPropList_METHOD *) WRAP_GetPropList,
  41. OOTID_OpenProperty,
  42. OOTID_SetProps,
  43. (OOTID_DeleteProps_METHOD *) WRAP_DeleteProps,
  44. (OOTID_CopyTo_METHOD *) WRAP_CopyTo,
  45. (OOTID_CopyProps_METHOD *) WRAP_CopyProps,
  46. (OOTID_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
  47. (OOTID_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
  48. };
  49. // enum and property tag array for getting the properties
  50. enum { ivalootidPR_COUNTRY_ID,
  51. ivalootidPR_AREA_CODE,
  52. ivalootidPR_TEL_NUMBER,
  53. ivalootidPR_EMAIL_ADDRESS,
  54. ivalootidPR_FAX_CP_NAME,
  55. ivalootidMax };
  56. static const SizedSPropTagArray(ivalootidMax,pta)=
  57. {
  58. ivalootidMax,
  59. {
  60. PR_COUNTRY_ID,
  61. PR_AREA_CODE_A,
  62. PR_TEL_NUMBER_A,
  63. PR_EMAIL_ADDRESS_A,
  64. PR_FAX_CP_NAME_A,
  65. }
  66. };
  67. /*************************************************************************
  68. *
  69. - HrNewOOTID
  70. -
  71. * Creates the OOTID object associated with a mail user.
  72. *
  73. *
  74. */
  75. HRESULT
  76. HrNewOOTID( LPMAPIPROP * lppMAPIPropNew,
  77. ULONG cbTemplateId,
  78. LPENTRYID lpTemplateId,
  79. ULONG ulTemplateFlags,
  80. LPMAPIPROP lpPropData,
  81. LPABLOGON lpABPLogon,
  82. LPCIID lpInterface,
  83. HINSTANCE hLibrary,
  84. LPALLOCATEBUFFER lpAllocBuff,
  85. LPALLOCATEMORE lpAllocMore,
  86. LPFREEBUFFER lpFreeBuff,
  87. LPMALLOC lpMalloc
  88. )
  89. {
  90. LPOOTID lpOOTID;
  91. SCODE sc;
  92. HRESULT hResult = hrSuccess;
  93. LPMAILUSER lpABOOUser = NULL;
  94. ULONG ulObjType;
  95. LPSPropValue lpspv=NULL;
  96. ULONG ulcValues;
  97. PARSEDTELNUMBER sParsedFaxAddr={{TEXT("")},{TEXT("")},{TEXT("")},{TEXT("")}};
  98. /*
  99. * Create the one-off object corresponding to the template id
  100. */
  101. hResult = HrNewFaxOOUser( &lpABOOUser,
  102. &ulObjType,
  103. cbTemplateId,
  104. lpTemplateId,
  105. lpABPLogon,
  106. lpInterface,
  107. hLibrary,
  108. lpAllocBuff,
  109. lpAllocMore,
  110. lpFreeBuff,
  111. lpMalloc
  112. );
  113. if (HR_FAILED(hResult))
  114. {
  115. goto err;
  116. }
  117. /*
  118. * Allocate space for the OOTID structure
  119. */
  120. sc = lpAllocBuff(SIZEOF(OOTID), (LPVOID *) & lpOOTID);
  121. if (FAILED(sc))
  122. {
  123. DebugTrace("NewOOTID() - AllocBuffer failed %s\n",SzDecodeScode(sc));
  124. hResult = ResultFromScode (sc);
  125. goto err;
  126. }
  127. /*
  128. * Initialize the OOTID structure
  129. */
  130. lpOOTID->lpVtbl = &vtblOOTID;
  131. lpOOTID->lcInit = 1;
  132. lpOOTID->hResult = hrSuccess;
  133. lpOOTID->idsLastError = 0;
  134. lpOOTID->hLibrary = hLibrary;
  135. lpOOTID->lpAllocBuff = lpAllocBuff;
  136. lpOOTID->lpAllocMore = lpAllocMore;
  137. lpOOTID->lpFreeBuff = lpFreeBuff;
  138. lpOOTID->lpMalloc = lpMalloc;
  139. lpOOTID->lpABLogon = lpABPLogon;
  140. lpOOTID->lpPropData = lpPropData;
  141. lpOOTID->lpABUser = lpABOOUser;
  142. lstrcpy(lpOOTID->szPreviousCPName, TEXT(""));
  143. /*
  144. * First time creation - must set the address type and template id.
  145. */
  146. if (ulTemplateFlags==FILL_ENTRY)
  147. {
  148. ULONG ulCount;
  149. LPSPropValue lpspv = NULL;
  150. /*
  151. * Copy all the properties from my object to the propdata
  152. * These properties were set on the oouser object when it was created
  153. * (by HrNewFaxOOUser calling into oouser.c)
  154. */
  155. hResult = lpABOOUser->lpVtbl->GetProps( lpABOOUser,
  156. NULL,
  157. 0, /* ansi */
  158. &ulCount,
  159. &lpspv
  160. );
  161. if (FAILED(hResult))
  162. goto err;
  163. hResult = lpPropData->lpVtbl->SetProps( lpPropData,
  164. ulCount,
  165. lpspv,
  166. NULL
  167. );
  168. lpFreeBuff(lpspv);
  169. if (FAILED(hResult))
  170. goto err;
  171. }
  172. // entry already exists in the PAB
  173. else
  174. {
  175. LPTSTR lpszCanonical=NULL;
  176. /*
  177. * Get the properties that make up the email address from the
  178. * mapiprop object
  179. */
  180. hResult = lpOOTID->lpPropData->lpVtbl->GetProps( lpOOTID->lpPropData,
  181. (LPSPropTagArray) &pta,
  182. 0, /* ansi */
  183. &ulcValues,
  184. &lpspv
  185. );
  186. // see if the tel number component of the email address exists on the object
  187. // if it doesn't, and there is a PR_EMAIL_ADDRESS,
  188. // create the address components from the email address
  189. if ( (PROP_TYPE(lpspv[ivalootidPR_TEL_NUMBER].ulPropTag) == PT_ERROR) &&
  190. (PROP_TYPE(lpspv[ivalootidPR_EMAIL_ADDRESS].ulPropTag) != PT_ERROR)
  191. )
  192. {
  193. #ifdef UNICODE
  194. WCHAR szTmp[ MAX_PATH ];
  195. CHAR szAnsiTelNumber[ 100 ];
  196. CHAR szAnsiAreaCode[ 5 ];
  197. szTmp[0] = 0;
  198. MultiByteToWideChar( CP_ACP, 0, lpspv[ivalootidPR_EMAIL_ADDRESS].Value.lpszA, -1, szTmp, ARRAYSIZE(szTmp) );
  199. DecodeFaxAddress(szTmp, &sParsedFaxAddr);
  200. #else
  201. DecodeFaxAddress(lpspv[ivalootidPR_EMAIL_ADDRESS].Value.LPSZ, &sParsedFaxAddr);
  202. #endif
  203. lpspv[ivalootidPR_TEL_NUMBER].ulPropTag = PR_TEL_NUMBER_A;
  204. #ifdef UNICODE
  205. szAnsiTelNumber[0] = 0;
  206. WideCharToMultiByte( CP_ACP, 0, sParsedFaxAddr.szTelNumber, -1, szAnsiTelNumber, ARRAYSIZE(szAnsiTelNumber), NULL, NULL );
  207. lpspv[ivalootidPR_TEL_NUMBER].Value.lpszA = szAnsiTelNumber;
  208. #else
  209. lpspv[ivalootidPR_TEL_NUMBER].Value.LPSZ = sParsedFaxAddr.szTelNumber;
  210. #endif
  211. lpspv[ivalootidPR_AREA_CODE].ulPropTag = PR_AREA_CODE_A;
  212. #ifdef UNICODE
  213. szAnsiAreaCode[0] = 0;
  214. WideCharToMultiByte( CP_ACP, 0, sParsedFaxAddr.szAreaCode, -1, szAnsiAreaCode, ARRAYSIZE(szAnsiAreaCode), NULL, NULL );
  215. lpspv[ivalootidPR_AREA_CODE].Value.lpszA = szAnsiAreaCode;
  216. #else
  217. lpspv[ivalootidPR_AREA_CODE].Value.LPSZ = sParsedFaxAddr.szAreaCode;
  218. #endif
  219. // CHECK: may need to get country id from country code
  220. lpspv[ivalootidPR_COUNTRY_ID].ulPropTag = PR_COUNTRY_ID;
  221. #ifdef UNICODE
  222. lpspv[ivalootidPR_COUNTRY_ID].Value.l = (DWORD) wcstol(sParsedFaxAddr.szCountryCode,NULL,0);
  223. #else
  224. lpspv[ivalootidPR_COUNTRY_ID].Value.l = (DWORD) atol(sParsedFaxAddr.szCountryCode);
  225. #endif
  226. }
  227. // save the starting (previous) cover page name, so that at SaveChanges time,
  228. // I can see if the user changed it
  229. if (PROP_TYPE(lpspv[ivalootidPR_FAX_CP_NAME].ulPropTag) != PT_ERROR)
  230. {
  231. #ifdef UNICODE
  232. lpOOTID->szPreviousCPName[0] = 0;
  233. MultiByteToWideChar( CP_ACP, 0, lpspv[ivalootidPR_FAX_CP_NAME].Value.lpszA, -1, lpOOTID->szPreviousCPName, ARRAYSIZE(lpOOTID->szPreviousCPName) );
  234. #else
  235. lstrcpy(lpOOTID->szPreviousCPName, lpspv[ivalootidPR_FAX_CP_NAME].Value.LPSZ);
  236. #endif
  237. }
  238. /* free the buffer */
  239. lpOOTID->lpFreeBuff(lpspv);
  240. if (HR_FAILED(hResult))
  241. {
  242. DebugTrace("HrNewOOTID: SetProps failed %s\n",SzDecodeScode(GetScode(hResult)));
  243. goto err;
  244. }
  245. }
  246. /*
  247. * AddRef lpPropData so we can use it after we return
  248. */
  249. (void)lpPropData->lpVtbl->AddRef(lpPropData);
  250. InitializeCriticalSection(&lpOOTID->cs);
  251. *lppMAPIPropNew = (LPVOID) lpOOTID;
  252. out:
  253. DebugTraceResult(HrNewOOTID, hResult);
  254. return hResult;
  255. err:
  256. if (lpABOOUser)
  257. lpABOOUser->lpVtbl->Release(lpABOOUser);
  258. lpFreeBuff(lpOOTID);
  259. goto out;
  260. }
  261. /*********************************************************************
  262. *********************************************************************
  263. *
  264. * The OOTID IMAPIProp methods
  265. *
  266. */
  267. STDMETHODIMP_(ULONG) OOTID_Release(LPOOTID lpOOTID)
  268. {
  269. LONG lcInit;
  270. /*
  271. * Check to see if it's large enough to hold this object
  272. */
  273. if (IsBadReadPtr(lpOOTID, sizeof(OOTID)))
  274. {
  275. /*
  276. * I'm not looking at an object that I expect to be.
  277. */
  278. return 1;
  279. }
  280. /*
  281. * Check to see that it's TIDs vtbl
  282. */
  283. if (lpOOTID->lpVtbl != &vtblOOTID)
  284. {
  285. /*
  286. * It's big enough but it's got the wrong vtbl.
  287. */
  288. return 1;
  289. }
  290. /*
  291. * Release the mapi property object
  292. */
  293. lpOOTID->lpPropData->lpVtbl->Release( lpOOTID->lpPropData );
  294. EnterCriticalSection(&lpOOTID->cs);
  295. lcInit = --lpOOTID->lcInit;
  296. LeaveCriticalSection(&lpOOTID->cs);
  297. if (lcInit == 0)
  298. {
  299. /*
  300. * Release the ABUser object
  301. */
  302. lpOOTID->lpABUser->lpVtbl->Release( lpOOTID->lpABUser );
  303. /*
  304. * Clean up the critical section
  305. */
  306. DeleteCriticalSection(&lpOOTID->cs);
  307. /*
  308. * Need to free the object
  309. */
  310. lpOOTID->lpFreeBuff(lpOOTID);
  311. return 0;
  312. }
  313. return lcInit;
  314. }
  315. /*****************************************************************************
  316. SetProps
  317. *****************************************************************************/
  318. STDMETHODIMP
  319. OOTID_SetProps( LPOOTID lpOOTID,
  320. ULONG cValues,
  321. LPSPropValue lpPropArray,
  322. LPSPropProblemArray * lppProblems
  323. )
  324. {
  325. enum { ivalspPR_DISPLAY_NAME = 0,
  326. ivalspMax };
  327. ULONG i;
  328. SPropValue spv[ivalspMax];
  329. HRESULT hResult=hrSuccess;
  330. /* Validate the object */
  331. if ( FBadUnknown(lpOOTID) ||
  332. IsBadWritePtr(lpOOTID, SIZEOF(lpOOTID)) ||
  333. IsBadReadPtr(lpOOTID->lpVtbl, offsetof(OOTID_Vtbl, SetProps)) ||
  334. OOTID_SetProps != lpOOTID->lpVtbl->SetProps
  335. )
  336. {
  337. DebugTrace("OOTID_SetProps -> E_INVALIDARG\n");
  338. return ResultFromScode(E_INVALIDARG);
  339. }
  340. for (i=0; i < cValues; i++)
  341. {
  342. // see if one of the set properties is PR_FAX_CP_NAME_A
  343. if (lpPropArray[i].ulPropTag == PR_FAX_CP_NAME_A)
  344. {
  345. // The cover page name is copied into the display name
  346. spv[ivalspPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
  347. spv[ivalspPR_DISPLAY_NAME].Value.lpszA = lpPropArray[i].Value.lpszA;
  348. // set PR_DISPLAY_NAME
  349. hResult = lpOOTID->lpPropData->lpVtbl->SetProps( lpOOTID->lpPropData,
  350. ivalspMax,
  351. spv,
  352. NULL
  353. );
  354. if (HR_FAILED(hResult))
  355. {
  356. DebugTrace("OOTID_SetProps: SetProps on PR_DISPLAY_NAME failed %s\n",
  357. SzDecodeScode(GetScode(hResult)));
  358. goto out;
  359. }
  360. }
  361. }
  362. out:
  363. // now set the properties I was asked to save
  364. return hResult=lpOOTID->lpPropData->lpVtbl->SetProps( lpOOTID->lpPropData,
  365. cValues,
  366. lpPropArray,
  367. lppProblems
  368. );
  369. }
  370. /*
  371. * These properties are used and set by the one off dialog.
  372. * These properties combined make up a valid email address and display name
  373. */
  374. // enum and property tag array for getting the properties
  375. enum { ivalootidgPR_DISPLAY_NAME = 0,
  376. ivalootidgPR_FAX_CP_NAME,
  377. ivalootidgPR_COUNTRY_ID,
  378. ivalootidgPR_AREA_CODE,
  379. ivalootidgPR_TEL_NUMBER,
  380. ivalootidgPR_GIVEN_NAME,
  381. ivalootidgPR_SURNAME,
  382. ivalootidgPR_EMAIL_ADDRESS,
  383. ivalootidgMax };
  384. static const SizedSPropTagArray(ivalootidgMax,ptag)=
  385. {
  386. ivalootidgMax,
  387. {
  388. PR_DISPLAY_NAME_A,
  389. PR_FAX_CP_NAME_A,
  390. PR_COUNTRY_ID,
  391. PR_AREA_CODE_A,
  392. PR_TEL_NUMBER_A,
  393. PR_GIVEN_NAME_A,
  394. PR_SURNAME_A,
  395. PR_EMAIL_ADDRESS_A,
  396. }
  397. };
  398. // enum for setting the created properties
  399. enum { /*ivalootidsPR_DISPLAY_NAME = 0,
  400. ivalootidsPR_FAX_CP_NAME,*/
  401. ivalootidsPR_EMAIL_ADDRESS = 0,
  402. ivalootidsPR_PRIMARY_FAX_NUMBER,
  403. ivalootidsMax };
  404. /*****************************************************************************
  405. SaveChanges
  406. *****************************************************************************/
  407. STDMETHODIMP
  408. OOTID_SaveChanges( LPOOTID lpOOTID,
  409. ULONG ulFlags
  410. )
  411. {
  412. HRESULT hResult;
  413. LPSPropValue lpspv=NULL;
  414. SPropValue spv[ivalootidsMax];
  415. ULONG ulcValues;
  416. BOOL bDispName=FALSE;
  417. BOOL bFirstName=FALSE;
  418. BOOL bSurName=FALSE;
  419. BOOL bCPName=FALSE;
  420. PARSEDTELNUMBER sParsedFaxAddr={{TEXT("")},{TEXT("")},{TEXT("")},{TEXT("")}};
  421. ULONG dwCountryCode=0;
  422. TCHAR szEncodedFaxAddress[CANONICAL_NUMBER_SIZE];
  423. LPSTR lpszCanonical=NULL;
  424. #ifdef UNICODE
  425. CHAR szAnsiFaxAddr[CANONICAL_NUMBER_SIZE];
  426. #endif
  427. /*
  428. * Check to see if it is big enough to be my object
  429. */
  430. if (IsBadReadPtr(lpOOTID, SIZEOF(OOTID)))
  431. {
  432. /*
  433. * Not big enough
  434. */
  435. return MakeResult(E_INVALIDARG);
  436. }
  437. /*
  438. * Check to see that it's OOTIDs vtbl
  439. */
  440. if (lpOOTID->lpVtbl != &vtblOOTID)
  441. {
  442. /*
  443. * vtbl not ours
  444. */
  445. return MakeResult(E_INVALIDARG);
  446. }
  447. /*
  448. * Get the properties that make up the email address from the
  449. * mapiprop object
  450. */
  451. hResult = lpOOTID->lpPropData->lpVtbl->GetProps( lpOOTID->lpPropData,
  452. (LPSPropTagArray) &ptag,
  453. 0, /* ansi */
  454. &ulcValues,
  455. &lpspv
  456. );
  457. /*
  458. * Abort in failure. Nothing to do without an email address
  459. */
  460. if (FAILED(hResult))
  461. {
  462. DebugTrace("OOTID_SaveChanges: GetProps failed %s\n",SzDecodeScode(GetScode(hResult)));
  463. goto err;
  464. }
  465. /***************************/
  466. /****** display name *******/
  467. /***************************/
  468. /*
  469. * Need to make the display name
  470. * I believe there must be either a PR_DISPLAY_NAME or a PR_FAX_CP_NAME. If there isn't,
  471. * I'll make one out of the first and last name
  472. */
  473. #ifdef OLD_CODE
  474. // Set the tags
  475. spv[ivalootidsPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
  476. spv[ivalootidsPR_FAX_CP_NAME].ulPropTag = PR_FAX_CP_NAME_A;
  477. // Set the props to the exact value I got from GetProps
  478. spv[ivalootidsPR_DISPLAY_NAME_A].Value.lpszA = lpspv[ivalootidgPR_DISPLAY_NAME].Value.lpszA;
  479. spv[ivalootidsPR_FAX_CP_NAME_A].Value.lpszA = lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA;
  480. if ( (PROP_TYPE(lpspv[ivalootidgPR_DISPLAY_NAME_A].ulPropTag) != PT_ERROR) &&
  481. lstrlenA(lpspv[ivalootidgPR_DISPLAY_NAME].Value.lpszA)
  482. )
  483. {
  484. bDispName = TRUE;
  485. }
  486. if ( (PROP_TYPE(lpspv[ivalootidgPR_FAX_CP_NAME].ulPropTag) != PT_ERROR) &&
  487. lstrlenA(lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA))
  488. {
  489. bCPName = TRUE;
  490. }
  491. // Can't find PR_GIVEN_NAME anywhere in the MAPI or Mail world for now
  492. if ( (PROP_TYPE(lpspv[ivalootidgPR_GIVEN_NAME].ulPropTag) != PT_ERROR) &&
  493. lstrlenA(lpspv[ivalootidgPR_GIVEN_NAME].Value.lpszA))
  494. {
  495. bFirstName = TRUE;
  496. }
  497. if ( (PROP_TYPE(lpspv[ivalootidgPR_SURNAME].ulPropTag) != PT_ERROR) &&
  498. lstrlenA(lpspv[ivalootidgPR_SURNAME].Value.lpszA))
  499. {
  500. bSurName = TRUE;
  501. }
  502. #ifdef EXTENDED_DEBUG
  503. {
  504. TCHAR msg[256];
  505. wsprintf(msg, TEXT("Display name: %s\nCover page name: %s\nGiven name: %s\nSurname: %s\n"),
  506. (bDispName ? lpspv[ivalootidgPR_DISPLAY_NAME].Value.LPSZ : TEXT("")),
  507. (bCPName ? lpspv[ivalootidgPR_FAX_CP_NAME].Value.LPSZ : TEXT("")),
  508. (bFirstName ? lpspv[ivalootidgPR_GIVEN_NAME].Value.LPSZ : TEXT("")),
  509. (bSurName ? lpspv[ivalootidgPR_SURNAME].Value.LPSZ : TEXT("")));
  510. MessageBox(HWND_DESKTOP, msg, TEXT("Debug Message"), MB_OK);
  511. }
  512. #endif
  513. /*
  514. The cases:
  515. (1) No PR_DISPLAY_NAME, but there is PR_GIVEN_NAME or PR_SURNAME: this is the
  516. creation of the entry, and the user entered first/last name in addition
  517. to cover page name. Don't override PR_DISPLAY_NAME with PR_FAX_CP_NAME. Exchange
  518. will use PR_GIVEN_NAME and PR_SURNAME to create PR_DISPLAY_NAME
  519. (2) No PR_DISPLAY_NAME, and also PR_GIVEN_NAME or PR_SURNAME: this is the
  520. creation of the entry, and the user did not enter first/last name.
  521. Override PR_DISPLAY_NAME with PR_FAX_CP_NAME.
  522. (3) There is a PR_DISPLAY_NAME, and the user has changed the PR_FAX_CP_NAME: this
  523. is not a first time entry. The user selected to edit the template, and changed
  524. the cover page name. We are assuming he wants to reflect these changes into
  525. the display name. There were some CompuServe complaints on not doing this.
  526. (4) There is a PR_DISPLAY_NAME, and the user did not change the PR_FAX_CP_NAME: this
  527. is not a first time entry. The user selected to edit the template, but did not
  528. change the cover page name. We are not overriding the display name in this
  529. case, thus providing a way for the user to have a display name different from
  530. the cover page name
  531. */
  532. if (!bDispName)
  533. {
  534. if (bFirstName || bSurName)
  535. // (1)
  536. {
  537. }
  538. else
  539. // (2)
  540. {
  541. // The cover page name is copied into the display name
  542. spv[ivalootidsPR_DISPLAY_NAME].Value.lpszA =
  543. lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA;
  544. }
  545. }
  546. else
  547. {
  548. #ifdef UNICODE
  549. CHAR szAnsiPrevName[ MAX_PATH ];
  550. szAnsiPrevName[0] = 0;
  551. WideCharToMultiByte( CP_ACP, 0, lpOOTID->szPreviousName, -1, szAnsiPrevName, ARRAYSIZE(szAnsiPrevName), NULL, NULL );
  552. if (lstrcmpA(lpspv[ivalootidgPR_FAX_CP_NAME_A].Value.lpszA, szAnsiPrevName))
  553. #else
  554. if (lstrcmp(lpspv[ivalootidgPR_FAX_CP_NAME_A].Value.lpszA, lpOOTID->szPreviousCPName))
  555. #endif
  556. // (3)
  557. {
  558. // The cover page name is copied into the display name
  559. spv[ivalootidsPR_DISPLAY_NAME].Value.lpszA =
  560. lpspv[ivalootidgPR_FAX_CP_NAME].Value.lpszA;
  561. }
  562. else
  563. // (4)
  564. {
  565. }
  566. }
  567. #endif
  568. /***************************/
  569. /****** email address ******/
  570. /***************************/
  571. // Now do the email address
  572. // initialize the email address prop value
  573. spv[ivalootidsPR_EMAIL_ADDRESS].ulPropTag = PR_EMAIL_ADDRESS_A;
  574. // if there is already an email address, and no fax number, this entry
  575. // is not created from the UI (which requires a fax number)
  576. // Generate the address components from the email address
  577. if ( (PROP_TYPE(lpspv[ivalootidgPR_EMAIL_ADDRESS].ulPropTag) != PT_ERROR) &&
  578. (lpspv[ivalootidgPR_EMAIL_ADDRESS].Value.lpszA) &&
  579. (lstrlenA(lpspv[ivalootidgPR_EMAIL_ADDRESS].Value.lpszA)) &&
  580. (PROP_TYPE(lpspv[ivalootidgPR_TEL_NUMBER].ulPropTag) == PT_ERROR)
  581. )
  582. {
  583. spv[ivalootidsPR_EMAIL_ADDRESS].Value.lpszA =
  584. lpspv[ivalootidgPR_EMAIL_ADDRESS].Value.lpszA;
  585. }
  586. // no email address. must compute from properties.
  587. else
  588. {
  589. // Is there a fax number ?
  590. if ( (PROP_TYPE(lpspv[ivalootidgPR_TEL_NUMBER].ulPropTag) != PT_ERROR) &&
  591. (lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA) &&
  592. (lstrlenA(lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA))
  593. )
  594. {
  595. // truncate if necessary. note that the MAPI dialog should limit the user
  596. // to this number of characters anyway
  597. #ifdef UNICODE
  598. sParsedFaxAddr.szTelNumber[0] = 0;
  599. MultiByteToWideChar( CP_ACP, 0,
  600. lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA, -1,
  601. sParsedFaxAddr.szTelNumber,
  602. ARRAYSIZE(sParsedFaxAddr.szTelNumber)
  603. );
  604. #else
  605. lstrcpyn( sParsedFaxAddr.szTelNumber,
  606. lpspv[ivalootidgPR_TEL_NUMBER].Value.lpszA,
  607. ARRAYSIZE(sParsedFaxAddr.szTelNumber)
  608. );
  609. #endif
  610. }
  611. else
  612. {
  613. // must have at least a fax number
  614. // this field is required in my MAPI dialog, so I should never get here
  615. DebugTrace("OOTID_SaveChanges: No PR_FAX_NUMBER (or invalid) on the object\n");
  616. goto err;
  617. }
  618. // Country Code
  619. if (PROP_TYPE(lpspv[ivalootidgPR_COUNTRY_ID].ulPropTag) != PT_ERROR)
  620. {
  621. if (!GetCountryCode(lpspv[ivalootidgPR_COUNTRY_ID].Value.ul, &dwCountryCode))
  622. {
  623. // Use none
  624. dwCountryCode = 0;
  625. }
  626. #ifdef UNICODE
  627. {
  628. CHAR szTemp[ARRAYSIZE(sParsedFaxAddr.szCountryCode)];
  629. itoa(dwCountryCode, szTemp, COUNTRY_CODE_SIZE);
  630. MultiByteToWideChar( CP_ACP, 0,
  631. szTemp, -1,
  632. sParsedFaxAddr.szCountryCode,
  633. ARRAYSIZE(sParsedFaxAddr.szCountryCode)
  634. );
  635. }
  636. #else
  637. itoa(dwCountryCode, sParsedFaxAddr.szCountryCode, COUNTRY_CODE_SIZE);
  638. #endif
  639. }
  640. // Area Code
  641. if ( (PROP_TYPE(lpspv[ivalootidgPR_AREA_CODE].ulPropTag) != PT_ERROR) &&
  642. (lpspv[ivalootidgPR_AREA_CODE].Value.lpszA)
  643. )
  644. {
  645. // if we ended up with a 0 as the area code (error or internal extension,
  646. // this won't be a canonical number and I don't need the area code.
  647. // truncate if necessary
  648. if (dwCountryCode != 0)
  649. {
  650. #ifdef UNICODE
  651. sParsedFaxAddr.szAreaCode[0] = 0;
  652. MultiByteToWideChar( CP_ACP, 0,
  653. lpspv[ivalootidgPR_AREA_CODE].Value.lpszA,
  654. -1,
  655. sParsedFaxAddr.szAreaCode,
  656. ARRAYSIZE(sParsedFaxAddr.szAreaCode)
  657. );
  658. #else
  659. lstrcpyn( sParsedFaxAddr.szAreaCode,
  660. lpspv[ivalootidgPR_AREA_CODE].Value.LPSZ,
  661. ARRAYSIZE(sParsedFaxAddr.szAreaCode)
  662. );
  663. #endif
  664. }
  665. }
  666. // Construct the canonical number from the components
  667. EncodeFaxAddress(szEncodedFaxAddress, &sParsedFaxAddr);
  668. #ifdef UNICODE
  669. szAnsiFaxAddr[0] = 0;
  670. WideCharToMultiByte( CP_ACP, 0, szEncodedFaxAddress, -1, szAnsiFaxAddr, ARRAYSIZE(szAnsiFaxAddr), NULL, NULL );
  671. spv[ivalootidsPR_EMAIL_ADDRESS].Value.lpszA = szAnsiFaxAddr;
  672. #else
  673. spv[ivalootidsPR_EMAIL_ADDRESS].Value.LPSZ = szEncodedFaxAddress;
  674. #endif
  675. }
  676. // now use the same fax number, but w/o the mailbox, to set the
  677. // primary fax property on the telephone pane
  678. spv[ivalootidsPR_PRIMARY_FAX_NUMBER].ulPropTag = PR_PRIMARY_FAX_NUMBER_A;
  679. // don't want the mailbox for this
  680. lpszCanonical = _mbsrchr(spv[ivalootidsPR_EMAIL_ADDRESS].Value.lpszA, '+');
  681. if (lpszCanonical)
  682. spv[ivalootidsPR_PRIMARY_FAX_NUMBER].Value.lpszA = lpszCanonical;
  683. else
  684. spv[ivalootidsPR_PRIMARY_FAX_NUMBER].Value.lpszA = "";
  685. /***************************/
  686. /****** toll list ******/
  687. /***************************/
  688. /* set the email address property value */
  689. hResult= lpOOTID->lpPropData->lpVtbl->SetProps( lpOOTID->lpPropData,
  690. ivalootidsMax,
  691. spv,
  692. NULL
  693. );
  694. if (HR_FAILED(hResult))
  695. {
  696. DebugTrace("OOTID_SaveChanges: SetProps failed %s\n",SzDecodeScode(GetScode(hResult)));
  697. goto err;
  698. }
  699. hResult = lpOOTID->lpPropData->lpVtbl->SaveChanges( lpOOTID->lpPropData,
  700. ulFlags
  701. );
  702. err:
  703. /* free the buffer */
  704. lpOOTID->lpFreeBuff(lpspv);
  705. DebugTraceResult(OOTID_SaveChanges,hResult);
  706. return hResult;
  707. }
  708. /*
  709. - OOTID_OpenProperty
  710. -
  711. * This is needed to support the countries table and dial helper button on the one-off
  712. * template. If the one-off template would only have edit controls nad checkboxes, I
  713. * could call the wrapper object OpenProperty.
  714. *
  715. */
  716. STDMETHODIMP
  717. OOTID_OpenProperty( LPOOTID lpOOTID,
  718. ULONG ulPropTag,
  719. LPCIID lpiid,
  720. ULONG ulInterfaceOptions,
  721. ULONG ulFlags,
  722. LPUNKNOWN * lppUnk
  723. )
  724. {
  725. HRESULT hResult;
  726. /*
  727. * Check to see if it's large enough to hold this object
  728. */
  729. if (IsBadReadPtr(lpOOTID, SIZEOF(OOTID)))
  730. {
  731. /*
  732. * No vtbl found
  733. */
  734. return ResultFromScode(E_INVALIDARG);
  735. }
  736. /*
  737. * Check to see that it's TIDs vtbl
  738. */
  739. if (lpOOTID->lpVtbl != &vtblOOTID)
  740. {
  741. /*
  742. * It's big enough but it's got the wrong vtbl.
  743. */
  744. return ResultFromScode(E_INVALIDARG);
  745. }
  746. /*
  747. * Don't want to check any other parameters here.
  748. * Calls down to wrapped objects will do this for
  749. * me.
  750. */
  751. switch (ulPropTag)
  752. {
  753. // For now, I just call the underlying (my) user object method to handle, which
  754. // means the template ID does not do anything.
  755. case PR_DETAILS_TABLE:
  756. case PR_DDLBX_COUNTRIES_TABLE:
  757. case PR_DIAL_HELPER_BUTTON:
  758. {
  759. hResult = lpOOTID->lpABUser->lpVtbl->OpenProperty(
  760. lpOOTID->lpABUser,
  761. ulPropTag,
  762. lpiid,
  763. ulInterfaceOptions,
  764. ulFlags,
  765. lppUnk);
  766. break;
  767. }
  768. default:
  769. {
  770. hResult = lpOOTID->lpPropData->lpVtbl->OpenProperty(
  771. lpOOTID->lpPropData,
  772. ulPropTag,
  773. lpiid,
  774. ulInterfaceOptions,
  775. ulFlags,
  776. lppUnk);
  777. break;
  778. }
  779. }
  780. DebugTraceResult(OOTID_OpenProperty, hResult);
  781. return hResult;
  782. }