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

📄 oledisp1.cpp

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 CPP
📖 第 1 页 / 共 3 页
字号:
		case VT_BSTR:
			pvarResult->bstrVal = (BSTR)dwResult;
			break;
		case VT_ERROR:
			pvarResult->scode = (SCODE)dwResult;
			break;
		case VT_BOOL:
			V_BOOL(pvarResult) = (VARIANT_BOOL)((BOOL)dwResult != 0 ? -1 : 0);
			break;
		case VT_VARIANT:
			*pvarResult = result.vaVal;
			break;
		case VT_DISPATCH:
		case VT_UNKNOWN:
			pvarResult->punkVal = (LPUNKNOWN)dwResult; // already AddRef
			break;
		}
	}
	else
	{
		// free unused return value
		switch (vtResult)
		{
		case VT_BSTR:
			if ((BSTR)dwResult != NULL)
				SysFreeString((BSTR)dwResult);
			break;
		case VT_DISPATCH:
		case VT_UNKNOWN:
			if ((LPUNKNOWN)dwResult != 0)
				((LPUNKNOWN)dwResult)->Release();
			break;
		case VT_VARIANT:
			VariantClear(&result.vaVal);
			break;
		}
	}

	return S_OK;    // success!
}

/////////////////////////////////////////////////////////////////////////////
// CCmdTarget::XDispatch implementation

STDMETHODIMP_(ULONG) COleDispatchImpl::AddRef()
{
	METHOD_PROLOGUE_EX_(CCmdTarget, Dispatch)
	return pThis->ExternalAddRef();
}

STDMETHODIMP_(ULONG) COleDispatchImpl::Release()
{
	METHOD_PROLOGUE_EX_(CCmdTarget, Dispatch)
	return pThis->ExternalRelease();
}

STDMETHODIMP COleDispatchImpl::QueryInterface(REFIID iid, LPVOID* ppvObj)
{
	METHOD_PROLOGUE_EX_(CCmdTarget, Dispatch)
	return pThis->ExternalQueryInterface(&iid, ppvObj);
}

STDMETHODIMP COleDispatchImpl::GetTypeInfoCount(UINT* pctinfo)
{
	METHOD_PROLOGUE_EX_(CCmdTarget, Dispatch)
	*pctinfo = pThis->GetTypeInfoCount();
	return S_OK;
}

STDMETHODIMP COleDispatchImpl::GetTypeInfo(UINT itinfo, LCID lcid,
	ITypeInfo** pptinfo)
{
	METHOD_PROLOGUE_EX_(CCmdTarget, Dispatch)
	ASSERT_POINTER(pptinfo, LPTYPEINFO);

	if (itinfo != 0)
		return E_INVALIDARG;

	IID iid;
	if (!pThis->GetDispatchIID(&iid))
		return E_NOTIMPL;

	return pThis->GetTypeInfoOfGuid(lcid, iid, pptinfo);
}

STDMETHODIMP COleDispatchImpl::GetIDsOfNames(
	REFIID riid, LPOLESTR* rgszNames, UINT cNames, LCID lcid, DISPID* rgdispid)
{
	METHOD_PROLOGUE_EX_(CCmdTarget, Dispatch)
	ASSERT_POINTER(rgszNames, char*);
	ASSERT_POINTER(rgdispid, DISPID);

	USES_CONVERSION;

	// check arguments
	if (riid != IID_NULL)
		return DISP_E_UNKNOWNINTERFACE;

	SCODE sc;
	LPTYPEINFO lpTypeInfo = NULL;
	if (lcid != 0 && SUCCEEDED(sc = GetTypeInfo(0, lcid, &lpTypeInfo)))
	{
		// For non-zero lcid, let typeinfo do the work (when available)
		ASSERT(lpTypeInfo != NULL);
		sc = lpTypeInfo->GetIDsOfNames(rgszNames, cNames, rgdispid);
		lpTypeInfo->Release();
		if (sc == TYPE_E_ELEMENTNOTFOUND)
			sc = DISP_E_UNKNOWNNAME;
	}
	else
	{
		// fill in the member name
		const AFX_DISPMAP* pDerivMap = pThis->GetDispatchMap();
		rgdispid[0] = pThis->MemberIDFromName(pDerivMap, OLE2CT(rgszNames[0]));
		if (rgdispid[0] == DISPID_UNKNOWN)
			sc = DISP_E_UNKNOWNNAME;
		else
			sc = S_OK;

		// argument names are always DISPID_UNKNOWN (for this implementation)
		for (UINT nIndex = 1; nIndex < cNames; nIndex++)
			rgdispid[nIndex] = DISPID_UNKNOWN;
	}

	return sc;
}

