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

📄 oledisp1.cpp

📁 c语言编程软件vc6.0中文绿色版_vc6.0官方下载
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	nCount = (nCount + (_ALIGN_STACK-1)) & ~(_ALIGN_STACK-1);
#endif

	// count bytes in return value
	ASSERT((UINT)vtResult < _countof(_afxRetVal));
	nCount += _afxRetVal[vtResult];
#ifdef _ALIGN_STACK
	nCount = (nCount + (_ALIGN_STACK-1)) & ~(_ALIGN_STACK-1);
#endif

	// count arguments
	ASSERT(pbParams != NULL);
	while (*pbParams != 0)
	{
		if (*pbParams != VT_MFCMARKER)
		{
			// align if necessary
			// get and add appropriate byte count
			const UINT* rgnBytes;
			if (*pbParams & VT_MFCBYREF)
				rgnBytes = _afxByRef;
			else
				rgnBytes = _afxByValue;
			ASSERT((*pbParams & ~VT_MFCBYREF) < _countof(_afxByValue));
#ifdef _ALIGN_DOUBLES
			// align doubles on 8 byte for some platforms
			if (*pbParams == VT_R8)
				nCount = (nCount + _ALIGN_DOUBLES-1) & ~(_ALIGN_DOUBLES-1);
#endif
			nCount += rgnBytes[*pbParams & ~VT_MFCBYREF];
#ifdef _ALIGN_STACK
			nCount = (nCount + (_ALIGN_STACK-1)) & ~(_ALIGN_STACK-1);
#endif
		}
		++pbParams;
	}
#if defined(_ALIGN_DOUBLES) && defined(_SHADOW_DOUBLES)
	// align doubles on 8 byte for some platforms
	nCount = (nCount + _ALIGN_DOUBLES-1) & ~(_ALIGN_DOUBLES-1);
#endif
	return nCount;
}

// push arguments on stack appropriate for C++ call (compiler dependent)
#ifndef _SHADOW_DOUBLES
SCODE CCmdTarget::PushStackArgs(BYTE* pStack, const BYTE* pbParams,
	void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams, UINT* puArgErr,
	VARIANT* rgTempVars)
#else
SCODE CCmdTarget::PushStackArgs(BYTE* pStack, const BYTE* pbParams,
	void* pResult, VARTYPE vtResult, DISPPARAMS* pDispParams, UINT* puArgErr,
	VARIANT* rgTempVars, UINT nSizeArgs)
