windows-nt/Source/XPSP1/NT/printscan/fax/exchange/ab/root.c
2020-09-26 16:20:57 +08:00

1596 lines
36 KiB
C

/***********************************************************************
*
* ROOT.C
*
*
* Sample AB Root object
* - This file contains the code for implementing the Sample AB
* root object and the hierarchy table.
*
* The Root container object is returned via an ABPOpenEntry() with a
* 0-sized entryid. It only has a limited set of properties available on
* it. The most useful method on it is GetHierarchyTable() which returns
* the root hierarchy associated with this provider.
*
* The hierarchy table has only a single row in it. The row represents the
* single .FAB file which this provider browses. If a provider wanted to
* browse many different lists, it would have multiple rows.
*
* The following routines are implemented in this file:
*
*
* To implement the Root container object:
*
* HrNewROOT
* SetErrorSz
* ROOT_QueryInterface
* ROOT_AddRef
* ROOT_Release
* ROOT_GetLastError
* ROOT_SaveChanges
* ROOT_OpenProperty
* ROOT_GetContentsTable
* ROOT_GetHierarchyTable
* ROOT_OpenEntry
* ROOT_CreateEntry
* ROOT_CopyEntries
* ROOT_DeleteEntries
* ROOT_ResolveNames
*
* Copyright 1992, 1993, 1994 Microsoft Corporation. All Rights Reserved.
*
* Revision History:
*
* When Who What
* -------- ------------------ ---------------------------------------
* 1.1.94 MAPI Original source from MAPI sample AB Provider
* 1.27.94 Yoram Yaacovi Modifications to make it an At Work Fax ABP
* 3.6.94 Yoram Yaacovi Update to MAPI build 154
* 8.3.94 Yoram Yaacovi Incorporated MAPI 304 changes
* 10.3.94 Yoram Yaacovi Incorporated MAPI 313 changes, mainly added ResolveNames
* 11.4.94 Yoram Yaacovi Incorporated MAPI 318 changes
*
***********************************************************************/
#define _FAXAB_ROOT
#include "faxab.h"
/*
* Defined in ABP.C
*/
extern MAPIUID muidABMAWF;
/*
* Root vtbl is filled in here
*/
static const ROOT_Vtbl vtblROOT =
{
ROOT_QueryInterface,
ROOT_AddRef,
ROOT_Release,
ROOT_GetLastError,
ROOT_SaveChanges,
(ROOT_GetProps_METHOD *) WRAP_GetProps,
(ROOT_GetPropList_METHOD *) WRAP_GetPropList,
ROOT_OpenProperty,
(ROOT_SetProps_METHOD *) WRAP_SetProps,
(ROOT_DeleteProps_METHOD *) WRAP_DeleteProps,
(ROOT_CopyTo_METHOD *) WRAP_CopyTo,
(ROOT_CopyProps_METHOD *) WRAP_CopyProps,
(ROOT_GetNamesFromIDs_METHOD *) WRAP_GetNamesFromIDs,
(ROOT_GetIDsFromNames_METHOD *) WRAP_GetIDsFromNames,
ROOT_GetContentsTable,
ROOT_GetHierarchyTable,
ROOT_OpenEntry,
ROOT_SetSearchCriteria,
ROOT_GetSearchCriteria,
ROOT_CreateEntry,
ROOT_CopyEntries,
ROOT_DeleteEntries,
ROOT_ResolveNames
};
/*
* Default properties in this object
*/
enum { ivalPR_DISPLAY_TYPE = 0,
ivalPR_OBJECT_TYPE,
ivalPR_ENTRYID,
ivalPR_RECORD_KEY,
ivalPR_SEARCH_KEY,
ivalPR_DISPLAY_NAME,
ivalPR_CONTAINER_FLAGS,
cvalMax };
/*
- HrNewROOT
-
* Creates a new Root Container object. This object is created
* when an lpABLogon::OpenEntry() is called with a 0-sized entryid.
*
*
*/
HRESULT
HrNewROOT( LPABCONT * lppROOT,
ULONG * lpulObjType,
LPABLOGON lpABPLogon,
LPCIID lpInterface,
HINSTANCE hLibrary,
LPALLOCATEBUFFER lpAllocBuff,
LPALLOCATEMORE lpAllocMore,
LPFREEBUFFER lpFreeBuff,
LPMALLOC lpMalloc
)
{
LPROOT lpROOT = NULL;
SCODE scode;
LPPROPDATA lpPropData = NULL;
SPropValue spv[cvalMax];
HRESULT hResult;
#ifdef UNICODE
CHAR szAnsiDisplayName[MAX_ROOT_NAME];
#endif
TCHAR szDisplayName[MAX_ROOT_NAME];
LPTSTR pszDisplayName = (LPTSTR) szDisplayName;
SCODE sc;
DIR_ENTRYID eidRoot = { {0, 0, 0, 0},
MUIDABMAWF,
MAWF_VERSION,
MAWF_DIRECTORY };
/* Do I support this interface?? */
if (lpInterface)
{
if ( memcmp(lpInterface, &IID_IUnknown, SIZEOF(IID)) &&
memcmp(lpInterface, &IID_IMAPIProp, SIZEOF(IID)) &&
memcmp(lpInterface, &IID_IMAPIContainer, SIZEOF(IID)) &&
memcmp(lpInterface, &IID_IABContainer, SIZEOF(IID))
)
{
DebugTraceSc(HrNewROOT, MAPI_E_INTERFACE_NOT_SUPPORTED);
return ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
}
}
/*
* Allocate space for the ROOT structure
*/
scode = lpAllocBuff( SIZEOF(ROOT), (LPVOID *) &lpROOT );
if (FAILED(scode))
{
hResult = ResultFromScode(scode);
goto err;
}
lpROOT->lpVtbl = &vtblROOT;
lpROOT->lcInit = 1;
lpROOT->hResult = hrSuccess;
lpROOT->idsLastError = 0;
lpROOT->hLibrary = hLibrary;
lpROOT->lpAllocBuff = lpAllocBuff;
lpROOT->lpAllocMore = lpAllocMore;
lpROOT->lpFreeBuff = lpFreeBuff;
lpROOT->lpMalloc = lpMalloc;
lpROOT->lpABLogon = lpABPLogon;
/*
* Create a property storage object
*/
scode = CreateIProp( (LPIID) &IID_IMAPIPropData,
lpAllocBuff,
lpAllocMore,
lpFreeBuff,
lpMalloc,
&lpPropData
);
if (FAILED(scode))
{
hResult = ResultFromScode(scode);
goto err;
}
/*
* Set up initial set of properties associated with this
* container.
*/
spv[ivalPR_DISPLAY_TYPE].ulPropTag = PR_DISPLAY_TYPE;
spv[ivalPR_DISPLAY_TYPE].Value.l = 0; /* undefined for now */
spv[ivalPR_OBJECT_TYPE].ulPropTag = PR_OBJECT_TYPE;
spv[ivalPR_OBJECT_TYPE].Value.l = MAPI_ABCONT;
spv[ivalPR_ENTRYID].ulPropTag = PR_ENTRYID;
spv[ivalPR_ENTRYID].Value.bin.cb = SIZEOF(DIR_ENTRYID);
spv[ivalPR_ENTRYID].Value.bin.lpb = (LPBYTE) &eidRoot;
spv[ivalPR_RECORD_KEY].ulPropTag = PR_RECORD_KEY;
spv[ivalPR_RECORD_KEY].Value.bin.cb = SIZEOF(DIR_ENTRYID);
spv[ivalPR_RECORD_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
spv[ivalPR_SEARCH_KEY].ulPropTag = PR_SEARCH_KEY;
spv[ivalPR_SEARCH_KEY].Value.bin.cb = sizeof(DIR_ENTRYID);
spv[ivalPR_SEARCH_KEY].Value.bin.lpb = (LPBYTE) &eidRoot;
sc = ScLoadString( IDS_ADDRESS_BOOK_ROOT_CONT,
MAX_ROOT_NAME,
NULL,
hLibrary,
(LPTSTR *) &pszDisplayName
);
if (FAILED(sc))
{
hResult = ResultFromScode(sc);
goto out;
}
spv[ivalPR_DISPLAY_NAME].ulPropTag = PR_DISPLAY_NAME_A;
#ifdef UNICODE
WideCharToMultiByte( CP_ACP, 0, szDisplayName, -1, szAnsiDisplayName, ARRAYSIZE(szAnsiDisplayName), NULL, NULL );
spv[ivalPR_DISPLAY_NAME].Value.lpszA = szAnsiDisplayName;
#else
spv[ivalPR_DISPLAY_NAME].Value.lpszA = szDisplayName;
#endif
spv[ivalPR_CONTAINER_FLAGS].ulPropTag = PR_CONTAINER_FLAGS;
spv[ivalPR_CONTAINER_FLAGS].Value.l = AB_SUBCONTAINERS;
/*
* Set the default properties
*/
hResult = lpPropData->lpVtbl->SetProps( lpPropData,
cvalMax,
spv,
NULL
);
if (HR_FAILED(hResult))
{
goto err;
}
(void) lpPropData->lpVtbl->HrSetObjAccess(lpPropData, IPROP_READONLY);
lpROOT->lpPropData = (LPMAPIPROP) lpPropData;
InitializeCriticalSection(&lpROOT->cs);
*lpulObjType = MAPI_ABCONT;
*lppROOT = (LPVOID) lpROOT;
out:
DebugTraceResult(HrNewROOT, hResult);
return hResult;
err:
/*
* free the root object
*/
lpFreeBuff (lpROOT);
/*
* free the prop data
*/
if (lpPropData)
lpPropData->lpVtbl->Release(lpPropData);
goto out;
}
/*************************************************************************
*
*
- SetErrorIDS
-
* Handles remembering the last error string associated with an object.
* This string is retrieved by the method GetLastError()
*
*
*/
VOID
SetErrorIDS(LPVOID lpObject, HRESULT hResult, UINT ids)
{
((LPROOT) lpObject)->hResult = hResult;
((LPROOT) lpObject)->idsLastError = ids;
}
/*
- ROOT_QueryInterface
-
* Supports QI'ing to IUnknown, IMAPIProp, IMAPIContainer, and IABContainer.
*
*/
STDMETHODIMP
ROOT_QueryInterface( LPROOT lpROOT,
REFIID lpiid,
LPVOID FAR * lppNewObj
)
{
HRESULT hr = hrSuccess;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* Not large enough
*/
hr = ResultFromScode(E_INVALIDARG);
goto out;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, QueryInterface)+SIZEOF(ROOT_QueryInterface_METHOD *)))
{
/*
* Jump table not derived from IUnknown
*/
hr = ResultFromScode(E_INVALIDARG);
goto out;
}
/*
* Check to see if the method is the same
*/
if (ROOT_QueryInterface != lpROOT->lpVtbl->QueryInterface)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hr = ResultFromScode(E_INVALIDARG);
goto out;
}
/* Check other parameters */
if ( IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)) ||
IsBadWritePtr(lppNewObj, (UINT) SIZEOF(LPVOID))
)
{
hr = ResultFromScode(E_INVALIDARG);
goto out;
}
/* See if the requested interface is one of ours */
if ( memcmp(lpiid, &IID_IUnknown, SIZEOF(IID)) &&
memcmp(lpiid, &IID_IMAPIProp, SIZEOF(IID)) &&
memcmp(lpiid, &IID_IMAPIContainer, SIZEOF(IID)) &&
memcmp(lpiid, &IID_IABContainer, SIZEOF(IID)))
{
*lppNewObj = NULL; /* OLE requires zeroing [out] parameter */
hr = ResultFromScode(E_NOINTERFACE);
goto out;
}
/* We'll do this one. Bump the usage count and return a new pointer. */
EnterCriticalSection(&lpROOT->cs);
++lpROOT->lcInit;
LeaveCriticalSection(&lpROOT->cs);
*lppNewObj = lpROOT;
out:
DebugTraceResult(ROOT_QueryInterface, hr);
return hr;
}
/**************************************************
*
- ROOT_AddRef
-
* Increment lcInit
*
*/
STDMETHODIMP_(ULONG) ROOT_AddRef(LPROOT lpROOT)
{
LONG lcInit;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* Not large enough
*/
return 1;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, AddRef)+SIZEOF(ROOT_AddRef_METHOD *)))
{
/*
* Jump table not derived from IUnknown
*/
return 1;
}
/*
* Check to see if the method is the same
*/
if (ROOT_AddRef != lpROOT->lpVtbl->AddRef)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
return 1;
}
EnterCriticalSection(&lpROOT->cs);
lcInit = ++lpROOT->lcInit;
LeaveCriticalSection(&lpROOT->cs);
return lcInit;
}
/**************************************************
*
- ROOT_Release
-
* Decrement lcInit.
* When lcInit == 0, free up the lpROOT structure
*
*/
STDMETHODIMP_(ULONG) ROOT_Release(LPROOT lpROOT)
{
LONG lcInit;
/*
* Check to see if it can be a ROOT object
*/
if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
{
/*
* Not large enough
*/
return 1;
}
/*
* Check to see that it's ROOTs vtbl
*/
if (lpROOT->lpVtbl != &vtblROOT)
{
/*
* Not my jump table
*/
return 1;
}
EnterCriticalSection(&lpROOT->cs);
lcInit = --lpROOT->lcInit;
LeaveCriticalSection(&lpROOT->cs);
if (lcInit == 0)
{
/*
* Delete our critical section
*/
DeleteCriticalSection(&lpROOT->cs);
/*
* Set the vtbl to NULL. This way the client will find out
* real fast if it's calling a method on a released object. That is,
* the client will crash. Hopefully, this will happen during the
* development stage of the client.
*/
lpROOT->lpVtbl = NULL;
/*
* free the property storage object
*/
if (lpROOT->lpPropData)
lpROOT->lpPropData->lpVtbl->Release(lpROOT->lpPropData);
/*
* Free the object
*/
lpROOT->lpFreeBuff(lpROOT);
return 0;
}
return lcInit;
}
/*
- ROOT_GetLastError
-
* Returns a string associated with the last hResult
* returned by the ROOT object.
*
*/
STDMETHODIMP
ROOT_GetLastError( LPROOT lpROOT,
HRESULT hError,
ULONG ulFlags,
LPMAPIERROR FAR * lppMapiError )
{
SCODE scode;
HRESULT hResult=hrSuccess;
LPTSTR lpszMessage = NULL;
/*
* Validate parameters
*/
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* Not large enough
*/
hResult = MakeResult(E_INVALIDARG);
return hResult;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, GetLastError)+SIZEOF(ROOT_GetLastError_METHOD *)))
{
/*
* Jump table not derived from IUnknown
*/
hResult = MakeResult(E_INVALIDARG);
return hResult;
}
/*
* Check to see if the method is the same
*/
if (ROOT_GetLastError != lpROOT->lpVtbl->GetLastError)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hResult = ResultFromScode(E_INVALIDARG);
DebugTraceResult(ROOT_GetLastError, hResult);
return hResult;
}
/*
* Validate ulFlags
*/
if (ulFlags & ~MAPI_UNICODE)
{
/*
* Unknown flag
*/
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
DebugTraceResult(ROOT_GetLastError, hResult);
return hResult;
}
/*
* NOTE: We don't handle UNICODE yet. Everything is
* assumed to be working in 8-bit char mode.
*/
if (ulFlags & MAPI_UNICODE)
{
hResult = ResultFromScode(MAPI_E_BAD_CHARWIDTH);
DebugTraceResult(ROOT_GetLastError, hResult);
return hResult;
}
/*
* Validate lppMapiError.
*/
if (IsBadWritePtr(lppMapiError, SIZEOF(LPMAPIERROR)))
{
hResult = ResultFromScode(E_INVALIDARG);
DebugTraceResult(ROOT_GetLastError, hResult);
return hResult;
}
EnterCriticalSection(&lpROOT->cs);
if ((hError != hrSuccess) && (hError == lpROOT->hResult))
{
scode = lpROOT->lpAllocBuff( SIZEOF( MAPIERROR ), lppMapiError );
if ( FAILED( scode ) )
{
hResult = ResultFromScode(scode);
goto ret;
}
RtlZeroMemory( *lppMapiError, SIZEOF( MAPIERROR ) );
(*lppMapiError)->ulVersion = MAPI_ERROR_VERSION;
/*
* Get the MAPI Allocated string associated with the last error
*/
scode = ScLoadString(lpROOT->idsLastError,
MAX_ERROR_STRING_LENGTH,
lpROOT->lpAllocBuff,
lpROOT->hLibrary,
&lpszMessage);
if ( FAILED( scode) )
{
hResult = ResultFromScode(scode);
goto ret;
}
scode = lpROOT->lpAllocMore( (lstrlen( lpszMessage ) + 1)*SIZEOF(TCHAR),
*lppMapiError,
&(*lppMapiError)->lpszError
);
if ( FAILED( scode ) )
{
hResult = ResultFromScode(scode);
goto ret;
}
lstrcpy( (*lppMapiError)->lpszError, lpszMessage );
}
else
{
*lppMapiError = NULL;
}
ret:
if ( hResult )
{
lpROOT->lpFreeBuff( *lppMapiError );
*lppMapiError = NULL;
}
lpROOT->lpFreeBuff( lpszMessage );
LeaveCriticalSection(&lpROOT->cs);
return hResult;
}
/*
- ROOT_SaveChanges
-
* Can't save changes on this object.
*
*
*/
STDMETHODIMP
ROOT_SaveChanges(LPROOT lpROOT, ULONG ulFlags)
{
HRESULT hResult;
/*
* Check to see if it's large enough to be this object
*/
if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
{
/*
* Not large enough
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
/*
* Check to see that it's ROOTs vtbl
*/
if (lpROOT->lpVtbl != &vtblROOT)
{
/*
* Not my vtbl
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (ulFlags & ~(KEEP_OPEN_READONLY|KEEP_OPEN_READONLY|FORCE_SAVE))
{
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
goto out;
}
hResult = ResultFromScode(E_ACCESSDENIED);
out:
DebugTraceResult(ROOT_SaveChanges, hResult);
return hResult;
}
/*
- ROOT_OpenProperty
-
*
* For this object I only need to support opening the hierarchy table.
*
*/
STDMETHODIMP
ROOT_OpenProperty( LPROOT lpROOT,
ULONG ulPropTag,
LPCIID lpiid,
ULONG ulInterfaceOptions,
ULONG ulFlags,
LPUNKNOWN * lppUnk)
{
HRESULT hResult;
/*
* Check to see if it's large enough to be this object
*/
if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
{
/*
* Not large enough
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
/*
* Check to see that it's ROOTs vtbl
*/
if (lpROOT->lpVtbl != &vtblROOT)
{
/*
* Not my vtbl
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN)))
{
/*
* Got to be able to return an object
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)))
{
/*
* An interface ID is required for this call.
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (ulFlags & ~(MAPI_CREATE|MAPI_MODIFY|MAPI_DEFERRED_ERRORS))
{
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
}
if (ulInterfaceOptions & ~MAPI_UNICODE)
{
/*
* Only UNICODE flag should be set for any of the objects that might
* be returned from this object.
*/
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
goto out;
}
if ( ulInterfaceOptions & MAPI_UNICODE )
{
hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
goto out;
}
if (ulFlags & MAPI_CREATE)
{
hResult = ResultFromScode(E_ACCESSDENIED);
goto out;
}
if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN)))
{
/*
* Got to be able to return an object
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (IsBadReadPtr(lpiid, (UINT) SIZEOF(IID)))
{
/*
* An interface ID is required for this call.
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (ulFlags & ~(MAPI_CREATE|MAPI_MODIFY|MAPI_DEFERRED_ERRORS))
{
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
goto out;
}
if (ulInterfaceOptions)
{
/*
* No flags should be set for any of the objects that might
* be returned from this object.
*/
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
goto out;
}
if (ulFlags & MAPI_CREATE)
{
hResult = ResultFromScode(E_ACCESSDENIED);
goto out;
}
switch (ulPropTag)
{
case PR_CONTAINER_HIERARCHY:
{
/*
* Check to see if they're expecting a IMAPITable object
*/
if (memcmp(lpiid, &IID_IMAPITable, SIZEOF(IID)))
{
hResult = ResultFromScode(MAPI_E_INTERFACE_NOT_SUPPORTED);
goto out;
}
hResult = ROOT_GetHierarchyTable(lpROOT, 0, (LPMAPITABLE *) lppUnk);
goto out;
}
default:
break;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
out:
DebugTraceResult(ROOT_OpenProperty, hResult);
return hResult;
}
/*************************************************************************
*
*
- ROOT_GetContentsTable
-
* There are no contents in the root
*
*
*
*/
STDMETHODIMP
ROOT_GetContentsTable( LPROOT lpROOT,
ULONG ulFlags,
LPMAPITABLE * lppTable)
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* Not large enough
*/
hResult = MakeResult(E_INVALIDARG);
return hResult;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, GetContentsTable)+SIZEOF(ROOT_GetContentsTable_METHOD *)))
{
/*
* Jump table not derived from IUnknown
*/
hResult = MakeResult(E_INVALIDARG);
return hResult;
}
/*
* Check to see if the method is the same
*/
if (ROOT_GetContentsTable != lpROOT->lpVtbl->GetContentsTable)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hResult = ResultFromScode(E_INVALIDARG);
DebugTraceResult(ROOT_GetContentsTable, hResult);
return hResult;
}
if (ulFlags & ~(MAPI_DEFERRED_ERRORS|MAPI_ASSOCIATED|MAPI_UNICODE))
{
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
goto out;
}
if ( ulFlags & MAPI_UNICODE )
{
hResult = ResultFromScode( MAPI_E_BAD_CHARWIDTH );
goto out;
}
if (!IsBadWritePtr(lppTable, SIZEOF(LPMAPITABLE)))
{
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
out:
DebugTraceResult(ROOT_GetContentsTable, hResult);
return hResult;
}
/*
- ROOT_GetHierarchyTable
-
* Returns the table with just one entry in it.
*
*
*
*/
STDMETHODIMP
ROOT_GetHierarchyTable( LPROOT lpROOT,
ULONG ulFlags,
LPMAPITABLE * lppTable)
{
HRESULT hResult = hrSuccess;
/*
* Validate parameters
*/
/*
* Check to see if it's large enough to be this object
*/
if (IsBadReadPtr(lpROOT, SIZEOF(ROOT)))
{
/*
* Not large enough
*/
hResult = ResultFromScode(E_INVALIDARG);
DebugTraceResult(ROOT_GetHierarchyTable, hResult);
return hResult;
}
/*
* Check to see that it's ROOTs vtbl
*/
if (lpROOT->lpVtbl != &vtblROOT)
{
/*
* Not my vtbl
*/
hResult = ResultFromScode(E_INVALIDARG);
DebugTraceResult(ROOT_GetHierarchyTable, hResult);
return hResult;
}
/*
* See if I can set the return variable
*/
if (IsBadWritePtr(lppTable, SIZEOF(LPMAPITABLE)))
{
hResult = ResultFromScode(E_INVALIDARG);
DebugTraceResult(ROOT_GetHierarchyTable, hResult);
return hResult;
}
/*
* Check flags:
* The only valid flags are CONVENIENT_DEPTH and MAPI_DEFERRED_ERRORS
*/
if (ulFlags & ~(CONVENIENT_DEPTH | MAPI_DEFERRED_ERRORS))
{
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
DebugTraceResult(ROOT_GetHierarchyTable, hResult);
return hResult;
}
/*
* Since we only have one item in our hierarchy table, CONVENIENT_DEPTH
* is equivalent to any other depth level (>1). So, just ignore the
* flag. MAPI_DEFERRED_ERROR is fine. We don't ever defer errors.
*/
/*
* Create a View Table for the hierarchy.
*/
hResult = HrBuildRootHier(lpROOT->lpABLogon, lppTable);
DebugTraceResult(ROOT_GetHierarchyTable, hResult);
return hResult;
}
/*
- ROOT_OpenEntry
-
* Check parameters and use our logon object's OpenEntry method.
*/
STDMETHODIMP
ROOT_OpenEntry( LPROOT lpROOT,
ULONG cbEntryID,
LPENTRYID lpEntryID,
LPCIID lpInterface,
ULONG ulFlags,
ULONG * lpulObjType,
LPUNKNOWN * lppUnk
)
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* No vtbl found
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, OpenEntry)+SIZEOF(ROOT_OpenEntry_METHOD *)))
{
/*
* vtbl cannot hold this method
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that it's the correct method
*/
if (ROOT_OpenEntry != lpROOT->lpVtbl->OpenEntry)
{
/*
* Not my vtbl
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
/*
* Check the entryID
*/
if ( cbEntryID &&
(cbEntryID < (ULONG) SIZEOF(ENTRYID) ||
IsBadReadPtr(lpEntryID, (UINT) cbEntryID))
)
{
/*
* Malformed entryID
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (lpInterface && IsBadReadPtr(lpInterface, SIZEOF(IID)))
{
/*
* malformed interface id
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (ulFlags & ~(MAPI_DEFERRED_ERRORS))
{
/*
* Flags are set that I have no idea about
*/
hResult = ResultFromScode(MAPI_E_UNKNOWN_FLAGS);
goto out;
}
if (IsBadWritePtr(lpulObjType, SIZEOF(ULONG)))
{
/*
* Can't return an object type
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
if (IsBadWritePtr(lppUnk, SIZEOF(LPUNKNOWN)))
{
/*
* Can't return an object
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
hResult = lpROOT->lpABLogon->lpVtbl->OpenEntry(lpROOT->lpABLogon,
cbEntryID,
lpEntryID,
lpInterface,
ulFlags,
lpulObjType,
lppUnk);
out:
DebugTraceResult(ROOT_OpenEntry, hResult);
return hResult;
}
/*
- ROOT_SetSearchCriteria
-
*
* Not implemented for this object
*/
STDMETHODIMP
ROOT_SetSearchCriteria( LPROOT lpROOT,
LPSRestriction lpRestriction,
LPENTRYLIST lpContainerList,
ULONG ulSearchFlags
)
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* Not large enough
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, SetSearchCriteria)+SIZEOF(ROOT_SetSearchCriteria_METHOD *)))
{
/*
* vtbl not large enough to support this method
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that it's the correct method
*/
if (ROOT_SetSearchCriteria != lpROOT->lpVtbl->SetSearchCriteria)
{
/*
* Not my vtbl
*/
hResult = ResultFromScode(E_INVALIDARG);
goto out;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
out:
DebugTraceResult(ROOT_SetSearchCriteria, hResult);
return hResult;
}
/*
- ROOT_GetSearchCriteria
-
*
* Not implemented for this object
*
*/
STDMETHODIMP
ROOT_GetSearchCriteria( LPROOT lpROOT,
ULONG ulFlags,
LPSRestriction FAR * lppRestriction,
LPENTRYLIST FAR * lppContainerList,
ULONG FAR * lpulSearchState
)
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* Not large enough
*/
hResult = MakeResult(E_INVALIDARG);
return hResult;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, GetSearchCriteria)+SIZEOF(ROOT_GetSearchCriteria_METHOD *)))
{
/*
* Jump table not derived from IUnknown
*/
hResult = MakeResult(E_INVALIDARG);
return hResult;
}
/*
* Check to see if the method is the same
*/
if (ROOT_GetSearchCriteria != lpROOT->lpVtbl->GetSearchCriteria)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hResult = ResultFromScode(E_INVALIDARG);
DebugTraceResult(ROOT_GetSearchCriteria, hResult);
return hResult;
}
if ( ulFlags & ~(MAPI_UNICODE) )
{
hResult = ResultFromScode( MAPI_E_UNKNOWN_FLAGS );
return hResult;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
DebugTraceResult(ROOT_GetSearchCriteria, hResult);
return hResult;
}
/*
- ROOT_CreateEntry
-
* New entries cannot be created in the root
*
*/
STDMETHODIMP
ROOT_CreateEntry( LPROOT lpROOT,
ULONG cbEntryID,
LPENTRYID lpEntryID,
ULONG ulCreateFlags,
LPMAPIPROP FAR * lppMAPIPropEntry
)
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* No vtbl found
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, CreateEntry)+SIZEOF(ROOT_CreateEntry_METHOD *)))
{
/*
* vtbl not large enough to hold this method
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see if the method is the same
*/
if (ROOT_CreateEntry != lpROOT->lpVtbl->CreateEntry)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
out:
DebugTraceResult(ROOT_CreateEntry, hResult);
return hResult;
}
/*
- ROOT_CopyEntries
-
* Entries cannot be copied into the root
*
*
*
*/
STDMETHODIMP
ROOT_CopyEntries( LPROOT lpROOT,
LPENTRYLIST lpEntries,
ULONG ulUIParam,
LPMAPIPROGRESS lpProgress,
ULONG ulFlags
)
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* No vtbl found
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, CopyEntries)+SIZEOF(ROOT_CopyEntries_METHOD *)))
{
/*
* vtbl not large enough to hold this method
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see if the method is the same
*/
if (ROOT_CopyEntries != lpROOT->lpVtbl->CopyEntries)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
out:
DebugTraceResult(ROOT_CopyEntries, hResult);
return hResult;
}
/*
- ROOT_DeleteEntries
-
* Entries cannot be deleted from the root
*
*
*
*/
STDMETHODIMP
ROOT_DeleteEntries( LPROOT lpROOT,
LPENTRYLIST lpEntries,
ULONG ulFlags)
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* No vtbl found
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, DeleteEntries)+SIZEOF(ROOT_DeleteEntries_METHOD *)))
{
/*
* vtbl not large enough to hold this method
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see if the method is the same
*/
if (ROOT_DeleteEntries != lpROOT->lpVtbl->DeleteEntries)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
out:
DebugTraceResult(ROOT_DeleteEntries, hResult);
return hResult;
}
/*
- ROOT_ResolveNames
-
* No special case handling of resolving names within this container
*
*
*
*/
STDMETHODIMP
ROOT_ResolveNames( LPROOT lpROOT,
LPSPropTagArray lptagaColSet,
ULONG ulFlags,
LPADRLIST lpAdrList,
LPFlagList lpFlagList )
{
HRESULT hResult;
/*
* Check to see if it has a lpVtbl object member
*/
if (IsBadReadPtr(lpROOT, offsetof(ROOT, lpVtbl)+SIZEOF(ROOT_Vtbl *)))
{
/*
* No vtbl found
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see that the Vtbl is large enough to include this method
*/
if (IsBadReadPtr(lpROOT->lpVtbl,
offsetof(ROOT_Vtbl, ResolveNames)+SIZEOF(ROOT_ResolveNames_METHOD *)))
{
/*
* vtbl not large enough to hold this method
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
/*
* Check to see if the method is the same
*/
if (ROOT_ResolveNames != lpROOT->lpVtbl->ResolveNames)
{
/*
* Wrong object - the object passed doesn't have this
* method.
*/
hResult = MakeResult(E_INVALIDARG);
goto out;
}
hResult = ResultFromScode(MAPI_E_NO_SUPPORT);
out:
DebugTraceResult(ROOT_ResolveNames, hResult);
return hResult;
}
#undef _FAXAB_ROOT