diff --git a/dlls/crypt32/str.c b/dlls/crypt32/str.c index e0e238b..cd128a0 100644 --- a/dlls/crypt32/str.c +++ b/dlls/crypt32/str.c @@ -48,7 +48,8 @@ static inline BOOL is_quotable_char(char c) } } -DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, +/* Only use this function internally. */ +static DWORD QuoteCertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, LPSTR psz, DWORD csz) { DWORD ret = 0, len, i; @@ -157,7 +158,8 @@ DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, return ret; } -DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, +/* Only use this function internally. */ +static DWORD QuoteCertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, LPWSTR psz, DWORD csz) { DWORD ret = 0, len, i, strLen; @@ -260,6 +262,133 @@ DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, return ret; } +DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, + LPSTR psz, DWORD csz) +{ + DWORD ret = 0, len, i; + + TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz); + + switch (dwValueType) + { + case CERT_RDN_ANY_TYPE: + break; + case CERT_RDN_NUMERIC_STRING: + case CERT_RDN_PRINTABLE_STRING: + case CERT_RDN_TELETEX_STRING: + case CERT_RDN_VIDEOTEX_STRING: + case CERT_RDN_IA5_STRING: + case CERT_RDN_GRAPHIC_STRING: + case CERT_RDN_VISIBLE_STRING: + case CERT_RDN_GENERAL_STRING: + len = pValue->cbData; + if (!psz || !csz) + ret = len; + else + { + char *ptr = psz; + + for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++) + *ptr = pValue->pbData[i]; + ret = ptr - psz; + } + break; + case CERT_RDN_BMP_STRING: + case CERT_RDN_UTF8_STRING: + len = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)pValue->pbData, + pValue->cbData / sizeof(WCHAR), NULL, 0, NULL, NULL); + if (!psz || !csz) + ret = len; + else + { + char *dst = psz; + + for (i = 0; i < pValue->cbData / sizeof(WCHAR) && + dst - psz < csz; dst++, i++) + { + LPCWSTR src = (LPCWSTR)pValue->pbData + i; + + WideCharToMultiByte(CP_ACP, 0, src, 1, dst, + csz - (dst - psz) - 1, NULL, NULL); + } + ret = dst - psz; + } + break; + default: + FIXME("string type %d unimplemented\n", dwValueType); + } + if (psz && csz) + { + *(psz + ret) = '\0'; + csz--; + ret++; + } + else + ret++; + TRACE("returning %d (%s)\n", ret, debugstr_a(psz)); + return ret; +} + +DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue, + LPWSTR psz, DWORD csz) +{ + DWORD ret = 0, len, i, strLen; + + TRACE("(%d, %p, %p, %d)\n", dwValueType, pValue, psz, csz); + + switch (dwValueType) + { + case CERT_RDN_ANY_TYPE: + break; + case CERT_RDN_NUMERIC_STRING: + case CERT_RDN_PRINTABLE_STRING: + case CERT_RDN_TELETEX_STRING: + case CERT_RDN_VIDEOTEX_STRING: + case CERT_RDN_IA5_STRING: + case CERT_RDN_GRAPHIC_STRING: + case CERT_RDN_VISIBLE_STRING: + case CERT_RDN_GENERAL_STRING: + len = pValue->cbData; + if (!psz || !csz) + ret = len; + else + { + WCHAR *ptr = psz; + + for (i = 0; i < pValue->cbData && ptr - psz < csz; ptr++, i++) + *ptr = pValue->pbData[i]; + ret = ptr - psz; + } + break; + case CERT_RDN_BMP_STRING: + case CERT_RDN_UTF8_STRING: + strLen = len = pValue->cbData / sizeof(WCHAR); + if (!psz || !csz) + ret = len; + else + { + WCHAR *ptr = psz; + + for (i = 0; i < strLen && ptr - psz < csz; ptr++, i++) + *ptr = ((LPCWSTR)pValue->pbData)[i]; + ret = ptr - psz; + } + break; + default: + FIXME("string type %d unimplemented\n", dwValueType); + } + if (psz && csz) + { + *(psz + ret) = '\0'; + csz--; + ret++; + } + else + ret++; + TRACE("returning %d (%s)\n", ret, debugstr_w(psz)); + return ret; +} + /* Adds the prefix prefix to the string pointed to by psz, followed by the * character '='. Copies no more than csz characters. Returns the number of * characters copied. If psz is NULL, returns the number of characters that @@ -358,10 +487,16 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName, psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); ret += chars; } - chars = CertRDNValueToStrA( - rdn->rgRDNAttr[j].dwValueType, - &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, - psz ? csz - ret : 0); + if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) + chars = QuoteCertRDNValueToStrA( + rdn->rgRDNAttr[j].dwValueType, + &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, + psz ? csz - ret : 0); + else + chars = CertRDNValueToStrA( + rdn->rgRDNAttr[j].dwValueType, + &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, + psz ? csz - ret : 0); if (chars) ret += chars - 1; if (j < rdn->cRDNAttr - 1) @@ -537,10 +672,16 @@ DWORD cert_name_to_str_with_indent(DWORD dwCertEncodingType, DWORD indentLevel, psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0); ret += chars; } - chars = CertRDNValueToStrW( - rdn->rgRDNAttr[j].dwValueType, - &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, - psz ? csz - ret : 0); + if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR) + chars = QuoteCertRDNValueToStrW( + rdn->rgRDNAttr[j].dwValueType, + &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, + psz ? csz - ret : 0); + else + chars = CertRDNValueToStrW( + rdn->rgRDNAttr[j].dwValueType, + &rdn->rgRDNAttr[j].Value, psz ? psz + ret : NULL, + psz ? csz - ret : 0); if (chars) ret += chars - 1; if (j < rdn->cRDNAttr - 1)