BOOL CXLAutomation::ExlInvoke(IDispatch *pdisp, LPOLESTR szMember, VARIANTARG * pvargReturn, WORD wInvokeAction, WORD wFlags) { HRESULT hr; DISPPARAMS dispparams; unsigned int uiArgErr; EXCEPINFO excep; // Get the IDs for the member and its arguments. GetIDsOfNames expects the // member name as the first name, followed by argument names (if any). m_alpszArgNames[0] = szMember; hr = pdisp->GetIDsOfNames( IID_NULL, m_alpszArgNames, 1 + m_iNamedArgCount, LOCALE_SYSTEM_DEFAULT, m_aDispIds); if (FAILED(hr)) { if (!(wFlags & DISP_NOSHOWEXCEPTIONS)) ShowException(szMember, hr, NULL, 0); return FALSE; } if (pvargReturn != NULL) ClearVariant(pvargReturn); // if doing a property put(ref), we need to adjust the first argument to have a // named arg of DISPID_PROPERTYPUT. if (wInvokeAction & (DISPATCH_PROPERTYPUT | DISPATCH_PROPERTYPUTREF)) { m_iNamedArgCount = 1; m_aDispIds[1] = DISPID_PROPERTYPUT; pvargReturn = NULL; } dispparams.rgdispidNamedArgs = m_aDispIds + 1; dispparams.rgvarg = m_aVargs; dispparams.cArgs = m_iArgCount; dispparams.cNamedArgs = m_iNamedArgCount; excep.pfnDeferredFillIn = NULL; hr = pdisp->Invoke(m_aDispIds[0], IID_NULL, LOCALE_SYSTEM_DEFAULT, wInvokeAction, &dispparams, pvargReturn, &excep, &uiArgErr); if (wFlags & DISP_FREEARGS) ClearAllArgs(); if (FAILED(hr)) { // display the exception information if appropriate: if (!(wFlags & DISP_NOSHOWEXCEPTIONS)) ShowException(szMember, hr, &excep, uiArgErr); // free exception structure information SysFreeString(excep.bstrSource); SysFreeString(excep.bstrDescription); SysFreeString(excep.bstrHelpFile); return FALSE; } return TRUE; }
void CXLAutomation::AddArgumentCommon(LPOLESTR lpszArgName, WORD wFlags, VARTYPE vt) { ClearVariant(&m_aVargs[m_iArgCount]); m_aVargs[m_iArgCount].vt = vt; m_awFlags[m_iArgCount] = wFlags; if (lpszArgName != NULL) { m_alpszArgNames[m_iNamedArgCount + 1] = lpszArgName; m_iNamedArgCount++; } }
void AddArgumentCommon(LPOLESTR lpszArgName, WORD wFlags, VARTYPE vt) { ClearVariant(&g_aVargs[g_iArgCount]); g_aVargs[g_iArgCount].vt = vt; g_awFlags[g_iArgCount] = wFlags; if (lpszArgName != NULL) { g_alpszArgNames[g_iNamedArgCount + 1] = lpszArgName; g_iNamedArgCount++; } }
/* * Constructs an 1-dimensional array containing variant strings. The strings * are copied from an incoming array of C-Strings. */ BOOL CXLAutomation::AddArgumentCStringArray(LPOLESTR lpszArgName, WORD wFlags, LPOLESTR *paszStrings, int iCount) { SAFEARRAY *psa; SAFEARRAYBOUND saBound; VARIANTARG *pvargBase; VARIANTARG *pvarg; int i, j; saBound.lLbound = 0; saBound.cElements = iCount; psa = SafeArrayCreate(VT_VARIANT, 1, &saBound); if (psa == NULL) return FALSE; SafeArrayAccessData(psa, (void**) &pvargBase); pvarg = pvargBase; for (i = 0; i < iCount; i++) { // copy each string in the list of strings ClearVariant(pvarg); pvarg->vt = VT_BSTR; if ((pvarg->bstrVal = SysAllocString(*paszStrings++)) == NULL) { // memory failure: back out and free strings alloc'ed up to // now, and then the array itself. pvarg = pvargBase; for (j = 0; j < i; j++) { SysFreeString(pvarg->bstrVal); pvarg++; } SafeArrayDestroy(psa); return FALSE; } pvarg++; } SafeArrayUnaccessData(psa); // With all memory allocated, setup this argument AddArgumentCommon(lpszArgName, wFlags, VT_VARIANT | VT_ARRAY); m_aVargs[m_iArgCount++].parray = psa; return TRUE; }
/* * ClearAllArgs * * Clears the existing contents of the arg array in preparation for * a new invocation. Frees argument memory if so marked. */ void CXLAutomation::ClearAllArgs() { int i; for (i = 0; i < m_iArgCount; i++) { if (m_awFlags[i] & DISPARG_NOFREEVARIANT) // free the variant's contents based on type ClearVariant(&m_aVargs[i]); else ReleaseVariant(&m_aVargs[i]); } m_iArgCount = 0; m_iNamedArgCount = 0; }
void ClearAllArgs() { int i; for (i = 0; i < g_iArgCount; i++) { if (g_awFlags[i] & DISPARG_NOFREEVARIANT) // free the variant's contents based on type ClearVariant(&g_aVargs[i]); else ReleaseVariant(&g_aVargs[i]); } g_iArgCount = 0; g_iNamedArgCount = 0; }
/* * ReleaseVariant * * Clears a particular variant structure and releases any external objects * or memory contained in the variant. Supports the data types listed above. */ int CXLAutomation::ReleaseVariant(VARIANTARG *pvarg) { VARTYPE vt; VARIANTARG *pvargArray; long lLBound, lUBound, l; vt = pvarg->vt & 0xfff; // mask off flags // check if an array. If so, free its contents, then the array itself. if (V_ISARRAY(pvarg)) { // variant arrays are all this routine currently knows about. Since a // variant can contain anything (even other arrays), call ourselves // recursively. if (vt == VT_VARIANT) { SafeArrayGetLBound(pvarg->parray, 1, &lLBound); SafeArrayGetUBound(pvarg->parray, 1, &lUBound); if (lUBound > lLBound) { lUBound -= lLBound; SafeArrayAccessData(pvarg->parray, (void**)&pvargArray); for (l = 0; l < lUBound; l++) { ReleaseVariant(pvargArray); pvargArray++; } SafeArrayUnaccessData(pvarg->parray); } } else { return 1; // non-variant type // MessageBox(NULL, _T("ReleaseVariant: Array contains non-variant type"), "Failed", MB_OK | MB_ICONSTOP); } // Free the array itself. SafeArrayDestroy(pvarg->parray); } else { switch (vt) { case VT_DISPATCH: //(*(pvarg->pdispVal->lpVtbl->Release))(pvarg->pdispVal); pvarg->pdispVal->Release(); break; case VT_BSTR: SysFreeString(pvarg->bstrVal); break; case VT_I2: case VT_BOOL: case VT_R8: case VT_ERROR: // to avoid erroring on an error return from Excel // no work for these types break; default: return 2; //unknonw type // MessageBox(NULL, _T("ReleaseVariant: Unknown type"), "Failed", MB_OK | MB_ICONSTOP); break; } } ClearVariant(pvarg); return 0; }
void ReleaseVariant(VARIANTARG *pvarg) { VARTYPE vt; VARIANTARG HUGEP *pvargArray; long lLBound, lUBound, l; vt = pvarg->vt & 0xfff; // mask off flags // check if an array. If so, free its contents, // then the array itself. if (V_ISARRAY(pvarg)) { // variant arrays are all this routine currently knows about. // Since a variant can contain anything (even other arrays), // call ourselves recursively. if (vt == VT_VARIANT) { SafeArrayGetLBound(pvarg->parray, 1, &lLBound); SafeArrayGetUBound(pvarg->parray, 1, &lUBound); if (lUBound > lLBound) { lUBound -= lLBound; SafeArrayAccessData(pvarg->parray,(void **) &pvargArray); for (l = 0; l < lUBound; l++) { ReleaseVariant(pvargArray); pvargArray++; } SafeArrayUnaccessData(pvarg->parray); } } else { MessageBox(g_hwndApp, "ReleaseVariant: Array contains non-variant type", g_szAppTitle, MB_OK | MB_ICONSTOP); } // Free the array itself. SafeArrayDestroy(pvarg->parray); } else { switch (vt) { case VT_DISPATCH: //14/12/2004 //!!!all comments had to be added (/***/(pvarg->pdispVal/*->lpVtbl*/->Release))(/*pvarg->pdispVal*/); break; case VT_BSTR: SysFreeString(pvarg->bstrVal); break; case VT_I2: case VT_BOOL: case VT_R8: case VT_ERROR: // to avoid erroring on an error return // from Excel // no work for these types break; default: MessageBox(g_hwndApp, "ReleaseVariant: Unknown type",g_szAppTitle, MB_OK | MB_ICONSTOP); break; } } ClearVariant(pvarg); }