STDMETHODIMP COleDispatchImpl::Invoke(
	DISPID dispid, REFIID riid, LCID lcid,
	WORD wFlags, DISPPARAMS* pDispParams, LPVARIANT pvarResult,
	LPEXCEPINFO pexcepinfo, UINT* puArgErr)
{
	METHOD_PROLOGUE_EX_(CCmdTarget, Dispatch)
	ASSERT_NULL_OR_POINTER(pvarResult, VARIANT);
	ASSERT_NULL_OR_POINTER(pexcepinfo, EXCEPINFO);
	ASSERT_NULL_OR_POINTER(puArgErr, UINT);

	// make sure pvarResult is initialized
	if (pvarResult != NULL)
		AfxVariantInit(pvarResult);

	// check arguments
	if (riid != IID_NULL)
		return DISP_E_UNKNOWNINTERFACE;

	// allow subclass to disable Invoke
	if (!pThis->IsInvokeAllowed(dispid))
		return E_UNEXPECTED;

	// copy param block for safety
	DISPPARAMS params = *pDispParams;
	pDispParams = &params;

	// most of the time, named arguments are not supported
	if (pDispParams->cNamedArgs != 0)
	{
		// only special PROPERTYPUT named argument is allowed
		if (pDispParams->cNamedArgs != 1 ||
			pDispParams->rgdispidNamedArgs[0] != DISPID_PROPERTYPUT)
		{
			return DISP_E_NONAMEDARGS;
		}
	}

	// get entry for the member ID
	const AFX_DISPMAP_ENTRY* pEntry = pThis->GetDispEntry(dispid);
	if (pEntry == NULL)
		return DISP_E_MEMBERNOTFOUND;

	// treat member calls on properties just like property get/set
	if ((wFlags == DISPATCH_METHOD) &&
		((pEntry->pfn == NULL && pEntry->pfnSet == NULL) ||
		 (pEntry->pfn == NULL && pEntry->pfnSet != NULL) ||
		 (pEntry->pfn != NULL && pEntry->pfnSet != NULL)))
	{
		// the entry describes a property but a method call is being
		//  attempted -- change it to a property get/set based on the
		//  number of parameters being passed.
		wFlags &= ~DISPATCH_METHOD;
		UINT nExpectedArgs = pEntry->lpszParams != NULL ?
			(UINT)lstrlenA(pEntry->lpszParams) : 0;
		if (pDispParams->cArgs <= nExpectedArgs)
		{
			// no extra param -- so treat as property get
			wFlags |= DISPATCH_PROPERTYGET;
		}
		else
		{
			// extra params -- treat as property set
			wFlags |= DISPATCH_PROPERTYPUTREF;
			pDispParams->cNamedArgs = 1;
		}
	}

	// property puts should not require a return value
	if (wFlags & (DISPATCH_PROPERTYPUTREF|DISPATCH_PROPERTYPUT))
	{
		pvarResult = NULL;
		// catch attempt to do property set on method
		if (pEntry->pfn != NULL && pEntry->pfnSet == NULL)
			return DISP_E_TYPEMISMATCH;
	}

	UINT uArgErr = (UINT)-1;    // no error yet
	SCODE sc = S_OK;

	// handle special cases of DISPATCH_PROPERTYPUT
	VARIANT* pvarParamSave = NULL;
	VARIANT vaParamSave;
	vaParamSave.vt = VT_ERROR;

	DISPPARAMS paramsTemp;
	VARIANT vaTemp;
	AfxVariantInit(&vaTemp);

	if (wFlags == DISPATCH_PROPERTYPUT && dispid != DISPID_VALUE)
	{
		// with PROPERTYPUT (no REF), the right hand side may need fixup
		if (pDispParams->rgvarg[0].vt == VT_DISPATCH &&
			pDispParams->rgvarg[0].pdispVal != NULL)
		{
			// remember old value for restore later
			pvarParamSave = &pDispParams->rgvarg[0];
			vaParamSave = pDispParams->rgvarg[0];
			AfxVariantInit(&pDispParams->rgvarg[0]);

			// get default value of right hand side
			memset(&paramsTemp, 0, sizeof(DISPPARAMS));
			sc = vaParamSave.pdispVal->Invoke(
				DISPID_VALUE, riid, lcid, DISPATCH_PROPERTYGET, &paramsTemp,
				&pDispParams->rgvarg[0], pexcepinfo, puArgErr);
		}

		// special handling for PROPERTYPUT (no REF), left hand side
		if (sc == S_OK && pEntry->vt == VT_DISPATCH)
		{
			memset(&paramsTemp, 0, sizeof(DISPPARAMS));

			// parameters are distributed depending on what the Get expects
			if (pEntry->lpszParams == NULL)
			{
				// paramsTemp is already setup for no parameters
				sc = Invoke(dispid, riid, lcid,
					DISPATCH_PROPERTYGET|DISPATCH_METHOD, &paramsTemp,
					&vaTemp, pexcepinfo, puArgErr);
				if (sc == S_OK &&
					(vaTemp.vt != VT_DISPATCH || vaTemp.pdispVal == NULL))
					sc = DISP_E_TYPEMISMATCH;
				else if (sc == S_OK)
				{
					ASSERT(vaTemp.vt == VT_DISPATCH && vaTemp.pdispVal != NULL);
					// we have the result, now call put on the default property
					sc = vaTemp.pdispVal->Invoke(
						DISPID_VALUE, riid, lcid, wFlags, pDispParams,
						pvarResult, pexcepinfo, puArgErr);
				}
			}
			else
			{
				// pass all but named params
				paramsTemp.rgvarg = &pDispParams->rgvarg[1];
				paramsTemp.cArgs = pDispParams->cArgs - 1;
				sc = Invoke(dispid, riid, lcid,
					DISPATCH_PROPERTYGET|DISPATCH_METHOD, &paramsTemp,
					&vaTemp, pexcepinfo, puArgErr);
				if (sc == S_OK &&
					(vaTemp.vt != VT_DISPATCH || vaTemp.pdispVal == NULL))
					sc = DISP_E_TYPEMISMATCH;
				else if (sc == S_OK)
				{
					ASSERT(vaTemp.vt == VT_DISPATCH && vaTemp.pdispVal != NULL);

					// we have the result, now call put on the default property
					paramsTemp = *pDispParams;
					paramsTemp.cArgs = paramsTemp.cNamedArgs;
					sc = vaTemp.pdispVal->Invoke(
						DISPID_VALUE, riid, lcid, wFlags, &paramsTemp,
						pvarResult, pexcepinfo, puArgErr);
				}
			}
			VariantClear(&vaTemp);

			if (sc != DISP_E_MEMBERNOTFOUND)
				goto Cleanup;
		}

		if (sc != S_OK && sc != DISP_E_MEMBERNOTFOUND)
			goto Cleanup;
	}

	// ignore DISP_E_MEMBERNOTFOUND from above
	ASSERT(sc == DISP_E_MEMBERNOTFOUND || sc == S_OK);

	// undo implied default value on right hand side on error
	if (sc != S_OK && pvarParamSave != NULL)
	{
		// default value stuff failed -- so try without default value
		pvarParamSave = NULL;
		VariantClear(&pDispParams->rgvarg[0]);
		pDispParams->rgvarg[0] = vaParamSave;
	}
	sc = S_OK;

	// check arguments against this entry
	UINT nOrigArgs; nOrigArgs = pDispParams->cArgs;
	if (wFlags & (DISPATCH_PROPERTYGET|DISPATCH_METHOD))
	{
		if (!(wFlags & DISPATCH_METHOD))
		{
			if (pEntry->vt == VT_EMPTY)
				return DISP_E_BADPARAMCOUNT;
			if (pvarResult == NULL)
				return DISP_E_PARAMNOTOPTIONAL;
		}
		if (pEntry->lpszParams == NULL && pDispParams->cArgs > 0)
		{
			if (pEntry->vt != VT_DISPATCH)
				return DISP_E_BADPARAMCOUNT;

			// it is VT_DISPATCH property/method but too many arguments supplied
			// transfer those arguments to the default property of the return value
			// after getting the return value from this call.  This is referred
			// to as collection lookup.
			pDispParams->cArgs = 0;
			if (pvarResult == NULL)
				pvarResult = &vaTemp;
		}
	}

	// make sure that parameters are not passed to a simple property
	if (pDispParams->cArgs > 1 &&
		(wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF)) &&
		pEntry->pfn == NULL)
	{
		sc = DISP_E_BADPARAMCOUNT;
		goto Cleanup;
	}

	// make sure that pvarResult is set for simple property get
	if (pEntry->pfn == NULL && pDispParams->cArgs == 0 && pvarResult == NULL)
	{
		sc = DISP_E_PARAMNOTOPTIONAL;
		goto Cleanup;
	}

	// make sure IsExpectingResult returns FALSE as appropriate
	BOOL bResultExpected;
	bResultExpected = pThis->m_bResultExpected;
	pThis->m_bResultExpected = pvarResult != NULL;

	TRY
	{
		if (pEntry->pfn == NULL)
		{
			// do standard property get/set
			if (pDispParams->cArgs == 0)
				pThis->GetStandardProp(pEntry, pvarResult, &uArgErr);
			else
				sc = pThis->SetStandardProp(pEntry, pDispParams, &uArgErr);
		}
		else
		{
			// do standard method call
			sc = pThis->CallMemberFunc(pEntry, wFlags,
				pvarResult, pDispParams, &uArgErr);
		}
	}
	CATCH(COleException, e)
	{
		sc = e->m_sc;
		DELETE_EXCEPTION(e);
	}
	AND_CATCH_ALL(e)
	{
		AFX_MANAGE_STATE(pThis->m_pModuleState);
		if (pexcepinfo != NULL)
		{
			// fill exception with translation of MFC exception
			COleDispatchException::Process(pexcepinfo, e);
		}
		DELETE_EXCEPTION(e);
		sc = DISP_E_EXCEPTION;
	}
	END_CATCH_ALL

	// restore original m_bResultExpected flag
	pThis->m_bResultExpected = bResultExpected;

	// handle special DISPATCH_PROPERTYGET collection lookup case
	if (sc == S_OK && nOrigArgs > pDispParams->cArgs)
	{
		ASSERT(wFlags & (DISPATCH_PROPERTYGET|DISPATCH_METHOD));
		ASSERT(pvarResult != NULL);
		// must be non-NULL dispatch, otherwise type mismatch
		if (pvarResult->vt != VT_DISPATCH || pvarResult->pdispVal == NULL)
		{
			sc = DISP_E_TYPEMISMATCH;
			goto Cleanup;
		}
		// otherwise, valid VT_DISPATCH was returned
		pDispParams->cArgs = nOrigArgs;
		LPDISPATCH lpTemp = pvarResult->pdispVal;
		if (pvarResult != &vaTemp)
			AfxVariantInit(pvarResult);
		else
			pvarResult = NULL;
		sc = lpTemp->Invoke(DISPID_VALUE, riid, lcid, wFlags,
			pDispParams, pvarResult, pexcepinfo, puArgErr);
		lpTemp->Release();
	}

