Sync to Wine-20050524:
Alexandre Julliard <julliard@winehq.org>
- Added rules for building import libraries in the individual dll
  makefiles, and added support for building a .def.a static import
  library too.
Michael Stefaniuc <mstefani@redhat.de>
- Reimplement VarMul(). It can multiply now all variants that the native
  (WinXP) function supports too.
- Fix VariantChangeType: calls to VarDecFromCy and VarDecFromDisp had
  source and destination swapped.
Richard Cohen <richard@daijobu.co.uk>
- Remove unused macro.
- Check for VT_I8 before testing it.
- VarMod returns DISP_E_OVERFLOW not E_INVALIDARG.
Robert Shearman <rob@codeweavers.com>
- Use I_RpcGetBuffer instead of HeapReAlloc for getting the Buffer
  memory.
Vincent Beron <vberon@mecano.gme.usherb.ca>
- Use SUBLANG_NEUTRAL for French resources.
Alex Villacis Lasso <a_villacis@palosanto.com>
- Fix leftover negative sign in height parameter for transparent
  bitmap.
- Properly announce whether bitmap is transparent in get_Attributes.
- GIF transparency is now palette-index based, instead of RGB based.
- Keep original bitmap and XOR mask separate, so that get_Handle
  returns original bitmap.
Modified: trunk/reactos/lib/oleaut32/Makefile.in
Modified: trunk/reactos/lib/oleaut32/oleaut32_Fr.rc
Modified: trunk/reactos/lib/oleaut32/olepicture.c
Modified: trunk/reactos/lib/oleaut32/tmarshal.c
Modified: trunk/reactos/lib/oleaut32/variant.c

Modified: trunk/reactos/lib/oleaut32/Makefile.in
--- trunk/reactos/lib/oleaut32/Makefile.in	2005-05-28 09:30:04 UTC (rev 15562)
+++ trunk/reactos/lib/oleaut32/Makefile.in	2005-05-28 09:35:29 UTC (rev 15563)
@@ -4,6 +4,7 @@
 SRCDIR    = @srcdir@
 VPATH     = @srcdir@
 MODULE    = oleaut32.dll
+IMPORTLIB = liboleaut32.$(IMPLIBEXT)
 IMPORTS   = ole32 rpcrt4 user32 gdi32 advapi32 kernel32 ntdll
 DELAYIMPORTS = comctl32 urlmon
 EXTRALIBS = $(LIBUNICODE) -luuid

Modified: trunk/reactos/lib/oleaut32/oleaut32_Fr.rc
--- trunk/reactos/lib/oleaut32/oleaut32_Fr.rc	2005-05-28 09:30:04 UTC (rev 15562)
+++ trunk/reactos/lib/oleaut32/oleaut32_Fr.rc	2005-05-28 09:35:29 UTC (rev 15563)
@@ -18,7 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-LANGUAGE LANG_FRENCH, SUBLANG_DEFAULT
+LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL
 
 STRINGTABLE DISCARDABLE
 {

Modified: trunk/reactos/lib/oleaut32/olepicture.c
--- trunk/reactos/lib/oleaut32/olepicture.c	2005-05-28 09:30:04 UTC (rev 15562)
+++ trunk/reactos/lib/oleaut32/olepicture.c	2005-05-28 09:35:29 UTC (rev 15563)
@@ -132,6 +132,7 @@
 
   /* Bitmap transparency mask */
     HBITMAP hbmMask;
+    HBITMAP hbmXor;
     COLORREF rgbTrans;
 
   /* data */
@@ -262,6 +263,7 @@
   newObject->keepOrigFormat = TRUE;
 
   newObject->hbmMask = NULL;
+  newObject->hbmXor = NULL;
   newObject->loadtime_magic = 0xdeadbeef;
   newObject->loadtime_format = 0;
   newObject->bIsDirty = FALSE;
@@ -320,6 +322,8 @@
     switch(Obj->desc.picType) {
     case PICTYPE_BITMAP:
       DeleteObject(Obj->desc.u.bmp.hbitmap);
+      if (Obj->hbmMask != NULL) DeleteObject(Obj->hbmMask);
+      if (Obj->hbmXor != NULL) DeleteObject(Obj->hbmXor);
       break;
     case PICTYPE_METAFILE:
       DeleteMetaFile(Obj->desc.u.wmf.hmeta);
@@ -588,12 +592,12 @@
       SetViewportOrgEx(hdcBmp, 0, This->origHeight, NULL);
       SetViewportExtEx(hdcBmp, This->origWidth, -This->origHeight, NULL);
 
-      hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
-
       if (This->hbmMask) {
 	  HDC hdcMask = CreateCompatibleDC(0);
 	  HBITMAP hOldbm = SelectObject(hdcMask, This->hbmMask);
 
+          hbmpOld = SelectObject(hdcBmp, This->hbmXor);
+
 	  SetMapMode(hdcMask, MM_ANISOTROPIC);
 	  SetWindowOrgEx(hdcMask, 0, 0, NULL);
 	  SetWindowExtEx(hdcMask, This->himetricWidth, This->himetricHeight, NULL);
@@ -607,8 +611,10 @@
 
 	  SelectObject(hdcMask, hOldbm);
 	  DeleteDC(hdcMask);
-      } else
+      } else {
+          hbmpOld = SelectObject(hdcBmp, This->desc.u.bmp.hbitmap);
 	  StretchBlt(hdc, x, y, cx, cy, hdcBmp, xSrc, ySrc, cxSrc, cySrc, SRCCOPY);
+      }
 
       SelectObject(hdcBmp, hbmpOld);
       DeleteDC(hdcBmp);
@@ -739,7 +745,7 @@
   TRACE("(%p)->(%p).\n", This, pdwAttr);
   *pdwAttr = 0;
   switch (This->desc.picType) {
-  case PICTYPE_BITMAP: 	break;	/* not 'truly' scalable, see MSDN. */
+  case PICTYPE_BITMAP: 	if (This->hbmMask) *pdwAttr = PICTURE_TRANSPARENT; break;	/* not 'truly' scalable, see MSDN. */
   case PICTYPE_ICON: *pdwAttr     = PICTURE_TRANSPARENT;break;
   case PICTYPE_METAFILE: *pdwAttr = PICTURE_TRANSPARENT|PICTURE_SCALABLE;break;
   default:FIXME("Unknown pictype %d\n",This->desc.picType);break;
@@ -1175,15 +1181,60 @@
 	HBITMAP hOldbitmap; 
 	HBITMAP hOldbitmapmask;
 
-	This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
+        unsigned int monopadding = (((unsigned)(gif->SWidth + 31)) >> 5) << 2;
+        HBITMAP hTempMask;
 
-	hOldbitmap = SelectObject(hdc,This->desc.u.bmp.hbitmap);
+        This->hbmXor = CreateDIBitmap(
+            hdcref,
+            &bmi->bmiHeader,
+            CBM_INIT,
+            bytes,
+            bmi,
+            DIB_RGB_COLORS
+        );
+
+        bmi->bmiColors[0].rgbRed = 0;
+        bmi->bmiColors[0].rgbGreen = 0;
+        bmi->bmiColors[0].rgbBlue = 0;
+        bmi->bmiColors[1].rgbRed = 255;
+        bmi->bmiColors[1].rgbGreen = 255;
+        bmi->bmiColors[1].rgbBlue = 255;
+
+        bmi->bmiHeader.biBitCount		= 1;
+        bmi->bmiHeader.biSizeImage		= monopadding*gif->SHeight;
+        bmi->bmiHeader.biClrUsed		= 2;
+
+        for (i = 0; i < gif->SHeight; i++) {
+            unsigned char * colorPointer = bytes + padding * i;
+            unsigned char * monoPointer = bytes + monopadding * i;
+            for (j = 0; j < gif->SWidth; j++) {
+                unsigned char pixel = colorPointer[j];
+                if ((j & 7) == 0) monoPointer[j >> 3] = 0;
+                if (pixel == (transparent & 0x000000FFU)) monoPointer[j >> 3] |= 1 << (7 - (j & 7));
+            }
+        }
+        hdcref = GetDC(0);
+        hTempMask = CreateDIBitmap(
+                hdcref,
+                &bmi->bmiHeader,
+                CBM_INIT,
+                bytes,
+                bmi,
+                DIB_RGB_COLORS
+        );
+        DeleteDC(hdcref);
+
+        bmi->bmiHeader.biHeight = -bmi->bmiHeader.biHeight;
+        This->hbmMask = CreateBitmap(bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 1, 1, NULL);
+	hOldbitmap = SelectObject(hdc, hTempMask);
 	hOldbitmapmask = SelectObject(hdcMask, This->hbmMask);
-	SetBkColor(hdc, This->rgbTrans);
+
+        SetBkColor(hdc, RGB(255, 255, 255));
 	BitBlt(hdcMask, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, hdc, 0, 0, SRCCOPY);
 
 	/* We no longer need the original bitmap, so we apply the first
 	   transformation with the mask to speed up the rendering */
+        SelectObject(hdc, This->hbmXor);
 	SetBkColor(hdc, RGB(0,0,0));
 	SetTextColor(hdc, RGB(255,255,255));
 	BitBlt(hdc, 0, 0, bmi->bmiHeader.biWidth, bmi->bmiHeader.biHeight, 
@@ -1193,6 +1244,7 @@
 	SelectObject(hdcMask, hOldbitmapmask);
 	DeleteDC(hdcMask);
 	DeleteDC(hdc);
+        DeleteObject(hTempMask);
     }
     
     DeleteDC(hdcref);

Modified: trunk/reactos/lib/oleaut32/tmarshal.c
--- trunk/reactos/lib/oleaut32/tmarshal.c	2005-05-28 09:30:04 UTC (rev 15562)
+++ trunk/reactos/lib/oleaut32/tmarshal.c	2005-05-28 09:35:29 UTC (rev 15563)
@@ -1979,7 +1979,8 @@
 
     memset(&buf,0,sizeof(buf));
     buf.size	= xmsg->cbBuffer;
-    buf.base	= xmsg->Buffer;
+    buf.base	= HeapAlloc(GetProcessHeap(), 0, xmsg->cbBuffer);
+    memcpy(buf.base, xmsg->Buffer, xmsg->cbBuffer);
     buf.curoff	= 0;
     buf.iid	= IID_IUnknown;
 
@@ -2173,9 +2174,9 @@
     if (hres != S_OK)
 	return hres;
    
-    /* might need to use IRpcChannelBuffer_GetBuffer ? */
     xmsg->cbBuffer	= buf.curoff;
-    xmsg->Buffer	= buf.base;
+    I_RpcGetBuffer((RPC_MESSAGE *)xmsg);
+    memcpy(xmsg->Buffer, buf.base, buf.curoff);
     HeapFree(GetProcessHeap(),0,args);
     return S_OK;
 }

Modified: trunk/reactos/lib/oleaut32/variant.c
--- trunk/reactos/lib/oleaut32/variant.c	2005-05-28 09:30:04 UTC (rev 15562)
+++ trunk/reactos/lib/oleaut32/variant.c	2005-05-28 09:35:29 UTC (rev 15563)
@@ -493,8 +493,8 @@
     case VT_R4:       return VarDecFromR4(V_R4(ps), &V_DECIMAL(pd));
     case VT_R8:       return VarDecFromR8(V_R8(ps), &V_DECIMAL(pd));
     case VT_DATE:     return VarDecFromDate(V_DATE(ps), &V_DECIMAL(pd));
-    case VT_CY:       return VarDecFromCy(V_CY(pd), &V_DECIMAL(ps));
-    case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(ps));
+    case VT_CY:       return VarDecFromCy(V_CY(ps), &V_DECIMAL(pd));
+    case VT_DISPATCH: return VarDecFromDisp(V_DISPATCH(ps), lcid, &V_DECIMAL(pd));
     case VT_BSTR:     return VarDecFromStr(V_BSTR(ps), lcid, dwFlags, &V_DECIMAL(pd));
     }
     break;
