Sebastian Lackner : shlwapi: Add implementation for StrCatChainW.

Alexandre Julliard julliard at wine.codeweavers.com
Tue Dec 16 15:06:06 CST 2014


Module: wine
Branch: master
Commit: 4b33a339cc5328b1c117f5ed0cbde1a6c4f6b7f5
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=4b33a339cc5328b1c117f5ed0cbde1a6c4f6b7f5

Author: Sebastian Lackner <sebastian at fds-team.de>
Date:   Sun Dec  7 22:55:31 2014 +0100

shlwapi: Add implementation for StrCatChainW.

Based on a patch by Huw Campbell.

---

 .../api-ms-win-downlevel-shlwapi-l1-1-0.spec       |   2 +-
 dlls/shlwapi/shlwapi.spec                          |   1 +
 dlls/shlwapi/string.c                              |  41 +++++++
 dlls/shlwapi/tests/string.c                        | 122 +++++++++++++++++++++
 4 files changed, 165 insertions(+), 1 deletion(-)

diff --git a/dlls/api-ms-win-downlevel-shlwapi-l1-1-0/api-ms-win-downlevel-shlwapi-l1-1-0.spec b/dlls/api-ms-win-downlevel-shlwapi-l1-1-0/api-ms-win-downlevel-shlwapi-l1-1-0.spec
index 9d266fa..7736645 100644
--- a/dlls/api-ms-win-downlevel-shlwapi-l1-1-0/api-ms-win-downlevel-shlwapi-l1-1-0.spec
+++ b/dlls/api-ms-win-downlevel-shlwapi-l1-1-0/api-ms-win-downlevel-shlwapi-l1-1-0.spec
@@ -86,7 +86,7 @@
 @ stdcall SHRegSetUSValueW( wstr wstr long ptr long long) shlwapi.SHRegSetUSValueW
 @ stdcall StrCatBuffA(str str long) shlwapi.StrCatBuffA
 @ stdcall StrCatBuffW(wstr wstr long) shlwapi.StrCatBuffW
-@ stub StrCatChainW
+@ stdcall StrCatChainW(ptr long long wstr) shlwapi.StrCatChainW
 @ stdcall StrChrA(str long) shlwapi.StrChrA
 @ stdcall StrChrIA(str long) shlwapi.StrChrIA
 @ stdcall StrChrIW(wstr long) shlwapi.StrChrIW
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..ca2f9b9 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,%u,%d,%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();
 }




More information about the wine-cvs mailing list