Cleanup:
	// restore any arguments which were modified
	if (pvarParamSave != NULL)
	{
		VariantClear(&pDispParams->rgvarg[0]);
		pDispParams->rgvarg[0] = vaParamSave;
	}

	// fill error argument if one is available
	if (sc != S_OK && puArgErr != NULL && uArgErr != -1)
		*puArgErr = uArgErr;

	return sc;
}

/////////////////////////////////////////////////////////////////////////////
// IDispatch specific exception

COleDispatchException::~COleDispatchException()
{
	// destructor code is compiler generated
}

void PASCAL COleDispatchException::Process(
	EXCEPINFO* pInfo, const CException* pAnyException)
{
	USES_CONVERSION;

	ASSERT(AfxIsValidAddress(pInfo, sizeof(EXCEPINFO)));
	ASSERT_VALID(pAnyException);

	// zero default & reserved members
	memset(pInfo, 0, sizeof(EXCEPINFO));

	// get description based on type of exception
	TCHAR szDescription[256];
	LPCTSTR pszDescription = szDescription;
	if (pAnyException->IsKindOf(RUNTIME_CLASS(COleDispatchException)))
	{
		// specific IDispatch style exception
		COleDispatchException* e = (COleDispatchException*)pAnyException;
		pszDescription = e->m_strDescription;
		pInfo->wCode = e->m_wCode;
		pInfo->dwHelpContext = e->m_dwHelpContext;
		pInfo->scode = e->m_scError;

		// propagate source and help file if present
		if (!e->m_strHelpFile.IsEmpty())
			pInfo->bstrHelpFile = ::SysAllocString(T2COLE(e->m_strHelpFile));
		if (!e->m_strSource.IsEmpty())
			pInfo->bstrSource = ::SysAllocString(T2COLE(e->m_strSource));
	}
	else if (pAnyException->IsKindOf(RUNTIME_CLASS(CMemoryException)))
	{
		// failed memory allocation
		AfxLoadString(AFX_IDP_FAILED_MEMORY_ALLOC, szDescription);
		pInfo->wCode = AFX_IDP_FAILED_MEMORY_ALLOC;
	}
	else
	{
		// other unknown/uncommon error
		AfxLoadString(AFX_IDP_INTERNAL_FAILURE, szDescription);
		pInfo->wCode = AFX_IDP_INTERNAL_FAILURE;
	}

	// build up rest of EXCEPINFO struct
	pInfo->bstrDescription = ::SysAllocString(T2COLE(pszDescription));
	if (pInfo->bstrSource == NULL)
		pInfo->bstrSource = ::SysAllocString(T2COLE(AfxGetAppName()));
	if (pInfo->bstrHelpFile == NULL && pInfo->dwHelpContext != 0)
		pInfo->bstrHelpFile = ::SysAllocString(T2COLE(AfxGetApp()->m_pszHelpFilePath));
}

