mirror of
https://github.com/reactos/reactos.git
synced 2024-12-31 19:42:51 +00:00
Autosyncing with Wine HEAD
svn path=/trunk/; revision=23201
This commit is contained in:
parent
74739f95d9
commit
fb9067d427
8 changed files with 950 additions and 145 deletions
|
@ -244,12 +244,7 @@ static BOOL WINAPI CertContext_GetProperty(void *context, DWORD dwPropId,
|
|||
return ret;
|
||||
}
|
||||
|
||||
/* info is assumed to be a CRYPT_KEY_PROV_INFO, followed by its container name,
|
||||
* provider name, and any provider parameters, in a contiguous buffer, but
|
||||
* where info's pointers are assumed to be invalid. Upon return, info's
|
||||
* pointers point to the appropriate memory locations.
|
||||
*/
|
||||
static void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info)
|
||||
void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info)
|
||||
{
|
||||
DWORD i, containerLen, provNameLen;
|
||||
LPBYTE data = (LPBYTE)info + sizeof(CRYPT_KEY_PROV_INFO);
|
||||
|
@ -1826,6 +1821,7 @@ static PCCERT_CONTEXT CRYPT_CreateSignedCert(PCRYPT_DER_BLOB blob,
|
|||
}
|
||||
|
||||
/* Copies data from the parameters into info, where:
|
||||
* pSerialNumber: The serial number. Must not be NULL.
|
||||
* pSubjectIssuerBlob: Specifies both the subject and issuer for info.
|
||||
* Must not be NULL
|
||||
* pSignatureAlgorithm: Optional.
|
||||
|
@ -1836,23 +1832,22 @@ static PCCERT_CONTEXT CRYPT_CreateSignedCert(PCRYPT_DER_BLOB blob,
|
|||
* pubKey: The public key of the certificate. Must not be NULL.
|
||||
* pExtensions: Extensions to be included with the certificate. Optional.
|
||||
*/
|
||||
static void CRYPT_MakeCertInfo(PCERT_INFO info,
|
||||
static void CRYPT_MakeCertInfo(PCERT_INFO info, PCRYPT_DATA_BLOB pSerialNumber,
|
||||
PCERT_NAME_BLOB pSubjectIssuerBlob,
|
||||
PCRYPT_ALGORITHM_IDENTIFIER pSignatureAlgorithm, PSYSTEMTIME pStartTime,
|
||||
PSYSTEMTIME pEndTime, PCERT_PUBLIC_KEY_INFO pubKey,
|
||||
PCERT_EXTENSIONS pExtensions)
|
||||
{
|
||||
/* FIXME: what serial number to use? */
|
||||
static const BYTE serialNum[] = { 1 };
|
||||
static CHAR oid[] = szOID_RSA_SHA1RSA;
|
||||
|
||||
assert(info);
|
||||
assert(pSerialNumber);
|
||||
assert(pSubjectIssuerBlob);
|
||||
assert(pubKey);
|
||||
|
||||
info->dwVersion = CERT_V3;
|
||||
info->SerialNumber.cbData = sizeof(serialNum);
|
||||
info->SerialNumber.pbData = (LPBYTE)serialNum;
|
||||
info->SerialNumber.cbData = pSerialNumber->cbData;
|
||||
info->SerialNumber.pbData = pSerialNumber->pbData;
|
||||
if (pSignatureAlgorithm)
|
||||
memcpy(&info->SignatureAlgorithm, pSignatureAlgorithm,
|
||||
sizeof(info->SignatureAlgorithm));
|
||||
|
@ -1910,9 +1905,9 @@ static HCRYPTPROV CRYPT_CreateKeyProv(void)
|
|||
UuidCreateFunc uuidCreate = (UuidCreateFunc)GetProcAddress(rpcrt,
|
||||
"UuidCreate");
|
||||
UuidToStringFunc uuidToString = (UuidToStringFunc)GetProcAddress(rpcrt,
|
||||
"UuidToString");
|
||||
"UuidToStringA");
|
||||
RpcStringFreeFunc rpcStringFree = (RpcStringFreeFunc)GetProcAddress(
|
||||
rpcrt, "RpcStringFree");
|
||||
rpcrt, "RpcStringFreeA");
|
||||
|
||||
if (uuidCreate && uuidToString && rpcStringFree)
|
||||
{
|
||||
|
@ -1978,10 +1973,12 @@ PCCERT_CONTEXT WINAPI CertCreateSelfSignCertificate(HCRYPTPROV hProv,
|
|||
{
|
||||
CERT_INFO info = { 0 };
|
||||
CRYPT_DER_BLOB blob = { 0, NULL };
|
||||
BOOL ret;
|
||||
BYTE serial[16];
|
||||
CRYPT_DATA_BLOB serialBlob = { sizeof(serial), serial };
|
||||
|
||||
CRYPT_MakeCertInfo(&info, pSubjectIssuerBlob, pSignatureAlgorithm,
|
||||
pStartTime, pEndTime, pubKey, pExtensions);
|
||||
CryptGenRandom(hProv, sizeof(serial), serial);
|
||||
CRYPT_MakeCertInfo(&info, &serialBlob, pSubjectIssuerBlob,
|
||||
pSignatureAlgorithm, pStartTime, pEndTime, pubKey, pExtensions);
|
||||
ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_CERT_TO_BE_SIGNED,
|
||||
&info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&blob.pbData,
|
||||
&blob.cbData);
|
||||
|
|
|
@ -89,7 +89,7 @@
|
|||
@ stdcall CertVerifySubjectCertificateContext(ptr ptr ptr)
|
||||
@ stdcall CertVerifyTimeValidity(ptr ptr)
|
||||
@ stub CertVerifyValidityNesting
|
||||
@ stub CreateFileU
|
||||
@ 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 CryptStringToBinaryA(str long long ptr ptr ptr ptr)
|
||||
|
|
|
@ -23,13 +23,20 @@
|
|||
#define ASN_BOOL (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x01)
|
||||
#define ASN_BITSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x03)
|
||||
#define ASN_ENUMERATED (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0a)
|
||||
#define ASN_UTF8STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x0c)
|
||||
#define ASN_SETOF (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x11)
|
||||
#define ASN_NUMERICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x12)
|
||||
#define ASN_PRINTABLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x13)
|
||||
#define ASN_T61STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x14)
|
||||
#define ASN_VIDEOTEXSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x15)
|
||||
#define ASN_IA5STRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x16)
|
||||
#define ASN_UTCTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x17)
|
||||
#define ASN_GENERALTIME (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x18)
|
||||
#define ASN_GRAPHICSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x19)
|
||||
#define ASN_VISIBLESTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1a)
|
||||
#define ASN_GENERALSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1b)
|
||||
#define ASN_UNIVERSALSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1c)
|
||||
#define ASN_BMPSTRING (ASN_UNIVERSAL | ASN_PRIMITIVE | 0x1e)
|
||||
|
||||
/* The following aren't defined in wincrypt.h, as they're "reserved" */
|
||||
#define CERT_CERT_PROP_ID 32
|
||||
|
@ -97,6 +104,14 @@ extern PCWINE_CONTEXT_INTERFACE pCTLInterface;
|
|||
const void *CRYPT_ReadSerializedElement(const BYTE *pbElement,
|
||||
DWORD cbElement, DWORD dwContextTypeFlags, DWORD *pdwContentType);
|
||||
|
||||
/* Fixes up the the pointers in info, where info is assumed to be a
|
||||
* CRYPT_KEY_PROV_INFO, followed by its container name, provider name, and any
|
||||
* provider parameters, in a contiguous buffer, but where info's pointers are
|
||||
* assumed to be invalid. Upon return, info's pointers point to the
|
||||
* appropriate memory locations.
|
||||
*/
|
||||
void CRYPT_FixKeyProvInfoPointers(PCRYPT_KEY_PROV_INFO info);
|
||||
|
||||
DWORD CertStore_GetAccessState(HCERTSTORE hCertStore);
|
||||
|
||||
/**
|
||||
|
|
|
@ -42,6 +42,7 @@
|
|||
#include "winbase.h"
|
||||
#include "excpt.h"
|
||||
#include "wincrypt.h"
|
||||
#include "winnls.h"
|
||||
#include "winreg.h"
|
||||
#include "snmp.h"
|
||||
#include "wine/debug.h"
|
||||
|
@ -1271,33 +1272,75 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
|
|||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
|
||||
|
||||
switch (pbEncoded[0])
|
||||
{
|
||||
case ASN_OCTETSTRING:
|
||||
valueType = CERT_RDN_OCTET_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_NUMERICSTRING:
|
||||
valueType = CERT_RDN_NUMERIC_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_PRINTABLESTRING:
|
||||
valueType = CERT_RDN_PRINTABLE_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_IA5STRING:
|
||||
valueType = CERT_RDN_IA5_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_T61STRING:
|
||||
valueType = CERT_RDN_T61_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_VIDEOTEXSTRING:
|
||||
valueType = CERT_RDN_VIDEOTEX_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_GRAPHICSTRING:
|
||||
valueType = CERT_RDN_GRAPHIC_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_VISIBLESTRING:
|
||||
valueType = CERT_RDN_VISIBLE_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_GENERALSTRING:
|
||||
valueType = CERT_RDN_GENERAL_STRING;
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_UNIVERSALSTRING:
|
||||
FIXME("ASN_UNIVERSALSTRING: unimplemented\n");
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
break;
|
||||
case ASN_BMPSTRING:
|
||||
valueType = CERT_RDN_BMP_STRING;
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
case ASN_UTF8STRING:
|
||||
valueType = CERT_RDN_UTF8_STRING;
|
||||
bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
|
||||
(LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2;
|
||||
break;
|
||||
default:
|
||||
FIXME("Unimplemented string type %02x\n", pbEncoded[0]);
|
||||
SetLastError(OSS_UNIMPLEMENTED);
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
DWORD bytesNeeded = sizeof(CERT_NAME_VALUE);
|
||||
|
||||
switch (pbEncoded[0])
|
||||
{
|
||||
case ASN_NUMERICSTRING:
|
||||
case ASN_PRINTABLESTRING:
|
||||
case ASN_IA5STRING:
|
||||
case ASN_T61STRING:
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
bytesNeeded += dataLen;
|
||||
break;
|
||||
}
|
||||
if (!value)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if (*pcbStructInfo < bytesNeeded)
|
||||
|
@ -1309,40 +1352,53 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValueInternal(DWORD dwCertEncodingType,
|
|||
else
|
||||
{
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
switch (pbEncoded[0])
|
||||
{
|
||||
case ASN_NUMERICSTRING:
|
||||
value->dwValueType = CERT_RDN_NUMERIC_STRING;
|
||||
break;
|
||||
case ASN_PRINTABLESTRING:
|
||||
value->dwValueType = CERT_RDN_PRINTABLE_STRING;
|
||||
break;
|
||||
case ASN_IA5STRING:
|
||||
value->dwValueType = CERT_RDN_IA5_STRING;
|
||||
break;
|
||||
case ASN_T61STRING:
|
||||
value->dwValueType = CERT_RDN_T61_STRING;
|
||||
break;
|
||||
}
|
||||
value->dwValueType = valueType;
|
||||
if (dataLen)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
assert(value->Value.pbData);
|
||||
switch (pbEncoded[0])
|
||||
{
|
||||
case ASN_OCTETSTRING:
|
||||
case ASN_NUMERICSTRING:
|
||||
case ASN_PRINTABLESTRING:
|
||||
case ASN_IA5STRING:
|
||||
case ASN_T61STRING:
|
||||
case ASN_VIDEOTEXSTRING:
|
||||
case ASN_GRAPHICSTRING:
|
||||
case ASN_VISIBLESTRING:
|
||||
case ASN_GENERALSTRING:
|
||||
value->Value.cbData = dataLen;
|
||||
if (dwFlags & CRYPT_DECODE_NOCOPY_FLAG)
|
||||
value->Value.pbData = (BYTE *)pbEncoded + 1 +
|
||||
lenBytes;
|
||||
else
|
||||
if (dataLen)
|
||||
{
|
||||
assert(value->Value.pbData);
|
||||
memcpy(value->Value.pbData,
|
||||
pbEncoded + 1 + lenBytes, dataLen);
|
||||
if (!(dwFlags & CRYPT_DECODE_NOCOPY_FLAG))
|
||||
memcpy(value->Value.pbData,
|
||||
pbEncoded + 1 + lenBytes, dataLen);
|
||||
else
|
||||
value->Value.pbData = (LPBYTE)pbEncoded + 1 +
|
||||
lenBytes;
|
||||
}
|
||||
break;
|
||||
case ASN_BMPSTRING:
|
||||
{
|
||||
LPWSTR str = (LPWSTR)value->Value.pbData;
|
||||
|
||||
value->Value.cbData = dataLen;
|
||||
for (i = 0; i < dataLen / 2; i++)
|
||||
str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
|
||||
pbEncoded[1 + lenBytes + 2 * i + 1];
|
||||
break;
|
||||
}
|
||||
case ASN_UTF8STRING:
|
||||
{
|
||||
LPWSTR str = (LPWSTR)value->Value.pbData;
|
||||
|
||||
value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
|
||||
(LPSTR)pbEncoded + 1 + lenBytes, dataLen,
|
||||
str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -1395,6 +1451,179 @@ static BOOL WINAPI CRYPT_AsnDecodeNameValue(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValueInternal(
|
||||
DWORD dwCertEncodingType, LPCSTR lpszStructType, const BYTE *pbEncoded,
|
||||
DWORD cbEncoded, DWORD dwFlags, PCRYPT_DECODE_PARA pDecodePara,
|
||||
void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
DWORD dataLen;
|
||||
CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
|
||||
|
||||
if ((ret = CRYPT_GetLen(pbEncoded, cbEncoded, &dataLen)))
|
||||
{
|
||||
BYTE lenBytes = GET_LEN_BYTES(pbEncoded[1]);
|
||||
DWORD bytesNeeded = sizeof(CERT_NAME_VALUE), valueType;
|
||||
|
||||
switch (pbEncoded[0])
|
||||
{
|
||||
case ASN_NUMERICSTRING:
|
||||
valueType = CERT_RDN_NUMERIC_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_PRINTABLESTRING:
|
||||
valueType = CERT_RDN_PRINTABLE_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_IA5STRING:
|
||||
valueType = CERT_RDN_IA5_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_T61STRING:
|
||||
valueType = CERT_RDN_T61_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_VIDEOTEXSTRING:
|
||||
valueType = CERT_RDN_VIDEOTEX_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_GRAPHICSTRING:
|
||||
valueType = CERT_RDN_GRAPHIC_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_VISIBLESTRING:
|
||||
valueType = CERT_RDN_VISIBLE_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_GENERALSTRING:
|
||||
valueType = CERT_RDN_GENERAL_STRING;
|
||||
bytesNeeded += (dataLen + 1) * 2;
|
||||
break;
|
||||
case ASN_UNIVERSALSTRING:
|
||||
valueType = CERT_RDN_UNIVERSAL_STRING;
|
||||
bytesNeeded += dataLen / 2 + 2;
|
||||
break;
|
||||
case ASN_BMPSTRING:
|
||||
valueType = CERT_RDN_BMP_STRING;
|
||||
bytesNeeded += dataLen + 2;
|
||||
break;
|
||||
case ASN_UTF8STRING:
|
||||
valueType = CERT_RDN_UTF8_STRING;
|
||||
bytesNeeded += MultiByteToWideChar(CP_UTF8, 0,
|
||||
(LPSTR)pbEncoded + 1 + lenBytes, dataLen, NULL, 0) * 2 + 2;
|
||||
break;
|
||||
default:
|
||||
SetLastError(CRYPT_E_ASN1_BADTAG);
|
||||
ret = FALSE;
|
||||
}
|
||||
if (ret)
|
||||
{
|
||||
if (!value)
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
else if (*pcbStructInfo < bytesNeeded)
|
||||
{
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
*pcbStructInfo = bytesNeeded;
|
||||
value->dwValueType = valueType;
|
||||
if (dataLen)
|
||||
{
|
||||
DWORD i;
|
||||
LPWSTR str = (LPWSTR)value->Value.pbData;
|
||||
|
||||
assert(value->Value.pbData);
|
||||
switch (pbEncoded[0])
|
||||
{
|
||||
case ASN_NUMERICSTRING:
|
||||
case ASN_PRINTABLESTRING:
|
||||
case ASN_IA5STRING:
|
||||
case ASN_T61STRING:
|
||||
case ASN_VIDEOTEXSTRING:
|
||||
case ASN_GRAPHICSTRING:
|
||||
case ASN_VISIBLESTRING:
|
||||
case ASN_GENERALSTRING:
|
||||
value->Value.cbData = dataLen * 2 + 2;
|
||||
for (i = 0; i < dataLen; i++)
|
||||
str[i] = pbEncoded[1 + lenBytes + i];
|
||||
str[i] = 0;
|
||||
break;
|
||||
case ASN_UNIVERSALSTRING:
|
||||
value->Value.cbData = dataLen / 2 + 2;
|
||||
for (i = 0; i < dataLen / 4; i++)
|
||||
str[i] = (pbEncoded[1 + lenBytes + 2 * i + 2] << 8)
|
||||
| pbEncoded[1 + lenBytes + 2 * i + 3];
|
||||
str[i] = 0;
|
||||
break;
|
||||
case ASN_BMPSTRING:
|
||||
value->Value.cbData = dataLen + 2;
|
||||
for (i = 0; i < dataLen / 2; i++)
|
||||
str[i] = (pbEncoded[1 + lenBytes + 2 * i] << 8) |
|
||||
pbEncoded[1 + lenBytes + 2 * i + 1];
|
||||
str[i] = 0;
|
||||
break;
|
||||
case ASN_UTF8STRING:
|
||||
value->Value.cbData = MultiByteToWideChar(CP_UTF8, 0,
|
||||
(LPSTR)pbEncoded + 1 + lenBytes, dataLen,
|
||||
str, bytesNeeded - sizeof(CERT_NAME_VALUE)) * 2;
|
||||
str[value->Value.cbData / 2] = 0;
|
||||
value->Value.cbData += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
value->Value.cbData = 0;
|
||||
value->Value.pbData = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeUnicodeNameValue(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
|
||||
__TRY
|
||||
{
|
||||
ret = CRYPT_AsnDecodeUnicodeNameValueInternal(dwCertEncodingType,
|
||||
lpszStructType, pbEncoded, cbEncoded,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, NULL, pcbStructInfo);
|
||||
if (ret && pvStructInfo)
|
||||
{
|
||||
ret = CRYPT_DecodeEnsureSpace(dwFlags, pDecodePara, pvStructInfo,
|
||||
pcbStructInfo, *pcbStructInfo);
|
||||
if (ret)
|
||||
{
|
||||
CERT_NAME_VALUE *value;
|
||||
|
||||
if (dwFlags & CRYPT_DECODE_ALLOC_FLAG)
|
||||
pvStructInfo = *(BYTE **)pvStructInfo;
|
||||
value = (CERT_NAME_VALUE *)pvStructInfo;
|
||||
value->Value.pbData = ((BYTE *)value + sizeof(CERT_NAME_VALUE));
|
||||
ret = CRYPT_AsnDecodeUnicodeNameValueInternal(
|
||||
dwCertEncodingType, lpszStructType, pbEncoded, cbEncoded,
|
||||
dwFlags & ~CRYPT_DECODE_ALLOC_FLAG, NULL, pvStructInfo,
|
||||
pcbStructInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
ret = FALSE;
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnDecodeRdnAttr(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, DWORD dwFlags,
|
||||
PCRYPT_DECODE_PARA pDecodePara, void *pvStructInfo, DWORD *pcbStructInfo)
|
||||
|
@ -3190,6 +3419,9 @@ BOOL WINAPI CryptDecodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)RSA_CSP_PUBLICKEYBLOB:
|
||||
decodeFunc = CRYPT_AsnDecodeRsaPubKey;
|
||||
break;
|
||||
case (WORD)X509_UNICODE_NAME_VALUE:
|
||||
decodeFunc = CRYPT_AsnDecodeUnicodeNameValue;
|
||||
break;
|
||||
case (WORD)X509_OCTET_STRING:
|
||||
decodeFunc = CRYPT_AsnDecodeOctets;
|
||||
break;
|
||||
|
|
|
@ -46,6 +46,7 @@
|
|||
#include "snmp.h"
|
||||
#include "wine/debug.h"
|
||||
#include "wine/exception.h"
|
||||
#include "wine/unicode.h"
|
||||
#include "crypt32_private.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(crypt);
|
||||
|
@ -163,6 +164,8 @@ static BOOL CRYPT_EncodeEnsureSpace(DWORD dwFlags,
|
|||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
*pcbEncoded = bytesNeeded;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -381,18 +384,18 @@ static BOOL WINAPI CRYPT_CopyEncodedBlob(DWORD dwCertEncodingType,
|
|||
*pcbEncoded = blob->cbData;
|
||||
ret = TRUE;
|
||||
}
|
||||
else if (*pcbEncoded < blob->cbData)
|
||||
{
|
||||
*pcbEncoded = blob->cbData;
|
||||
SetLastError(ERROR_MORE_DATA);
|
||||
ret = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (blob->cbData)
|
||||
memcpy(pbEncoded, blob->pbData, blob->cbData);
|
||||
*pcbEncoded = blob->cbData;
|
||||
ret = TRUE;
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
|
||||
pcbEncoded, blob->cbData)))
|
||||
{
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
if (blob->cbData)
|
||||
memcpy(pbEncoded, blob->pbData, blob->cbData);
|
||||
*pcbEncoded = blob->cbData;
|
||||
ret = TRUE;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -910,6 +913,104 @@ static BOOL WINAPI CRYPT_AsnEncodeOid(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeStringCoerce(const CERT_NAME_VALUE *value,
|
||||
BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCSTR str = (LPCSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
|
||||
encodedLen = value->Value.cbData ? value->Value.cbData : lstrlenA(str);
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = tag;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
memcpy(pbEncoded, str, encodedLen);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeBMPString(const CERT_NAME_VALUE *value,
|
||||
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCWSTR str = (LPCWSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, strLen;
|
||||
|
||||
strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
|
||||
lstrlenW(str);
|
||||
CRYPT_EncodeLen(strLen * 2, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + strLen * 2;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = ASN_BMPSTRING;
|
||||
CRYPT_EncodeLen(strLen * 2, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
for (i = 0; i < strLen; i++)
|
||||
{
|
||||
*pbEncoded++ = (str[i] & 0xff00) >> 8;
|
||||
*pbEncoded++ = str[i] & 0x00ff;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeUTF8String(const CERT_NAME_VALUE *value,
|
||||
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCWSTR str = (LPCWSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen, strLen;
|
||||
|
||||
strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
|
||||
lstrlenW(str);
|
||||
encodedLen = WideCharToMultiByte(CP_UTF8, 0, str, strLen, NULL, 0, NULL,
|
||||
NULL);
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = ASN_UTF8STRING;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
WideCharToMultiByte(CP_UTF8, 0, str, strLen, (LPSTR)pbEncoded,
|
||||
bytesNeeded - lenBytes - 1, NULL, NULL);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
|
@ -918,59 +1019,71 @@ static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
|
|||
|
||||
__TRY
|
||||
{
|
||||
BYTE tag;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
const CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
|
||||
|
||||
switch (value->dwValueType)
|
||||
{
|
||||
case CERT_RDN_NUMERIC_STRING:
|
||||
tag = ASN_NUMERICSTRING;
|
||||
encodedLen = value->Value.cbData;
|
||||
break;
|
||||
case CERT_RDN_PRINTABLE_STRING:
|
||||
tag = ASN_PRINTABLESTRING;
|
||||
encodedLen = value->Value.cbData;
|
||||
break;
|
||||
case CERT_RDN_T61_STRING:
|
||||
tag = ASN_T61STRING;
|
||||
encodedLen = value->Value.cbData;
|
||||
break;
|
||||
case CERT_RDN_IA5_STRING:
|
||||
tag = ASN_IA5STRING;
|
||||
encodedLen = value->Value.cbData;
|
||||
break;
|
||||
case CERT_RDN_ANY_TYPE:
|
||||
/* explicitly disallowed */
|
||||
SetLastError(E_INVALIDARG);
|
||||
return FALSE;
|
||||
ret = FALSE;
|
||||
break;
|
||||
case CERT_RDN_ENCODED_BLOB:
|
||||
ret = CRYPT_CopyEncodedBlob(dwCertEncodingType, NULL,
|
||||
&value->Value, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_OCTET_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_OCTETSTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_NUMERIC_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_NUMERICSTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_PRINTABLE_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_PRINTABLESTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_TELETEX_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_T61STRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_VIDEOTEX_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value,
|
||||
ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_IA5_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_IA5STRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_GRAPHIC_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GRAPHICSTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_VISIBLE_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_VISIBLESTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_GENERAL_STRING:
|
||||
ret = CRYPT_AsnEncodeStringCoerce(value, ASN_GENERALSTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_UNIVERSAL_STRING:
|
||||
FIXME("CERT_RDN_UNIVERSAL_STRING: unimplemented\n");
|
||||
SetLastError(CRYPT_E_ASN1_CHOICE);
|
||||
ret = FALSE;
|
||||
break;
|
||||
case CERT_RDN_BMP_STRING:
|
||||
ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_UTF8_STRING:
|
||||
ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
default:
|
||||
FIXME("String type %ld unimplemented\n", value->dwValueType);
|
||||
return FALSE;
|
||||
}
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara, pbEncoded,
|
||||
pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = tag;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
switch (value->dwValueType)
|
||||
{
|
||||
case CERT_RDN_NUMERIC_STRING:
|
||||
case CERT_RDN_PRINTABLE_STRING:
|
||||
case CERT_RDN_T61_STRING:
|
||||
case CERT_RDN_IA5_STRING:
|
||||
memcpy(pbEncoded, value->Value.pbData, value->Value.cbData);
|
||||
}
|
||||
}
|
||||
SetLastError(CRYPT_E_ASN1_CHOICE);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
|
@ -982,6 +1095,284 @@ static BOOL WINAPI CRYPT_AsnEncodeNameValue(DWORD dwCertEncodingType,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeUnicodeStringCoerce(const CERT_NAME_VALUE *value,
|
||||
BYTE tag, DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCWSTR str = (LPCWSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
|
||||
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
|
||||
lstrlenW(str);
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = tag;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
for (i = 0; i < encodedLen; i++)
|
||||
*pbEncoded++ = (BYTE)str[i];
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeNumericString(const CERT_NAME_VALUE *value,
|
||||
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCWSTR str = (LPCWSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
|
||||
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
|
||||
lstrlenW(str);
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = ASN_NUMERICSTRING;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
for (i = 0; ret && i < encodedLen; i++)
|
||||
{
|
||||
if (isdigitW(str[i]))
|
||||
*pbEncoded++ = (BYTE)str[i];
|
||||
else
|
||||
{
|
||||
*pcbEncoded = i;
|
||||
SetLastError(CRYPT_E_INVALID_NUMERIC_STRING);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline int isprintableW(WCHAR wc)
|
||||
{
|
||||
return isalnumW(wc) || isspaceW(wc) || wc == '\'' || wc == '(' ||
|
||||
wc == ')' || wc == '+' || wc == ',' || wc == '-' || wc == '.' ||
|
||||
wc == '/' || wc == ':' || wc == '=' || wc == '?';
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodePrintableString(const CERT_NAME_VALUE *value,
|
||||
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCWSTR str = (LPCWSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
|
||||
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
|
||||
lstrlenW(str);
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = ASN_PRINTABLESTRING;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
for (i = 0; ret && i < encodedLen; i++)
|
||||
{
|
||||
if (isprintableW(str[i]))
|
||||
*pbEncoded++ = (BYTE)str[i];
|
||||
else
|
||||
{
|
||||
*pcbEncoded = i;
|
||||
SetLastError(CRYPT_E_INVALID_PRINTABLE_STRING);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeIA5String(const CERT_NAME_VALUE *value,
|
||||
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCWSTR str = (LPCWSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, encodedLen;
|
||||
|
||||
encodedLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
|
||||
lstrlenW(str);
|
||||
CRYPT_EncodeLen(encodedLen, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + encodedLen;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = ASN_IA5STRING;
|
||||
CRYPT_EncodeLen(encodedLen, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
for (i = 0; ret && i < encodedLen; i++)
|
||||
{
|
||||
if (str[i] <= 0x7f)
|
||||
*pbEncoded++ = (BYTE)str[i];
|
||||
else
|
||||
{
|
||||
*pcbEncoded = i;
|
||||
SetLastError(CRYPT_E_INVALID_IA5_STRING);
|
||||
ret = FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL CRYPT_AsnEncodeUniversalString(const CERT_NAME_VALUE *value,
|
||||
DWORD dwFlags, PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded,
|
||||
DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = TRUE;
|
||||
LPCWSTR str = (LPCWSTR)value->Value.pbData;
|
||||
DWORD bytesNeeded, lenBytes, strLen;
|
||||
|
||||
/* FIXME: doesn't handle composite characters */
|
||||
strLen = value->Value.cbData ? value->Value.cbData / sizeof(WCHAR) :
|
||||
lstrlenW(str);
|
||||
CRYPT_EncodeLen(strLen * 4, NULL, &lenBytes);
|
||||
bytesNeeded = 1 + lenBytes + strLen * 4;
|
||||
if (!pbEncoded)
|
||||
*pcbEncoded = bytesNeeded;
|
||||
else
|
||||
{
|
||||
if ((ret = CRYPT_EncodeEnsureSpace(dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded, bytesNeeded)))
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
if (dwFlags & CRYPT_ENCODE_ALLOC_FLAG)
|
||||
pbEncoded = *(BYTE **)pbEncoded;
|
||||
*pbEncoded++ = ASN_UNIVERSALSTRING;
|
||||
CRYPT_EncodeLen(strLen * 4, pbEncoded, &lenBytes);
|
||||
pbEncoded += lenBytes;
|
||||
for (i = 0; i < strLen; i++)
|
||||
{
|
||||
*pbEncoded++ = 0;
|
||||
*pbEncoded++ = 0;
|
||||
*pbEncoded++ = (BYTE)((str[i] & 0xff00) >> 8);
|
||||
*pbEncoded++ = (BYTE)(str[i] & 0x00ff);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeUnicodeNameValue(DWORD dwCertEncodingType,
|
||||
LPCSTR lpszStructType, const void *pvStructInfo, DWORD dwFlags,
|
||||
PCRYPT_ENCODE_PARA pEncodePara, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
BOOL ret = FALSE;
|
||||
|
||||
__TRY
|
||||
{
|
||||
const CERT_NAME_VALUE *value = (CERT_NAME_VALUE *)pvStructInfo;
|
||||
|
||||
switch (value->dwValueType)
|
||||
{
|
||||
case CERT_RDN_ANY_TYPE:
|
||||
case CERT_RDN_ENCODED_BLOB:
|
||||
case CERT_RDN_OCTET_STRING:
|
||||
SetLastError(CRYPT_E_NOT_CHAR_STRING);
|
||||
break;
|
||||
case CERT_RDN_NUMERIC_STRING:
|
||||
ret = CRYPT_AsnEncodeNumericString(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_PRINTABLE_STRING:
|
||||
ret = CRYPT_AsnEncodePrintableString(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_TELETEX_STRING:
|
||||
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_T61STRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_VIDEOTEX_STRING:
|
||||
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value,
|
||||
ASN_VIDEOTEXSTRING, dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_IA5_STRING:
|
||||
ret = CRYPT_AsnEncodeIA5String(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_GRAPHIC_STRING:
|
||||
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GRAPHICSTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_VISIBLE_STRING:
|
||||
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_VISIBLESTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_GENERAL_STRING:
|
||||
ret = CRYPT_AsnEncodeUnicodeStringCoerce(value, ASN_GENERALSTRING,
|
||||
dwFlags, pEncodePara, pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_UNIVERSAL_STRING:
|
||||
ret = CRYPT_AsnEncodeUniversalString(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_BMP_STRING:
|
||||
ret = CRYPT_AsnEncodeBMPString(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
case CERT_RDN_UTF8_STRING:
|
||||
ret = CRYPT_AsnEncodeUTF8String(value, dwFlags, pEncodePara,
|
||||
pbEncoded, pcbEncoded);
|
||||
break;
|
||||
default:
|
||||
SetLastError(CRYPT_E_ASN1_CHOICE);
|
||||
}
|
||||
}
|
||||
__EXCEPT_PAGE_FAULT
|
||||
{
|
||||
SetLastError(STATUS_ACCESS_VIOLATION);
|
||||
}
|
||||
__ENDTRY
|
||||
return ret;
|
||||
}
|
||||
|
||||
static BOOL WINAPI CRYPT_AsnEncodeRdnAttr(DWORD dwCertEncodingType,
|
||||
CERT_RDN_ATTR *attr, BYTE *pbEncoded, DWORD *pcbEncoded)
|
||||
{
|
||||
|
@ -2396,6 +2787,9 @@ BOOL WINAPI CryptEncodeObjectEx(DWORD dwCertEncodingType, LPCSTR lpszStructType,
|
|||
case (WORD)RSA_CSP_PUBLICKEYBLOB:
|
||||
encodeFunc = CRYPT_AsnEncodeRsaPubKey;
|
||||
break;
|
||||
case (WORD)X509_UNICODE_NAME_VALUE:
|
||||
encodeFunc = CRYPT_AsnEncodeUnicodeNameValue;
|
||||
break;
|
||||
case (WORD)X509_OCTET_STRING:
|
||||
encodeFunc = CRYPT_AsnEncodeOctets;
|
||||
break;
|
||||
|
|
|
@ -363,6 +363,16 @@ const void *CRYPT_ReadSerializedElement(const BYTE *pbElement, DWORD cbElement,
|
|||
ret = contextInterface->setProp(context,
|
||||
hdr->propID, 0, pbElement);
|
||||
break;
|
||||
case CERT_KEY_PROV_INFO_PROP_ID:
|
||||
{
|
||||
PCRYPT_KEY_PROV_INFO info =
|
||||
(PCRYPT_KEY_PROV_INFO)pbElement;
|
||||
|
||||
CRYPT_FixKeyProvInfoPointers(info);
|
||||
ret = contextInterface->setProp(context,
|
||||
hdr->propID, 0, pbElement);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
FIXME("prop ID %ld: stub\n", hdr->propID);
|
||||
}
|
||||
|
|
|
@ -1723,6 +1723,54 @@ static PWINECRYPT_CERTSTORE CRYPT_SysOpenStoreA(HCRYPTPROV hCryptProv,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreW(HCRYPTPROV hCryptProv,
|
||||
DWORD dwFlags, const void *pvPara)
|
||||
{
|
||||
FIXME("(%ld, %08lx, %s): stub\n", hCryptProv, dwFlags,
|
||||
debugstr_w((LPCWSTR)pvPara));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static PWINECRYPT_CERTSTORE CRYPT_FileNameOpenStoreA(HCRYPTPROV hCryptProv,
|
||||
DWORD dwFlags, const void *pvPara)
|
||||
{
|
||||
int len;
|
||||
PWINECRYPT_CERTSTORE ret = NULL;
|
||||
|
||||
TRACE("(%ld, %08lx, %s)\n", hCryptProv, dwFlags,
|
||||
debugstr_a((LPCSTR)pvPara));
|
||||
|
||||
if (!pvPara)
|
||||
{
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
return NULL;
|
||||
}
|
||||
len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, NULL, 0);
|
||||
if (len)
|
||||
{
|
||||
LPWSTR storeName = CryptMemAlloc(len * sizeof(WCHAR));
|
||||
|
||||
if (storeName)
|
||||
{
|
||||
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)pvPara, -1, storeName, len);
|
||||
ret = CRYPT_FileNameOpenStoreW(hCryptProv, dwFlags, storeName);
|
||||
CryptMemFree(storeName);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static PWINECRYPT_CERTSTORE CRYPT_PhysOpenStoreW(HCRYPTPROV hCryptProv,
|
||||
DWORD dwFlags, const void *pvPara)
|
||||
{
|
||||
if (dwFlags & CERT_SYSTEM_STORE_RELOCATE_FLAG)
|
||||
FIXME("(%ld, %08lx, %p): stub\n", hCryptProv, dwFlags, pvPara);
|
||||
else
|
||||
FIXME("(%ld, %08lx, %s): stub\n", hCryptProv, dwFlags,
|
||||
debugstr_w((LPCWSTR)pvPara));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
|
||||
DWORD dwMsgAndCertEncodingType, HCRYPTPROV hCryptProv, DWORD dwFlags,
|
||||
const void* pvPara)
|
||||
|
@ -1743,6 +1791,12 @@ HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
|
|||
case (int)CERT_STORE_PROV_REG:
|
||||
openFunc = CRYPT_RegOpenStore;
|
||||
break;
|
||||
case (int)CERT_STORE_PROV_FILENAME_A:
|
||||
openFunc = CRYPT_FileNameOpenStoreA;
|
||||
break;
|
||||
case (int)CERT_STORE_PROV_FILENAME_W:
|
||||
openFunc = CRYPT_FileNameOpenStoreW;
|
||||
break;
|
||||
case (int)CERT_STORE_PROV_COLLECTION:
|
||||
openFunc = CRYPT_CollectionOpenStore;
|
||||
break;
|
||||
|
@ -1758,6 +1812,9 @@ HCERTSTORE WINAPI CertOpenStore(LPCSTR lpszStoreProvider,
|
|||
case (int)CERT_STORE_PROV_SYSTEM_REGISTRY_W:
|
||||
openFunc = CRYPT_SysRegOpenStoreW;
|
||||
break;
|
||||
case (int)CERT_STORE_PROV_PHYSICAL_W:
|
||||
openFunc = CRYPT_PhysOpenStoreW;
|
||||
break;
|
||||
default:
|
||||
if (LOWORD(lpszStoreProvider))
|
||||
FIXME("unimplemented type %d\n", LOWORD(lpszStoreProvider));
|
||||
|
|
|
@ -62,6 +62,7 @@ DWORD WINAPI CertRDNValueToStrA(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
|
|||
}
|
||||
else
|
||||
ret++;
|
||||
TRACE("returning %ld (%s)\n", ret, debugstr_a(psz));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -106,9 +107,35 @@ DWORD WINAPI CertRDNValueToStrW(DWORD dwValueType, PCERT_RDN_VALUE_BLOB pValue,
|
|||
}
|
||||
else
|
||||
ret++;
|
||||
TRACE("returning %ld (%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
|
||||
* would be copied.
|
||||
*/
|
||||
static DWORD CRYPT_AddPrefixA(LPCSTR prefix, LPSTR psz, DWORD csz)
|
||||
{
|
||||
DWORD chars;
|
||||
|
||||
TRACE("(%s, %p, %ld)\n", debugstr_a(prefix), psz, csz);
|
||||
|
||||
if (psz)
|
||||
{
|
||||
chars = min(lstrlenA(prefix), csz);
|
||||
memcpy(psz, prefix, chars);
|
||||
csz -= chars;
|
||||
*(psz + chars) = '=';
|
||||
chars++;
|
||||
csz--;
|
||||
}
|
||||
else
|
||||
chars = lstrlenA(prefix) + 1;
|
||||
return chars;
|
||||
}
|
||||
|
||||
DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
|
||||
DWORD dwStrType, LPSTR psz, DWORD csz)
|
||||
{
|
||||
|
@ -147,36 +174,45 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
|
|||
else
|
||||
rdnSep = plusSep;
|
||||
rdnSepLen = strlen(rdnSep);
|
||||
for (i = 0; ret < csz && i < info->cRDN; i++)
|
||||
for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
|
||||
{
|
||||
for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
|
||||
for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++)
|
||||
{
|
||||
DWORD chars;
|
||||
char prefixBuf[10]; /* big enough for GivenName */
|
||||
LPCSTR prefix = NULL;
|
||||
|
||||
if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
|
||||
prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId;
|
||||
else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
|
||||
{
|
||||
PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
|
||||
CRYPT_OID_INFO_OID_KEY,
|
||||
info->rgRDN[i].rgRDNAttr[j].pszObjId,
|
||||
CRYPT_RDN_ATTR_OID_GROUP_ID);
|
||||
|
||||
if (oidInfo)
|
||||
{
|
||||
WideCharToMultiByte(CP_ACP, 0, oidInfo->pwszName, -1,
|
||||
prefixBuf, sizeof(prefixBuf), NULL, NULL);
|
||||
prefix = prefixBuf;
|
||||
}
|
||||
else
|
||||
prefix = info->rgRDN[i].rgRDNAttr[j].pszObjId;
|
||||
}
|
||||
if (prefix)
|
||||
{
|
||||
/* - 1 is needed to account for the NULL terminator. */
|
||||
chars = min(
|
||||
lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
|
||||
csz - ret - 1);
|
||||
if (psz && chars)
|
||||
memcpy(psz + ret, info->rgRDN[i].rgRDNAttr[j].pszObjId,
|
||||
chars);
|
||||
chars = CRYPT_AddPrefixA(prefix,
|
||||
psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
|
||||
ret += chars;
|
||||
csz -= chars;
|
||||
if (csz > 1)
|
||||
{
|
||||
if (psz)
|
||||
*(psz + ret) = '=';
|
||||
ret++;
|
||||
csz--;
|
||||
}
|
||||
}
|
||||
/* FIXME: handle quoting */
|
||||
chars = CertRDNValueToStrA(
|
||||
info->rgRDN[i].rgRDNAttr[j].dwValueType,
|
||||
&info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
|
||||
csz - ret - 1);
|
||||
psz ? csz - ret : 0);
|
||||
if (chars)
|
||||
ret += chars - 1;
|
||||
if (j < info->rgRDN[i].cRDNAttr - 1)
|
||||
|
@ -203,9 +239,64 @@ DWORD WINAPI CertNameToStrA(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
|
|||
}
|
||||
else
|
||||
ret++;
|
||||
TRACE("Returning %s\n", debugstr_a(psz));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Adds the prefix prefix to the wide-character 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 would be copied.
|
||||
* Assumes the characters in prefix are ASCII (not multibyte characters.)
|
||||
*/
|
||||
static DWORD CRYPT_AddPrefixAToW(LPCSTR prefix, LPWSTR psz, DWORD csz)
|
||||
{
|
||||
DWORD chars;
|
||||
|
||||
TRACE("(%s, %p, %ld)\n", debugstr_a(prefix), psz, csz);
|
||||
|
||||
if (psz)
|
||||
{
|
||||
DWORD i;
|
||||
|
||||
chars = min(lstrlenA(prefix), csz);
|
||||
for (i = 0; i < chars; i++)
|
||||
*(psz + i) = prefix[i];
|
||||
csz -= chars;
|
||||
*(psz + chars) = '=';
|
||||
chars++;
|
||||
csz--;
|
||||
}
|
||||
else
|
||||
chars = lstrlenA(prefix) + 1;
|
||||
return chars;
|
||||
}
|
||||
|
||||
/* 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
|
||||
* would be copied.
|
||||
*/
|
||||
static DWORD CRYPT_AddPrefixW(LPCWSTR prefix, LPWSTR psz, DWORD csz)
|
||||
{
|
||||
DWORD chars;
|
||||
|
||||
TRACE("(%s, %p, %ld)\n", debugstr_w(prefix), psz, csz);
|
||||
|
||||
if (psz)
|
||||
{
|
||||
chars = min(lstrlenW(prefix), csz);
|
||||
memcpy(psz, prefix, chars * sizeof(WCHAR));
|
||||
csz -= chars;
|
||||
*(psz + chars) = '=';
|
||||
chars++;
|
||||
csz--;
|
||||
}
|
||||
else
|
||||
chars = lstrlenW(prefix) + 1;
|
||||
return chars;
|
||||
}
|
||||
|
||||
DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
|
||||
DWORD dwStrType, LPWSTR psz, DWORD csz)
|
||||
{
|
||||
|
@ -244,41 +335,49 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
|
|||
else
|
||||
rdnSep = plusSep;
|
||||
rdnSepLen = lstrlenW(rdnSep);
|
||||
for (i = 0; ret < csz && i < info->cRDN; i++)
|
||||
for (i = 0; (!psz || ret < csz) && i < info->cRDN; i++)
|
||||
{
|
||||
for (j = 0; ret < csz && j < info->rgRDN[i].cRDNAttr; j++)
|
||||
for (j = 0; (!psz || ret < csz) && j < info->rgRDN[i].cRDNAttr; j++)
|
||||
{
|
||||
DWORD chars;
|
||||
LPCSTR prefixA = NULL;
|
||||
LPCWSTR prefixW = NULL;
|
||||
|
||||
if ((dwStrType & 0x000000ff) == CERT_OID_NAME_STR)
|
||||
prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId;
|
||||
else if ((dwStrType & 0x000000ff) == CERT_X500_NAME_STR)
|
||||
{
|
||||
PCCRYPT_OID_INFO oidInfo = CryptFindOIDInfo(
|
||||
CRYPT_OID_INFO_OID_KEY,
|
||||
info->rgRDN[i].rgRDNAttr[j].pszObjId,
|
||||
CRYPT_RDN_ATTR_OID_GROUP_ID);
|
||||
|
||||
if (oidInfo)
|
||||
prefixW = oidInfo->pwszName;
|
||||
else
|
||||
prefixA = info->rgRDN[i].rgRDNAttr[j].pszObjId;
|
||||
}
|
||||
if (prefixW)
|
||||
{
|
||||
/* - 1 is needed to account for the NULL terminator. */
|
||||
chars = min(
|
||||
lstrlenA(info->rgRDN[i].rgRDNAttr[j].pszObjId),
|
||||
csz - ret - 1);
|
||||
if (psz && chars)
|
||||
{
|
||||
DWORD k;
|
||||
|
||||
for (k = 0; k < chars; k++)
|
||||
*(psz + ret + k) =
|
||||
info->rgRDN[i].rgRDNAttr[j].pszObjId[k];
|
||||
}
|
||||
chars = CRYPT_AddPrefixW(prefixW,
|
||||
psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
|
||||
ret += chars;
|
||||
csz -= chars;
|
||||
}
|
||||
else if (prefixA)
|
||||
{
|
||||
/* - 1 is needed to account for the NULL terminator. */
|
||||
chars = CRYPT_AddPrefixAToW(prefixA,
|
||||
psz ? psz + ret : NULL, psz ? csz - ret - 1 : 0);
|
||||
ret += chars;
|
||||
csz -= chars;
|
||||
if (csz > 1)
|
||||
{
|
||||
if (psz)
|
||||
*(psz + ret) = '=';
|
||||
ret++;
|
||||
csz--;
|
||||
}
|
||||
}
|
||||
/* FIXME: handle quoting */
|
||||
chars = CertRDNValueToStrW(
|
||||
info->rgRDN[i].rgRDNAttr[j].dwValueType,
|
||||
&info->rgRDN[i].rgRDNAttr[j].Value, psz ? psz + ret : NULL,
|
||||
csz - ret - 1);
|
||||
psz ? csz - ret : 0);
|
||||
if (chars)
|
||||
ret += chars - 1;
|
||||
if (j < info->rgRDN[i].cRDNAttr - 1)
|
||||
|
@ -305,6 +404,7 @@ DWORD WINAPI CertNameToStrW(DWORD dwCertEncodingType, PCERT_NAME_BLOB pName,
|
|||
}
|
||||
else
|
||||
ret++;
|
||||
TRACE("Returning %s\n", debugstr_w(psz));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue