ABLOGON.C
Upload User: bangxh
Upload Date: 2007-01-31
Package Size: 42235k
Code Size: 45k
Category:

Windows Develop

Development Platform:

Visual C++

  1. /***********************************************************************
  2.  *
  3.  *  ABLOGON.C
  4.  *
  5.  *
  6.  *  The Sample Address Book Provider.
  7.  *
  8.  *  This file has the code to implement the Sample Address Book's logon
  9.  *  object.
  10.  *
  11.  *  The following routines are implemented in this file:
  12.  *  
  13.  *  ABPLOGON_QueryInterface
  14.  *  ABPLOGON_Release
  15.  *  ABPLOGON_Logoff
  16.  *  ABPLOGON_OpenEntry
  17.  *  ABPLOGON_CompareEntryIDs
  18.  *  ABPLOGON_Advise
  19.  *  ABPLOGON_Unadvise
  20.  *  ABPLOGON_OpenStatusEntry
  21.  *  ABPLOGON_OpenTemplateID
  22.  *  ABPLOGON_GetOneOffTable
  23.  *  ABPLOGON_PrepareRecips
  24.  *  
  25.  *  LpMuidFromLogon
  26.  *  HrLpszGetCurrentFileName
  27.  *  HrReplaceCurrentfileName
  28.  *  GenerateContainerDN
  29.  *  HrBuildRootHier
  30.  *  
  31.  *
  32.  *  Copyright 1992-1995 Microsoft Corporation.  All Rights Reserved.
  33.  *
  34.  ***********************************************************************/
  35. #include "abp.h"
  36. #include "sampabp.rh"
  37. #include <smpab.h>
  38. /*
  39.  *  Definition of the logon object
  40.  */
  41. typedef struct _ABPLOGON {
  42.     ABPLOGON_Vtbl FAR *     lpVtbl;
  43.     SAB_IUnknown;
  44.     /*
  45.      *  Private structure
  46.      */
  47.     LPABPROVIDER lpABP;
  48.     LPSTR lpszFileName;         /* Name of file that is browsed */
  49.     MAPIUID muidID;             /* UID for this logon object */
  50.     LPMAPISUP lpMapiSup;        /* MAPI Support object - gotten via ABP_Logon */
  51.     /*
  52.      *  Table Data for canned tables
  53.      */
  54.     LPTABLEDATA lpTDatRoot;     /*  Root hierarchy  */
  55.     LPTABLEDATA lpTDatOO;       /*  One Off Table  */
  56. } ABPLOGON, FAR *LPABPLOGON;
  57. ABPLOGON_Vtbl vtblABPLOGON =
  58. {
  59.     ABPLOGON_QueryInterface,
  60.     (ABPLOGON_AddRef_METHOD *) ROOT_AddRef,
  61.     ABPLOGON_Release,
  62.     (ABPLOGON_GetLastError_METHOD *) ROOT_GetLastError,
  63.     ABPLOGON_Logoff,
  64.     ABPLOGON_OpenEntry,
  65.     ABPLOGON_CompareEntryIDs,
  66.     ABPLOGON_Advise,
  67.     ABPLOGON_Unadvise,
  68.     ABPLOGON_OpenStatusEntry,
  69.     ABPLOGON_OpenTemplateID,
  70.     ABPLOGON_GetOneOffTable,
  71.     ABPLOGON_PrepareRecips
  72. };
  73. /*
  74.  -  HrNewABLogon
  75.  -
  76.  *
  77.  *  Creates a new Sample AB Logon object.
  78.  */
  79. HRESULT
  80. HrNewABLogon(   LPABLOGON *         lppABLogon,
  81.                 LPABPROVIDER        lpABP,
  82.                 LPMAPISUP           lpMAPISup,
  83.                 LPSTR               lpszSABFile,
  84.                 LPMAPIUID           lpmuid,
  85.                 HINSTANCE           hLibrary,
  86.                 LPALLOCATEBUFFER    lpAllocBuff,
  87.                 LPALLOCATEMORE      lpAllocMore,
  88.                 LPFREEBUFFER        lpFreeBuff,
  89.                 LPMALLOC            lpMalloc )
  90. {
  91.     SCODE sc;
  92.     HRESULT hResult = hrSuccess;
  93.     SPropValue rgSPVStat[6];
  94.     LPABPLOGON lpABPLogon = NULL;
  95.     /*
  96.      *  Allocate space for the lpABPLogon object
  97.      */
  98.     sc = lpAllocBuff(sizeof(ABPLOGON), &lpABPLogon);
  99.     if (FAILED(sc))
  100.     {
  101.         hResult = ResultFromScode(sc);
  102.         goto out;
  103.     }
  104.     /*
  105.      *  Initialize the ABPLogon object
  106.      */
  107.     lpABPLogon->lpVtbl = &vtblABPLOGON;
  108.     lpABPLogon->lcInit = 1;
  109.     lpABPLogon->hResult = hrSuccess;
  110.     lpABPLogon->idsLastError = 0;
  111.     lpABPLogon->hLibrary = hLibrary;
  112.     lpABPLogon->lpMalloc = lpMalloc;
  113.     lpABPLogon->lpAllocBuff = lpAllocBuff;
  114.     lpABPLogon->lpAllocMore = lpAllocMore;
  115.     lpABPLogon->lpFreeBuff = lpFreeBuff;
  116.     lpABPLogon->lpMapiSup = lpMAPISup;
  117.     lpABPLogon->lpABP = (LPABPROVIDER) lpABP;
  118.     lpABPLogon->lpszFileName = lpszSABFile;
  119.     lpABPLogon->muidID = *lpmuid;
  120.     lpABPLogon->lpTDatRoot = NULL;
  121.     lpABPLogon->lpTDatOO = NULL;
  122.     /*
  123.      *  Register my status row...
  124.      */
  125.     rgSPVStat[0].ulPropTag = PR_DISPLAY_NAME_A;
  126.     rgSPVStat[0].Value.lpszA = lpszSABFile;
  127.     rgSPVStat[1].ulPropTag = PR_RESOURCE_METHODS;
  128.     rgSPVStat[1].Value.l = 0;   
  129.     rgSPVStat[2].ulPropTag = PR_RESOURCE_FLAGS;
  130.     rgSPVStat[2].Value.l = 0;
  131.     rgSPVStat[3].ulPropTag = PR_STATUS_CODE;
  132.     rgSPVStat[3].Value.l = STATUS_AVAILABLE;
  133.     rgSPVStat[4].ulPropTag = PR_STATUS_STRING;
  134.     rgSPVStat[4].Value.lpszA = "Available";
  135.     rgSPVStat[5].ulPropTag = PR_PROVIDER_DISPLAY;
  136.     rgSPVStat[5].Value.lpszA = "Sample Address Book Provider";
  137.     /*
  138.      *  Set the Status Row for this provider,
  139.      *  but do not allow an error from setting the
  140.      *  status row to cause failure to Logon.
  141.      */
  142.     (void)lpMAPISup->lpVtbl->ModifyStatusRow(lpMAPISup,
  143.         sizeof(rgSPVStat) / sizeof(SPropValue), rgSPVStat, 0);
  144.     /*
  145.      *  AddRef the support object, because we're keeping
  146.      *  a pointer to it in our Logon object.
  147.      */
  148.     lpMAPISup->lpVtbl->AddRef(lpMAPISup);
  149.     /*
  150.      *  AddRef our parent ABInit object
  151.      */
  152.     lpABP->lpVtbl->AddRef(lpABP);
  153.     InitializeCriticalSection(&lpABPLogon->cs);
  154.     
  155.     *lppABLogon = (LPABLOGON) lpABPLogon;
  156. out:
  157.     DebugTraceResult(HrNewABPLogon, hResult);
  158.     return hResult;
  159. }   
  160. /*************************************************************************
  161.  *
  162.  -  ABPLOGON_QueryInterface
  163.  -
  164.  */
  165. STDMETHODIMP
  166. ABPLOGON_QueryInterface(LPABPLOGON lpABPLogon, REFIID lpiid,
  167.     LPVOID * ppvObj)
  168. {
  169.     
  170.     Validate_IUnknown_QueryInterface(lpABPLogon, lpiid, ppvObj);
  171.     /*  See if the requested interface is one of ours */
  172.     if (memcmp(lpiid, &IID_IUnknown, sizeof(IID)) &&
  173.         memcmp(lpiid, &IID_IABLogon, sizeof(IID)))
  174.     {
  175.         *ppvObj = NULL;         /* OLE requires zeroing [out] parameter on error */
  176.         DebugTraceSc(ABPLOGON_QueryInterface, E_NOINTERFACE);
  177.         return ResultFromScode(E_NOINTERFACE);
  178.     }
  179.     /*  We'll do this one. Bump the usage count and return a new pointer. */
  180.     EnterCriticalSection(&lpABPLogon->cs);
  181.     ++lpABPLogon->lcInit;
  182.     LeaveCriticalSection(&lpABPLogon->cs);
  183.     
  184.     *ppvObj = lpABPLogon;
  185.     return hrSuccess;
  186. }
  187. /*
  188.  *  Use ROOTs AddRef
  189.  */
  190. /*************************************************************************
  191.  *
  192.  -  ABPLOGON_Release
  193.  -
  194.  */
  195. STDMETHODIMP_(ULONG)
  196. ABPLOGON_Release(LPABPLOGON lpABPLogon)
  197. {
  198.     LONG lcInit;
  199.     EnterCriticalSection(&lpABPLogon->cs);
  200.     lcInit = --lpABPLogon->lcInit;
  201.     LeaveCriticalSection(&lpABPLogon->cs);
  202.     if (lcInit == 0)
  203.     {
  204.         /*
  205.          *  Free up the file
  206.          */
  207.         lpABPLogon->lpFreeBuff(lpABPLogon->lpszFileName);
  208.         /*
  209.          *  Release the Hierarchy Table Data
  210.          */
  211.         if (lpABPLogon->lpTDatRoot)
  212.             lpABPLogon->lpTDatRoot->lpVtbl->Release(lpABPLogon->lpTDatRoot);
  213.         /*
  214.          *  Release the One-Off Table Data
  215.          */
  216.         if (lpABPLogon->lpTDatOO)
  217.             lpABPLogon->lpTDatOO->lpVtbl->Release(lpABPLogon->lpTDatOO);
  218.         /*
  219.          *  No longer need to be holding on to our parent
  220.          */
  221.         lpABPLogon->lpABP->lpVtbl->Release(lpABPLogon->lpABP);
  222.     
  223.         /*
  224.          *  Release the support object last.
  225.          */
  226.         lpABPLogon->lpMapiSup->lpVtbl->Release(lpABPLogon->lpMapiSup);
  227.         DeleteCriticalSection(&lpABPLogon->cs);
  228.         lpABPLogon->lpVtbl = NULL;
  229.         lpABPLogon->lpFreeBuff(lpABPLogon);
  230.         return (0);
  231.     }
  232.     return lcInit;
  233. }
  234. /*************************************************************************
  235.  *
  236.  -  ABPLOGON_Logoff
  237.  -
  238.  *  Logoff from this logon object.  Clean up any resources/objects that
  239.  *  our logon object has accumulated.
  240.  *
  241.  *
  242.  */
  243. STDMETHODIMP
  244. ABPLOGON_Logoff(LPABPLOGON lpABPLogon, ULONG ulFlags)
  245. {
  246.     /*
  247.      *  Remove this logon object from the list of known
  248.      *  logon objects associated with this initialization
  249.      *  of this provider.
  250.      */
  251.     (void) RemoveLogonObject(lpABPLogon->lpABP, lpABPLogon, lpABPLogon->lpFreeBuff);
  252.     return hrSuccess;
  253. }
  254. /*************************************************************************
  255.  *
  256.  -  ABPLOGON_OpenEntry
  257.  -
  258.  *  Creates an object with (at least) the IMAPIProp interface from an
  259.  *  entryID.
  260.  *
  261.  *  There are four valid types of entryIDs handled:
  262.  *
  263.  *    NULL          <- return back the root container object
  264.  *    DIR_ENTRYID   <- return back the directory container object
  265.  *    USR_ENTRYID   <- return back the MAILUSER object
  266.  *    OOUSR_ENTRYID <- return back the OneOff MAILUSER object
  267.  *
  268.  *  Note:  This call is reused for all other internal objects that support OpenEntry().
  269.  *    Those other calls *must* check their parameters before calling this method.
  270.  *    The only other way this method is called is via MAPI which does parameter checking
  271.  *    for us.  The most we'll do here is assert our parameters.
  272.  */
  273. STDMETHODIMP
  274. ABPLOGON_OpenEntry(LPABPLOGON lpABPLogon,
  275.     ULONG cbEntryID,
  276.     LPENTRYID lpEntryID,
  277.     LPCIID lpInterface,
  278.     ULONG ulFlags,
  279.     ULONG * lpulObjType,
  280.     LPUNKNOWN * lppUnk)
  281. {
  282.     LPDIR_ENTRYID lpSampEID = (LPDIR_ENTRYID) lpEntryID;
  283.     HRESULT hResult = hrSuccess;
  284.     /*
  285.      *  Check the EntryID
  286.      */
  287.     if (!cbEntryID)
  288.     {
  289.         LPABCONT lpABCont = NULL;
  290.         /*
  291.          *  Special case:  the root level object
  292.          */
  293.         NFAssertSz(!lpEntryID, "Non-NULL entry id passed with 0 cb to OpenEntry()n");
  294.         
  295.         /*  Make this new object  */
  296.         hResult = HrNewROOT((LPABCONT *) lppUnk,
  297.                             lpulObjType,
  298.                             (LPABLOGON) lpABPLogon,
  299.                             lpInterface,
  300.                             lpABPLogon->hLibrary,
  301.                             lpABPLogon->lpAllocBuff,
  302.                             lpABPLogon->lpAllocMore,
  303.                             lpABPLogon->lpFreeBuff,
  304.                             lpABPLogon->lpMalloc);
  305.         goto out;
  306.     }
  307.     /*
  308.      *  There's an entryID there, is it mine??
  309.      *  I need to check because I'm reusing this routine for
  310.      *  my Container->OpenEntry call, and I can't be sure the
  311.      *  client will always be well behaved.
  312.      *
  313.      *  When this routine is called from MAPI, this call is redundant.  But
  314.      *  because I'm reusing this routine, I gotta check.
  315.      */
  316.     /*  Compare MAPIUIDs  */
  317.     if (memcmp(&(((LPDIR_ENTRYID) lpEntryID)->muid), &muidABSample,
  318.             sizeof(MAPIUID)))
  319.     {
  320.         /*
  321.          *  Not mine!
  322.          */
  323.         hResult = ResultFromScode(MAPI_E_INVALID_ENTRYID);
  324.         goto out;
  325.     }
  326.     /*
  327.      *  What object does this correspond to??
  328.      */
  329.     /*  I've only got two types: containers and users  */
  330.     if (lpSampEID->ulType == SAMP_DIRECTORY)
  331.     {
  332.         LPABLOGON lpABPLogonT = NULL;
  333.         /* entry id must have the same verson number */
  334.         if (lpSampEID->ulVersion != SAMP_VERSION)
  335.         {
  336.             hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  337.             SetErrorIDS(lpABPLogon, hResult, IDS_OLD_EID);
  338.             goto out;
  339.         }
  340.         /*
  341.          *  find the correct logon object for this entryid
  342.          */
  343.         (void) FindLogonObject(lpABPLogon->lpABP, &lpSampEID->muidID, &lpABPLogonT);
  344.         /* did we find the corresponding logon object */
  345.         if (!lpABPLogonT)
  346.         {
  347.             hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  348.             goto out;
  349.         }
  350.         hResult = HrNewSampDirectory( (LPABCONT *) lppUnk,
  351.                                     lpulObjType,
  352.                                     (LPABLOGON) lpABPLogonT,
  353.                                     lpInterface,
  354.                                     lpABPLogon->hLibrary,
  355.                                     lpABPLogon->lpAllocBuff,
  356.                                     lpABPLogon->lpAllocMore,
  357.                                     lpABPLogon->lpFreeBuff,
  358.                                     lpABPLogon->lpMalloc);
  359.         goto out;
  360.     }
  361.     if (lpSampEID->ulType == SAMP_USER)
  362.         if (cbEntryID == (ULONG) sizeof(USR_ENTRYID))
  363.         {
  364.             hResult = HrNewSampUser( (LPMAILUSER *) lppUnk,
  365.                                     lpulObjType,
  366.                                     cbEntryID,
  367.                                     lpEntryID,
  368.                                     (LPABLOGON) lpABPLogon,
  369.                                     lpInterface,
  370.                                     lpABPLogon->hLibrary,
  371.                                     lpABPLogon->lpAllocBuff,
  372.                                     lpABPLogon->lpAllocMore,
  373.                                     lpABPLogon->lpFreeBuff,
  374.                                     lpABPLogon->lpMalloc);
  375.             goto out;
  376.         }
  377.     if (lpSampEID->ulType == SAMP_OOUSER)
  378.         if (cbEntryID == (ULONG) sizeof(OOUSR_ENTRYID))
  379.         {
  380.             hResult = HrNewSampOOUser( (LPMAILUSER *) lppUnk,
  381.                                         lpulObjType,
  382.                                         cbEntryID,
  383.                                         lpEntryID,
  384.                                         (LPABLOGON) lpABPLogon,
  385.                                         lpInterface,
  386.                                         lpABPLogon->hLibrary,
  387.                                         lpABPLogon->lpAllocBuff,
  388.                                         lpABPLogon->lpAllocMore,
  389.                                         lpABPLogon->lpFreeBuff,
  390.                                         lpABPLogon->lpMalloc);
  391.             goto out;
  392.         }
  393.     hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  394. out:
  395.     DebugTraceResult(ABPLOGON_OpenEntry, hResult);
  396.     return hResult;
  397. }
  398. /*************************************************************************
  399.  *
  400.  -  ABPLOGON_CompareEntryIDs
  401.  -
  402.  *  If the two entryids are mine and they're of the same type, then
  403.  *  just do a binary comparison to see if they're equal.
  404.  *
  405.  */
  406. STDMETHODIMP
  407. ABPLOGON_CompareEntryIDs(LPABPLOGON lpABPLogon,
  408.     ULONG cbEntryID1,
  409.     LPENTRYID lpEntryID1,
  410.     ULONG cbEntryID2,
  411.     LPENTRYID lpEntryID2,
  412.     ULONG ulFlags,
  413.     ULONG * lpulResult)
  414. {
  415.     LPDIR_ENTRYID lpSampEID1 = (LPDIR_ENTRYID) lpEntryID1;
  416.     LPDIR_ENTRYID lpSampEID2 = (LPDIR_ENTRYID) lpEntryID2;
  417.     HRESULT hResult = hrSuccess;
  418.     /*
  419.      *  Check to see if their MUID is mine
  420.      */
  421.     if (memcmp(&(lpSampEID1->muid), &muidABSample, sizeof(MAPIUID)) ||
  422.         memcmp(&(lpSampEID2->muid), &muidABSample, sizeof(MAPIUID)))
  423.     {
  424.         /*
  425.          *  No recognition of these entryids.
  426.          */
  427.         *lpulResult = (ULONG) FALSE;
  428.         hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  429.         goto out;
  430.     }
  431.     /*
  432.      *  See if the type of entryids are the same
  433.      */
  434.     if (lpSampEID1->ulType != lpSampEID2->ulType)
  435.     {
  436.         /*
  437.          *  They're not, so they don't match
  438.          */
  439.         *lpulResult = (ULONG) FALSE;
  440.         goto out;
  441.     }
  442.     /*
  443.      *  See if the entryids are the same size.  They'd better be
  444.      *  if they're the same type.
  445.      */
  446.     if (cbEntryID1 != cbEntryID2)
  447.     {
  448.         /*
  449.          *  They're not?!?  Then I don't know these...
  450.          */
  451.         *lpulResult = (ULONG) FALSE;
  452.         hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  453.         goto out;
  454.     }
  455.     /*
  456.      *  Check for Directory entryids
  457.      */
  458.     if (lpSampEID1->ulType == SAMP_DIRECTORY)
  459.     {
  460.         /*
  461.          *  Ok, I'm dealing with directory entryids
  462.          */
  463.         /*
  464.          *  Better make sure it's the right size
  465.          */
  466.         if (cbEntryID1 != sizeof(DIR_ENTRYID))
  467.         {
  468.             /*
  469.              *  This doesn't make sense.  I don't recognize this entryid.
  470.              */
  471.             *lpulResult = (ULONG) FALSE;
  472.             hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  473.             goto out;
  474.         }
  475.         /*
  476.          *  At this point it's just a memcmp
  477.          */
  478.         if (memcmp(lpSampEID1, lpSampEID2, sizeof(DIR_ENTRYID)))
  479.         {
  480.             /*
  481.              *  They're not equal
  482.              */
  483.             *lpulResult = (ULONG) FALSE;
  484.             goto out;
  485.         }
  486.         /*
  487.          *  They must be the same
  488.          */
  489.         *lpulResult = (ULONG) TRUE;
  490.         goto out;
  491.     }
  492.     if (lpSampEID1->ulType == SAMP_USER)
  493.     {
  494.         /*
  495.          *  Ok, I'm dealing with user entryids
  496.          */
  497.         /*
  498.          *  Better make sure it's the right size
  499.          */
  500.         if (cbEntryID1 != sizeof(USR_ENTRYID))
  501.         {
  502.             /*
  503.              *  This doesn't make sense.  I don't recognize this entryid.
  504.              */
  505.             *lpulResult = (ULONG) FALSE;
  506.             hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  507.             goto out;
  508.         }
  509.         /*
  510.          *  At this point it's just a memcmp
  511.          */
  512.         if (memcmp(lpSampEID1, lpSampEID2, sizeof(USR_ENTRYID)))
  513.         {
  514.             /*
  515.              *  They're not equal
  516.              */
  517.             *lpulResult = (ULONG) FALSE;
  518.             goto out;
  519.         }
  520.         /*
  521.          *  They must be the same
  522.          */
  523.         *lpulResult = (ULONG) TRUE;
  524.         goto out;
  525.     }
  526.     if (lpSampEID1->ulType == SAMP_OOUSER)
  527.     {
  528.         /*
  529.          *  Ok, I'm dealing with oneoff user entryids
  530.          */
  531.         /*
  532.          *  Better make sure it's the right size
  533.          */
  534.         if (cbEntryID1 != sizeof(OOUSR_ENTRYID))
  535.         {
  536.             /*
  537.              *  This doesn't make sense.  I don't recognize this entryid.
  538.              */
  539.             *lpulResult = (ULONG) FALSE;
  540.             hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  541.             goto out;
  542.         }
  543.         /*
  544.          *  At this point it's just a memcmp
  545.          */
  546.         if (memcmp(lpSampEID1, lpSampEID2, sizeof(OOUSR_ENTRYID)))
  547.         {
  548.             /*
  549.              *  They're not equal
  550.              */
  551.             *lpulResult = (ULONG) FALSE;
  552.             goto out;
  553.         }
  554.         /*
  555.          *  They must be the same
  556.          */
  557.         *lpulResult = (ULONG) TRUE;
  558.         goto out;
  559.     }
  560.     /*
  561.      *  It's no entryid I know of
  562.      */
  563.     *lpulResult = (ULONG) FALSE;
  564.     hResult = ResultFromScode(MAPI_E_UNKNOWN_ENTRYID);
  565. out:
  566.     DebugTraceResult(ABPLOGON_CompareEntryIDs, hResult);
  567.     return hResult;
  568. }
  569. /*************************************************************************
  570.  *
  571.  -  ABPLOGON_OpenStatusEntry
  572.  -
  573.  *
  574.  *
  575.  *
  576.  */
  577. STDMETHODIMP
  578. ABPLOGON_OpenStatusEntry(LPABPLOGON lpABPLogon,
  579.     LPCIID lpIID,
  580.     ULONG ulFlags,
  581.     ULONG FAR * lpulObjType,
  582.     LPMAPISTATUS FAR * lppEntry)
  583. {
  584.     HRESULT hr;
  585.     /*
  586.      *  Validate Parameters
  587.      */
  588.     Validate_IABLogon_OpenStatusEntry(lpABPLogon, lpIID, ulFlags,
  589.                                         lpulObjType, lppEntry);
  590.     hr = HrNewStatusObject( lppEntry,
  591.                             lpulObjType,
  592.                             ulFlags,
  593.                             (LPABLOGON) lpABPLogon,
  594.                             lpIID,
  595.                             lpABPLogon->hLibrary,
  596.                             lpABPLogon->lpAllocBuff,
  597.                             lpABPLogon->lpAllocMore,
  598.                             lpABPLogon->lpFreeBuff,
  599.                             lpABPLogon->lpMalloc);
  600.     DebugTraceResult(ABPLOGON_OpenStatusEntry, hr);
  601.     return hr;
  602. }
  603. /*************************************************************************
  604.  *
  605.  -  ABPLOGON_OpenTemplateID
  606.  -
  607.  *
  608.  *
  609.  *
  610.  */
  611. STDMETHODIMP
  612. ABPLOGON_OpenTemplateID(LPABPLOGON lpABPLogon,
  613.     ULONG cbTemplateId,
  614.     LPENTRYID lpTemplateId,
  615.     ULONG ulTemplateFlags,
  616.     LPMAPIPROP lpMAPIPropData,
  617.     LPCIID lpInterface,
  618.     LPMAPIPROP * lppMAPIPropNew,
  619.     LPMAPIPROP lpMAPIPropSibling)
  620. {
  621.     HRESULT hResult;
  622.     /*
  623.      *  Validate Parameters
  624.      */
  625.     Validate_IABLogon_OpenTemplateID(lpABPLogon, cbTemplateId, lpTemplateId,
  626.                             ulTemplateFlags, lpMAPIPropData, lpInterface,
  627.                             lppMAPIPropNew, lpMAPIPropSibling);
  628.     /* //$ need stronger checking here... */
  629.     /* entryid better be right size */
  630.     if (cbTemplateId != sizeof(OOUSR_ENTRYID) && cbTemplateId != sizeof(USR_ENTRYID))
  631.     {
  632.         hResult = ResultFromScode(MAPI_E_INVALID_ENTRYID);
  633.         goto out;
  634.     }
  635.     /*  is it my entry id compare MAPIUIDs  */
  636.     if (memcmp(&(((LPUSR_ENTRYID) lpTemplateId)->muid), &muidABSample,
  637.             sizeof(MAPIUID)))
  638.     {
  639.         hResult = ResultFromScode( MAPI_E_INVALID_ENTRYID );
  640.         goto out;
  641.     }
  642.     /* better be a oneoff user entryid or a user entry id */
  643.     if (((LPUSR_ENTRYID) lpTemplateId)->ulType == SAMP_OOUSER)
  644.     {
  645.         hResult = HrNewOOTID(   lppMAPIPropNew,
  646.                                 cbTemplateId,
  647.                                 lpTemplateId,
  648.                                 ulTemplateFlags,
  649.                                 lpMAPIPropData,
  650.                                 (LPABLOGON) lpABPLogon,
  651.                                 lpInterface,
  652.                                 lpABPLogon->hLibrary,
  653.                                 lpABPLogon->lpAllocBuff,
  654.                                 lpABPLogon->lpAllocMore,
  655.                                 lpABPLogon->lpFreeBuff,
  656.                                 lpABPLogon->lpMalloc);
  657.             
  658.     }
  659.     else if (((LPUSR_ENTRYID) lpTemplateId)->ulType == SAMP_USER)
  660.     {
  661.         hResult = HrNewTID( lppMAPIPropNew,
  662.                             cbTemplateId,
  663.                             lpTemplateId,
  664.                             ulTemplateFlags,
  665.                             lpMAPIPropData,
  666.                             (LPABLOGON) lpABPLogon,
  667.                             lpInterface,
  668.                             lpABPLogon->hLibrary,
  669.                             lpABPLogon->lpAllocBuff,
  670.                             lpABPLogon->lpAllocMore,
  671.                             lpABPLogon->lpFreeBuff,
  672.                             lpABPLogon->lpMalloc);
  673.     }
  674.     else
  675.     {
  676.         hResult = MakeResult(MAPI_E_INVALID_ENTRYID);
  677.     }
  678. out:
  679.     DebugTraceResult(ABPLOGON_OpenTemplateID, hResult);
  680.     return hResult;
  681. }
  682. /*
  683.  -  ABPLOGON_GetOneOffTable
  684.  -
  685.  *  Returns the lists of one-offs that this providers can support creation of.
  686.  *  This list is added to the entries gathered from all the other AB logon objects
  687.  *  and exposed to the user as the list of things that can be created on a 
  688.  *  message.  Also this total list is available to other providers through the
  689.  *  support method GetOneOffTable().
  690.  *  
  691.  *  Note:  There's a bug here that if there are more than one Sample Address Books
  692.  *  installed on a particular profile, then there will be multiple entries in the
  693.  *  one-off table from this provider.  This can be changed to only have one one-off
  694.  *  entry, no matter how many SABs are configured in a profile, if the one-off table
  695.  *  was associated with the ABInit object.
  696.  */
  697. /*
  698.  *  Column set for the oneoff table
  699.  */
  700. enum {  ivalootPR_DISPLAY_NAME_A = 0,
  701.         ivalootPR_ENTRYID,
  702.         ivalootPR_DEPTH,
  703.         ivalootPR_SELECTABLE,
  704.         ivalootPR_ADDRTYPE_A,
  705.         ivalootPR_DISPLAY_TYPE,
  706.         ivalootPR_INSTANCE_KEY,
  707.         ivalootMax };
  708. static const SizedSPropTagArray(ivalootMax, tagaColSetOOTable) =
  709. {
  710.     ivalootMax,
  711.     {
  712.         PR_DISPLAY_NAME_A,
  713.         PR_ENTRYID,
  714.         PR_DEPTH,
  715.         PR_SELECTABLE,
  716.         PR_ADDRTYPE_A,
  717.         PR_DISPLAY_TYPE,
  718.         PR_INSTANCE_KEY
  719.     }
  720. };
  721. STDMETHODIMP
  722. ABPLOGON_GetOneOffTable(
  723.     LPABPLOGON lpABPLogon,
  724.     ULONG ulFlags,
  725.     LPMAPITABLE * lppTable)
  726. {
  727.     SCODE sc;
  728.     HRESULT hResult;
  729.     SRow sRow;
  730.     SPropValue rgsPropValue[ivalootMax];
  731.     ULONG ulInstanceKey = 1;
  732.     OOUSR_ENTRYID EntryID;
  733.     /*
  734.      *  Validate Parameters
  735.      */
  736.      
  737.     
  738.     Validate_IABLogon_GetOneOffTable(lpABPLogon, ulFlags, lppTable);
  739.     if ( ulFlags & MAPI_UNICODE )
  740.     {
  741.         DebugTraceArg( APBLOGON_GetOneOffTable, "UNICODE not supported" );
  742.         return ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  743.     }
  744.     
  745.     
  746.     EnterCriticalSection(&lpABPLogon->cs);
  747.     
  748.     /*
  749.      * If there's not one already associated with this logon object,
  750.      * then create one.
  751.      */
  752.     if (!lpABPLogon->lpTDatOO)
  753.     {
  754.         /* Create a Table data object */
  755.         sc = CreateTable(
  756.             (LPIID) &IID_IMAPITableData,
  757.             lpABPLogon->lpAllocBuff,
  758.             lpABPLogon->lpAllocMore,
  759.             lpABPLogon->lpFreeBuff,
  760.             lpABPLogon->lpMalloc,
  761.             0,
  762.             PR_DISPLAY_NAME_A,
  763.             (LPSPropTagArray) &tagaColSetOOTable,
  764.             &(lpABPLogon->lpTDatOO));
  765.         if (FAILED(sc))
  766.         {
  767.             hResult = ResultFromScode(sc);
  768.             goto out;
  769.         }
  770.         /* Constants*/
  771.         sRow.cValues = ivalootMax;
  772.         sRow.lpProps = rgsPropValue;
  773.         /* The Display Name */
  774.         rgsPropValue[ivalootPR_DISPLAY_NAME_A].ulPropTag = PR_DISPLAY_NAME_A;
  775.         rgsPropValue[ivalootPR_DISPLAY_NAME_A].Value.lpszA = "Sample Address Book Recipient";
  776.         /* the Entry ID*/
  777.         ZeroMemory(&EntryID, sizeof(OOUSR_ENTRYID));
  778.         EntryID.muid = muidABSample;
  779.         EntryID.ulVersion = SAMP_VERSION;
  780.         EntryID.ulType = SAMP_OOUSER;
  781.         rgsPropValue[ivalootPR_ENTRYID].ulPropTag = PR_ENTRYID;
  782.         rgsPropValue[ivalootPR_ENTRYID].Value.bin.cb = sizeof(OOUSR_ENTRYID);
  783.         rgsPropValue[ivalootPR_ENTRYID].Value.bin.lpb = (LPVOID) &EntryID;
  784.         /* the depth property */
  785.         rgsPropValue[ivalootPR_DEPTH].ulPropTag = PR_DEPTH;
  786.         rgsPropValue[ivalootPR_DEPTH].Value.l = 0;
  787.         /* the selectable property */
  788.         rgsPropValue[ivalootPR_SELECTABLE].ulPropTag = PR_SELECTABLE;
  789.         rgsPropValue[ivalootPR_SELECTABLE].Value.b = TRUE;
  790.         /*
  791.          *  The address type that would be generated by an entry
  792.          *  created from this template
  793.          */
  794.         rgsPropValue[ivalootPR_ADDRTYPE_A].ulPropTag = PR_ADDRTYPE;
  795.         rgsPropValue[ivalootPR_ADDRTYPE_A].Value.lpszA = lpszEMT;
  796.         /*
  797.          *  The display type associated with a recipient built with this template
  798.          */
  799.         rgsPropValue[ivalootPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  800.         rgsPropValue[ivalootPR_DISPLAY_TYPE].Value.l = DT_MAILUSER;
  801.         /*
  802.          *  The instance key of this row in this one-off table.  Since there's only one
  803.          *  row in this one-off table, just default it to a value of 1.
  804.          */
  805.         rgsPropValue[ivalootPR_INSTANCE_KEY].ulPropTag = PR_INSTANCE_KEY;
  806.         rgsPropValue[ivalootPR_INSTANCE_KEY].Value.bin.cb = sizeof(ULONG);
  807.         rgsPropValue[ivalootPR_INSTANCE_KEY].Value.bin.lpb = (LPBYTE) &ulInstanceKey;
  808.         (void) lpABPLogon->lpTDatOO->lpVtbl->HrModifyRow(
  809.                             lpABPLogon->lpTDatOO,
  810.                             &sRow);
  811.     }
  812.     /*
  813.      *  Get a view to return to the caller
  814.      */
  815.     hResult = lpABPLogon->lpTDatOO->lpVtbl->HrGetView(
  816.         lpABPLogon->lpTDatOO,
  817.         NULL,
  818.         NULL,
  819.         0,
  820.         (LPMAPITABLE *) lppTable);
  821. out:
  822.     LeaveCriticalSection(&lpABPLogon->cs);
  823.     DebugTraceResult(ABPLogon_GetOneOffTable, hResult);
  824.     return hResult;
  825. }
  826. /*************************************************************************
  827.  *
  828.  -  ABPLOGON_Advise
  829.  -
  830.  *  NYI
  831.  *
  832.  *
  833.  */
  834. STDMETHODIMP
  835. ABPLOGON_Advise(LPABPLOGON lpABPLogon,
  836.     ULONG cbEntryID,
  837.     LPENTRYID lpEntryID,
  838.     ULONG ulEventMask,
  839.     LPMAPIADVISESINK lpAdviseSink,
  840.     ULONG FAR * lpulConnection)
  841. {
  842.     DebugTraceSc(ABPLOGON_Advise, MAPI_E_NO_SUPPORT);
  843.     return ResultFromScode(MAPI_E_NO_SUPPORT);
  844. }
  845. /*************************************************************************
  846.  *
  847.  -  ABPLOGON_Unadvise
  848.  -
  849.  *  NYI
  850.  *
  851.  *
  852.  */
  853. STDMETHODIMP
  854. ABPLOGON_Unadvise(LPABPLOGON lpABPLogon, ULONG ulConnection)
  855. {
  856.     DebugTraceSc(ABPLOGON_Unadvise, MAPI_E_NO_SUPPORT);
  857.     return ResultFromScode(MAPI_E_NO_SUPPORT);
  858. }
  859. /*************************************************************************
  860.  *
  861.  -  ABPLOGON_PrepareRecips
  862.  -
  863.  *
  864.  *
  865.  *
  866.  */
  867. STDMETHODIMP
  868. ABPLOGON_PrepareRecips(LPABPLOGON lpABPLogon,
  869.     ULONG ulFlags,
  870.     LPSPropTagArray lpPropTagArray,
  871.     LPADRLIST lpRecipList)
  872. {
  873.     HRESULT         hResult         = hrSuccess;
  874.     UINT            iRecip;
  875.     UINT            iProp;
  876.     ULONG           cValues;
  877.     LPSPropValue    lpspvUser       = NULL;
  878.     LPSPropValue    lpNewRecip      = NULL;
  879.     LPMAPIPROP      lpMAPIPropEntry = NULL;
  880.     SCODE           sc              = S_OK;
  881.     ULONG           ulObjType;
  882.     BOOL            fUselpspvUser;
  883.     /* loop through all the recipients */
  884.     
  885.     if (!lpPropTagArray)
  886.     {
  887.         /*
  888.          *  They only want us to update our entryID from ephemeral to
  889.          *  permanent.  Since ours are already permanent, we don't need to
  890.          *  do anything.
  891.          */
  892.         goto out;
  893.     }
  894.     for (iRecip = 0; iRecip < lpRecipList->cEntries; iRecip++)
  895.     {
  896.         LPUSR_ENTRYID   lpEntryID   = NULL;
  897.         ULONG           cbEntryID;
  898.         LPSPropValue    lpPropVal       = NULL;
  899.         LPSPropValue    rgpropvalsRecip = lpRecipList->aEntries[iRecip].rgPropVals;
  900.         ULONG           cPropsRecip     = lpRecipList->aEntries[iRecip].cValues;
  901.         /* For each recipient, find its entryid */
  902.         
  903.         lpPropVal = PpropFindProp( rgpropvalsRecip, cPropsRecip, PR_ENTRYID );
  904.         
  905.         if ( lpPropVal )
  906.         {
  907.             lpEntryID = (LPUSR_ENTRYID)lpPropVal->Value.bin.lpb;
  908.             cbEntryID = lpPropVal->Value.bin.cb;
  909.         }
  910.         else
  911.             continue;
  912.                 
  913.         /* Is it one of ours? */
  914.          
  915.         if ( cbEntryID < CbNewENTRYID(0)
  916.             || IsBadReadPtr( (LPVOID) lpEntryID, (UINT) cbEntryID ) )
  917.         {
  918.             continue;   /* no */
  919.         }
  920.          
  921.         if ( memcmp( &(lpEntryID->muid), &muidABSample, sizeof(MAPIUID) ) )
  922.             continue;   /* no */
  923.         /* Try and open it. */
  924.          
  925.         hResult = HrNewSampUser((LPMAILUSER *)&lpMAPIPropEntry,
  926.                                 &ulObjType, 
  927.                                 cbEntryID, 
  928.                                 (LPENTRYID) lpEntryID, 
  929.                                 (LPABLOGON) lpABPLogon,
  930.                                 NULL, 
  931.                                 lpABPLogon->hLibrary,
  932.                                 lpABPLogon->lpAllocBuff,
  933.                                 lpABPLogon->lpAllocMore,
  934.                                 lpABPLogon->lpFreeBuff,
  935.                                 lpABPLogon->lpMalloc );
  936.         if ( HR_FAILED(hResult) )
  937.         {
  938.              /* Couldn't open it...; Ignore it and keep looking */
  939.             hResult = hrSuccess;
  940.             DebugTrace( "ABPLOGON_PrepareRecips sees a bad user entry IDn" );
  941.             continue;
  942.         }
  943.         /* Get the properties requested */
  944.         hResult = lpMAPIPropEntry->lpVtbl->GetProps( lpMAPIPropEntry, 
  945.                 lpPropTagArray, 0, /* ansi */
  946.                 &cValues, &lpspvUser );
  947.         /* No longer need lpMAPIPropEntry  */
  948.         
  949.         lpMAPIPropEntry->lpVtbl->Release(lpMAPIPropEntry);
  950.         lpMAPIPropEntry = NULL;
  951.         if (HR_FAILED(hResult))
  952.         {
  953.             /* Failed getting properties. Cleanup and ignore this entry */
  954.             hResult = hrSuccess;
  955.             continue;
  956.         }
  957.         
  958.         hResult = hrSuccess;
  959.         Assert(cValues == lpPropTagArray->cValues);
  960.         /*
  961.          *  This is the hard part.
  962.          *  Merge the two property sets: lpspvUser and lpsPropVal.  Note that
  963.          *  both of these sets may have the same property - chances are they do.
  964.          *  for these conflicts, lpspvUser should be the one we get the property
  965.          *  from.
  966.          *
  967.          *  Guess how big the resultant SPropValue array is, and allocate one of that
  968.          *  size.
  969.          */
  970.         sc = lpABPLogon->lpAllocBuff( (cValues + cPropsRecip) * sizeof( SPropValue ), 
  971.                 &lpNewRecip);
  972.         if (FAILED(sc))
  973.         {
  974.             /*
  975.              *  Ok, to fail the call here.  If we're running into out of memory conditions
  976.              *  we're all in trouble.
  977.              */
  978.             hResult = ResultFromScode( sc );
  979.             goto err;
  980.         }
  981.         /*
  982.          *  Copy lpspvUser properties over to lpNewRecip
  983.          *  Check each property in lpsvUser to ensure that it isn't PT_ERROR, if so
  984.          *  find the propval in rgpropvalsRecip ( the [in] recip prop val array ), 
  985.          *  if it exists and use that property.
  986.          */
  987.         
  988.         for (iProp = 0; iProp < cValues; iProp++)
  989.         {
  990.             fUselpspvUser = TRUE;
  991.             
  992.             if ( PROP_TYPE( lpspvUser[iProp].ulPropTag ) == PT_ERROR )
  993.             {
  994.                 lpPropVal = PpropFindProp( rgpropvalsRecip, cPropsRecip,
  995.                          lpPropTagArray->aulPropTag[iProp] );
  996.                          
  997.                 if ( lpPropVal )
  998.                 {
  999.                     sc = PropCopyMore(  lpNewRecip + iProp, lpPropVal,
  1000.                             lpABPLogon->lpAllocMore, lpNewRecip );
  1001.                             
  1002.                     fUselpspvUser = FALSE;      
  1003.                 }
  1004.             }
  1005.                 
  1006.             if ( fUselpspvUser )
  1007.             {
  1008.                 sc = PropCopyMore(  lpNewRecip + iProp, lpspvUser + iProp,
  1009.                         lpABPLogon->lpAllocMore, lpNewRecip );
  1010.             }
  1011.             
  1012.             if (FAILED(sc))
  1013.             {
  1014.                 if (sc == MAPI_E_NOT_ENOUGH_MEMORY)
  1015.                 {
  1016.                     hResult = MakeResult(sc);
  1017.                     goto err;
  1018.                 }
  1019.                 
  1020.                 /*
  1021.                  *   Otherwise we've run into something wierd in the prop value array
  1022.                  *   like PT_UNSPECIFIED, PT_NULL, or PT_OBJECT.  In which case continue
  1023.                  *   on.
  1024.                  */
  1025.             }
  1026.         }
  1027.         
  1028.         /* Done with lpspvUser */
  1029.         
  1030.         lpABPLogon->lpFreeBuff( lpspvUser );
  1031.         lpspvUser = NULL;
  1032.         /*
  1033.          *  Copy those properties that aren't already in lpNewRecip
  1034.          *  from rgpropvalsRecip.  Don't copy over the PT_ERROR prop vals
  1035.          */
  1036.         for ( iProp = 0; iProp < cPropsRecip; iProp++ )
  1037.         {
  1038.         
  1039.             if ( PpropFindProp( lpNewRecip, cValues, rgpropvalsRecip[iProp].ulPropTag ) 
  1040.                 || PROP_TYPE( rgpropvalsRecip[iProp].ulPropTag ) == PT_ERROR )
  1041.                 continue;
  1042.             sc = PropCopyMore(  lpNewRecip + cValues, rgpropvalsRecip + iProp,
  1043.                     lpABPLogon->lpAllocMore, lpNewRecip );
  1044.             if ( FAILED( sc ) )
  1045.             {
  1046.                 if (sc == MAPI_E_NOT_ENOUGH_MEMORY)
  1047.                 {
  1048.                      
  1049.                     hResult = ResultFromScode( sc );
  1050.                     goto err;
  1051.                 }
  1052.                 
  1053.                 /*
  1054.                  *  Otherwise we've run into something wierd in the prop value array
  1055.                  *  like PT_UNSPECIFIED, PT_NULL, or PT_OBJECT.  In which case continue
  1056.                  *  on.
  1057.                  */
  1058.             }
  1059.             
  1060.             cValues++;
  1061.         }
  1062.         /*
  1063.          *  Replace the AdrEntry in the AdrList with this new lpNewRecip.  And
  1064.          *  don't forget the cValues!
  1065.          */
  1066.         lpRecipList->aEntries[iRecip].rgPropVals = lpNewRecip;
  1067.         lpRecipList->aEntries[iRecip].cValues    = cValues;
  1068.         /* Finally, free up the old AdrEntry. */
  1069.         lpABPLogon->lpFreeBuff( rgpropvalsRecip );
  1070.     }
  1071. out:
  1072.     DebugTraceResult( ABPLOGON_PrepareRecips, hResult );
  1073.     return hResult;
  1074. err:
  1075.     lpABPLogon->lpFreeBuff( lpspvUser );
  1076.     goto out;
  1077. }
  1078. /*
  1079.  *  LpMuidFromLogon -
  1080.  *    Returns the particular ABPLOGON object's unique identifier.
  1081.  *
  1082.  */  
  1083. LPMAPIUID
  1084. LpMuidFromLogon(LPABLOGON lpABLogon)
  1085. {
  1086.     LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1087.     AssertSz(!IsBadReadPtr(lpABPLogon, sizeof(ABPLOGON)), "Bad logon object!n");
  1088.     return (&(lpABPLogon->muidID));
  1089. }
  1090. /*
  1091.  *  HrLpszGetCurrentFileName -
  1092.  *    Returns a copy of the current .SAB file pointed to by this logon object.
  1093.  *
  1094.  */
  1095. HRESULT
  1096. HrLpszGetCurrentFileName(LPABLOGON lpABLogon, LPSTR * lppszFileName)
  1097. {
  1098.     LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1099.     SCODE sc;
  1100.     HRESULT hResult = hrSuccess;
  1101.     AssertSz(!IsBadReadPtr(lpABPLogon, sizeof(ABPLOGON)), "SAB: Bad logon object!n");
  1102.     AssertSz(!IsBadWritePtr(lppszFileName, sizeof(LPSTR)), "SAB: Bad dest string!n");
  1103.     EnterCriticalSection(&lpABPLogon->cs);
  1104.     
  1105.     sc = lpABPLogon->lpAllocBuff (lstrlenA(lpABPLogon->lpszFileName)+1, lppszFileName);
  1106.     if (FAILED(sc))
  1107.     {
  1108.         hResult = ResultFromScode(sc);
  1109.         goto ret;
  1110.     }
  1111.     lstrcpyA( *lppszFileName, lpABPLogon->lpszFileName);
  1112.     
  1113. ret:
  1114.     LeaveCriticalSection(&lpABPLogon->cs);
  1115.     DebugTraceResult(HrLpszGetCurrentFileName, hResult);
  1116.     return hResult;
  1117. }
  1118. /*
  1119.  *  HrReplaceCurrentFileName -
  1120.  *    Replaces the current file name associated with this logon object and tries
  1121.  *    to save it all away in the profile.
  1122.  */
  1123. HRESULT
  1124. HrReplaceCurrentFileName(LPABLOGON lpABLogon, LPSTR lpszNewFile)
  1125. {
  1126.     LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1127.     HRESULT hResult = hrSuccess;
  1128.     LPPROFSECT lpProfSect = NULL;
  1129.     LPSTR lpstrT;
  1130.     SCODE sc;
  1131.     SPropValue rgspv[1];
  1132.     AssertSz(!IsBadReadPtr(lpABPLogon, sizeof(ABPLOGON)), "Bad logon object!n");
  1133.     
  1134.     EnterCriticalSection(&lpABPLogon->cs);
  1135.     /*
  1136.      *  SAB file name has changed have to update profile and objects
  1137.      */
  1138.     if (lstrcmpA(lpszNewFile, lpABPLogon->lpszFileName))
  1139.     {
  1140.         /*
  1141.          *  Open the private profile section...
  1142.          */
  1143.         hResult = lpABPLogon->lpMapiSup->lpVtbl->OpenProfileSection(
  1144.             lpABPLogon->lpMapiSup,
  1145.             NULL,
  1146.             MAPI_MODIFY,
  1147.             &lpProfSect);
  1148.         if (HR_FAILED(hResult))
  1149.         {
  1150.             /*
  1151.              *  Shouldn't get here, but in case I do, just...
  1152.              */
  1153.             goto ret;
  1154.         }
  1155.         /*
  1156.          *  Save the new name back into the profile
  1157.          */
  1158.         rgspv[0].ulPropTag = PR_SAB_FILE;
  1159.         rgspv[0].Value.lpszA = lpszNewFile;
  1160.         /*
  1161.          *  Don't care if I can save it in the profile or not.
  1162.          *  Saving it's a nice to have, but absolutely required
  1163.          *  for operation of this particular provider.
  1164.          */
  1165.         (void) lpProfSect->lpVtbl->SetProps(
  1166.             lpProfSect,
  1167.             1,
  1168.             rgspv,
  1169.             NULL);
  1170.         lpProfSect->lpVtbl->Release(lpProfSect);
  1171.         /*
  1172.          *  Allocate and copy this new one
  1173.          */
  1174.         sc = lpABPLogon->lpAllocBuff (lstrlenA(lpszNewFile)+1, &lpstrT);
  1175.         if (FAILED(sc))
  1176.         {
  1177.             hResult = ResultFromScode(sc);
  1178.             goto ret;
  1179.         }
  1180.         lstrcpyA( lpstrT, lpszNewFile );
  1181.         /*
  1182.          *  Free up the old one...
  1183.          */
  1184.         lpABPLogon->lpFreeBuff(lpABPLogon->lpszFileName);
  1185.         /*
  1186.          *  Put in the new one.
  1187.          */
  1188.         lpABPLogon->lpszFileName = lpstrT;
  1189.         /*
  1190.          *  Update the hierarchy table
  1191.          */
  1192.         hResult = HrBuildRootHier((LPABLOGON)lpABPLogon, NULL);
  1193.     }
  1194. ret:
  1195.     LeaveCriticalSection(&lpABPLogon->cs);
  1196.     DebugTraceResult(HrReplaceCurrentFileName, hResult);
  1197.     return hResult;
  1198. }
  1199. /*
  1200.  *  GenerateContainerDN -
  1201.  *      Common code for generating the display name of the single
  1202.  *      container exposed from this logon object.
  1203.  */
  1204. void
  1205. GenerateContainerDN(LPABLOGON lpABLogon, LPSTR lpszName)
  1206. {
  1207.     LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1208.     LPSTR lpszFileName;
  1209.     int ich;
  1210.     AssertSz(!IsBadReadPtr(lpABPLogon, sizeof(ABPLOGON)), "Bad logon object!n");
  1211.     
  1212.     EnterCriticalSection(&lpABPLogon->cs);
  1213.     lpszFileName = lpABPLogon->lpszFileName;
  1214.     /* get the filename without the path */
  1215.     for (ich = lstrlenA(lpszFileName) - 1; ich >= 0; ich--)
  1216.     {
  1217.         if (lpszFileName[ich] == '\')
  1218.             break;
  1219.     }
  1220.     /* skip past the backslash */
  1221.     ich++;
  1222.     wsprintfA(lpszName, "SAB using %s", lpszFileName + ich);
  1223.     LeaveCriticalSection(&lpABPLogon->cs);
  1224. }
  1225. /*
  1226.  -  HrBuildRootHier
  1227.  -
  1228.  *
  1229.  *  Builds up the root hierarchy for the Sample Address Book.  
  1230.  *
  1231.  *
  1232.  */
  1233. enum {  ivalPR_DISPLAY_NAME_A = 0,
  1234.         ivalPR_ENTRYID,
  1235.         ivalPR_DEPTH,
  1236.         ivalPR_OBJECT_TYPE,
  1237.         ivalPR_DISPLAY_TYPE,
  1238.         ivalPR_CONTAINER_FLAGS,
  1239.         ivalPR_INSTANCE_KEY,
  1240.         ivalPR_AB_PROVIDER_ID,
  1241.         cvalMax };
  1242. static const SizedSPropTagArray(cvalMax, tagaRootColSet) =
  1243. {
  1244.     cvalMax,
  1245.     {
  1246.         PR_DISPLAY_NAME_A,
  1247.         PR_ENTRYID,
  1248.         PR_DEPTH,
  1249.         PR_OBJECT_TYPE,
  1250.         PR_DISPLAY_TYPE,
  1251.         PR_CONTAINER_FLAGS,
  1252.         PR_INSTANCE_KEY,
  1253.         PR_AB_PROVIDER_ID
  1254.     }
  1255. };
  1256. HRESULT
  1257. HrBuildRootHier(LPABLOGON lpABLogon, LPMAPITABLE * lppMAPITable)
  1258. {
  1259.     HRESULT hResult;
  1260.     SCODE sc;
  1261.     SRow sRow;
  1262.     SPropValue rgsPropValue[cvalMax];
  1263.     ULONG ulInstanceKey = 1;
  1264.     char szBuf[MAX_PATH];
  1265.     LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1266.     DIR_ENTRYID eidRoot =   {   {0, 0, 0, 0},
  1267.                                 MUIDABSAMPLE,
  1268.                                 SAMP_VERSION,
  1269.                                 SAMP_DIRECTORY };
  1270.     
  1271.     EnterCriticalSection(&lpABPLogon->cs);
  1272.     /*
  1273.      *  See if we have a TaD yet
  1274.      */
  1275.     if (!lpABPLogon->lpTDatRoot)
  1276.     {
  1277.         /* Create a Table Data object */
  1278.         if (sc = CreateTable((LPIID) &IID_IMAPITableData,
  1279.                     lpABPLogon->lpAllocBuff,
  1280.                     lpABPLogon->lpAllocMore,
  1281.                     lpABPLogon->lpFreeBuff,
  1282.                     lpABPLogon->lpMalloc,
  1283.                     0,
  1284.                     PR_ENTRYID,
  1285.                     (LPSPropTagArray) &tagaRootColSet,
  1286.                     &(lpABPLogon->lpTDatRoot)))
  1287.         {
  1288.             hResult = ResultFromScode(sc);
  1289.             goto out;
  1290.         }
  1291.     }
  1292.     /* Constants */
  1293.     sRow.cValues = cvalMax;
  1294.     sRow.lpProps = rgsPropValue;
  1295.     /* First, the Display Name stuff*/
  1296.     rgsPropValue[ivalPR_DISPLAY_NAME_A].ulPropTag   = PR_DISPLAY_NAME_A;
  1297.     GenerateContainerDN((LPABLOGON) lpABPLogon, szBuf);
  1298.     rgsPropValue[ivalPR_DISPLAY_NAME_A].Value.lpszA = szBuf;
  1299.     /*
  1300.      *  For each SAB logon object associated with it's init object,
  1301.      *  we have a unique MAPIUID.  It's the only thing that distinguishes
  1302.      *  one SAB entryid from another in the merged hierarchy table that
  1303.      *  MAPI generates.
  1304.      */
  1305.     rgsPropValue[ivalPR_ENTRYID].ulPropTag          = PR_ENTRYID;
  1306.     eidRoot.muidID = lpABPLogon->muidID;
  1307.     rgsPropValue[ivalPR_ENTRYID].Value.bin.cb       = sizeof(DIR_ENTRYID);
  1308.     rgsPropValue[ivalPR_ENTRYID].Value.bin.lpb      = (LPVOID) &eidRoot;
  1309.     rgsPropValue[ivalPR_DEPTH].ulPropTag            = PR_DEPTH;
  1310.     rgsPropValue[ivalPR_DEPTH].Value.l              = 0;
  1311.     rgsPropValue[ivalPR_OBJECT_TYPE].ulPropTag      = PR_OBJECT_TYPE;
  1312.     rgsPropValue[ivalPR_OBJECT_TYPE].Value.l        = MAPI_ABCONT;
  1313.     rgsPropValue[ivalPR_DISPLAY_TYPE].ulPropTag     = PR_DISPLAY_TYPE;
  1314.     rgsPropValue[ivalPR_DISPLAY_TYPE].Value.l       = DT_NOT_SPECIFIC;
  1315.     rgsPropValue[ivalPR_CONTAINER_FLAGS].ulPropTag  = PR_CONTAINER_FLAGS;
  1316.     rgsPropValue[ivalPR_CONTAINER_FLAGS].Value.l    = AB_RECIPIENTS | AB_UNMODIFIABLE;
  1317.     rgsPropValue[ivalPR_INSTANCE_KEY].ulPropTag     = PR_INSTANCE_KEY;
  1318.     rgsPropValue[ivalPR_INSTANCE_KEY].Value.bin.cb  = sizeof(ULONG);
  1319.     rgsPropValue[ivalPR_INSTANCE_KEY].Value.bin.lpb = (LPBYTE) &ulInstanceKey;
  1320.     rgsPropValue[ivalPR_AB_PROVIDER_ID].ulPropTag   = PR_AB_PROVIDER_ID;
  1321.     rgsPropValue[ivalPR_AB_PROVIDER_ID].Value.bin.cb= sizeof(MAPIUID);
  1322.     rgsPropValue[ivalPR_AB_PROVIDER_ID].Value.bin.lpb= (LPBYTE) &muidSABProviderID;
  1323.     hResult = lpABPLogon->lpTDatRoot->lpVtbl->HrModifyRow(
  1324.         lpABPLogon->lpTDatRoot, &sRow);
  1325.     if (HR_FAILED(hResult))
  1326.         goto out;
  1327.     /*
  1328.      *  Check to see if they want a view returned as well
  1329.      */
  1330.     if (lppMAPITable)
  1331.     {
  1332.         /* Get a view from the Table data object */
  1333.         hResult =
  1334.             lpABPLogon->lpTDatRoot->lpVtbl->HrGetView(
  1335.             lpABPLogon->lpTDatRoot,
  1336.             NULL,
  1337.             NULL,
  1338.             0,
  1339.             lppMAPITable);
  1340.     }
  1341. out:
  1342.     LeaveCriticalSection(&lpABPLogon->cs);
  1343.     
  1344.     DebugTraceResult(HrBuildRootHier, hResult);
  1345.     return hResult;
  1346. }
  1347. /*
  1348.  *  Checks to see if the file passed in is still the actual file that
  1349.  *  should be browsed.
  1350.  */
  1351. BOOL
  1352. FEqualSABFiles( LPABLOGON lpABLogon,
  1353.                 LPSTR lpszFileName)
  1354. {
  1355.     LPABPLOGON lpABPLogon = (LPABPLOGON) lpABLogon;
  1356.     BOOL fEqual;
  1357.     AssertSz(!IsBadReadPtr(lpABPLogon, sizeof(ABPLOGON)), "Bad logon object!n");
  1358.     
  1359.     EnterCriticalSection(&lpABPLogon->cs);
  1360.     fEqual = !lstrcmpA( lpszFileName, lpABPLogon->lpszFileName );
  1361.     LeaveCriticalSection(&lpABPLogon->cs);
  1362.     return fEqual;
  1363. }