@@ -2914,58 +2914,168 @@
 /**********************************************************************
  *              VarMul [OLEAUT32.156]
  *
+ * Multiply two variants.
+ *
+ * PARAMS
+ *  left    [I] First variant
+ *  right   [I] Second variant
+ *  result  [O] Result variant
+ *
+ * RETURNS
+ *  Success: S_OK.
+ *  Failure: An HRESULT error code indicating the error.
+ *
+ * NOTES
+ *  Native VarMul up to and including WinXP dosn't like as input variants
+ *  I1, UI2, UI4, UI8, INT and UINT. But it can multiply apples with oranges.
+ *
+ *  Native VarMul dosn't check for NULL in/out pointers and crashes. We do the
+ *  same here.
+ *
+ * FIXME
+ *  Overflow checking for R8 (double) overflow. Return DISP_E_OVERFLOW in that
+ *  case.
  */
 HRESULT WINAPI VarMul(LPVARIANT left, LPVARIANT right, LPVARIANT result)
 {
-    HRESULT rc = E_FAIL;
-    VARTYPE lvt,rvt,resvt;
-    VARIANT lv,rv;
-    BOOL found;
+    HRESULT hres;
+    VARTYPE lvt, rvt, resvt, tvt;
+    VARIANT lv, rv, tv;
+    double r8res;
 
+    /* Variant priority for coercion. Sorted from lowest to highest.
+       VT_ERROR shows an invalid input variant type. */
+    enum coerceprio { vt_UI1 = 0, vt_I2, vt_I4, vt_I8, vt_CY, vt_R4, vt_R8,
+                      vt_DECIMAL, vt_NULL, vt_ERROR };
+    /* Mapping from priority to variant type. Keep in sync with coerceprio! */
+    VARTYPE prio2vt[] = { VT_UI1, VT_I2, VT_I4, VT_I8, VT_CY, VT_R4, VT_R8,
+                          VT_DECIMAL, VT_NULL, VT_ERROR };
+
+    /* Mapping for coercion from input variant to priority of result variant. */
+    static VARTYPE coerce[] = {
+        /* VT_EMPTY, VT_NULL, VT_I2, VT_I4, VT_R4 */
+        vt_UI1, vt_NULL, vt_I2, vt_I4, vt_R4,
+        /* VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH */
+        vt_R8, vt_CY, vt_R8, vt_R8, vt_ERROR,
+        /* VT_ERROR, VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL */
+        vt_ERROR, vt_I2, vt_ERROR, vt_ERROR, vt_DECIMAL,
+        /* 15, VT_I1, VT_UI1, VT_UI2, VT_UI4 VT_I8 */
+        vt_ERROR, vt_ERROR, vt_UI1, vt_ERROR, vt_ERROR, vt_I8
+    };
+
     TRACE("(%p->(%s%s),%p->(%s%s),%p)\n", left, debugstr_VT(left),
-          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right), result);
+          debugstr_VF(left), right, debugstr_VT(right), debugstr_VF(right),
+          result);
 
-    VariantInit(&lv);VariantInit(&rv);
+    VariantInit(&lv);
+    VariantInit(&rv);
+    VariantInit(&tv);
     lvt = V_VT(left)&VT_TYPEMASK;
     rvt = V_VT(right)&VT_TYPEMASK;
-    found = FALSE;resvt=VT_VOID;
-    if (((1<<lvt) | (1<<rvt)) & (VTBIT_R4|VTBIT_R8)) {
-	found = TRUE;
-	resvt = VT_R8;
+
+    /* If we have any flag set (VT_ARRAY, VT_VECTOR, etc.) bail out.
+       Same for any input variant type > VT_I8 */
+    if (V_VT(left) & ~VT_TYPEMASK || V_VT(right) & ~VT_TYPEMASK ||
+        lvt > VT_I8 || rvt > VT_I8) {
+        hres = DISP_E_BADVARTYPE;
+        goto end;
     }
-    if (!found && (((1<<lvt) | (1<<rvt)) & (VTBIT_I1|VTBIT_I2|VTBIT_UI1|VTBIT_UI2|VTBIT_I4|VTBIT_UI4|(1<<VT_INT)|(1<<VT_UINT)))) {
-	found = TRUE;
-	resvt = VT_I4;
+
+    /* Determine the variant type to coerce to. */
+    if (coerce[lvt] > coerce[rvt]) {
+        resvt = prio2vt[coerce[lvt]];
+        tvt = prio2vt[coerce[rvt]];
+    } else {
+        resvt = prio2vt[coerce[rvt]];
+        tvt = prio2vt[coerce[lvt]];
     }
-    if (!found) {
-	FIXME("can't expand vt %d vs %d to a target type.\n",lvt,rvt);
-	return E_FAIL;
+
+    /* Special cases where the result variant type is defined by both
+       input variants and not only that with the highest priority */
+    if (resvt == VT_R4 && (tvt == VT_CY || tvt == VT_I8 || tvt == VT_I4))
+        resvt = VT_R8;
+    if (lvt == VT_EMPTY && rvt == VT_EMPTY)
+        resvt = VT_I2;
+
+    /* For overflow detection use the biggest compatible type for the
+       multiplication */
+    switch (resvt) {
+        case VT_ERROR:
+            hres = DISP_E_BADVARTYPE;
+            goto end;
+        case VT_NULL:
+            hres = S_OK;
+            V_VT(result) = VT_NULL;
+            goto end;
+        case VT_UI1:
+        case VT_I2:
+        case VT_I4:
+        case VT_I8:
+            tvt = VT_I8;
+            break;
+        case VT_R4:
+            tvt = VT_R8;
+            break;
+        default:
+            tvt = resvt;
     }
-    rc = VariantChangeType(&lv, left, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(left),resvt);
-	return rc;
+
+    /* Now coerce the variants */
+    hres = VariantChangeType(&lv, left, 0, tvt);
+    if (FAILED(hres))
+        goto end;
+    hres = VariantChangeType(&rv, right, 0, tvt);
+    if (FAILED(hres))
+        goto end;
+
+    /* Do the math */
+    hres = S_OK;
+    V_VT(&tv) = tvt;
+    V_VT(result) = resvt;
+    switch (tvt) {
+        case VT_DECIMAL:
+            hres = VarDecMul(&V_DECIMAL(&lv), &V_DECIMAL(&rv),
+                             &V_DECIMAL(result));
+            goto end;
+        case VT_CY:
+            hres = VarCyMul(V_CY(&lv), V_CY(&rv), &V_CY(result));
+            goto end;
+        case VT_I8:
+            /* Overflow detection */
+            r8res = (double)V_I8(&lv) * (double)V_I8(&rv);
+            if (r8res > (double)I8_MAX || r8res < (double)I8_MIN) {
+                V_VT(result) = VT_R8;
+                V_R8(result) = r8res;
+                goto end;
+            } else
+                V_I8(&tv) = V_I8(&lv) * V_I8(&rv);
+            break;
+        case VT_R8:
+            /* FIXME: overflow detection */
+            V_R8(&tv) = V_R8(&lv) * V_R8(&rv);
+            break;
+        default:
+            ERR("We shouldn't get here! tvt = %d!\n", tvt);
+            break;
     }
-    rc = VariantChangeType(&rv, right, 0, resvt);
-    if (FAILED(rc)) {
-	FIXME("Could not convert 0x%x to %d?\n",V_VT(right),resvt);
-	return rc;
+    if (rvt != tvt) {
+        while ((hres = VariantChangeType(result, &tv, 0, resvt)) != S_OK) {
+            /* Overflow! Change to the vartype with the next higher priority */
+            resvt = prio2vt[coerce[resvt] + 1];
+        }
+    } else
+        hres = VariantCopy(result, &tv);
+
+end:
+    if (hres != S_OK) {
+        V_VT(result) = VT_EMPTY;
+        V_I4(result) = 0;       /* No V_EMPTY */
     }
-    switch (resvt) {
-    case VT_R8:
-	V_VT(result) = resvt;
-	V_R8(result) = V_R8(&lv) * V_R8(&rv);
-	rc = S_OK;
-	break;
-    case VT_I4:
-	V_VT(result) = resvt;
-	V_I4(result) = V_I4(&lv) * V_I4(&rv);
-	rc = S_OK;
-	break;
-    }
-    TRACE("returning 0x%8lx (%s%s),%g\n", rc, debugstr_VT(result),
-          debugstr_VF(result), V_VT(result) == VT_R8 ? V_R8(result) : (double)V_I4(result));
-    return rc;
+    VariantClear(&lv);
+    VariantClear(&rv);
+    VariantClear(&tv);
+    TRACE("returning 0x%8lx (variant type %s)\n", hres, debugstr_VT(result));
+    return hres;
 }
 
 /**********************************************************************
@@ -4267,7 +4377,7 @@
       return DISP_E_TYPEMISMATCH;
     case VT_DECIMAL:
       V_VT(result) = VT_EMPTY;
-      return E_INVALIDARG;
+      return DISP_E_OVERFLOW;
     case VT_ERROR:
       return DISP_E_TYPEMISMATCH;
     case VT_RECORD:
@@ -4352,7 +4462,7 @@
       } else
       {
 	V_VT(result) = VT_EMPTY;
-        return E_INVALIDARG;
+        return DISP_E_OVERFLOW;
       }
     case VT_ERROR:
       return DISP_E_TYPEMISMATCH;