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.

609 lines
17 KiB

  1. /***********************************************************************
  2. *
  3. * OOUSER.C
  4. *
  5. * Microsoft At Work Fax AB One Off Mail User object
  6. * This file contains the code for implementing the Microsoft At Work Fax AB
  7. * One Off Mail user.
  8. *
  9. * Copyright 1992, 1994 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. * 3.17.94 Yoram Yaacovi Update to MAPI build 154
  18. * 4.8.94 Yoram Yaacovi Update to MAPI build 158. Made edit boxes editable
  19. * 4.12.94 Yoram Yaacovi Most props are now set on the OOTID (ootid.c) object
  20. * instead of the OOUSER object.
  21. * 8.8.94 Yoram Yaacovi Updated to MAPI 304 and new spec
  22. *
  23. ***********************************************************************/
  24. #define _FAXAB_OOUSER
  25. #include "faxab.h"
  26. /*
  27. * External functions
  28. */
  29. /*
  30. * Display table control structures for the OneOff property sheet.
  31. */
  32. /*
  33. * Control definitions in abuser.c
  34. */
  35. extern DTBLEDIT editUserDisplayName;
  36. extern DTBLEDIT editUserAreaCode;
  37. extern DTBLEDIT editUserTelNumber;
  38. extern DTBLDDLBX ddlbxCountryCodes;
  39. /*
  40. * General Property Page definition
  41. *
  42. * Should be kept in sync with the one for an AB user in abuser.c
  43. * Could not use the same because of some fields that need to be editable
  44. * here, and read-only for an AB user
  45. */
  46. // extern DTCTL rgdtctlUserGeneral[];
  47. // extern WORD sizeof_rgdtpageUserGeneral;
  48. // extern DTPAGE rgdtpageUser[];
  49. // extern WORD sizeof_rgdtpageUser;
  50. // Description the the Fax AB pane in MAPI dialog description language
  51. static DTCTL rgdtctlOOUserGeneral[] =
  52. {
  53. /* general property page */
  54. { DTCT_PAGE, 0, NULL, 0, NULL, 0, &dtblpage },
  55. /* cover page name static control and edit control */
  56. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_DISPLAY_NAME_LABEL, &dtbllabel },
  57. { DTCT_EDIT, DT_REQUIRED | DT_EDITABLE | DT_ACCEPT_DBCS | DT_SET_IMMEDIATE,
  58. NULL, 0, (LPTSTR)szNoFilter, IDC_RECIP_DISPLAY_NAME, &editUserDisplayName },
  59. /* Country codes label and drop down list box */
  60. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_COUNTRY_CODE_LABEL, &dtbllabel },
  61. { DTCT_DDLBX, DT_EDITABLE, NULL, 0, NULL, IDC_RECIP_COUNTRY_CODE, &ddlbxCountryCodes },
  62. /* Area code and fax number label */
  63. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_FAX_NUMBER_LABEL, &dtbllabel },
  64. /* area code edit control */
  65. { DTCT_EDIT, DT_EDITABLE, NULL, 0, (LPTSTR)szDigitsOnlyFilter, IDC_RECIP_FAX_NUMBER_AREA_CODE, &editUserAreaCode },
  66. /* Fax number static control and edit control */
  67. { DTCT_LABEL, 0, NULL, 0, NULL, IDC_RECIP_FAX_NUMBER_LABEL2, &dtbllabel },
  68. { DTCT_EDIT, DT_REQUIRED | DT_EDITABLE, NULL, 0, (LPTSTR)szDigitsOnlyFilter, IDC_RECIP_FAX_NUMBER, &editUserTelNumber}
  69. };
  70. /*
  71. * The OneOff property sheet definition
  72. * Currently using exactly the same layout as the AB user dialog
  73. * with some fields editable here and read-only for an AB user
  74. */
  75. static DTPAGE rgdtpageOOUser[] =
  76. {
  77. {
  78. ARRAYSIZE(rgdtctlOOUserGeneral),
  79. (LPTSTR)MAKEINTRESOURCE(MAWFRecipient),
  80. TEXT(""),
  81. rgdtctlOOUserGeneral
  82. },
  83. };
  84. /*
  85. * ABOOUser jump table is defined here...
  86. */
  87. ABOOUSER_Vtbl vtblABOOUSER =
  88. {
  89. (ABOOUSER_QueryInterface_METHOD *) ABU_QueryInterface,
  90. (ABOOUSER_AddRef_METHOD *) WRAP_AddRef,
  91. ABOOUSER_Release,
  92. (ABOOUSER_GetLastError_METHOD *) WRAP_GetLastError,
  93. (ABOOUSER_SaveChanges_METHOD *) WRAP_SaveChanges,
  94. (ABOOUSER_GetProps_METHOD *) WRAP_GetProps,
  95. (ABOOUSER_GetPropList_METHOD *) WRAP_GetPropList,
  96. ABOOUSER_OpenProperty,
  97. (ABOOUSER_SetProps_METHOD *) WRAP_SetProps,
  98. (ABOOUSER_DeleteProps_METHOD *) WRAP_DeleteProps,
  99. (ABOOUSER_CopyTo_METHOD *) WRAP_CopyTo,
  100. (ABOOUSER_CopyProps_METHOD *) WRAP_CopyProps,
  101. (ABOOUSER_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
  102. (ABOOUSER_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
  103. };
  104. enum { ivalusrPR_DISPLAY_TYPE = 0,
  105. ivalusrPR_OBJECT_TYPE,
  106. ivalusrPR_ADDRTYPE,
  107. ivalusrPR_COUNTRY_ID,
  108. ivalusrPR_AREA_CODE,
  109. #ifdef INIT_TEL_NUMBER
  110. ivalusrPR_TEL_NUMBER,
  111. #endif
  112. ivalusrPR_TEMPLATEID,
  113. cvalusrMax };
  114. /*************************************************************************
  115. *
  116. - HrNewFaxOOUser
  117. -
  118. * Creates the IMAPIProp associated with a one off mail user.
  119. *
  120. *
  121. */
  122. HRESULT
  123. HrNewFaxOOUser( LPMAILUSER * lppMAPIPropEntry,
  124. ULONG * lpulObjType,
  125. ULONG cbEntryID,
  126. LPENTRYID lpEntryID,
  127. LPABLOGON lpABPLogon,
  128. LPCIID lpInterface,
  129. HINSTANCE hLibrary,
  130. LPALLOCATEBUFFER lpAllocBuff,
  131. LPALLOCATEMORE lpAllocMore,
  132. LPFREEBUFFER lpFreeBuff,
  133. LPMALLOC lpMalloc
  134. )
  135. {
  136. LPABOOUSER lpABOOUser = NULL;
  137. SCODE sc;
  138. HRESULT hr = hrSuccess;
  139. LPPROPDATA lpPropData = NULL;
  140. SPropValue spv[cvalusrMax];
  141. #ifdef UNICODE
  142. CHAR szAnsiAreaCode[ AREA_CODE_SIZE ];
  143. CHAR szEMT[ MAX_PATH ];
  144. #endif
  145. /* Do I support this interface?? */
  146. if (lpInterface)
  147. {
  148. if ( memcmp(lpInterface, &IID_IMailUser, SIZEOF(IID)) &&
  149. memcmp(lpInterface, &IID_IMAPIProp, SIZEOF(IID)) &&
  150. memcmp(lpInterface, &IID_IUnknown, SIZEOF(IID))
  151. )
  152. {
  153. DebugTraceSc(HrNewSampOOUser, MAPI_E_INTERFACE_NOT_SUPPORTED);
  154. return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  155. }
  156. }
  157. /*
  158. * Allocate space for the ABOOUser structure
  159. */
  160. sc = lpAllocBuff(SIZEOF(ABOOUSER), (LPVOID *) & lpABOOUser);
  161. if (FAILED(sc))
  162. {
  163. hr = ResultFromScode (sc);
  164. DebugTraceResult(NewFaxUser, hr);
  165. goto err;
  166. }
  167. lpABOOUser->lpVtbl = &vtblABOOUSER;
  168. lpABOOUser->lcInit = 1;
  169. lpABOOUser->hResult = hrSuccess;
  170. lpABOOUser->idsLastError = 0;
  171. lpABOOUser->hLibrary = hLibrary;
  172. lpABOOUser->lpAllocBuff = lpAllocBuff;
  173. lpABOOUser->lpAllocMore = lpAllocMore;
  174. lpABOOUser->lpFreeBuff = lpFreeBuff;
  175. lpABOOUser->lpMalloc = lpMalloc;
  176. lpABOOUser->lpABLogon = lpABPLogon;
  177. lpABOOUser->lpTDatDDListBox = NULL;
  178. /*
  179. * Create lpPropData
  180. */
  181. sc = CreateIProp( (LPIID) &IID_IMAPIPropData,
  182. lpAllocBuff,
  183. lpAllocMore,
  184. lpFreeBuff,
  185. lpMalloc,
  186. &lpPropData
  187. );
  188. if (FAILED(sc))
  189. {
  190. hr = ResultFromScode (sc);
  191. goto err;
  192. }
  193. /*
  194. * Set up the initial set of properties
  195. */
  196. spv[ivalusrPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  197. spv[ivalusrPR_DISPLAY_TYPE].Value.l = DT_MAILUSER;
  198. spv[ivalusrPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  199. spv[ivalusrPR_OBJECT_TYPE].Value.l = MAPI_MAILUSER;
  200. spv[ivalusrPR_ADDRTYPE].ulPropTag = PR_ADDRTYPE_A;
  201. #ifdef UNICODE
  202. szEMT[0] = 0;
  203. WideCharToMultiByte( CP_ACP, 0, lpszEMT, -1, szEMT, ARRAYSIZE(szEMT), NULL, NULL );
  204. spv[ivalusrPR_ADDRTYPE].Value.lpszA = szEMT;
  205. #else
  206. spv[ivalusrPR_ADDRTYPE].Value.LPSZ = lpszEMT;
  207. #endif
  208. spv[ivalusrPR_TEMPLATEID].ulPropTag = PR_TEMPLATEID;
  209. spv[ivalusrPR_TEMPLATEID].Value.bin.cb = SIZEOF(OOUSER_ENTRYID);
  210. spv[ivalusrPR_TEMPLATEID].Value.bin.lpb = (LPBYTE) lpEntryID;
  211. spv[ivalusrPR_COUNTRY_ID].ulPropTag = PR_COUNTRY_ID;
  212. /*
  213. spv[ivalusrPR_COUNTRY_ID].Value.ul = 1; // U.S.;
  214. */
  215. spv[ivalusrPR_COUNTRY_ID].Value.ul = GetCurrentLocationCountryID();
  216. // display the area code of the current location
  217. spv[ivalusrPR_AREA_CODE].ulPropTag = PR_AREA_CODE_A;
  218. #ifdef UNICODE
  219. szAnsiAreaCode[0] = 0;
  220. WideCharToMultiByte( CP_ACP, 0, GetCurrentLocationAreaCode(), -1, szAnsiAreaCode, ARRAYSIZE(szAnsiAreaCode), NULL, NULL );
  221. spv[ivalusrPR_AREA_CODE].Value.lpszA = szAnsiAreaCode;
  222. #else
  223. spv[ivalusrPR_AREA_CODE].Value.lpszA = GetCurrentLocationAreaCode();
  224. #endif
  225. #ifdef INIT_TEL_NUMBER
  226. // initialize the fax number, so that it won't be PT_ERROR
  227. spv[ivalusrPR_TEL_NUMBER].ulPropTag = PR_TEL_NUMBER_A;
  228. spv[ivalusrPR_TEL_NUMBER].Value.lpszA = (LPSTR) "";
  229. #endif
  230. /*
  231. * Note that we're using our entryID for our templateID.
  232. * This is a really simple way to implement templateIDs.
  233. * (See TID.C)
  234. */
  235. /*
  236. * Set the default properties
  237. */
  238. hr = lpPropData->lpVtbl->SetProps( lpPropData,
  239. cvalusrMax,
  240. spv,
  241. NULL
  242. );
  243. if (HR_FAILED(hr))
  244. {
  245. DebugTraceResult(NewFaxOOUser, hr);
  246. goto err;
  247. }
  248. (void) lpPropData->lpVtbl->HrSetObjAccess(lpPropData, IPROP_READWRITE);
  249. lpABOOUser->lpPropData = (LPMAPIPROP) lpPropData;
  250. InitializeCriticalSection(&lpABOOUser->cs);
  251. *lppMAPIPropEntry = (LPVOID) lpABOOUser;
  252. *lpulObjType = MAPI_MAILUSER;
  253. out:
  254. DebugTraceResult(HrNewSampOOUser, hr);
  255. return hr;
  256. err:
  257. if (lpPropData)
  258. lpPropData->lpVtbl->Release(lpPropData);
  259. lpFreeBuff( lpABOOUser );
  260. goto out;
  261. }
  262. /***************************************************
  263. *
  264. * The actual ABOOUser methods
  265. */
  266. /**************************************************
  267. *
  268. - ABOOUSER_Release
  269. -
  270. * Decrement lpInit.
  271. * When lcInit == 0, free up the lpABOOUser structure
  272. *
  273. */
  274. STDMETHODIMP_(ULONG)
  275. ABOOUSER_Release (LPABOOUSER lpABOOUser)
  276. {
  277. LONG lcInit;
  278. /*
  279. * Check to see if it's big enough to hold this object
  280. */
  281. if (IsBadReadPtr(lpABOOUser, SIZEOF(ABOOUSER)))
  282. {
  283. /*
  284. * Not large enough
  285. */
  286. return 1;
  287. }
  288. /*
  289. * Check to see that it's the correct vtbl
  290. */
  291. if (lpABOOUser->lpVtbl != &vtblABOOUSER)
  292. {
  293. /*
  294. * Not my vtbl
  295. */
  296. return 1;
  297. }
  298. EnterCriticalSection(&lpABOOUser->cs);
  299. lcInit = --lpABOOUser->lcInit;
  300. LeaveCriticalSection(&lpABOOUser->cs);
  301. if (lcInit == 0)
  302. {
  303. /*
  304. * Get rid of the lpPropData
  305. */
  306. lpABOOUser->lpPropData->lpVtbl->Release(lpABOOUser->lpPropData);
  307. /*
  308. * Get rid of the country codes table
  309. */
  310. if (lpABOOUser->lpTDatDDListBox)
  311. lpABOOUser->lpTDatDDListBox->lpVtbl->Release(lpABOOUser->lpTDatDDListBox);
  312. /*
  313. * Destroy the critical section for this object
  314. */
  315. DeleteCriticalSection(&lpABOOUser->cs);
  316. /*
  317. * Set the vtbl to NULL. This way the client will find out
  318. * real fast if it's calling a method on a released object. That is,
  319. * the client will crash. Hopefully, this will happen during the
  320. * development stage of the client.
  321. */
  322. lpABOOUser->lpVtbl = NULL;
  323. /*
  324. * Need to free the object
  325. */
  326. lpABOOUser->lpFreeBuff( lpABOOUser );
  327. return 0;
  328. }
  329. return lcInit;
  330. }
  331. /*************************************************************************
  332. *
  333. - ABOOUSER_OpenProperty
  334. -
  335. *
  336. * This is how we get the display table associated with this users
  337. * details screen.
  338. */
  339. STDMETHODIMP
  340. ABOOUSER_OpenProperty( LPABOOUSER lpABOOUser,
  341. ULONG ulPropTag,
  342. LPCIID lpiid,
  343. ULONG ulInterfaceOptions,
  344. ULONG ulFlags,
  345. LPUNKNOWN * lppUnk)
  346. {
  347. LPMAPITABLE lpDisplayTable=NULL;
  348. /*
  349. * Since the default is that we do not support opening this
  350. * object, we can initialize our hResult here.
  351. */
  352. HRESULT hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  353. /*
  354. * Check to see if it can be pointing to the right structure.
  355. */
  356. if (IsBadReadPtr(lpABOOUser, SIZEOF(ABOOUSER)))
  357. {
  358. /*
  359. * Not big enough to be my object
  360. */
  361. hResult = ResultFromScode(E_INVALIDARG);
  362. goto out;
  363. }
  364. /*
  365. * Check to see that it's got the correct vtbl
  366. */
  367. if (lpABOOUser->lpVtbl != &vtblABOOUSER)
  368. {
  369. /*
  370. * Not my vtbl
  371. */
  372. hResult = ResultFromScode(E_INVALIDARG);
  373. goto out;
  374. }
  375. if (IsBadReadPtr(lpiid, SIZEOF(IID)))
  376. {
  377. /*
  378. * Interfaces are required on this method.
  379. */
  380. hResult = ResultFromScode(E_ACCESSDENIED);
  381. goto out;
  382. }
  383. if (ulInterfaceOptions & ~MAPI_UNICODE )
  384. {
  385. /*
  386. * Only UNICODE flag should be set for any of the objects that might
  387. * be returned from this object.
  388. */
  389. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  390. goto out;
  391. }
  392. if ( ulInterfaceOptions & MAPI_UNICODE )
  393. {
  394. hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  395. goto out;
  396. }
  397. if (ulFlags & ~(MAPI_CREATE|MAPI_MODIFY|MAPI_DEFERRED_ERRORS))
  398. {
  399. /*
  400. * Don't understand the flags that were passed in
  401. */
  402. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  403. goto out;
  404. }
  405. if (ulFlags & MAPI_CREATE)
  406. {
  407. /*
  408. * Don't support creating any sub-objects
  409. */
  410. hResult = ResultFromScode(E_ACCESSDENIED);
  411. goto out;
  412. }
  413. if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN)))
  414. {
  415. /*
  416. * Got to be able to return an object
  417. */
  418. hResult = ResultFromScode(E_INVALIDARG);
  419. goto out;
  420. }
  421. // If the caller is trying to open a table property and is not expecting a table interface..
  422. switch (ulPropTag)
  423. {
  424. case PR_DETAILS_TABLE:
  425. case PR_DDLBX_COUNTRIES_TABLE:
  426. if (memcmp( lpiid, &IID_IMAPITable, SIZEOF(IID) ))
  427. {
  428. // ... we will abort right here
  429. hResult = ResultFromScode(E_NOINTERFACE);
  430. goto out;
  431. }
  432. break;
  433. default:
  434. break;
  435. }
  436. /* Check to see if I need a display table*/
  437. switch (ulPropTag)
  438. {
  439. case PR_DETAILS_TABLE:
  440. /* Looking for the display table*/
  441. /* // Going to use the AB user display array, but make all editable
  442. // fields editable
  443. for (i=0; i < (sizeof_rgdtpageUserGeneral / sizeof(DTCTL)); i++)
  444. if ((rgdtctlUserGeneral[i].ulCtlType == DTCT_EDIT) ||
  445. (rgdtctlUserGeneral[i].ulCtlType == DTCT_DDLBX))
  446. */
  447. /* Create a display table */
  448. hResult = BuildDisplayTable( lpABOOUser->lpAllocBuff,
  449. lpABOOUser->lpAllocMore,
  450. lpABOOUser->lpFreeBuff,
  451. lpABOOUser->lpMalloc,
  452. lpABOOUser->hLibrary,
  453. ARRAYSIZE(rgdtpageOOUser),
  454. rgdtpageOOUser,
  455. 0,
  456. &lpDisplayTable,
  457. NULL
  458. );
  459. #ifdef WRAP_TABLE
  460. HrNewTableWrap(&lpDisplayTable);
  461. #endif
  462. *lppUnk = (LPUNKNOWN) lpDisplayTable;
  463. if (HR_FAILED(hResult))
  464. {
  465. goto out;
  466. }
  467. /*
  468. * We're succeeding. Ensure our hResult is set properly
  469. */
  470. hResult = hrSuccess;
  471. break;
  472. case PR_DDLBX_COUNTRIES_TABLE:
  473. // This table is not changing dynamically. No need to rebuild if already built.
  474. if (!lpABOOUser->lpTDatDDListBox)
  475. {
  476. hResult = HrBuildDDLBXCountriesTable((LPABUSER) lpABOOUser);
  477. if (HR_FAILED(hResult))
  478. goto out;
  479. }
  480. Assert(lpABOOUser->lpTDatDDListBox);
  481. /* Get a view from the TAD*/
  482. hResult = lpABOOUser->lpTDatDDListBox->lpVtbl->HrGetView(
  483. lpABOOUser->lpTDatDDListBox,
  484. NULL,
  485. NULL,
  486. 0,
  487. (LPMAPITABLE *) lppUnk);
  488. break;
  489. default:
  490. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  491. break;
  492. }
  493. out:
  494. DebugTraceResult(ABOOUSER_OpenProperty, hResult);
  495. return hResult;
  496. }
  497. /**********************************************************************
  498. *
  499. * Private functions
  500. */
  501. #undef _FAXAB_OOUSER