#endif
{
	ASSERT(pStack != NULL);
	ASSERT(pResult != NULL);
	ASSERT(pDispParams != NULL);
	ASSERT(puArgErr != NULL);

#ifdef _SHADOW_DOUBLES
	double* pDoubleShadow = (double*)(pStack + nSizeArgs);
	double* pDoubleShadowMax = pDoubleShadow + _SHADOW_DOUBLES;
#endif

	// C++ member functions use the __thiscall convention, where parameters
	//  are pushed last to first.  Assuming the stack grows down, this means
	//  that the first parameter is at the lowest memory address in the
	//  stack frame and the last parameter is at the highest address.


#ifdef _RETVAL_FIRST
	// push any necessary return value stuff on the stack (pre args)
	//  (an ambient pointer is pushed to stack relative data)
	if (vtResult == VT_CY || vtResult == VT_VARIANT)
	{
#ifdef _ALIGN_STACK
		ASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
#endif
		*(_STACK_PTR*)pStack = (_STACK_PTR)pResult;
		pStack += sizeof(_STACK_PTR);
#ifdef _ALIGN_STACK
		ASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
#endif
	}
#endif //_RETVAL_FIRST

	// push the 'this' pointer
#ifdef _ALIGN_STACK
	ASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
#endif
	*(_STACK_PTR*)pStack = (_STACK_PTR)this;
	pStack += sizeof(_STACK_PTR);
#ifdef _ALIGN_STACK
	ASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
#endif

#ifndef _RETVAL_FIRST
	// push any necessary return value stuff on the stack (post args)
	//  (an ambient pointer is pushed to stack relative data)
	if (vtResult == VT_CY || vtResult == VT_VARIANT)
	{
#ifdef _ALIGN_STACK
		ASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
#endif
		*(_STACK_PTR*)pStack = (_STACK_PTR)pResult;
		pStack += sizeof(_STACK_PTR);
#ifdef _ALIGN_STACK
		ASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
#endif
	}
#endif //!_RETVAL_FIRST

	// push the arguments (first to last, low address to high address)
	VARIANT* pArgs = pDispParams->rgvarg;
	BOOL bNamedArgs = FALSE;
	int iArg = pDispParams->cArgs; // start with positional arguments
	int iArgMin = pDispParams->cNamedArgs;

	ASSERT(pbParams != NULL);
	for (const BYTE* pb = pbParams; *pb != '\0'; ++pb)
	{
		--iArg; // move to next arg

		// convert MFC parameter type to IDispatch VARTYPE
		VARTYPE vt = *pb;
		if (vt != VT_MFCMARKER && (vt & VT_MFCBYREF))
			vt = (VARTYPE)((vt & ~VT_MFCBYREF) | VT_BYREF);

		VARIANT* pArg;
		if (iArg >= iArgMin)
		{
			// hit named args before using all positional args?
			if (vt == VT_MFCMARKER)
				break;

			// argument specified by caller -- use it
			pArg = &pArgs[iArg];
			if (vt != VT_VARIANT && vt != pArg->vt)
			{
				// argument is not of appropriate type, attempt to coerce it
				VARIANT* pArgTemp = &rgTempVars[iArg];
				ASSERT(pArgTemp->vt == VT_EMPTY);
#if defined(_UNICODE) || defined(OLE2ANSI)
				VARTYPE vtTarget = vt;
#else
				VARTYPE vtTarget = (VARTYPE) ((vt == VT_BSTRA) ? VT_BSTR : vt);
#endif
				if (pArg->vt != vtTarget)
				{
					SCODE sc = VariantChangeType(pArgTemp, pArg, 0, vtTarget);
					if (FAILED(sc))
					{
						TRACE0("Warning: automation argument coercion failed.\n");
						*puArgErr = iArg;
						return sc;
					}
					ASSERT(pArgTemp->vt == vtTarget);
				}

#if !defined(_UNICODE) && !defined(OLE2ANSI)
				if (vt == VT_BSTRA)
				{
					if (pArg->vt != vtTarget)
					{
						// coerce above created a new string
						// convert it to ANSI and free it
						ASSERT(pArgTemp->vt == VT_BSTR);
						BSTR bstrW = pArgTemp->bstrVal;
						pArgTemp->bstrVal = AfxBSTR2ABSTR(bstrW);
						SysFreeString(bstrW);
					}
					else
					{
						// convert the string to ANSI from original
						pArgTemp->bstrVal = AfxBSTR2ABSTR(pArg->bstrVal);
						pArgTemp->vt = VT_BSTR;
					}
					vt = VT_BSTR;
				}
#endif
				pArg = pArgTemp;
			}
		}
		else
		{
			if (vt == VT_MFCMARKER)
			{
				// start processing named arguments
				iArg = pDispParams->cNamedArgs;
				iArgMin = 0;
				bNamedArgs = TRUE;
				continue;
			}

			if (bNamedArgs || vt != VT_VARIANT)
				break;  // function not expecting optional argument

			// argument not specified by caller -- provide default variant
			static VARIANT vaDefault;   // Note: really is 'const'
			vaDefault.vt = VT_ERROR;
			vaDefault.scode = DISP_E_PARAMNOTFOUND;
			pArg = &vaDefault;
		}

		// push parameter value on the stack
		switch (vt)
		{
		// by value parameters
		case VT_UI1:
			*(_STACK_INT*)pStack = pArg->bVal; // 'BYTE' is passed as 'int'
			pStack += sizeof(_STACK_INT);
			break;
		case VT_I2:
			*(_STACK_INT*)pStack = pArg->iVal;
			pStack += sizeof(_STACK_INT);   // 'short' is passed as 'int'
			break;
		case VT_I4:
			*(_STACK_LONG*)pStack = pArg->lVal;
			pStack += sizeof(_STACK_LONG);
			break;
		case VT_R4:
			*(_STACK_FLOAT*)pStack = (_STACK_FLOAT)pArg->fltVal;
			pStack += sizeof(_STACK_FLOAT);
#ifdef _SHADOW_DOUBLES
			if (pDoubleShadow < pDoubleShadowMax)
				*pDoubleShadow++ = (double)pArg->fltVal;
#endif
			break;
		case VT_R8:
#ifdef _ALIGN_DOUBLES
			// align doubles on 8 byte for some platforms
			pStack = (BYTE*)(((DWORD)pStack + _ALIGN_DOUBLES-1) &
				~(_ALIGN_DOUBLES-1));
#endif
			*(_STACK_DOUBLE*)pStack = (_STACK_DOUBLE)pArg->dblVal;
			pStack += sizeof(_STACK_DOUBLE);
#ifdef _SHADOW_DOUBLES
			if (pDoubleShadow < pDoubleShadowMax)
				*pDoubleShadow++ = pArg->dblVal;
#endif
			break;
		case VT_DATE:
#ifdef _ALIGN_DOUBLES
			// align doubles on 8 byte for some platforms
			pStack = (BYTE*)(((DWORD)pStack + _ALIGN_DOUBLES-1) &
				~(_ALIGN_DOUBLES-1));
#endif
			*(_STACK_DOUBLE*)pStack = (_STACK_DOUBLE)pArg->date;
			pStack += sizeof(_STACK_DOUBLE);
#ifdef _SHADOW_DOUBLES
			if (pDoubleShadow < pDoubleShadowMax)
				*pDoubleShadow++ = pArg->date;
#endif
			break;
		case VT_CY:
			*(CY*)pStack = pArg->cyVal;
			pStack += sizeof(CY);
			break;
		case VT_BSTR:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->bstrVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_ERROR:
			*(_STACK_LONG*)pStack = (_STACK_LONG)pArg->scode;
			pStack += sizeof(_STACK_LONG);
			break;
		case VT_BOOL:
			*(_STACK_LONG*)pStack = (_STACK_LONG)(V_BOOL(pArg) != 0);
			pStack += sizeof(_STACK_LONG);
			break;
		case VT_VARIANT:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_DISPATCH:
		case VT_UNKNOWN:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->punkVal;
			pStack += sizeof(_STACK_PTR);
			break;

		// by reference parameters
		case VT_UI2|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pbVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_I2|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->piVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_I4|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->plVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_R4|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pfltVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_R8|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pdblVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_DATE|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pdate;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_CY|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pcyVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_BSTR|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pbstrVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_ERROR|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pscode;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_BOOL|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pboolVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_VARIANT|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->pvarVal;
			pStack += sizeof(_STACK_PTR);
			break;
		case VT_DISPATCH|VT_BYREF:
		case VT_UNKNOWN|VT_BYREF:
			*(_STACK_PTR*)pStack = (_STACK_PTR)pArg->ppunkVal;
			pStack += sizeof(_STACK_PTR);
			break;

		default:
			ASSERT(FALSE);
		}

#ifdef _ALIGN_STACK
		// align stack as appropriate for next parameter
		pStack = (BYTE*)(((DWORD)pStack + (_ALIGN_STACK-1)) &
			~(_ALIGN_STACK-1));
		ASSERT(((DWORD)pStack & (_ALIGN_STACK-1)) == 0);
#endif
	}

	// check that all source arguments were consumed
	if (iArg > 0)
	{
		*puArgErr = iArg;
		return DISP_E_BADPARAMCOUNT;
	}
	// check that all target arguments were filled
	if (*pb != '\0')
	{
		*puArgErr = pDispParams->cArgs;
		return DISP_E_PARAMNOTOPTIONAL;
	}
	return S_OK;    // success!
}

