PATCH: oleaut32 / vb6 rollup

Marcus Meissner mm at lst.de
Tue Dec 24 07:49:00 CST 2002


Hi,

this is a oleaut32 rollup patch.

After this, one larger VB6 application called AccuTerm 2000 runs up to the
point where it displays the main screen. It still has more failures, but
I am working on it.

Ciao, Marcus

Changelog:
	Added some wstr to .spec entries which get BSTR arguments.
	In OleCreatePictureEx icons have width/height to query.
	DispCallFunc should pass the interface ptr during the call.
	VariantCopy does not check the result of VariantClear. (added testcase)
	VariantCopyInd does copy VT_DISPATCH and VT_UNKNOWN (and no longer
	just silently fails).
	VT_ARRAY|VT_UI1 -> VT_BSTR coercion is just a memcpy apparently
	(added testcase).
	VarBstrCat enhanced a bit.

Index: oleaut32.spec
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/oleaut32.spec,v
retrieving revision 1.46
diff -u -r1.46 oleaut32.spec
--- oleaut32.spec	23 Dec 2002 02:02:50 -0000	1.46
+++ oleaut32.spec	24 Dec 2002 13:35:43 -0000
@@ -2,7 +2,7 @@
 2 stdcall SysAllocString(wstr) SysAllocString
 3 stdcall SysReAllocString(ptr wstr) SysReAllocString
 4 stdcall SysAllocStringLen(wstr long) SysAllocStringLen
-5 stdcall SysReAllocStringLen(ptr ptr long) SysReAllocStringLen
+5 stdcall SysReAllocStringLen(ptr wstr long) SysReAllocStringLen
 6 stdcall SysFreeString(wstr) SysFreeString
 7 stdcall SysStringLen(wstr) SysStringLen
 8 stdcall VariantInit(ptr) VariantInit
@@ -145,8 +145,8 @@
 146 stdcall DispCallFunc(ptr long long long long ptr ptr ptr) DispCallFunc
 147 stdcall VariantChangeTypeEx(ptr ptr long long long) VariantChangeTypeEx
 148 stdcall SafeArrayPtrOfIndex(ptr ptr ptr) SafeArrayPtrOfIndex
-149 stdcall SysStringByteLen(ptr) SysStringByteLen
-150 stdcall SysAllocStringByteLen(ptr long) SysAllocStringByteLen
+149 stdcall SysStringByteLen(wstr) SysStringByteLen
+150 stdcall SysAllocStringByteLen(wstr long) SysAllocStringByteLen
 152 stub VarEqv # stdcall (ptr ptr ptr)
 153 stub VarIdiv # stdcall (ptr ptr ptr)
 154 stub VarImp # stdcall (ptr ptr ptr)
Index: olepicture.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/olepicture.c,v
retrieving revision 1.20
diff -u -r1.20 olepicture.c
--- olepicture.c	11 Nov 2002 19:54:22 -0000	1.20
+++ olepicture.c	24 Dec 2002 13:35:53 -0000
@@ -997,6 +997,8 @@
     } else {
 	This->desc.picType = PICTYPE_ICON;
 	This->desc.u.icon.hicon = hicon;
+	This->himetricWidth = cifd->idEntries[i].bWidth;
+	This->himetricHeight = cifd->idEntries[i].bHeight;
 	hr = S_OK;
     }
     break;
Index: typelib.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/typelib.c,v
retrieving revision 1.84
diff -u -r1.84 typelib.c
--- typelib.c	12 Dec 2002 22:59:25 -0000	1.84
+++ typelib.c	24 Dec 2002 13:36:56 -0000
@@ -4113,7 +4108,7 @@
         argsize += _argsize(prgvt[i]);
     }
     args = (DWORD*)HeapAlloc(GetProcessHeap(),0,sizeof(DWORD)*argsize);
-    args[0]=0;      /* this is the fake IDispatch interface pointer */
+    args[0] = pvInstance;      /* this is the fake IDispatch interface pointer */
     argspos = 1;
     for (i=0;i<cActuals;i++) {
 	int arglen;
Index: 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	24 Dec 2002 13:37:28 -0000
@@ -1919,64 +1920,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 +2041,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 +2080,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 +2122,37 @@
  */
 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;
 
-	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);
+	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;
+	default:
+		FIXME("Cannot coerce array into vt %d yet. Please report/implement!\n", vt);
+		return E_FAIL;
 	}
-	HeapFree(GetProcessHeap(),0,addr);
-	*narr = darr;
 	return S_OK;
 }
 
@@ -2239,7 +2227,6 @@
 				 */
 				VariantClear( &Variant );
 			}
