Hi, This obsoletes the last parts of my vb6 rollup patch. Ciao, Marcus Changelog: Handle VT_ERROR->VT_I4/VT_R4 coercion. VariantCopy does not need to check the return of VariantClear. VariantCopyInd now copies VT_UNKNOWN and VT_DISPATCH too. VarCmp handles VT_BOOL. VarFormat handles VT_BSTR. coerce_array fixed for VT_ARRAY|VT_UI1 -> VT_BSTR and VT_ARRAY|x -> VT_SAFEARRAY cases. VarCat tries to coerce types into VT_BSTR to do cat. Index: dlls/oleaut32/variant.c =================================================================== RCS file: /home/wine/wine/dlls/oleaut32/variant.c,v retrieving revision 1.50 diff -u -r1.50 variant.c --- variant.c 23 Dec 2002 02:03:10 -0000 1.50 +++ variant.c 28 Dec 2002 22:28:26 -0000 @@ -1164,7 +1164,12 @@ break; case( VT_I2 ): res = VarI4FromI2( V_UNION(ps,iVal), &V_UNION(pd,lVal) ); - break; + + break; + case( VT_ERROR ): + V_UNION(pd,lVal) = V_UNION(pd,scode); + res = S_OK; + break; case( VT_INT ): case( VT_I4 ): res = VariantCopy( pd, ps ); @@ -1391,9 +1396,9 @@ case( VT_UI4 ): res = VarR4FromUI4( V_UNION(ps,ulVal), &V_UNION(pd,fltVal) ); break; - case( VT_R4 ): - res = VariantCopy( pd, ps ); - break; + case( VT_R4 ): + res = VariantCopy( pd, ps ); + break; case( VT_R8 ): res = VarR4FromR8( V_UNION(ps,dblVal), &V_UNION(pd,fltVal) ); break; @@ -1409,6 +1414,10 @@ case( VT_CY ): res = VarR4FromCy( V_UNION(ps,cyVal), &V_UNION(pd,fltVal) ); break; + case( VT_ERROR ): + V_UNION(pd,fltVal) = V_UNION(ps,scode); + res = S_OK; + break; case( VT_DISPATCH ): /*res = VarR4FromDisp( V_UNION(ps,pdispVal), lcid, &V_UNION(pd,fltVal) );*/ case( VT_DECIMAL ): @@ -1919,64 +1929,61 @@ */ if( pvargDest != pvargSrc && res == S_OK ) { - res = VariantClear( pvargDest ); + VariantClear( pvargDest ); /* result is not checked */ - if( res == S_OK ) + if( V_VT(pvargSrc) & VT_BYREF ) + { + /* In the case of byreference we only need + * to copy the pointer. + */ + pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3; + V_VT(pvargDest) = V_VT(pvargSrc); + } + else { - if( V_VT(pvargSrc) & VT_BYREF ) + /* + * The VT_ARRAY flag is another way to designate a safe array. + */ + if (V_VT(pvargSrc) & VT_ARRAY) { - /* In the case of byreference we only need - * to copy the pointer. - */ - pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3; - V_VT(pvargDest) = V_VT(pvargSrc); + SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray)); } else { - /* - * The VT_ARRAY flag is another way to designate a safe array. + /* In the case of by value we need to + * copy the actual value. In the case of + * VT_BSTR a copy of the string is made, + * if VT_DISPATCH or VT_IUNKNOWN AddRef is + * called to increment the object's reference count. */ - if (V_VT(pvargSrc) & VT_ARRAY) - { - SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray)); - } - else + switch( V_VT(pvargSrc) & VT_TYPEMASK ) { - /* In the case of by value we need to - * copy the actual value. In the case of - * VT_BSTR a copy of the string is made, - * if VT_DISPATCH or VT_IUNKNOWN AddRef is - * called to increment the object's reference count. - */ - switch( V_VT(pvargSrc) & VT_TYPEMASK ) - { - case( VT_BSTR ): - V_UNION(pvargDest,bstrVal) = SYSDUPSTRING( V_UNION(pvargSrc,bstrVal) ); - break; - case( VT_DISPATCH ): - V_UNION(pvargDest,pdispVal) = V_UNION(pvargSrc,pdispVal); - if (V_UNION(pvargDest,pdispVal)!=NULL) - ICOM_CALL(AddRef,V_UNION(pvargDest,pdispVal)); - break; - case( VT_VARIANT ): - VariantCopy(V_UNION(pvargDest,pvarVal),V_UNION(pvargSrc,pvarVal)); - break; - case( VT_UNKNOWN ): - V_UNION(pvargDest,punkVal) = V_UNION(pvargSrc,punkVal); - if (V_UNION(pvargDest,pdispVal)!=NULL) - ICOM_CALL(AddRef,V_UNION(pvargDest,punkVal)); - break; - case( VT_SAFEARRAY ): - SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray)); - break; - default: - pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3; - break; - } + case( VT_BSTR ): + V_UNION(pvargDest,bstrVal) = SYSDUPSTRING( V_UNION(pvargSrc,bstrVal) ); + break; + case( VT_DISPATCH ): + V_UNION(pvargDest,pdispVal) = V_UNION(pvargSrc,pdispVal); + if (V_UNION(pvargDest,pdispVal)!=NULL) + ICOM_CALL(AddRef,V_UNION(pvargDest,pdispVal)); + break; + case( VT_VARIANT ): + VariantCopy(V_UNION(pvargDest,pvarVal),V_UNION(pvargSrc,pvarVal)); + break; + case( VT_UNKNOWN ): + V_UNION(pvargDest,punkVal) = V_UNION(pvargSrc,punkVal); + if (V_UNION(pvargDest,pdispVal)!=NULL) + ICOM_CALL(AddRef,V_UNION(pvargDest,punkVal)); + break; + case( VT_SAFEARRAY ): + SafeArrayCopy(V_UNION(pvargSrc,parray), &V_UNION(pvargDest,parray)); + break; + default: + pvargDest->n1.n2.n3 = pvargSrc->n1.n2.n3; + break; } - - V_VT(pvargDest) = V_VT(pvargSrc); } + V_VT(pvargDest) = V_VT(pvargSrc); + dump_Variant(pvargDest); } } @@ -2043,6 +2050,9 @@ V_UNION(pvargDest,bstrVal) = SYSDUPSTRING( *(V_UNION(pvargSrc,pbstrVal)) ); break; case( VT_DISPATCH ): + V_UNION(pvargDest,pdispVal) = *V_UNION(pvargSrc,ppdispVal); + if (V_UNION(pvargDest,pdispVal)!=NULL) + ICOM_CALL(AddRef,V_UNION(pvargDest,pdispVal)); break; case( VT_VARIANT ): { @@ -2079,6 +2089,9 @@ } break; case( VT_UNKNOWN ): + V_UNION(pvargDest,punkVal) = *V_UNION(pvargSrc,ppunkVal); + if (V_UNION(pvargDest,pdispVal)!=NULL) + ICOM_CALL(AddRef,V_UNION(pvargDest,punkVal)); break; case( VT_SAFEARRAY ): SafeArrayCopy(*V_UNION(pvargSrc,pparray), &V_UNION(pvargDest,parray)); @@ -2118,53 +2131,42 @@ */ static HRESULT coerce_array( - VARIANTARG* src, SAFEARRAY **narr, LCID lcid, USHORT wFlags, VARTYPE vt + VARIANTARG* src, VARIANTARG *dst, LCID lcid, USHORT wFlags, VARTYPE vt ) { - int elems,i,j; - SAFEARRAY *darr, *sarr = V_ARRAY(src); - long *addr; + SAFEARRAY *sarr = V_ARRAY(src); HRESULT hres; + LPVOID data; + VARTYPE vartype; - hres = SafeArrayAllocDescriptor( sarr->cDims, &darr); - if (FAILED(hres)) return hres; - memcpy( - darr->rgsabound, - sarr->rgsabound, - sizeof(sarr->rgsabound[0])*sarr->cDims - ); - hres = SafeArrayAllocData(darr); - if (FAILED(hres)) { - SafeArrayDestroyDescriptor(darr); - return hres; - } - elems = 1; - for (i=0;i<sarr->cDims;i++) - elems *= sarr->rgsabound[i].cElements; - addr = HeapAlloc(GetProcessHeap(),0,sizeof(long)*sarr->cDims); - for (i=0;i<elems;i++) { - VARIANT tmpvar,newvar; - int tmpi = i; - /* convert absolute value in array address */ - for (j=0;j<sarr->cDims;j++) { - addr[j] = (tmpi % sarr->rgsabound[j].cElements) + sarr->rgsabound[j].lLbound; - tmpi /= sarr->rgsabound[j].cElements; - } - V_VT(&tmpvar) = V_VT(src) & VT_TYPEMASK; - hres = SafeArrayGetElement(sarr, addr, &V_UNION(&tmpvar,lVal)); - if (FAILED(hres)) { - FIXME("Did not get element %d\n",i); + SafeArrayGetVartype(sarr,&vartype); + switch (vt) { + case VT_BSTR: + if (sarr->cDims != 1) { + FIXME("Can not coerce array with dim %d into BSTR\n", sarr->cDims); return E_FAIL; } - hres = Coerce( &newvar, lcid, wFlags, &tmpvar, vt ); - if (FAILED(hres)) return E_FAIL; - hres = SafeArrayPutElement( darr, addr, &V_UNION(&newvar,lVal)); - if (FAILED(hres)) { - FIXME("SAPE failed for element %d, %lx\n",i,hres); + switch (V_VT(src) & VT_TYPEMASK) { + case VT_UI1: + hres = SafeArrayAccessData(sarr, &data); + if (FAILED(hres)) return hres; + + /* Yes, just memcpied apparently. */ + V_BSTR(dst) = SysAllocStringByteLen(data, sarr->rgsabound[0].cElements); + hres = SafeArrayUnaccessData(sarr); + if (FAILED(hres)) return hres; + break; + default: + FIXME("Cannot coerce array of %d into BSTR yet. Please report!\n", V_VT(src) & VT_TYPEMASK); return E_FAIL; } + break; + case VT_SAFEARRAY: + V_VT(dst) = VT_SAFEARRAY; + return SafeArrayCopy(sarr, &V_ARRAY(dst)); + default: + FIXME("Cannot coerce array of vt 0x%x/0x%x into vt 0x%x yet. Please report/implement!\n", vartype, V_VT(src), vt); + return E_FAIL; } - HeapFree(GetProcessHeap(),0,addr); - *narr = darr; return S_OK; } @@ -2239,7 +2241,6 @@ */ VariantClear( &Variant ); } - } else { if (V_VT(pvargSrc) & VT_ARRAY) { if ((V_VT(pvargSrc) & 0xf000) != VT_ARRAY) { @@ -2247,7 +2248,7 @@ return E_FAIL; } V_VT(pvargDest) = VT_ARRAY | vt; - res = coerce_array(pvargSrc, &V_ARRAY(pvargDest), lcid, wFlags, vt); + res = coerce_array(pvargSrc, pvargDest, lcid, wFlags, vt); } else { if ((V_VT(pvargSrc) & 0xf000)) { FIXME("VT_TYPEMASK %x is unhandled in normal case.\n",V_VT(pvargSrc) & VT_TYPEMASK); @@ -5022,14 +5024,40 @@ V_VT(out) = VT_NULL; return S_OK; } - else if (V_VT(left) == VT_BSTR && V_VT(right) == VT_BSTR) + + if (V_VT(left) == VT_BSTR && V_VT(right) == VT_BSTR) { V_VT(out) = VT_BSTR; VarBstrCat (V_BSTR(left), V_BSTR(right), &V_BSTR(out)); return S_OK; } - else - FIXME ("types not supported\n"); + if (V_VT(left) == VT_BSTR) { + VARIANT bstrvar; + HRESULT hres; + + V_VT(out) = VT_BSTR; + hres = VariantChangeTypeEx(&bstrvar,right,0,0,VT_BSTR); + if (hres) { + FIXME("Failed to convert right side from vt %d to VT_BSTR?\n",V_VT(right)); + return hres; + } + VarBstrCat (V_BSTR(left), V_BSTR(&bstrvar), &V_BSTR(out)); + return S_OK; + } + if (V_VT(right) == VT_BSTR) { + VARIANT bstrvar; + HRESULT hres; + + V_VT(out) = VT_BSTR; + hres = VariantChangeTypeEx(&bstrvar,left,0,0,VT_BSTR); + if (hres) { + FIXME("Failed to convert right side from vt %d to VT_BSTR?\n",V_VT(right)); + return hres; + } + VarBstrCat (V_BSTR(&bstrvar), V_BSTR(right), &V_BSTR(out)); + return S_OK; + } + FIXME ("types %d / %d not supported\n",V_VT(left)&VT_TYPEMASK, V_VT(right)&VT_TYPEMASK); return S_OK; } @@ -5078,6 +5106,7 @@ case VT_UI2 : lVal = V_UNION(left,uiVal); break; case VT_UI4 : lVal = V_UNION(left,ulVal); break; case VT_UINT : lVal = V_UNION(left,ulVal); break; + case VT_BOOL : lVal = V_UNION(left,boolVal); break; default: lOk = FALSE; } @@ -5091,6 +5120,7 @@ case VT_UI2 : rVal = V_UNION(right,uiVal); break; case VT_UI4 : rVal = V_UNION(right,ulVal); break; case VT_UINT : rVal = V_UNION(right,ulVal); break; + case VT_BOOL : rVal = V_UNION(right,boolVal); break; default: rOk = FALSE; } @@ -5139,7 +5169,7 @@ } - FIXME("VarCmp partial implementation, doesnt support these pair of variant types"); + FIXME("VarCmp partial implementation, doesnt support vt 0x%x / 0x%x\n",V_VT(left), V_VT(right)); return E_FAIL; } @@ -5824,13 +5854,18 @@ } else if ((V_VT(varIn)&VT_TYPEMASK) == VT_R8) { if (V_VT(varIn)&VT_BYREF) { - sprintf(pBuffer, "%f", *(double *)V_UNION(varIn,byref)); + sprintf(pBuffer, "%f", *V_UNION(varIn,pdblVal)); } else { sprintf(pBuffer, "%f", V_UNION(varIn,dblVal)); } *pbstrOut = StringDupAtoBstr( pBuffer ); + } else if ((V_VT(varIn)&VT_TYPEMASK) == VT_BSTR) { + if (V_VT(varIn)&VT_BYREF) + *pbstrOut = SysAllocString( *V_UNION(varIn,pbstrVal) ); + else + *pbstrOut = SysAllocString( V_UNION(varIn,bstrVal) ); } else { FIXME("VarFormat: Unsupported format %d!\n", V_VT(varIn)&VT_TYPEMASK); *pbstrOut = StringDupAtoBstr( "??" );