home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / dbmsg / mapi / flatfile.ab / abp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  29.0 KB  |  1,149 lines

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