home *** CD-ROM | disk | FTP | other *** search
/ Power GUI Programming with VisualAge C++ / powergui.iso / trialva / ibmcppw / sdk / mapi / win16 / dev / sample.ab / root.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-07-11  |  36.9 KB  |  1,604 lines

  1. /***********************************************************************
  2.  *
  3.  *  ROOT.C
  4.  *
  5.  *
  6.  *  Sample AB Root object
  7.  *      - This file contains the code for implementing the Sample AB
  8.  *      root object and the hierarchy table.
  9.  *
  10.  *  The Root container object is returned via an ABPOpenEntry() with a
  11.  *  0-sized entryid.  It only has a limited set of properties available on
  12.  *  it.  The most useful method on it is GetHierarchyTable() which returns
  13.  *  the root hierarchy associated with this provider.
  14.  *
  15.  *  The hierarchy table has only a single row in it.  The row represents the
  16.  *  single .SAB file which this provider browses.  If a provider wanted to
  17.  *  browse many different lists, it would have multiple rows.
  18.  *
  19.  *  The following routines are implemented in this file:
  20.  *
  21.  *
  22.  *    To implement the Root container object:
  23.  *
  24.  *      HrNewROOT
  25.  *      SetErrorSz
  26.  *      ROOT_QueryInterface
  27.  *      ROOT_AddRef
  28.  *      ROOT_Release
  29.  *      ROOT_GetLastError
  30.  *      ROOT_SaveChanges
  31.  *      ROOT_OpenProperty
  32.  *      ROOT_GetContentsTable
  33.  *      ROOT_GetHierarchyTable
  34.  *      ROOT_OpenEntry
  35.  *      ROOT_CreateEntry
  36.  *      ROOT_CopyEntries
  37.  *      ROOT_DeleteEntries
  38.  *      ROOT_ResolveNames
  39.  *
  40.  *  Copyright 1992-1995 Microsoft Corporation.  All Rights Reserved.
  41.  *
  42.  ***********************************************************************/
  43.  
  44. #include "abp.h"
  45. #include "sampabp.rh"
  46.  
  47.  
  48. /*
  49.  *  The structure behind the 'this' pointer
  50.  */
  51. typedef struct _ROOT
  52. {
  53.     const ROOT_Vtbl FAR *   lpVtbl;
  54.  
  55.     SAB_Wrapped;
  56.     
  57. } ROOT, *LPROOT;
  58.  
  59.  
  60. /*
  61.  *  Root vtbl is filled in here
  62.  */
  63. static const ROOT_Vtbl vtblROOT =
  64. {
  65.     ROOT_QueryInterface,
  66.     ROOT_AddRef,
  67.     ROOT_Release,
  68.     ROOT_GetLastError,
  69.     ROOT_SaveChanges,
  70.     (ROOT_GetProps_METHOD *) WRAP_GetProps,
  71.     (ROOT_GetPropList_METHOD *) WRAP_GetPropList,
  72.     ROOT_OpenProperty,
  73.     (ROOT_SetProps_METHOD *) WRAP_SetProps,
  74.     (ROOT_DeleteProps_METHOD *) WRAP_DeleteProps,
  75.     (ROOT_CopyTo_METHOD *) WRAP_CopyTo,
  76.     (ROOT_CopyProps_METHOD *) WRAP_CopyProps,
  77.     (ROOT_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
  78.     (ROOT_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
  79.     ROOT_GetContentsTable,
  80.     ROOT_GetHierarchyTable,
  81.     ROOT_OpenEntry,
  82.     ROOT_SetSearchCriteria,
  83.     ROOT_GetSearchCriteria,
  84.     ROOT_CreateEntry,
  85.     ROOT_CopyEntries,
  86.     ROOT_DeleteEntries,
  87.     ROOT_ResolveNames
  88. };
  89.  
  90.  
  91. /*
  92.  *  Default properties in this object
  93.  */
  94. enum {  ivalPR_DISPLAY_TYPE = 0,
  95.         ivalPR_OBJECT_TYPE,
  96.         ivalPR_ENTRYID,
  97.         ivalPR_RECORD_KEY,
  98.         ivalPR_SEARCH_KEY,
  99.         ivalPR_DISPLAY_NAME_A,
  100.         ivalPR_CONTAINER_FLAGS,
  101.         cvalMax };
  102.  
  103. /*
  104.  -  HrNewROOT
  105.  -
  106.  *  Creates a new Root Container object.  This object is created
  107.  *  when an lpABLogon::OpenEntry() is called with a 0-sized entryid.
  108.  *
  109.  *
  110.  */
  111. HRESULT
  112. HrNewROOT(LPABCONT *        lppROOT,
  113.           ULONG *           lpulObjType,
  114.           LPABLOGON         lpABPLogon,
  115.           LPCIID            lpInterface,
  116.           HINSTANCE         hLibrary,
  117.           LPALLOCATEBUFFER  lpAllocBuff,
  118.           LPALLOCATEMORE    lpAllocMore,
  119.           LPFREEBUFFER      lpFreeBuff,
  120.           LPMALLOC          lpMalloc )
  121. {
  122.     LPROOT lpROOT = NULL;
  123.     SCODE scode;
  124.     LPPROPDATA lpPropData = NULL;
  125.     SPropValue spv[cvalMax];
  126.     HRESULT hResult;
  127.     char szDisplayName[MAX_ROOT_NAME];
  128.     LPSTR pszDisplayName = (LPSTR) szDisplayName;
  129.     SCODE sc;
  130.     DIR_ENTRYID eidRoot =   {   {0, 0, 0, 0},
  131.                                 MUIDABSAMPLE,
  132.                                 SAMP_VERSION,
  133.                                 SAMP_DIRECTORY };
  134.  
  135.     /*  Do I support this interface?? */
  136.     if (lpInterface)
  137.     {
  138.         if (memcmp(lpInterface, &IID_IUnknown, sizeof(IID)) &&
  139.             memcmp(lpInterface, &IID_IMAPIProp, sizeof(IID)) &&
  140.             memcmp(lpInterface, &IID_IMAPIContainer, sizeof(IID)) &&
  141.             memcmp(lpInterface, &IID_IABContainer, sizeof(IID)))
  142.         {
  143.             DebugTraceSc(HrNewROOT, MAPI_E_INTERFACE_NOT_SUPPORTED);
  144.             return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  145.         }
  146.     }
  147.     /*
  148.      *  Allocate space for the ROOT structure
  149.      */
  150.     scode = lpAllocBuff (sizeof(ROOT), (LPVOID *) &lpROOT);
  151.     if (FAILED(scode))
  152.     {
  153.         hResult = ResultFromScode(scode);
  154.         goto err;
  155.     }
  156.  
  157.     lpROOT->lpVtbl = &vtblROOT;
  158.     lpROOT->lcInit = 1;
  159.     lpROOT->hResult = hrSuccess;
  160.     lpROOT->idsLastError = 0;
  161.  
  162.     lpROOT->hLibrary = hLibrary;
  163.     lpROOT->lpAllocBuff = lpAllocBuff;
  164.     lpROOT->lpAllocMore = lpAllocMore;
  165.     lpROOT->lpFreeBuff = lpFreeBuff;
  166.     lpROOT->lpMalloc = lpMalloc;
  167.  
  168.     lpROOT->lpABLogon = lpABPLogon;
  169.  
  170.     /*
  171.      *  Create a property storage object
  172.      */
  173.  
  174.     scode = CreateIProp((LPIID) &IID_IMAPIPropData,
  175.         lpAllocBuff,
  176.         lpAllocMore,
  177.         lpFreeBuff,
  178.         lpMalloc,
  179.         &lpPropData);
  180.  
  181.     if (FAILED(scode))
  182.     {
  183.         hResult = ResultFromScode(scode);
  184.         goto err;
  185.     }
  186.  
  187.     /*
  188.      *  Set up initial set of properties associated with this
  189.      *  container.
  190.      */
  191.  
  192.     spv[ivalPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  193.     spv[ivalPR_DISPLAY_TYPE].Value.l = 0;           /* undefined for now */
  194.  
  195.     spv[ivalPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  196.     spv[ivalPR_OBJECT_TYPE].Value.l = MAPI_ABCONT;
  197.  
  198.     spv[ivalPR_ENTRYID].ulPropTag = PR_ENTRYID;
  199.     spv[ivalPR_ENTRYID].Value.bin.cb = sizeof(DIR_ENTRYID);
  200.     spv[ivalPR_ENTRYID].Value.bin.lpb = (LPBYTE) &eidRoot;
  201.  
  202.     spv[ivalPR_RECORD_KEY].ulPropTag = PR_RECORD_KEY;
  203.     spv[ivalPR_RECORD_KEY].Value.bin.cb = sizeof(DIR_ENTRYID);
  204.     spv[ivalPR_RECORD_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  205.  
  206.     spv[ivalPR_SEARCH_KEY].ulPropTag = PR_SEARCH_KEY;
  207.     spv[ivalPR_SEARCH_KEY].Value.bin.cb = sizeof(DIR_ENTRYID);
  208.     spv[ivalPR_SEARCH_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  209.  
  210.     sc = ScLoadString(  IDS_ROOT_NAME,
  211.                         MAX_ROOT_NAME,
  212.                         NULL,
  213.                         hLibrary,
  214.                         (LPSTR *) &pszDisplayName);
  215.     if (FAILED(sc))
  216.     {
  217.         hResult = ResultFromScode(sc);
  218.         goto out;
  219.     }
  220.  
  221.     spv[ivalPR_DISPLAY_NAME_A].ulPropTag = PR_DISPLAY_NAME_A;
  222.     spv[ivalPR_DISPLAY_NAME_A].Value.lpszA = szDisplayName;
  223.  
  224.     spv[ivalPR_CONTAINER_FLAGS].ulPropTag = PR_CONTAINER_FLAGS;
  225.     spv[ivalPR_CONTAINER_FLAGS].Value.l = AB_SUBCONTAINERS;
  226.  
  227.     /*
  228.      *   Set the default properties
  229.      */
  230.     hResult = lpPropData->lpVtbl->SetProps(lpPropData,
  231.         cvalMax,
  232.         spv,
  233.         NULL);
  234.  
  235.     if (HR_FAILED(hResult))
  236.     {
  237.         goto err;
  238.     }
  239.  
  240.     /*
  241.      *  The whole object is set READONLY thus eliminating the need to
  242.      *  set access rights for the individual properties.
  243.      */
  244.     (void) lpPropData->lpVtbl->HrSetObjAccess(lpPropData, IPROP_READONLY);
  245.  
  246.     lpROOT->lpPropData = (LPMAPIPROP) lpPropData;
  247.  
  248.     InitializeCriticalSection(&lpROOT->cs);
  249.  
  250.  
  251.     /*  We must AddRef the lpABPLogon object since we will be using it
  252.      */
  253.     lpABPLogon->lpVtbl->AddRef(lpABPLogon);
  254.  
  255.     *lpulObjType = MAPI_ABCONT;
  256.     *lppROOT = (LPVOID) lpROOT;
  257.  
  258. out:
  259.     DebugTraceResult(HrNewROOT, hResult);
  260.     return hResult;
  261.  
  262. err:
  263.     /*
  264.      *  free the root object
  265.      */
  266.     lpFreeBuff (lpROOT);
  267.  
  268.     /*
  269.      *  free the prop data
  270.      */
  271.     if (lpPropData)
  272.         lpPropData->lpVtbl->Release(lpPropData);
  273.  
  274.     goto out;
  275.     
  276. }
  277.  
  278. /*************************************************************************
  279.  *
  280.  *
  281.  -  SetErrorIDS
  282.  -
  283.  *  Handles remembering the last error string associated with an object.
  284.  *  This string is retrieved by the method GetLastError()
  285.  *
  286.  *
  287.  */
  288.  
  289. VOID
  290. SetErrorIDS(LPVOID lpObject, HRESULT hResult, UINT ids)
  291. {
  292.     ((LPROOT) lpObject)->hResult = hResult;
  293.     ((LPROOT) lpObject)->idsLastError = ids;
  294. }
  295.  
  296. /*
  297.  -  ROOT_QueryInterface
  298.  -
  299.  *  Supports QI'ing to IUnknown, IMAPIProp, IMAPIContainer, and IABContainer.
  300.  *
  301.  */
  302. STDMETHODIMP
  303. ROOT_QueryInterface(LPROOT lpROOT,
  304.                     REFIID lpiid,
  305.                     LPVOID FAR * lppNewObj)
  306. {
  307.  
  308.     HRESULT hr = hrSuccess;
  309.  
  310.     /*
  311.      *  Check to see if it has a lpVtbl object member
  312.      */
  313.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  314.     {
  315.         /*
  316.          *  Not large enough
  317.          */
  318.         hr = ResultFromScode(E_INVALIDARG);
  319.         goto out;
  320.     }
  321.  
  322.     /*
  323.      *  Check to see that the Vtbl is large enough to include this method
  324.      */
  325.     if (IsBadReadPtr(lpROOT->lpVtbl,
  326.                      offsetof(ROOT_Vtbl, QueryInterface)+sizeof(ROOT_QueryInterface_METHOD *)))
  327.     {
  328.         /*
  329.          *  Jump table not derived from IUnknown
  330.          */
  331.         hr = ResultFromScode(E_INVALIDARG);
  332.         goto out;
  333.     }
  334.  
  335.     /*
  336.      *  Check to see if the method is the same
  337.      */
  338.     if (ROOT_QueryInterface != lpROOT->lpVtbl->QueryInterface)
  339.     {
  340.         /*
  341.          *  Wrong object - the object passed doesn't have this
  342.          *  method.
  343.          */
  344.         hr = ResultFromScode(E_INVALIDARG);
  345.         goto out;
  346.     }
  347.  
  348.     /*  Check other parameters */
  349.  
  350.     if (IsBadReadPtr(lpiid, (UINT) sizeof(IID))
  351.         || IsBadWritePtr(lppNewObj, (UINT) sizeof(LPVOID)))
  352.     {
  353.         hr = ResultFromScode(E_INVALIDARG);
  354.         goto out;
  355.     }
  356.  
  357.     /*  See if the requested interface is one of ours */
  358.  
  359.     if (memcmp(lpiid, &IID_IUnknown, sizeof(IID)) &&
  360.         memcmp(lpiid, &IID_IMAPIProp, sizeof(IID)) &&
  361.         memcmp(lpiid, &IID_IMAPIContainer, sizeof(IID)) &&
  362.         memcmp(lpiid, &IID_IABContainer, sizeof(IID)))
  363.     {
  364.         *lppNewObj = NULL;      /* OLE requires zeroing [out] parameter */
  365.         hr = ResultFromScode(E_NOINTERFACE);
  366.         goto out;
  367.     }
  368.  
  369.     /*  We'll do this one. Bump the usage count and return a new pointer. */
  370.  
  371.     EnterCriticalSection(&lpROOT->cs);
  372.     ++lpROOT->lcInit;
  373.     LeaveCriticalSection(&lpROOT->cs);
  374.     
  375.     *lppNewObj = lpROOT;
  376.  
  377. out:
  378.  
  379.     DebugTraceResult(ROOT_QueryInterface, hr);
  380.     return hr;
  381. }
  382.  
  383. /**************************************************
  384.  *
  385.  -  ROOT_AddRef
  386.  -
  387.  *      Increment lcInit
  388.  *
  389.  */
  390.  
  391. STDMETHODIMP_(ULONG) ROOT_AddRef(LPROOT lpROOT)
  392. {
  393.     LONG lcInit;
  394.  
  395.     /*
  396.      *  Check to see if it has a lpVtbl object member
  397.      */
  398.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  399.     {
  400.         /*
  401.          *  Not large enough
  402.          */
  403.         return 1;
  404.     }
  405.  
  406.     /*
  407.      *  Check to see that the Vtbl is large enough to include this method
  408.      */
  409.     if (IsBadReadPtr(lpROOT->lpVtbl,
  410.                      offsetof(ROOT_Vtbl, AddRef)+sizeof(ROOT_AddRef_METHOD *)))
  411.     {
  412.         /*
  413.          *  Jump table not derived from IUnknown
  414.          */
  415.         return 1;
  416.     }
  417.  
  418.     /*
  419.      *  Check to see if the method is the same
  420.      */
  421.     if (ROOT_AddRef != lpROOT->lpVtbl->AddRef)
  422.     {
  423.         /*
  424.          *  Wrong object - the object passed doesn't have this
  425.          *  method.
  426.          */
  427.         return 1;
  428.     }
  429.  
  430.     EnterCriticalSection(&lpROOT->cs);
  431.     lcInit = ++lpROOT->lcInit;
  432.     LeaveCriticalSection(&lpROOT->cs);
  433.  
  434.     return lcInit;
  435. }
  436.  
  437. /**************************************************
  438.  *
  439.  -  ROOT_Release
  440.  -
  441.  *      Decrement lcInit.
  442.  *      When lcInit == 0, free up the lpROOT structure
  443.  *
  444.  */
  445.  
  446. STDMETHODIMP_(ULONG) ROOT_Release(LPROOT lpROOT)
  447. {
  448.  
  449.     LONG lcInit;
  450.     
  451.     /*
  452.      *  Check to see if it can be a ROOT object
  453.      */
  454.     if (IsBadReadPtr(lpROOT, sizeof(ROOT)))
  455.     {
  456.         /*
  457.          *  Not large enough
  458.          */
  459.         return 1;
  460.     }
  461.  
  462.     /*
  463.      *  Check to see that it's ROOTs vtbl
  464.      */
  465.     if (lpROOT->lpVtbl != &vtblROOT)
  466.     {
  467.         /*
  468.          *  Not my jump table
  469.          */
  470.         return 1;
  471.     }
  472.  
  473.     EnterCriticalSection(&lpROOT->cs);
  474.     lcInit = --lpROOT->lcInit;
  475.     LeaveCriticalSection(&lpROOT->cs);
  476.  
  477.     if (lcInit == 0)
  478.     {
  479.  
  480.         /*
  481.          *  Delete our critical section
  482.          */
  483.  
  484.         DeleteCriticalSection(&lpROOT->cs);
  485.  
  486.         /*
  487.          *  Set the vtbl to NULL.  This way the client will find out
  488.          *  real fast if it's calling a method on a released object.  That is,
  489.          *  the client will crash.  Hopefully, this will happen during the
  490.          *  development stage of the client.
  491.          */
  492.         lpROOT->lpVtbl = NULL;
  493.  
  494.         /*
  495.          *  free the property storage object
  496.          */
  497.         if (lpROOT->lpPropData)
  498.             lpROOT->lpPropData->lpVtbl->Release(lpROOT->lpPropData);
  499.  
  500.         /*  
  501.          *  Release our reference to the ABLogon object.
  502.          */
  503.         if (lpROOT->lpABLogon)
  504.         {
  505.             lpROOT->lpABLogon->lpVtbl->Release(lpROOT->lpABLogon);
  506.             lpROOT->lpABLogon = NULL;
  507.         }
  508.  
  509.         /*
  510.          *  Free the object
  511.          */
  512.  
  513.         lpROOT->lpFreeBuff(lpROOT);
  514.         return 0;
  515.     }
  516.  
  517.     return lcInit;
  518. }
  519.  
  520. /*
  521.  -  ROOT_GetLastError
  522.  -
  523.  *      Returns a string associated with the last hResult
  524.  *  returned by the ROOT object.
  525.  *
  526.  */
  527.  
  528. STDMETHODIMP
  529. ROOT_GetLastError(  LPROOT lpROOT,
  530.                     HRESULT hError,
  531.                     ULONG ulFlags,
  532.                     LPMAPIERROR FAR * lppMapiError )
  533. {
  534.     SCODE scode;
  535.     HRESULT hResult = hrSuccess;
  536.     LPSTR   lpszMessage = NULL;
  537.  
  538.     /*
  539.      *  Validate parameters
  540.      */
  541.  
  542.     /*
  543.      *  Check to see if it has a lpVtbl object member
  544.      */
  545.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  546.     {
  547.         /*
  548.          *  Not large enough
  549.          */
  550.         hResult = MakeResult(E_INVALIDARG);
  551.  
  552.         return hResult;
  553.     }
  554.  
  555.     /*
  556.      *  Check to see that the Vtbl is large enough to include this method
  557.      */
  558.     if (IsBadReadPtr(lpROOT->lpVtbl,
  559.         offsetof(ROOT_Vtbl, GetLastError)+sizeof(ROOT_GetLastError_METHOD *)))
  560.     {
  561.         /*
  562.          *  Jump table not derived from IUnknown
  563.          */
  564.  
  565.         hResult = MakeResult(E_INVALIDARG);
  566.  
  567.         return hResult;
  568.     }
  569.  
  570.     /*
  571.      *  Check to see if the method is the same
  572.      */
  573.     if (ROOT_GetLastError != lpROOT->lpVtbl->GetLastError)
  574.     {
  575.         /*
  576.          *  Wrong object - the object passed doesn't have this
  577.          *  method.
  578.          */
  579.         hResult = ResultFromScode(E_INVALIDARG);
  580.         DebugTraceResult(ROOT_GetLastError, hResult);
  581.         return hResult;
  582.     }
  583.  
  584.     /*
  585.      *  Validate ulFlags
  586.      */
  587.     if (ulFlags & ~MAPI_UNICODE)
  588.     {
  589.         /*
  590.          * Unknown flag
  591.          */
  592.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  593.         DebugTraceResult(ROOT_GetLastError, hResult);
  594.         return hResult;
  595.     }
  596.  
  597.  
  598.     /*
  599.      *  NOTE:  We don't handle UNICODE yet.  Everything is
  600.      *  assumed to be working in 8-bit char mode.
  601.      */
  602.     if (ulFlags & MAPI_UNICODE)
  603.     {
  604.         hResult = ResultFromScode(MAPI_E_BAD_CHARWIDTH);
  605.         DebugTraceResult(ROOT_GetLastError, hResult);
  606.         return hResult;
  607.     }
  608.  
  609.     /*
  610.      *  Validate lppMapiError.
  611.      */
  612.     if (IsBadWritePtr(lppMapiError, sizeof(LPMAPIERROR)))
  613.     {
  614.         hResult = ResultFromScode(E_INVALIDARG);
  615.         DebugTraceResult(ROOT_GetLastError, hResult);
  616.         return hResult;
  617.     }
  618.  
  619.     EnterCriticalSection(&lpROOT->cs);
  620.     
  621.     if ((hError != hrSuccess) && (hError == lpROOT->hResult))
  622.     {
  623.         scode = lpROOT->lpAllocBuff( sizeof( MAPIERROR ), lppMapiError );
  624.         if ( FAILED( scode ) )      
  625.         {
  626.             hResult = ResultFromScode(scode);
  627.             goto ret;
  628.         }
  629.         
  630.         ZeroMemory( *lppMapiError, sizeof( MAPIERROR ) );
  631.         
  632.         (*lppMapiError)->ulVersion = MAPI_ERROR_VERSION;
  633.  
  634.         /*
  635.          *  Get the MAPI Allocated string associated with the last error
  636.          */
  637.         scode = ScLoadString(lpROOT->idsLastError,
  638.                              MAX_ERROR_STRING_LENGTH,
  639.                              lpROOT->lpAllocBuff,
  640.                              lpROOT->hLibrary,
  641.                              &lpszMessage);
  642.         if ( FAILED( scode) )                            
  643.         {
  644.             hResult = ResultFromScode(scode);
  645.             goto ret;
  646.         }
  647.         
  648.         scode = lpROOT->lpAllocMore( lstrlenA( lpszMessage ) + 1, *lppMapiError, 
  649.             &(*lppMapiError)->lpszError );
  650.         if ( FAILED( scode ) )      
  651.         {
  652.             hResult = ResultFromScode(scode);
  653.             goto ret;
  654.         }
  655.         
  656.         lstrcpyA( (*lppMapiError)->lpszError, lpszMessage );
  657.         
  658.         
  659.     } else
  660.     {
  661.         *lppMapiError = NULL;
  662.     }
  663.  
  664. ret:
  665.     if ( hResult )
  666.     {
  667.         lpROOT->lpFreeBuff( *lppMapiError );
  668.         *lppMapiError = NULL;
  669.     }
  670.     
  671.     lpROOT->lpFreeBuff( lpszMessage );
  672.     LeaveCriticalSection(&lpROOT->cs);
  673.  
  674.     return hResult;
  675. }
  676.  
  677. /*
  678.  -  ROOT_SaveChanges
  679.  -
  680.  *  Can't save changes on this object.
  681.  *
  682.  *
  683.  */
  684. STDMETHODIMP
  685. ROOT_SaveChanges(LPROOT lpROOT, ULONG ulFlags)
  686. {
  687.  
  688.     HRESULT hResult;
  689.  
  690.     /*
  691.      *  Check to see if it's large enough to be this object
  692.      */
  693.     if (IsBadReadPtr(lpROOT, sizeof(ROOT)))
  694.     {
  695.         /*
  696.          *  Not large enough
  697.          */
  698.         hResult = ResultFromScode(E_INVALIDARG);
  699.         goto out;
  700.     }
  701.  
  702.     /*
  703.      *  Check to see that it's ROOTs vtbl
  704.      */
  705.     if (lpROOT->lpVtbl != &vtblROOT)
  706.     {
  707.         /*
  708.          *  Not my vtbl
  709.          */
  710.         hResult = ResultFromScode(E_INVALIDARG);
  711.         goto out;
  712.     }
  713.  
  714.     if (ulFlags & ~(KEEP_OPEN_READONLY|KEEP_OPEN_READONLY|FORCE_SAVE))
  715.     {
  716.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  717.         goto out;
  718.     }
  719.  
  720.  
  721.     hResult = ResultFromScode(E_ACCESSDENIED);
  722.  
  723. out:
  724.     DebugTraceResult(ROOT_SaveChanges, hResult);
  725.     return hResult;
  726.  
  727. }
  728.  
  729. /*
  730.  -  ROOT_OpenProperty
  731.  -
  732.  *
  733.  *  For this object I only need to support opening the hierarchy table.
  734.  *
  735.  */
  736. STDMETHODIMP
  737. ROOT_OpenProperty(  LPROOT lpROOT,
  738.                     ULONG ulPropTag,
  739.                     LPCIID lpiid,
  740.                     ULONG ulInterfaceOptions,
  741.                     ULONG ulFlags,
  742.                     LPUNKNOWN * lppUnk)
  743. {
  744.  
  745.     HRESULT hResult;
  746.  
  747.     /*
  748.      *  Check to see if it's large enough to be this object
  749.      */
  750.     if (IsBadReadPtr(lpROOT, sizeof(ROOT)))
  751.     {
  752.         /*
  753.          *  Not large enough
  754.          */
  755.         hResult = ResultFromScode(E_INVALIDARG);
  756.         goto out;
  757.     }
  758.  
  759.     /*
  760.      *  Check to see that it's ROOTs vtbl
  761.      */
  762.     if (lpROOT->lpVtbl != &vtblROOT)
  763.     {
  764.         /*
  765.          *  Not my vtbl
  766.          */
  767.         hResult = ResultFromScode(E_INVALIDARG);
  768.         goto out;
  769.     }
  770.  
  771.     if (IsBadWritePtr(lppUnk, sizeof(LPUNKNOWN)))
  772.     {
  773.         /*
  774.          *  Got to be able to return an object
  775.          */
  776.         hResult = ResultFromScode(E_INVALIDARG);
  777.         goto out;
  778.     }
  779.  
  780.     if (IsBadReadPtr(lpiid, (UINT) sizeof(IID)))
  781.     {
  782.         /*
  783.          *  An interface ID is required for this call.
  784.          */
  785.  
  786.         hResult = ResultFromScode(E_INVALIDARG);
  787.         goto out;
  788.     }
  789.  
  790.     if (IsBadWritePtr(lppUnk, sizeof(LPUNKNOWN)))
  791.     {
  792.         /*
  793.          *  Got to be able to return an object
  794.          */
  795.         hResult = ResultFromScode(E_INVALIDARG);
  796.         goto out;
  797.     }
  798.  
  799.     /*
  800.      *  Make sure we are getting a valid PropTag.
  801.      */
  802.     if (FBadPropTag(ulPropTag))
  803.     {
  804.         hResult = ResultFromScode(E_INVALIDARG);
  805.         goto out;
  806.     }
  807.  
  808.     /*
  809.      *  check for unknown flags
  810.      */
  811.     if (ulFlags & ~(  MAPI_DEFERRED_ERRORS | STREAM_APPEND
  812.                     | MAPI_CREATE | MAPI_MODIFY))
  813.     {
  814.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  815.         goto out;
  816.     }
  817.  
  818.     /*
  819.      *  STREAM_APPEND is only valid on a stream interface.
  820.      */
  821.     if (   (ulFlags & STREAM_APPEND)
  822.         && memcmp(lpiid, &IID_IStream, sizeof(IID)) )
  823.     {
  824.         hResult = ResultFromScode(MAPI_E_INVALID_PARAMETER);
  825.         goto out;
  826.     }
  827.     
  828.     if (ulFlags & MAPI_CREATE)
  829.     {
  830.         hResult = ResultFromScode(E_ACCESSDENIED);
  831.         goto out;       
  832.     }
  833.         
  834.     if (ulInterfaceOptions & ~MAPI_UNICODE)
  835.     {
  836.         /*
  837.          *  Only UNICODE flag should be set for any of the objects that might
  838.          *  be returned from this object.
  839.          */
  840.         
  841.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  842.         goto out;
  843.     }
  844.     
  845.     if ( ulInterfaceOptions & MAPI_UNICODE )
  846.     {
  847.         hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  848.         goto out;
  849.     }
  850.  
  851.  
  852.     switch (ulPropTag)
  853.     {
  854.  
  855.         case PR_CONTAINER_HIERARCHY:
  856.         {
  857.             /*
  858.              *  Check to see if they're expecting a IMAPITable object
  859.              */
  860.             if (memcmp(lpiid, &IID_IMAPITable, sizeof(IID)))
  861.             {
  862.                 hResult = ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  863.                 goto out;
  864.             }
  865.  
  866.             hResult = ROOT_GetHierarchyTable(lpROOT, 0, (LPMAPITABLE *) lppUnk);
  867.  
  868.             goto out;
  869.         }
  870.  
  871.         default:
  872.             break;
  873.  
  874.     }
  875.     
  876.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  877.  
  878. out:
  879.  
  880.     DebugTraceResult(ROOT_OpenProperty, hResult);
  881.     return hResult;
  882.  
  883. }
  884.  
  885. /*************************************************************************
  886.  *
  887.  *
  888.  -  ROOT_GetContentsTable
  889.  -
  890.  *  There are no contents in the root
  891.  *
  892.  *
  893.  *
  894.  */
  895. STDMETHODIMP
  896. ROOT_GetContentsTable(  LPROOT lpROOT,
  897.                         ULONG ulFlags,
  898.                         LPMAPITABLE * lppTable)
  899. {
  900.  
  901.     HRESULT hResult;
  902.  
  903.     /*
  904.      *  Check to see if it has a lpVtbl object member
  905.      */
  906.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  907.     {
  908.         /*
  909.          *  Not large enough
  910.          */
  911.         hResult = MakeResult(E_INVALIDARG);
  912.  
  913.         return hResult;
  914.     }
  915.  
  916.     /*
  917.      *  Check to see that the Vtbl is large enough to include this method
  918.      */
  919.     if (IsBadReadPtr(lpROOT->lpVtbl,
  920.         offsetof(ROOT_Vtbl, GetContentsTable)+sizeof(ROOT_GetContentsTable_METHOD *)))
  921.     {
  922.         /*
  923.          *  Jump table not derived from IUnknown
  924.          */
  925.  
  926.         hResult = MakeResult(E_INVALIDARG);
  927.  
  928.         return hResult;
  929.     }
  930.  
  931.     /*
  932.      *  Check to see if the method is the same
  933.      */
  934.     if (ROOT_GetContentsTable != lpROOT->lpVtbl->GetContentsTable)
  935.     {
  936.         /*
  937.          *  Wrong object - the object passed doesn't have this
  938.          *  method.
  939.          */
  940.         hResult = ResultFromScode(E_INVALIDARG);
  941.         DebugTraceResult(ROOT_GetContentsTable, hResult);
  942.         return hResult;
  943.     }
  944.  
  945.     if (ulFlags & ~(MAPI_DEFERRED_ERRORS|MAPI_ASSOCIATED|MAPI_UNICODE))
  946.     {
  947.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  948.         goto out;
  949.     }
  950.     
  951.     if ( ulFlags & MAPI_UNICODE )
  952.     {
  953.         hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  954.         goto out;
  955.     }
  956.     
  957.     if (!IsBadWritePtr(lppTable, sizeof(LPMAPITABLE)))
  958.     {
  959.         hResult = ResultFromScode(E_INVALIDARG);
  960.         goto out;
  961.     }
  962.  
  963.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  964.  
  965. out:
  966.     DebugTraceResult(ROOT_GetContentsTable, hResult);
  967.     return hResult;
  968.  
  969. }
  970.  
  971. /*
  972.  -  ROOT_GetHierarchyTable
  973.  -
  974.  *  Returns the table with just one entry in it.
  975.  *
  976.  *
  977.  *
  978.  */
  979. STDMETHODIMP
  980. ROOT_GetHierarchyTable( LPROOT lpROOT,
  981.                         ULONG ulFlags,
  982.                         LPMAPITABLE * lppTable)
  983. {
  984.  
  985.     HRESULT hResult = hrSuccess;
  986.  
  987.     /*
  988.      *  Validate parameters
  989.      */
  990.  
  991.     /*
  992.      *  Check to see if it's large enough to be this object
  993.      */
  994.     if (IsBadReadPtr(lpROOT, sizeof(ROOT)))
  995.     {
  996.         /*
  997.          *  Not large enough
  998.          */
  999.         hResult = ResultFromScode(E_INVALIDARG);
  1000.         DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  1001.         return hResult;
  1002.     }
  1003.  
  1004.     /*
  1005.      *  Check to see that it's ROOTs vtbl
  1006.      */
  1007.     if (lpROOT->lpVtbl != &vtblROOT)
  1008.     {
  1009.         /*
  1010.          *  Not my vtbl
  1011.          */
  1012.         hResult = ResultFromScode(E_INVALIDARG);
  1013.         DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  1014.         return hResult;
  1015.     }
  1016.  
  1017.     /*
  1018.      *  See if I can set the return variable
  1019.      */
  1020.     if (IsBadWritePtr(lppTable, sizeof(LPMAPITABLE)))
  1021.     {
  1022.         hResult = ResultFromScode(E_INVALIDARG);
  1023.  
  1024.         DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  1025.         return hResult;
  1026.     }
  1027.  
  1028.     /*
  1029.      *  Check flags:
  1030.      *    The only valid flags are CONVENIENT_DEPTH and MAPI_DEFERRED_ERRORS
  1031.      */
  1032.  
  1033.     if (ulFlags & ~(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS))
  1034.     {
  1035.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  1036.  
  1037.         DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  1038.         return hResult;
  1039.     }
  1040.  
  1041.     /*
  1042.      *  Since we only have one item in our hierarchy table, CONVENIENT_DEPTH
  1043.      *  is equivalent to any other depth level (>1).  So, just ignore the
  1044.      *  flag.  MAPI_DEFERRED_ERROR is fine.  We don't ever defer errors.
  1045.      */
  1046.  
  1047.     /*
  1048.      *  Create a View Table for the hierarchy.
  1049.      */
  1050.     hResult = HrBuildRootHier(lpROOT->lpABLogon, lppTable);
  1051.  
  1052.     DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  1053.     return hResult;
  1054.  
  1055. }
  1056.  
  1057. /*
  1058.  -  ROOT_OpenEntry
  1059.  -
  1060.  *  Check parameters and use our logon object's OpenEntry method.
  1061.  */
  1062. STDMETHODIMP
  1063. ROOT_OpenEntry(LPROOT lpROOT,
  1064.     ULONG cbEntryID,
  1065.     LPENTRYID lpEntryID,
  1066.     LPCIID lpInterface,
  1067.     ULONG ulFlags,
  1068.     ULONG * lpulObjType,
  1069.     LPUNKNOWN * lppUnk)
  1070. {
  1071.     HRESULT hResult;
  1072.  
  1073.     /*
  1074.      *  Check to see if it has a lpVtbl object member
  1075.      */
  1076.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1077.     {
  1078.         /*
  1079.          *  No vtbl found
  1080.          */
  1081.         hResult = MakeResult(E_INVALIDARG);
  1082.         goto out;
  1083.     }
  1084.  
  1085.     /*
  1086.      *  Check to see that the Vtbl is large enough to include this method
  1087.      */
  1088.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1089.         offsetof(ROOT_Vtbl, OpenEntry)+sizeof(ROOT_OpenEntry_METHOD *)))
  1090.     {
  1091.         /*
  1092.          *  vtbl cannot hold this method
  1093.          */
  1094.  
  1095.         hResult = MakeResult(E_INVALIDARG);
  1096.         goto out;
  1097.     }
  1098.  
  1099.     /*
  1100.      *  Check to see that it's the correct method
  1101.      */
  1102.     if (ROOT_OpenEntry != lpROOT->lpVtbl->OpenEntry)
  1103.     {
  1104.         /*
  1105.          *  Not my vtbl
  1106.          */
  1107.         hResult = ResultFromScode(E_INVALIDARG);
  1108.         goto out;
  1109.     }
  1110.  
  1111.     /*
  1112.      *  Check the entryID
  1113.      */
  1114.     if (cbEntryID &&
  1115.         (cbEntryID < (ULONG) sizeof(ENTRYID) ||
  1116.          IsBadReadPtr(lpEntryID, (UINT) cbEntryID)))
  1117.     {
  1118.         /*
  1119.          *  Malformed entryID
  1120.          */
  1121.         
  1122.         hResult = ResultFromScode(E_INVALIDARG);
  1123.         goto out;
  1124.     }
  1125.  
  1126.     if (lpInterface && IsBadReadPtr(lpInterface, sizeof(IID)))
  1127.     {
  1128.         /*
  1129.          *  malformed interface id
  1130.          */
  1131.         
  1132.         hResult = ResultFromScode(E_INVALIDARG);
  1133.         goto out;
  1134.     }
  1135.  
  1136.     if (ulFlags & ~(MAPI_DEFERRED_ERRORS))
  1137.     {
  1138.         /*
  1139.          *  Flags are set that I have no idea about
  1140.          */
  1141.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  1142.         goto out;
  1143.     }
  1144.  
  1145.     if (IsBadWritePtr(lpulObjType, sizeof(ULONG)))
  1146.     {
  1147.         /*
  1148.          *  Can't return an object type
  1149.          */
  1150.         
  1151.         hResult = ResultFromScode(E_INVALIDARG);
  1152.         goto out;
  1153.     }
  1154.  
  1155.     if (IsBadWritePtr(lppUnk, sizeof(LPUNKNOWN)))
  1156.     {
  1157.         /*
  1158.          *  Can't return an object
  1159.          */
  1160.         
  1161.         hResult = ResultFromScode(E_INVALIDARG);
  1162.         goto out;
  1163.     }
  1164.  
  1165.     hResult = lpROOT->lpABLogon->lpVtbl->OpenEntry(lpROOT->lpABLogon,
  1166.         cbEntryID,
  1167.         lpEntryID,
  1168.         lpInterface,
  1169.         ulFlags,
  1170.         lpulObjType,
  1171.         lppUnk);
  1172.     
  1173. out:
  1174.  
  1175.     DebugTraceResult(ROOT_OpenEntry, hResult);
  1176.     return hResult;
  1177.  
  1178. }
  1179.  
  1180. /*
  1181.  -  ROOT_SetSearchCriteria
  1182.  -
  1183.  *
  1184.  *  Not implemented for this object
  1185.  */
  1186. STDMETHODIMP
  1187. ROOT_SetSearchCriteria(LPROOT lpROOT,
  1188.     LPSRestriction lpRestriction,
  1189.     LPENTRYLIST lpContainerList,
  1190.     ULONG ulSearchFlags)
  1191. {
  1192.     HRESULT hResult;
  1193.  
  1194.     /*
  1195.      *  Check to see if it has a lpVtbl object member
  1196.      */
  1197.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1198.     {
  1199.         /*
  1200.          *  Not large enough
  1201.          */
  1202.         hResult = MakeResult(E_INVALIDARG);
  1203.  
  1204.         goto out;
  1205.     }
  1206.  
  1207.     /*
  1208.      *  Check to see that the Vtbl is large enough to include this method
  1209.      */
  1210.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1211.         offsetof(ROOT_Vtbl, SetSearchCriteria)+sizeof(ROOT_SetSearchCriteria_METHOD *)))
  1212.     {
  1213.         /*
  1214.          *  vtbl not large enough to support this method
  1215.          */
  1216.  
  1217.         hResult = MakeResult(E_INVALIDARG);
  1218.  
  1219.         goto out;
  1220.     }
  1221.  
  1222.     /*
  1223.      *  Check to see that it's the correct method
  1224.      */
  1225.     if (ROOT_SetSearchCriteria != lpROOT->lpVtbl->SetSearchCriteria)
  1226.     {
  1227.         /*
  1228.          *  Not my vtbl
  1229.          */
  1230.         hResult = ResultFromScode(E_INVALIDARG);
  1231.         goto out;
  1232.     }
  1233.  
  1234.     /*
  1235.      *  Check for bad restriction.  This is from the mapi utilities DLL.
  1236.      */
  1237.     if (lpRestriction && FBadRestriction(lpRestriction))
  1238.     {
  1239.         hResult = ResultFromScode(MAPI_E_INVALID_PARAMETER);
  1240.         goto out;
  1241.     }
  1242.  
  1243.     /*
  1244.      *  Check for bad container list.  This is from the mapi utilities DLL.
  1245.      */
  1246.     if (lpContainerList && FBadEntryList(lpContainerList))
  1247.     {
  1248.         hResult = ResultFromScode(MAPI_E_INVALID_PARAMETER);
  1249.         goto out;
  1250.     }
  1251.  
  1252.     /*
  1253.      *  Check for unknown flags.
  1254.      */
  1255.     if ( ulSearchFlags & ~(  STOP_SEARCH | RESTART_SEARCH | RECURSIVE_SEARCH
  1256.                            | SHALLOW_SEARCH | FOREGROUND_SEARCH
  1257.                            | BACKGROUND_SEARCH) )
  1258.     {
  1259.         hResult = ResultFromScode( MAPI_E_UNKNOWN_FLAGS );
  1260.         goto out;
  1261.     }
  1262.  
  1263.  
  1264.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1265.  
  1266. out:
  1267.     DebugTraceResult(ROOT_SetSearchCriteria, hResult);
  1268.     return hResult;
  1269. }
  1270.  
  1271. /*
  1272.  -  ROOT_GetSearchCriteria
  1273.  -
  1274.  *
  1275.  *  Not implemented for this object
  1276.  *
  1277.  */
  1278. STDMETHODIMP
  1279. ROOT_GetSearchCriteria(LPROOT lpROOT,
  1280.     ULONG ulFlags,
  1281.     LPSRestriction FAR * lppRestriction,
  1282.     LPENTRYLIST FAR * lppContainerList,
  1283.     ULONG FAR * lpulSearchState)
  1284. {
  1285.     HRESULT hResult;
  1286.  
  1287.     /*
  1288.      *  Check to see if it has a lpVtbl object member
  1289.      */
  1290.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1291.     {
  1292.         /*
  1293.          *  Not large enough
  1294.          */
  1295.         hResult = MakeResult(E_INVALIDARG);
  1296.  
  1297.         return hResult;
  1298.     }
  1299.  
  1300.     /*
  1301.      *  Check to see that the Vtbl is large enough to include this method
  1302.      */
  1303.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1304.         offsetof(ROOT_Vtbl, GetSearchCriteria)+sizeof(ROOT_GetSearchCriteria_METHOD *)))
  1305.     {
  1306.         /*
  1307.          *  Jump table not derived from IUnknown
  1308.          */
  1309.  
  1310.         hResult = MakeResult(E_INVALIDARG);
  1311.  
  1312.         return hResult;
  1313.     }
  1314.  
  1315.     /*
  1316.      *  Check to see if the method is the same
  1317.      */
  1318.     if (ROOT_GetSearchCriteria != lpROOT->lpVtbl->GetSearchCriteria)
  1319.     {
  1320.         /*
  1321.          *  Wrong object - the object passed doesn't have this
  1322.          *  method.
  1323.          */
  1324.         hResult = ResultFromScode(E_INVALIDARG);
  1325.         DebugTraceResult(ROOT_GetSearchCriteria, hResult);
  1326.         return hResult;
  1327.     }
  1328.  
  1329.     if ( ulFlags & ~(MAPI_UNICODE) )
  1330.     {
  1331.         hResult = ResultFromScode( MAPI_E_UNKNOWN_FLAGS );
  1332.         
  1333.         return hResult;
  1334.         
  1335.     }
  1336.     
  1337.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1338.  
  1339.     DebugTraceResult(ROOT_GetSearchCriteria, hResult);
  1340.     return hResult;
  1341. }
  1342.  
  1343. /*
  1344.  -  ROOT_CreateEntry
  1345.  -
  1346.  *  New entries cannot be created in the root
  1347.  *
  1348.  */
  1349. STDMETHODIMP
  1350. ROOT_CreateEntry(LPROOT lpROOT,
  1351.     ULONG cbEntryID,
  1352.     LPENTRYID lpEntryID,
  1353.     ULONG ulCreateFlags,
  1354.     LPMAPIPROP FAR * lppMAPIPropEntry)
  1355. {
  1356.  
  1357.     HRESULT hResult;
  1358.  
  1359.     /*
  1360.      *  Check to see if it has a lpVtbl object member
  1361.      */
  1362.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1363.     {
  1364.         /*
  1365.          *  No vtbl found
  1366.          */
  1367.         hResult = MakeResult(E_INVALIDARG);
  1368.         goto out;
  1369.     }
  1370.  
  1371.     /*
  1372.      *  Check to see that the Vtbl is large enough to include this method
  1373.      */
  1374.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1375.                      offsetof(ROOT_Vtbl, CreateEntry)+sizeof(ROOT_CreateEntry_METHOD *)))
  1376.     {
  1377.         /*
  1378.          *  vtbl not large enough to hold this method
  1379.          */
  1380.  
  1381.         hResult = MakeResult(E_INVALIDARG);
  1382.         goto out;
  1383.     }
  1384.  
  1385.     /*
  1386.      *  Check to see if the method is the same
  1387.      */
  1388.     if (ROOT_CreateEntry != lpROOT->lpVtbl->CreateEntry)
  1389.     {
  1390.         /*
  1391.          *  Wrong object - the object passed doesn't have this
  1392.          *  method.
  1393.          */
  1394.  
  1395.         hResult = MakeResult(E_INVALIDARG);
  1396.         goto out;
  1397.     }
  1398.  
  1399.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1400.  
  1401. out:
  1402.     DebugTraceResult(ROOT_CreateEntry, hResult);
  1403.     return hResult;
  1404.  
  1405. }
  1406.  
  1407. /*
  1408.  -  ROOT_CopyEntries
  1409.  -
  1410.  *  Entries cannot be copied into the root
  1411.  *
  1412.  *
  1413.  *
  1414.  */
  1415. STDMETHODIMP
  1416. ROOT_CopyEntries(LPROOT lpROOT,
  1417.     LPENTRYLIST lpEntries,
  1418.     ULONG ulUIParam,
  1419.     LPMAPIPROGRESS lpProgress,
  1420.     ULONG ulFlags)
  1421. {
  1422.  
  1423.     HRESULT hResult;
  1424.  
  1425.     /*
  1426.      *  Check to see if it has a lpVtbl object member
  1427.      */
  1428.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1429.     {
  1430.         /*
  1431.          *  No vtbl found
  1432.          */
  1433.         hResult = MakeResult(E_INVALIDARG);
  1434.         goto out;
  1435.     }
  1436.  
  1437.     /*
  1438.      *  Check to see that the Vtbl is large enough to include this method
  1439.      */
  1440.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1441.                      offsetof(ROOT_Vtbl, CopyEntries)+sizeof(ROOT_CopyEntries_METHOD *)))
  1442.     {
  1443.         /*
  1444.          *  vtbl not large enough to hold this method
  1445.          */
  1446.  
  1447.         hResult = MakeResult(E_INVALIDARG);
  1448.         goto out;
  1449.     }
  1450.  
  1451.     /*
  1452.      *  Check to see if the method is the same
  1453.      */
  1454.     if (ROOT_CopyEntries != lpROOT->lpVtbl->CopyEntries)
  1455.     {
  1456.         /*
  1457.          *  Wrong object - the object passed doesn't have this
  1458.          *  method.
  1459.          */
  1460.  
  1461.         hResult = MakeResult(E_INVALIDARG);
  1462.         goto out;
  1463.     }
  1464.  
  1465.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1466.  
  1467.  
  1468. out:
  1469.     DebugTraceResult(ROOT_CopyEntries, hResult);
  1470.     return hResult;
  1471.  
  1472. }
  1473.  
  1474. /*
  1475.  -  ROOT_DeleteEntries
  1476.  -
  1477.  *  Entries cannot be deleted from the root
  1478.  *
  1479.  *
  1480.  *
  1481.  */
  1482. STDMETHODIMP
  1483. ROOT_DeleteEntries(LPROOT lpROOT,
  1484.     LPENTRYLIST lpEntries,
  1485.     ULONG ulFlags)
  1486. {
  1487.  
  1488.     HRESULT hResult;
  1489.  
  1490.     /*
  1491.      *  Check to see if it has a lpVtbl object member
  1492.      */
  1493.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1494.     {
  1495.         /*
  1496.          *  No vtbl found
  1497.          */
  1498.         hResult = MakeResult(E_INVALIDARG);
  1499.         goto out;
  1500.     }
  1501.  
  1502.     /*
  1503.      *  Check to see that the Vtbl is large enough to include this method
  1504.      */
  1505.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1506.                      offsetof(ROOT_Vtbl, DeleteEntries)+sizeof(ROOT_DeleteEntries_METHOD *)))
  1507.     {
  1508.         /*
  1509.          *  vtbl not large enough to hold this method
  1510.          */
  1511.  
  1512.         hResult = MakeResult(E_INVALIDARG);
  1513.         goto out;
  1514.     }
  1515.  
  1516.     /*
  1517.      *  Check to see if the method is the same
  1518.      */
  1519.     if (ROOT_DeleteEntries != lpROOT->lpVtbl->DeleteEntries)
  1520.     {
  1521.         /*
  1522.          *  Wrong object - the object passed doesn't have this
  1523.          *  method.
  1524.          */
  1525.  
  1526.         hResult = MakeResult(E_INVALIDARG);
  1527.         goto out;
  1528.     }
  1529.  
  1530.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1531.  
  1532. out:
  1533.     DebugTraceResult(ROOT_DeleteEntries, hResult);
  1534.     return hResult;
  1535. }
  1536.  
  1537. /*
  1538.  -  ROOT_ResolveNames
  1539.  -
  1540.  *  No special case handling of resolving names within this container
  1541.  *
  1542.  *
  1543.  *
  1544.  */
  1545. STDMETHODIMP
  1546. ROOT_ResolveNames(  LPROOT          lpROOT,
  1547.                     LPSPropTagArray lptagaColSet,
  1548.                     ULONG           ulFlags,
  1549.                     LPADRLIST       lpAdrList,
  1550.                     LPFlagList      lpFlagList )
  1551. {
  1552.  
  1553.     HRESULT hResult;
  1554.  
  1555.     /*
  1556.      *  Check to see if it has a lpVtbl object member
  1557.      */
  1558.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1559.     {
  1560.         /*
  1561.          *  No vtbl found
  1562.          */
  1563.         hResult = MakeResult(E_INVALIDARG);
  1564.         goto out;
  1565.     }
  1566.  
  1567.     /*
  1568.      *  Check to see that the Vtbl is large enough to include this method
  1569.      */
  1570.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1571.                      offsetof(ROOT_Vtbl, ResolveNames)+sizeof(ROOT_ResolveNames_METHOD *)))
  1572.     {
  1573.         /*
  1574.          *  vtbl not large enough to hold this method
  1575.          */
  1576.  
  1577.         hResult = MakeResult(E_INVALIDARG);
  1578.         goto out;
  1579.     }
  1580.  
  1581.     /*
  1582.      *  Check to see if the method is the same
  1583.      */
  1584.     if (ROOT_ResolveNames != lpROOT->lpVtbl->ResolveNames)
  1585.     {
  1586.         /*
  1587.          *  Wrong object - the object passed doesn't have this
  1588.          *  method.
  1589.          */
  1590.  
  1591.         hResult = MakeResult(E_INVALIDARG);
  1592.         goto out;
  1593.     }
  1594.  
  1595.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1596.  
  1597. out:
  1598.     DebugTraceResult(ROOT_ResolveNames, hResult);
  1599.     return hResult;
  1600. }
  1601.  
  1602.  
  1603.  
  1604.