PATCH: variant stuff

Marcus Meissner marcus at jet.franken.de
Sat Dec 28 16:37:44 CST 2002


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( "??" );



More information about the wine-patches mailing list