Rev 39265 | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed
/******************************************************************************** BDX: Binary Data eXchange format library* Copyright (C) 1999-2006 Thomas Baier** This library is free software; you can redistribute it and/or* modify it under the terms of the GNU Library General Public* License as published by the Free Software Foundation; either* version 2 of the License, or (at your option) any later version.** This library is distributed in the hope that it will be useful,* but WITHOUT ANY WARRANTY; without even the implied warranty of* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU* Library General Public License for more details.** You should have received a copy of the GNU Library General Public* License along with this library; if not, write to the Free* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,* MA 02110-1301, USA.** Conversion functions from VARIANT to BDX and vice versa.*******************************************************************************/#ifndef _BDX_COM_H_#include "bdx_com.h"#endif#include "bdx.h"#include "bdx_util.h"/* #include "com_util.h" */#include <windows.h>#include <stdio.h>#include <assert.h>/** prototypes for internal helper functions*/static int BDXScalar2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static int BDXArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static int BDXBoolArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static int BDXIntArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static int BDXDoubleArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static int BDXSpecialArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static int BDXStringArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static int BDXGenericArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData);static unsigned int GetArrayBounds (BDX_Data* pBDXData,SAFEARRAYBOUND** ppArrayBounds);static char* MyW2A(wchar_t* w);static int VariantScalar2BDX (VARIANT VariantData,BDX_Data** ppBDXData);static int VariantArray2BDX (VARIANT VariantData,BDX_Data** ppBDXData);static int VariantBoolArray2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantI2Array2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantI4Array2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantUI1Array2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantR4Array2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantR8Array2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantErrorArray2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantStringArray2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static int VariantVariantArray2BDX(VARIANT VariantData,BDX_Data* ppBDXData,unsigned int pTotalElements);static unsigned long getSpecialValueFromSCODE(SCODE pSCODE);static SCODE getSCODEFromSpecialValue(unsigned long pSpecialVal);BSTR ANSI2BSTR(char const* str){OLECHAR* _str = com_getOLECHAR (str);BSTR bstr = SysAllocString (_str);free (_str);return bstr;}/** get the ANSI string from an BSTR *//* 04-06-30 | baier | wrong parameters for WideCharToMultiByte *//* 04-10-20 | baier | check for NULL first */char* BSTR2ANSI(BSTR bstr){UINT count = 0;char* str;if(bstr == NULL) {return NULL;}count = SysStringLen (bstr);str = (char*) malloc (count+1);str[count] = 0x0;WideCharToMultiByte(CP_ACP,0,bstr,-1,str,count+1,NULL,NULL);return str;}OLECHAR* com_getOLECHAR(char const* str){int chars;OLECHAR* _str;chars = MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,str,-1,NULL,0);if (chars == 0) {return NULL;}_str = (OLECHAR*) calloc(chars,sizeof (OLECHAR));chars = MultiByteToWideChar(CP_ACP,MB_PRECOMPOSED,str,-1,_str,chars);return _str;}static char* MyW2A(wchar_t* w){char* rc = BSTR2ANSI(w);if(rc == NULL) {rc = strdup("");}return rc;}/* 06-02-15 | baier | trace on error */int WINAPI BDX2Variant (BDX_Data* pBDXData,VARIANT* pVariantData){int lRet = 0;if(pBDXData->version != BDX_VERSION) {BDX_ERR(printf("BDX2Variant: got invalid BDX version. Expected %d, got %d\n",BDX_VERSION,pBDXData->version));return -1;}switch (pBDXData->type & BDX_CMASK){/* scalar? */case BDX_SCALAR:lRet = BDXScalar2Variant (pBDXData,pVariantData);break;/* treat vectors and arrays the same for the moment */case BDX_ARRAY:lRet = BDXArray2Variant (pBDXData,pVariantData);break;default:BDX_TRACE(printf("BDX2Variant: unknown type, bailing out\n"));lRet = -2;}return lRet;}int WINAPI Variant2BDX (VARIANT VariantData,BDX_Data** ppBDXData){/* scalar or array/vector? */if(V_ISARRAY (&VariantData)) /* (data.vt & VT_ARRAY) == VT_ARRAY) */{return VariantArray2BDX (VariantData,ppBDXData);}else{return VariantScalar2BDX (VariantData,ppBDXData);}return -2;}/* 05-05-20 | baier | BDX_SPECIAL, BDX_HANDLE *//* 06-02-15 | baier | fixes for COM objects/EXTPTRSXP */static int BDXScalar2Variant (BDX_Data* pBDXData,VARIANT* pVariantData){int lRet = 0;switch (pBDXData->type & BDX_SMASK){case BDX_BOOL:pVariantData->vt = VT_BOOL;pVariantData->boolVal = pBDXData->data.raw_data[0].bool_value ? VARIANT_TRUE : VARIANT_FALSE;break;case BDX_INT:pVariantData->vt = VT_I4;pVariantData->lVal = pBDXData->data.raw_data[0].int_value;break;case BDX_DOUBLE:pVariantData->vt = VT_R8;pVariantData->dblVal = pBDXData->data.raw_data[0].double_value;break;case BDX_STRING:{pVariantData->vt = VT_BSTR;pVariantData->bstrVal =ANSI2BSTR(pBDXData->data.raw_data[0].string_value);}break;case BDX_HANDLE:{LPSTREAM lStream = pBDXData->data.raw_data[0].ptr;HRESULT lRc = CoUnmarshalInterface(lStream,&IID_IDispatch,(void**) &V_DISPATCH(pVariantData));if(FAILED(lRc)) {BDX_ERR(printf("unmarshalling stream ptr %p failed with hr=%08x\n",lStream,lRc));return -1;} else {BDX_ERR(printf("successfully marshalled COM interface\n"));}/* create SEXP for COM object */V_VT(pVariantData) = VT_DISPATCH;break;}case BDX_SPECIAL:V_VT(pVariantData) = VT_ERROR;V_ERROR(pVariantData) =getSCODEFromSpecialValue(pBDXData->data.raw_data[0].special_value);break;default:BDX_ERR(printf("unsupported BDX type %08x found\n",pBDXData->type));lRet = -2;}return lRet;}/* 05-06-05 | baier | BDX_GENERIC *//* 05-06-08 | baier | array of BDX_SPECIAL *//* 06-02-15 | baier | fixes for COM objects/EXTPTRSXP */static int BDXArray2Variant (BDX_Data* pBDXData,VARIANT* pVariantData){int lRet = 0;switch (pBDXData->type & BDX_SMASK){case BDX_BOOL:lRet = BDXBoolArray2Variant (pBDXData,pVariantData);break;case BDX_INT:lRet = BDXIntArray2Variant (pBDXData,pVariantData);break;case BDX_DOUBLE:lRet = BDXDoubleArray2Variant (pBDXData,pVariantData);break;case BDX_SPECIAL:lRet = BDXSpecialArray2Variant (pBDXData,pVariantData);break;case BDX_STRING:lRet = BDXStringArray2Variant (pBDXData,pVariantData);break;case BDX_GENERIC:lRet = BDXGenericArray2Variant(pBDXData,pVariantData);break;default:BDX_ERR(printf("BDXArray2Variant: unsupported array type %x\n",pBDXData->type));lRet = -2;}return lRet;}static int BDXBoolArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData){unsigned int lMaxIndex;SAFEARRAYBOUND* lArrayBounds;VARIANT_BOOL HUGEP* lBoolArray;unsigned int i;lMaxIndex = GetArrayBounds (pBDXData,&lArrayBounds);pVariantData->vt = VT_ARRAY | VT_BOOL;pVariantData->parray = SafeArrayCreate (VT_BOOL,pBDXData->dim_count,lArrayBounds);free (lArrayBounds); lArrayBounds = 0;if (pVariantData->parray == 0){return -4;}/* access the data */if(SafeArrayAccessData (pVariantData->parray,(void*) &lBoolArray) != S_OK) {/* free safe array data */SafeArrayDestroy (pVariantData->parray);pVariantData->parray = 0;return -3;}/* copy the data */for(i = 0;i < lMaxIndex;i++) {lBoolArray[i] = pBDXData->data.raw_data[i].bool_value ? VARIANT_TRUE : VARIANT_FALSE;}SafeArrayUnlock (pVariantData->parray);return 0;}static int BDXIntArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData){unsigned int lMaxIndex;SAFEARRAYBOUND* lArrayBounds;long HUGEP* lIntArray;unsigned int i;lMaxIndex = GetArrayBounds (pBDXData,&lArrayBounds);pVariantData->vt = VT_ARRAY | VT_I4;pVariantData->parray = SafeArrayCreate (VT_I4,pBDXData->dim_count,lArrayBounds);free (lArrayBounds);if (pVariantData->parray == 0){return -4;}/* access the data */if (SafeArrayAccessData (pVariantData->parray,(void*) &lIntArray) != S_OK){/* free array data */SafeArrayDestroy (pVariantData->parray);pVariantData->parray = 0;return -3;}/* copy the data */for (i = 0;i < lMaxIndex;i++){lIntArray[i] = pBDXData->data.raw_data[i].int_value;}/* @TODO: SafeArrayUnaccessData()*/SafeArrayUnlock (pVariantData->parray);return 0;}static int BDXDoubleArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData){unsigned int lMaxIndex;SAFEARRAYBOUND* lArrayBounds;double HUGEP* lDoubleArray;unsigned int i;lMaxIndex = GetArrayBounds (pBDXData,&lArrayBounds);pVariantData->vt = VT_ARRAY | VT_R8;pVariantData->parray = SafeArrayCreate (VT_R8,pBDXData->dim_count,lArrayBounds);free (lArrayBounds);if (pVariantData->parray == 0){return -4;}/* access the data */if (SafeArrayAccessData (pVariantData->parray,(void*) &lDoubleArray) != S_OK){/* free safe array data */SafeArrayDestroy (pVariantData->parray);pVariantData->parray = 0;return -3;}/* copy the data */for (i = 0;i < lMaxIndex;i++){lDoubleArray[i] = pBDXData->data.raw_data[i].double_value;}SafeArrayUnlock (pVariantData->parray);return 0;}/* 06-05-16 | baier | fix: use ...raw_data[i].special_value instead of* ...raw_data[i].double_value */static int BDXSpecialArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData){unsigned int lMaxIndex;SAFEARRAYBOUND* lArrayBounds;SCODE HUGEP* lErrorArray;unsigned int i;lMaxIndex = GetArrayBounds (pBDXData,&lArrayBounds);pVariantData->vt = VT_ARRAY | VT_ERROR;pVariantData->parray = SafeArrayCreate (VT_R8,pBDXData->dim_count,lArrayBounds);free (lArrayBounds);if (pVariantData->parray == 0){return -4;}/* access the data */if (SafeArrayAccessData (pVariantData->parray,(void*) &lErrorArray) != S_OK){/* free safe array data */SafeArrayDestroy (pVariantData->parray);pVariantData->parray = 0;return -3;}/* copy the data */for (i = 0;i < lMaxIndex;i++){lErrorArray[i] =getSCODEFromSpecialValue(pBDXData->data.raw_data[i].special_value);}SafeArrayUnlock (pVariantData->parray);return 0;}static int BDXStringArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData){unsigned int lMaxIndex;SAFEARRAYBOUND* lArrayBounds;unsigned int i;BSTR HUGEP* lStringArray;lMaxIndex = GetArrayBounds (pBDXData,&lArrayBounds);pVariantData->vt = VT_ARRAY | VT_BSTR;pVariantData->parray = SafeArrayCreate (VT_BSTR,pBDXData->dim_count,lArrayBounds);free (lArrayBounds);if (pVariantData->parray == 0){return -4;}/* access the data */if (SafeArrayAccessData (pVariantData->parray,(void*) &lStringArray) != S_OK){/* free safe array data */SafeArrayDestroy (pVariantData->parray);pVariantData->parray = 0;return -3;}/* copy the data */for(i = 0;i < lMaxIndex;i++) {lStringArray[i] = ANSI2BSTR(pBDXData->data.raw_data[i].string_value);}SafeArrayUnlock (pVariantData->parray);return 0;}/* 05-06-05 | baier | convert a BDX_GENERIC array to a SAFEARRAY of VARIANT */static int BDXGenericArray2Variant(BDX_Data* pBDXData,VARIANT* pVariantData){unsigned int lMaxIndex;SAFEARRAYBOUND* lArrayBounds;VARIANT HUGEP* lVariantArray;unsigned int i;lMaxIndex = GetArrayBounds (pBDXData,&lArrayBounds);pVariantData->vt = VT_ARRAY | VT_VARIANT;pVariantData->parray = SafeArrayCreate (VT_VARIANT,pBDXData->dim_count,lArrayBounds);free (lArrayBounds);if (pVariantData->parray == 0){return -4;}/* access the data */if (SafeArrayAccessData (pVariantData->parray,(void*) &lVariantArray) != S_OK){/* free safe array data */SafeArrayDestroy (pVariantData->parray);pVariantData->parray = 0;return -3;}/* copy the data */for (i = 0;i < lMaxIndex;i++) {switch(pBDXData->data.raw_data_with_type[i].type) {case BDX_BOOL:V_VT(&lVariantArray[i]) = VT_BOOL;V_BOOL(&lVariantArray[i]) =pBDXData->data.raw_data_with_type[i].raw_data.bool_value? VARIANT_TRUE : VARIANT_FALSE;break;case BDX_INT:V_VT(&lVariantArray[i]) = VT_I4;V_I4(&lVariantArray[i]) =pBDXData->data.raw_data_with_type[i].raw_data.int_value;break;case BDX_DOUBLE:V_VT(&lVariantArray[i]) = VT_R8;V_R8(&lVariantArray[i]) =pBDXData->data.raw_data_with_type[i].raw_data.double_value;break;case BDX_STRING:{V_VT(&lVariantArray[i]) = VT_BSTR;V_BSTR(&lVariantArray[i]) =ANSI2BSTR(pBDXData->data.raw_data_with_type[i].raw_data.string_value);}break;case BDX_HANDLE:{LPSTREAM lStream = pBDXData->data.raw_data_with_type[i].raw_data.ptr;HRESULT lRc = CoUnmarshalInterface(lStream,&IID_IDispatch,(void*) V_DISPATCH(&lVariantArray[i]));if(FAILED(lRc)) {BDX_ERR(printf("unmarshalling stream ptr %p (index %d) failed with hr=%08x\n",lStream,i,lRc));return -1;}/* create SEXP for COM object */V_VT(&lVariantArray[i]) = VT_DISPATCH;}case BDX_SPECIAL:V_VT(&lVariantArray[i]) = VT_ERROR;V_ERROR(&lVariantArray[i]) =getSCODEFromSpecialValue(pBDXData->data.raw_data_with_type[i].raw_data.special_value);break;default:BDX_ERR(printf("unsupported BDX type %08x found at index %d\n",pBDXData->data.raw_data_with_type[i].type,i));return -2;}}SafeArrayUnlock (pVariantData->parray);return 0;}static unsigned int GetArrayBounds (BDX_Data* pBDXData,SAFEARRAYBOUND** ppArrayBounds){/* number of dimensions in lData->dim_count, allocate the array */SAFEARRAYBOUND* lArrayBounds = (SAFEARRAYBOUND*) malloc (pBDXData->dim_count * sizeof (SAFEARRAYBOUND));unsigned int i;unsigned int lMaxIndex = 1;for (i = 0;i < pBDXData->dim_count;i++){lArrayBounds[i].cElements = pBDXData->dimensions[i];lMaxIndex *= pBDXData->dimensions[i];lArrayBounds[i].lLbound = 0;}*ppArrayBounds = lArrayBounds;return lMaxIndex;}/* 04-11-16 | baier | set BDX version *//* 05-05-19 | baier | VT_DISPATCH, VT_ERROR *//* 05-11-29 | baier | handle VT_EMPTY, too */int VariantScalar2BDX (VARIANT VariantData,BDX_Data** ppBDXData){/* allocate base buffer */BDX_Data* lData = (BDX_Data*) malloc (sizeof (BDX_Data));lData->version = BDX_VERSION;*ppBDXData = 0;/* scalar */lData->type = BDX_SCALAR;lData->dim_count = 1;lData->dimensions = (BDX_Dimension*) malloc (sizeof (BDX_Dimension));lData->dimensions[0] = 1;lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData));switch (VariantData.vt & VT_TYPEMASK){/* boolean data */case VT_BOOL: /* boolean: 0x0000 is false, 0xffff is true (boolVal) */lData->type |= BDX_BOOL;if(!V_ISBYREF(&VariantData)) {if (VariantData.boolVal == VARIANT_FALSE) {lData->data.raw_data[0].bool_value = 0;} else if (VariantData.boolVal == VARIANT_TRUE) {lData->data.raw_data[0].bool_value = 1;} else {free (lData->data.raw_data);free (lData->dimensions);free (lData);return -4;}} else {if (*VariantData.pboolVal == VARIANT_FALSE) {lData->data.raw_data[0].bool_value = 0;} else if (*VariantData.pboolVal == VARIANT_TRUE) {lData->data.raw_data[0].bool_value = 1;} else {free (lData->data.raw_data);free (lData->dimensions);free (lData);return -4;}}break;/* integer data */case VT_I2: /* 2-byte signed integer (iVal) */lData->type |= BDX_INT;if(!V_ISBYREF(&VariantData)) {lData->data.raw_data[0].int_value = VariantData.iVal;} else {lData->data.raw_data[0].int_value = *VariantData.piVal;}break;case VT_I4: /* 4-byte signed integer (lVal) */lData->type |= BDX_INT;if(!V_ISBYREF(&VariantData)) {lData->data.raw_data[0].int_value = VariantData.lVal;} else {lData->data.raw_data[0].int_value = *VariantData.plVal;}break;case VT_UI1: /* unsigned one-byte integer (bVal) */lData->type |= BDX_INT;if(!V_ISBYREF(&VariantData)) {lData->data.raw_data[0].int_value = VariantData.bVal;} else {lData->data.raw_data[0].int_value = *VariantData.pbVal;}break;/* real and double data */case VT_R4: /* 4-byte IEEE floating point (fltVal) */lData->type |= BDX_DOUBLE;if(!V_ISBYREF(&VariantData)) {lData->data.raw_data[0].double_value = VariantData.fltVal;} else {lData->data.raw_data[0].double_value = *VariantData.pfltVal;}break;case VT_R8: /* 8-byte IEEE floating point (dblVal) */lData->type |= BDX_DOUBLE;if(!V_ISBYREF(&VariantData)) {lData->data.raw_data[0].double_value = VariantData.dblVal;} else {lData->data.raw_data[0].double_value = *VariantData.pdblVal;}break;/* string data */case VT_BSTR: /* basic string (bstrVal) */{lData->type |= BDX_STRING;if(!V_ISBYREF(&VariantData)) {lData->data.raw_data[0].string_value = MyW2A(VariantData.bstrVal);} else {lData->data.raw_data[0].string_value = MyW2A(*VariantData.pbstrVal);}}break;case VT_EMPTY: /* empty cells in Excel for example */lData->type |= BDX_SPECIAL;lData->data.raw_data[0].special_value = BDX_SV_NULL;break;case VT_ERROR: /* special values (e.g. NA, NaN) */{SCODE lCode;lData->type |= BDX_SPECIAL;if(!V_ISBYREF(&VariantData)) {lCode = V_ERROR(&VariantData);} else {lCode = *V_ERRORREF(&VariantData);}lData->data.raw_data[0].special_value =getSpecialValueFromSCODE(lCode);}break;case VT_DISPATCH: /* COM objects (IDispatch) */{/* COM object is marshalled into stream** 1. stream object holds reference to IDispatch* 2. reference count is increased in the meanwhile* 3. must use CoGetInterfaceAndReleaseStream() to unmarshal* 4. Release() must be called on object afterwards*/LPSTREAM lStream = NULL;HRESULT lRc;lRc = CoMarshalInterThreadInterfaceInStream(&IID_IUnknown,(LPUNKNOWN) V_DISPATCH(&VariantData),&lStream);if(FAILED(lRc)) {BDX_TRACE(printf("VariantScalar2BDX: error %08x marshalling interface into stream\n",lRc));return -5;}lData->data.raw_data[0].ptr = lStream;lData->type |= BDX_HANDLE;}break;/* unknown? */default:free(lData->data.raw_data);free(lData->dimensions);free(lData);return -4;}*ppBDXData = lData;return 0;}/* 04-11-16 | baier | set BDX version *//* 05-06-08 | baier | array of error values */static int VariantArray2BDX(VARIANT VariantData,BDX_Data** ppBDXData){SAFEARRAY* lArray;int lRc = 0;/* allocate base buffer */BDX_Data* lData = (BDX_Data*) malloc (sizeof (BDX_Data));unsigned int lTotalSize = 1;lData->version = BDX_VERSION;*ppBDXData = 0;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}/* vector */lData->type = BDX_ARRAY;lData->dim_count = SafeArrayGetDim (lArray);lData->dimensions = (BDX_Dimension*) malloc (sizeof (BDX_Dimension) * lData->dim_count);/* get the dimensions */{unsigned int i;for (i = 0;i < lData->dim_count;i++){long lUpperBound;long lLowerBound;if (FAILED (SafeArrayGetLBound (lArray,i+1,&lLowerBound))){free (lData->dimensions);free (lData);return -3;}if (FAILED (SafeArrayGetUBound (lArray,i+1,&lUpperBound))){free (lData->dimensions);free (lData);return -3;}lData->dimensions[i] = lUpperBound - lLowerBound + 1;lTotalSize *= lData->dimensions[i];}}switch (VariantData.vt & VT_TYPEMASK){/* boolean data */case VT_BOOL: /* boolean: 0x0000 is false, 0xffff is true (boolVal) */lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantBoolArray2BDX (VariantData,lData,lTotalSize);break;/* integer data */case VT_I2: /* 2-byte signed integer (iVal) */lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantI2Array2BDX (VariantData,lData,lTotalSize);break;case VT_I4: /* 4-byte signed integer (lVal) */lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantI4Array2BDX (VariantData,lData,lTotalSize);break;case VT_UI1: /* unsigned one-byte integer (bVal) */lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantUI1Array2BDX (VariantData,lData,lTotalSize);break;/* real and double data */case VT_R4: /* 4-byte IEEE floating point (fltVal) */lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantR4Array2BDX (VariantData,lData,lTotalSize);break;case VT_R8: /* 8-byte IEEE floating point (dblVal) */lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantR8Array2BDX (VariantData,lData,lTotalSize);break;/* string data */case VT_BSTR: /* basic string (bstrVal) */lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantStringArray2BDX (VariantData,lData,lTotalSize);break;/* variant array */case VT_VARIANT:lData->data.raw_data_with_type = (BDX_RawDataWithType*) malloc (sizeof (BDX_RawDataWithType) * lTotalSize);lRc = VariantVariantArray2BDX (VariantData,lData,lTotalSize);break;/* array of error values */case VT_ERROR:lData->data.raw_data = (BDX_RawData*) malloc (sizeof (BDX_RawData) * lTotalSize);lRc = VariantErrorArray2BDX (VariantData,lData,lTotalSize);break;/* unknown? */default:lRc = -2;}if (lRc < 0) {/* even if it doesn't matter */switch(lData->type & ~BDX_ARRAY) {case BDX_GENERIC:free(lData->data.raw_data_with_type);case BDX_BOOL:case BDX_INT:case BDX_DOUBLE:case BDX_STRING:case BDX_SPECIAL:free(lData->data.raw_data);break;default:/* don't know */break;}free (lData->dimensions);free (lData);} else {*ppBDXData = lData;}return lRc;}/* 04-05-12 | baier | handle VT_BYREF */static int VariantBoolArray2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */VARIANT_BOOL HUGEP* lBoolArray;SAFEARRAY* lArray;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lBoolArray) != S_OK) {return -3;}pBDXData->type |= BDX_BOOL;/* copy the data */for (i = 0;i < pTotalElements;i++) {if (lBoolArray[i] == VARIANT_FALSE) {pBDXData->data.raw_data[i].bool_value = 0;} else if (lBoolArray[i] == VARIANT_TRUE) {pBDXData->data.raw_data[0].bool_value = 1;} else {return -2;}}SafeArrayUnlock (lArray);return 0;}/* 04-05-12 | baier | handle VT_BYREF */static int VariantI2Array2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */short HUGEP* lIntArray;SAFEARRAY* lArray;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lIntArray) != S_OK){return -3;}pBDXData->type |= BDX_INT;/* copy the data */for (i = 0;i < pTotalElements;i++) {pBDXData->data.raw_data[i].int_value = lIntArray[i];}SafeArrayUnlock (lArray);return 0;}/* 04-05-12 | baier | handle VT_BYREF */static int VariantI4Array2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */long HUGEP* lIntArray;SAFEARRAY* lArray;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lIntArray) != S_OK){return -3;}pBDXData->type |= BDX_INT;/* copy the data */for (i = 0;i < pTotalElements;i++){pBDXData->data.raw_data[i].int_value = lIntArray[i];}SafeArrayUnlock (lArray);return 0;}/* 04-05-12 | baier | handle VT_BYREF */static int VariantUI1Array2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */unsigned char HUGEP* lIntArray;SAFEARRAY* lArray;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lIntArray) != S_OK){return -3;}pBDXData->type |= BDX_INT;/* copy the data */for (i = 0;i < pTotalElements;i++){pBDXData->data.raw_data[i].int_value = lIntArray[i];}SafeArrayUnlock (lArray);return 0;}/* 04-05-12 | baier | handle VT_BYREF */static int VariantR4Array2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */float HUGEP* lRealArray;SAFEARRAY* lArray;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lRealArray) != S_OK){return -3;}pBDXData->type |= BDX_DOUBLE;/* copy the data */for (i = 0;i < pTotalElements;i++){pBDXData->data.raw_data[i].double_value = lRealArray[i];}SafeArrayUnlock (lArray);return 0;}/* 04-05-12 | baier | handle VT_BYREF */static int VariantR8Array2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */double HUGEP* lRealArray;SAFEARRAY* lArray;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lRealArray) != S_OK){return -3;}pBDXData->type |= BDX_DOUBLE;/* copy the data */for (i = 0;i < pTotalElements;i++){pBDXData->data.raw_data[i].double_value = lRealArray[i];}SafeArrayUnlock (lArray);return 0;}/* 05-06-08 | baier | new */static int VariantErrorArray2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */SCODE HUGEP* lErrorArray;SAFEARRAY* lArray;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lErrorArray) != S_OK){return -3;}pBDXData->type |= BDX_SPECIAL;/* copy the data */for (i = 0;i < pTotalElements;i++){pBDXData->data.raw_data[i].special_value =getSpecialValueFromSCODE(lErrorArray[i]);}SafeArrayUnlock (lArray);return 0;}/* 04-05-12 | baier | handle VT_BYREF */static int VariantStringArray2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){/* access the data */BSTR HUGEP* lStringArray;SAFEARRAY* lArray;unsigned int i;unsigned int limit = pTotalElements;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}if (SafeArrayAccessData (lArray,(void*) &lStringArray) != S_OK){return -3;}pBDXData->type |= BDX_STRING;/* copy the data */for (i = 0;i < pTotalElements;i++){#if 1pBDXData->data.raw_data[i].string_value = MyW2A(lStringArray[i]);#else#endifif(i >= limit){i=i;}}SafeArrayUnlock (lArray);return 0;}/* 05-11-29 | baier | handle VT_EMPTY, too *//* 06-07-03 | baier | bug fix: homogenous array never was transferred, fixed */static int VariantVariantArray2BDX(VARIANT VariantData,BDX_Data* pBDXData,unsigned int pTotalElements){SAFEARRAY* lArray;VARIANT HUGEP* lVariantArray;VARTYPE lCoerceTo = VT_UNKNOWN;unsigned int i;if(!V_ISBYREF(&VariantData)) {lArray = VariantData.parray;} else {lArray = *VariantData.pparray;}/* access the data */if (SafeArrayAccessData (lArray,(void*) &lVariantArray) != S_OK){return -3;}/** Transfer of VARIANT-arrays: The algorithm is defined as:** 1. if all elements are of the same type, the (compound) type* is transferred as a homogenous array** 2. if both integer and floating points variables are found,* and no other types used, data is converted to floating point* and transferred as a floating point array** 3. arrays in arrays are NOT supported** 4. VT_ERROR (e.g. NAN, N/A) will cause a transfer of maybe* homogenous data but with "special" types, too** 5. everything else (which can be transferred) is transferred* as is.*//** first check, if all values are of similar type*/for(i = 0;i < pTotalElements;i++) {/* just check the common data type to coerce to */if(V_ISARRAY(&lVariantArray[i])) {/* we cannot handle arrays in arrays */BDX_ERR(printf("VariantVariantArray2BDX: array found at index %d; not supported\n",i));SafeArrayUnlock (lArray);return -4;}switch(V_VT(&lVariantArray[i])) {case VT_BOOL:if((lCoerceTo == VT_UNKNOWN) || (lCoerceTo == VT_BOOL)) {lCoerceTo = VT_BOOL;} else {lCoerceTo = VT_ERROR; /* this really means: transfer as is */}break;case VT_I2: /* 2-byte signed integer (iVal) */case VT_UI1: /* unsigned one-byte integer (bVal) */case VT_I4:if((lCoerceTo == VT_UNKNOWN) || (lCoerceTo == VT_I4)) {lCoerceTo = VT_I4;} else {lCoerceTo = VT_ERROR; /* this really means: transfer as is */}break;case VT_R4:case VT_R8:if((lCoerceTo == VT_UNKNOWN) || (lCoerceTo == VT_I4)|| (lCoerceTo == VT_R8)) {lCoerceTo = VT_R8;} else {lCoerceTo = VT_ERROR; /* this really means: transfer as is */}break;case VT_BSTR:if((lCoerceTo == VT_UNKNOWN) || (lCoerceTo == VT_BSTR)) {lCoerceTo = VT_BSTR;} else {lCoerceTo = VT_ERROR; /* this really means: transfer as is */}case VT_EMPTY: /* empty cells in Excel for example */case VT_ERROR:/* excel specifies cell errors with the following typedef. These are ORed with 0x800a0000typedef enum {xlErrDiv0 = 2007,xlErrNA = 2042,xlErrName = 2029,xlErrNull = 2000,xlErrNum = 2036,xlErrRef = 2023,xlErrValue = 2015} XlCVError;*/lCoerceTo = VT_ERROR; /* this really means: transfer as is */break;default:BDX_ERR(printf("VariantVariantArray2BDX: type %d found at index %d; not supported\n",V_VT(&lVariantArray[i]),i));SafeArrayUnlock (lArray);return -4;}}switch(lCoerceTo) {case VT_BOOL:pBDXData->type |= BDX_BOOL;break;case VT_I4:pBDXData->type |= BDX_INT;break;case VT_R8:pBDXData->type |= BDX_DOUBLE;break;case VT_BSTR:pBDXData->type |= BDX_STRING;break;case VT_ERROR:/* data will be transferred as is */pBDXData->type |= BDX_GENERIC; /* generic array (no specific base type) */break;default:BDX_ERR(printf("VariantVariantArray2BDX: internal error (#1, val %d)\n",lCoerceTo));SafeArrayUnlock (lArray);return -4;}/* copy the data */if(lCoerceTo != VT_ERROR) {for (i = 0;i < pTotalElements;i++) {VARIANT lTmpVariant;VariantInit(&lTmpVariant);VariantChangeTypeEx(&lTmpVariant,&lVariantArray[i],MAKELCID(MAKELANGID(LANG_ENGLISH,SUBLANG_NEUTRAL),0),VARIANT_ALPHABOOL,lCoerceTo);switch(lCoerceTo) {case VT_BOOL:if (lTmpVariant.boolVal == VARIANT_FALSE) {pBDXData->data.raw_data[i].bool_value = 0;} else {pBDXData->data.raw_data[i].bool_value = 1;}break;case VT_I4:pBDXData->data.raw_data[i].int_value = V_I4(&lTmpVariant);break;case VT_R8:pBDXData->data.raw_data[i].double_value = V_R8(&lTmpVariant);break;case VT_BSTR:pBDXData->data.raw_data[i].string_value = MyW2A(V_BSTR(&lTmpVariant));default:/* never reached */BDX_ERR(printf("VariantVariantArray2BDX: internal error (#1, type %d at %i)\n",lCoerceTo,i));break;}VariantClear(&lTmpVariant);}} else {for (i = 0;i < pTotalElements;i++) {switch(V_VT(&lVariantArray[i])){case VT_BOOL:pBDXData->data.raw_data_with_type[i].type = BDX_BOOL;if(!V_ISBYREF(&lVariantArray[i])) {if(lVariantArray[i].boolVal == VARIANT_FALSE) {pBDXData->data.raw_data_with_type[i].raw_data.bool_value = 0;} else {pBDXData->data.raw_data_with_type[i].raw_data.bool_value = 1;}} else {if(*lVariantArray[i].pboolVal == VARIANT_FALSE) {pBDXData->data.raw_data_with_type[i].raw_data.bool_value = 0;} else {pBDXData->data.raw_data_with_type[i].raw_data.bool_value = 1;}}break;case VT_I2: /* 2-byte signed integer (iVal) */pBDXData->data.raw_data_with_type[i].type = BDX_INT;if(!V_ISBYREF(&lVariantArray[i])) {pBDXData->data.raw_data_with_type[i].raw_data.int_value = lVariantArray[i].iVal;} else {pBDXData->data.raw_data_with_type[i].raw_data.int_value = *lVariantArray[i].piVal;}break;case VT_UI1: /* unsigned one-byte integer (bVal) */pBDXData->data.raw_data_with_type[i].type = BDX_INT;if(!V_ISBYREF(&lVariantArray[i])) {pBDXData->data.raw_data_with_type[i].raw_data.int_value = lVariantArray[i].bVal;} else {pBDXData->data.raw_data_with_type[i].raw_data.int_value = *lVariantArray[i].pbVal;}break;case VT_I4:pBDXData->data.raw_data_with_type[i].type = BDX_INT;if(!V_ISBYREF(&lVariantArray[i])) {pBDXData->data.raw_data_with_type[i].raw_data.int_value = lVariantArray[i].lVal;} else {pBDXData->data.raw_data_with_type[i].raw_data.int_value = *lVariantArray[i].plVal;}break;case VT_R4:pBDXData->data.raw_data_with_type[i].type = BDX_DOUBLE;if(!V_ISBYREF(&lVariantArray[i])) {pBDXData->data.raw_data_with_type[i].raw_data.double_value = lVariantArray[i].fltVal;} else {pBDXData->data.raw_data_with_type[i].raw_data.double_value = *lVariantArray[i].pfltVal;}break;case VT_R8:pBDXData->data.raw_data_with_type[i].type = BDX_DOUBLE;if(!V_ISBYREF(&lVariantArray[i])) {pBDXData->data.raw_data_with_type[i].raw_data.double_value = lVariantArray[i].dblVal;} else {pBDXData->data.raw_data_with_type[i].raw_data.double_value = *lVariantArray[i].pdblVal;}break;case VT_BSTR:pBDXData->data.raw_data_with_type[i].type = BDX_STRING;if(!V_ISBYREF(&lVariantArray[i])) {pBDXData->data.raw_data_with_type[i].raw_data.string_value = MyW2A(lVariantArray[i].bstrVal);} else {pBDXData->data.raw_data_with_type[i].raw_data.string_value = MyW2A(*lVariantArray[i].pbstrVal);}break;case VT_EMPTY: /* empty cells in Excel for example */pBDXData->data.raw_data_with_type[i].type = BDX_SPECIAL;pBDXData->data.raw_data_with_type[i].raw_data.special_value =BDX_SV_NULL;break;case VT_ERROR:pBDXData->data.raw_data_with_type[i].type = BDX_SPECIAL;{SCODE sc;if(!V_ISBYREF(&lVariantArray[i])) {sc = lVariantArray[i].scode;} else {sc = *lVariantArray[i].pscode;}pBDXData->data.raw_data_with_type[i].raw_data.special_value =getSpecialValueFromSCODE(sc);}break;default:BDX_ERR(printf("VariantVariantArray2BDX: internal error (#1, type %d at %i)\n",V_VT(&lVariantArray[i]),i));break;}}}SafeArrayUnlock (lArray);return 0;}static unsigned long getSpecialValueFromSCODE(SCODE pSCODE){/* excel specifies cell errors with the following typedef. These are ORed with 0x800a0000typedef enum {xlErrDiv0 = 2007,xlErrNA = 2042,xlErrName = 2029,xlErrNull = 2000,xlErrNum = 2036,xlErrRef = 2023,xlErrValue = 2015} XlCVError;*/switch(pSCODE & ~0x800a0000) {case 2007: /* xlErrDiv0 */return BDX_SV_DIV0;case 2042: /* xlErrNA */return BDX_SV_NA;break;case 2000: /* xlErrNull */return BDX_SV_NULL;break;default:return BDX_SV_UNK;}}static SCODE getSCODEFromSpecialValue(unsigned long pSpecialVal){/* excel specifies cell errors with the following typedef. These are ORed with 0x800a0000typedef enum {xlErrDiv0 = 2007,xlErrNA = 2042,xlErrName = 2029,xlErrNull = 2000,xlErrNum = 2036,xlErrRef = 2023,xlErrValue = 2015} XlCVError;*/switch(pSpecialVal) {case BDX_SV_NULL:return 0x800a0000 | 2000;case BDX_SV_NA:return 0x800a0000 | 2042;case BDX_SV_DIV0:case BDX_SV_INF:case BDX_SV_NAN:case BDX_SV_NINF:/* DIV/0 and +Inf transform to +Inf *//* NAN is just NaN *//* -Inf is -Inf */return 0x800a0000 | 2007;case BDX_SV_UNK:default:return 0x800a0000 | 2042;}}