diff --git a/README.md b/README.md index 5961470a..8cb3db13 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ Current patches include: * Support for GetVolumePathName * Implement an Arial replacement font (http://bugs.winehq.org/show_bug.cgi?id=32323) * Workaround for TransactNamedPipe not being supported (http://bugs.winehq.org/show_bug.cgi?id=17273) +* Fix incorrect scaling for DECIMAL values in VarDecAdd (http://bugs.winehq.org/show_bug.cgi?id=31269) * XEMBED support for embedding Wine windows inside Linux applications * Reduced SetTimer minimum value from 15 ms to 5 ms (improves Silverlight framerates) * Lockfree algorithm for filedescriptor cache (improves file access speed) diff --git a/debian/changelog b/debian/changelog index 938cced8..c83051a3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ wine-compholio (1.7.22) UNRELEASED; urgency=low * Implement RegSetKeySecurity on top of NtSetSecurityObject. * Updated RegSetKeySecurity patch to work with special root keys. * Add patch for wtsapi32.WTSEnumerateProcessesW function. + * Fix incorrect scaling for DECIMAL values in VarDecAdd. -- Erich E. Hoover Fri, 04 Jul 2014 13:18:40 -0600 wine-compholio (1.7.21) unstable; urgency=low diff --git a/patches/16-oleaut32/0001-oleaut32-tests-Add-additional-tests-for-VarDecAdd.patch b/patches/16-oleaut32/0001-oleaut32-tests-Add-additional-tests-for-VarDecAdd.patch new file mode 100644 index 00000000..f96242f0 --- /dev/null +++ b/patches/16-oleaut32/0001-oleaut32-tests-Add-additional-tests-for-VarDecAdd.patch @@ -0,0 +1,57 @@ +From 1c9a2005470cde9d347c166c7e2db0c40832e6fc Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 7 Jul 2014 21:11:51 +0200 +Subject: oleaut32/tests: Add additional tests for VarDecAdd. + +--- + dlls/oleaut32/tests/vartype.c | 31 +++++++++++++++++++++++++++++++ + 1 file changed, 31 insertions(+) + +diff --git a/dlls/oleaut32/tests/vartype.c b/dlls/oleaut32/tests/vartype.c +index b873d82..8ca3f14 100644 +--- a/dlls/oleaut32/tests/vartype.c ++++ b/dlls/oleaut32/tests/vartype.c +@@ -4408,9 +4408,40 @@ static void test_VarDecAdd(void) + ok(hres == DISP_E_OVERFLOW,"Expected overflow, got (%d,%d,%d,(%8x,%8x)x) hres 0x%08x\n", + S(U(out)).scale, S(U(out)).sign, out.Hi32, S1(U1(out)).Mid32, S1(U1(out)).Lo32, hres); + ++ SETDEC64(l,1,0,0xffffffff,0xffffffff,0xffffffff);SETDEC(r,1,0,0,1); MATH2(VarDecAdd); ++ todo_wine EXPECTDEC64(0,0,0x19999999,0x99999999,0x9999999A); ++ ++ SETDEC64(l,0,0,0xe22ea493,0xb30310a7,0x70000000);SETDEC64(r,0,0,0xe22ea493,0xb30310a7,0x70000000); MATH2(VarDecAdd); ++ ok(hres == DISP_E_OVERFLOW,"Expected overflow, got (%d,%d,%d,(%8x,%8x)x) hres 0x%08x\n", ++ S(U(out)).scale, S(U(out)).sign, out.Hi32, S1(U1(out)).Mid32, S1(U1(out)).Lo32, hres); ++ ++ SETDEC64(l,1,0,0xe22ea493,0xb30310a7,0x70000000);SETDEC64(r,1,0,0xe22ea493,0xb30310a7,0x70000000); MATH2(VarDecAdd); ++ todo_wine EXPECTDEC64(0,0,0x2d3c8750,0xbd670354,0xb0000000); ++ + SETDEC(l,3,128,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); + MATH2(VarDecAdd); todo_wine EXPECTDEC64(0,0,-1,0xFFFFFFFF,0xFFFFFF84); + ++ SETDEC(l,3,0,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); MATH2(VarDecAdd); ++ ok(hres == DISP_E_OVERFLOW,"Expected overflow, got (%d,%d,%d,(%8x,%8x)x) hres 0x%08x\n", ++ S(U(out)).scale, S(U(out)).sign, out.Hi32, S1(U1(out)).Mid32, S1(U1(out)).Lo32, hres); ++ ++ SETDEC(l,4,0,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); MATH2(VarDecAdd); ++ ok(hres == DISP_E_OVERFLOW,"Expected overflow, got (%d,%d,%d,(%8x,%8x)x) hres 0x%08x\n", ++ S(U(out)).scale, S(U(out)).sign, out.Hi32, S1(U1(out)).Mid32, S1(U1(out)).Lo32, hres); ++ ++ SETDEC(l,5,0,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); MATH2(VarDecAdd); ++ ok(hres == DISP_E_OVERFLOW,"Expected overflow, got (%d,%d,%d,(%8x,%8x)x) hres 0x%08x\n", ++ S(U(out)).scale, S(U(out)).sign, out.Hi32, S1(U1(out)).Mid32, S1(U1(out)).Lo32, hres); ++ ++ SETDEC(l,6,0,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); ++ MATH2(VarDecAdd); todo_wine EXPECTDEC64(0,0,-1,0xFFFFFFFF,0xFFFFFFFF); ++ ++ SETDEC(l,3,128,0,123456); SETDEC64(r,0,0,0x19999999,0x99999999,0x99999999); ++ MATH2(VarDecAdd); todo_wine EXPECTDEC64(1,0,-1,0xFFFFFFFF,0xFFFFFB27); ++ ++ SETDEC(l,3,128,0,123567); SETDEC64(r,0,0,0x19999999,0x99999999,0x99999999); ++ MATH2(VarDecAdd); todo_wine EXPECTDEC64(1,0,-1,0xFFFFFFFF,0xFFFFFB26); ++ + /* Promotes to the highest scale, so here the results are in the scale of 2 */ + SETDEC(l,2,0,0,0); SETDEC(r,0,0,0,0); MATH2(VarDecAdd); EXPECTDEC(2,0,0,0); + SETDEC(l,2,0,0,100); SETDEC(r,0,0,0,1); MATH2(VarDecAdd); EXPECTDEC(2,0,0,200); +-- +1.7.9.5 + diff --git a/patches/16-oleaut32/0002-oleaut32-Decrease-accuracy-if-scaling-is-not-possibl.patch b/patches/16-oleaut32/0002-oleaut32-Decrease-accuracy-if-scaling-is-not-possibl.patch new file mode 100644 index 00000000..e3784c4d --- /dev/null +++ b/patches/16-oleaut32/0002-oleaut32-Decrease-accuracy-if-scaling-is-not-possibl.patch @@ -0,0 +1,168 @@ +From bdabced415b7374f6797d9a593f9f0c17bb59f39 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Mon, 7 Jul 2014 22:13:59 +0200 +Subject: oleaut32: Decrease accuracy if scaling is not possible in VarDecAdd. + +--- + dlls/oleaut32/tests/vartype.c | 10 +++--- + dlls/oleaut32/vartype.c | 70 +++++++++++++++++++++++++++++++---------- + 2 files changed, 59 insertions(+), 21 deletions(-) + +diff --git a/dlls/oleaut32/tests/vartype.c b/dlls/oleaut32/tests/vartype.c +index 8ca3f14..026149a 100644 +--- a/dlls/oleaut32/tests/vartype.c ++++ b/dlls/oleaut32/tests/vartype.c +@@ -4419,7 +4419,7 @@ static void test_VarDecAdd(void) + todo_wine EXPECTDEC64(0,0,0x2d3c8750,0xbd670354,0xb0000000); + + SETDEC(l,3,128,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); +- MATH2(VarDecAdd); todo_wine EXPECTDEC64(0,0,-1,0xFFFFFFFF,0xFFFFFF84); ++ MATH2(VarDecAdd); EXPECTDEC64(0,0,-1,0xFFFFFFFF,0xFFFFFF84); + + SETDEC(l,3,0,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); MATH2(VarDecAdd); + ok(hres == DISP_E_OVERFLOW,"Expected overflow, got (%d,%d,%d,(%8x,%8x)x) hres 0x%08x\n", +@@ -4434,13 +4434,13 @@ static void test_VarDecAdd(void) + S(U(out)).scale, S(U(out)).sign, out.Hi32, S1(U1(out)).Mid32, S1(U1(out)).Lo32, hres); + + SETDEC(l,6,0,0,123456); SETDEC64(r,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); +- MATH2(VarDecAdd); todo_wine EXPECTDEC64(0,0,-1,0xFFFFFFFF,0xFFFFFFFF); ++ MATH2(VarDecAdd); EXPECTDEC64(0,0,-1,0xFFFFFFFF,0xFFFFFFFF); + + SETDEC(l,3,128,0,123456); SETDEC64(r,0,0,0x19999999,0x99999999,0x99999999); +- MATH2(VarDecAdd); todo_wine EXPECTDEC64(1,0,-1,0xFFFFFFFF,0xFFFFFB27); ++ MATH2(VarDecAdd); EXPECTDEC64(1,0,-1,0xFFFFFFFF,0xFFFFFB27); + + SETDEC(l,3,128,0,123567); SETDEC64(r,0,0,0x19999999,0x99999999,0x99999999); +- MATH2(VarDecAdd); todo_wine EXPECTDEC64(1,0,-1,0xFFFFFFFF,0xFFFFFB26); ++ MATH2(VarDecAdd); EXPECTDEC64(1,0,-1,0xFFFFFFFF,0xFFFFFB26); + + /* Promotes to the highest scale, so here the results are in the scale of 2 */ + SETDEC(l,2,0,0,0); SETDEC(r,0,0,0,0); MATH2(VarDecAdd); EXPECTDEC(2,0,0,0); +@@ -4663,7 +4663,7 @@ static void test_VarDecCmp(void) + SETDEC(out,0,DECIMAL_NEG,-1,-1); SETDEC(l,0,DECIMAL_NEG,-1,-1); MATH1(VarDecCmp); EXPECT_EQ; + + SETDEC(l,3,0,0,123456); SETDEC64(out,0,0,0xFFFFFFFF,0xFFFFFFFF,0xFFFFFFFF); +- MATH1(VarDecCmp); todo_wine EXPECT_LT; ++ MATH1(VarDecCmp); EXPECT_LT; + } + + static void test_VarDecCmpR8(void) +diff --git a/dlls/oleaut32/vartype.c b/dlls/oleaut32/vartype.c +index 4d067e0..e9b45ff 100644 +--- a/dlls/oleaut32/vartype.c ++++ b/dlls/oleaut32/vartype.c +@@ -4164,6 +4164,8 @@ static HRESULT VARIANT_DI_FromR4(float source, VARIANT_DI * dest); + static HRESULT VARIANT_DI_FromR8(double source, VARIANT_DI * dest); + static void VARIANT_DIFromDec(const DECIMAL * from, VARIANT_DI * to); + static void VARIANT_DecFromDI(const VARIANT_DI * from, DECIMAL * to); ++static unsigned char VARIANT_int_divbychar(DWORD * p, unsigned int n, unsigned char divisor); ++static BOOL VARIANT_int_iszero(const DWORD * p, unsigned int n); + + /************************************************************************ + * VarDecFromR4 (OLEAUT32.193) +@@ -4439,12 +4441,13 @@ HRESULT WINAPI VarDecFromUI8(ULONG64 ullIn, DECIMAL* pDecOut) + /* Make two DECIMALS the same scale; used by math functions below */ + static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft, + const DECIMAL** ppDecRight, +- DECIMAL* pDecOut) ++ DECIMAL pDecOut[2]) + { + static DECIMAL scaleFactor; ++ unsigned char remainder; + DECIMAL decTemp; ++ VARIANT_DI di; + int scaleAmount, i; +- HRESULT hRet = S_OK; + + if (DEC_SIGN(*ppDecLeft) & ~DECIMAL_NEG || DEC_SIGN(*ppDecRight) & ~DECIMAL_NEG) + return E_INVALIDARG; +@@ -4459,27 +4462,62 @@ static HRESULT VARIANT_DecScale(const DECIMAL** ppDecLeft, + if (scaleAmount > 0) + { + decTemp = *(*ppDecRight); /* Left is bigger - scale the right hand side */ +- *ppDecRight = pDecOut; ++ *ppDecRight = &pDecOut[0]; + } + else + { + decTemp = *(*ppDecLeft); /* Right is bigger - scale the left hand side */ +- *ppDecLeft = pDecOut; +- i = scaleAmount = -scaleAmount; ++ *ppDecLeft = &pDecOut[0]; ++ i = -scaleAmount; + } + +- if (DEC_SCALE(&decTemp) + scaleAmount > DEC_MAX_SCALE) +- return DISP_E_OVERFLOW; /* Can't scale up */ ++ /* Multiply up the value to be scaled by the correct amount (if possible) */ ++ while (i > 0 && SUCCEEDED(VarDecMul(&decTemp, &scaleFactor, &pDecOut[0]))) ++ { ++ decTemp = pDecOut[0]; ++ i--; ++ } + +- /* Multiply up the value to be scaled by the correct amount */ +- while (SUCCEEDED(hRet) && i--) ++ if (!i) + { +- /* Note we are multiplying by a value with a scale of 0, so we don't recurse */ +- hRet = VarDecMul(&decTemp, &scaleFactor, pDecOut); +- decTemp = *pDecOut; ++ DEC_SCALE(&pDecOut[0]) += (scaleAmount > 0) ? scaleAmount : (-scaleAmount); ++ return S_OK; /* Same scale */ + } +- DEC_SCALE(pDecOut) += scaleAmount; /* Set the new scale */ +- return hRet; ++ ++ /* Scaling further not possible, reduce accuracy of other argument */ ++ pDecOut[0] = decTemp; ++ if (scaleAmount > 0) ++ { ++ DEC_SCALE(&pDecOut[0]) += scaleAmount - i; ++ VARIANT_DIFromDec(*ppDecLeft, &di); ++ *ppDecLeft = &pDecOut[1]; ++ } ++ else ++ { ++ DEC_SCALE(&pDecOut[0]) += (-scaleAmount) - i; ++ VARIANT_DIFromDec(*ppDecRight, &di); ++ *ppDecRight = &pDecOut[1]; ++ } ++ ++ di.scale -= i; ++ remainder = 0; ++ while (i-- > 0 && !VARIANT_int_iszero(di.bitsnum, sizeof(di.bitsnum)/sizeof(DWORD))) ++ { ++ remainder = VARIANT_int_divbychar(di.bitsnum, sizeof(di.bitsnum)/sizeof(DWORD), 10); ++ if (remainder > 0) WARN("losing significant digits (remainder %u)...\n", remainder); ++ } ++ ++ /* round up the result - native oleaut32 does this */ ++ if (remainder >= 5) { ++ for (remainder = 1, i = 0; i < sizeof(di.bitsnum)/sizeof(DWORD) && remainder; i++) { ++ ULONGLONG digit = di.bitsnum[i] + 1; ++ remainder = (digit > 0xFFFFFFFF) ? 1 : 0; ++ di.bitsnum[i] = digit & 0xFFFFFFFF; ++ } ++ } ++ ++ VARIANT_DecFromDI(&di, &pDecOut[1]); ++ return S_OK; + } + + /* Add two unsigned 32 bit values with overflow */ +@@ -4554,9 +4592,9 @@ static inline int VARIANT_DecCmp(const DECIMAL *pDecLeft, const DECIMAL *pDecRig + HRESULT WINAPI VarDecAdd(const DECIMAL* pDecLeft, const DECIMAL* pDecRight, DECIMAL* pDecOut) + { + HRESULT hRet; +- DECIMAL scaled; ++ DECIMAL scaled[2]; + +- hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, &scaled); ++ hRet = VARIANT_DecScale(&pDecLeft, &pDecRight, scaled); + + if (SUCCEEDED(hRet)) + { +-- +1.7.9.5 + diff --git a/patches/16-oleaut32/6df5c5c3-f06a-4506-ae04-a07d58652136.def b/patches/16-oleaut32/6df5c5c3-f06a-4506-ae04-a07d58652136.def new file mode 100644 index 00000000..6c188b8e --- /dev/null +++ b/patches/16-oleaut32/6df5c5c3-f06a-4506-ae04-a07d58652136.def @@ -0,0 +1,3 @@ +Revision: 1 +Author: Sebastian Lackner +Title: Fix incorrect scaling of DECIMAL values in VarDecAdd. diff --git a/patches/patch-list.patch b/patches/patch-list.patch index 231b7780..983664bd 100644 --- a/patches/patch-list.patch +++ b/patches/patch-list.patch @@ -6,7 +6,7 @@ diff --git a/libs/wine/config.c b/libs/wine/config.c index a273502..5fa0cd5 100644 --- a/libs/wine/config.c +++ b/libs/wine/config.c -@@ -478,6 +478,43 @@ const char *wine_get_version(void) +@@ -478,6 +478,44 @@ const char *wine_get_version(void) return PACKAGE_VERSION; } @@ -31,6 +31,7 @@ index a273502..5fa0cd5 100644 + { "3405aa34-f341-11e3-83ce-0090f5c75ad5:1", "Erich E. Hoover", "Add default security descriptor ownership and DACLs for processes." }, + { "e46b26df-3c1b-419c-9579-f0d1e1c50bea:1", "Sebastian Lackner", "Workaround for broken implementation of shlwapi url functions." }, + { "3790a2d5-f930-423e-9c03-f7fc1c1e0811:1", "Sebastian Lackner", "Partial implementation of WTSEnumerateProcessesW." }, ++ { "6df5c5c3-f06a-4506-ae04-a07d58652136:1", "Sebastian Lackner", "Fix incorrect scaling of DECIMAL values in VarDecAdd." }, + { "0b21d7ac-0387-4493-aa38-fbafe3e749f5:2", "Michael Müller", "Decrease minimum SetTimer interval to 5 ms." }, + { "2394843e-2bc4-4fa4-8368-1ef32093b89e:1", "Michael Müller", "Allow changing strict draw ordering through an exported function." }, + { "255473fa-4e0a-4f51-952b-4deecc1a2181:1", "Michael Müller", "Indicate direct rendering through OpenGL extension." },