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.

1595 lines
36 KiB

  1. /***********************************************************************
  2. *
  3. * ROOT.C
  4. *
  5. *
  6. * Sample AB Root object
  7. * - This file contains the code for implementing the Sample AB
  8. * root object and the hierarchy table.
  9. *
  10. * The Root container object is returned via an ABPOpenEntry() with a
  11. * 0-sized entryid. It only has a limited set of properties available on
  12. * it. The most useful method on it is GetHierarchyTable() which returns
  13. * the root hierarchy associated with this provider.
  14. *
  15. * The hierarchy table has only a single row in it. The row represents the
  16. * single .FAB file which this provider browses. If a provider wanted to
  17. * browse many different lists, it would have multiple rows.
  18. *
  19. * The following routines are implemented in this file:
  20. *
  21. *
  22. * To implement the Root container object:
  23. *
  24. * HrNewROOT
  25. * SetErrorSz
  26. * ROOT_QueryInterface
  27. * ROOT_AddRef
  28. * ROOT_Release
  29. * ROOT_GetLastError
  30. * ROOT_SaveChanges
  31. * ROOT_OpenProperty
  32. * ROOT_GetContentsTable
  33. * ROOT_GetHierarchyTable
  34. * ROOT_OpenEntry
  35. * ROOT_CreateEntry
  36. * ROOT_CopyEntries
  37. * ROOT_DeleteEntries
  38. * ROOT_ResolveNames
  39. *
  40. * Copyright 1992, 1993, 1994 Microsoft Corporation. All Rights Reserved.
  41. *
  42. * Revision History:
  43. *
  44. * When Who What
  45. * -------- ------------------ ---------------------------------------
  46. * 1.1.94 MAPI Original source from MAPI sample AB Provider
  47. * 1.27.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
  48. * 3.6.94 Yoram Yaacovi Update to MAPI build 154
  49. * 8.3.94 Yoram Yaacovi Incorporated MAPI 304 changes
  50. * 10.3.94 Yoram Yaacovi Incorporated MAPI 313 changes, mainly added ResolveNames
  51. * 11.4.94 Yoram Yaacovi Incorporated MAPI 318 changes
  52. *
  53. ***********************************************************************/
  54. #define _FAXAB_ROOT
  55. #include "faxab.h"
  56. /*
  57. * Defined in ABP.C
  58. */
  59. extern MAPIUID muidABMAWF;
  60. /*
  61. * Root vtbl is filled in here
  62. */
  63. static const ROOT_Vtbl vtblROOT =
  64. {
  65. ROOT_QueryInterface,
  66. ROOT_AddRef,
  67. ROOT_Release,
  68. ROOT_GetLastError,
  69. ROOT_SaveChanges,
  70. (ROOT_GetProps_METHOD *) WRAP_GetProps,
  71. (ROOT_GetPropList_METHOD *) WRAP_GetPropList,
  72. ROOT_OpenProperty,
  73. (ROOT_SetProps_METHOD *) WRAP_SetProps,
  74. (ROOT_DeleteProps_METHOD *) WRAP_DeleteProps,
  75. (ROOT_CopyTo_METHOD *) WRAP_CopyTo,
  76. (ROOT_CopyProps_METHOD *) WRAP_CopyProps,
  77. (ROOT_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
  78. (ROOT_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
  79. ROOT_GetContentsTable,
  80. ROOT_GetHierarchyTable,
  81. ROOT_OpenEntry,
  82. ROOT_SetSearchCriteria,
  83. ROOT_GetSearchCriteria,
  84. ROOT_CreateEntry,
  85. ROOT_CopyEntries,
  86. ROOT_DeleteEntries,
  87. ROOT_ResolveNames
  88. };
  89. /*
  90. * Default properties in this object
  91. */
  92. enum { ivalPR_DISPLAY_TYPE = 0,
  93. ivalPR_OBJECT_TYPE,
  94. ivalPR_ENTRYID,
  95. ivalPR_RECORD_KEY,
  96. ivalPR_SEARCH_KEY,
  97. ivalPR_DISPLAY_NAME,
  98. ivalPR_CONTAINER_FLAGS,
  99. cvalMax };
  100. /*
  101. - HrNewROOT
  102. -
  103. * Creates a new Root Container object. This object is created
  104. * when an lpABLogon::OpenEntry() is called with a 0-sized entryid.
  105. *
  106. *
  107. */
  108. HRESULT
  109. HrNewROOT( LPABCONT * lppROOT,
  110. ULONG * lpulObjType,
  111. LPABLOGON lpABPLogon,
  112. LPCIID lpInterface,
  113. HINSTANCE hLibrary,
  114. LPALLOCATEBUFFER lpAllocBuff,
  115. LPALLOCATEMORE lpAllocMore,
  116. LPFREEBUFFER lpFreeBuff,
  117. LPMALLOC lpMalloc
  118. )
  119. {
  120. LPROOT lpROOT = NULL;
  121. SCODE scode;
  122. LPPROPDATA lpPropData = NULL;
  123. SPropValue spv[cvalMax];
  124. HRESULT hResult;
  125. #ifdef UNICODE
  126. CHAR szAnsiDisplayName[MAX_ROOT_NAME];
  127. #endif
  128. TCHAR szDisplayName[MAX_ROOT_NAME];
  129. LPTSTR pszDisplayName = (LPTSTR) szDisplayName;
  130. SCODE sc;
  131. DIR_ENTRYID eidRoot = { {0, 0, 0, 0},
  132. MUIDABMAWF,
  133. MAWF_VERSION,
  134. MAWF_DIRECTORY };
  135. /* Do I support this interface?? */
  136. if (lpInterface)
  137. {
  138. if ( memcmp(lpInterface, &IID_IUnknown, SIZEOF(IID)) &&
  139. memcmp(lpInterface, &IID_IMAPIProp, SIZEOF(IID)) &&
  140. memcmp(lpInterface, &IID_IMAPIContainer, SIZEOF(IID)) &&
  141. memcmp(lpInterface, &IID_IABContainer, SIZEOF(IID))
  142. )
  143. {
  144. DebugTraceSc(HrNewROOT, MAPI_E_INTERFACE_NOT_SUPPORTED);
  145. return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  146. }
  147. }
  148. /*
  149. * Allocate space for the ROOT structure
  150. */
  151. scode = lpAllocBuff( SIZEOF(ROOT), (LPVOID *) &lpROOT );
  152. if (FAILED(scode))
  153. {
  154. hResult = ResultFromScode(scode);
  155. goto err;
  156. }
  157. lpROOT->lpVtbl = &vtblROOT;
  158. lpROOT->lcInit = 1;
  159. lpROOT->hResult = hrSuccess;
  160. lpROOT->idsLastError = 0;
  161. lpROOT->hLibrary = hLibrary;
  162. lpROOT->lpAllocBuff = lpAllocBuff;
  163. lpROOT->lpAllocMore = lpAllocMore;
  164. lpROOT->lpFreeBuff = lpFreeBuff;
  165. lpROOT->lpMalloc = lpMalloc;
  166. lpROOT->lpABLogon = lpABPLogon;
  167. /*
  168. * Create a property storage object
  169. */
  170. scode = CreateIProp( (LPIID) &IID_IMAPIPropData,
  171. lpAllocBuff,
  172. lpAllocMore,
  173. lpFreeBuff,
  174. lpMalloc,
  175. &lpPropData
  176. );
  177. if (FAILED(scode))
  178. {
  179. hResult = ResultFromScode(scode);
  180. goto err;
  181. }
  182. /*
  183. * Set up initial set of properties associated with this
  184. * container.
  185. */
  186. spv[ivalPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  187. spv[ivalPR_DISPLAY_TYPE].Value.l = 0; /* undefined for now */
  188. spv[ivalPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  189. spv[ivalPR_OBJECT_TYPE].Value.l = MAPI_ABCONT;
  190. spv[ivalPR_ENTRYID].ulPropTag = PR_ENTRYID;
  191. spv[ivalPR_ENTRYID].Value.bin.cb = SIZEOF(DIR_ENTRYID);
  192. spv[ivalPR_ENTRYID].Value.bin.lpb = (LPBYTE) &eidRoot;
  193. spv[ivalPR_RECORD_KEY].ulPropTag = PR_RECORD_KEY;
  194. spv[ivalPR_RECORD_KEY].Value.bin.cb = SIZEOF(DIR_ENTRYID);
  195. spv[ivalPR_RECORD_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  196. spv[ivalPR_SEARCH_KEY].ulPropTag = PR_SEARCH_KEY;
  197. spv[ivalPR_SEARCH_KEY].Value.bin.cb = sizeof(DIR_ENTRYID);
  198. spv[ivalPR_SEARCH_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  199. sc = ScLoadString( IDS_ADDRESS_BOOK_ROOT_CONT,
  200. MAX_ROOT_NAME,
  201. NULL,
  202. hLibrary,
  203. (LPTSTR *) &pszDisplayName
  204. );
  205. if (FAILED(sc))
  206. {
  207. hResult = ResultFromScode(sc);
  208. goto out;
  209. }
  210. spv[ivalPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
  211. #ifdef UNICODE
  212. WideCharToMultiByte( CP_ACP, 0, szDisplayName, -1, szAnsiDisplayName, ARRAYSIZE(szAnsiDisplayName), NULL, NULL );
  213. spv[ivalPR_DISPLAY_NAME].Value.lpszA = szAnsiDisplayName;
  214. #else
  215. spv[ivalPR_DISPLAY_NAME].Value.lpszA = szDisplayName;
  216. #endif
  217. spv[ivalPR_CONTAINER_FLAGS].ulPropTag = PR_CONTAINER_FLAGS;
  218. spv[ivalPR_CONTAINER_FLAGS].Value.l = AB_SUBCONTAINERS;
  219. /*
  220. * Set the default properties
  221. */
  222. hResult = lpPropData->lpVtbl->SetProps( lpPropData,
  223. cvalMax,
  224. spv,
  225. NULL
  226. );
  227. if (HR_FAILED(hResult))
  228. {
  229. goto err;
  230. }
  231. (void) lpPropData->lpVtbl->HrSetObjAccess(lpPropData, IPROP_READONLY);
  232. lpROOT->lpPropData = (LPMAPIPROP) lpPropData;
  233. InitializeCriticalSection(&lpROOT->cs);
  234. *lpulObjType = MAPI_ABCONT;
  235. *lppROOT = (LPVOID) lpROOT;
  236. out:
  237. DebugTraceResult(HrNewROOT, hResult);
  238. return hResult;
  239. err:
  240. /*
  241. * free the root object
  242. */
  243. lpFreeBuff (lpROOT);
  244. /*
  245. * free the prop data
  246. */
  247. if (lpPropData)
  248. lpPropData->lpVtbl->Release(lpPropData);
  249. goto out;
  250. }
  251. /*************************************************************************
  252. *
  253. *
  254. - SetErrorIDS
  255. -
  256. * Handles remembering the last error string associated with an object.
  257. * This string is retrieved by the method GetLastError()
  258. *
  259. *
  260. */
  261. VOID
  262. SetErrorIDS(LPVOID lpObject, HRESULT hResult, UINT ids)
  263. {
  264. ((LPROOT) lpObject)->hResult = hResult;
  265. ((LPROOT) lpObject)->idsLastError = ids;
  266. }
  267. /*
  268. - ROOT_QueryInterface
  269. -
  270. * Supports QI'ing to IUnknown, IMAPIProp, IMAPIContainer, and IABContainer.
  271. *
  272. */
  273. STDMETHODIMP
  274. ROOT_QueryInterface( LPROOT lpROOT,
  275. REFIID lpiid,
  276. LPVOID FAR * lppNewObj
  277. )
  278. {
  279. HRESULT hr = hrSuccess;
  280. /*
  281. * Check to see if it has a lpVtbl object member
  282. */
  283. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  284. {
  285. /*
  286. * Not large enough
  287. */
  288. hr = ResultFromScode(E_INVALIDARG);
  289. goto out;
  290. }
  291. /*
  292. * Check to see that the Vtbl is large enough to include this method
  293. */
  294. if (IsBadReadPtr(lpROOT->lpVtbl,
  295. offsetof(ROOT_Vtbl, QueryInterface)+SIZEOF(ROOT_QueryInterface_METHOD *)))
  296. {
  297. /*
  298. * Jump table not derived from IUnknown
  299. */
  300. hr = ResultFromScode(E_INVALIDARG);
  301. goto out;
  302. }
  303. /*
  304. * Check to see if the method is the same
  305. */
  306. if (ROOT_QueryInterface != lpROOT->lpVtbl->QueryInterface)
  307. {
  308. /*
  309. * Wrong object - the object passed doesn't have this
  310. * method.
  311. */
  312. hr = ResultFromScode(E_INVALIDARG);
  313. goto out;
  314. }
  315. /* Check other parameters */
  316. if ( IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)) ||
  317. IsBadWritePtr(lppNewObj, (UINT) SIZEOF(LPVOID))
  318. )
  319. {
  320. hr = ResultFromScode(E_INVALIDARG);
  321. goto out;
  322. }
  323. /* See if the requested interface is one of ours */
  324. if ( memcmp(lpiid, &IID_IUnknown, SIZEOF(IID)) &&
  325. memcmp(lpiid, &IID_IMAPIProp, SIZEOF(IID)) &&
  326. memcmp(lpiid, &IID_IMAPIContainer, SIZEOF(IID)) &&
  327. memcmp(lpiid, &IID_IABContainer, SIZEOF(IID)))
  328. {
  329. *lppNewObj = NULL; /* OLE requires zeroing [out] parameter */
  330. hr = ResultFromScode(E_NOINTERFACE);
  331. goto out;
  332. }
  333. /* We'll do this one. Bump the usage count and return a new pointer. */
  334. EnterCriticalSection(&lpROOT->cs);
  335. ++lpROOT->lcInit;
  336. LeaveCriticalSection(&lpROOT->cs);
  337. *lppNewObj = lpROOT;
  338. out:
  339. DebugTraceResult(ROOT_QueryInterface, hr);
  340. return hr;
  341. }
  342. /**************************************************
  343. *
  344. - ROOT_AddRef
  345. -
  346. * Increment lcInit
  347. *
  348. */
  349. STDMETHODIMP_(ULONG) ROOT_AddRef(LPROOT lpROOT)
  350. {
  351. LONG lcInit;
  352. /*
  353. * Check to see if it has a lpVtbl object member
  354. */
  355. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  356. {
  357. /*
  358. * Not large enough
  359. */
  360. return 1;
  361. }
  362. /*
  363. * Check to see that the Vtbl is large enough to include this method
  364. */
  365. if (IsBadReadPtr(lpROOT->lpVtbl,
  366. offsetof(ROOT_Vtbl, AddRef)+SIZEOF(ROOT_AddRef_METHOD *)))
  367. {
  368. /*
  369. * Jump table not derived from IUnknown
  370. */
  371. return 1;
  372. }
  373. /*
  374. * Check to see if the method is the same
  375. */
  376. if (ROOT_AddRef != lpROOT->lpVtbl->AddRef)
  377. {
  378. /*
  379. * Wrong object - the object passed doesn't have this
  380. * method.
  381. */
  382. return 1;
  383. }
  384. EnterCriticalSection(&lpROOT->cs);
  385. lcInit = ++lpROOT->lcInit;
  386. LeaveCriticalSection(&lpROOT->cs);
  387. return lcInit;
  388. }
  389. /**************************************************
  390. *
  391. - ROOT_Release
  392. -
  393. * Decrement lcInit.
  394. * When lcInit == 0, free up the lpROOT structure
  395. *
  396. */
  397. STDMETHODIMP_(ULONG) ROOT_Release(LPROOT lpROOT)
  398. {
  399. LONG lcInit;
  400. /*
  401. * Check to see if it can be a ROOT object
  402. */
  403. if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
  404. {
  405. /*
  406. * Not large enough
  407. */
  408. return 1;
  409. }
  410. /*
  411. * Check to see that it's ROOTs vtbl
  412. */
  413. if (lpROOT->lpVtbl != &vtblROOT)
  414. {
  415. /*
  416. * Not my jump table
  417. */
  418. return 1;
  419. }
  420. EnterCriticalSection(&lpROOT->cs);
  421. lcInit = --lpROOT->lcInit;
  422. LeaveCriticalSection(&lpROOT->cs);
  423. if (lcInit == 0)
  424. {
  425. /*
  426. * Delete our critical section
  427. */
  428. DeleteCriticalSection(&lpROOT->cs);
  429. /*
  430. * Set the vtbl to NULL. This way the client will find out
  431. * real fast if it's calling a method on a released object. That is,
  432. * the client will crash. Hopefully, this will happen during the
  433. * development stage of the client.
  434. */
  435. lpROOT->lpVtbl = NULL;
  436. /*
  437. * free the property storage object
  438. */
  439. if (lpROOT->lpPropData)
  440. lpROOT->lpPropData->lpVtbl->Release(lpROOT->lpPropData);
  441. /*
  442. * Free the object
  443. */
  444. lpROOT->lpFreeBuff(lpROOT);
  445. return 0;
  446. }
  447. return lcInit;
  448. }
  449. /*
  450. - ROOT_GetLastError
  451. -
  452. * Returns a string associated with the last hResult
  453. * returned by the ROOT object.
  454. *
  455. */
  456. STDMETHODIMP
  457. ROOT_GetLastError( LPROOT lpROOT,
  458. HRESULT hError,
  459. ULONG ulFlags,
  460. LPMAPIERROR FAR * lppMapiError )
  461. {
  462. SCODE scode;
  463. HRESULT hResult=hrSuccess;
  464. LPTSTR lpszMessage = NULL;
  465. /*
  466. * Validate parameters
  467. */
  468. /*
  469. * Check to see if it has a lpVtbl object member
  470. */
  471. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  472. {
  473. /*
  474. * Not large enough
  475. */
  476. hResult = MakeResult(E_INVALIDARG);
  477. return hResult;
  478. }
  479. /*
  480. * Check to see that the Vtbl is large enough to include this method
  481. */
  482. if (IsBadReadPtr(lpROOT->lpVtbl,
  483. offsetof(ROOT_Vtbl, GetLastError)+SIZEOF(ROOT_GetLastError_METHOD *)))
  484. {
  485. /*
  486. * Jump table not derived from IUnknown
  487. */
  488. hResult = MakeResult(E_INVALIDARG);
  489. return hResult;
  490. }
  491. /*
  492. * Check to see if the method is the same
  493. */
  494. if (ROOT_GetLastError != lpROOT->lpVtbl->GetLastError)
  495. {
  496. /*
  497. * Wrong object - the object passed doesn't have this
  498. * method.
  499. */
  500. hResult = ResultFromScode(E_INVALIDARG);
  501. DebugTraceResult(ROOT_GetLastError, hResult);
  502. return hResult;
  503. }
  504. /*
  505. * Validate ulFlags
  506. */
  507. if (ulFlags & ~MAPI_UNICODE)
  508. {
  509. /*
  510. * Unknown flag
  511. */
  512. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  513. DebugTraceResult(ROOT_GetLastError, hResult);
  514. return hResult;
  515. }
  516. /*
  517. * NOTE: We don't handle UNICODE yet. Everything is
  518. * assumed to be working in 8-bit char mode.
  519. */
  520. if (ulFlags & MAPI_UNICODE)
  521. {
  522. hResult = ResultFromScode(MAPI_E_BAD_CHARWIDTH);
  523. DebugTraceResult(ROOT_GetLastError, hResult);
  524. return hResult;
  525. }
  526. /*
  527. * Validate lppMapiError.
  528. */
  529. if (IsBadWritePtr(lppMapiError, SIZEOF(LPMAPIERROR)))
  530. {
  531. hResult = ResultFromScode(E_INVALIDARG);
  532. DebugTraceResult(ROOT_GetLastError, hResult);
  533. return hResult;
  534. }
  535. EnterCriticalSection(&lpROOT->cs);
  536. if ((hError != hrSuccess) && (hError == lpROOT->hResult))
  537. {
  538. scode = lpROOT->lpAllocBuff( SIZEOF( MAPIERROR ), lppMapiError );
  539. if ( FAILED( scode ) )
  540. {
  541. hResult = ResultFromScode(scode);
  542. goto ret;
  543. }
  544. RtlZeroMemory( *lppMapiError, SIZEOF( MAPIERROR ) );
  545. (*lppMapiError)->ulVersion = MAPI_ERROR_VERSION;
  546. /*
  547. * Get the MAPI Allocated string associated with the last error
  548. */
  549. scode = ScLoadString(lpROOT->idsLastError,
  550. MAX_ERROR_STRING_LENGTH,
  551. lpROOT->lpAllocBuff,
  552. lpROOT->hLibrary,
  553. &lpszMessage);
  554. if ( FAILED( scode) )
  555. {
  556. hResult = ResultFromScode(scode);
  557. goto ret;
  558. }
  559. scode = lpROOT->lpAllocMore( (lstrlen( lpszMessage ) + 1)*SIZEOF(TCHAR),
  560. *lppMapiError,
  561. &(*lppMapiError)->lpszError
  562. );
  563. if ( FAILED( scode ) )
  564. {
  565. hResult = ResultFromScode(scode);
  566. goto ret;
  567. }
  568. lstrcpy( (*lppMapiError)->lpszError, lpszMessage );
  569. }
  570. else
  571. {
  572. *lppMapiError = NULL;
  573. }
  574. ret:
  575. if ( hResult )
  576. {
  577. lpROOT->lpFreeBuff( *lppMapiError );
  578. *lppMapiError = NULL;
  579. }
  580. lpROOT->lpFreeBuff( lpszMessage );
  581. LeaveCriticalSection(&lpROOT->cs);
  582. return hResult;
  583. }
  584. /*
  585. - ROOT_SaveChanges
  586. -
  587. * Can't save changes on this object.
  588. *
  589. *
  590. */
  591. STDMETHODIMP
  592. ROOT_SaveChanges(LPROOT lpROOT, ULONG ulFlags)
  593. {
  594. HRESULT hResult;
  595. /*
  596. * Check to see if it's large enough to be this object
  597. */
  598. if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
  599. {
  600. /*
  601. * Not large enough
  602. */
  603. hResult = ResultFromScode(E_INVALIDARG);
  604. goto out;
  605. }
  606. /*
  607. * Check to see that it's ROOTs vtbl
  608. */
  609. if (lpROOT->lpVtbl != &vtblROOT)
  610. {
  611. /*
  612. * Not my vtbl
  613. */
  614. hResult = ResultFromScode(E_INVALIDARG);
  615. goto out;
  616. }
  617. if (ulFlags & ~(KEEP_OPEN_READONLY|KEEP_OPEN_READONLY|FORCE_SAVE))
  618. {
  619. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  620. goto out;
  621. }
  622. hResult = ResultFromScode(E_ACCESSDENIED);
  623. out:
  624. DebugTraceResult(ROOT_SaveChanges, hResult);
  625. return hResult;
  626. }
  627. /*
  628. - ROOT_OpenProperty
  629. -
  630. *
  631. * For this object I only need to support opening the hierarchy table.
  632. *
  633. */
  634. STDMETHODIMP
  635. ROOT_OpenProperty( LPROOT lpROOT,
  636. ULONG ulPropTag,
  637. LPCIID lpiid,
  638. ULONG ulInterfaceOptions,
  639. ULONG ulFlags,
  640. LPUNKNOWN * lppUnk)
  641. {
  642. HRESULT hResult;
  643. /*
  644. * Check to see if it's large enough to be this object
  645. */
  646. if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
  647. {
  648. /*
  649. * Not large enough
  650. */
  651. hResult = ResultFromScode(E_INVALIDARG);
  652. goto out;
  653. }
  654. /*
  655. * Check to see that it's ROOTs vtbl
  656. */
  657. if (lpROOT->lpVtbl != &vtblROOT)
  658. {
  659. /*
  660. * Not my vtbl
  661. */
  662. hResult = ResultFromScode(E_INVALIDARG);
  663. goto out;
  664. }
  665. if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN)))
  666. {
  667. /*
  668. * Got to be able to return an object
  669. */
  670. hResult = ResultFromScode(E_INVALIDARG);
  671. goto out;
  672. }
  673. if (IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)))
  674. {
  675. /*
  676. * An interface ID is required for this call.
  677. */
  678. hResult = ResultFromScode(E_INVALIDARG);
  679. goto out;
  680. }
  681. if (ulFlags & ~(MAPI_CREATE|MAPI_MODIFY|MAPI_DEFERRED_ERRORS))
  682. {
  683. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  684. }
  685. if (ulInterfaceOptions & ~MAPI_UNICODE)
  686. {
  687. /*
  688. * Only UNICODE flag should be set for any of the objects that might
  689. * be returned from this object.
  690. */
  691. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  692. goto out;
  693. }
  694. if ( ulInterfaceOptions & MAPI_UNICODE )
  695. {
  696. hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  697. goto out;
  698. }
  699. if (ulFlags & MAPI_CREATE)
  700. {
  701. hResult = ResultFromScode(E_ACCESSDENIED);
  702. goto out;
  703. }
  704. if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN)))
  705. {
  706. /*
  707. * Got to be able to return an object
  708. */
  709. hResult = ResultFromScode(E_INVALIDARG);
  710. goto out;
  711. }
  712. if (IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)))
  713. {
  714. /*
  715. * An interface ID is required for this call.
  716. */
  717. hResult = ResultFromScode(E_INVALIDARG);
  718. goto out;
  719. }
  720. if (ulFlags & ~(MAPI_CREATE|MAPI_MODIFY|MAPI_DEFERRED_ERRORS))
  721. {
  722. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  723. goto out;
  724. }
  725. if (ulInterfaceOptions)
  726. {
  727. /*
  728. * No flags should be set for any of the objects that might
  729. * be returned from this object.
  730. */
  731. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  732. goto out;
  733. }
  734. if (ulFlags & MAPI_CREATE)
  735. {
  736. hResult = ResultFromScode(E_ACCESSDENIED);
  737. goto out;
  738. }
  739. switch (ulPropTag)
  740. {
  741. case PR_CONTAINER_HIERARCHY:
  742. {
  743. /*
  744. * Check to see if they're expecting a IMAPITable object
  745. */
  746. if (memcmp(lpiid, &IID_IMAPITable, SIZEOF(IID)))
  747. {
  748. hResult = ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  749. goto out;
  750. }
  751. hResult = ROOT_GetHierarchyTable(lpROOT, 0, (LPMAPITABLE *) lppUnk);
  752. goto out;
  753. }
  754. default:
  755. break;
  756. }
  757. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  758. out:
  759. DebugTraceResult(ROOT_OpenProperty, hResult);
  760. return hResult;
  761. }
  762. /*************************************************************************
  763. *
  764. *
  765. - ROOT_GetContentsTable
  766. -
  767. * There are no contents in the root
  768. *
  769. *
  770. *
  771. */
  772. STDMETHODIMP
  773. ROOT_GetContentsTable( LPROOT lpROOT,
  774. ULONG ulFlags,
  775. LPMAPITABLE * lppTable)
  776. {
  777. HRESULT hResult;
  778. /*
  779. * Check to see if it has a lpVtbl object member
  780. */
  781. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  782. {
  783. /*
  784. * Not large enough
  785. */
  786. hResult = MakeResult(E_INVALIDARG);
  787. return hResult;
  788. }
  789. /*
  790. * Check to see that the Vtbl is large enough to include this method
  791. */
  792. if (IsBadReadPtr(lpROOT->lpVtbl,
  793. offsetof(ROOT_Vtbl, GetContentsTable)+SIZEOF(ROOT_GetContentsTable_METHOD *)))
  794. {
  795. /*
  796. * Jump table not derived from IUnknown
  797. */
  798. hResult = MakeResult(E_INVALIDARG);
  799. return hResult;
  800. }
  801. /*
  802. * Check to see if the method is the same
  803. */
  804. if (ROOT_GetContentsTable != lpROOT->lpVtbl->GetContentsTable)
  805. {
  806. /*
  807. * Wrong object - the object passed doesn't have this
  808. * method.
  809. */
  810. hResult = ResultFromScode(E_INVALIDARG);
  811. DebugTraceResult(ROOT_GetContentsTable, hResult);
  812. return hResult;
  813. }
  814. if (ulFlags & ~(MAPI_DEFERRED_ERRORS|MAPI_ASSOCIATED|MAPI_UNICODE))
  815. {
  816. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  817. goto out;
  818. }
  819. if ( ulFlags & MAPI_UNICODE )
  820. {
  821. hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  822. goto out;
  823. }
  824. if (!IsBadWritePtr(lppTable, SIZEOF(LPMAPITABLE)))
  825. {
  826. hResult = ResultFromScode(E_INVALIDARG);
  827. goto out;
  828. }
  829. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  830. out:
  831. DebugTraceResult(ROOT_GetContentsTable, hResult);
  832. return hResult;
  833. }
  834. /*
  835. - ROOT_GetHierarchyTable
  836. -
  837. * Returns the table with just one entry in it.
  838. *
  839. *
  840. *
  841. */
  842. STDMETHODIMP
  843. ROOT_GetHierarchyTable( LPROOT lpROOT,
  844. ULONG ulFlags,
  845. LPMAPITABLE * lppTable)
  846. {
  847. HRESULT hResult = hrSuccess;
  848. /*
  849. * Validate parameters
  850. */
  851. /*
  852. * Check to see if it's large enough to be this object
  853. */
  854. if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
  855. {
  856. /*
  857. * Not large enough
  858. */
  859. hResult = ResultFromScode(E_INVALIDARG);
  860. DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  861. return hResult;
  862. }
  863. /*
  864. * Check to see that it's ROOTs vtbl
  865. */
  866. if (lpROOT->lpVtbl != &vtblROOT)
  867. {
  868. /*
  869. * Not my vtbl
  870. */
  871. hResult = ResultFromScode(E_INVALIDARG);
  872. DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  873. return hResult;
  874. }
  875. /*
  876. * See if I can set the return variable
  877. */
  878. if (IsBadWritePtr(lppTable, SIZEOF(LPMAPITABLE)))
  879. {
  880. hResult = ResultFromScode(E_INVALIDARG);
  881. DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  882. return hResult;
  883. }
  884. /*
  885. * Check flags:
  886. * The only valid flags are CONVENIENT_DEPTH and MAPI_DEFERRED_ERRORS
  887. */
  888. if (ulFlags & ~(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS))
  889. {
  890. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  891. DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  892. return hResult;
  893. }
  894. /*
  895. * Since we only have one item in our hierarchy table, CONVENIENT_DEPTH
  896. * is equivalent to any other depth level (>1). So, just ignore the
  897. * flag. MAPI_DEFERRED_ERROR is fine. We don't ever defer errors.
  898. */
  899. /*
  900. * Create a View Table for the hierarchy.
  901. */
  902. hResult = HrBuildRootHier(lpROOT->lpABLogon, lppTable);
  903. DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  904. return hResult;
  905. }
  906. /*
  907. - ROOT_OpenEntry
  908. -
  909. * Check parameters and use our logon object's OpenEntry method.
  910. */
  911. STDMETHODIMP
  912. ROOT_OpenEntry( LPROOT lpROOT,
  913. ULONG cbEntryID,
  914. LPENTRYID lpEntryID,
  915. LPCIID lpInterface,
  916. ULONG ulFlags,
  917. ULONG * lpulObjType,
  918. LPUNKNOWN * lppUnk
  919. )
  920. {
  921. HRESULT hResult;
  922. /*
  923. * Check to see if it has a lpVtbl object member
  924. */
  925. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  926. {
  927. /*
  928. * No vtbl found
  929. */
  930. hResult = MakeResult(E_INVALIDARG);
  931. goto out;
  932. }
  933. /*
  934. * Check to see that the Vtbl is large enough to include this method
  935. */
  936. if (IsBadReadPtr(lpROOT->lpVtbl,
  937. offsetof(ROOT_Vtbl, OpenEntry)+SIZEOF(ROOT_OpenEntry_METHOD *)))
  938. {
  939. /*
  940. * vtbl cannot hold this method
  941. */
  942. hResult = MakeResult(E_INVALIDARG);
  943. goto out;
  944. }
  945. /*
  946. * Check to see that it's the correct method
  947. */
  948. if (ROOT_OpenEntry != lpROOT->lpVtbl->OpenEntry)
  949. {
  950. /*
  951. * Not my vtbl
  952. */
  953. hResult = ResultFromScode(E_INVALIDARG);
  954. goto out;
  955. }
  956. /*
  957. * Check the entryID
  958. */
  959. if ( cbEntryID &&
  960. (cbEntryID < (ULONG) SIZEOF(ENTRYID) ||
  961. IsBadReadPtr(lpEntryID, (UINT) cbEntryID))
  962. )
  963. {
  964. /*
  965. * Malformed entryID
  966. */
  967. hResult = ResultFromScode(E_INVALIDARG);
  968. goto out;
  969. }
  970. if (lpInterface && IsBadReadPtr(lpInterface, SIZEOF(IID)))
  971. {
  972. /*
  973. * malformed interface id
  974. */
  975. hResult = ResultFromScode(E_INVALIDARG);
  976. goto out;
  977. }
  978. if (ulFlags & ~(MAPI_DEFERRED_ERRORS))
  979. {
  980. /*
  981. * Flags are set that I have no idea about
  982. */
  983. hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  984. goto out;
  985. }
  986. if (IsBadWritePtr(lpulObjType, SIZEOF(ULONG)))
  987. {
  988. /*
  989. * Can't return an object type
  990. */
  991. hResult = ResultFromScode(E_INVALIDARG);
  992. goto out;
  993. }
  994. if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN)))
  995. {
  996. /*
  997. * Can't return an object
  998. */
  999. hResult = ResultFromScode(E_INVALIDARG);
  1000. goto out;
  1001. }
  1002. hResult = lpROOT->lpABLogon->lpVtbl->OpenEntry(lpROOT->lpABLogon,
  1003. cbEntryID,
  1004. lpEntryID,
  1005. lpInterface,
  1006. ulFlags,
  1007. lpulObjType,
  1008. lppUnk);
  1009. out:
  1010. DebugTraceResult(ROOT_OpenEntry, hResult);
  1011. return hResult;
  1012. }
  1013. /*
  1014. - ROOT_SetSearchCriteria
  1015. -
  1016. *
  1017. * Not implemented for this object
  1018. */
  1019. STDMETHODIMP
  1020. ROOT_SetSearchCriteria( LPROOT lpROOT,
  1021. LPSRestriction lpRestriction,
  1022. LPENTRYLIST lpContainerList,
  1023. ULONG ulSearchFlags
  1024. )
  1025. {
  1026. HRESULT hResult;
  1027. /*
  1028. * Check to see if it has a lpVtbl object member
  1029. */
  1030. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  1031. {
  1032. /*
  1033. * Not large enough
  1034. */
  1035. hResult = MakeResult(E_INVALIDARG);
  1036. goto out;
  1037. }
  1038. /*
  1039. * Check to see that the Vtbl is large enough to include this method
  1040. */
  1041. if (IsBadReadPtr(lpROOT->lpVtbl,
  1042. offsetof(ROOT_Vtbl, SetSearchCriteria)+SIZEOF(ROOT_SetSearchCriteria_METHOD *)))
  1043. {
  1044. /*
  1045. * vtbl not large enough to support this method
  1046. */
  1047. hResult = MakeResult(E_INVALIDARG);
  1048. goto out;
  1049. }
  1050. /*
  1051. * Check to see that it's the correct method
  1052. */
  1053. if (ROOT_SetSearchCriteria != lpROOT->lpVtbl->SetSearchCriteria)
  1054. {
  1055. /*
  1056. * Not my vtbl
  1057. */
  1058. hResult = ResultFromScode(E_INVALIDARG);
  1059. goto out;
  1060. }
  1061. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1062. out:
  1063. DebugTraceResult(ROOT_SetSearchCriteria, hResult);
  1064. return hResult;
  1065. }
  1066. /*
  1067. - ROOT_GetSearchCriteria
  1068. -
  1069. *
  1070. * Not implemented for this object
  1071. *
  1072. */
  1073. STDMETHODIMP
  1074. ROOT_GetSearchCriteria( LPROOT lpROOT,
  1075. ULONG ulFlags,
  1076. LPSRestriction FAR * lppRestriction,
  1077. LPENTRYLIST FAR * lppContainerList,
  1078. ULONG FAR * lpulSearchState
  1079. )
  1080. {
  1081. HRESULT hResult;
  1082. /*
  1083. * Check to see if it has a lpVtbl object member
  1084. */
  1085. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  1086. {
  1087. /*
  1088. * Not large enough
  1089. */
  1090. hResult = MakeResult(E_INVALIDARG);
  1091. return hResult;
  1092. }
  1093. /*
  1094. * Check to see that the Vtbl is large enough to include this method
  1095. */
  1096. if (IsBadReadPtr(lpROOT->lpVtbl,
  1097. offsetof(ROOT_Vtbl, GetSearchCriteria)+SIZEOF(ROOT_GetSearchCriteria_METHOD *)))
  1098. {
  1099. /*
  1100. * Jump table not derived from IUnknown
  1101. */
  1102. hResult = MakeResult(E_INVALIDARG);
  1103. return hResult;
  1104. }
  1105. /*
  1106. * Check to see if the method is the same
  1107. */
  1108. if (ROOT_GetSearchCriteria != lpROOT->lpVtbl->GetSearchCriteria)
  1109. {
  1110. /*
  1111. * Wrong object - the object passed doesn't have this
  1112. * method.
  1113. */
  1114. hResult = ResultFromScode(E_INVALIDARG);
  1115. DebugTraceResult(ROOT_GetSearchCriteria, hResult);
  1116. return hResult;
  1117. }
  1118. if ( ulFlags & ~(MAPI_UNICODE) )
  1119. {
  1120. hResult = ResultFromScode( MAPI_E_UNKNOWN_FLAGS );
  1121. return hResult;
  1122. }
  1123. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1124. DebugTraceResult(ROOT_GetSearchCriteria, hResult);
  1125. return hResult;
  1126. }
  1127. /*
  1128. - ROOT_CreateEntry
  1129. -
  1130. * New entries cannot be created in the root
  1131. *
  1132. */
  1133. STDMETHODIMP
  1134. ROOT_CreateEntry( LPROOT lpROOT,
  1135. ULONG cbEntryID,
  1136. LPENTRYID lpEntryID,
  1137. ULONG ulCreateFlags,
  1138. LPMAPIPROP FAR * lppMAPIPropEntry
  1139. )
  1140. {
  1141. HRESULT hResult;
  1142. /*
  1143. * Check to see if it has a lpVtbl object member
  1144. */
  1145. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  1146. {
  1147. /*
  1148. * No vtbl found
  1149. */
  1150. hResult = MakeResult(E_INVALIDARG);
  1151. goto out;
  1152. }
  1153. /*
  1154. * Check to see that the Vtbl is large enough to include this method
  1155. */
  1156. if (IsBadReadPtr(lpROOT->lpVtbl,
  1157. offsetof(ROOT_Vtbl, CreateEntry)+SIZEOF(ROOT_CreateEntry_METHOD *)))
  1158. {
  1159. /*
  1160. * vtbl not large enough to hold this method
  1161. */
  1162. hResult = MakeResult(E_INVALIDARG);
  1163. goto out;
  1164. }
  1165. /*
  1166. * Check to see if the method is the same
  1167. */
  1168. if (ROOT_CreateEntry != lpROOT->lpVtbl->CreateEntry)
  1169. {
  1170. /*
  1171. * Wrong object - the object passed doesn't have this
  1172. * method.
  1173. */
  1174. hResult = MakeResult(E_INVALIDARG);
  1175. goto out;
  1176. }
  1177. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1178. out:
  1179. DebugTraceResult(ROOT_CreateEntry, hResult);
  1180. return hResult;
  1181. }
  1182. /*
  1183. - ROOT_CopyEntries
  1184. -
  1185. * Entries cannot be copied into the root
  1186. *
  1187. *
  1188. *
  1189. */
  1190. STDMETHODIMP
  1191. ROOT_CopyEntries( LPROOT lpROOT,
  1192. LPENTRYLIST lpEntries,
  1193. ULONG ulUIParam,
  1194. LPMAPIPROGRESS lpProgress,
  1195. ULONG ulFlags
  1196. )
  1197. {
  1198. HRESULT hResult;
  1199. /*
  1200. * Check to see if it has a lpVtbl object member
  1201. */
  1202. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  1203. {
  1204. /*
  1205. * No vtbl found
  1206. */
  1207. hResult = MakeResult(E_INVALIDARG);
  1208. goto out;
  1209. }
  1210. /*
  1211. * Check to see that the Vtbl is large enough to include this method
  1212. */
  1213. if (IsBadReadPtr(lpROOT->lpVtbl,
  1214. offsetof(ROOT_Vtbl, CopyEntries)+SIZEOF(ROOT_CopyEntries_METHOD *)))
  1215. {
  1216. /*
  1217. * vtbl not large enough to hold this method
  1218. */
  1219. hResult = MakeResult(E_INVALIDARG);
  1220. goto out;
  1221. }
  1222. /*
  1223. * Check to see if the method is the same
  1224. */
  1225. if (ROOT_CopyEntries != lpROOT->lpVtbl->CopyEntries)
  1226. {
  1227. /*
  1228. * Wrong object - the object passed doesn't have this
  1229. * method.
  1230. */
  1231. hResult = MakeResult(E_INVALIDARG);
  1232. goto out;
  1233. }
  1234. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1235. out:
  1236. DebugTraceResult(ROOT_CopyEntries, hResult);
  1237. return hResult;
  1238. }
  1239. /*
  1240. - ROOT_DeleteEntries
  1241. -
  1242. * Entries cannot be deleted from the root
  1243. *
  1244. *
  1245. *
  1246. */
  1247. STDMETHODIMP
  1248. ROOT_DeleteEntries( LPROOT lpROOT,
  1249. LPENTRYLIST lpEntries,
  1250. ULONG ulFlags)
  1251. {
  1252. HRESULT hResult;
  1253. /*
  1254. * Check to see if it has a lpVtbl object member
  1255. */
  1256. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  1257. {
  1258. /*
  1259. * No vtbl found
  1260. */
  1261. hResult = MakeResult(E_INVALIDARG);
  1262. goto out;
  1263. }
  1264. /*
  1265. * Check to see that the Vtbl is large enough to include this method
  1266. */
  1267. if (IsBadReadPtr(lpROOT->lpVtbl,
  1268. offsetof(ROOT_Vtbl, DeleteEntries)+SIZEOF(ROOT_DeleteEntries_METHOD *)))
  1269. {
  1270. /*
  1271. * vtbl not large enough to hold this method
  1272. */
  1273. hResult = MakeResult(E_INVALIDARG);
  1274. goto out;
  1275. }
  1276. /*
  1277. * Check to see if the method is the same
  1278. */
  1279. if (ROOT_DeleteEntries != lpROOT->lpVtbl->DeleteEntries)
  1280. {
  1281. /*
  1282. * Wrong object - the object passed doesn't have this
  1283. * method.
  1284. */
  1285. hResult = MakeResult(E_INVALIDARG);
  1286. goto out;
  1287. }
  1288. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1289. out:
  1290. DebugTraceResult(ROOT_DeleteEntries, hResult);
  1291. return hResult;
  1292. }
  1293. /*
  1294. - ROOT_ResolveNames
  1295. -
  1296. * No special case handling of resolving names within this container
  1297. *
  1298. *
  1299. *
  1300. */
  1301. STDMETHODIMP
  1302. ROOT_ResolveNames( LPROOT lpROOT,
  1303. LPSPropTagArray lptagaColSet,
  1304. ULONG ulFlags,
  1305. LPADRLIST lpAdrList,
  1306. LPFlagList lpFlagList )
  1307. {
  1308. HRESULT hResult;
  1309. /*
  1310. * Check to see if it has a lpVtbl object member
  1311. */
  1312. if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
  1313. {
  1314. /*
  1315. * No vtbl found
  1316. */
  1317. hResult = MakeResult(E_INVALIDARG);
  1318. goto out;
  1319. }
  1320. /*
  1321. * Check to see that the Vtbl is large enough to include this method
  1322. */
  1323. if (IsBadReadPtr(lpROOT->lpVtbl,
  1324. offsetof(ROOT_Vtbl, ResolveNames)+SIZEOF(ROOT_ResolveNames_METHOD *)))
  1325. {
  1326. /*
  1327. * vtbl not large enough to hold this method
  1328. */
  1329. hResult = MakeResult(E_INVALIDARG);
  1330. goto out;
  1331. }
  1332. /*
  1333. * Check to see if the method is the same
  1334. */
  1335. if (ROOT_ResolveNames != lpROOT->lpVtbl->ResolveNames)
  1336. {
  1337. /*
  1338. * Wrong object - the object passed doesn't have this
  1339. * method.
  1340. */
  1341. hResult = MakeResult(E_INVALIDARG);
  1342. goto out;
  1343. }
  1344. hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1345. out:
  1346. DebugTraceResult(ROOT_ResolveNames, hResult);
  1347. return hResult;
  1348. }
  1349. #undef _FAXAB_ROOT