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.

1403 lines
38 KiB

  1. /***********************************************************************
  2. *
  3. * ABP.C
  4. *
  5. *
  6. * The Microsoft At Work Fax Address Book Provider.
  7. * This file contains the routines that handle the ABPJump table.
  8. *
  9. * The following routines are implemented in this file:
  10. *
  11. * ABProviderInit
  12. * ABP_QueryInterface
  13. * ABP_Release
  14. * ABP_Shutdown
  15. * ABP_Logon
  16. *
  17. * ServiceEntry
  18. * HrOpenSingleProvider
  19. *
  20. * RemoveLogonObject
  21. * FindLogonObject
  22. * ScLoadString
  23. *
  24. * Globals defined in this file:
  25. *
  26. * Copyright 1992, 1993 Microsoft Corporation. All Rights Reserved.
  27. *
  28. * Revision History:
  29. *
  30. * When Who What
  31. * -------- ------------------ ---------------------------------------
  32. * 1.1.94 MAPI Original source from MAPI sample AB Provider
  33. * 1.27.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
  34. * 3.5.94 Yoram Yaacovi Update to MAPI build 154
  35. * 4.1.94 Yoram Yaacovi Update to MAPI and sample AB build 157
  36. * 8.1.94 Yoram Yaacovi Update to MAPI and sample AB build 306
  37. *
  38. ***********************************************************************/
  39. #define _FAXAB_ABP
  40. #include "faxab.h"
  41. /*
  42. * Prototypes for the functions in this file, most of which I return
  43. * in the jump table returned from ABProviderInit().
  44. */
  45. ABPROVIDERINIT ABProviderInit;
  46. MSGSERVICEENTRY FABServiceEntry;
  47. HRESULT HrOpenSingleProvider( LPPROVIDERADMIN lpAdminProviders,
  48. LPPROFSECT FAR *lppProfSect
  49. );
  50. void LoadIniParams(void);
  51. /*
  52. * The jump table returned from ABProviderInit().
  53. */
  54. ABP_Vtbl vtblABP =
  55. {
  56. ABP_QueryInterface,
  57. (ABP_AddRef_METHOD *) ROOT_AddRef,
  58. ABP_Release,
  59. ABP_Shutdown,
  60. ABP_Logon
  61. };
  62. /*************************************************************************
  63. *
  64. - ABProviderInit
  65. -
  66. * Initializes this provider. Returns a jump table that contains the
  67. * addresses of the rest of the functions.
  68. *
  69. */
  70. HRESULT STDMAPIINITCALLTYPE
  71. ABProviderInit (
  72. HINSTANCE hLibrary,
  73. LPMALLOC lpMalloc,
  74. LPALLOCATEBUFFER lpAllocBuff,
  75. LPALLOCATEMORE lpAllocMore,
  76. LPFREEBUFFER lpFreeBuff,
  77. ULONG ulFlags,
  78. ULONG ulMAPIVersion,
  79. ULONG FAR * lpulABVersion,
  80. LPABPROVIDER FAR * lppABProvider)
  81. {
  82. HRESULT hResult = hrSuccess;
  83. LPABP lpABP;
  84. SCODE scode;
  85. //DebugBreak();
  86. DebugTrace("AWFXAB32(ABProviderInit): entering\n");
  87. // Get registry settings
  88. LoadIniParams();
  89. #ifdef DEBUG
  90. if (fDebugTrap)
  91. DebugBreak();
  92. #endif
  93. /*
  94. * Check the version
  95. */
  96. if (ulMAPIVersion < CURRENT_SPI_VERSION)
  97. {
  98. /*
  99. * MAPI's version is too old.
  100. */
  101. /*
  102. * See if they understand my version
  103. */
  104. *lpulABVersion = CURRENT_SPI_VERSION;
  105. DebugTraceSc(ABProviderInit, MAPI_E_VERSION);
  106. return ResultFromScode(MAPI_E_VERSION);
  107. }
  108. /*
  109. * Allocate memory for this Init Object
  110. */
  111. scode = lpAllocBuff (SIZEOF(ABP), &lpABP);
  112. if (FAILED(scode))
  113. {
  114. /*
  115. * Out of memory
  116. */
  117. DebugTraceSc(ABProviderInit, scode);
  118. return ResultFromScode(scode);
  119. }
  120. /*
  121. * Initialize the idle engine that MAPI supplies. This is most useful
  122. * when browsing the .FAB file. See ABCTBLn.C.
  123. */
  124. if (MAPIInitIdle( NULL )==-1)
  125. {
  126. hResult = ResultFromScode(E_FAIL);
  127. goto err;
  128. }
  129. /*
  130. * Hold on to the lpMalloc
  131. */
  132. if (lpMalloc)
  133. lpMalloc->lpVtbl->AddRef(lpMalloc);
  134. lpABP->lpVtbl = &vtblABP;
  135. lpABP->lcInit = 1;
  136. lpABP->hLibrary = hLibrary;
  137. lpABP->lpMalloc = lpMalloc;
  138. lpABP->lpAllocBuff = lpAllocBuff;
  139. lpABP->lpAllocMore = lpAllocMore;
  140. lpABP->lpFreeBuff = lpFreeBuff;
  141. lpABP->lpObjectList= NULL;
  142. InitializeCriticalSection(&lpABP->cs);
  143. *lppABProvider = (LPABPROVIDER)lpABP;
  144. *lpulABVersion = CURRENT_SPI_VERSION;
  145. /*
  146. * Get our Locale Identifier
  147. */
  148. lcidUser = GetUserDefaultLCID();
  149. out:
  150. DebugTraceResult(ABProviderInit, hResult);
  151. return hResult;
  152. err:
  153. lpFreeBuff(lpABP);
  154. goto out;
  155. }
  156. /*
  157. * The Init Object's methods implementation
  158. */
  159. /**********************************************************************
  160. - ABP_QueryInterface
  161. -
  162. * Supports QI'ing to IUnknown and IABProvider
  163. *
  164. * Note that for all the methods of IABProvider that parameter validation
  165. * is unnecessary. This is because MAPI is handling all the parameters
  166. * being passed in.
  167. * At best you can assert your parameters.
  168. */
  169. STDMETHODIMP
  170. ABP_QueryInterface (LPABP lpABP, REFIID lpiid, LPVOID *ppvObj)
  171. {
  172. DebugTrace("AWFXAB32(ABP_QueryInterface): entering\n");
  173. /* See if the requested interface is one of ours */
  174. if ( memcmp (lpiid, &IID_IUnknown, SIZEOF (IID)) &&
  175. memcmp (lpiid, &IID_IABProvider, SIZEOF (IID))
  176. )
  177. {
  178. *ppvObj = NULL; /* OLE requires zeroing [out] parameter on error */
  179. DebugTraceSc(ABP_QueryInterface, E_NOINTERFACE);
  180. return ResultFromScode (E_NOINTERFACE);
  181. }
  182. /* We'll do this one. Bump the usage count and return a new pointer. */
  183. EnterCriticalSection(&lpABP->cs);
  184. ++lpABP->lcInit;
  185. LeaveCriticalSection(&lpABP->cs);
  186. *ppvObj = lpABP;
  187. return hrSuccess;
  188. }
  189. /*
  190. * Use ROOTs AddRef
  191. */
  192. /*************************************************************************
  193. *
  194. - ABP_Release
  195. -
  196. * Releases and cleans up this object
  197. */
  198. STDMETHODIMP_(ULONG)
  199. ABP_Release (LPABP lpABP)
  200. {
  201. long lcInit;
  202. DebugTrace("AWFXAB32(ABP_Release): entering\n");
  203. EnterCriticalSection(&lpABP->cs);
  204. lcInit = --lpABP->lcInit;
  205. LeaveCriticalSection(&lpABP->cs);
  206. if (lcInit == 0)
  207. {
  208. DeleteCriticalSection(&lpABP->cs);
  209. lpABP->lpVtbl = NULL;
  210. lpABP->lpFreeBuff(lpABP);
  211. return (0);
  212. }
  213. return lcInit;
  214. }
  215. /**********************************************************************
  216. - ABP_Shutdown
  217. -
  218. * Informs this provider that MAPI is done with it.
  219. *
  220. *
  221. */
  222. STDMETHODIMP
  223. ABP_Shutdown (LPABP lpABP, ULONG FAR *lpulFlags)
  224. {
  225. DebugTrace("AWFXAB32(ABP_Shutdown): entering\n");
  226. MAPIDeinitIdle();
  227. if (lpABP->lpMalloc)
  228. {
  229. lpABP->lpMalloc->lpVtbl->Release(lpABP->lpMalloc);
  230. lpABP->lpMalloc = NULL;
  231. }
  232. return hrSuccess;
  233. }
  234. /*************************************************************************
  235. *
  236. - ABP_Logon
  237. -
  238. * Create a logon object and return it to MAPI.
  239. *
  240. */
  241. /*
  242. * The PropTagArray used to retrieve logon properties
  243. */
  244. enum { ivallogonPR_FAB_FILE=0,
  245. ivallogonPR_FAB_UID,
  246. cvallogonMax };
  247. static const SizedSPropTagArray(cvallogonMax, tagaFABLogonProps) =
  248. {
  249. cvallogonMax,
  250. {
  251. PR_FAB_FILE_A,
  252. PR_FAB_UID
  253. }
  254. };
  255. STDMETHODIMP
  256. ABP_Logon( LPABP lpABP,
  257. LPMAPISUP lpMAPISup,
  258. ULONG ulUIParam,
  259. LPTSTR lpszProfileName,
  260. ULONG ulFlags,
  261. ULONG FAR * lpulpcbSecurity,
  262. LPBYTE FAR * lppbSecurity,
  263. LPMAPIERROR FAR * lppMapiError,
  264. LPABLOGON FAR * lppABPLogon
  265. )
  266. {
  267. LPABLOGON lpABLogon = NULL;
  268. HRESULT hResult = hrSuccess;
  269. SCODE scode;
  270. LPPROFSECT lpProfSect = NULL;
  271. LPSPropValue lpsPropVal = NULL;
  272. ULONG cValues = 0;
  273. TCHAR szFileName[MAX_PATH];
  274. LPTSTR lpstrT = NULL;
  275. BOOL fUINeeded;
  276. BOOL fNeedMAPIUID = FALSE;
  277. MAPIUID muidID;
  278. LPOBJECTLIST lpObjectList;
  279. LPTSTR lpszAppName=NULL;
  280. #ifdef UNICODE
  281. CHAR szAnsiFileName[ MAX_PATH ];
  282. #endif
  283. #ifdef EXTENDED_DEBUG
  284. MessageBox((HWND) ulUIParam, TEXT("ABP_Logon: entering"), TEXT("awfxab debug message"), MB_OK);
  285. #endif
  286. DebugTrace("AWFXAB32(ABP_Logon): entering\n");
  287. szFileName[0] = TEXT('\0');
  288. *lppMapiError = NULL;
  289. if ( ulFlags & MAPI_UNICODE )
  290. {
  291. DebugTraceArg( ABP_Logon, "Bad Character width" );
  292. return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  293. }
  294. /*
  295. * Get the name of my browse file from the profile section
  296. */
  297. /* Open the section for my provider */
  298. hResult = lpMAPISup->lpVtbl->OpenProfileSection( lpMAPISup,
  299. NULL,
  300. MAPI_MODIFY,
  301. &lpProfSect
  302. );
  303. if (HR_FAILED(hResult))
  304. goto out;
  305. /* Get the property containing the Fax AB file name. */
  306. hResult = lpProfSect->lpVtbl->GetProps( lpProfSect,
  307. (LPSPropTagArray)&tagaFABLogonProps,
  308. 0, // ANSI
  309. &cValues,
  310. &lpsPropVal
  311. );
  312. if (HR_FAILED(hResult))
  313. goto out;
  314. #ifdef DEBUG
  315. /* The only expected return code is MAPI_E_NOT_FOUND. */
  316. if (hResult != hrSuccess)
  317. {
  318. if (GetScode (hResult) != MAPI_W_ERRORS_RETURNED)
  319. {
  320. DebugTrace("AWFXAB32(ABP_Logon): got unexpected hResult: ");
  321. DebugTraceResult(ProfileGetProps, hResult);
  322. }
  323. else if (lpsPropVal[0].Value.err != MAPI_E_NOT_FOUND)
  324. {
  325. DebugTrace("AWFXAB32(ABP_Logon): got unexpected scode: ");
  326. DebugTraceSc(ProfileGetProps, lpsPropVal[0].Value.err);
  327. }
  328. }
  329. #endif
  330. /* Ignore warnings from reading the property. */
  331. hResult = hrSuccess;
  332. /* copy the Fax Address Book file name */
  333. if (lpsPropVal[0].ulPropTag==PR_FAB_FILE_A)
  334. {
  335. UINT cch = lstrlenA(lpsPropVal[0].Value.lpszA);
  336. if (cch >= MAX_PATH)
  337. cch = MAX_PATH-1;
  338. if (cch)
  339. #ifdef UNICODE
  340. MultiByteToWideChar( CP_ACP, 0, lpsPropVal[0].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
  341. #else
  342. memcpy(szFileName, lpsPropVal[0].Value.lpszA, cch);
  343. #endif
  344. szFileName[cch] = TEXT('\0');
  345. }
  346. else
  347. {
  348. DebugTrace("AWFXAB32(ABP_Logon): PR_FAB_FILE not found\n");
  349. }
  350. /* copy the fab uid */
  351. if (lpsPropVal[1].ulPropTag==PR_FAB_UID)
  352. {
  353. memcpy(&muidID,lpsPropVal[1].Value.bin.lpb, SIZEOF(MAPIUID));
  354. }
  355. else
  356. {
  357. DebugTrace("AWFXAB32(ABP_Logon): PR_FAB_UID not found\n");
  358. fNeedMAPIUID = TRUE;
  359. }
  360. /* Discard GetProps() return data, if any. */
  361. lpABP->lpFreeBuff (lpsPropVal);
  362. /*
  363. * (UI needed unless the file name is good and file exists.)
  364. *
  365. * in Fax, the AB is not exposed, so there is never a UI
  366. * If you insist on using a fax AB, you can set the name in the registry
  367. */
  368. fUINeeded = TRUE;
  369. if (szFileName[0] != 0)
  370. {
  371. /* Verify the file exists. */
  372. HANDLE hFile = CreateFile (
  373. szFileName,
  374. GENERIC_READ,
  375. FILE_SHARE_READ,
  376. NULL,
  377. OPEN_EXISTING,
  378. FILE_ATTRIBUTE_NORMAL,
  379. NULL);
  380. if (hFile != INVALID_HANDLE_VALUE)
  381. {
  382. CloseHandle (hFile);
  383. fUINeeded = FALSE;
  384. }
  385. }
  386. // Am I allowed to bring up UI ?
  387. if (ulFlags & AB_NO_DIALOG)
  388. fUINeeded = FALSE;
  389. // If the registry flag does not allow to expose the fax AB UI, don't allow it, no
  390. // matter what happened earlier
  391. if (!fExposeFaxAB)
  392. fUINeeded = FALSE;
  393. /*
  394. * if the sab file name was not found in the profile or the sab file
  395. * does not exist we have to get the user to pick another one and
  396. * save back into the profile
  397. */
  398. if (fUINeeded)
  399. {
  400. OPENFILENAME openfilename;
  401. SPropValue sProp[1];
  402. /*
  403. * Can't bring up UI unless the client allows it
  404. */
  405. if (ulFlags & AB_NO_DIALOG)
  406. {
  407. hResult = ResultFromScode (MAPI_E_LOGON_FAILED);
  408. goto out;
  409. }
  410. /*
  411. * Get the user to select a file
  412. */
  413. openfilename.lStructSize = SIZEOF(OPENFILENAME);
  414. openfilename.hwndOwner = (HWND) ulUIParam;
  415. openfilename.hInstance = 0; /* Ignored */
  416. openfilename.lpstrFilter = TEXT("Microsoft Fax Address Book files\0*.fab\0\0");
  417. openfilename.lpstrCustomFilter = NULL;
  418. openfilename.nMaxCustFilter = 0;
  419. openfilename.nFilterIndex = 0;
  420. openfilename.lpstrFile = szFileName;
  421. openfilename.nMaxFile = MAX_PATH;
  422. openfilename.lpstrFileTitle = NULL;
  423. openfilename.nMaxFileTitle = 0;
  424. openfilename.lpstrInitialDir = NULL;
  425. openfilename.lpstrTitle = TEXT("Microsoft Fax Address Book");
  426. openfilename.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NOCHANGEDIR;
  427. openfilename.nFileOffset = 0;
  428. openfilename.nFileExtension = 0;
  429. openfilename.lpstrDefExt = TEXT("fab");
  430. openfilename.lCustData = 0;
  431. openfilename.lpfnHook = NULL;
  432. openfilename.lpTemplateName = NULL;
  433. /*
  434. * Call up the common dialog
  435. */
  436. if (!GetOpenFileName (&openfilename))
  437. {
  438. #ifdef DEBUG
  439. DWORD dwT;
  440. dwT = CommDlgExtendedError();
  441. #endif /* DEBUG */
  442. // next two lines not needed for fax AB. an empty fax AB is valid.
  443. // hResult = ResultFromScode (MAPI_E_LOGON_FAILED);
  444. // goto out;
  445. }
  446. /*
  447. * Set the fab file name property value
  448. */
  449. sProp[0].ulPropTag = PR_FAB_FILE_A;
  450. #ifdef UNICODE
  451. WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
  452. sProp[0].Value.lpszA = szAnsiFileName;
  453. #else
  454. sProp[0].Value.lpszA = szFileName;
  455. #endif
  456. /*
  457. * Save the fab file into the profile
  458. */
  459. if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
  460. {
  461. /*
  462. * Do nothing... So I couldn't save it away this time...
  463. */
  464. DebugTraceResult("ABP_Logon got unexpected result on SetProps\n", hResult);
  465. hResult = hrSuccess;
  466. }
  467. } // if (fUINeeded)
  468. /*
  469. * if the uid was not found we have to generate a new muid for the
  470. * PR_SAB_ID property and save it back into the profile
  471. */
  472. if (fNeedMAPIUID)
  473. {
  474. SPropValue sProp[1];
  475. /*
  476. * Get a new fab uid
  477. */
  478. hResult=lpMAPISup->lpVtbl->NewUID(lpMAPISup,&muidID);
  479. if (HR_FAILED(hResult))
  480. {
  481. DebugTraceResult(NewUID, hResult);
  482. goto out;
  483. }
  484. /*
  485. * Set the fab uid property value
  486. */
  487. sProp[1].ulPropTag = PR_FAB_UID;
  488. sProp[1].Value.bin.cb = SIZEOF(MAPIUID);
  489. sProp[1].Value.bin.lpb = (LPBYTE)&muidID;
  490. /*
  491. * Save the sab uid into the profile
  492. */
  493. if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
  494. {
  495. /*
  496. * Do nothing... So I couldn't save it away this time...
  497. */
  498. DebugTraceResult("ABP_Logon got unexpected result on SetProps\n", hResult);
  499. hResult = hrSuccess;
  500. }
  501. } // if (fNeedMAPIUID)
  502. /*
  503. * Allocate space for keeping the file name in the ABLogon object
  504. */
  505. if (scode = lpABP->lpAllocBuff((lstrlen(szFileName)+1)*SIZEOF(TCHAR), &lpstrT))
  506. {
  507. hResult = ResultFromScode (scode);
  508. goto out;
  509. }
  510. lstrcpy (lpstrT, szFileName);
  511. hResult = HrNewABLogon( &lpABLogon,
  512. (LPABPROVIDER) lpABP,
  513. lpMAPISup,
  514. lpstrT,
  515. &muidID,
  516. lpABP->hLibrary,
  517. lpABP->lpAllocBuff,
  518. lpABP->lpAllocMore,
  519. lpABP->lpFreeBuff,
  520. lpABP->lpMalloc
  521. );
  522. if (HR_FAILED(hResult))
  523. {
  524. goto out;
  525. }
  526. /*
  527. * Allocate space for another object list item
  528. */
  529. if (scode = lpABP->lpAllocBuff( sizeof(OBJECTLIST), &lpObjectList))
  530. {
  531. hResult = ResultFromScode(scode);
  532. goto out;
  533. }
  534. /*
  535. * add logon object to list
  536. */
  537. /* Get the Critical Section */
  538. EnterCriticalSection(&lpABP->cs);
  539. /* add logon object to begining of providers object list */
  540. lpObjectList->lpObject = (LPVOID) lpABLogon;
  541. lpObjectList->lppNext = lpABP->lpObjectList;
  542. /* insert new logon object into the head of the providers object list */
  543. lpABP->lpObjectList = lpObjectList;
  544. /* leave critical section */
  545. LeaveCriticalSection(&lpABP->cs);
  546. /*
  547. * Register my MAPIUID for this provider,
  548. * but do not allow an error from setting the
  549. * MAPIUID to cause failure to Logon.
  550. */
  551. (void)lpMAPISup->lpVtbl->SetProviderUID(lpMAPISup,
  552. (LPMAPIUID) &muidABMAWF, 0);
  553. #ifdef DO_WE_REALLY_NEED_TAPI
  554. /*
  555. * TAPI
  556. *
  557. * everything seems OK. get TAPI initialized
  558. */
  559. scode = ScLoadString( IDS_APP_NAME,
  560. MAX_PATH,
  561. lpABP->lpAllocBuff,
  562. lpABP->hLibrary,
  563. &lpszAppName
  564. );
  565. InitTAPI(lpABP->hLibrary, (HWND) ulUIParam, lpszAppName);
  566. // Make sure we have the required location information handy
  567. // bring up mini-dial helper if not
  568. InitLocationParams((HWND) ulUIParam);
  569. #endif
  570. lpABP->lpFreeBuff(lpszAppName);
  571. // return the object to the caller
  572. *lppABPLogon = lpABLogon;
  573. out:
  574. if (lpProfSect)
  575. lpProfSect->lpVtbl->Release(lpProfSect);
  576. if (hResult)
  577. {
  578. lpABP->lpFreeBuff(lpstrT);
  579. Assert(lpABLogon == NULL);
  580. /* Verify we don't return warnings at this time. */
  581. Assert(HR_FAILED(hResult));
  582. }
  583. DebugTraceResult(ABP_Logon, hResult);
  584. return hResult;
  585. }
  586. /*************************************************************************
  587. -
  588. - RemoveLogonObject
  589. -
  590. * Removes a particular logon object from the list of logon objects
  591. * that's kept track of in the IABProvider object
  592. */
  593. void
  594. RemoveLogonObject( LPABPROVIDER lpABProvider,
  595. LPVOID lpvABLogon,
  596. LPFREEBUFFER lpFreeBuff
  597. )
  598. {
  599. LPOBJECTLIST *lppObjectList;
  600. LPOBJECTLIST lpObjectListT;
  601. LPABP lpABP = (LPABP) lpABProvider;
  602. #if defined DEBUG
  603. BOOL fFound = FALSE;
  604. #endif
  605. /* Get the Critical Section */
  606. EnterCriticalSection(&lpABP->cs);
  607. /*
  608. * remove this logon object from the provider init objects list
  609. * of logon objects
  610. */
  611. lppObjectList = &(lpABP->lpObjectList);
  612. while (*lppObjectList)
  613. {
  614. /* is this the logon object? */
  615. if ((*lppObjectList)->lpObject == lpvABLogon)
  616. {
  617. /* save next list item */
  618. lpObjectListT = (*lppObjectList)->lppNext;
  619. /* free the object list item */
  620. lpFreeBuff(*lppObjectList);
  621. /* delete object from the list */
  622. *lppObjectList = lpObjectListT;
  623. #if defined DEBUG
  624. fFound = TRUE;
  625. #endif
  626. break;
  627. }
  628. lppObjectList = &(*lppObjectList)->lppNext;
  629. }
  630. /* leave critical section */
  631. LeaveCriticalSection(&lpABP->cs);
  632. #if defined DEBUG
  633. AssertSz(fFound, "Logon object not found on providers object list");
  634. #endif
  635. return;
  636. }
  637. /*************************************************************************
  638. -
  639. - FindLogonObject
  640. -
  641. * Finds a particular logon object by its muid.
  642. */
  643. void
  644. FindLogonObject( LPABPROVIDER lpABProvider,
  645. LPMAPIUID lpMuidToFind,
  646. LPABLOGON * lppABLogon
  647. )
  648. {
  649. LPABP lpABP = (LPABP) lpABProvider;
  650. LPABLOGON lpABLogonT = NULL;
  651. LPOBJECTLIST lpObjectList = NULL;
  652. LPMAPIUID lpMuidLogon = NULL;
  653. Assert(!IsBadReadPtr(lpABP, SIZEOF(ABP)));
  654. Assert(!IsBadReadPtr(lpMuidToFind, SIZEOF(MAPIUID)));
  655. Assert(!IsBadReadPtr(lppABLogon, SIZEOF(LPABLOGON)));
  656. /* Get the Critical Section */
  657. EnterCriticalSection(&lpABP->cs);
  658. *lppABLogon = NULL;
  659. for (lpObjectList = lpABP->lpObjectList;
  660. lpObjectList; lpObjectList = lpObjectList->lppNext)
  661. {
  662. lpABLogonT = (LPABLOGON) lpObjectList->lpObject;
  663. lpMuidLogon = LpMuidFromLogon(lpABLogonT);
  664. if (memcmp((LPVOID) lpMuidLogon, (LPVOID) lpMuidToFind, SIZEOF(MAPIUID)) == 0)
  665. {
  666. *lppABLogon = lpABLogonT;
  667. break;
  668. }
  669. }
  670. /* leave critical section */
  671. LeaveCriticalSection(&lpABP->cs);
  672. }
  673. /*************************************************************************
  674. *
  675. - FABServiceEntry
  676. -
  677. * This funtion is used by MAPI to configure the Sample Address Book.
  678. * It's a lot like ABP_Logon, except that it doesn't return a logon object
  679. * and it can be passed in its configuration information (as defined in
  680. * smpab.h) from MAPI so that no UI is required.
  681. *
  682. * lppMapiError a pointer to a MAPI error structure which allows
  683. * the provider to return extended error info to MAPI
  684. */
  685. STDAPI
  686. FABServiceEntry(
  687. HINSTANCE hInstance,
  688. LPMALLOC lpMalloc,
  689. LPMAPISUP lpMAPISup,
  690. ULONG ulUIParam,
  691. ULONG ulFlags,
  692. ULONG ulContext,
  693. ULONG cValues,
  694. LPSPropValue lpProps,
  695. LPPROVIDERADMIN lpAdminProviders,
  696. LPMAPIERROR FAR *lppMapiError)
  697. {
  698. OPENFILENAME openfilename;
  699. TCHAR szFileName[MAX_PATH];
  700. HRESULT hResult=hrSuccess;
  701. SPropValue sProp[cvallogonMax];
  702. LPSPropValue lpsPropVal = NULL;
  703. ULONG ulCount = 0;
  704. LPALLOCATEBUFFER lpAllocBuff;
  705. LPALLOCATEMORE lpAllocMore;
  706. LPFREEBUFFER lpFreeBuff;
  707. MAPIUID muid;
  708. LPPROFSECT lpProf = NULL;
  709. BOOL fFABFound=FALSE; // No fab file name yet
  710. BOOL fUIDFound=FALSE; // No fab uid yet
  711. BOOL fNeedMAPIUID = FALSE;
  712. ULONG uliProp;
  713. #ifdef UNICODE
  714. CHAR szAnsiFileName[ MAX_PATH ];
  715. #endif
  716. #ifdef EXTENDED_DEBUG
  717. TCHAR szTempBuf[256];
  718. #endif
  719. //DebugBreak();
  720. DebugTrace("AWFXAB32(ServiceEntry): entering\n");
  721. // Get registry settings
  722. LoadIniParams();
  723. #ifdef DEBUG
  724. if (fDebugTrap)
  725. DebugBreak();
  726. #endif
  727. /*
  728. * Parameter validation
  729. */
  730. // check the support object
  731. if (IsBadReadPtr(lpMAPISup, SIZEOF(LPMAPISUP)))
  732. {
  733. DebugTraceSc(ServiceEntry, E_INVALIDARG);
  734. return ResultFromScode(E_INVALIDARG);
  735. }
  736. if ( ulFlags & MAPI_UNICODE )
  737. {
  738. DebugTraceArg( ServiceEntry, "Bad character width" );
  739. return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  740. }
  741. #ifdef EXTENDED_DEBUG
  742. switch (ulContext) {
  743. case MSG_SERVICE_DELETE:
  744. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_DELETE called!"), TEXT("awfxab debug message"), MB_OK);
  745. break;
  746. case MSG_SERVICE_INSTALL:
  747. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_INSTALL called!"), TEXT("awfxab debug message"), MB_OK);
  748. break;
  749. case MSG_SERVICE_UNINSTALL:
  750. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_UNINSTALL called!"), TEXT("awfxab debug message"), MB_OK);
  751. break;
  752. case MSG_SERVICE_CREATE:
  753. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_CREATE called!"), TEXT("awfxab debug message"), MB_OK);
  754. break;
  755. case MSG_SERVICE_CONFIGURE:
  756. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_CONFIGURE called!"), TEXT("awfxab debug message"), MB_OK);
  757. break;
  758. case MSG_SERVICE_PROVIDER_CREATE:
  759. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_PROVIDER_CREATE called!"), TEXT("awfxab debug message"), MB_OK);
  760. break;
  761. case MSG_SERVICE_PROVIDER_DELETE:
  762. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry MSG_SERVICE_PROVIDER_DELETE called!"), TEXT("awfxab debug message"), MB_OK);
  763. break;
  764. default:
  765. MessageBox((HWND) ulUIParam, TEXT("ServiceEntry unknown called!"), TEXT("awfxab debug message"), MB_OK);
  766. break;
  767. }
  768. #endif
  769. /*
  770. * Check what to do
  771. */
  772. if ( ulContext==MSG_SERVICE_DELETE ||
  773. ulContext==MSG_SERVICE_INSTALL ||
  774. ulContext==MSG_SERVICE_UNINSTALL
  775. )
  776. {
  777. return hrSuccess;
  778. }
  779. // Only supporting MSG_SERVICE_CONFIGURE and MSG_SERVICE_CREATE
  780. if ( ulContext!=MSG_SERVICE_CONFIGURE &&
  781. ulContext!=MSG_SERVICE_CREATE
  782. )
  783. {
  784. DebugTrace("ServiceEntry unsupported context\n");
  785. return ResultFromScode(MAPI_E_NO_SUPPORT);
  786. }
  787. /* Get the memory allocation routines we'll be needing. */
  788. hResult = lpMAPISup->lpVtbl->GetMemAllocRoutines( lpMAPISup,
  789. &lpAllocBuff,
  790. &lpAllocMore,
  791. &lpFreeBuff
  792. );
  793. if (hResult)
  794. {
  795. DebugTraceResult (MAPISUP::GetMemAllocRoutines, hResult);
  796. goto out;
  797. }
  798. /* Open the profile section associated with our provider */
  799. hResult = HrOpenSingleProvider(lpAdminProviders, &lpProf);
  800. if (hResult)
  801. {
  802. DebugTrace ("AWFXAB32(ServiceEntry): Unable to open the profile.");
  803. goto out;
  804. }
  805. #ifdef EXTENDED_DEBUG
  806. wsprintf (szTempBuf, TEXT("ServiceEntry: HrOpenSingleProvider succeeded. hResult=0x%08lx\n"), (ULONG) hResult);
  807. MessageBox( (HWND)ulUIParam,
  808. szTempBuf,
  809. TEXT("awfxab Debug Message"),
  810. MB_ICONINFORMATION
  811. );
  812. #endif
  813. // No file name for now
  814. szFileName[0] = TEXT('\0');
  815. /*
  816. * Now looking for the two properties I need:
  817. * PR_FAB_FILE
  818. * PR_FAB_UID
  819. *
  820. * they can either be:
  821. * 1. in the lpProps passed to ServiceEntry
  822. * 2. in my profile section
  823. * 3. be requested from the user through a UI
  824. */
  825. // see if these properties exist on the profile
  826. hResult = lpProf->lpVtbl->GetProps( lpProf,
  827. (LPSPropTagArray)&tagaFABLogonProps,
  828. ulFlags & MAPI_UNICODE,
  829. &ulCount,
  830. &lpsPropVal
  831. );
  832. // If the GetProps fail, I'm dump some debug messages, but it's OK to continue.
  833. // Can still get the props from the ServiceEntry input parameter or from UI
  834. if (hResult!=hrSuccess)
  835. {
  836. #ifdef DEBUG
  837. /* The only expected return code is MAPI_E_NOT_FOUND. */
  838. if (GetScode (hResult) != MAPI_W_ERRORS_RETURNED)
  839. {
  840. DebugTrace("AWFXAB32(ServiceEntry): got unexpected hResult: ");
  841. DebugTraceResult(ProfileGetProps, hResult);
  842. }
  843. else if (lpsPropVal[0].Value.err != MAPI_E_NOT_FOUND)
  844. {
  845. DebugTrace("AWFXAB32(ServiceEntry): got unexpected scode: ");
  846. DebugTraceSc(ProfileGetProps, lpsPropVal[0].Value.err);
  847. }
  848. #endif
  849. /* Ignore errors/warnings from reading the property. */
  850. hResult = hrSuccess;
  851. // These two should be false anyway at this point
  852. fFABFound = FALSE;
  853. fUIDFound = FALSE;
  854. }
  855. /************************
  856. *** PR_FAB_FILE ******
  857. ************************/
  858. /*
  859. * 1. Check the lpProps (cValues) passed to ServiceEntry
  860. */
  861. // First, look for the fab file property in the config props that were passed to
  862. // ServiceEntry. So I am not really looking at what I got in the above GetProps yet
  863. for (uliProp=0; uliProp < cValues; uliProp++)
  864. {
  865. if (PROP_ID(lpProps[uliProp].ulPropTag)==PROP_ID(PR_FAB_FILE_A))
  866. // This is the fab file property
  867. break;
  868. }
  869. // If the fab file property was found (must be found, isn't it ?) and it has a
  870. // non-error value, get the fab filename from it
  871. if ((uliProp < cValues) && (PROP_TYPE(lpProps[uliProp].ulPropTag)!=PT_ERROR))
  872. {
  873. ULONG cch = lstrlenA(lpProps[uliProp].Value.lpszA);
  874. if (cch >= MAX_PATH)
  875. cch = MAX_PATH-1;
  876. if (cch)
  877. #ifdef UNICODE
  878. MultiByteToWideChar( CP_ACP, 0, lpProps[uliProp].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
  879. #else
  880. memcpy(szFileName, lpProps[uliProp].Value.LPSZ, (size_t)cch*SIZEOF(TCHAR));
  881. #endif
  882. szFileName[cch] = TEXT('\0');
  883. // got my FAB file. Might be "". No need for UI for that
  884. fFABFound = TRUE;
  885. }
  886. /*
  887. * 2. Now the properties I got from the profile (if any)
  888. */
  889. // no fab file name in the input properties. Look in the profile properties
  890. else if ( (PROP_ID(lpsPropVal[0].ulPropTag) == PROP_ID(PR_FAB_FILE_A)) &&
  891. (PROP_TYPE(lpsPropVal[0].ulPropTag)!= PT_ERROR)
  892. )
  893. {
  894. ULONG cch = lstrlenA(lpsPropVal[0].Value.lpszA);
  895. if (cch >= MAX_PATH)
  896. cch = MAX_PATH-1;
  897. if (cch)
  898. #ifdef UNICODE
  899. MultiByteToWideChar( CP_ACP, 0, lpProps[0].Value.lpszA, -1, szFileName, ARRAYSIZE(szFileName) );
  900. #else
  901. memcpy(szFileName, lpsPropVal[0].Value.LPSZ, (size_t)cch*SIZEOF(TCHAR));
  902. #endif
  903. szFileName[cch] = TEXT('\0');
  904. fFABFound = TRUE;
  905. }
  906. else
  907. {
  908. fFABFound = FALSE;
  909. }
  910. /*
  911. * 3. Last resort: UI
  912. */
  913. if (fExposeFaxAB)
  914. {
  915. if (!fFABFound || (ulFlags & UI_SERVICE))
  916. {
  917. openfilename.lStructSize = SIZEOF(OPENFILENAME);
  918. openfilename.hwndOwner = (HWND) ulUIParam;
  919. openfilename.hInstance = 0; /* Ignored */
  920. openfilename.lpstrFilter = TEXT("Microsoft Fax Address Book files\0*.fab\0\0");
  921. openfilename.lpstrCustomFilter = NULL;
  922. openfilename.nMaxCustFilter = 0;
  923. openfilename.nFilterIndex = 0;
  924. openfilename.lpstrFile = szFileName;
  925. openfilename.nMaxFile = MAX_PATH;
  926. openfilename.lpstrFileTitle = NULL;
  927. openfilename.nMaxFileTitle = 0;
  928. openfilename.lpstrInitialDir = NULL;
  929. openfilename.lpstrTitle = TEXT("Pick a Microsoft Fax Address Book file");
  930. openfilename.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
  931. openfilename.nFileOffset = 0;
  932. openfilename.nFileExtension = 0;
  933. openfilename.lpstrDefExt = TEXT("fab");
  934. openfilename.lCustData = 0;
  935. openfilename.lpfnHook = NULL;
  936. openfilename.lpTemplateName = NULL;
  937. // This hides the fax address book. define FAXAB_YES to expose it.
  938. // No Fax address book, unless it's hardcoded into the profile
  939. /*
  940. * Call up the common dialog
  941. */
  942. if (!GetOpenFileName (&openfilename))
  943. {
  944. // user pressed cancel
  945. // CHECK: This means we do not have a fab file. Shouldn't I return
  946. // some kind of an error ? The SAB doesn't.
  947. goto out;
  948. }
  949. }
  950. }
  951. /*
  952. * Set the file name property
  953. */
  954. sProp[ivallogonPR_FAB_FILE].ulPropTag = PR_FAB_FILE_A;
  955. #ifdef UNICODE
  956. WideCharToMultiByte( CP_ACP, 0, szFileName, -1, szAnsiFileName, ARRAYSIZE(szAnsiFileName), NULL, NULL );
  957. sProp[ivallogonPR_FAB_FILE].Value.lpszA = szAnsiFileName;
  958. #else
  959. sProp[ivallogonPR_FAB_FILE].Value.lpszA = szFileName;
  960. #endif
  961. /* if no properties were found then we're configuring for the
  962. * first time and so we have to generate a new muid for the
  963. * PR_FAB_ID property
  964. */
  965. /************************
  966. *** PR_FAB_UID ******
  967. ************************/
  968. /*
  969. * 1. Check the lpProps (cValues) passed to ServiceEntry
  970. */
  971. for (uliProp=0; uliProp < cValues; uliProp++)
  972. {
  973. if (PROP_ID(lpProps[uliProp].ulPropTag)==PROP_ID(PR_FAB_UID))
  974. break;
  975. }
  976. if ( (uliProp < cValues) && (PROP_TYPE(lpProps[uliProp].ulPropTag)!=PT_ERROR))
  977. {
  978. memcpy(&muid,lpProps[uliProp].Value.bin.lpb,SIZEOF(MAPIUID));
  979. fUIDFound = TRUE;
  980. }
  981. /*
  982. * 2. Now the properties I got from the profile (if any)
  983. */
  984. else if ( (PROP_ID(lpsPropVal[1].ulPropTag) == PROP_ID(PR_FAB_UID)) &&
  985. (PROP_TYPE(lpsPropVal[1].ulPropTag) != PT_ERROR)
  986. )
  987. {
  988. memcpy(&muid,lpsPropVal[1].Value.bin.lpb,SIZEOF(MAPIUID));
  989. fUIDFound = TRUE;
  990. }
  991. else
  992. {
  993. /* need to generate a uid */
  994. fUIDFound = FALSE;
  995. }
  996. /* Discard GetProps() return data, if any. */
  997. if (lpsPropVal)
  998. lpFreeBuff (lpsPropVal);
  999. /*
  1000. * 3. Last resort: generate a UID
  1001. */
  1002. if (!fUIDFound)
  1003. {
  1004. hResult = lpMAPISup->lpVtbl->NewUID(lpMAPISup,&muid);
  1005. if (HR_FAILED(hResult))
  1006. {
  1007. /*
  1008. * Can't get a uid so just leave
  1009. */
  1010. goto out;
  1011. }
  1012. }
  1013. /*
  1014. * Set the id property
  1015. */
  1016. sProp[ivallogonPR_FAB_UID].ulPropTag = PR_FAB_UID;
  1017. sProp[ivallogonPR_FAB_UID].Value.bin.cb = SIZEOF(MAPIUID);
  1018. sProp[ivallogonPR_FAB_UID].Value.bin.lpb = (LPBYTE) &muid;
  1019. /*
  1020. * Save the file name and the id back into the profile
  1021. */
  1022. hResult=lpProf->lpVtbl->SetProps( lpProf,
  1023. cvallogonMax,
  1024. sProp,
  1025. NULL
  1026. );
  1027. if (HR_FAILED(hResult))
  1028. {
  1029. /*
  1030. * Do nothing... So I couldn't save it away this time...
  1031. */
  1032. DebugTrace("AWFXAB32(ServiceEntry): could not SetProps in profile\n");
  1033. hResult = hrSuccess;
  1034. }
  1035. out:
  1036. if (lpProf)
  1037. lpProf->lpVtbl->Release(lpProf);
  1038. DebugTraceResult(ServiceEntry, hResult);
  1039. return hResult;
  1040. }
  1041. /*************************************************************************
  1042. - HrOpenSingleProvider
  1043. -
  1044. * Opens the profile section associated with this provider.
  1045. *
  1046. * If the ServiceEntry() function exported from a provider had
  1047. * more than 1 section associated with it, this is where you'd get the chance
  1048. * to get all of them.
  1049. */
  1050. static SizedSPropTagArray(1, tagaProviderTable) =
  1051. {
  1052. 1,
  1053. {
  1054. PR_PROVIDER_UID
  1055. }
  1056. };
  1057. HRESULT
  1058. HrOpenSingleProvider( LPPROVIDERADMIN lpAdminProviders,
  1059. LPPROFSECT FAR * lppProfSect
  1060. )
  1061. {
  1062. HRESULT hResult;
  1063. LPMAPITABLE lpTable = NULL;
  1064. LPSRowSet lpRows = NULL;
  1065. LPSPropValue lpProp;
  1066. hResult = lpAdminProviders->lpVtbl->GetProviderTable( lpAdminProviders,
  1067. 0,
  1068. &lpTable
  1069. );
  1070. if (HR_FAILED(hResult))
  1071. goto out;
  1072. hResult = lpTable->lpVtbl->SetColumns(lpTable, (LPSPropTagArray) &tagaProviderTable, 0);
  1073. if (HR_FAILED(hResult))
  1074. goto out;
  1075. hResult = lpTable->lpVtbl->QueryRows(lpTable, 1, 0, &lpRows);
  1076. if (HR_FAILED(hResult))
  1077. goto out;
  1078. if (lpRows->cRows == 0)
  1079. {
  1080. hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  1081. goto out;
  1082. }
  1083. lpProp = lpRows->aRow[0].lpProps;
  1084. hResult = lpAdminProviders->lpVtbl->OpenProfileSection(
  1085. lpAdminProviders,
  1086. (LPMAPIUID) lpProp->Value.bin.lpb,
  1087. NULL,
  1088. MAPI_MODIFY,
  1089. lppProfSect);
  1090. out:
  1091. FreeProws(lpRows);
  1092. if (lpTable)
  1093. lpTable->lpVtbl->Release(lpTable);
  1094. DebugTraceResult(HrOpenSingleProvider, hResult);
  1095. return hResult;
  1096. }
  1097. /*
  1098. - ScLoadString
  1099. -
  1100. * Loads a string from a resource. It will optionally allocate the string if
  1101. * a allocation function is passed in. Otherwise it assumes that the *lppsz
  1102. * is already allocated.
  1103. */
  1104. SCODE ScLoadString( UINT ids,
  1105. ULONG ulcch,
  1106. LPALLOCATEBUFFER lpAllocBuff,
  1107. HINSTANCE hLibrary,
  1108. LPTSTR * lppsz
  1109. )
  1110. {
  1111. SCODE sc = S_OK;
  1112. int iRet;
  1113. /*
  1114. * Assert parameters
  1115. */
  1116. Assert((lpAllocBuff ? !IsBadCodePtr((FARPROC) lpAllocBuff):TRUE));
  1117. Assert(ids!=0);
  1118. if (lpAllocBuff)
  1119. {
  1120. sc = lpAllocBuff(ulcch*SIZEOF(TCHAR), lppsz);
  1121. if (FAILED(sc))
  1122. {
  1123. goto out;
  1124. }
  1125. }
  1126. #ifdef DEBUG
  1127. else
  1128. {
  1129. Assert(!IsBadWritePtr(*lppsz, (UINT) ulcch*SIZEOF(TCHAR)));
  1130. }
  1131. #endif /* DEBUG */
  1132. iRet = LoadString( hLibrary,
  1133. ids,
  1134. *lppsz,
  1135. (UINT)ulcch
  1136. );
  1137. if (!iRet)
  1138. {
  1139. DebugTrace("AWFXAB32(ScLoadString): LoadString() failed...\n");
  1140. sc = E_FAIL;
  1141. goto out;
  1142. }
  1143. out:
  1144. DebugTraceSc(ScLoadString, sc);
  1145. return sc;
  1146. }
  1147. /*************************************************************************
  1148. *
  1149. - LoadIniParams
  1150. -
  1151. * Loads any paramters I need from the registry
  1152. *
  1153. */
  1154. void LoadIniParams(void)
  1155. {
  1156. //fExposeFaxAB = TRUE;
  1157. #if 0
  1158. fExposeFaxAB = GetInitializerInt( HKEY_CURRENT_USER,
  1159. TEXT("Address Book Provider"),
  1160. TEXT("ExposeFaxAB"),
  1161. FALSE,
  1162. TEXT("Software\\Microsoft\\At Work Fax")
  1163. );
  1164. fDebugTrap = GetInitializerInt( HKEY_CURRENT_USER,
  1165. TEXT("Address Book Provider"),
  1166. TEXT("DebugTrap"),
  1167. FALSE,
  1168. TEXT("Software\\Microsoft\\At Work Fax")
  1169. );
  1170. #endif
  1171. }
  1172. #undef _FAXAB_ABP