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

Windows编程

开发平台:

Visual C++

  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. #include "abp.h"
  44. #include "sampabp.rh"
  45. /*
  46.  *  The structure behind the 'this' pointer
  47.  */
  48. typedef struct _ROOT
  49. {
  50.     const ROOT_Vtbl FAR *   lpVtbl;
  51.     SAB_Wrapped;
  52.     
  53. } ROOT, *LPROOT;
  54. /*
  55.  *  Root vtbl is filled in here
  56.  */
  57. static const ROOT_Vtbl vtblROOT =
  58. {
  59.     ROOT_QueryInterface,
  60.     ROOT_AddRef,
  61.     ROOT_Release,
  62.     ROOT_GetLastError,
  63.     ROOT_SaveChanges,
  64.     (ROOT_GetProps_METHOD *) WRAP_GetProps,
  65.     (ROOT_GetPropList_METHOD *) WRAP_GetPropList,
  66.     ROOT_OpenProperty,
  67.     (ROOT_SetProps_METHOD *) WRAP_SetProps,
  68.     (ROOT_DeleteProps_METHOD *) WRAP_DeleteProps,
  69.     (ROOT_CopyTo_METHOD *) WRAP_CopyTo,
  70.     (ROOT_CopyProps_METHOD *) WRAP_CopyProps,
  71.     (ROOT_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
  72.     (ROOT_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
  73.     ROOT_GetContentsTable,
  74.     ROOT_GetHierarchyTable,
  75.     ROOT_OpenEntry,
  76.     ROOT_SetSearchCriteria,
  77.     ROOT_GetSearchCriteria,
  78.     ROOT_CreateEntry,
  79.     ROOT_CopyEntries,
  80.     ROOT_DeleteEntries,
  81.     ROOT_ResolveNames
  82. };
  83. /*
  84.  *  Default properties in this object
  85.  */
  86. enum {  ivalPR_DISPLAY_TYPE = 0,
  87.         ivalPR_OBJECT_TYPE,
  88.         ivalPR_ENTRYID,
  89.         ivalPR_RECORD_KEY,
  90.         ivalPR_SEARCH_KEY,
  91.         ivalPR_DISPLAY_NAME_A,
  92.         ivalPR_CONTAINER_FLAGS,
  93.         cvalMax };
  94. /*
  95.  -  HrNewROOT
  96.  -
  97.  *  Creates a new Root Container object.  This object is created
  98.  *  when an lpABLogon::OpenEntry() is called with a 0-sized entryid.
  99.  *
  100.  *
  101.  */
  102. HRESULT
  103. HrNewROOT(LPABCONT *        lppROOT,
  104.           ULONG *           lpulObjType,
  105.           LPABLOGON         lpABPLogon,
  106.           LPCIID            lpInterface,
  107.           HINSTANCE         hLibrary,
  108.           LPALLOCATEBUFFER  lpAllocBuff,
  109.           LPALLOCATEMORE    lpAllocMore,
  110.           LPFREEBUFFER      lpFreeBuff,
  111.           LPMALLOC          lpMalloc )
  112. {
  113.     LPROOT lpROOT = NULL;
  114.     SCODE scode;
  115.     LPPROPDATA lpPropData = NULL;
  116.     SPropValue spv[cvalMax];
  117.     HRESULT hResult;
  118.     char szDisplayName[MAX_ROOT_NAME];
  119.     LPSTR pszDisplayName = (LPSTR) szDisplayName;
  120.     SCODE sc;
  121.     DIR_ENTRYID eidRoot =   {   {0, 0, 0, 0},
  122.                                 MUIDABSAMPLE,
  123.                                 SAMP_VERSION,
  124.                                 SAMP_DIRECTORY };
  125.     /*  Do I support this interface?? */
  126.     if (lpInterface)
  127.     {
  128.         if (memcmp(lpInterface, &IID_IUnknown, sizeof(IID)) &&
  129.             memcmp(lpInterface, &IID_IMAPIProp, sizeof(IID)) &&
  130.             memcmp(lpInterface, &IID_IMAPIContainer, sizeof(IID)) &&
  131.             memcmp(lpInterface, &IID_IABContainer, sizeof(IID)))
  132.         {
  133.             DebugTraceSc(HrNewROOT, MAPI_E_INTERFACE_NOT_SUPPORTED);
  134.             return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  135.         }
  136.     }
  137.     /*
  138.      *  Allocate space for the ROOT structure
  139.      */
  140.     scode = lpAllocBuff (sizeof(ROOT), (LPVOID *) &lpROOT);
  141.     if (FAILED(scode))
  142.     {
  143.         hResult = ResultFromScode(scode);
  144.         goto err;
  145.     }
  146.     lpROOT->lpVtbl = &vtblROOT;
  147.     lpROOT->lcInit = 1;
  148.     lpROOT->hResult = hrSuccess;
  149.     lpROOT->idsLastError = 0;
  150.     lpROOT->hLibrary = hLibrary;
  151.     lpROOT->lpAllocBuff = lpAllocBuff;
  152.     lpROOT->lpAllocMore = lpAllocMore;
  153.     lpROOT->lpFreeBuff = lpFreeBuff;
  154.     lpROOT->lpMalloc = lpMalloc;
  155.     lpROOT->lpABLogon = lpABPLogon;
  156.     /*
  157.      *  Create a property storage object
  158.      */
  159.     scode = CreateIProp((LPIID) &IID_IMAPIPropData,
  160.         lpAllocBuff,
  161.         lpAllocMore,
  162.         lpFreeBuff,
  163.         lpMalloc,
  164.         &lpPropData);
  165.     if (FAILED(scode))
  166.     {
  167.         hResult = ResultFromScode(scode);
  168.         goto err;
  169.     }
  170.     /*
  171.      *  Set up initial set of properties associated with this
  172.      *  container.
  173.      */
  174.     spv[ivalPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
  175.     spv[ivalPR_DISPLAY_TYPE].Value.l = 0;           /* undefined for now */
  176.     spv[ivalPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
  177.     spv[ivalPR_OBJECT_TYPE].Value.l = MAPI_ABCONT;
  178.     spv[ivalPR_ENTRYID].ulPropTag = PR_ENTRYID;
  179.     spv[ivalPR_ENTRYID].Value.bin.cb = sizeof(DIR_ENTRYID);
  180.     spv[ivalPR_ENTRYID].Value.bin.lpb = (LPBYTE) &eidRoot;
  181.     spv[ivalPR_RECORD_KEY].ulPropTag = PR_RECORD_KEY;
  182.     spv[ivalPR_RECORD_KEY].Value.bin.cb = sizeof(DIR_ENTRYID);
  183.     spv[ivalPR_RECORD_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  184.     spv[ivalPR_SEARCH_KEY].ulPropTag = PR_SEARCH_KEY;
  185.     spv[ivalPR_SEARCH_KEY].Value.bin.cb = sizeof(DIR_ENTRYID);
  186.     spv[ivalPR_SEARCH_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
  187.     sc = ScLoadString(  IDS_ROOT_NAME,
  188.                         MAX_ROOT_NAME,
  189.                         NULL,
  190.                         hLibrary,
  191.                         (LPSTR *) &pszDisplayName);
  192.     if (FAILED(sc))
  193.     {
  194.         hResult = ResultFromScode(sc);
  195.         goto out;
  196.     }
  197.     spv[ivalPR_DISPLAY_NAME_A].ulPropTag = PR_DISPLAY_NAME_A;
  198.     spv[ivalPR_DISPLAY_NAME_A].Value.lpszA = szDisplayName;
  199.     spv[ivalPR_CONTAINER_FLAGS].ulPropTag = PR_CONTAINER_FLAGS;
  200.     spv[ivalPR_CONTAINER_FLAGS].Value.l = AB_SUBCONTAINERS;
  201.     /*
  202.      *   Set the default properties
  203.      */
  204.     hResult = lpPropData->lpVtbl->SetProps(lpPropData,
  205.         cvalMax,
  206.         spv,
  207.         NULL);
  208.     if (HR_FAILED(hResult))
  209.     {
  210.         goto err;
  211.     }
  212.     /*
  213.      *  The whole object is set READONLY thus eliminating the need to
  214.      *  set access rights for the individual properties.
  215.      */
  216.     (void) lpPropData->lpVtbl->HrSetObjAccess(lpPropData, IPROP_READONLY);
  217.     lpROOT->lpPropData = (LPMAPIPROP) lpPropData;
  218.     InitializeCriticalSection(&lpROOT->cs);
  219.     /*  We must AddRef the lpABPLogon object since we will be using it
  220.      */
  221.     lpABPLogon->lpVtbl->AddRef(lpABPLogon);
  222.     *lpulObjType = MAPI_ABCONT;
  223.     *lppROOT = (LPVOID) lpROOT;
  224. out:
  225.     DebugTraceResult(HrNewROOT, hResult);
  226.     return hResult;
  227. err:
  228.     /*
  229.      *  free the root object
  230.      */
  231.     lpFreeBuff (lpROOT);
  232.     /*
  233.      *  free the prop data
  234.      */
  235.     if (lpPropData)
  236.         lpPropData->lpVtbl->Release(lpPropData);
  237.     goto out;
  238.     
  239. }
  240. /*************************************************************************
  241.  *
  242.  *
  243.  -  SetErrorIDS
  244.  -
  245.  *  Handles remembering the last error string associated with an object.
  246.  *  This string is retrieved by the method GetLastError()
  247.  *
  248.  *
  249.  */
  250. VOID
  251. SetErrorIDS(LPVOID lpObject, HRESULT hResult, UINT ids)
  252. {
  253.     ((LPROOT) lpObject)->hResult = hResult;
  254.     ((LPROOT) lpObject)->idsLastError = ids;
  255. }
  256. /*
  257.  -  ROOT_QueryInterface
  258.  -
  259.  *  Supports QI'ing to IUnknown, IMAPIProp, IMAPIContainer, and IABContainer.
  260.  *
  261.  */
  262. STDMETHODIMP
  263. ROOT_QueryInterface(LPROOT lpROOT,
  264.                     REFIID lpiid,
  265.                     LPVOID FAR * lppNewObj)
  266. {
  267.     HRESULT hr = hrSuccess;
  268.     /*
  269.      *  Check to see if it has a lpVtbl object member
  270.      */
  271.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  272.     {
  273.         /*
  274.          *  Not large enough
  275.          */
  276.         hr = ResultFromScode(E_INVALIDARG);
  277.         goto out;
  278.     }
  279.     /*
  280.      *  Check to see that the Vtbl is large enough to include this method
  281.      */
  282.     if (IsBadReadPtr(lpROOT->lpVtbl,
  283.                      offsetof(ROOT_Vtbl, QueryInterface)+sizeof(ROOT_QueryInterface_METHOD *)))
  284.     {
  285.         /*
  286.          *  Jump table not derived from IUnknown
  287.          */
  288.         hr = ResultFromScode(E_INVALIDARG);
  289.         goto out;
  290.     }
  291.     /*
  292.      *  Check to see if the method is the same
  293.      */
  294.     if (ROOT_QueryInterface != lpROOT->lpVtbl->QueryInterface)
  295.     {
  296.         /*
  297.          *  Wrong object - the object passed doesn't have this
  298.          *  method.
  299.          */
  300.         hr = ResultFromScode(E_INVALIDARG);
  301.         goto out;
  302.     }
  303.     Validate_IUnknown_QueryInterface(lpROOT, lpiid, lppNewObj);
  304.     /*  See if the requested interface is one of ours */
  305.     if (memcmp(lpiid, &IID_IUnknown, sizeof(IID)) &&
  306.         memcmp(lpiid, &IID_IMAPIProp, sizeof(IID)) &&
  307.         memcmp(lpiid, &IID_IMAPIContainer, sizeof(IID)) &&
  308.         memcmp(lpiid, &IID_IABContainer, sizeof(IID)))
  309.     {
  310.         *lppNewObj = NULL;      /* OLE requires zeroing [out] parameter */
  311.         hr = ResultFromScode(E_NOINTERFACE);
  312.         goto out;
  313.     }
  314.     /*  We'll do this one. Bump the usage count and return a new pointer. */
  315.     EnterCriticalSection(&lpROOT->cs);
  316.     ++lpROOT->lcInit;
  317.     LeaveCriticalSection(&lpROOT->cs);
  318.     
  319.     *lppNewObj = lpROOT;
  320. out:
  321.     DebugTraceResult(ROOT_QueryInterface, hr);
  322.     return hr;
  323. }
  324. /**************************************************
  325.  *
  326.  -  ROOT_AddRef
  327.  -
  328.  *      Increment lcInit
  329.  *
  330.  */
  331. STDMETHODIMP_(ULONG) ROOT_AddRef(LPROOT lpROOT)
  332. {
  333.     LONG lcInit;
  334.     /*
  335.      *  Check to see if it has a lpVtbl object member
  336.      */
  337.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  338.     {
  339.         /*
  340.          *  Not large enough
  341.          */
  342.         return 1;
  343.     }
  344.     /*
  345.      *  Check to see that the Vtbl is large enough to include this method
  346.      */
  347.     if (IsBadReadPtr(lpROOT->lpVtbl,
  348.                      offsetof(ROOT_Vtbl, AddRef)+sizeof(ROOT_AddRef_METHOD *)))
  349.     {
  350.         /*
  351.          *  Jump table not derived from IUnknown
  352.          */
  353.         return 1;
  354.     }
  355.     /*
  356.      *  Check to see if the method is the same
  357.      */
  358.     if (ROOT_AddRef != lpROOT->lpVtbl->AddRef)
  359.     {
  360.         /*
  361.          *  Wrong object - the object passed doesn't have this
  362.          *  method.
  363.          */
  364.         return 1;
  365.     }
  366.     Validate_IUnknown_AddRef(lpROOT);
  367.     EnterCriticalSection(&lpROOT->cs);
  368.     lcInit = ++lpROOT->lcInit;
  369.     LeaveCriticalSection(&lpROOT->cs);
  370.     return lcInit;
  371. }
  372. /**************************************************
  373.  *
  374.  -  ROOT_Release
  375.  -
  376.  *      Decrement lcInit.
  377.  *      When lcInit == 0, free up the lpROOT structure
  378.  *
  379.  */
  380. STDMETHODIMP_(ULONG) ROOT_Release(LPROOT lpROOT)
  381. {
  382.     LONG lcInit;
  383.     
  384.     /*
  385.      *  Check to see if it can be a ROOT object
  386.      */
  387.     if (IsBadReadPtr(lpROOT, sizeof(ROOT)))
  388.     {
  389.         /*
  390.          *  Not large enough
  391.          */
  392.         return 1;
  393.     }
  394.     /*
  395.      *  Check to see that it's ROOTs vtbl
  396.      */
  397.     if (lpROOT->lpVtbl != &vtblROOT)
  398.     {
  399.         /*
  400.          *  Not my jump table
  401.          */
  402.         return 1;
  403.     }
  404.     Validate_IUnknown_Release(lpROOT);
  405.     EnterCriticalSection(&lpROOT->cs);
  406.     lcInit = --lpROOT->lcInit;
  407.     LeaveCriticalSection(&lpROOT->cs);
  408.     if (lcInit == 0)
  409.     {
  410.         /*
  411.          *  Delete our critical section
  412.          */
  413.         DeleteCriticalSection(&lpROOT->cs);
  414.         /*
  415.          *  Set the vtbl to NULL.  This way the client will find out
  416.          *  real fast if it's calling a method on a released object.  That is,
  417.          *  the client will crash.  Hopefully, this will happen during the
  418.          *  development stage of the client.
  419.          */
  420.         lpROOT->lpVtbl = NULL;
  421.         /*
  422.          *  free the property storage object
  423.          */
  424.         if (lpROOT->lpPropData)
  425.             lpROOT->lpPropData->lpVtbl->Release(lpROOT->lpPropData);
  426.         /*  
  427.          *  Release our reference to the ABLogon object.
  428.          */
  429.         if (lpROOT->lpABLogon)
  430.         {
  431.             lpROOT->lpABLogon->lpVtbl->Release(lpROOT->lpABLogon);
  432.             lpROOT->lpABLogon = NULL;
  433.         }
  434.         /*
  435.          *  Free the object
  436.          */
  437.         lpROOT->lpFreeBuff(lpROOT);
  438.         return 0;
  439.     }
  440.     return lcInit;
  441. }
  442. /*
  443.  -  ROOT_GetLastError
  444.  -
  445.  *      Returns a string associated with the last hResult
  446.  *  returned by the ROOT object.
  447.  *
  448.  */
  449. STDMETHODIMP
  450. ROOT_GetLastError(  LPROOT lpROOT,
  451.                     HRESULT hError,
  452.                     ULONG ulFlags,
  453.                     LPMAPIERROR FAR * lppMapiError )
  454. {
  455.     SCODE scode;
  456.     HRESULT hResult = hrSuccess;
  457.     LPSTR   lpszMessage = NULL;
  458.     /*
  459.      *  Validate parameters
  460.      */
  461.     /*
  462.      *  Check to see if it has a lpVtbl object member
  463.      */
  464.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  465.     {
  466.         /*
  467.          *  Not large enough
  468.          */
  469.         hResult = MakeResult(E_INVALIDARG);
  470.         return hResult;
  471.     }
  472.     /*
  473.      *  Check to see that the Vtbl is large enough to include this method
  474.      */
  475.     if (IsBadReadPtr(lpROOT->lpVtbl,
  476.         offsetof(ROOT_Vtbl, GetLastError)+sizeof(ROOT_GetLastError_METHOD *)))
  477.     {
  478.         /*
  479.          *  Jump table not derived from IUnknown
  480.          */
  481.         hResult = MakeResult(E_INVALIDARG);
  482.         return hResult;
  483.     }
  484.     /*
  485.      *  Check to see if the method is the same
  486.      */
  487.     if (ROOT_GetLastError != lpROOT->lpVtbl->GetLastError)
  488.     {
  489.         /*
  490.          *  Wrong object - the object passed doesn't have this
  491.          *  method.
  492.          */
  493.         hResult = ResultFromScode(E_INVALIDARG);
  494.         DebugTraceResult(ROOT_GetLastError, hResult);
  495.         return hResult;
  496.     }
  497.     Validate_IMAPIProp_GetLastError(lpROOT, hError, ulFlags, lppMapiError);
  498.     /*                              
  499.      *  NOTE:  We don't handle UNICODE yet.  Everything is
  500.      *  assumed to be working in 8-bit char mode.
  501.      */
  502.     if (ulFlags & MAPI_UNICODE)
  503.     {
  504.         hResult = ResultFromScode(MAPI_E_BAD_CHARWIDTH);
  505.         DebugTraceResult(ROOT_GetLastError, hResult);
  506.         return hResult;
  507.     }
  508.     EnterCriticalSection(&lpROOT->cs);
  509.     
  510.     if ((hError != hrSuccess) && (hError == lpROOT->hResult))
  511.     {
  512.         scode = lpROOT->lpAllocBuff( sizeof( MAPIERROR ), lppMapiError );
  513.         if ( FAILED( scode ) )      
  514.         {
  515.             hResult = ResultFromScode(scode);
  516.             goto ret;
  517.         }
  518.         
  519.         ZeroMemory( *lppMapiError, sizeof( MAPIERROR ) );
  520.         
  521.         (*lppMapiError)->ulVersion = MAPI_ERROR_VERSION;
  522.         /*
  523.          *  Get the MAPI Allocated string associated with the last error
  524.          */
  525.         scode = ScLoadString(lpROOT->idsLastError,
  526.                              MAX_ERROR_STRING_LENGTH,
  527.                              lpROOT->lpAllocBuff,
  528.                              lpROOT->hLibrary,
  529.                              &lpszMessage);
  530.         if ( FAILED( scode) )                            
  531.         {
  532.             hResult = ResultFromScode(scode);
  533.             goto ret;
  534.         }
  535.         
  536.         scode = lpROOT->lpAllocMore( lstrlenA( lpszMessage ) + 1, *lppMapiError, 
  537.             &(*lppMapiError)->lpszError );
  538.         if ( FAILED( scode ) )      
  539.         {
  540.             hResult = ResultFromScode(scode);
  541.             goto ret;
  542.         }
  543.         
  544.         lstrcpyA( (*lppMapiError)->lpszError, lpszMessage );
  545.         
  546.         
  547.     } else
  548.     {
  549.         *lppMapiError = NULL;
  550.     }
  551. ret:
  552.     if ( hResult )
  553.     {
  554.         lpROOT->lpFreeBuff( *lppMapiError );
  555.         *lppMapiError = NULL;
  556.     }
  557.     
  558.     lpROOT->lpFreeBuff( lpszMessage );
  559.     LeaveCriticalSection(&lpROOT->cs);
  560.     return hResult;
  561. }
  562. /*
  563.  -  ROOT_SaveChanges
  564.  -
  565.  *  Can't save changes on this object.
  566.  *
  567.  *
  568.  */
  569. STDMETHODIMP
  570. ROOT_SaveChanges(LPROOT lpROOT, ULONG ulFlags)
  571. {
  572.     HRESULT hResult;
  573.     ROOT_ValidateObject(ROOT_SaveChanges, lpROOT);
  574.     Validate_IMAPIProp_SaveChanges(lpROOT, ulFlags);
  575.     hResult = ResultFromScode(E_ACCESSDENIED);
  576.     DebugTraceResult(ROOT_SaveChanges, hResult);
  577.     return hResult;
  578. }
  579. /*
  580.  -  ROOT_OpenProperty
  581.  -
  582.  *
  583.  *  For this object I only need to support opening the hierarchy table.
  584.  *
  585.  */
  586. STDMETHODIMP
  587. ROOT_OpenProperty(  LPROOT lpROOT,
  588.                     ULONG ulPropTag,
  589.                     LPCIID lpiid,
  590.                     ULONG ulInterfaceOptions,
  591.                     ULONG ulFlags,
  592.                     LPUNKNOWN * lppUnk)
  593. {
  594.     HRESULT hResult;
  595.     ROOT_ValidateObject(ROOT_OpenProperty, lpROOT);
  596.     
  597.     Validate_IMAPIProp_OpenProperty(lpROOT, ulPropTag, lpiid,
  598.                             ulInterfaceOptions, ulFlags, lppUnk);
  599.     
  600.     if (ulFlags & MAPI_CREATE)
  601.     {
  602.         hResult = ResultFromScode(E_ACCESSDENIED);
  603.         goto out;       
  604.     }
  605.         
  606.     if (ulInterfaceOptions & ~MAPI_UNICODE)
  607.     {
  608.         /*
  609.          *  Only UNICODE flag should be set for any of the objects that might
  610.          *  be returned from this object.
  611.          */
  612.         
  613.         hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
  614.         goto out;
  615.     }
  616.     
  617.     if ( ulInterfaceOptions & MAPI_UNICODE )
  618.     {
  619.         hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  620.         goto out;
  621.     }
  622.     switch (ulPropTag)
  623.     {
  624.         case PR_CONTAINER_HIERARCHY:
  625.         {
  626.             /*
  627.              *  Check to see if they're expecting a IMAPITable object
  628.              */
  629.             if (memcmp(lpiid, &IID_IMAPITable, sizeof(IID)))
  630.             {
  631.                 hResult = ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
  632.                 goto out;
  633.             }
  634.             hResult = ROOT_GetHierarchyTable(lpROOT, 0, (LPMAPITABLE *) lppUnk);
  635.             goto out;
  636.         }
  637.         default:
  638.             break;
  639.     }
  640.     
  641.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  642. out:
  643.     DebugTraceResult(ROOT_OpenProperty, hResult);
  644.     return hResult;
  645. }
  646. /*************************************************************************
  647.  *
  648.  *
  649.  -  ROOT_GetContentsTable
  650.  -
  651.  *  There are no contents in the root
  652.  *
  653.  *
  654.  *
  655.  */
  656. STDMETHODIMP
  657. ROOT_GetContentsTable(  LPROOT lpROOT,
  658.                         ULONG ulFlags,
  659.                         LPMAPITABLE * lppTable)
  660. {
  661.     HRESULT hResult;
  662.     /*
  663.      *  Check to see if it has a lpVtbl object member
  664.      */
  665.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  666.     {
  667.         /*
  668.          *  Not large enough
  669.          */
  670.         hResult = MakeResult(E_INVALIDARG);
  671.         return hResult;
  672.     }
  673.     /*
  674.      *  Check to see that the Vtbl is large enough to include this method
  675.      */
  676.     if (IsBadReadPtr(lpROOT->lpVtbl,
  677.         offsetof(ROOT_Vtbl, GetContentsTable)+sizeof(ROOT_GetContentsTable_METHOD *)))
  678.     {
  679.         /*
  680.          *  Jump table not derived from IUnknown
  681.          */
  682.         hResult = MakeResult(E_INVALIDARG);
  683.         return hResult;
  684.     }
  685.     /*
  686.      *  Check to see if the method is the same
  687.      */
  688.     if (ROOT_GetContentsTable != lpROOT->lpVtbl->GetContentsTable)
  689.     {
  690.         /*
  691.          *  Wrong object - the object passed doesn't have this
  692.          *  method.
  693.          */
  694.         hResult = ResultFromScode(E_INVALIDARG);
  695.         DebugTraceResult(ROOT_GetContentsTable, hResult);
  696.         return hResult;
  697.     }
  698.     Validate_IMAPIContainer_GetContentsTable(lpROOT, ulFlags, lppTable);
  699.     
  700.     if ( ulFlags & MAPI_UNICODE )
  701.     {
  702.         hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
  703.         goto out;
  704.     }
  705.     
  706.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  707. out:
  708.     DebugTraceResult(ROOT_GetContentsTable, hResult);
  709.     return hResult;
  710. }
  711. /*
  712.  -  ROOT_GetHierarchyTable
  713.  -
  714.  *  Returns the table with just one entry in it.
  715.  *
  716.  *
  717.  *
  718.  */
  719. STDMETHODIMP
  720. ROOT_GetHierarchyTable( LPROOT lpROOT,
  721.                         ULONG ulFlags,
  722.                         LPMAPITABLE * lppTable)
  723. {
  724.     HRESULT hResult = hrSuccess;
  725.     ROOT_ValidateObject(ROOT_GetHierarchyTable, lpROOT);
  726.     Validate_IMAPIContainer_GetHierarchyTable(lpROOT, ulFlags, lppTable);
  727.     
  728.     /*
  729.      *  Since we only have one item in our hierarchy table, CONVENIENT_DEPTH
  730.      *  is equivalent to any other depth level (>1).  So, just ignore the
  731.      *  flag.  MAPI_DEFERRED_ERROR is fine.  We don't ever defer errors.
  732.      */
  733.     /*
  734.      *  Create a View Table for the hierarchy.
  735.      */
  736.     hResult = HrBuildRootHier(lpROOT->lpABLogon, lppTable);
  737.     DebugTraceResult(ROOT_GetHierarchyTable, hResult);
  738.     return hResult;
  739. }
  740. /*
  741.  -  ROOT_OpenEntry
  742.  -
  743.  *  Check parameters and use our logon object's OpenEntry method.
  744.  */
  745. STDMETHODIMP
  746. ROOT_OpenEntry(LPROOT lpROOT,
  747.     ULONG cbEntryID,
  748.     LPENTRYID lpEntryID,
  749.     LPCIID lpInterface,
  750.     ULONG ulFlags,
  751.     ULONG * lpulObjType,
  752.     LPUNKNOWN * lppUnk)
  753. {
  754.     HRESULT hResult;
  755.     
  756.     /*
  757.      *  Check to see if it has a lpVtbl object member
  758.      */
  759.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  760.     {
  761.         /*
  762.          *  No vtbl found
  763.          */
  764.         hResult = MakeResult(E_INVALIDARG);
  765.         goto out;
  766.     }
  767.     /*
  768.      *  Check to see that the Vtbl is large enough to include this method
  769.      */
  770.     if (IsBadReadPtr(lpROOT->lpVtbl,
  771.         offsetof(ROOT_Vtbl, OpenEntry)+sizeof(ROOT_OpenEntry_METHOD *)))
  772.     {
  773.         /*
  774.          *  vtbl cannot hold this method
  775.          */
  776.         hResult = MakeResult(E_INVALIDARG);
  777.         goto out;
  778.     }
  779.     /*
  780.      *  Check to see that it's the correct method
  781.      */
  782.     if (ROOT_OpenEntry != lpROOT->lpVtbl->OpenEntry)
  783.     {
  784.         /*
  785.          *  Not my vtbl
  786.          */
  787.         hResult = ResultFromScode(E_INVALIDARG);
  788.         goto out;
  789.     }
  790.     Validate_IABLogon_OpenEntry(lpROOT, cbEntryID, lpEntryID, lpInterface,
  791.                                     ulFlags, lpulObjType, lppUnk);
  792.     hResult = lpROOT->lpABLogon->lpVtbl->OpenEntry(lpROOT->lpABLogon,
  793.         cbEntryID,
  794.         lpEntryID,
  795.         lpInterface,
  796.         ulFlags,
  797.         lpulObjType,
  798.         lppUnk);
  799.     
  800. out:
  801.     DebugTraceResult(ROOT_OpenEntry, hResult);
  802.     return hResult;
  803. }
  804. /*
  805.  -  ROOT_SetSearchCriteria
  806.  -
  807.  *
  808.  *  Not implemented for this object
  809.  */
  810. STDMETHODIMP
  811. ROOT_SetSearchCriteria(LPROOT lpROOT,
  812.     LPSRestriction lpRestriction,
  813.     LPENTRYLIST lpContainerList,
  814.     ULONG ulSearchFlags)
  815. {
  816.     HRESULT hResult;
  817.     /*
  818.      *  Check to see if it has a lpVtbl object member
  819.      */
  820.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  821.     {
  822.         /*
  823.          *  Not large enough
  824.          */
  825.         hResult = MakeResult(E_INVALIDARG);
  826.         goto out;
  827.     }
  828.     /*
  829.      *  Check to see that the Vtbl is large enough to include this method
  830.      */
  831.     if (IsBadReadPtr(lpROOT->lpVtbl,
  832.         offsetof(ROOT_Vtbl, SetSearchCriteria)+sizeof(ROOT_SetSearchCriteria_METHOD *)))
  833.     {
  834.         /*
  835.          *  vtbl not large enough to support this method
  836.          */
  837.         hResult = MakeResult(E_INVALIDARG);
  838.         goto out;
  839.     }
  840.     /*
  841.      *  Check to see that it's the correct method
  842.      */
  843.     if (ROOT_SetSearchCriteria != lpROOT->lpVtbl->SetSearchCriteria)
  844.     {
  845.         /*
  846.          *  Not my vtbl
  847.          */
  848.         hResult = ResultFromScode(E_INVALIDARG);
  849.         goto out;
  850.     }
  851.     Validate_IMAPIContainer_SetSearchCriteria(lpROOT, lpRestriction,
  852.                                         lpContainerList, ulSearchFlags);
  853.     
  854.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  855. out:
  856.     DebugTraceResult(ROOT_SetSearchCriteria, hResult);
  857.     return hResult;
  858. }
  859. /*
  860.  -  ROOT_GetSearchCriteria
  861.  -
  862.  *
  863.  *  Not implemented for this object
  864.  *
  865.  */
  866. STDMETHODIMP
  867. ROOT_GetSearchCriteria(LPROOT lpROOT,
  868.     ULONG ulFlags,
  869.     LPSRestriction FAR * lppRestriction,
  870.     LPENTRYLIST FAR * lppContainerList,
  871.     ULONG FAR * lpulSearchState)
  872. {
  873.     HRESULT hResult;
  874.     /*
  875.      *  Check to see if it has a lpVtbl object member
  876.      */
  877.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  878.     {
  879.         /*
  880.          *  Not large enough
  881.          */
  882.         hResult = MakeResult(E_INVALIDARG);
  883.         return hResult;
  884.     }
  885.     /*
  886.      *  Check to see that the Vtbl is large enough to include this method
  887.      */
  888.     if (IsBadReadPtr(lpROOT->lpVtbl,
  889.         offsetof(ROOT_Vtbl, GetSearchCriteria)+sizeof(ROOT_GetSearchCriteria_METHOD *)))
  890.     {
  891.         /*
  892.          *  Jump table not derived from IUnknown
  893.          */
  894.         hResult = MakeResult(E_INVALIDARG);
  895.         return hResult;
  896.     }
  897.     /*
  898.      *  Check to see if the method is the same
  899.      */
  900.     if (ROOT_GetSearchCriteria != lpROOT->lpVtbl->GetSearchCriteria)
  901.     {
  902.         /*
  903.          *  Wrong object - the object passed doesn't have this
  904.          *  method.
  905.          */
  906.         hResult = ResultFromScode(E_INVALIDARG);
  907.         DebugTraceResult(ROOT_GetSearchCriteria, hResult);
  908.         return hResult;
  909.     }
  910.     
  911.     Validate_IMAPIContainer_GetSearchCriteria(lpROOT, ulFlags, lppRestriction,
  912.                                             lppContainerList, lpulSearchState);
  913.     
  914.     
  915.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  916.     DebugTraceResult(ROOT_GetSearchCriteria, hResult);
  917.     return hResult;
  918. }
  919. /*
  920.  -  ROOT_CreateEntry
  921.  -
  922.  *  New entries cannot be created in the root
  923.  *
  924.  */
  925. STDMETHODIMP
  926. ROOT_CreateEntry(LPROOT lpROOT,
  927.     ULONG cbEntryID,
  928.     LPENTRYID lpEntryID,
  929.     ULONG ulCreateFlags,
  930.     LPMAPIPROP FAR * lppMAPIPropEntry)
  931. {
  932.     HRESULT hResult;
  933.     /*
  934.      *  Check to see if it has a lpVtbl object member
  935.      */
  936.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  937.     {
  938.         /*
  939.          *  No vtbl found
  940.          */
  941.         hResult = MakeResult(E_INVALIDARG);
  942.         goto out;
  943.     }
  944.     /*
  945.      *  Check to see that the Vtbl is large enough to include this method
  946.      */
  947.     if (IsBadReadPtr(lpROOT->lpVtbl,
  948.                      offsetof(ROOT_Vtbl, CreateEntry)+sizeof(ROOT_CreateEntry_METHOD *)))
  949.     {
  950.         /*
  951.          *  vtbl not large enough to hold this method
  952.          */
  953.         hResult = MakeResult(E_INVALIDARG);
  954.         goto out;
  955.     }
  956.     /*
  957.      *  Check to see if the method is the same
  958.      */
  959.     if (ROOT_CreateEntry != lpROOT->lpVtbl->CreateEntry)
  960.     {
  961.         /*
  962.          *  Wrong object - the object passed doesn't have this
  963.          *  method.
  964.          */
  965.         hResult = MakeResult(E_INVALIDARG);
  966.         goto out;
  967.     }
  968.     Validate_IABContainer_CreateEntry(lpROOT, cbEntryID, lpEntryID,
  969.                                 ulCreateFlags, lppMAPIPropEntry );
  970.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  971. out:
  972.     DebugTraceResult(ROOT_CreateEntry, hResult);
  973.     return hResult;
  974. }
  975. /*
  976.  -  ROOT_CopyEntries
  977.  -
  978.  *  Entries cannot be copied into the root
  979.  *
  980.  *
  981.  *
  982.  */
  983. STDMETHODIMP
  984. ROOT_CopyEntries(LPROOT lpROOT,
  985.     LPENTRYLIST lpEntries,
  986.     ULONG ulUIParam,
  987.     LPMAPIPROGRESS lpProgress,
  988.     ULONG ulFlags)
  989. {
  990.     HRESULT hResult;
  991.     /*
  992.      *  Check to see if it has a lpVtbl object member
  993.      */
  994.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  995.     {
  996.         /*
  997.          *  No vtbl found
  998.          */
  999.         hResult = MakeResult(E_INVALIDARG);
  1000.         goto out;
  1001.     }
  1002.     /*
  1003.      *  Check to see that the Vtbl is large enough to include this method
  1004.      */
  1005.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1006.                      offsetof(ROOT_Vtbl, CopyEntries)+sizeof(ROOT_CopyEntries_METHOD *)))
  1007.     {
  1008.         /*
  1009.          *  vtbl not large enough to hold this method
  1010.          */
  1011.         hResult = MakeResult(E_INVALIDARG);
  1012.         goto out;
  1013.     }
  1014.     /*
  1015.      *  Check to see if the method is the same
  1016.      */
  1017.     if (ROOT_CopyEntries != lpROOT->lpVtbl->CopyEntries)
  1018.     {
  1019.         /*
  1020.          *  Wrong object - the object passed doesn't have this
  1021.          *  method.
  1022.          */
  1023.         hResult = MakeResult(E_INVALIDARG);
  1024.         goto out;
  1025.     }
  1026.     Validate_IABContainer_CopyEntries(lpROOT, lpEntries, ulUIParam,
  1027.                                         lpProgress, ulFlags);
  1028.     
  1029.     
  1030.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1031. out:
  1032.     DebugTraceResult(ROOT_CopyEntries, hResult);
  1033.     return hResult;
  1034. }
  1035. /*
  1036.  -  ROOT_DeleteEntries
  1037.  -
  1038.  *  Entries cannot be deleted from the root
  1039.  *
  1040.  *
  1041.  *
  1042.  */
  1043. STDMETHODIMP
  1044. ROOT_DeleteEntries(LPROOT lpROOT,
  1045.     LPENTRYLIST lpEntries,
  1046.     ULONG ulFlags)
  1047. {
  1048.     HRESULT hResult;
  1049.     /*
  1050.      *  Check to see if it has a lpVtbl object member
  1051.      */
  1052.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1053.     {
  1054.         /*
  1055.          *  No vtbl found
  1056.          */
  1057.         hResult = MakeResult(E_INVALIDARG);
  1058.         goto out;
  1059.     }
  1060.     /*
  1061.      *  Check to see that the Vtbl is large enough to include this method
  1062.      */
  1063.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1064.                      offsetof(ROOT_Vtbl, DeleteEntries)+sizeof(ROOT_DeleteEntries_METHOD *)))
  1065.     {
  1066.         /*
  1067.          *  vtbl not large enough to hold this method
  1068.          */
  1069.         hResult = MakeResult(E_INVALIDARG);
  1070.         goto out;
  1071.     }
  1072.     /*
  1073.      *  Check to see if the method is the same
  1074.      */
  1075.     if (ROOT_DeleteEntries != lpROOT->lpVtbl->DeleteEntries)
  1076.     {
  1077.         /*
  1078.          *  Wrong object - the object passed doesn't have this
  1079.          *  method.
  1080.          */
  1081.         hResult = MakeResult(E_INVALIDARG);
  1082.         goto out;
  1083.     }
  1084.     Validate_IABContainer_DeleteEntries(lpROOT, lpEntries, ulFlags);
  1085.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1086. out:
  1087.     DebugTraceResult(ROOT_DeleteEntries, hResult);
  1088.     return hResult;
  1089. }
  1090. /*
  1091.  -  ROOT_ResolveNames
  1092.  -
  1093.  *  No special case handling of resolving names within this container
  1094.  *
  1095.  *
  1096.  *
  1097.  */
  1098. STDMETHODIMP
  1099. ROOT_ResolveNames(  LPROOT          lpROOT,
  1100.                     LPSPropTagArray lptagaColSet,
  1101.                     ULONG           ulFlags,
  1102.                     LPADRLIST       lpAdrList,
  1103.                     LPFlagList      lpFlagList )
  1104. {
  1105.     HRESULT hResult;
  1106.         
  1107.     /*
  1108.      *  Check to see if it has a lpVtbl object member
  1109.      */
  1110.     if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+sizeof(ROOT_Vtbl *)))
  1111.     {
  1112.         /*
  1113.          *  No vtbl found
  1114.          */
  1115.         hResult = MakeResult(E_INVALIDARG);
  1116.         goto out;
  1117.     }
  1118.     /*
  1119.      *  Check to see that the Vtbl is large enough to include this method
  1120.      */
  1121.     if (IsBadReadPtr(lpROOT->lpVtbl,
  1122.                      offsetof(ROOT_Vtbl, ResolveNames)+sizeof(ROOT_ResolveNames_METHOD *)))
  1123.     {
  1124.         /*
  1125.          *  vtbl not large enough to hold this method
  1126.          */
  1127.         hResult = MakeResult(E_INVALIDARG);
  1128.         goto out;
  1129.     }
  1130.     /*
  1131.      *  Check to see if the method is the same
  1132.      */
  1133.     if (ROOT_ResolveNames != lpROOT->lpVtbl->ResolveNames)
  1134.     {
  1135.         /*
  1136.          *  Wrong object - the object passed doesn't have this
  1137.          *  method.
  1138.          */
  1139.         hResult = MakeResult(E_INVALIDARG);
  1140.         goto out;
  1141.     }
  1142.     CheckParameters_IABContainer_ResolveNames(lpROOT, lptagaColSet, ulFlags,
  1143.                                             lpAdrList, lpFlagList);
  1144.     
  1145.     hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
  1146. out:
  1147.     DebugTraceResult(ROOT_ResolveNames, hResult);
  1148.     return hResult;
  1149. }