From ec9701cec2ac824d3db6561ed9d5c0410e59c477 Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Sun, 7 Dec 2014 23:23:22 +0100 Subject: [PATCH] Added patch to implement shlwapi.StrCatChainW. --- README.md | 3 +- debian/changelog | 1 + patches/Makefile | 13 + ...-Add-implementation-for-StrCatChainW.patch | 233 ++++++++++++++++++ patches/shlwapi-StrCatChainW/definition | 1 + 5 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 patches/shlwapi-StrCatChainW/0001-shlwapi-Add-implementation-for-StrCatChainW.patch create mode 100644 patches/shlwapi-StrCatChainW/definition diff --git a/README.md b/README.md index 4162c537..64134acd 100644 --- a/README.md +++ b/README.md @@ -37,12 +37,13 @@ Wine. All those differences are also documented on the Included bug fixes and improvements =================================== -**Bugfixes and features included in the next upcoming release [4]:** +**Bugfixes and features included in the next upcoming release [5]:** * Add support for GetPropValue to PulseAudio backend * Fix condition mask handling in RtlVerifyVersionInfo ([Wine Bug #36143](https://bugs.winehq.org/show_bug.cgi?id=36143)) * Fix possible segfault in pulse_rd_loop of PulseAudio backend * Set last error when GetRawInputDeviceList fails ([Wine Bug #37667](https://bugs.winehq.org/show_bug.cgi?id=37667)) +* Support for StrCatChainW **Bugs fixed in Wine Staging 1.7.32 [108]:** diff --git a/debian/changelog b/debian/changelog index 29b9236f..c10a1e5b 100644 --- a/debian/changelog +++ b/debian/changelog @@ -4,6 +4,7 @@ wine-compholio (1.7.33) UNRELEASED; urgency=low * Added patch to set last error when GetRawInputDeviceList fails. * Added patch to fix possible segfault in pulse_rd_loop of PulseAudio backend. * Added patch to implement support for GetPropValue to PulseAudio backend. + * Added patch to implement shlwapi.StrCatChainW. * Removed patch to fix copy and paste errors in ws2_32 tests (accepted upstream). * Removed patch to fix ordering of IP addresses by metric if two addresses have the same metric (accepted upstream). * Removed patch to reset data->pWintrustData->u.pFile->hFile after closing handle (accepted upstream). diff --git a/patches/Makefile b/patches/Makefile index 9672a1c0..65e9430f 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -99,6 +99,7 @@ PATCHLIST := \ shell32-SHCreateSessionKey.ok \ shell32-SHFileOperation.ok \ shlwapi-PathIsDirectoryEmptyW.ok \ + shlwapi-StrCatChainW.ok \ shlwapi-UrlCombine.ok \ user32-Dialog_Paint_Event.ok \ user32-DrawTextExW.ok \ @@ -1525,6 +1526,18 @@ shlwapi-PathIsDirectoryEmptyW.ok: echo '+ { "Michael Müller", "shlwapi: Correctly treat '\''.'\'' when enumerating files in PathIsDirectoryEmptyW.", 1 },'; \ ) > shlwapi-PathIsDirectoryEmptyW.ok +# Patchset shlwapi-StrCatChainW +# | +# | Modified files: +# | * dlls/shlwapi/shlwapi.spec, dlls/shlwapi/string.c, dlls/shlwapi/tests/string.c +# | +.INTERMEDIATE: shlwapi-StrCatChainW.ok +shlwapi-StrCatChainW.ok: + $(call APPLY_FILE,shlwapi-StrCatChainW/0001-shlwapi-Add-implementation-for-StrCatChainW.patch) + @( \ + echo '+ { "Sebastian Lackner", "shlwapi: Add implementation for StrCatChainW.", 1 },'; \ + ) > shlwapi-StrCatChainW.ok + # Patchset shlwapi-UrlCombine # | # | Modified files: diff --git a/patches/shlwapi-StrCatChainW/0001-shlwapi-Add-implementation-for-StrCatChainW.patch b/patches/shlwapi-StrCatChainW/0001-shlwapi-Add-implementation-for-StrCatChainW.patch new file mode 100644 index 00000000..5fce64cf --- /dev/null +++ b/patches/shlwapi-StrCatChainW/0001-shlwapi-Add-implementation-for-StrCatChainW.patch @@ -0,0 +1,233 @@ +From a850bb89ae8c415c8d7f04ba1c77b8933ca66d64 Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Sun, 7 Dec 2014 22:55:31 +0100 +Subject: shlwapi: Add implementation for StrCatChainW. + +Based on a patch by Huw Campbell. +--- + dlls/shlwapi/shlwapi.spec | 1 + + dlls/shlwapi/string.c | 41 +++++++++++++++ + dlls/shlwapi/tests/string.c | 122 ++++++++++++++++++++++++++++++++++++++++++++ + 3 files changed, 164 insertions(+) + +diff --git a/dlls/shlwapi/shlwapi.spec b/dlls/shlwapi/shlwapi.spec +index b7aac08..6b6ead2 100644 +--- a/dlls/shlwapi/shlwapi.spec ++++ b/dlls/shlwapi/shlwapi.spec +@@ -759,6 +759,7 @@ + @ stdcall StrCSpnW (wstr wstr) + @ stdcall StrCatBuffA (str str long) + @ stdcall StrCatBuffW (wstr wstr long) ++@ stdcall StrCatChainW (ptr long long wstr) + @ stdcall StrCatW (ptr wstr) + @ stdcall StrChrA (str long) + @ stdcall StrChrIA (str long) +diff --git a/dlls/shlwapi/string.c b/dlls/shlwapi/string.c +index 9ba6038..dfa383e 100644 +--- a/dlls/shlwapi/string.c ++++ b/dlls/shlwapi/string.c +@@ -459,6 +459,47 @@ LPWSTR WINAPI StrCatW(LPWSTR lpszStr, LPCWSTR lpszSrc) + } + + /************************************************************************* ++ * StrCatChainW [SHLWAPI.@] ++ * ++ * Concatenates two unicode strings. ++ * ++ * PARAMS ++ * lpszStr [O] Initial string ++ * cchMax [I] Length of destination buffer ++ * ichAt [I] Offset from the destination buffer to begin concatenation ++ * lpszCat [I] String to concatenate ++ * ++ * RETURNS ++ * The offset from the beginning of pszDst to the terminating NULL. ++ */ ++DWORD WINAPI StrCatChainW(LPWSTR lpszStr, DWORD cchMax, DWORD ichAt, LPCWSTR lpszCat) ++{ ++ TRACE("(%s,%i,%i,%s)\n", debugstr_w(lpszStr), cchMax, ichAt, debugstr_w(lpszCat)); ++ ++ if (ichAt == -1) ++ ichAt = strlenW(lpszStr); ++ ++ if (!cchMax) ++ return ichAt; ++ ++ if (ichAt == cchMax) ++ ichAt--; ++ ++ if (lpszCat && ichAt <= cchMax) ++ { ++ lpszStr += ichAt; ++ while (ichAt < cchMax - 1 && *lpszCat) ++ { ++ *lpszStr++ = *lpszCat++; ++ ichAt++; ++ } ++ *lpszStr = 0; ++ } ++ ++ return ichAt; ++} ++ ++/************************************************************************* + * StrCpyW [SHLWAPI.@] + * + * Copy a string to another string. +diff --git a/dlls/shlwapi/tests/string.c b/dlls/shlwapi/tests/string.c +index c72b774..ac14db0 100644 +--- a/dlls/shlwapi/tests/string.c ++++ b/dlls/shlwapi/tests/string.c +@@ -48,6 +48,7 @@ static DWORD (WINAPI *pSHAnsiToAnsi)(LPCSTR,LPSTR,int); + static DWORD (WINAPI *pSHUnicodeToUnicode)(LPCWSTR,LPWSTR,int); + static LPSTR (WINAPI *pStrCatBuffA)(LPSTR,LPCSTR,INT); + static LPWSTR (WINAPI *pStrCatBuffW)(LPWSTR,LPCWSTR,INT); ++static DWORD (WINAPI *pStrCatChainW)(LPWSTR,DWORD,DWORD,LPCWSTR); + static LPSTR (WINAPI *pStrCpyNXA)(LPSTR,LPCSTR,int); + static LPWSTR (WINAPI *pStrCpyNXW)(LPWSTR,LPCWSTR,int); + static LPSTR (WINAPI *pStrFormatByteSize64A)(LONGLONG,LPSTR,UINT); +@@ -1481,6 +1482,125 @@ static void test_StrStrNIW(void) + } + } + ++static void test_StrCatChainW(void) ++{ ++ static const WCHAR deadbeefW[] = {'D','e','A','d','B','e','E','f',0}; ++ static const WCHAR deadW[] = {'D','e','A','d',0}; ++ static const WCHAR beefW[] = {'B','e','E','f',0}; ++ ++ WCHAR buf[32 + 1]; ++ DWORD ret; ++ ++ if (!pStrCatChainW) ++ { ++ win_skip("StrCatChainW is not available\n"); ++ return; ++ } ++ ++ /* Test with NULL buffer */ ++ ret = pStrCatChainW(NULL, 0, 0, beefW); ++ ok(ret == 0, "Expected StrCatChainW to return 0, got %u\n", ret); ++ ++ /* Test with empty buffer */ ++ memset(buf, 0x11, sizeof(buf)); ++ ret = pStrCatChainW(buf, 0, 0, beefW); ++ ok(ret == 0, "Expected StrCatChainW to return 0, got %u\n", ret); ++ ok(buf[0] == 0x1111, "Expected buf[0] = 0x1111, got %x\n", buf[0]); ++ ++ memcpy(buf, deadbeefW, sizeof(deadbeefW)); ++ ret = pStrCatChainW(buf, 0, -1, beefW); ++ ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret); ++ ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); ++ ++ /* Append data to existing string with offset = -1 */ ++ memset(buf, 0x11, sizeof(buf)); ++ ret = pStrCatChainW(buf, 32, 0, deadW); ++ ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret); ++ ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ++ ret = pStrCatChainW(buf, 32, -1, beefW); ++ ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret); ++ ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); ++ ++ /* Append data at a fixed offset */ ++ memset(buf, 0x11, sizeof(buf)); ++ ret = pStrCatChainW(buf, 32, 0, deadW); ++ ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret); ++ ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ++ ret = pStrCatChainW(buf, 32, 4, beefW); ++ ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret); ++ ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); ++ ++ /* Buffer exactly sufficient for string + terminating null */ ++ memset(buf, 0x11, sizeof(buf)); ++ ret = pStrCatChainW(buf, 5, 0, deadW); ++ ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret); ++ ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ++ /* Buffer too small, string will be truncated */ ++ memset(buf, 0x11, sizeof(buf)); ++ ret = pStrCatChainW(buf, 4, 0, deadW); ++ if (ret == 4) ++ { ++ /* Windows 2000 and XP uses a slightly different implementation ++ * for StrCatChainW, which doesn't ensure that strings are null- ++ * terminated. Skip test if we detect such an implementation. */ ++ win_skip("Windows2000/XP behaviour detected for StrCatChainW, skipping tests\n"); ++ return; ++ } ++ ok(ret == 3, "Expected StrCatChainW to return 3, got %u\n", ret); ++ ok(!memcmp(buf, deadW, 3 * sizeof(WCHAR)), "Buffer contains wrong data\n"); ++ ok(!buf[3], "String is not nullterminated\n"); ++ ok(buf[4] == 0x1111, "Expected buf[4] = 0x1111, got %x\n", buf[4]); ++ ++ /* Overwrite part of an existing string */ ++ ret = pStrCatChainW(buf, 4, 1, beefW); ++ ok(ret == 3, "Expected StrCatChainW to return 3, got %u\n", ret); ++ ok(buf[0] == 'D', "Expected buf[0] = 'D', got %x\n", buf[0]); ++ ok(buf[1] == 'B', "Expected buf[1] = 'B', got %x\n", buf[1]); ++ ok(buf[2] == 'e', "Expected buf[2] = 'e', got %x\n", buf[2]); ++ ok(!buf[3], "String is not nullterminated\n"); ++ ok(buf[4] == 0x1111, "Expected buf[4] = 0x1111, got %x\n", buf[4]); ++ ++ /* Test appending to full buffer */ ++ memset(buf, 0x11, sizeof(buf)); ++ memcpy(buf, deadbeefW, sizeof(deadbeefW)); ++ memcpy(buf + 9, deadW, sizeof(deadW)); ++ ret = pStrCatChainW(buf, 9, 8, beefW); ++ ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret); ++ ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); ++ ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ++ /* Offset points at the end of the buffer */ ++ ret = pStrCatChainW(buf, 9, 9, beefW); ++ ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret); ++ ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); ++ ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ++ /* Offset points outside of the buffer */ ++ ret = pStrCatChainW(buf, 9, 10, beefW); ++ ok(ret == 10, "Expected StrCatChainW to return 10, got %u\n", ret); ++ ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); ++ ok(!memcmp(buf + 9, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ++ /* The same but without nullterminated string */ ++ memcpy(buf, deadbeefW, sizeof(deadbeefW)); ++ ret = pStrCatChainW(buf, 5, -1, deadW); ++ ok(ret == 8, "Expected StrCatChainW to return 8, got %u\n", ret); ++ ok(!memcmp(buf, deadbeefW, sizeof(deadbeefW)), "Buffer contains wrong data\n"); ++ ++ ret = pStrCatChainW(buf, 5, 5, deadW); ++ ok(ret == 4, "Expected StrCatChainW to return 4, got %u\n", ret); ++ ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ok(buf[5] == 'e', "Expected buf[5] = 'e', got %x\n", buf[5]); ++ ++ ret = pStrCatChainW(buf, 5, 6, deadW); ++ ok(ret == 6, "Expected StrCatChainW to return 6, got %u\n", ret); ++ ok(!memcmp(buf, deadW, sizeof(deadW)), "Buffer contains wrong data\n"); ++ ok(buf[5] == 'e', "Expected buf[5] = 'e', got %x\n", buf[5]); ++} ++ + START_TEST(string) + { + HMODULE hShlwapi; +@@ -1500,6 +1620,7 @@ START_TEST(string) + pSHUnicodeToUnicode = (void *)GetProcAddress(hShlwapi, (LPSTR)346); + pStrCatBuffA = (void *)GetProcAddress(hShlwapi, "StrCatBuffA"); + pStrCatBuffW = (void *)GetProcAddress(hShlwapi, "StrCatBuffW"); ++ pStrCatChainW = (void *)GetProcAddress(hShlwapi, "StrCatChainW"); + pStrCpyNXA = (void *)GetProcAddress(hShlwapi, (LPSTR)399); + pStrCpyNXW = (void *)GetProcAddress(hShlwapi, (LPSTR)400); + pStrChrNW = (void *)GetProcAddress(hShlwapi, "StrChrNW"); +@@ -1565,6 +1686,7 @@ START_TEST(string) + test_StrStrIW(); + test_StrStrNW(); + test_StrStrNIW(); ++ test_StrCatChainW(); + + CoUninitialize(); + } +-- +2.1.3 + diff --git a/patches/shlwapi-StrCatChainW/definition b/patches/shlwapi-StrCatChainW/definition new file mode 100644 index 00000000..b8f07da0 --- /dev/null +++ b/patches/shlwapi-StrCatChainW/definition @@ -0,0 +1 @@ +Fixes: Support for StrCatChainW