-
 		} else {
 			if (V_VT(pvargSrc) & VT_ARRAY) {
 				if ((V_VT(pvargSrc) & 0xf000) != VT_ARRAY) {
@@ -2247,7 +2234,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 +5010,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;
 }
 
Index: tests/safearray.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/tests/safearray.c,v
retrieving revision 1.1
diff -u -r1.1 safearray.c
--- tests/safearray.c	23 Dec 2002 02:02:49 -0000	1.1
+++ tests/safearray.c	24 Dec 2002 13:37:30 -0000
@@ -37,7 +37,7 @@
 #include "oleauto.h"
 
 #define VARTYPE_NOT_SUPPORTED 0
-static int vttypes[] = {
+static UINT vttypes[] = {
   /* this is taken from wtypes.h.  Only [S]es are supported by the SafeArray */
 VARTYPE_NOT_SUPPORTED,  /* VT_EMPTY    [V]   [P]    nothing			*/
 VARTYPE_NOT_SUPPORTED,  /* VT_NULL     [V]   [P]    SQL style Nul	*/
@@ -88,9 +88,11 @@
 START_TEST(safearray)
 {
 	SAFEARRAY 	*a;
-	int 		i;
+	unsigned int 	i;
 	HRESULT 	hres;
 	SAFEARRAYBOUND	bound;
+	VARIANT		v;
+	LPVOID		data;
 
 	hres = SafeArrayAllocDescriptor(0,&a);
 	ok(E_INVALIDARG == hres,"SAAD(0) failed with hres %lx",hres);
@@ -100,12 +102,12 @@
 
 	for (i=1;i<100;i++) {
 		hres=SafeArrayAllocDescriptor(i,&a);
-		ok(S_OK == hres,"SAAD(%d) failed with %lx\n",i,hres);
+		ok(S_OK == hres,"SAAD(%d) failed with %lx",i,hres);
 		
-		ok(a->cDims == i,"a->cDims not initialised?\n");
+		ok(a->cDims == i,"a->cDims not initialised?");
 
 		hres=SafeArrayDestroyDescriptor(a);
-		ok(S_OK == hres,"SADD failed with %lx\n",hres);
+		ok(S_OK == hres,"SADD failed with %lx",hres);
 	}
 
 	hres=SafeArrayAllocDescriptor(65535,&a);
@@ -124,13 +126,29 @@
 	bound.cElements	= 1;
 	bound.lLbound	= 0;
 	a = SafeArrayCreate(-1, 1, &bound);
-	ok(NULL == a,"SAC(-1,1,[1,0]) not failed?\n");
+	ok(NULL == a,"SAC(-1,1,[1,0]) not failed?");
 	
 	for (i=0;i<sizeof(vttypes)/sizeof(vttypes[0]);i++) {
 		a = SafeArrayCreate(i, 1, &bound);
 		ok(	((a == NULL) && (vttypes[i] == 0)) ||
 			((a != NULL) && (vttypes[i] == a->cbElements)),
-		"SAC(%d,1,[1,0]), result %ld, expected %d\n",i,(a?a->cbElements:0),vttypes[i]
+		"SAC(%d,1,[1,0]), result %ld, expected %d",i,(a?a->cbElements:0),vttypes[i]
 		);
 	}
+
+
+	/* Test conversion of type|VT_ARRAY <-> VT_BSTR */
+	bound.lLbound = 0;
+	bound.cElements = 10;
+	a = SafeArrayCreate(VT_UI1, 1, &bound);
+	ok(a != NULL, "SAC failed.");
+	ok(S_OK == SafeArrayAccessData(a, &data),"SACD failed");
+	memcpy(data,"Hello World",10);
+	ok(S_OK == SafeArrayUnaccessData(a),"SAUD failed");
+	V_VT(&v) = VT_ARRAY|VT_UI1;
+	V_ARRAY(&v) = a;
+	hres = VariantChangeTypeEx(&v, &v, 0, 0, VT_BSTR);
+	ok(hres==S_OK, "CTE VT_ARRAY|VT_UI1 -> VT_BSTR failed with %lx",hres);
+	ok(V_VT(&v) == VT_BSTR,"CTE VT_ARRAY|VT_UI1 -> VT_BSTR did not return VT_BSTR, but %d.",V_VT(&v));
+	ok(V_BSTR(&v)[0] == 0x6548,"First letter are not 'He', but %x", V_BSTR(&v)[0]);
 }
Index: tests/vartest.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/tests/vartest.c,v
retrieving revision 1.5
diff -u -r1.5 vartest.c
--- tests/vartest.c	24 Dec 2002 00:49:27 -0000	1.5
+++ tests/vartest.c	24 Dec 2002 13:37:41 -0000
@@ -2610,12 +2610,20 @@
 		    sprintf(msg,"vt %d, return value %lx, expected was %lx",vartypes[i].ind,rc,vartypes[i].vcex1);
 		    ok(vartypes[i].vcex2 == rc, msg);
 
-		V_VT(&va) = 99;
-		d = 4.123;
-		V_UNION(&va,dblVal) = d;
-		ok(DISP_E_BADVARTYPE == VariantClear( &va ), "should give DISP_E_BADVARTYPE");
 	}
 #endif
+
+	V_VT(&va) = 99;
+	d = 4.123;
+	V_UNION(&va,dblVal) = d;
+	ok(DISP_E_BADVARTYPE == VariantClear( &va ), "should give DISP_E_BADVARTYPE");
+
+	V_VT(&va) = VT_BOOL;
+	V_BOOL(&va) = VARIANT_TRUE;
+	V_BOOL(&vb) = 99;
+
+	ok(S_OK == VariantCopy(&va, &vb),"VariantCopy to illegal variant did not return S_OK");
+
 	VariantClear( &va );
 	VariantClear( &vb );
 	VariantClear( &vc );



More information about the wine-patches mailing list