2 * crypt32 Crypt*Object functions
4 * Copyright 2007 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #define NONAMELESSUNION
28 #include "crypt32_private.h"
30 #include "wine/unicode.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(crypt);
35 static BOOL CRYPT_ReadBlobFromFile(LPCWSTR fileName, PCERT_BLOB blob)
40 TRACE("%s\n", debugstr_w(fileName));
42 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
43 OPEN_EXISTING, 0, NULL);
44 if (file != INVALID_HANDLE_VALUE)
47 blob->cbData = GetFileSize(file, NULL);
50 blob->pbData = CryptMemAlloc(blob->cbData);
55 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
60 TRACE("returning %d\n", ret);
64 static BOOL CRYPT_QueryContextObject(DWORD dwObjectType, const void *pvObject,
65 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
66 DWORD *pdwContentType, HCERTSTORE *phCertStore, const void **ppvContext)
69 const CERT_BLOB *blob;
76 case CERT_QUERY_OBJECT_FILE:
77 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
78 * just read the file directly
80 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
83 case CERT_QUERY_OBJECT_BLOB:
84 blob = (const CERT_BLOB *)pvObject;
88 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
94 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
95 CERT_STORE_CREATE_NEW_FLAG, NULL);
97 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT)
99 ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING,
100 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
102 contentType = CERT_QUERY_CONTENT_CERT;
104 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL))
106 ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
107 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
109 contentType = CERT_QUERY_CONTENT_CRL;
111 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
113 ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
114 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
116 contentType = CERT_QUERY_CONTENT_CTL;
120 if (pdwMsgAndCertEncodingType)
121 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
123 *pdwContentType = contentType;
125 *phCertStore = CertDuplicateStore(store);
127 CertCloseStore(store, 0);
128 if (blob == &fileBlob)
129 CryptMemFree(blob->pbData);
130 TRACE("returning %d\n", ret);
134 static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType,
135 const void *pvObject, DWORD dwExpectedContentTypeFlags,
136 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
137 HCERTSTORE *phCertStore, const void **ppvContext)
140 const CERT_BLOB *blob;
141 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
146 switch (dwObjectType)
148 case CERT_QUERY_OBJECT_FILE:
149 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
150 * just read the file directly
152 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
155 case CERT_QUERY_OBJECT_BLOB:
156 blob = (const CERT_BLOB *)pvObject;
160 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
166 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData,
167 CERT_STORE_ALL_CONTEXT_FLAG, &contextType);
170 DWORD contentType, certStoreOffset;
175 case CERT_STORE_CERTIFICATE_CONTEXT:
176 contextInterface = pCertInterface;
177 contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT;
178 certStoreOffset = offsetof(CERT_CONTEXT, hCertStore);
179 if (!(dwExpectedContentTypeFlags &
180 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT))
182 SetLastError(ERROR_INVALID_DATA);
187 case CERT_STORE_CRL_CONTEXT:
188 contextInterface = pCRLInterface;
189 contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL;
190 certStoreOffset = offsetof(CRL_CONTEXT, hCertStore);
191 if (!(dwExpectedContentTypeFlags &
192 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL))
194 SetLastError(ERROR_INVALID_DATA);
199 case CERT_STORE_CTL_CONTEXT:
200 contextInterface = pCTLInterface;
201 contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL;
202 certStoreOffset = offsetof(CTL_CONTEXT, hCertStore);
203 if (!(dwExpectedContentTypeFlags &
204 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))
206 SetLastError(ERROR_INVALID_DATA);
212 SetLastError(ERROR_INVALID_DATA);
216 if (pdwMsgAndCertEncodingType)
217 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
219 *pdwContentType = contentType;
221 *phCertStore = CertDuplicateStore(
222 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
224 *ppvContext = contextInterface->duplicate(context);
228 if (contextInterface && context)
229 contextInterface->free(context);
230 if (blob == &fileBlob)
231 CryptMemFree(blob->pbData);
232 TRACE("returning %d\n", ret);
236 static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType,
237 const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
238 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
240 LPCWSTR fileName = (LPCWSTR)pvObject;
244 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
246 FIXME("unimplemented for non-file type %d\n", dwObjectType);
247 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
250 TRACE("%s\n", debugstr_w(fileName));
251 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
252 OPEN_EXISTING, 0, NULL);
253 if (file != INVALID_HANDLE_VALUE)
255 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
256 CERT_STORE_CREATE_NEW_FLAG, NULL);
258 ret = CRYPT_ReadSerializedStoreFromFile(file, store);
261 if (pdwMsgAndCertEncodingType)
262 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
264 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
266 *phCertStore = CertDuplicateStore(store);
268 CertCloseStore(store, 0);
271 TRACE("returning %d\n", ret);
275 /* Used to decode non-embedded messages */
276 static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject,
277 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
278 DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
281 const CERT_BLOB *blob;
283 HCRYPTMSG msg = NULL;
284 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
286 switch (dwObjectType)
288 case CERT_QUERY_OBJECT_FILE:
289 /* This isn't an embedded PKCS7 message, so just read the file
292 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
295 case CERT_QUERY_OBJECT_BLOB:
296 blob = (const CERT_BLOB *)pvObject;
300 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
307 /* Try it first as a PKCS content info */
308 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
309 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
311 msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL);
314 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
317 DWORD type, len = sizeof(type);
319 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
322 if ((dwExpectedContentTypeFlags &
323 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
325 if (type != CMSG_SIGNED)
327 SetLastError(ERROR_INVALID_DATA);
330 else if (pdwContentType)
331 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
333 else if ((dwExpectedContentTypeFlags &
334 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
336 if (type != CMSG_DATA)
338 SetLastError(ERROR_INVALID_DATA);
341 else if (pdwContentType)
342 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
353 /* Failing that, try explicitly typed messages */
355 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
357 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL);
360 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
367 if (msg && pdwContentType)
368 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
371 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
373 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL);
376 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
383 if (msg && pdwContentType)
384 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
386 if (pdwMsgAndCertEncodingType)
387 *pdwMsgAndCertEncodingType = encodingType;
393 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0,
396 if (blob == &fileBlob)
397 CryptMemFree(blob->pbData);
398 TRACE("returning %d\n", ret);
402 static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType,
403 const void *pvObject, DWORD dwExpectedContentTypeFlags,
404 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
405 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
411 TRACE("%s\n", debugstr_w((LPCWSTR)pvObject));
413 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
415 FIXME("don't know what to do for type %d embedded signed messages\n",
417 SetLastError(E_INVALIDARG);
420 file = CreateFileW((LPCWSTR)pvObject, GENERIC_READ, FILE_SHARE_READ,
421 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
422 if (file != INVALID_HANDLE_VALUE)
424 ret = CryptSIPRetrieveSubjectGuid((LPCWSTR)pvObject, file, &subject);
427 SIP_DISPATCH_INFO sip;
429 memset(&sip, 0, sizeof(sip));
430 sip.cbSize = sizeof(sip);
431 ret = CryptSIPLoad(&subject, 0, &sip);
434 SIP_SUBJECTINFO subjectInfo;
438 memset(&subjectInfo, 0, sizeof(subjectInfo));
439 subjectInfo.cbSize = sizeof(subjectInfo);
440 subjectInfo.pgSubjectType = &subject;
441 subjectInfo.hFile = file;
442 subjectInfo.pwsFileName = (LPCWSTR)pvObject;
443 ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData,
447 blob.pbData = CryptMemAlloc(blob.cbData);
450 ret = sip.pfGet(&subjectInfo, &encodingType, 0,
451 &blob.cbData, blob.pbData);
454 ret = CRYPT_QueryMessageObject(
455 CERT_QUERY_OBJECT_BLOB, &blob,
456 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
457 pdwMsgAndCertEncodingType, NULL, phCertStore,
459 if (ret && pdwContentType)
461 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED;
463 CryptMemFree(blob.pbData);
467 SetLastError(ERROR_OUTOFMEMORY);
475 TRACE("returning %d\n", ret);
479 BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject,
480 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
481 DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
482 DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg,
483 const void **ppvContext)
485 static const DWORD unimplementedTypes =
486 CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX |
487 CERT_QUERY_CONTENT_FLAG_CERT_PAIR;
490 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
491 dwObjectType, pvObject, dwExpectedContentTypeFlags,
492 dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType,
493 pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext);
495 if (dwExpectedContentTypeFlags & unimplementedTypes)
496 WARN("unimplemented for types %08x\n",
497 dwExpectedContentTypeFlags & unimplementedTypes);
498 if (!(dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY))
500 FIXME("unimplemented for anything but binary\n");
501 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
505 *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
515 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) ||
516 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) ||
517 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
519 ret = CRYPT_QueryContextObject(dwObjectType, pvObject,
520 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
521 phCertStore, ppvContext);
524 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE))
526 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject,
527 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
530 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) ||
531 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) ||
532 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)))
534 ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject,
535 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
536 phCertStore, ppvContext);
539 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
540 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)))
542 ret = CRYPT_QueryMessageObject(dwObjectType, pvObject,
543 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
547 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED))
549 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject,
550 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
553 TRACE("returning %d\n", ret);
557 static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType,
558 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
559 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
566 bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR);
568 bytesNeeded = sizeof(WCHAR);
571 *pcbFormat = bytesNeeded;
574 else if (*pcbFormat < bytesNeeded)
576 *pcbFormat = bytesNeeded;
577 SetLastError(ERROR_MORE_DATA);
582 static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
583 static const WCHAR endFmt[] = { '%','0','2','x',0 };
585 LPWSTR ptr = pbFormat;
587 *pcbFormat = bytesNeeded;
590 for (i = 0; i < cbEncoded; i++)
592 if (i < cbEncoded - 1)
593 ptr += sprintfW(ptr, fmt, pbEncoded[i]);
595 ptr += sprintfW(ptr, endFmt, pbEncoded[i]);
605 #define MAX_STRING_RESOURCE_LEN 128
607 static const WCHAR commaSpace[] = { ',',' ',0 };
613 WCHAR str[MAX_STRING_RESOURCE_LEN];
616 static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map,
617 DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first)
619 DWORD bytesNeeded = sizeof(WCHAR);
621 BOOL ret = TRUE, localFirst = *first;
623 for (i = 0; i < mapEntries; i++)
624 if (bits & map[i].bit)
627 bytesNeeded += strlenW(commaSpace) * sizeof(WCHAR);
629 bytesNeeded += strlenW(map[i].str) * sizeof(WCHAR);
634 *pcbFormat = bytesNeeded;
636 else if (*pcbFormat < bytesNeeded)
639 *pcbFormat = bytesNeeded;
640 SetLastError(ERROR_MORE_DATA);
645 LPWSTR str = pbFormat;
648 *pcbFormat = bytesNeeded;
649 for (i = 0; i < mapEntries; i++)
650 if (bits & map[i].bit)
654 strcpyW(str, commaSpace);
655 str += strlenW(commaSpace);
658 strcpyW(str, map[i].str);
659 str += strlenW(map[i].str);
666 static struct BitToString keyUsageByte0Map[] = {
667 { CERT_DIGITAL_SIGNATURE_KEY_USAGE, IDS_DIGITAL_SIGNATURE, { 0 } },
668 { CERT_NON_REPUDIATION_KEY_USAGE, IDS_NON_REPUDIATION, { 0 } },
669 { CERT_KEY_ENCIPHERMENT_KEY_USAGE, IDS_KEY_ENCIPHERMENT, { 0 } },
670 { CERT_DATA_ENCIPHERMENT_KEY_USAGE, IDS_DATA_ENCIPHERMENT, { 0 } },
671 { CERT_KEY_AGREEMENT_KEY_USAGE, IDS_KEY_AGREEMENT, { 0 } },
672 { CERT_KEY_CERT_SIGN_KEY_USAGE, IDS_CERT_SIGN, { 0 } },
673 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE, IDS_OFFLINE_CRL_SIGN, { 0 } },
674 { CERT_CRL_SIGN_KEY_USAGE, IDS_CRL_SIGN, { 0 } },
675 { CERT_ENCIPHER_ONLY_KEY_USAGE, IDS_ENCIPHER_ONLY, { 0 } },
677 static struct BitToString keyUsageByte1Map[] = {
678 { CERT_DECIPHER_ONLY_KEY_USAGE, IDS_DECIPHER_ONLY, { 0 } },
681 static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType,
682 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
683 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
687 CRYPT_BIT_BLOB *bits;
692 SetLastError(E_INVALIDARG);
695 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_KEY_USAGE,
696 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
698 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
699 DWORD bytesNeeded = sizeof(WCHAR);
701 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
702 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
703 if (!bits->cbData || bits->cbData > 2)
705 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
707 *pcbFormat = bytesNeeded;
708 else if (*pcbFormat < bytesNeeded)
710 *pcbFormat = bytesNeeded;
711 SetLastError(ERROR_MORE_DATA);
716 LPWSTR str = pbFormat;
718 *pcbFormat = bytesNeeded;
719 strcpyW(str, infoNotAvailable);
724 static BOOL stringsLoaded = FALSE;
732 i < sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]);
734 LoadStringW(hInstance, keyUsageByte0Map[i].id,
735 keyUsageByte0Map[i].str, MAX_STRING_RESOURCE_LEN);
737 i < sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]);
739 LoadStringW(hInstance, keyUsageByte1Map[i].id,
740 keyUsageByte1Map[i].str, MAX_STRING_RESOURCE_LEN);
741 stringsLoaded = TRUE;
743 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
744 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
745 NULL, &bitStringLen, &first);
746 bytesNeeded += bitStringLen;
747 if (bits->cbData == 2)
749 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
750 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
751 NULL, &bitStringLen, &first);
752 bytesNeeded += bitStringLen;
754 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
755 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
756 bits->cbData, NULL, &size);
759 *pcbFormat = bytesNeeded;
760 else if (*pcbFormat < bytesNeeded)
762 *pcbFormat = bytesNeeded;
763 SetLastError(ERROR_MORE_DATA);
768 LPWSTR str = pbFormat;
770 bitStringLen = bytesNeeded;
772 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
773 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
774 str, &bitStringLen, &first);
775 str += bitStringLen / sizeof(WCHAR) - 1;
776 if (bits->cbData == 2)
778 bitStringLen = bytesNeeded;
779 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
780 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
781 str, &bitStringLen, &first);
782 str += bitStringLen / sizeof(WCHAR) - 1;
786 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
787 bits->cbData, str, &size);
788 str += size / sizeof(WCHAR) - 1;
798 static const WCHAR crlf[] = { '\r','\n',0 };
800 static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN];
801 static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN];
802 static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN];
803 static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN];
805 static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType,
806 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
807 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
811 CERT_BASIC_CONSTRAINTS2_INFO *info;
816 SetLastError(E_INVALIDARG);
819 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2,
820 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
822 static const WCHAR pathFmt[] = { '%','d',0 };
823 static BOOL stringsLoaded = FALSE;
824 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
825 WCHAR pathLength[MAX_STRING_RESOURCE_LEN];
826 LPCWSTR sep, subjectType;
829 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
832 sepLen = strlenW(crlf) * sizeof(WCHAR);
837 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
842 LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader,
843 sizeof(subjectTypeHeader) / sizeof(subjectTypeHeader[0]));
844 LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA,
845 sizeof(subjectTypeCA) / sizeof(subjectTypeCA[0]));
846 LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT,
848 sizeof(subjectTypeEndCert) / sizeof(subjectTypeEndCert[0]));
849 LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader,
850 sizeof(pathLengthHeader) / sizeof(pathLengthHeader[0]));
851 stringsLoaded = TRUE;
853 bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR);
855 subjectType = subjectTypeCA;
857 subjectType = subjectTypeEndCert;
858 bytesNeeded += strlenW(subjectType) * sizeof(WCHAR);
859 bytesNeeded += sepLen;
860 bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR);
861 if (info->fPathLenConstraint)
862 sprintfW(pathLength, pathFmt, info->dwPathLenConstraint);
864 LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength,
865 sizeof(pathLength) / sizeof(pathLength[0]));
866 bytesNeeded += strlenW(pathLength) * sizeof(WCHAR);
868 *pcbFormat = bytesNeeded;
869 else if (*pcbFormat < bytesNeeded)
871 *pcbFormat = bytesNeeded;
872 SetLastError(ERROR_MORE_DATA);
877 LPWSTR str = pbFormat;
879 *pcbFormat = bytesNeeded;
880 strcpyW(str, subjectTypeHeader);
881 str += strlenW(subjectTypeHeader);
882 strcpyW(str, subjectType);
883 str += strlenW(subjectType);
885 str += sepLen / sizeof(WCHAR);
886 strcpyW(str, pathLengthHeader);
887 str += strlenW(pathLengthHeader);
888 strcpyW(str, pathLength);
889 str += strlenW(pathLength);
896 static BOOL CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB *blob, int id,
897 LPWSTR str, DWORD *pcbStr)
899 WCHAR buf[MAX_STRING_RESOURCE_LEN];
903 LoadStringW(hInstance, id, buf, sizeof(buf) / sizeof(buf[0]));
904 CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
905 blob->pbData, blob->cbData, NULL, &bytesNeeded);
906 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
909 *pcbStr = bytesNeeded;
912 else if (*pcbStr < bytesNeeded)
914 *pcbStr = bytesNeeded;
915 SetLastError(ERROR_MORE_DATA);
920 *pcbStr = bytesNeeded;
923 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
924 ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
925 blob->pbData, blob->cbData, str, &bytesNeeded);
930 static BOOL CRYPT_FormatKeyId(CRYPT_DATA_BLOB *keyId, LPWSTR str,
933 return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr);
936 static BOOL CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB *serialNum, LPWSTR str,
939 return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER,
943 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
944 static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
946 static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel,
947 CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr)
950 WCHAR buf[MAX_STRING_RESOURCE_LEN];
951 WCHAR mask[MAX_STRING_RESOURCE_LEN];
954 DWORD bytesNeeded = sizeof(WCHAR);
955 DWORD strType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
957 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
958 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
959 switch (entry->dwAltNameChoice)
961 case CERT_ALT_NAME_RFC822_NAME:
962 LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf,
963 sizeof(buf) / sizeof(buf[0]));
964 bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR);
967 case CERT_ALT_NAME_DNS_NAME:
968 LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf,
969 sizeof(buf) / sizeof(buf[0]));
970 bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR);
973 case CERT_ALT_NAME_DIRECTORY_NAME:
975 DWORD directoryNameLen;
977 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
978 strType |= CERT_NAME_STR_CRLF_FLAG;
979 directoryNameLen = cert_name_to_str_with_indent(X509_ASN_ENCODING,
980 indentLevel + 1, &entry->u.DirectoryName, strType, NULL, 0);
981 LoadStringW(hInstance, IDS_ALT_NAME_DIRECTORY_NAME, buf,
982 sizeof(buf) / sizeof(buf[0]));
983 bytesNeeded += (directoryNameLen - 1) * sizeof(WCHAR);
984 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
985 bytesNeeded += strlenW(colonCrlf) * sizeof(WCHAR);
987 bytesNeeded += sizeof(WCHAR); /* '=' */
991 case CERT_ALT_NAME_URL:
992 LoadStringW(hInstance, IDS_ALT_NAME_URL, buf,
993 sizeof(buf) / sizeof(buf[0]));
994 bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR);
997 case CERT_ALT_NAME_IP_ADDRESS:
999 static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.',
1000 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1002 static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d',
1005 LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf,
1006 sizeof(buf) / sizeof(buf[0]));
1007 if (entry->u.IPAddress.cbData == 8)
1009 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1011 LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask,
1012 sizeof(mask) / sizeof(mask[0]));
1013 bytesNeeded += strlenW(mask) * sizeof(WCHAR);
1014 sprintfW(ipAddrBuf, ipAddrFmt,
1015 entry->u.IPAddress.pbData[0],
1016 entry->u.IPAddress.pbData[1],
1017 entry->u.IPAddress.pbData[2],
1018 entry->u.IPAddress.pbData[3]);
1019 bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR);
1020 /* indent again, for the mask line */
1021 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1022 sprintfW(maskBuf, ipAddrFmt,
1023 entry->u.IPAddress.pbData[4],
1024 entry->u.IPAddress.pbData[5],
1025 entry->u.IPAddress.pbData[6],
1026 entry->u.IPAddress.pbData[7]);
1027 bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR);
1028 bytesNeeded += strlenW(crlf) * sizeof(WCHAR);
1032 sprintfW(ipAddrBuf, ipAddrWithMaskFmt,
1033 entry->u.IPAddress.pbData[0],
1034 entry->u.IPAddress.pbData[1],
1035 entry->u.IPAddress.pbData[2],
1036 entry->u.IPAddress.pbData[3],
1037 entry->u.IPAddress.pbData[4],
1038 entry->u.IPAddress.pbData[5],
1039 entry->u.IPAddress.pbData[6],
1040 entry->u.IPAddress.pbData[7]);
1041 bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR);
1047 FIXME("unknown IP address format (%d bytes)\n",
1048 entry->u.IPAddress.cbData);
1054 FIXME("unimplemented for %d\n", entry->dwAltNameChoice);
1059 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1061 *pcbStr = bytesNeeded;
1062 else if (*pcbStr < bytesNeeded)
1064 *pcbStr = bytesNeeded;
1065 SetLastError(ERROR_MORE_DATA);
1072 *pcbStr = bytesNeeded;
1073 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1075 for (i = 0; i < indentLevel; i++)
1077 strcpyW(str, indent);
1078 str += strlenW(indent);
1082 str += strlenW(str);
1083 switch (entry->dwAltNameChoice)
1085 case CERT_ALT_NAME_RFC822_NAME:
1086 case CERT_ALT_NAME_DNS_NAME:
1087 case CERT_ALT_NAME_URL:
1088 strcpyW(str, entry->u.pwszURL);
1090 case CERT_ALT_NAME_DIRECTORY_NAME:
1091 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1093 strcpyW(str, colonCrlf);
1094 str += strlenW(colonCrlf);
1098 cert_name_to_str_with_indent(X509_ASN_ENCODING,
1099 indentLevel + 1, &entry->u.DirectoryName, strType, str,
1100 bytesNeeded / sizeof(WCHAR));
1102 case CERT_ALT_NAME_IP_ADDRESS:
1103 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1105 strcpyW(str, ipAddrBuf);
1106 str += strlenW(ipAddrBuf);
1108 str += strlenW(crlf);
1109 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1111 for (i = 0; i < indentLevel; i++)
1113 strcpyW(str, indent);
1114 str += strlenW(indent);
1118 str += strlenW(mask);
1119 strcpyW(str, maskBuf);
1122 strcpyW(str, ipAddrBuf);
1130 static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel,
1131 CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr)
1133 DWORD i, size, bytesNeeded = 0;
1138 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1141 sepLen = strlenW(crlf) * sizeof(WCHAR);
1146 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1149 for (i = 0; ret && i < name->cAltEntry; i++)
1151 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1152 &name->rgAltEntry[i], NULL, &size);
1155 bytesNeeded += size - sizeof(WCHAR);
1156 if (i < name->cAltEntry - 1)
1157 bytesNeeded += sepLen;
1162 bytesNeeded += sizeof(WCHAR);
1164 *pcbStr = bytesNeeded;
1165 else if (*pcbStr < bytesNeeded)
1167 *pcbStr = bytesNeeded;
1168 SetLastError(ERROR_MORE_DATA);
1173 *pcbStr = bytesNeeded;
1174 for (i = 0; ret && i < name->cAltEntry; i++)
1176 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1177 &name->rgAltEntry[i], str, &size);
1180 str += size / sizeof(WCHAR) - 1;
1181 if (i < name->cAltEntry - 1)
1184 str += sepLen / sizeof(WCHAR);
1193 static const WCHAR colonSep[] = { ':',' ',0 };
1195 static BOOL WINAPI CRYPT_FormatAltName(DWORD dwCertEncodingType,
1196 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1197 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1201 CERT_ALT_NAME_INFO *info;
1204 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ALTERNATE_NAME,
1205 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1207 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, info, pbFormat, pcbFormat);
1213 static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType,
1214 CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr)
1216 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1217 DWORD bytesNeeded, sepLen;
1221 LoadStringW(hInstance, IDS_CERT_ISSUER, buf, sizeof(buf) / sizeof(buf[0]));
1222 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, NULL,
1224 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1225 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1228 sepLen = strlenW(colonCrlf) * sizeof(WCHAR);
1233 sepLen = strlenW(colonSep) * sizeof(WCHAR);
1235 bytesNeeded += sepLen;
1239 *pcbStr = bytesNeeded;
1240 else if (*pcbStr < bytesNeeded)
1242 *pcbStr = bytesNeeded;
1243 SetLastError(ERROR_MORE_DATA);
1248 *pcbStr = bytesNeeded;
1250 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
1251 str += strlenW(str);
1253 str += sepLen / sizeof(WCHAR);
1254 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, str,
1261 static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType,
1262 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1263 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1266 CERT_AUTHORITY_KEY_ID2_INFO *info;
1272 SetLastError(E_INVALIDARG);
1275 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2,
1276 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1278 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1281 BOOL needSeparator = FALSE;
1283 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1286 sepLen = strlenW(crlf) * sizeof(WCHAR);
1291 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1294 if (info->KeyId.cbData)
1296 needSeparator = TRUE;
1297 ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size);
1300 /* don't include NULL-terminator more than once */
1301 bytesNeeded += size - sizeof(WCHAR);
1304 if (info->AuthorityCertIssuer.cAltEntry)
1307 bytesNeeded += sepLen;
1308 needSeparator = TRUE;
1309 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1310 &info->AuthorityCertIssuer, NULL, &size);
1313 /* don't include NULL-terminator more than once */
1314 bytesNeeded += size - sizeof(WCHAR);
1317 if (info->AuthorityCertSerialNumber.cbData)
1320 bytesNeeded += sepLen;
1321 ret = CRYPT_FormatCertSerialNumber(
1322 &info->AuthorityCertSerialNumber, NULL, &size);
1325 /* don't include NULL-terminator more than once */
1326 bytesNeeded += size - sizeof(WCHAR);
1332 *pcbFormat = bytesNeeded;
1333 else if (*pcbFormat < bytesNeeded)
1335 *pcbFormat = bytesNeeded;
1336 SetLastError(ERROR_MORE_DATA);
1341 LPWSTR str = pbFormat;
1343 *pcbFormat = bytesNeeded;
1344 needSeparator = FALSE;
1345 if (info->KeyId.cbData)
1347 needSeparator = TRUE;
1348 /* Overestimate size available, it's already been checked
1352 ret = CRYPT_FormatKeyId(&info->KeyId, str, &size);
1354 str += size / sizeof(WCHAR) - 1;
1356 if (info->AuthorityCertIssuer.cAltEntry)
1361 str += sepLen / sizeof(WCHAR);
1363 needSeparator = TRUE;
1364 /* Overestimate size available, it's already been checked
1368 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1369 &info->AuthorityCertIssuer, str, &size);
1371 str += size / sizeof(WCHAR) - 1;
1373 if (info->AuthorityCertSerialNumber.cbData)
1378 str += sepLen / sizeof(WCHAR);
1380 /* Overestimate size available, it's already been checked
1384 ret = CRYPT_FormatCertSerialNumber(
1385 &info->AuthorityCertSerialNumber, str, &size);
1394 static WCHAR aia[MAX_STRING_RESOURCE_LEN];
1395 static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN];
1396 static WCHAR ocsp[MAX_STRING_RESOURCE_LEN];
1397 static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN];
1398 static WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1399 static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN];
1401 static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType,
1402 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1403 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1406 CERT_AUTHORITY_INFO_ACCESS *info;
1412 SetLastError(E_INVALIDARG);
1415 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
1416 X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG,
1417 NULL, &info, &size)))
1419 DWORD bytesNeeded = sizeof(WCHAR);
1421 if (!info->cAccDescr)
1423 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1425 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1426 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1427 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1429 *pcbFormat = bytesNeeded;
1430 else if (*pcbFormat < bytesNeeded)
1432 *pcbFormat = bytesNeeded;
1433 SetLastError(ERROR_MORE_DATA);
1438 *pcbFormat = bytesNeeded;
1439 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1444 static const WCHAR numFmt[] = { '%','d',0 };
1445 static const WCHAR equal[] = { '=',0 };
1446 static BOOL stringsLoaded = FALSE;
1448 LPCWSTR headingSep, accessMethodSep, locationSep;
1449 WCHAR accessDescrNum[11];
1453 LoadStringW(hInstance, IDS_AIA, aia,
1454 sizeof(aia) / sizeof(aia[0]));
1455 LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod,
1456 sizeof(accessMethod) / sizeof(accessMethod[0]));
1457 LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp,
1458 sizeof(ocsp) / sizeof(ocsp[0]));
1459 LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers,
1460 sizeof(caIssuers) / sizeof(caIssuers[0]));
1461 LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown,
1462 sizeof(unknown) / sizeof(unknown[0]));
1463 LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation,
1464 sizeof(accessLocation) / sizeof(accessLocation[0]));
1465 stringsLoaded = TRUE;
1467 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1470 accessMethodSep = crlf;
1471 locationSep = colonCrlf;
1475 headingSep = colonSep;
1476 accessMethodSep = commaSpace;
1477 locationSep = equal;
1480 for (i = 0; ret && i < info->cAccDescr; i++)
1483 bytesNeeded += sizeof(WCHAR); /* left bracket */
1484 sprintfW(accessDescrNum, numFmt, i + 1);
1485 bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR);
1486 bytesNeeded += sizeof(WCHAR); /* right bracket */
1487 bytesNeeded += strlenW(aia) * sizeof(WCHAR);
1488 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1490 bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR);
1491 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1492 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1493 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1495 bytesNeeded += strlenW(ocsp) * sizeof(WCHAR);
1496 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1497 szOID_PKIX_CA_ISSUERS))
1498 bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers);
1500 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1501 bytesNeeded += sizeof(WCHAR); /* space */
1502 bytesNeeded += sizeof(WCHAR); /* left paren */
1503 bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod)
1505 bytesNeeded += sizeof(WCHAR); /* right paren */
1506 /* Delimiter between access method and location */
1507 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1508 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1509 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1510 bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR);
1511 bytesNeeded += strlenW(locationSep) * sizeof(WCHAR);
1512 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1513 &info->rgAccDescr[i].AccessLocation, NULL, &size);
1515 bytesNeeded += size - sizeof(WCHAR);
1516 /* Need extra delimiter between access method entries */
1517 if (i < info->cAccDescr - 1)
1518 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1523 *pcbFormat = bytesNeeded;
1524 else if (*pcbFormat < bytesNeeded)
1526 *pcbFormat = bytesNeeded;
1527 SetLastError(ERROR_MORE_DATA);
1532 LPWSTR str = pbFormat;
1533 DWORD altNameEntrySize;
1535 *pcbFormat = bytesNeeded;
1536 for (i = 0; ret && i < info->cAccDescr; i++)
1541 sprintfW(accessDescrNum, numFmt, i + 1);
1542 strcpyW(str, accessDescrNum);
1543 str += strlenW(accessDescrNum);
1546 str += strlenW(aia);
1547 strcpyW(str, headingSep);
1548 str += strlenW(headingSep);
1549 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1551 strcpyW(str, indent);
1552 str += strlenW(indent);
1554 strcpyW(str, accessMethod);
1555 str += strlenW(accessMethod);
1556 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1560 str += strlenW(ocsp);
1562 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1563 szOID_PKIX_CA_ISSUERS))
1565 strcpyW(str, caIssuers);
1566 str += strlenW(caIssuers);
1570 strcpyW(str, unknown);
1571 str += strlenW(unknown);
1575 for (oidPtr = info->rgAccDescr[i].pszAccessMethod;
1576 *oidPtr; oidPtr++, str++)
1579 strcpyW(str, accessMethodSep);
1580 str += strlenW(accessMethodSep);
1581 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1583 strcpyW(str, indent);
1584 str += strlenW(indent);
1586 strcpyW(str, accessLocation);
1587 str += strlenW(accessLocation);
1588 strcpyW(str, locationSep);
1589 str += strlenW(locationSep);
1590 /* This overestimates the size available, but that
1591 * won't matter since we checked earlier whether enough
1592 * space for the entire string was available.
1594 altNameEntrySize = bytesNeeded;
1595 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1596 &info->rgAccDescr[i].AccessLocation, str,
1599 str += altNameEntrySize / sizeof(WCHAR) - 1;
1600 if (i < info->cAccDescr - 1)
1602 strcpyW(str, accessMethodSep);
1603 str += strlenW(accessMethodSep);
1614 static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN];
1615 static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN];
1616 static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN];
1617 static WCHAR superseded[MAX_STRING_RESOURCE_LEN];
1618 static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN];
1619 static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN];
1621 struct reason_map_entry
1627 static struct reason_map_entry reason_map[] = {
1628 { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE },
1629 { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE },
1630 { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged,
1631 IDS_REASON_AFFILIATION_CHANGED },
1632 { CRL_REASON_SUPERSEDED_FLAG, superseded, IDS_REASON_SUPERSEDED },
1633 { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased,
1634 IDS_REASON_CESSATION_OF_OPERATION },
1635 { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold,
1636 IDS_REASON_CERTIFICATE_HOLD },
1639 static BOOL CRYPT_FormatReason(DWORD dwFormatStrType,
1640 const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr)
1642 static const WCHAR sep[] = { ',',' ',0 };
1643 static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 };
1644 static BOOL stringsLoaded = FALSE;
1645 int i, numReasons = 0;
1647 DWORD bytesNeeded = sizeof(WCHAR);
1652 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1653 LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason,
1654 MAX_STRING_RESOURCE_LEN);
1655 stringsLoaded = TRUE;
1657 /* No need to check reasonFlags->cbData, we already know it's positive.
1658 * Ignore any other bytes, as they're for undefined bits.
1660 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1662 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1664 bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR);
1666 bytesNeeded += strlenW(sep) * sizeof(WCHAR);
1669 sprintfW(bits, bitsFmt, reasonFlags->pbData[0]);
1670 bytesNeeded += strlenW(bits);
1672 *pcbStr = bytesNeeded;
1673 else if (*pcbStr < bytesNeeded)
1675 *pcbStr = bytesNeeded;
1676 SetLastError(ERROR_MORE_DATA);
1681 *pcbStr = bytesNeeded;
1682 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1684 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1686 strcpyW(str, reason_map[i].reason);
1687 str += strlenW(reason_map[i].reason);
1688 if (i < sizeof(reason_map) / sizeof(reason_map[0]) - 1 &&
1692 str += strlenW(sep);
1701 static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN];
1702 static WCHAR distPointName[MAX_STRING_RESOURCE_LEN];
1703 static WCHAR fullName[MAX_STRING_RESOURCE_LEN];
1704 static WCHAR rdnName[MAX_STRING_RESOURCE_LEN];
1705 static WCHAR reason[MAX_STRING_RESOURCE_LEN];
1706 static WCHAR issuer[MAX_STRING_RESOURCE_LEN];
1708 static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType,
1709 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1710 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1713 CRL_DIST_POINTS_INFO *info;
1719 SetLastError(E_INVALIDARG);
1722 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS,
1723 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1725 static const WCHAR numFmt[] = { '%','d',0 };
1726 static const WCHAR commaSep[] = { ',',' ',0 };
1727 static const WCHAR colon[] = { ':',0 };
1728 static BOOL stringsLoaded = FALSE;
1729 DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */
1730 BOOL haveAnEntry = FALSE;
1731 LPCWSTR headingSep, distPointSep, nameSep;
1732 WCHAR distPointNum[11];
1737 LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint,
1738 sizeof(crlDistPoint) / sizeof(crlDistPoint[0]));
1739 LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName,
1740 sizeof(distPointName) / sizeof(distPointName[0]));
1741 LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName,
1742 sizeof(fullName) / sizeof(fullName[0]));
1743 LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName,
1744 sizeof(rdnName) / sizeof(rdnName[0]));
1745 LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason,
1746 sizeof(reason) / sizeof(reason[0]));
1747 LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer,
1748 sizeof(issuer) / sizeof(issuer[0]));
1749 stringsLoaded = TRUE;
1751 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1754 distPointSep = crlf;
1755 nameSep = colonCrlf;
1759 headingSep = colonSep;
1760 distPointSep = commaSep;
1764 for (i = 0; ret && i < info->cDistPoint; i++)
1766 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1768 if (distPoint->DistPointName.dwDistPointNameChoice !=
1769 CRL_DIST_POINT_NO_NAME)
1771 bytesNeeded += strlenW(distPointName) * sizeof(WCHAR);
1772 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1773 if (distPoint->DistPointName.dwDistPointNameChoice ==
1774 CRL_DIST_POINT_FULL_NAME)
1775 bytesNeeded += strlenW(fullName) * sizeof(WCHAR);
1777 bytesNeeded += strlenW(rdnName) * sizeof(WCHAR);
1778 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1779 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1780 bytesNeeded += 2 * strlenW(indent) * sizeof(WCHAR);
1781 /* The indent level (3) is higher than when used as the issuer,
1782 * because the name is subordinate to the name type (full vs.
1785 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1786 &distPoint->DistPointName.u.FullName, NULL, &size);
1788 bytesNeeded += size - sizeof(WCHAR);
1791 else if (distPoint->ReasonFlags.cbData)
1793 bytesNeeded += strlenW(reason) * sizeof(WCHAR);
1794 ret = CRYPT_FormatReason(dwFormatStrType,
1795 &distPoint->ReasonFlags, NULL, &size);
1797 bytesNeeded += size - sizeof(WCHAR);
1800 else if (distPoint->CRLIssuer.cAltEntry)
1802 bytesNeeded += strlenW(issuer) * sizeof(WCHAR);
1803 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1804 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1805 &distPoint->CRLIssuer, NULL, &size);
1807 bytesNeeded += size - sizeof(WCHAR);
1812 bytesNeeded += sizeof(WCHAR); /* left bracket */
1813 sprintfW(distPointNum, numFmt, i + 1);
1814 bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR);
1815 bytesNeeded += sizeof(WCHAR); /* right bracket */
1816 bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR);
1817 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1818 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1819 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1824 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1826 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1827 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1828 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1830 *pcbFormat = bytesNeeded;
1831 else if (*pcbFormat < bytesNeeded)
1833 *pcbFormat = bytesNeeded;
1834 SetLastError(ERROR_MORE_DATA);
1839 *pcbFormat = bytesNeeded;
1840 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1846 *pcbFormat = bytesNeeded;
1847 else if (*pcbFormat < bytesNeeded)
1849 *pcbFormat = bytesNeeded;
1850 SetLastError(ERROR_MORE_DATA);
1855 LPWSTR str = pbFormat;
1857 *pcbFormat = bytesNeeded;
1858 for (i = 0; ret && i < info->cDistPoint; i++)
1860 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1863 sprintfW(distPointNum, numFmt, i + 1);
1864 strcpyW(str, distPointNum);
1865 str += strlenW(distPointNum);
1867 strcpyW(str, crlDistPoint);
1868 str += strlenW(crlDistPoint);
1869 strcpyW(str, headingSep);
1870 str += strlenW(headingSep);
1871 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1873 strcpyW(str, indent);
1874 str += strlenW(indent);
1876 if (distPoint->DistPointName.dwDistPointNameChoice !=
1877 CRL_DIST_POINT_NO_NAME)
1879 DWORD altNameSize = bytesNeeded;
1881 strcpyW(str, distPointName);
1882 str += strlenW(distPointName);
1883 strcpyW(str, nameSep);
1884 str += strlenW(nameSep);
1885 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1887 strcpyW(str, indent);
1888 str += strlenW(indent);
1889 strcpyW(str, indent);
1890 str += strlenW(indent);
1892 if (distPoint->DistPointName.dwDistPointNameChoice ==
1893 CRL_DIST_POINT_FULL_NAME)
1895 strcpyW(str, fullName);
1896 str += strlenW(fullName);
1900 strcpyW(str, rdnName);
1901 str += strlenW(rdnName);
1903 strcpyW(str, nameSep);
1904 str += strlenW(nameSep);
1905 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1906 &distPoint->DistPointName.u.FullName, str,
1909 str += altNameSize / sizeof(WCHAR) - 1;
1911 else if (distPoint->ReasonFlags.cbData)
1913 DWORD reasonSize = bytesNeeded;
1915 strcpyW(str, reason);
1916 str += strlenW(reason);
1917 ret = CRYPT_FormatReason(dwFormatStrType,
1918 &distPoint->ReasonFlags, str, &reasonSize);
1920 str += reasonSize / sizeof(WCHAR) - 1;
1922 else if (distPoint->CRLIssuer.cAltEntry)
1924 DWORD crlIssuerSize = bytesNeeded;
1926 strcpyW(str, issuer);
1927 str += strlenW(issuer);
1928 strcpyW(str, nameSep);
1929 str += strlenW(nameSep);
1930 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1931 &distPoint->CRLIssuer, str,
1934 str += crlIssuerSize / sizeof(WCHAR) - 1;
1944 static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType,
1945 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1946 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1949 CERT_ENHKEY_USAGE *usage;
1955 SetLastError(E_INVALIDARG);
1958 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE,
1959 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size)))
1961 WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1963 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1967 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1970 sepLen = strlenW(crlf) * sizeof(WCHAR);
1975 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1978 LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown,
1979 sizeof(unknown) / sizeof(unknown[0]));
1980 for (i = 0; i < usage->cUsageIdentifier; i++)
1982 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
1983 usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
1986 bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR);
1988 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1989 bytesNeeded += sizeof(WCHAR); /* space */
1990 bytesNeeded += sizeof(WCHAR); /* left paren */
1991 bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) *
1993 bytesNeeded += sizeof(WCHAR); /* right paren */
1994 if (i < usage->cUsageIdentifier - 1)
1995 bytesNeeded += sepLen;
1998 *pcbFormat = bytesNeeded;
1999 else if (*pcbFormat < bytesNeeded)
2001 *pcbFormat = bytesNeeded;
2002 SetLastError(ERROR_MORE_DATA);
2007 LPWSTR str = pbFormat;
2009 *pcbFormat = bytesNeeded;
2010 for (i = 0; i < usage->cUsageIdentifier; i++)
2012 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2013 usage->rgpszUsageIdentifier[i],
2014 CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2019 strcpyW(str, info->pwszName);
2020 str += strlenW(info->pwszName);
2024 strcpyW(str, unknown);
2025 str += strlenW(unknown);
2029 for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++)
2033 if (i < usage->cUsageIdentifier - 1)
2036 str += sepLen / sizeof(WCHAR);
2045 static struct BitToString netscapeCertTypeMap[] = {
2046 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_CLIENT, { 0 } },
2047 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_SERVER, { 0 } },
2048 { NETSCAPE_SMIME_CERT_TYPE, IDS_NETSCAPE_SMIME, { 0 } },
2049 { NETSCAPE_SIGN_CERT_TYPE, IDS_NETSCAPE_SIGN, { 0 } },
2050 { NETSCAPE_SSL_CA_CERT_TYPE, IDS_NETSCAPE_SSL_CA, { 0 } },
2051 { NETSCAPE_SMIME_CA_CERT_TYPE, IDS_NETSCAPE_SMIME_CA, { 0 } },
2052 { NETSCAPE_SIGN_CA_CERT_TYPE, IDS_NETSCAPE_SIGN_CA, { 0 } },
2055 static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType,
2056 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2057 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2061 CRYPT_BIT_BLOB *bits;
2066 SetLastError(E_INVALIDARG);
2069 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS,
2070 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
2072 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
2073 DWORD bytesNeeded = sizeof(WCHAR);
2075 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
2076 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
2077 if (!bits->cbData || bits->cbData > 1)
2079 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
2081 *pcbFormat = bytesNeeded;
2082 else if (*pcbFormat < bytesNeeded)
2084 *pcbFormat = bytesNeeded;
2085 SetLastError(ERROR_MORE_DATA);
2090 LPWSTR str = pbFormat;
2092 *pcbFormat = bytesNeeded;
2093 strcpyW(str, infoNotAvailable);
2098 static BOOL stringsLoaded = FALSE;
2105 for (i = 0; i < sizeof(netscapeCertTypeMap) /
2106 sizeof(netscapeCertTypeMap[0]); i++)
2107 LoadStringW(hInstance, netscapeCertTypeMap[i].id,
2108 netscapeCertTypeMap[i].str, MAX_STRING_RESOURCE_LEN);
2109 stringsLoaded = TRUE;
2111 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2112 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2113 NULL, &bitStringLen, &first);
2114 bytesNeeded += bitStringLen;
2115 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
2116 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2117 bits->cbData, NULL, &size);
2118 bytesNeeded += size;
2120 *pcbFormat = bytesNeeded;
2121 else if (*pcbFormat < bytesNeeded)
2123 *pcbFormat = bytesNeeded;
2124 SetLastError(ERROR_MORE_DATA);
2129 LPWSTR str = pbFormat;
2131 bitStringLen = bytesNeeded;
2133 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2134 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2135 str, &bitStringLen, &first);
2136 str += bitStringLen / sizeof(WCHAR) - 1;
2139 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2140 bits->cbData, str, &size);
2141 str += size / sizeof(WCHAR) - 1;
2151 static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN];
2152 static WCHAR available[MAX_STRING_RESOURCE_LEN];
2153 static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN];
2154 static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN];
2155 static WCHAR yes[MAX_STRING_RESOURCE_LEN];
2156 static WCHAR no[MAX_STRING_RESOURCE_LEN];
2158 static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType,
2159 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2160 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2163 SPC_FINANCIAL_CRITERIA criteria;
2164 DWORD size = sizeof(criteria);
2169 SetLastError(E_INVALIDARG);
2172 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
2173 SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria,
2176 static BOOL stringsLoaded = FALSE;
2177 DWORD bytesNeeded = sizeof(WCHAR);
2183 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria,
2184 sizeof(financialCriteria) / sizeof(financialCriteria[0]));
2185 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available,
2186 sizeof(available) / sizeof(available[0]));
2187 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE,
2188 notAvailable, sizeof(notAvailable) / sizeof(notAvailable[0]));
2189 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA,
2190 meetsCriteria, sizeof(meetsCriteria) / sizeof(meetsCriteria[0]));
2191 LoadStringW(hInstance, IDS_YES, yes, sizeof(yes) / sizeof(yes[0]));
2192 LoadStringW(hInstance, IDS_NO, no, sizeof(no) / sizeof(no[0]));
2193 stringsLoaded = TRUE;
2195 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2198 sepLen = strlenW(crlf) * sizeof(WCHAR);
2203 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2205 bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR);
2206 if (criteria.fFinancialInfoAvailable)
2208 bytesNeeded += strlenW(available) * sizeof(WCHAR);
2209 bytesNeeded += sepLen;
2210 bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR);
2211 if (criteria.fMeetsCriteria)
2212 bytesNeeded += strlenW(yes) * sizeof(WCHAR);
2214 bytesNeeded += strlenW(no) * sizeof(WCHAR);
2217 bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR);
2219 *pcbFormat = bytesNeeded;
2220 else if (*pcbFormat < bytesNeeded)
2222 *pcbFormat = bytesNeeded;
2223 SetLastError(ERROR_MORE_DATA);
2228 LPWSTR str = pbFormat;
2230 *pcbFormat = bytesNeeded;
2231 strcpyW(str, financialCriteria);
2232 str += strlenW(financialCriteria);
2233 if (criteria.fFinancialInfoAvailable)
2235 strcpyW(str, available);
2236 str += strlenW(available);
2238 str += sepLen / sizeof(WCHAR);
2239 strcpyW(str, meetsCriteria);
2240 str += strlenW(meetsCriteria);
2241 if (criteria.fMeetsCriteria)
2248 strcpyW(str, notAvailable);
2249 str += strlenW(notAvailable);
2256 static BOOL WINAPI CRYPT_FormatUnicodeString(DWORD dwCertEncodingType,
2257 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2258 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2261 CERT_NAME_VALUE *value;
2267 SetLastError(E_INVALIDARG);
2270 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING,
2271 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &value, &size)))
2274 *pcbFormat = value->Value.cbData;
2275 else if (*pcbFormat < value->Value.cbData)
2277 *pcbFormat = value->Value.cbData;
2278 SetLastError(ERROR_MORE_DATA);
2283 LPWSTR str = pbFormat;
2285 *pcbFormat = value->Value.cbData;
2286 strcpyW(str, (LPWSTR)value->Value.pbData);
2292 typedef BOOL (WINAPI *CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *,
2293 LPCSTR, const BYTE *, DWORD, void *, DWORD *);
2295 static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType,
2296 DWORD formatStrType, LPCSTR lpszStructType)
2298 CryptFormatObjectFunc format = NULL;
2300 if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
2302 SetLastError(ERROR_FILE_NOT_FOUND);
2305 if (!HIWORD(lpszStructType))
2307 switch (LOWORD(lpszStructType))
2309 case LOWORD(X509_KEY_USAGE):
2310 format = CRYPT_FormatKeyUsage;
2312 case LOWORD(X509_ALTERNATE_NAME):
2313 format = CRYPT_FormatAltName;
2315 case LOWORD(X509_BASIC_CONSTRAINTS2):
2316 format = CRYPT_FormatBasicConstraints2;
2318 case LOWORD(X509_AUTHORITY_KEY_ID2):
2319 format = CRYPT_FormatAuthorityKeyId2;
2321 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
2322 format = CRYPT_FormatAuthorityInfoAccess;
2324 case LOWORD(X509_CRL_DIST_POINTS):
2325 format = CRYPT_FormatCRLDistPoints;
2327 case LOWORD(X509_ENHANCED_KEY_USAGE):
2328 format = CRYPT_FormatEnhancedKeyUsage;
2330 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT):
2331 format = CRYPT_FormatSpcFinancialCriteria;
2335 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2336 format = CRYPT_FormatAltName;
2337 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2338 format = CRYPT_FormatAltName;
2339 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2340 format = CRYPT_FormatKeyUsage;
2341 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2342 format = CRYPT_FormatAltName;
2343 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2344 format = CRYPT_FormatAltName;
2345 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2346 format = CRYPT_FormatBasicConstraints2;
2347 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
2348 format = CRYPT_FormatAuthorityInfoAccess;
2349 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
2350 format = CRYPT_FormatAuthorityKeyId2;
2351 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
2352 format = CRYPT_FormatCRLDistPoints;
2353 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
2354 format = CRYPT_FormatEnhancedKeyUsage;
2355 else if (!strcmp(lpszStructType, szOID_NETSCAPE_CERT_TYPE))
2356 format = CRYPT_FormatNetscapeCertType;
2357 else if (!strcmp(lpszStructType, szOID_NETSCAPE_BASE_URL) ||
2358 !strcmp(lpszStructType, szOID_NETSCAPE_REVOCATION_URL) ||
2359 !strcmp(lpszStructType, szOID_NETSCAPE_CA_REVOCATION_URL) ||
2360 !strcmp(lpszStructType, szOID_NETSCAPE_CERT_RENEWAL_URL) ||
2361 !strcmp(lpszStructType, szOID_NETSCAPE_CA_POLICY_URL) ||
2362 !strcmp(lpszStructType, szOID_NETSCAPE_SSL_SERVER_NAME) ||
2363 !strcmp(lpszStructType, szOID_NETSCAPE_COMMENT))
2364 format = CRYPT_FormatUnicodeString;
2365 else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID))
2366 format = CRYPT_FormatSpcFinancialCriteria;
2370 BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType,
2371 DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
2372 const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat)
2374 CryptFormatObjectFunc format = NULL;
2375 HCRYPTOIDFUNCADDR hFunc = NULL;
2378 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType,
2379 dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType),
2380 pbEncoded, cbEncoded, pbFormat, pcbFormat);
2382 if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType,
2383 dwFormatStrType, lpszStructType)))
2385 static HCRYPTOIDFUNCSET set = NULL;
2388 set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0);
2389 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2390 (void **)&format, &hFunc);
2392 if (!format && (dwCertEncodingType & CERT_ENCODING_TYPE_MASK) ==
2393 X509_ASN_ENCODING && !(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX))
2394 format = CRYPT_FormatHexString;
2396 ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType,
2397 pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat,
2400 CryptFreeOIDFunctionAddress(hFunc, 0);