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;