ABP.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:29k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /***********************************************************************
  2.  *
  3.  *  ABP.C
  4.  *
  5.  *
  6.  *  The Sample 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.  *  Copyright 1992-1995 Microsoft Corporation.  All Rights Reserved.
  25.  *
  26.  ***********************************************************************/
  27. #include "abp.h"
  28. #include <smpab.h>
  29. /*
  30.  *  The Local Identifier
  31.  */
  32. LCID lcidUser;
  33. /*
  34.  *  This provider's MAPIUID.  It's used as part of the entryIDs generated from this provider.
  35.  */
  36. MAPIUID muidABSample = MUIDABSAMPLE;
  37. /*
  38.  *  This provider's value for PR_AB_PROVIDER_ID.  It's found in the hierarchy table exposed
  39.  *  by this provider
  40.  */
  41. MAPIUID muidSABProviderID = SAB_PROVIDER_ID;
  42. /*
  43.  *  This provider's Email Type
  44.  */
  45. LPSTR lpszEMT = SZEMAILTYPE;
  46. /*
  47.  *  Used to keep track of all logon objects created on the ABPInit object
  48.  */
  49. typedef struct _object
  50. {
  51.     struct _object *lppNext;
  52.     LPVOID lpObject;
  53. } OBJECTLIST, *LPOBJECTLIST;
  54. /*
  55.  *  structures and filters defined for display tables
  56.  *
  57.  */
  58. DTBLLABEL dtbllabel = {sizeof(DTBLLABEL), 0};
  59. DTBLPAGE dtblpage = {sizeof(DTBLPAGE), 0, 0, 0};
  60. DTBLGROUPBOX dtblgroupbox = {sizeof(DTBLGROUPBOX), 0};
  61. CHAR szNoFilter[] = "*";
  62. CHAR szAddrTypeFilter[] = "[~:]";
  63. CHAR szFileNameFilter[] = "[~   \\]"; /* ends up [~<space><tab>\] */
  64. /*
  65.  *  Prototypes for the functions in this file, most of which I return
  66.  *  in the jump table returned from ABProviderInit().
  67.  */
  68. //ABPROVIDERINIT ABProviderInit;
  69. MSGSERVICEENTRY ServiceEntry;
  70. HRESULT HrOpenSingleProvider(LPPROVIDERADMIN lpAdminProviders,
  71.                              LPPROFSECT FAR * lppProfSect);
  72. /*
  73.  *  Definition of the init object
  74.  */
  75. typedef struct _ABP {
  76.     ABP_Vtbl FAR *      lpVtbl;
  77.     SAB_IUnknown;
  78.     /*
  79.      * list of logon objects 
  80.      */
  81.     LPOBJECTLIST  lpObjectList;   
  82. } ABP, FAR *LPABP;
  83. /*
  84.  *  The ABInit object's vtbl is filled in here
  85.  */
  86. ABP_Vtbl vtblABP =
  87. {
  88.     ABP_QueryInterface,
  89.     (ABP_AddRef_METHOD *) ROOT_AddRef,
  90.     ABP_Release,
  91.     ABP_Shutdown,
  92.     ABP_Logon
  93. };
  94. /*
  95.  -  ABProviderInit
  96.  -
  97.  *  Initializes this provider.  Returns an IABProvider object.
  98.  *
  99.  */
  100. STDINITMETHODIMP
  101. ABProviderInit(
  102.     HINSTANCE hLibrary,
  103.     LPMALLOC lpMalloc,
  104.     LPALLOCATEBUFFER lpAllocBuff,
  105.     LPALLOCATEMORE lpAllocMore,
  106.     LPFREEBUFFER lpFreeBuff,
  107.     ULONG ulFlags,
  108.     ULONG ulMAPIVersion,
  109.     ULONG FAR * lpulABVersion,
  110.     LPABPROVIDER FAR * lppABProvider)
  111. {
  112.     HRESULT hResult = hrSuccess;
  113.     LPABP lpABP;
  114.     SCODE sc;
  115.     /*
  116.      *  Check the version
  117.      */
  118.     if (ulMAPIVersion < CURRENT_SPI_VERSION)
  119.     {
  120.         /*
  121.          *  MAPI's version is too old.
  122.          */
  123.         /*
  124.          *  See if they understand my version
  125.          */
  126.         *lpulABVersion = CURRENT_SPI_VERSION;
  127.         
  128.         DebugTraceSc(ABProviderInit, MAPI_E_VERSION);
  129.         return ResultFromScode(MAPI_E_VERSION);
  130.     }
  131.     /*
  132.      *  Allocate memory for this Init Object
  133.      */
  134.     sc = lpAllocBuff (sizeof(ABP), &lpABP);
  135.     if (FAILED(sc))
  136.     {
  137.         /*
  138.          *  Out of memory
  139.          */
  140.         DebugTraceSc(ABProviderInit, sc);
  141.         return ResultFromScode(sc);
  142.     }
  143.     /*
  144.      *  Initialize the idle engine that MAPI supplies.  This is most useful
  145.      *  when browsing the .SAB file.  See ABCTBLn.C.
  146.      */
  147.     if (MAPIInitIdle(NULL) == -1)
  148.     {
  149.         hResult = ResultFromScode(E_FAIL);
  150.         goto err;
  151.     }
  152.     /*
  153.      *  Hold on to the lpMalloc
  154.      */
  155.     Assert(lpMalloc);
  156.     lpMalloc->lpVtbl->AddRef(lpMalloc);
  157.     lpABP->lpVtbl = &vtblABP;
  158.     lpABP->lcInit = 1;
  159.     lpABP->hLibrary = hLibrary;
  160.     lpABP->lpMalloc = lpMalloc;
  161.     lpABP->lpAllocBuff = lpAllocBuff;
  162.     lpABP->lpAllocMore = lpAllocMore;
  163.     lpABP->lpFreeBuff = lpFreeBuff;
  164.     lpABP->lpObjectList = NULL;
  165.     InitializeCriticalSection(&lpABP->cs);
  166.     *lppABProvider = (LPABPROVIDER) lpABP;
  167.     *lpulABVersion = CURRENT_SPI_VERSION;
  168.     /*
  169.      *  Get our Locale Identifier
  170.      */
  171.     lcidUser = GetUserDefaultLCID();
  172. out:
  173.     DebugTraceResult(ABProviderInit, hResult);
  174.     return hResult;
  175. err:
  176.     lpFreeBuff(lpABP);
  177.     goto out;
  178. }
  179. /*
  180.  -  ABP_QueryInterface
  181.  -
  182.  *  Supports QI'ing to IUnknown and IABProvider
  183.  *  
  184.  *  Note that for all the methods of IABProvider that parameter validation
  185.  *  is unnecessary.  This is because MAPI is handling all the parameters
  186.  *  being passed in.
  187.  *  At best you can assert your parameters.
  188.  */
  189. STDMETHODIMP
  190. ABP_QueryInterface(LPABP lpABP, REFIID lpiid, LPVOID * ppvObj)
  191. {
  192.     /*  See if the requested interface is one of ours */
  193.     if (memcmp(lpiid, &IID_IUnknown, sizeof(IID)) &&
  194.         memcmp(lpiid, &IID_IABProvider, sizeof(IID)))
  195.     {
  196.         *ppvObj = NULL;         /* OLE requires zeroing [out] parameter on error */
  197.         DebugTraceSc(ABP_QueryInterface, E_NOINTERFACE);
  198.         return ResultFromScode(E_NOINTERFACE);
  199.     }
  200.     /*  We'll do this one. Bump the usage count and return a new pointer. */
  201.     EnterCriticalSection(&lpABP->cs);
  202.     ++lpABP->lcInit;
  203.     LeaveCriticalSection(&lpABP->cs);
  204.     
  205.     *ppvObj = lpABP;
  206.     return hrSuccess;
  207. }
  208. /*
  209.  -  ABP_Release
  210.  -
  211.  *  Releases and cleans up this object
  212.  */
  213. STDMETHODIMP_(ULONG)
  214. ABP_Release(LPABP lpABP)
  215. {
  216.     long lcInit;
  217.     EnterCriticalSection(&lpABP->cs);
  218.     lcInit = --lpABP->lcInit;
  219.     LeaveCriticalSection(&lpABP->cs);
  220.     if (lcInit == 0)
  221.     {
  222.         DeleteCriticalSection(&lpABP->cs);
  223.         lpABP->lpVtbl = NULL;
  224.         lpABP->lpFreeBuff(lpABP);
  225.         return (0);
  226.     }
  227.     return lcInit;
  228. }
  229. /*
  230.  -  ABP_Shutdown
  231.  -
  232.  *  Informs this provider that MAPI is done with it.
  233.  *
  234.  *
  235.  */
  236. STDMETHODIMP
  237. ABP_Shutdown(LPABP lpABP, ULONG FAR * lpulFlags)
  238. {
  239.     MAPIDeinitIdle();
  240.     if (lpABP->lpMalloc)
  241.     {
  242.         lpABP->lpMalloc->lpVtbl->Release(lpABP->lpMalloc);
  243.         lpABP->lpMalloc = NULL;
  244.     }
  245.     return hrSuccess;
  246. }
  247. /*
  248.  -  ABP_Logon
  249.  -
  250.  *  Create a logon object and return it to MAPI.
  251.  *
  252.  */
  253. /*
  254.  *  The PropTagArray used to retrieve logon properties
  255.  */
  256. enum {  ivallogonPR_SAB_FILE,
  257.         ivallogonPR_SAB_UID,
  258.         cvallogonMax };
  259. static const SizedSPropTagArray(cvallogonMax, tagaSABLogonProps) =
  260. {
  261.     cvallogonMax,
  262.     {
  263.         PR_SAB_FILE,
  264.         PR_SAB_UID
  265.     }
  266. };
  267. STDMETHODIMP
  268. ABP_Logon(  LPABP             lpABP,
  269.             LPMAPISUP         lpMAPISup,
  270.             ULONG             ulUIParam,
  271.             LPTSTR            lpszProfileName,
  272.             ULONG             ulFlags,
  273.             ULONG FAR *       lpulpcbSecurity,
  274.             LPBYTE FAR *      lppbSecurity,
  275.             LPMAPIERROR FAR * lppMapiError,
  276.             LPABLOGON FAR *   lppABPLogon)
  277. {
  278.     LPABLOGON       lpABLogon       = NULL;
  279.     HRESULT         hResult         = hrSuccess;
  280.     SCODE           scode;
  281.     LPPROFSECT      lpProfSect      = NULL;
  282.     LPSPropValue    lpsPropVal      = NULL;
  283.     ULONG           cValues         = 0;
  284.     LPSTR           lpstrT          = NULL;
  285.     BOOL            fUINeeded;
  286.     BOOL            fNeedMAPIUID    = FALSE;
  287.     MAPIUID         muidID;
  288.     LPOBJECTLIST    lpObjectList;
  289.     CHAR            szFileName[MAX_PATH];
  290.     szFileName[0] = '';
  291.     
  292.     *lppMapiError = NULL;
  293.     
  294.     if ( ulFlags & MAPI_UNICODE )
  295.     {
  296.         DebugTraceArg( ABP_Logon, "Bad Character width" );
  297.         return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  298.     }
  299.     
  300.     /*
  301.      *  Get the name of my browse file from the profile section
  302.      */
  303.     /*  Open the section for my provider */
  304.     hResult = lpMAPISup->lpVtbl->OpenProfileSection(lpMAPISup,
  305.                 NULL,
  306.                 MAPI_MODIFY,
  307.                 &lpProfSect);
  308.     if (HR_FAILED(hResult))
  309.         goto out;
  310.     /*  Get the property containing the browse file name and the sab uid. */
  311.     hResult = lpProfSect->lpVtbl->GetProps(
  312.         lpProfSect,
  313.         (LPSPropTagArray) &tagaSABLogonProps,
  314.         0,      /* ansi */
  315.         &cValues,
  316.         &lpsPropVal);
  317.     if (HR_FAILED(hResult))
  318.         goto out;
  319. #ifdef DEBUG
  320.     if (hResult != hrSuccess)
  321.     {
  322.         if (PROP_TYPE(lpsPropVal[ivallogonPR_SAB_FILE].ulPropTag) == PT_ERROR
  323.             && lpsPropVal[0].Value.err != MAPI_E_NOT_FOUND)
  324.         {
  325.             TraceSz1("ABP_Logon (PR_SAB_FILE) got unexpected scode: %sn",
  326.                 SzDecodeScode(lpsPropVal[ivallogonPR_SAB_FILE].Value.err));
  327.         }
  328.         if (PROP_TYPE(lpsPropVal[ivallogonPR_SAB_UID].ulPropTag) == PT_ERROR
  329.             && lpsPropVal[ivallogonPR_SAB_UID].Value.err != MAPI_E_NOT_FOUND)
  330.         {
  331.             TraceSz1("ABP_Logon (PR_SAB_UID) got unexpected scode: %sn",
  332.                 SzDecodeScode(lpsPropVal[1].Value.err));
  333.         }
  334.     }
  335. #endif
  336.     /*  Ignore warnings from reading the property. */
  337.     hResult = hrSuccess;
  338.     /* copy the sab file name */
  339.     if (lpsPropVal[0].ulPropTag == PR_SAB_FILE)
  340.     {
  341.         UINT cch = lstrlenA(lpsPropVal[0].Value.lpszA);
  342.         if (cch >= MAX_PATH)
  343.             cch = MAX_PATH - 1;
  344.         if (cch)
  345.             memcpy(szFileName, lpsPropVal[0].Value.lpszA, cch);
  346.         szFileName[cch] = '';
  347.     }
  348.     else
  349.     {
  350.         DebugTrace("ABP_Logon PR_SAB_FILE not found");
  351.     }
  352.     /* copy the sab uid */
  353.     if (lpsPropVal[1].ulPropTag == PR_SAB_UID)
  354.     {
  355.         memcpy(&muidID, lpsPropVal[1].Value.bin.lpb, sizeof(MAPIUID));
  356.     }
  357.     else
  358.     {
  359.         DebugTrace("ABP_Logon PR_SAB_UID not found");
  360.         fNeedMAPIUID = TRUE;
  361.     }
  362.     /*  Discard GetProps() return data, if any. */
  363.     lpABP->lpFreeBuff(lpsPropVal);
  364.     /*
  365.      *  UI needed unless the file name is good and file exists.
  366.      */
  367.     fUINeeded = TRUE;
  368.     if (szFileName[0] != 0)
  369.     {
  370.         /* Verify the file exists. */
  371.         HANDLE hFile = CreateFile(
  372.             szFileName,
  373.             GENERIC_READ,
  374.             FILE_SHARE_READ,
  375.             NULL,
  376.             OPEN_EXISTING,
  377.             FILE_ATTRIBUTE_NORMAL,
  378.             NULL);
  379.         if (hFile != INVALID_HANDLE_VALUE)
  380.         {
  381.             CloseHandle(hFile);
  382.             fUINeeded = FALSE;
  383.         }
  384.     }
  385.     /*
  386.     *  if the sab file name was not found in the profile or the sab file
  387.     *  does not exist we have to get the user to pick another one and
  388.     *  save back into the profile
  389.     */
  390.     if (fUINeeded)
  391.     {
  392.         OPENFILENAME openfilename;
  393.         SPropValue sProp[1];
  394.         /*
  395.          *  Can't bring up UI unless the client allows it
  396.          */
  397.         if (ulFlags & AB_NO_DIALOG)
  398.         {
  399.             hResult = ResultFromScode(MAPI_E_LOGON_FAILED);
  400.             goto out;
  401.         }
  402.         /*
  403.          *  Get the user to select a file
  404.          */
  405.         openfilename.lStructSize = sizeof(OPENFILENAME);
  406.         openfilename.hwndOwner = (HWND) ulUIParam;
  407.         openfilename.hInstance = 0; /* Ignored */
  408.         openfilename.lpstrFilter = TEXT("Sample AB files*.sab");
  409.         openfilename.lpstrCustomFilter = NULL;
  410.         openfilename.nMaxCustFilter = 0;
  411.         openfilename.nFilterIndex = 0;
  412.         openfilename.lpstrFile = szFileName;
  413.         openfilename.nMaxFile = MAX_PATH;
  414.         openfilename.lpstrFileTitle = NULL;
  415.         openfilename.nMaxFileTitle = 0;
  416.         openfilename.lpstrInitialDir = NULL;
  417.         openfilename.lpstrTitle = TEXT("Sample Address Book");
  418.         openfilename.Flags = OFN_FILEMUSTEXIST |
  419.             OFN_HIDEREADONLY |
  420.             OFN_NOCHANGEDIR;
  421.         openfilename.nFileOffset = 0;
  422.         openfilename.nFileExtension = 0;
  423.         openfilename.lpstrDefExt = TEXT("sab");
  424.         openfilename.lCustData = 0;
  425.         openfilename.lpfnHook = NULL;
  426.         openfilename.lpTemplateName = NULL;
  427.         /*
  428.          *  Call up the common dialog
  429.          */
  430.         if (!GetOpenFileName(&openfilename))
  431.         {
  432. #ifdef DEBUG
  433.             DWORD dwT;
  434.             dwT = CommDlgExtendedError();
  435. #endif /* DEBUG */
  436.             
  437.             hResult = ResultFromScode(MAPI_E_LOGON_FAILED);
  438.             goto out;
  439.         }
  440.         /*
  441.          *  Set the sab file name property value
  442.          */
  443.         sProp[0].ulPropTag = PR_SAB_FILE;
  444.         sProp[0].Value.lpszA = szFileName;
  445.         /*
  446.          *  Save the sab file into the profile
  447.          */
  448.         if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
  449.         {
  450.             /*
  451.              *  Do nothing...  So I couldn't save it away this time...
  452.              */
  453.             DebugTraceResult("ABP_Logon got unexpected result on SetPropsn", hResult);
  454.             hResult = hrSuccess;
  455.         }
  456.     }
  457.     /*
  458.     *  if the uid was not found we have to generate a new muid for the
  459.     *  PR_SAB_ID property and save it back into the profile
  460.     */
  461.     if (fNeedMAPIUID)
  462.     {
  463.         SPropValue sProp[1];
  464.         /*
  465.          *  Get a new sab uid
  466.          */
  467.         hResult = lpMAPISup->lpVtbl->NewUID(lpMAPISup, &muidID);
  468.         if (HR_FAILED(hResult))
  469.         {
  470.             goto out;
  471.         }
  472.         /*
  473.          *  Set the sab uid property value
  474.          */
  475.         sProp[0].ulPropTag = PR_SAB_UID;
  476.         sProp[0].Value.bin.cb = sizeof(MAPIUID);
  477.         sProp[0].Value.bin.lpb = (LPBYTE) &muidID;
  478.         /*
  479.          *  Save the sab uid into the profile
  480.          */
  481.         if (hResult = lpProfSect->lpVtbl->SetProps(lpProfSect, 1, sProp, NULL))
  482.         {
  483.             /*
  484.              *  Do nothing...  So I couldn't save it away this time...
  485.              */
  486.             DebugTraceResult("ABP_Logon got unexpected result on SetPropsn", hResult);
  487.             hResult = hrSuccess;
  488.         }
  489.     }
  490.     /*
  491.      *  Allocate space for keeping the file name in the ABLogon object
  492.      */
  493.     if (scode = lpABP->lpAllocBuff(lstrlenA(szFileName)+1, &lpstrT))
  494.     {
  495.         hResult = ResultFromScode(scode);
  496.         goto out;
  497.     }
  498.     lstrcpyA(lpstrT, szFileName);
  499.     hResult = HrNewABLogon(&lpABLogon,
  500.                             (LPABPROVIDER) lpABP,
  501.                             lpMAPISup,
  502.                             lpstrT,
  503.                             &muidID,
  504.                             lpABP->hLibrary,
  505.                             lpABP->lpAllocBuff,
  506.                             lpABP->lpAllocMore,
  507.                             lpABP->lpFreeBuff,
  508.                             lpABP->lpMalloc );
  509.     if (HR_FAILED(hResult))
  510.     {
  511.         goto out;
  512.     }
  513.     /*
  514.      *  Allocate space for another object list item
  515.      */
  516.     scode = lpABP->lpAllocBuff(sizeof(OBJECTLIST), &lpObjectList);
  517.     if (FAILED(scode))
  518.     {
  519.         hResult = ResultFromScode(scode);
  520.         goto out;
  521.     }
  522.     /* Get the Critical Section */
  523.     EnterCriticalSection(&lpABP->cs);
  524.     /* add logon object to begining of providers object list */
  525.     lpObjectList->lpObject = (LPVOID) lpABLogon;
  526.     lpObjectList->lppNext = lpABP->lpObjectList;
  527.     /* insert new logon object into the head of the providers object list */
  528.     lpABP->lpObjectList = lpObjectList;
  529.     /* leave critical section */
  530.     LeaveCriticalSection(&lpABP->cs);
  531.     /*
  532.      *  Register my MAPIUID for this provider,
  533.      *  but do not allow an error from setting the
  534.      *  MAPIUID to cause failure to Logon.
  535.      */
  536.     (void)lpMAPISup->lpVtbl->SetProviderUID(lpMAPISup,
  537.         (LPMAPIUID) &muidABSample, 0);
  538.     *lppABPLogon = lpABLogon;
  539. out:
  540.     if (lpProfSect)
  541.         lpProfSect->lpVtbl->Release(lpProfSect);
  542.     if (hResult)
  543.     {
  544.         lpABP->lpFreeBuff(lpstrT);
  545.         Assert(lpABLogon == NULL);
  546.         /* Verify we don't return warnings at this time. */
  547.         Assert(HR_FAILED(hResult));
  548.     }
  549.     DebugTraceResult(ABP_Logon, hResult);
  550.     return hResult;
  551. }
  552. /*
  553.  *  Removes a particular logon object from the list of logon objects
  554.  *  that's kept track of in the IABProvider object
  555.  */
  556. void
  557. RemoveLogonObject(LPABPROVIDER lpABProvider, LPVOID lpvABLogon, LPFREEBUFFER lpFreeBuff)
  558. {
  559.     LPOBJECTLIST *lppObjectList;
  560.     LPOBJECTLIST lpObjectListT;
  561.     LPABP lpABP = (LPABP) lpABProvider;
  562. #if defined DEBUG
  563.     BOOL fFound = FALSE;
  564. #endif
  565.     /* Get the Critical Section */
  566.     EnterCriticalSection(&lpABP->cs);
  567.     /*
  568.      *  remove this logon object from the provider init objects list
  569.      *  of logon objects
  570.      */
  571.     lppObjectList = &(lpABP->lpObjectList);
  572.     while (*lppObjectList)
  573.     {
  574.         /* is this the logon object? */
  575.         if ((*lppObjectList)->lpObject == lpvABLogon)
  576.         {
  577.             /* save next list item */
  578.             lpObjectListT = (*lppObjectList)->lppNext;
  579.             /* free the object list item */
  580.             lpFreeBuff(*lppObjectList);
  581.             /* delete object from the list */
  582.             *lppObjectList = lpObjectListT;
  583. #if defined DEBUG
  584.             fFound = TRUE;
  585. #endif
  586.             break;
  587.         }
  588.         lppObjectList = &(*lppObjectList)->lppNext;
  589.     }
  590.     /* leave critical section */
  591.     LeaveCriticalSection(&lpABP->cs);
  592. #if defined DEBUG
  593.     AssertSz(fFound, TEXT("Logon object not found on providers object list"));
  594. #endif
  595.     return;
  596. }   
  597. /*
  598.  *  Finds a particular logon object by its muid.
  599.  */
  600. void
  601. FindLogonObject(LPABPROVIDER lpABProvider, LPMAPIUID lpMuidToFind, LPABLOGON * lppABLogon)
  602. {
  603.     LPABP lpABP = (LPABP) lpABProvider;
  604.     LPABLOGON lpABLogonT = NULL;
  605.     LPOBJECTLIST lpObjectList = NULL;
  606.     LPMAPIUID lpMuidLogon = NULL;
  607.     Assert(!IsBadReadPtr(lpABP, sizeof(ABP)));
  608.     Assert(!IsBadReadPtr(lpMuidToFind, sizeof(MAPIUID)));
  609.     Assert(!IsBadReadPtr(lppABLogon, sizeof(LPABLOGON)));
  610.     /* Get the Critical Section */
  611.     EnterCriticalSection(&lpABP->cs);
  612.     *lppABLogon = NULL;
  613.     for (lpObjectList = lpABP->lpObjectList;
  614.         lpObjectList; lpObjectList = lpObjectList->lppNext)
  615.     {
  616.         lpABLogonT = (LPABLOGON) lpObjectList->lpObject;
  617.         
  618.         lpMuidLogon = LpMuidFromLogon(lpABLogonT);
  619.         if (memcmp((LPVOID) lpMuidLogon, (LPVOID) lpMuidToFind, sizeof(MAPIUID)) == 0)
  620.         {
  621.             *lppABLogon = lpABLogonT;
  622.             break;
  623.         }
  624.     }
  625.     /* leave critical section */
  626.     LeaveCriticalSection(&lpABP->cs);
  627. }
  628. /*
  629.  -  ServiceEntry
  630.  -
  631.  *  This funtion is used by MAPI to configure the Sample Address Book.  
  632.  *  It's a lot like ABP_Logon, except that it doesn't return a logon object
  633.  *  and it can be passed in its configuration information (as defined in
  634.  *  smpab.h) from MAPI so that no UI is required.
  635.  *
  636.  */
  637. STDAPI
  638. ServiceEntry(HINSTANCE hInstance,
  639.              LPMALLOC lpMalloc,
  640.              LPMAPISUP lpMAPISup,
  641.              ULONG ulUIParam,
  642.              ULONG ulFlags,
  643.              ULONG ulContext,
  644.              ULONG cValues,
  645.              LPSPropValue lpProps,
  646.              LPPROVIDERADMIN lpAdminProviders,
  647.              LPMAPIERROR FAR *lppMapiError)
  648. {
  649.     OPENFILENAME openfilename;
  650.     char szFileName[MAX_PATH];
  651.     HRESULT hResult = hrSuccess;
  652.     LPSPropValue lpsPropVal = NULL;
  653.     ULONG ulCount = 0;
  654.     LPALLOCATEBUFFER lpAllocBuff;
  655.     LPALLOCATEMORE lpAllocMore;
  656.     LPFREEBUFFER lpFreeBuff;
  657.     LPPROFSECT lpProf = NULL;
  658.     BOOL fUINeeded = FALSE;
  659.     BOOL fNeedMAPIUID = FALSE;
  660.     SPropValue sProp[2];
  661.     ULONG uliProp;
  662.     MAPIUID muid;
  663.     /*  Validate parameters */
  664.     /* check the support object */
  665.     if (IsBadReadPtr(lpMAPISup, sizeof(LPMAPISUP)))
  666.     {
  667.         DebugTraceSc(ServiceEntry, E_INVALIDARG);
  668.         return ResultFromScode(E_INVALIDARG);
  669.     }
  670.     
  671.     if ( ulFlags & MAPI_UNICODE )
  672.     {
  673.         DebugTraceArg( ServiceEntry, "Bad character width" );
  674.         return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  675.     }
  676.     
  677.     /*
  678.      *  check for context
  679.      */
  680.     if (ulContext == MSG_SERVICE_DELETE || ulContext == MSG_SERVICE_INSTALL
  681.         || ulContext == MSG_SERVICE_UNINSTALL)
  682.         return hrSuccess;
  683.     if (ulContext != MSG_SERVICE_CONFIGURE && ulContext != MSG_SERVICE_CREATE)
  684.     {
  685.         DebugTrace(TEXT("ServiceEntry unsupported context"));
  686.         return ResultFromScode(MAPI_E_NO_SUPPORT);
  687.     }
  688.     /*  Get the memory allocation routines we'll be needing. */
  689.     hResult = lpMAPISup->lpVtbl->GetMemAllocRoutines(lpMAPISup,
  690.         &lpAllocBuff, &lpAllocMore, &lpFreeBuff);
  691.     if (hResult)
  692.     {
  693.         DebugTraceResult(MAPISUP: :GetMemAllocRoutines, hResult);
  694.         goto out;
  695.     }
  696.     /* Open the profile section associated with our provider */
  697.     hResult = HrOpenSingleProvider(lpAdminProviders, &lpProf);
  698.     if (hResult)
  699.     {
  700.         DebugTrace(TEXT("Unable to open the profile."));
  701.         goto out;
  702.     }
  703.     szFileName[0] = '';
  704.     /* get sab filename and uid from profile */
  705.     hResult = lpProf->lpVtbl->GetProps(
  706.         lpProf,
  707.         (LPSPropTagArray) &tagaSABLogonProps,
  708.         ulFlags & MAPI_UNICODE,
  709.         &ulCount,
  710.         &lpsPropVal);
  711.     /*  Ignore errors/warnings from reading the property. */
  712.     hResult = hrSuccess;
  713.     /* Look for the .SAB in the config props first */
  714.     for (uliProp = 0; uliProp < cValues; uliProp++)
  715.     {
  716.         if (PROP_ID(lpProps[uliProp].ulPropTag) == PROP_ID(PR_SAB_FILE))
  717.             break;
  718.     }
  719.     if (uliProp < cValues &&
  720.         PROP_TYPE(lpProps[uliProp].ulPropTag) != PT_ERROR)
  721.     {
  722.         ULONG cch = lstrlenA(lpProps[uliProp].Value.lpszA);
  723.         if (cch >= MAX_PATH)
  724.             cch = MAX_PATH - 1;
  725.         if (cch)
  726.             memcpy(szFileName, lpProps[uliProp].Value.lpszA, (size_t) cch);
  727.         szFileName[cch] = '';
  728.     }
  729.     else if (lpsPropVal && PROP_ID(lpsPropVal[0].ulPropTag) ==
  730.         PROP_ID(PR_SAB_FILE) &&
  731.         PROP_TYPE(lpsPropVal[0].ulPropTag) != PT_ERROR)
  732.     {
  733.         ULONG cch = lstrlenA(lpsPropVal[0].Value.lpszA);
  734.         if (cch >= MAX_PATH)
  735.             cch = MAX_PATH - 1;
  736.         if (cch)
  737.             memcpy(szFileName, lpsPropVal[0].Value.lpszA, (size_t) cch);
  738.         szFileName[cch] = '';
  739.     }
  740.     else
  741.     {
  742.         /* need to ask the user for the sab file */
  743.         fUINeeded = TRUE;
  744.     }
  745.     /* Look for the SAB_UID in the config props first */
  746.     for (uliProp = 0; uliProp < cValues; uliProp++)
  747.     {
  748.         if (PROP_ID(lpProps[uliProp].ulPropTag) == PROP_ID(PR_SAB_UID))
  749.             break;
  750.     }
  751.     if (uliProp < cValues &&
  752.         PROP_TYPE(lpProps[uliProp].ulPropTag) != PT_ERROR)
  753.     {
  754.         memcpy(&muid, lpProps[uliProp].Value.bin.lpb, sizeof(MAPIUID));
  755.     }
  756.     else if (lpsPropVal && PROP_ID(lpsPropVal[1].ulPropTag) ==
  757.         PROP_ID(PR_SAB_UID) && PROP_TYPE(lpsPropVal[1].ulPropTag) != PT_ERROR)
  758.     {
  759.         memcpy(&muid, lpsPropVal[1].Value.bin.lpb, sizeof(MAPIUID));
  760.     }
  761.     else
  762.     {
  763.         /* need to generate a uid */
  764.         fNeedMAPIUID = TRUE;
  765.     }
  766.     /*  Discard GetProps() return data, if any.
  767.      */
  768.     if (lpsPropVal)
  769.         lpFreeBuff(lpsPropVal);
  770.     /*
  771.      *  if the sab file name was not found in the profile we have to
  772.      *  get the user to pick one and save it back into the profile
  773.      */
  774.     if (   fUINeeded
  775.         && !(ulFlags & (SERVICE_UI_ALLOWED | SERVICE_UI_ALWAYS | UI_SERVICE)))
  776.     {
  777.         /*  We need UI to configure but it's not allowed so we can't configure.
  778.          */
  779.         hResult = ResultFromScode(MAPI_E_UNCONFIGURED);
  780.         DebugTrace("SMPAB::ServiceEntry - Missing properties required to configure service.n");
  781.         goto out;
  782.     }
  783.     if ((fUINeeded) || (ulFlags & UI_SERVICE))
  784.     {
  785.         /*
  786.         *  Get the user to pick a SAB file
  787.         */
  788.         openfilename.lStructSize = sizeof(OPENFILENAME);
  789.         openfilename.hwndOwner = (HWND) ulUIParam;
  790.         openfilename.hInstance = 0; /* Ignored */
  791.         openfilename.lpstrFilter = "Sample AB files*.sab";
  792.         openfilename.lpstrCustomFilter = NULL;
  793.         openfilename.nMaxCustFilter = 0;
  794.         openfilename.nFilterIndex = 0;
  795.         openfilename.lpstrFile = szFileName;
  796.         openfilename.nMaxFile = MAX_PATH;
  797.         openfilename.lpstrFileTitle = NULL;
  798.         openfilename.nMaxFileTitle = 0;
  799.         openfilename.lpstrInitialDir = NULL;
  800.         openfilename.lpstrTitle = "Pick a Sample Address Book file";
  801.         openfilename.Flags = OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR | OFN_HIDEREADONLY;
  802.         openfilename.nFileOffset = 0;
  803.         openfilename.nFileExtension = 0;
  804.         openfilename.lpstrDefExt = "sab";
  805.         openfilename.lCustData = 0;
  806.         openfilename.lpfnHook = NULL;
  807.         openfilename.lpTemplateName = NULL;
  808.         /*
  809.         *  Call up the common dialog
  810.         */
  811.         if (!GetOpenFileName(&openfilename))
  812.         {
  813.             /* user pressed cancel */
  814.             goto out;
  815.         }
  816.     }
  817.     /*
  818.     *  if the uid was not found we have to generate a new muid for the
  819.     *  PR_SAB_ID property and save it back into the profile
  820.     */
  821.     if (fNeedMAPIUID)
  822.     {
  823.         hResult = lpMAPISup->lpVtbl->NewUID(lpMAPISup, &muid);
  824.         if (HR_FAILED(hResult))
  825.         {
  826.             /*
  827.             *  Can't get a uid so just leave
  828.             */
  829.             goto out;
  830.         }
  831.     }
  832.     /*
  833.     *  Set the file name property
  834.     */
  835.     sProp[ivallogonPR_SAB_FILE].ulPropTag = PR_SAB_FILE;
  836.     sProp[ivallogonPR_SAB_FILE].Value.lpszA = szFileName;
  837.     /*
  838.     *  Set the id property
  839.     */
  840.     sProp[ivallogonPR_SAB_UID].ulPropTag = PR_SAB_UID;
  841.     sProp[ivallogonPR_SAB_UID].Value.bin.cb = sizeof(MAPIUID);
  842.     sProp[ivallogonPR_SAB_UID].Value.bin.lpb = (LPBYTE) &muid;
  843.     /*
  844.     *  Save the sab file and the uid back into the profile
  845.     */
  846.     hResult = lpProf->lpVtbl->SetProps(
  847.         lpProf,
  848.         sizeof(sProp) / sizeof(SPropValue),
  849.         sProp,
  850.         NULL);
  851.     if (HR_FAILED(hResult))
  852.     {
  853.         /*
  854.         *  Do nothing...  So I couldn't save it away this time...
  855.         */
  856.         DebugTrace(TEXT("ServiceEntry could not SetProp in profile"));
  857.         hResult = hrSuccess;
  858.     }
  859. out:
  860.     if (lpProf)
  861.         lpProf->lpVtbl->Release(lpProf);
  862.     DebugTraceResult(ServiceEntry, hResult);
  863.     return hResult;
  864. }
  865. /*
  866.  -  HrOpenSingleProvider
  867.  -
  868.  *  Opens the profile section associated with this provider.
  869.  *
  870.  *  If the ServiceEntry() function exported from a provider had
  871.  *  more than 1 section associated with it, this is where you'd get the chance
  872.  *  to get all of them.
  873.  */
  874. static SizedSPropTagArray(1, tagaProviderTable) =
  875. {
  876.     1,
  877.     {
  878.         PR_PROVIDER_UID
  879.     }
  880. };
  881. HRESULT
  882. HrOpenSingleProvider(LPPROVIDERADMIN lpAdminProviders,
  883.                      LPPROFSECT FAR * lppProfSect)
  884. {
  885.     HRESULT hResult;
  886.     LPMAPITABLE lpTable = NULL;
  887.     LPSRowSet lpRows = NULL;
  888.     LPSPropValue lpProp;
  889.     hResult = lpAdminProviders->lpVtbl->GetProviderTable(
  890.         lpAdminProviders,
  891.         0,
  892.         &lpTable);
  893.     if (HR_FAILED(hResult))
  894.         goto out;
  895.     hResult = lpTable->lpVtbl->SetColumns(lpTable, (LPSPropTagArray) &tagaProviderTable, 0);
  896.     if (HR_FAILED(hResult))
  897.         goto out;
  898.     hResult = lpTable->lpVtbl->QueryRows(lpTable, 1, 0, &lpRows);
  899.     if (HR_FAILED(hResult))
  900.         goto out;
  901.     if (lpRows->cRows == 0)
  902.     {
  903.         hResult = ResultFromScode(MAPI_E_NOT_FOUND);
  904.         goto out;
  905.     }
  906.     lpProp = lpRows->aRow[0].lpProps;
  907.     hResult = lpAdminProviders->lpVtbl->OpenProfileSection(
  908.                 lpAdminProviders,
  909.                 (LPMAPIUID) lpProp->Value.bin.lpb,
  910.                 NULL,
  911.                 MAPI_MODIFY,
  912.                 lppProfSect);
  913. out:
  914.     FreeProws(lpRows);
  915.     if (lpTable)
  916.         lpTable->lpVtbl->Release(lpTable);
  917.     DebugTraceResult(HrOpenSingleProvider, hResult);
  918.     return hResult;
  919. }
  920. /*
  921.  -  ScLoadString
  922.  -
  923.  *  Loads a string from a resource.  It will optionally allocate the string if
  924.  *  a allocation function is passed in.  Otherwise it assumes that the *lppsz
  925.  *  is already allocated.
  926.  */
  927. SCODE ScLoadString( UINT                ids,
  928.                     ULONG               ulcch,
  929.                     LPALLOCATEBUFFER    lpAllocBuff,
  930.                     HINSTANCE           hLibrary,
  931.                     LPSTR *             lppsz)
  932. {
  933.     SCODE sc = S_OK;
  934.     int iRet;
  935.     /*
  936.      *  Assert parameters
  937.      */
  938.     Assert((lpAllocBuff ? !IsBadCodePtr((FARPROC) lpAllocBuff):TRUE));
  939.     Assert(ids!=0);
  940.     if (lpAllocBuff)
  941.     {
  942.         sc = lpAllocBuff(ulcch, lppsz);
  943.         if (FAILED(sc))
  944.         {
  945.             goto out;
  946.         }
  947.     }
  948. #ifdef DEBUG
  949.     else
  950.     {
  951.         Assert(!IsBadWritePtr(*lppsz, (UINT) ulcch));
  952.     }
  953. #endif /* DEBUG */
  954.     
  955.     iRet = LoadStringA( hLibrary,
  956.                         ids,
  957.                         *lppsz,
  958.                         (UINT) ulcch);
  959.     if (!iRet)
  960.     {
  961.         DebugTrace("LoadString() failed...n");
  962.         sc = E_FAIL;
  963.         goto out;
  964.     }
  965. out:
  966.     DebugTraceSc(ScLoadString, sc);
  967.     return sc;
  968. }