COleDispatchException::COleDispatchException(
	LPCTSTR lpszDescription, UINT nHelpID, WORD wCode)
{
	m_dwHelpContext = nHelpID != 0 ? HID_BASE_DISPATCH+nHelpID : 0;
	m_wCode = wCode;
	if (lpszDescription != NULL)
		m_strDescription = lpszDescription;
	m_scError = wCode != 0 ? NOERROR : E_UNEXPECTED;
}

COleDispatchException::GetErrorMessage(LPTSTR lpszError, UINT nMaxError,
		PUINT pnHelpContext)
{
	ASSERT(lpszError != NULL && AfxIsValidString(lpszError, nMaxError));

	if (pnHelpContext != NULL)
		*pnHelpContext = 0;

	lstrcpyn(lpszError, m_strDescription, nMaxError);
	return TRUE;
}

void AFXAPI AfxThrowOleDispatchException(WORD wCode, LPCTSTR lpszDescription,
	UINT nHelpID)
{
	ASSERT(AfxIsValidString(lpszDescription));
	THROW(new COleDispatchException(lpszDescription, nHelpID, wCode));
}

void AFXAPI AfxThrowOleDispatchException(WORD wCode, UINT nDescriptionID,
	UINT nHelpID)
{
	TCHAR szBuffer[256];
	VERIFY(AfxLoadString(nDescriptionID, szBuffer) != 0);
	if (nHelpID == -1)
		nHelpID = nDescriptionID;
	THROW(new COleDispatchException(szBuffer, nHelpID, wCode));
}

#ifdef AFX_INIT_SEG
#pragma code_seg(AFX_INIT_SEG)
#endif

IMPLEMENT_DYNAMIC(COleDispatchException, CException)

/////////////////////////////////////////////////////////////////////////////

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -