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

📄 idispatcheximpl.h

📁 《脚本驱动的应用软件开发方法与实践》源码
💻 H
📖 第 1 页 / 共 3 页
字号:

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