// --ruleclsf.cpp-------------------------------------------------------------
//
// Implementation file for the CFolderRules control class and its
//class factory.
//
// The CFolderRules class is a controlling class. It controls the
// CIExchangeFolderRules class (which implements the IExchangeFolderRules
// programatic interface defined in rulecls.h). When we add automation
// capabilities, it will also control the standard OLE dispatch interface
// for this class.
//
// Copyright (C) Microsoft Corp. 1986-1996. All rights reserved.
//
// ---------------------------------------------------------------------------
#include "edk.h"
#include "srowlst.h"
#include "ruleclsf.h"
#include "ruleclsf.chk"
// $--CFolderRules::CFolderRules-----------------------------------------------
//
// DESCRIPTION:CFolderRules controlling class class constructor.
//
// INPUT:None.
//
// RETURNS: Ptr to new CFolderRules instance.
//
//-----------------------------------------------------------------------------
CFolderRules::CFolderRules()
{
DEBUGPRIVATE("CFolderRules::CFolderRules().\n");
m_hr =NOERROR; // no error so far
m_refs =1;
m_lpMapiTbl =NULL;
m_lpExchTbl =NULL;
m_lpFolder =NULL;
m_prog_interface = new CIExchangeFolderRules;
if ( m_prog_interface == NULL )
{
m_hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Set programming interface ptr to this object.
m_prog_interface->m_pFR = this;
cleanup:
; // no operation
}
// $--CFolderRules::~CFolderRules----------------------------------------------
//
// DESCRIPTION:CFolderRules controlling class class destructor.
//
// INPUT:None.
//
// RETURNS: Nothing.
//
//-----------------------------------------------------------------------------
CFolderRules::~CFolderRules()
{
DEBUGPRIVATE("CFolderRules::~CFolderRules().\n");
delete m_prog_interface;
ULRELEASE(m_lpMapiTbl);
ULRELEASE(m_lpExchTbl);
ULRELEASE(m_lpFolder);
}
// $--CFolderRules::Create-----------------------------------------------------
//
// DESCRIPTION:Create a new instance of the CFolderRules object.
//Also take care of setting up the standard OLE dispatch
//object pointer for the new instance.
//
// INPUT:None.
//
// RETURNS: Ptr to new CFolderRules object on success; NULL otherwise.
//
//-----------------------------------------------------------------------------
CFolderRules FAR *
CFolderRules::Create()// RETURNS CFolderRules pointer
{
CFolderRules FAR *pFolderRules =NULL;
DEBUGPRIVATE("CFolderRules::Create().\n");
// Create an instance of CFolderRules.
pFolderRules = new FAR CFolderRules();
if (pFolderRules == NULL)
{
HR_LOG(E_FAIL);
pFolderRules = NULL;
goto cleanup;
}
if (FAILED(pFolderRules->m_hr))
{
HR_LOG(pFolderRules->m_hr);
ULRELEASE(pFolderRules);
goto cleanup;
}
cleanup:
return pFolderRules;
}
// $--CFolderRules::HrGetProviders---------------------------------------------
//
// DESCRIPTION:Get an array of rules provider names.
//
// OUTPUT:
//
// [lpcProviders]-- Pointer to ulong that will be set to count of
// providers on successful return.
//[lpppszProviders]-- Pointer to array of string pointers that will be set
// to point at an array of provider name string pointers
// on successful return.
//
// RETURNS: NOERRORif successful;
//E_OUTOFMEMORYif not enough memory;
// E_FAIL otherwise.
//
//-----------------------------------------------------------------------------
HRESULT
CFolderRules::HrGetProviders(// RETURNS: HRESULT
OUTLPULONGlpcProviders,// count of providers
OUTLPSTR FAR * FAR *lpppszProviders// ptr to array of providers
)
{
HRESULThr =NOERROR;
DEBUGPRIVATE("CFolderRules::HrGetProviders()\n");
if (m_lpFolder == NULL)
hr = E_FAIL;
else
hr = m_SRowLst.HrGetProviders(lpcProviders, lpppszProviders);
RETURN(hr);
}
// $--CFolderRules::HrOpen-----------------------------------------------------
//
// DESCRIPTION:Open the object on a rules folder.
//
// INPUT:
//
// [lpMDB]-- Ptr to MDB object containing the rules folder.
// [cbentryid]-- Number of bytes in folder's entry identifier.
// [lpentryid]-- Folder's entry identifier.
// [lpszProvider]-- Provider for rules. Multiple providers may have
// rules on a folder. The IExchangeFolderRules interface
// provides access to the rules associated with a
// single specified provider. May be NULL, in which case
// a provider list can be obtained, but no other operations
// are possible.
//
// RETURNS: NOERROR on success;
// E_INVALIDARG if bad input;
//E_NOINTERFACE if the rules table does not exist on the folder;
// E_FAIL otherwise.
//
//-----------------------------------------------------------------------------
HRESULT
CFolderRules::HrOpen(// RETURNS: HRESULT
INLPMDBlpMDB,// MDB store pointer
INULONGcbentryid, // # bytes in entry ID
INLPENTRYIDlpentryid,// entry ID pointer
INLPSTRlpszProvider// provider name
)
{
HRESULThr =NOERROR;
LPSRowSetlpRows =NULL;
ULONGulObjType =0;
// NOTE: The following order of properties is assumed by lots
// of other code (CFolderRules, CIExchangeFolderRules).
SizedSPropTagArray(C_RULEPROPS, rgPropTag) =
{
C_RULEPROPS,
{
PR_RULE_SEQUENCE,
PR_RULE_STATE,
PR_RULE_CONDITION,
PR_RULE_ACTIONS,
PR_RULE_PROVIDER,
PR_RULE_LEVEL,
PR_RULE_NAME
}
};
DEBUGPRIVATE("CFolderRules::HrOpen()\n");
hr = CHK_CFolderRules_HrOpen(lpMDB, cbentryid, lpentryid, lpszProvider);
if (FAILED(hr))
RETURN(hr);
// Don't allow multiple opens on one object.
if (m_lpFolder != NULL)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Open the folder.
hr = lpMDB->OpenEntry(cbentryid,
lpentryid,
NULL,
MAPI_BEST_ACCESS|
MAPI_DEFERRED_ERRORS,
&ulObjType,
(LPUNKNOWN FAR *)&m_lpFolder);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
if (ulObjType != MAPI_FOLDER)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Open the RULE table property on the folder. The returned table
// pointer may be used to get a MAPI table for reading and it can
// also be used to modify the rules table. If there is no rules table,
// this call will fail with E_NOINTERFACE.
hr = m_lpFolder->OpenProperty(PR_RULES_TABLE,
(LPGUID)&IID_IExchangeModifyTable,
0,
MAPI_DEFERRED_ERRORS,
(LPUNKNOWN FAR *)&m_lpExchTbl);
if (FAILED(hr))
goto cleanup;
// Open a MAPI table on the RULE table property. This table can be
// read to determine what the rules table looks like.
hr = m_lpExchTbl->GetTable(0, &m_lpMapiTbl);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Select columns needed.
hr = m_lpMapiTbl->SetColumns((LPSPropTagArray)&rgPropTag, 0);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Get all the rows in the table up to EDK_MAX_QUERY_ROWS. If there
// are more rows than this, fail with MAPI_E_TABLE_TOO_BIG.
hr = m_lpMapiTbl->QueryRows(EDK_MAX_QUERY_ROWS, 0, &lpRows);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// Check to be sure that table is not bigger than EDK_MAX_QUERY_ROWS.
// We do this by checking whether or not the cursor is positioned at
// the end of the table.
if (lpRows->cRows == EDK_MAX_QUERY_ROWS)
{
ULONGulRow =0;
ULONGulNumerator =0;
ULONGulDenominator =0;
hr = m_lpMapiTbl->QueryPosition(&ulRow, &ulNumerator, &ulDenominator);
if (FAILED(hr))
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
// SeekRowApprox() doc states that if ulNumerator == ulDenominator, you
// are at the end of the table.
if (ulNumerator != ulDenominator)
{
hr = HR_LOG(E_FAIL);
goto cleanup;
}
}
// Store the table in a sorted and more manageable format.
hr = m_SRowLst.HrInitialize(lpszProvider, lpRows);
if (FAILED(hr))
goto cleanup;
// NOTE - lpRows gets deallocated in SROWLST::Initialize(). We NULL it
// out here as a safeguard against future use.
lpRows = NULL;
cleanup:
if (FAILED(hr))
{
ULRELEASE(m_lpMapiTbl);
ULRELEASE(m_lpExchTbl);
ULRELEASE(m_lpFolder);
}
RETURN(hr);
}
//---------------------------------------------------------------------
// IUnknown methods
//---------------------------------------------------------------------
// $--CFolderRules::QueryInterface---------------------------------------------
//
// DESCRIPTION:Return pointer to object which implements the desired
//interface, if this object supports the interface.
//
// INPUT:
//
// [riid]-- Reference to interface identifier of desired interface.
//
// [ppv]-- Ptr to object which supports interface. NULL if none.
//
// RETURNS: NOERROR if successful;
//E_INVALIDARG if bad input.
//E_NOINTERFACE if interface isn't supported.
//
// Interfaces supported:
//
// IUnknown
// IDispatch (eventually)
// IExchangeFolderRules
// DFolderRules (eventually)
//
//-----------------------------------------------------------------------------
STDMETHODIMP
CFolderRules::QueryInterface(// RETURNS: HRESULT
INREFIIDriid, // interface ID reference
OUTLPVOID FAR *ppv // pointer to interface pointer
)
{
HRESULT hr =NOERROR;
DEBUGPRIVATE("CFolderRules::QueryInterface().\n");
hr = CHK_CFolderRules_QueryInterface(riid, ppv);
if (FAILED(hr))
RETURN(hr);
*ppv = NULL;
// See if we support the requested interface.
if (IsEqualIID(riid, IID_IUnknown)) // IUnknown interface is ourself
{
*ppv = this; // Return ourself
}
else if (IsEqualIID(riid, IID_IExchangeFolderRules))
{
// User wants our programatic interface.
*ppv = m_prog_interface;
}
else
{
// We don't support the requested interface.
*ppv = NULL;
hr = HR_LOG(E_NOINTERFACE);
goto cleanup;
}
// If we reach this point, no error occurred. Increment reference count.
AddRef();
cleanup:
RETURN(hr);
}
// $--CFolderRules::AddRef-----------------------------------------------------
//
// DESCRIPTION:Increment the reference count on this object.
//
// INPUT:None.
//
// RETURNS: New reference count.
//
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CFolderRules::AddRef()// RETURNS: ULONG
{
DEBUGPRIVATE("CFolderRules::AddRef().\n");
ASSERTERROR(m_refs, "Bad m_refs.");
m_refs++;
return m_refs;
}
// $--CFolderRules::Release----------------------------------------------------
//
// DESCRIPTION:Decrement the reference count on this object. If the
//reference count reaches 0, destroy this object.
//
// INPUT:None.
//
// RETURNS: New reference count.
//
//-----------------------------------------------------------------------------
STDMETHODIMP_(ULONG)
CFolderRules::Release()// RETURNS: ULONG
{
ULONG ulRefCount =0;
DEBUGPRIVATE("CFolderRules::Release().\n");
ASSERTERROR(m_refs, "Bad m_refs.");
m_refs--;
if (!m_refs)
{
delete this;
ulRefCount = 0;
}
else
{
ulRefCount = m_refs;
}
return ulRefCount;
}