// indirect call helper (see OLECALL.CPP for implementation)

extern "C" DWORD AFXAPI
_AfxDispatchCall(AFX_PMSG pfn, void* pArgs, UINT nSizeArgs);

// invoke standard method given IDispatch parameters/return value, etc.
SCODE CCmdTarget::CallMemberFunc(const AFX_DISPMAP_ENTRY* pEntry, WORD wFlags,
	VARIANT* pvarResult, DISPPARAMS* pDispParams, UINT* puArgErr)
{
	AFX_MANAGE_STATE(m_pModuleState);

	ASSERT(pEntry != NULL);
	ASSERT(pEntry->pfn != NULL);

	// special union used only to hold largest return value possible
	union AFX_RESULT
	{
		VARIANT vaVal;
		CY cyVal;
		float fltVal;
		double dblVal;
		DWORD nVal;
	};

	// get default function and parameters
	BYTE bNoParams = 0;
	const BYTE* pbParams = (const BYTE*)pEntry->lpszParams;
	if (pbParams == NULL)
		pbParams = &bNoParams;
	UINT nParams = lstrlenA((LPCSTR)pbParams);

	// get default function and return value information
	AFX_PMSG pfn = pEntry->pfn;
	VARTYPE vtResult = pEntry->vt;

	// make DISPATCH_PROPERTYPUT look like call with one extra parameter
	if (wFlags & (DISPATCH_PROPERTYPUT|DISPATCH_PROPERTYPUTREF))
	{
		BYTE* pbPropSetParams = (BYTE*)_alloca(nParams+3);
		ASSERT(pbPropSetParams != NULL);    // stack overflow?

		ASSERT(!(pEntry->vt & VT_BYREF));
		memcpy(pbPropSetParams, pbParams, nParams);
		pbParams = pbPropSetParams;

		VARTYPE vtProp = pEntry->vt;
#if !defined(_UNICODE) && !defined(OLE2ANSI)
		if (vtProp == VT_BSTR)
			vtProp = VT_BSTRA;
#endif
		// VT_MFCVALUE serves serves as marker denoting start of named params
		pbPropSetParams[nParams++] = (BYTE)VT_MFCMARKER;
		pbPropSetParams[nParams++] = (BYTE)vtProp;
		pbPropSetParams[nParams] = 0;

		// call "set" function instead of "get"
		ASSERT(pEntry->pfnSet != NULL);
		pfn = pEntry->pfnSet;
		vtResult = VT_EMPTY;
	}

	// allocate temporary space for VARIANT temps created by VariantChangeType
	VARIANT* rgTempVars =
		(VARIANT*)_alloca(pDispParams->cArgs * sizeof(VARIANT));
	if (rgTempVars == NULL)
	{
		TRACE0("Error: stack overflow in IDispatch::Invoke!\n");
		return E_OUTOFMEMORY;
	}
	memset(rgTempVars, 0, pDispParams->cArgs * sizeof(VARIANT));

	// determine size of arguments and allocate stack space
	UINT nSizeArgs = GetStackSize(pbParams, vtResult);
	ASSERT(nSizeArgs != 0);
	if (nSizeArgs < _STACK_MIN)
		nSizeArgs = _STACK_MIN;
	BYTE* pStack = (BYTE*)_alloca(nSizeArgs + _SCRATCH_SIZE);
	if (pStack == NULL)
	{
		TRACE0("Error: stack overflow in IDispatch::Invoke!\n");
		return E_OUTOFMEMORY;
	}

	// push all the args on to the stack allocated memory
	AFX_RESULT result;
#ifndef _SHADOW_DOUBLES
	SCODE sc = PushStackArgs(pStack, pbParams, &result, vtResult,
		pDispParams, puArgErr, rgTempVars);
#else
	SCODE sc = PushStackArgs(pStack, pbParams, &result, vtResult,
		pDispParams, puArgErr, rgTempVars, nSizeArgs);
#endif
	pStack += _STACK_OFFSET;

	DWORD dwResult = 0;
	if (sc == S_OK)
	{
		TRY
		{
			// PushStackArgs will fail on argument mismatches
			DWORD (AFXAPI *pfnDispatch)(AFX_PMSG, void*, UINT) =
				&_AfxDispatchCall;

			// floating point return values are a special case
			switch (vtResult)
			{
			case VT_R4:
				result.fltVal = ((float (AFXAPI*)(AFX_PMSG, void*, UINT))
					pfnDispatch)(pfn, pStack, nSizeArgs);
				break;
			case VT_R8:
				result.dblVal = ((double (AFXAPI*)(AFX_PMSG, void*, UINT))
					pfnDispatch)(pfn, pStack, nSizeArgs);
				break;
			case VT_DATE:
				result.dblVal = ((DATE (AFXAPI*)(AFX_PMSG, void*, UINT))
					pfnDispatch)(pfn, pStack, nSizeArgs);
				break;

			default:
				dwResult = pfnDispatch(pfn, pStack, nSizeArgs);
				break;
			}
		}
		CATCH_ALL(e)
		{
			// free temporaries created by VariantChangeType
			for (UINT iArg = 0; iArg < pDispParams->cArgs; ++iArg)
				VariantClear(&rgTempVars[iArg]);

			THROW_LAST();
		}
		END_CATCH_ALL
	}

	// free temporaries created by VariantChangeType
	for (UINT iArg = 0; iArg < pDispParams->cArgs; ++iArg)
		VariantClear(&rgTempVars[iArg]);

	// handle error during PushStackParams
	if (sc != S_OK)
		return sc;

	// property puts don't touch the return value
	if (pvarResult != NULL)
	{
		// clear pvarResult just in case
		pvarResult->vt = vtResult;

		// build return value VARIANT from result union
		switch (vtResult)
		{
		case VT_UI2:
			pvarResult->bVal = (BYTE)dwResult;
			break;
		case VT_I2:
			pvarResult->iVal = (short)dwResult;
			break;
		case VT_I4:
			pvarResult->lVal = (long)dwResult;
			break;
		case VT_R4:
			pvarResult->fltVal = result.fltVal;
			break;
		case VT_R8:
			pvarResult->dblVal = result.dblVal;
			break;
		case VT_CY:
			pvarResult->cyVal = result.cyVal;
			break;
		case VT_DATE:
			pvarResult->date = result.dblVal;
			break;

⌨️ 快捷键说明

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