Daniel Lehman : crypt32: Implement CryptBinaryToStringW(HEXRAW).

Alexandre Julliard julliard at winehq.org
Mon Feb 10 16:32:46 CST 2020


Module: wine
Branch: master
Commit: f92581ee82117220bdacaeebba5e8f1eae93274f
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=f92581ee82117220bdacaeebba5e8f1eae93274f

Author: Daniel Lehman <dlehman at esri.com>
Date:   Fri Jan 24 07:05:08 2020 -0800

crypt32: Implement CryptBinaryToStringW(HEXRAW).

Signed-off-by: Daniel Lehman <dlehman at esri.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/crypt32/base64.c       | 46 +++++++++++++++++++++++++
 dlls/crypt32/tests/base64.c | 82 ++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 127 insertions(+), 1 deletion(-)

diff --git a/dlls/crypt32/base64.c b/dlls/crypt32/base64.c
index ac60c6efbd..221b452d7e 100644
--- a/dlls/crypt32/base64.c
+++ b/dlls/crypt32/base64.c
@@ -477,6 +477,49 @@ static BOOL BinaryToBase64W(const BYTE *pbBinary,
     return ret;
 }
 
+static BOOL BinaryToHexW(const BYTE *bin, DWORD nbin, DWORD flags, LPWSTR str, DWORD *nstr)
+{
+    static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+    DWORD needed;
+
+    if (flags & CRYPT_STRING_NOCRLF)
+        needed = 0;
+    else if (flags & CRYPT_STRING_NOCR)
+        needed = 1;
+    else
+        needed = 2;
+
+    needed += nbin * 2 + 1;
+    if (needed > *nstr)
+    {
+        SetLastError(ERROR_MORE_DATA);
+        return FALSE;
+    }
+
+    *nstr = needed;
+    if (!str)
+        return TRUE;
+
+    while (nbin--)
+    {
+        *str++ = hex[(*bin >> 4) & 0xf];
+        *str++ = hex[*bin & 0xf];
+        bin++;
+    }
+
+    if (flags & CRYPT_STRING_NOCR)
+        *str++ = '\n';
+    else if (!(flags & CRYPT_STRING_NOCRLF))
+    {
+        *str++ = '\r';
+        *str++ = '\n';
+    }
+
+    *str = 0;
+    *nstr = needed - 1;
+    return TRUE;
+}
+
 BOOL WINAPI CryptBinaryToStringW(const BYTE *pbBinary,
  DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString)
 {
@@ -507,6 +550,9 @@ BOOL WINAPI CryptBinaryToStringW(const BYTE *pbBinary,
     case CRYPT_STRING_BASE64X509CRLHEADER:
         encoder = BinaryToBase64W;
         break;
+    case CRYPT_STRING_HEXRAW:
+        encoder = BinaryToHexW;
+        break;
     case CRYPT_STRING_HEX:
     case CRYPT_STRING_HEXASCII:
     case CRYPT_STRING_HEXADDR:
diff --git a/dlls/crypt32/tests/base64.c b/dlls/crypt32/tests/base64.c
index 31605fe6b9..ac41d5c86d 100644
--- a/dlls/crypt32/tests/base64.c
+++ b/dlls/crypt32/tests/base64.c
@@ -238,7 +238,12 @@ static void encode_compare_base64_W(const BYTE *toEncode, DWORD toEncodeLen, DWO
 
 static void test_CryptBinaryToString(void)
 {
-    DWORD strLen, strLen2, i;
+    static const DWORD flags[] = { 0, CRYPT_STRING_NOCR, CRYPT_STRING_NOCRLF };
+    static const WCHAR hexdig[] = L"0123456789abcdef";
+    OSVERSIONINFOA ver = { sizeof(ver) };
+    BYTE input[256 * sizeof(WCHAR)];
+    DWORD strLen, strLen2, i, j;
+    WCHAR *hex, *cmp, *ptr;
     BOOL ret;
 
     ret = CryptBinaryToStringA(NULL, 0, 0, NULL, NULL);
@@ -357,6 +362,81 @@ static void test_CryptBinaryToString(void)
 
         heap_free(encodedW);
     }
+
+    /* winxp and win2k3 are documented as not handling HEXRAW but do not return failure */
+    GetVersionExA(&ver);
+    if (ver.dwMajorVersion <= 5)
+    {
+        win_skip("CryptBinaryToString(HEX) not supported\n");
+        return;
+    }
+
+    for (i = 0; i < sizeof(input) / sizeof(WCHAR); i++)
+        ((WCHAR *)input)[i] = i;
+
+    for (i = 0; i < ARRAY_SIZE(flags); i++)
+    {
+        strLen = ~0;
+        ret = CryptBinaryToStringW(input, sizeof(input), CRYPT_STRING_HEXRAW|flags[i],
+                                   NULL, &strLen);
+        ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
+        if (flags[i] & CRYPT_STRING_NOCRLF)
+            strLen2 = 0;
+        else if (flags[i] & CRYPT_STRING_NOCR)
+            strLen2 = 1;
+        else
+            strLen2 = 2;
+        strLen2 += sizeof(input) * 2 + 1;
+        ok(strLen == strLen2, "Expected length %d, got %d\n", strLen2, strLen);
+
+        hex = heap_alloc(strLen * sizeof(WCHAR));
+        memset(hex, 0xcc, strLen * sizeof(WCHAR));
+        ptr = cmp = heap_alloc(strLen * sizeof(WCHAR));
+        for (j = 0; j < ARRAY_SIZE(input); j++)
+        {
+            *ptr++ = hexdig[(input[j] >> 4) & 0xf];
+            *ptr++ = hexdig[input[j] & 0xf];
+        }
+        if (flags[i] & CRYPT_STRING_NOCR)
+        {
+            *ptr++ = '\n';
+        }
+        else if (!(flags[i] & CRYPT_STRING_NOCRLF))
+        {
+            *ptr++ = '\r';
+            *ptr++ = '\n';
+        }
+        *ptr++ = 0;
+        ret = CryptBinaryToStringW(input, sizeof(input), CRYPT_STRING_HEXRAW|flags[i],
+                                   hex, &strLen);
+        ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
+        strLen2--;
+        ok(strLen == strLen2, "Expected length %d, got %d\n", strLen, strLen2);
+        ok(!memcmp(hex, cmp, strLen * sizeof(WCHAR)), "Unexpected value\n");
+
+        /* adjusts size if buffer too big */
+        strLen *= 2;
+        ret = CryptBinaryToStringW(input, sizeof(input), CRYPT_STRING_HEXRAW|flags[i],
+                                   hex, &strLen);
+        ok(ret, "CryptBinaryToStringW failed: %d\n", GetLastError());
+        ok(strLen == strLen2, "Expected length %d, got %d\n", strLen, strLen2);
+
+        /* no writes if buffer too small */
+        strLen /= 2;
+        strLen2 /= 2;
+        memset(hex, 0xcc, strLen * sizeof(WCHAR));
+        memset(cmp, 0xcc, strLen * sizeof(WCHAR));
+        SetLastError(0xdeadbeef);
+        ret = CryptBinaryToStringW(input, sizeof(input), CRYPT_STRING_HEXRAW|flags[i],
+                                   hex, &strLen);
+        ok(!ret && GetLastError() == ERROR_MORE_DATA,"Expected ERROR_MORE_DATA, got ret=%d le=%u\n",
+           ret, GetLastError());
+        ok(strLen == strLen2, "Expected length %d, got %d\n", strLen, strLen2);
+        ok(!memcmp(hex, cmp, strLen * sizeof(WCHAR)), "Unexpected value\n");
+
+        heap_free(hex);
+        heap_free(cmp);
+    }
 }
 
 static void decodeAndCompareBase64_A(LPCSTR toDecode, LPCSTR header,




More information about the wine-cvs mailing list