Juan Lang : crypt32: Partially implement CryptBinaryToStringW.

Alexandre Julliard julliard at winehq.org
Tue Nov 3 15:37:15 CST 2009


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

Author: Juan Lang <juan.lang at gmail.com>
Date:   Thu Oct 29 15:13:29 2009 -0700

crypt32: Partially implement CryptBinaryToStringW.

---

 dlls/crypt32/base64.c     |  194 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/crypt32/crypt32.spec |    2 +-
 2 files changed, 195 insertions(+), 1 deletions(-)

diff --git a/dlls/crypt32/base64.c b/dlls/crypt32/base64.c
index 17e05d9..d542db1 100644
--- a/dlls/crypt32/base64.c
+++ b/dlls/crypt32/base64.c
@@ -60,6 +60,8 @@ static const char b64[] =
 
 typedef BOOL (*BinaryToStringAFunc)(const BYTE *pbBinary,
  DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString);
+typedef BOOL (*BinaryToStringWFunc)(const BYTE *pbBinary,
+ DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString);
 
 static BOOL EncodeBinaryToBinaryA(const BYTE *pbBinary,
  DWORD cbBinary, DWORD dwFlags, LPSTR pszString, DWORD *pcchString)
@@ -280,6 +282,198 @@ BOOL WINAPI CryptBinaryToStringA(const BYTE *pbBinary,
     return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString);
 }
 
+static LONG encodeBase64W(const BYTE *in_buf, int in_len, LPCWSTR sep,
+ WCHAR* out_buf, DWORD *out_len)
+{
+    int div, i;
+    const BYTE *d = in_buf;
+    int bytes = (in_len*8 + 5)/6, pad_bytes = (bytes % 4) ? 4 - (bytes % 4) : 0;
+    DWORD needed;
+    LPWSTR ptr;
+
+    TRACE("bytes is %d, pad bytes is %d\n", bytes, pad_bytes);
+    needed = bytes + pad_bytes + 1;
+    needed += (needed / 64 + 1) * strlenW(sep);
+
+    if (needed > *out_len)
+    {
+        *out_len = needed;
+        return ERROR_INSUFFICIENT_BUFFER;
+    }
+    else
+        *out_len = needed;
+
+    /* Three bytes of input give 4 chars of output */
+    div = in_len / 3;
+
+    ptr = out_buf;
+    i = 0;
+    while (div > 0)
+    {
+        if (i && i % 64 == 0)
+        {
+            strcpyW(ptr, sep);
+            ptr += strlenW(sep);
+        }
+        /* first char is the first 6 bits of the first byte*/
+        *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
+        /* second char is the last 2 bits of the first byte and the first 4
+         * bits of the second byte */
+        *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
+        /* third char is the last 4 bits of the second byte and the first 2
+         * bits of the third byte */
+        *ptr++ = b64[ ((d[1] << 2) & 0x3c) | (d[2] >> 6 & 0x03)];
+        /* fourth char is the remaining 6 bits of the third byte */
+        *ptr++ = b64[   d[2]       & 0x3f];
+        i += 4;
+        d += 3;
+        div--;
+    }
+
+    switch(pad_bytes)
+    {
+        case 1:
+            /* first char is the first 6 bits of the first byte*/
+            *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
+            /* second char is the last 2 bits of the first byte and the first 4
+             * bits of the second byte */
+            *ptr++ = b64[ ((d[0] << 4) & 0x30) | (d[1] >> 4 & 0x0f)];
+            /* third char is the last 4 bits of the second byte padded with
+             * two zeroes */
+            *ptr++ = b64[ ((d[1] << 2) & 0x3c) ];
+            /* fourth char is a = to indicate one byte of padding */
+            *ptr++ = '=';
+            break;
+        case 2:
+            /* first char is the first 6 bits of the first byte*/
+            *ptr++ = b64[ ( d[0] >> 2) & 0x3f ];
+            /* second char is the last 2 bits of the first byte padded with
+             * four zeroes*/
+            *ptr++ = b64[ ((d[0] << 4) & 0x30)];
+            /* third char is = to indicate padding */
+            *ptr++ = '=';
+            /* fourth char is = to indicate padding */
+            *ptr++ = '=';
+            break;
+    }
+    strcpyW(ptr, sep);
+
+    return ERROR_SUCCESS;
+}
+
+static BOOL BinaryToBase64W(const BYTE *pbBinary,
+ DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString)
+{
+    static const WCHAR crlf[] = { '\r','\n',0 }, lf[] = { '\n',0 };
+    BOOL ret = TRUE;
+    LPCWSTR header = NULL, trailer = NULL, sep = NULL;
+    DWORD charsNeeded;
+
+    if (dwFlags & CRYPT_STRING_NOCR)
+        sep = lf;
+    else
+        sep = crlf;
+    switch (dwFlags & 0x7fffffff)
+    {
+    case CRYPT_STRING_BASE64:
+        /* no header or footer */
+        break;
+    case CRYPT_STRING_BASE64HEADER:
+        header = CERT_HEADER_W;
+        trailer = CERT_TRAILER_W;
+        break;
+    case CRYPT_STRING_BASE64REQUESTHEADER:
+        header = CERT_REQUEST_HEADER_W;
+        trailer = CERT_REQUEST_TRAILER_W;
+        break;
+    case CRYPT_STRING_BASE64X509CRLHEADER:
+        header = X509_HEADER_W;
+        trailer = X509_TRAILER_W;
+        break;
+    }
+
+    charsNeeded = 0;
+    encodeBase64W(pbBinary, cbBinary, sep, NULL, &charsNeeded);
+    charsNeeded += strlenW(sep);
+    if (header)
+        charsNeeded += strlenW(header) + strlenW(sep);
+    if (trailer)
+        charsNeeded += strlenW(trailer) + strlenW(sep);
+    if (charsNeeded <= *pcchString)
+    {
+        LPWSTR ptr = pszString;
+        DWORD size = charsNeeded;
+
+        if (header)
+        {
+            strcpyW(ptr, header);
+            ptr += strlenW(ptr);
+            strcpyW(ptr, sep);
+            ptr += strlenW(sep);
+        }
+        encodeBase64W(pbBinary, cbBinary, sep, ptr, &size);
+        ptr += size - 1;
+        if (trailer)
+        {
+            strcpyW(ptr, trailer);
+            ptr += strlenW(ptr);
+            strcpyW(ptr, sep);
+            ptr += strlenW(sep);
+        }
+        *pcchString = charsNeeded - 1;
+    }
+    else if (pszString)
+    {
+        *pcchString = charsNeeded;
+        SetLastError(ERROR_INSUFFICIENT_BUFFER);
+        ret = FALSE;
+    }
+    else
+        *pcchString = charsNeeded;
+    return ret;
+}
+
+BOOL WINAPI CryptBinaryToStringW(const BYTE *pbBinary,
+ DWORD cbBinary, DWORD dwFlags, LPWSTR pszString, DWORD *pcchString)
+{
+    BinaryToStringWFunc encoder = NULL;
+
+    TRACE("(%p, %d, %08x, %p, %p)\n", pbBinary, cbBinary, dwFlags, pszString,
+     pcchString);
+
+    if (!pbBinary)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    if (!pcchString)
+    {
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+
+    switch (dwFlags & 0x7fffffff)
+    {
+    case CRYPT_STRING_BASE64:
+    case CRYPT_STRING_BASE64HEADER:
+    case CRYPT_STRING_BASE64REQUESTHEADER:
+    case CRYPT_STRING_BASE64X509CRLHEADER:
+        encoder = BinaryToBase64W;
+        break;
+    case CRYPT_STRING_BINARY:
+    case CRYPT_STRING_HEX:
+    case CRYPT_STRING_HEXASCII:
+    case CRYPT_STRING_HEXADDR:
+    case CRYPT_STRING_HEXASCIIADDR:
+        FIXME("Unimplemented type %d\n", dwFlags & 0x7fffffff);
+        /* fall through */
+    default:
+        SetLastError(ERROR_INVALID_PARAMETER);
+        return FALSE;
+    }
+    return encoder(pbBinary, cbBinary, dwFlags, pszString, pcchString);
+}
+
 static inline BYTE decodeBase64Byte(int c)
 {
     BYTE ret;
diff --git a/dlls/crypt32/crypt32.spec b/dlls/crypt32/crypt32.spec
index 534bee7..bcab030 100644
--- a/dlls/crypt32/crypt32.spec
+++ b/dlls/crypt32/crypt32.spec
@@ -98,7 +98,7 @@
 @ stdcall CertVerifyValidityNesting(ptr ptr)
 @ stdcall CreateFileU(wstr long long ptr long long ptr) kernel32.CreateFileW
 @ stdcall CryptBinaryToStringA(ptr long long ptr ptr)
-@ stub CryptBinaryToStringW # (ptr long long ptr ptr)
+@ stdcall CryptBinaryToStringW(ptr long long ptr ptr)
 @ stdcall CryptStringToBinaryA(str long long ptr ptr ptr ptr)
 @ stdcall CryptStringToBinaryW (wstr long long ptr ptr ptr ptr)
 @ stdcall CryptAcquireContextU(ptr wstr wstr long long) advapi32.CryptAcquireContextW




More information about the wine-cvs mailing list