VB-Error: Type mismatch

Fabian Cenedese Cenedese at indel.ch
Wed Feb 25 03:15:15 CST 2004


>>I'm trying (again) to run a VB app on wine. But it never shows up. Instead
>>I only see a dialog with this Type mismatch error and then it quits. I tried
>>to find the place where it goes wrong. Apparently it tries to parse a number
>>from a string in VB notation.
>>0009:trace:ole:VarParseNumFromStr (L"&H8000",1024,0x00000000,0x408bdee0,0x408bdae0)
>
>I found that this string "&H8000" comes from my code and it's intentional.
>In VB you can convert a string to a long by using i=CLng(str). But if the
>string number is in hex format it needs to be VB hex notation. This works
>on Windows and fails on wine. I now need to find out how CLng(str)
>converts the string and why this is different on wine.

Contrary to my first tests these API functions understand VB hex
numbers quite well. There is no problem with these calls on Win2K:

OLECHAR test[]={'&', 'H', 'F', '0', '8', 'F', '\0'};
VarI4FromStr(test, LANG_NEUTRAL, NUMPRS_STD, &out);
VarParseNumFromStr(test, LANG_NEUTRAL, NUMPRS_STD, &np, rgb);

So I implemented this in wine too. If anybody has a program (mostly VB)
that uses hex numbers in strings please try it out. Without any other remarks
I'll send it to wine-patches.

bye  Fabi



Index: wine/dlls/oleaut32/variant.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/variant.c,v
retrieving revision 1.88
diff -u -r1.88 variant.c
--- wine/dlls/oleaut32/variant.c        25 Feb 2004 01:35:01 -0000      1.88
+++ wine/dlls/oleaut32/variant.c        25 Feb 2004 08:00:10 -0000
@@ -1468,6 +1468,7 @@
 #define B_EXPONENT_START      0x4
 #define B_INEXACT_ZEROS       0x8
 #define B_LEADING_ZERO        0x10
+#define B_PROCESSING_HEX      0x20
 
 /**********************************************************************
  *              VarParseNumFromStr [OLEAUT32.46]
@@ -1698,6 +1699,33 @@
       dwState |= B_NEGATIVE_EXPONENT;
       cchUsed++;
     }
+    else if ((*lpszStr == '&' && *(lpszStr+1) == 'H') &&
+             pNumprs->dwInFlags & NUMPRS_HEX_OCT &&
+             !(pNumprs->dwOutFlags & NUMPRS_EXPONENT))
+    {
+      dwState |= B_PROCESSING_HEX;
+      pNumprs->dwOutFlags |= NUMPRS_HEX_OCT;
+      cchUsed=cchUsed+2;
+      lpszStr++;
+    }
+    else if (((*lpszStr >= 'a' && *lpszStr <= 'f') ||
+             (*lpszStr >= 'A' && *lpszStr <= 'F')) &&
+             dwState & B_PROCESSING_HEX)
+    {
+      if (pNumprs->cDig >= iMaxDigits)
+      {
+        return DISP_E_OVERFLOW;
+      }
+      else
+      {
+        if (*lpszStr >= 'a')
+          rgbTmp[pNumprs->cDig] = *lpszStr - 'a' + 10;
+        else
+          rgbTmp[pNumprs->cDig] = *lpszStr - 'A' + 10;
+      }
+      pNumprs->cDig++;
+      cchUsed++;
+    }
     else
       break; /* Stop at an unrecognised character */
 
@@ -1728,14 +1756,20 @@
     /* cDig of X and writes X+Y where Y>=0 number of digits to rgbDig */
     memcpy(rgbDig, rgbTmp, pNumprs->cDig * sizeof(BYTE));
 
