📄 idispatcheximpl.h
字号:
/***************************************************************************
* Function: IDispatchExImpl::InvokeByDispID()
* Args: <DISPID> dispid - the dispid of the entry to invoke
* <LCID> lcid - the locale id
* <WORD> wFlags - calling flags
* <DISPPARAMS*> pDispParams - the dispparams of the method
* <VARIANT*> pvtResult - the variant holding the result
* <EXCEPINFO*> pExcepInfo - the exception info pointer
* Returns: <HRESULT> Standard COM codes
* Purpose: Invokes the LPDISPATCH held in the dispid passed in
***************************************************************************/
HRESULT InvokeByDispID(DISPID dispid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pvtResult, EXCEPINFO* pExcepInfo)
{
HRESULT hr = DISP_E_MEMBERNOTFOUND;
// Look up the entry in the dispid map
MapDispidToEntry::const_iterator it = m_mapDispidToEntry.find(dispid);
if (it != m_mapDispidToEntry.end())
{
CDynamicDispatchEntry* const pEntry = (*it).second;
// Get the variant that holds the dispatch
VARIANT vtDisp;
hr = pEntry->GetVar(&vtDisp);
if (SUCCEEDED(hr))
{
// Check to see that the item is not deleted
if (pEntry->IsDeleted() == false)
{
UINT nErrArg = 0;
// Determine if this is an exposed method or a
// dynamically added property/method
if (pEntry->UseTypeInfo() == false)
{
// Call the Zeroth member of the dispatch object
// This should be the only function contained in
// the dispatch object
hr = vtDisp.pdispVal->Invoke(0,IID_NULL,lcid,wFlags,
pDispParams,pvtResult,pExcepInfo,&nErrArg);
}
else
{
// This should be forwarded to the TypeInfo
hr = S_FALSE;
}
}
else
{
// Can't invoke one that was deleted
hr = DISP_E_MEMBERNOTFOUND;
}
// Clear the variable
VariantClear(&vtDisp);
}
}
return hr;
}
public:
// These two methods allow for access to the members via name
// Add entries into your IDL if you want this functionality
/***************************************************************************
* Function: IDispatchExImpl::Get()
* Args: <BSTR> bstrVarName - the name of the variable to fetch
* <VARIANT*> pvtVar - the object that will get the data
* <DWORD> dwGrfDex - the flags describing the comparison operator
* Returns: <HRESULT> Standard COM codes
* Purpose: Retrieves the variable by name. This is an optional method of
* getting properties.
***************************************************************************/
STDMETHOD(Get)(BSTR bstrVarName, VARIANT* pvtVar,
DWORD dwGrfDex = fdexNameCaseSensitive)
{
// Serialize access, since another thread might try to modify members at
// the same time we are accessing them
// RefCountExclusiveLock lock(m_csAccessSync);
HRESULT hr = S_OK;
// Get the entry of the specified named var
CDynamicDispatchEntry* pEntry = GetEntryByName(bstrVarName, dwGrfDex);
if (pEntry)
{
// Check to see if this is an ITypeInfo member
if (pEntry->UseTypeInfo() == false)
{
// Copy the variant
hr = pEntry->GetVar(pvtVar);
}
else
{
// Build the params that we want to use
DISPPARAMS dispparams = { NULL, NULL, 0, 0 };
// Forward to the type info
hr = m_pti->Invoke(this, pEntry->GetDispID(), DISPATCH_PROPERTYGET | DISPATCH_METHOD,
&dispparams, pvtVar, 0, 0);
}
}
else
{
// Clear the variable
hr = VariantClear(pvtVar);
}
return hr;
}
/***************************************************************************
* Function: IDispatchExImpl::Set()
* Args: <BSTR> bstrVarName - the name of the variable to fetch
* <VARIANT*> pvtVar - the object that will give the data
* <BOOL> bAutoAdd - if the variable not found, add it automatically
* <DWORD> dwGrfDex - the flags describing the comparison operator
* Returns: <HRESULT> Standard COM codes
* Purpose: Sets the variable by name. This is an optional method of
* setting properties. NOTE: This must be declared as propertyput
* in the IDL file or the typeinfo won't process it.
***************************************************************************/
STDMETHOD(Set)(BSTR bstrVarName, VARIANT* pvtVar, BOOL bAutoAdd = TRUE,
DWORD dwGrfDex = fdexNameCaseSensitive)
{
// Serialize access, since another thread might try to modify members at
// the same time we are accessing them
// RefCountExclusiveLock lock(m_csAccessSync);
HRESULT hr = E_INVALIDARG;
// Get the entry of the specified named var
CDynamicDispatchEntry* pEntry = GetEntryByName(bstrVarName, dwGrfDex);
if (pEntry)
{
// Check to see if this is an ITypeInfo member
if (pEntry->UseTypeInfo() == false)
{
// Copy the variant
hr = pEntry->SetVar(pvtVar);
}
else
{
// Named var of type put
DISPID dispid = DISPID_PROPERTYPUT;
// Build the params that we want to use
DISPPARAMS dispparams = { pvtVar, &dispid, 1, 1 };
// Forward to the type info
hr = m_pti->Invoke(this, pEntry->GetDispID(), DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF,
&dispparams, 0, 0, 0);
}
}
else
{
// The entry was not found. We may create it here!
if (bAutoAdd)
{
DISPID dispid = 0;
hr = CreateNewEntry(bstrVarName, &dispid, *pvtVar);
}
}
return hr;
}
public:
IDispatchExImpl() : m_dispidNext(DISPID_START)
{
}
virtual ~IDispatchExImpl()
{
// Need to iterate through the dispid map and delete the Entry pointers
MapNameToEntry::iterator it, itEnd(m_mapNameToEntry.end());
for (it = m_mapNameToEntry.begin(); it != itEnd; ++it)
{
if ((*it).first) // BSTR
{
SysFreeString((*it).first);
}
if ((*it).second) // Entry pointer
{
delete (*it).second;
}
}
for (it = m_mapCaselessNameToEntry.begin(); it != m_mapCaselessNameToEntry.end(); ++it)
{
if ((*it).first) // BSTR
{
SysFreeString((*it).first);
}
}
}
// --- IUnknown methods ---
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
void **ppvObject)
{
if (IID_IDispatchEx == riid)
{
*ppvObject = static_cast<IDispatchEx*> (this);
AddRef();
return S_OK;
}
else
{
return __base::QueryInterface(riid, ppvObject);
}
}
// --- IDispatch methods ---
/***************************************************************************
* Function: IDispatchExImpl::GetTypeInfoCount()
* Args: <UINT*> pnTypeInfoCount - always set to one
* Returns: <HRESULT> Standard COM codes
* Purpose: Tells the caller the number of type info interfaces that we
* support.
***************************************************************************/
STDMETHOD(GetTypeInfoCount)(UINT* pnTypeInfoCount)
{
// This call is inherently thread safe so no synchronization is needed
// Validate the pointer passed in
// We only return type info for the derived class
*pnTypeInfoCount = 1;
return S_OK;
}
/***************************************************************************
* Function: IDispatchExImpl::GetTypeInfo()
* Args: <UINT> nTypeInfoIndex - must be 1
* <LCID> ignored
* <ITypeInfo**> ppTypeInfo - the pointer that gets a copy of ours
* Returns: <HRESULT> Standard COM codes
* Purpose: This method returns a pointer to the derived class' type info
***************************************************************************/
STDMETHOD(GetTypeInfo)(UINT nTypeInfoIndex, LCID, ITypeInfo** ppTypeInfo)
{
// This call is inherently thread safe so no synchronization is needed
// Validate the pointer passed in
nTypeInfoIndex;
*ppTypeInfo = m_pti;
m_pti->AddRef();
return S_OK;
}
/***************************************************************************
* Function: IDispatchExImpl::GetIDsOfNames()
* Args: <REFIID> reserved, so ignored
* <LPOLESTR*> szNameArray - the array of names to map to DISPIDs
* <UINT> nNames - the number of names in the array
* <LCID> lcid - the locale indicator to look up the names for
* <DISPID*> parrDispIDs - the array of DISPIDs to fill in
* Returns: <HRESULT> Standard COM codes
* Purpose: Determines the DISPID of each named property or method.
***************************************************************************/
STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR* szNameArray, UINT nNames, LCID,
DISPID* parrDispIDs)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
HRESULT hr = S_OK;
// Loop through the arrays letting GetDispID do the work
for (UINT index = 0; index < nNames && SUCCEEDED(hr); ++index)
{
// Pass the call on to GetDispID
// Since the caller is using IDispatch to get the ID and
// not the Ex version to get it, assume case insensitivity
hr = GetDispID(szNameArray[index], fdexNameCaseInsensitive, &parrDispIDs[index]);
}
return hr;
}
/***************************************************************************
* Function: IDispatchExImpl::Invoke()
* Args: <DISPID> dispid - the dispid of the entry to invoke
* <REFIID> ignored
* <LCID> lcid - the locale id
* <WORD> wFlags - calling flags
* <DISPPARAMS*> pDispParams - the dispparams of the method
* <VARIANT*> pvtResult - the variant holding the result
* <EXCEPINFO*> pExcepInfo - the exception info pointer
* <UINT*> pnArgErr - the number of arguments that had errors
* Returns: <HRESULT> Standard COM codes
* Purpose: Calls the method of a dispatch id
***************************************************************************/
STDMETHOD(Invoke)(DISPID dispIdMember, REFIID, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pVarResult, EXCEPINFO* pExcepInfo,
UINT* pnArgErr)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
if (pnArgErr)
{
// Zero it out
*pnArgErr = 0;
}
return InvokeEx(dispIdMember, lcid, wFlags, pDispParams, pVarResult, pExcepInfo, 0);
}
// --- IDispatchEx methods ---
/***************************************************************************
* Function: IDispatchExImpl::DeleteMemberByDispID()
* Args: <DISPID> dispid - the dispid to delete from the dynamic props
* Returns: <HRESULT> Standard COM codes
* Purpose: Deletes a property/method from the dynamic list
***************************************************************************/
STDMETHOD(DeleteMemberByDispID)(DISPID dispid)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
HRESULT hr = S_OK;
// Get the pointer to the entry
MapDispidToEntry::const_iterator it = m_mapDispidToEntry.find(dispid);
if (it != m_mapDispidToEntry.end())
{
CDynamicDispatchEntry* const pEntry = (*it).second;
hr = pEntry->MarkDeleted();
}
return hr;
}
/***************************************************************************
* Function: IDispatchExImpl::DeleteMemberByName()
* Args: <BSTR> bstrName - the name of the entry to delete
* <DWORD> dwGrfDex - the flags describing the comparison operator
* Returns: <HRESULT> Standard COM codes
* Purpose: Deletes a property/method from the dynamic list
***************************************************************************/
STDMETHOD(DeleteMemberByName)(BSTR bstrName, DWORD dwGrfDex)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
HRESULT hr = S_OK;
// Get a pointer to the entry if valid
CDynamicDispatchEntry* pEntry = GetEntryByName(bstrName, dwGrfDex);
if (pEntry)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -