Sync to Wine-20050524:
Alexandre Julliard <julliard(a)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(a)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(a)daijobu.co.uk>
- Remove unused macro.
- Check for VT_I8 before testing it.
- VarMod returns DISP_E_OVERFLOW not E_INVALIDARG.
Robert Shearman <rob(a)codeweavers.com>
- Use I_RpcGetBuffer instead of HeapReAlloc for getting the Buffer
memory.
Vincent Beron <vberon(a)mecano.gme.usherb.ca>
- Use SUBLANG_NEUTRAL for French resources.
Alex Villacis Lasso <a_villacis(a)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;