-    while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
-    {
-      if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
-        pNumprs->nPwr10--;
-      else
-        pNumprs->nPwr10++;
+    if (dwState & B_PROCESSING_HEX) {
+      /* hex number have always the same format */
+      pNumprs->nPwr10=0;
+      pNumprs->nBaseShift=4;
+    } else {
+      while (pNumprs->cDig > 1 && !rgbTmp[pNumprs->cDig - 1])
+      {
+        if (pNumprs->dwOutFlags & NUMPRS_DECIMAL)
+          pNumprs->nPwr10--;
+        else
+          pNumprs->nPwr10++;
 
-      pNumprs->cDig--;
+        pNumprs->cDig--;
+      }
     }
   } else
   {
@@ -1870,7 +1904,110 @@
   if (pNumprs->nBaseShift)
   {
     /* nBaseShift indicates a hex or octal number */
-    FIXME("nBaseShift=%d not yet implemented, returning overflow\n", pNumprs->nBaseShift);
+    ULONG64 ul64 = 0;
+    LONG64 l64;
+    int i;
+
+    /* Convert the hex or octal number string into a UI64 */
+    for (i = 0; i < pNumprs->cDig; i++)
+    {
+      if (ul64 > ((UI8_MAX>>pNumprs->nBaseShift) - rgbDig[i]))
+      {
+        TRACE("Overflow multiplying digits\n");
+        return DISP_E_OVERFLOW;
+      }
+      ul64 = (ul64<<pNumprs->nBaseShift) + rgbDig[i];
+    }
+
+    /* also make a negative representation */
+    l64=-ul64;
+
+    /* Try signed and unsigned types in size order */
+    if (dwVtBits & VTBIT_I1 && ((ul64 <= I1_MAX)||(l64 >= I1_MIN)))
+    {
+      V_VT(pVarDst) = VT_I1;
+      if (ul64 <= I1_MAX)
+          V_I1(pVarDst) = ul64;
+      else
+          V_I1(pVarDst) = l64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_UI1 && ul64 <= UI1_MAX)
+    {
+      V_VT(pVarDst) = VT_UI1;
+      V_UI1(pVarDst) = ul64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_I2 && ((ul64 <= I2_MAX)||(l64 >= I2_MIN)))
+    {
+      V_VT(pVarDst) = VT_I2;
+      if (ul64 <= I2_MAX)
+          V_I2(pVarDst) = ul64;
+      else
+          V_I2(pVarDst) = l64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_UI2 && ul64 <= UI2_MAX)
+    {
+      V_VT(pVarDst) = VT_UI2;
+      V_UI2(pVarDst) = ul64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_I4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
+    {
+      V_VT(pVarDst) = VT_I4;
+      if (ul64 <= I4_MAX)
+          V_I4(pVarDst) = ul64;
+      else
+          V_I4(pVarDst) = l64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_UI4 && ul64 <= UI4_MAX)
+    {
+      V_VT(pVarDst) = VT_UI4;
+      V_UI4(pVarDst) = ul64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_I8 && ((ul64 <= I4_MAX)||(l64>=I4_MIN)))
+    {
+      V_VT(pVarDst) = VT_I8;
+      V_I8(pVarDst) = ul64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_UI8)
+    {
+      V_VT(pVarDst) = VT_UI8;
+      V_UI8(pVarDst) = ul64;
+      return S_OK;
+    }
+    else if ((dwVtBits & REAL_VTBITS) == VTBIT_DECIMAL)
+    {
+      V_VT(pVarDst) = VT_DECIMAL;
+      DEC_SIGNSCALE(&V_DECIMAL(pVarDst)) = SIGNSCALE(DECIMAL_POS,0);
+      DEC_HI32(&V_DECIMAL(pVarDst)) = 0;
+      DEC_LO64(&V_DECIMAL(pVarDst)) = ul64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_R4 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
+    {
+      V_VT(pVarDst) = VT_R4;
+      if (ul64 <= I4_MAX)
+          V_R4(pVarDst) = ul64;
+      else
+          V_R4(pVarDst) = l64;
+      return S_OK;
+    }
+    else if (dwVtBits & VTBIT_R8 && ((ul64 <= I4_MAX)||(l64 >= I4_MIN)))
+    {
+      V_VT(pVarDst) = VT_R8;
+      if (ul64 <= I4_MAX)
+          V_R8(pVarDst) = ul64;
+      else
+          V_R8(pVarDst) = l64;
+      return S_OK;
+    }
+
+    TRACE("Overflow: possible return types: 0x%lx, value: %s\n", dwVtBits, wine_dbgstr_longlong(ul64));
     return DISP_E_OVERFLOW;
   }
 
Index: wine/dlls/oleaut32/tests/vartest.c
===================================================================
RCS file: /home/wine/wine/dlls/oleaut32/tests/vartest.c,v
retrieving revision 1.23
diff -u -r1.23 vartest.c
--- wine/dlls/oleaut32/tests/vartest.c  6 Feb 2004 05:23:48 -0000       1.23
+++ wine/dlls/oleaut32/tests/vartest.c  25 Feb 2004 08:00:13 -0000
@@ -789,6 +789,15 @@
   EXPECTRGB(2,0);
   EXPECTRGB(3,FAILDIG);
 
+  /* VB hex */
+  CONVERT("&HF800", NUMPRS_HEX_OCT);
+  EXPECT(4,NUMPRS_HEX_OCT,0x40,6,4,0);
+  EXPECTRGB(0,15);
+  EXPECTRGB(1,8);
+  EXPECTRGB(2,0);
+  EXPECTRGB(3,0);
+  EXPECTRGB(4,FAILDIG);
+
   /** NUMPRS_PARENS **/
 
   /* Empty parens = error */





More information about the wine-devel mailing list