/*********************************************************************** * * 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