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 / ablogon.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-04-11  |  44.7 KB  |  1,634 lines

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