📄 idispatcheximpl.h
字号:
hr = pEntry->MarkDeleted();
}
return hr;
}
/***************************************************************************
* Function: IDispatchExImpl::GetDispID()
* Args: <BSTR> bstrName - the name of the entry to get the dispid of
* <DWORD> dwGrfDex - the flags describing the comparison operator
* <DISPID*> pDispID - the out param of the dispid
* Returns: <HRESULT> Standard COM codes
* Purpose: Returns the DISPID of a given named entry
***************************************************************************/
STDMETHOD(GetDispID)(BSTR bstrName, DWORD dwGrfDex, DISPID* pDispID)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
HRESULT hr = S_OK;
// Find the entry that corresponds to this name
CDynamicDispatchEntry* pEntry = GetEntryByName(bstrName, dwGrfDex);
if (pEntry)
{
// Check to see if this item was deleted or if it should be
// added if it was
if (pEntry->IsDeleted() == false ||
(pEntry->IsDeleted() == true && dwGrfDex & fdexNameEnsure))
{
// Set the out parameter to this entry's dispid
*pDispID = pEntry->GetDispID();
}
else
{
// Tell the caller that the member was deleted
hr = DISP_E_UNKNOWNNAME;
}
}
else
{
// The entry was not found, so we need to check if we are
// supposed to automatically add it
if (dwGrfDex & fdexNameEnsure)
{
// We need to create a new entry
hr = CreateNewEntry(bstrName, pDispID, VARIANT());
}
else
{
// The item was not found
hr = DISP_E_UNKNOWNNAME;
}
}
// If can't find the dispid set the outgoing var
if (FAILED(hr))
{
// Set the dispid to Unknown
*pDispID = DISPID_UNKNOWN;
}
return hr;
}
/***************************************************************************
* Function: IDispatchExImpl::GetMemberName()
* Args: <DISPID> dispid - the dispid to get the name of
* <BSTR*> pbstrName - receives the name of the entry
* Returns: <HRESULT> Standard COM codes
* Purpose: Returns the name of a given dispid entry
***************************************************************************/
STDMETHOD(GetMemberName)(DISPID dispid, BSTR* pbstrName)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
HRESULT hr = S_OK;
// Look up the entry in the dispid map
// to find the entry that corresponds to this name
MapDispidToEntry::const_iterator it = m_mapDispidToEntry.find(dispid);
if (it != m_mapDispidToEntry.end())
{
CDynamicDispatchEntry* const pEntry = (*it).second;
// Make sure this was not deleted
if (pEntry->IsDeleted() == false)
{
// Copy the name of the entry
*pbstrName = SysAllocString(pEntry->GetName());
}
else
{
// Indicate that we do not know what is going on
hr = DISP_E_MEMBERNOTFOUND;
}
}
else
{
// Indicate that we do not know what is going on
hr = DISP_E_MEMBERNOTFOUND;
}
return hr;
}
/***************************************************************************
* Function: IDispatchExImpl::GetMemberProperties()
* Args: <DISPID> dispid - the dispid to get the name of
* <DWORD> dwGrfDex - the fetch flags (ignored)
* <BSTR*> pbstrName - receives the name of the entry
* Returns: <HRESULT> Standard COM codes
* Purpose: Returns the name of a given dispid entry
***************************************************************************/
STDMETHOD(GetMemberProperties)(DISPID dispid, DWORD, DWORD* pdwGrfDex)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
dispid;
if (pdwGrfDex)
{
// Set the flags to "can do everything"
*pdwGrfDex = grfdexPropCanAll;
}
return S_OK;
}
/***************************************************************************
* Function: IDispatchExImpl::GetNameSpaceParent()
* Args: <IUnknown**> ignored
* Returns: <HRESULT> Standard COM codes
* Purpose: Not supported
***************************************************************************/
STDMETHOD(GetNameSpaceParent)(IUnknown**)
{
return E_NOTIMPL;
}
/***************************************************************************
* Function: IDispatchExImpl::GetNextDispID()
* Args: <DWORD> dwGrfDex - the flags to fetch with
* <DISPID> dispid - the dispid the caller is currently on
* <DISPID*> pdispid - the out parameter for the next ID
* Returns: <HRESULT> Standard COM codes
* Purpose: Returns the next dispid in the list
***************************************************************************/
STDMETHOD(GetNextDispID)(DWORD dwGrfDex, DISPID dispid, DISPID* pDispID)
{
// Serialize access, since another thread might try to modify members at
// the same time
// RefCountExclusiveLock lock(m_csAccessSync);
dwGrfDex;
// We need to check for the request of the first DISPID
if (dispid != DISPID_STARTENUM)
{
// Get the next dispid
return GetNextDispID(dispid,pDispID);
}
else
{
// Find the first dispid in the map
return GetStartDispID(pDispID);
}
}
/***************************************************************************
* Function: IDispatchExImpl::InvokeEx()
* 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
* <IServiceProvider*> ignored
* Returns: <HRESULT> Standard COM codes
* Purpose: Processes the callers request to execute a method. This can be
* a property get/put or a function call.
***************************************************************************/
STDMETHOD(InvokeEx)(DISPID dispid, LCID lcid, WORD wFlags,
DISPPARAMS* pDispParams, VARIANT* pvtResult, EXCEPINFO* pExcepInfo,
IServiceProvider*)
{
// 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_FAIL;
try
{
// Check to see if we are retrieving a property
if (wFlags & DISPATCH_PROPERTYGET)
{
// Validate that they passed in a valid variant for results
// and have no parameters assigned to the "Get"
if (pvtResult &&
(pDispParams == 0 || pDispParams->cArgs == 0))
{
// Do the "Get" with the specified ID
hr = GetVariantByDispID(dispid,pvtResult);
}
else
{
// They passed in bogus stuff
hr = E_INVALIDARG;
}
}
// Check to see if we are setting a property
if (wFlags & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF))
{
// Validate that params passed in
if (pDispParams && (pDispParams->cArgs == 1 ||
(pDispParams->cNamedArgs == 1 &&
pDispParams->rgdispidNamedArgs[0] == DISPID_PROPERTYPUT)))
{
// Set the new value to the variant in the first index
hr = SetVariantByDispID(dispid,&pDispParams->rgvarg[0]);
}
else
{
// They parameter is not optional
hr = DISP_E_PARAMNOTOPTIONAL;
}
}
// Finally, check to see if we are invoking a function
if (wFlags & DISPATCH_METHOD)
{
hr = InvokeByDispID(dispid, lcid, wFlags, pDispParams, pvtResult, pExcepInfo);
}
// Check to see if this dispid is in the typeinfo object
if (hr == S_FALSE)
{
UINT nErrArg = 0;
// Forward to the type info
hr = m_pti->Invoke(this,dispid,wFlags,pDispParams,pvtResult,pExcepInfo,&nErrArg);
}
}
catch (...)
{
hr = E_UNEXPECTED;
}
return hr;
}
};
////////////////////////////////////////////////////////////////////////////////////
// Class that holds the dynamic dispatch info
class CDynamicDispatchEntry
{
private:
// For determing the type and state of the entry
bool m_bUseTypeInfo;
bool m_bIsDeleted;
VARIANT m_vtVar; // Holds the data at this entry
BSTR m_bstrName; // The name of the entry as the script engine sees it
DISPID m_dispid; // The dispid of the entry as returned to the engine
public:
// Default constructor
CDynamicDispatchEntry()
: m_bUseTypeInfo(false)
, m_bIsDeleted(true)
, m_bstrName(0)
, m_dispid(-1)
{
VariantInit(&m_vtVar);
}
// An empty entry (same as deleted)
CDynamicDispatchEntry(BSTR bstrName, DISPID dispid)
: m_bUseTypeInfo(false)
, m_bIsDeleted(true)
, m_dispid(dispid)
, m_bstrName(SysAllocString(bstrName))
{
VariantInit(&m_vtVar);
}
// A completely specified entry
CDynamicDispatchEntry(BSTR bstrName, DISPID dispid, VARIANT vtVar, bool bIsFunc = false)
: m_bUseTypeInfo(bIsFunc)
, m_bIsDeleted(false)
, m_dispid(dispid)
, m_bstrName(SysAllocString(bstrName))
{
VariantInit(&m_vtVar);
VariantCopy(&m_vtVar, &vtVar);
}
// Default destructor
virtual ~CDynamicDispatchEntry()
{
if (m_bstrName)
{
SysFreeString(m_bstrName);
m_bstrName = 0;
}
VariantClear(&m_vtVar);
}
// Attributes
inline BSTR GetName(void) { return m_bstrName; }
inline DISPID GetDispID(void) { return m_dispid; }
inline bool IsDeleted(void) { return m_bIsDeleted; }
inline bool UseTypeInfo(void) { return m_bUseTypeInfo; }
inline HRESULT GetVar(VARIANT* pvtDest)
{
// Copy our variant into the dest
if (m_vtVar.vt == VT_EMPTY)
{
pvtDest->vt = VT_EMPTY;
return S_FALSE;
}
return VariantCopy(pvtDest, &m_vtVar);
}
inline HRESULT SetVar(VARIANT* pvtSrc)
{
// If we are setting this property, it must not be deleted
m_bIsDeleted = false;
// Clear out whatever was already there
HRESULT hr = VariantClear(&m_vtVar);
if (SUCCEEDED(hr))
{
// Copy their variant into our variant
hr = VariantCopy(&m_vtVar, pvtSrc);
}
return hr;
}
// Operations
inline HRESULT MarkDeleted(void)
{
HRESULT hr = S_FALSE;
// Determine if this is a function provided by an ancestor dispatch class
if (!m_bUseTypeInfo)
{
VariantClear(&m_vtVar);
m_bIsDeleted = true;
hr = S_OK;
}
return hr;
}
};
#endif // __IDispatchExImpl_H__
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -