⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 idispatcheximpl.h

📁 《脚本驱动的应用软件开发方法与实践》源码
💻 H
📖 第 1 页 / 共 3 页
字号:
			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 + -