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 typedef BOOL (WINAPI
*CryptFormatObjectFunc
)(DWORD
, DWORD
, DWORD
, void *,
2257 LPCSTR
, const BYTE
*, DWORD
, void *, DWORD
*);
2259 static CryptFormatObjectFunc
CRYPT_GetBuiltinFormatFunction(DWORD encodingType
,
2260 DWORD formatStrType
, LPCSTR lpszStructType
)
2262 CryptFormatObjectFunc format
= NULL
;
2264 if ((encodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
)
2266 SetLastError(ERROR_FILE_NOT_FOUND
);
2269 if (!HIWORD(lpszStructType
))
2271 switch (LOWORD(lpszStructType
))
2273 case LOWORD(X509_KEY_USAGE
):
2274 format
= CRYPT_FormatKeyUsage
;
2276 case LOWORD(X509_ALTERNATE_NAME
):
2277 format
= CRYPT_FormatAltName
;
2279 case LOWORD(X509_BASIC_CONSTRAINTS2
):
2280 format
= CRYPT_FormatBasicConstraints2
;
2282 case LOWORD(X509_AUTHORITY_KEY_ID2
):
2283 format
= CRYPT_FormatAuthorityKeyId2
;
2285 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
2286 format
= CRYPT_FormatAuthorityInfoAccess
;
2288 case LOWORD(X509_CRL_DIST_POINTS
):
2289 format
= CRYPT_FormatCRLDistPoints
;
2291 case LOWORD(X509_ENHANCED_KEY_USAGE
):
2292 format
= CRYPT_FormatEnhancedKeyUsage
;
2294 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT
):
2295 format
= CRYPT_FormatSpcFinancialCriteria
;
2299 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2300 format
= CRYPT_FormatAltName
;
2301 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2302 format
= CRYPT_FormatAltName
;
2303 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2304 format
= CRYPT_FormatKeyUsage
;
2305 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2306 format
= CRYPT_FormatAltName
;
2307 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2308 format
= CRYPT_FormatAltName
;
2309 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2310 format
= CRYPT_FormatBasicConstraints2
;
2311 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
2312 format
= CRYPT_FormatAuthorityInfoAccess
;
2313 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
2314 format
= CRYPT_FormatAuthorityKeyId2
;
2315 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2316 format
= CRYPT_FormatCRLDistPoints
;
2317 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2318 format
= CRYPT_FormatEnhancedKeyUsage
;
2319 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_CERT_TYPE
))
2320 format
= CRYPT_FormatNetscapeCertType
;
2321 else if (!strcmp(lpszStructType
, SPC_FINANCIAL_CRITERIA_OBJID
))
2322 format
= CRYPT_FormatSpcFinancialCriteria
;
2326 BOOL WINAPI
CryptFormatObject(DWORD dwCertEncodingType
, DWORD dwFormatType
,
2327 DWORD dwFormatStrType
, void *pFormatStruct
, LPCSTR lpszStructType
,
2328 const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
, DWORD
*pcbFormat
)
2330 CryptFormatObjectFunc format
= NULL
;
2331 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2334 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType
,
2335 dwFormatType
, dwFormatStrType
, pFormatStruct
, debugstr_a(lpszStructType
),
2336 pbEncoded
, cbEncoded
, pbFormat
, pcbFormat
);
2338 if (!(format
= CRYPT_GetBuiltinFormatFunction(dwCertEncodingType
,
2339 dwFormatStrType
, lpszStructType
)))
2341 static HCRYPTOIDFUNCSET set
= NULL
;
2344 set
= CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC
, 0);
2345 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2346 (void **)&format
, &hFunc
);
2348 if (!format
&& (dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) ==
2349 X509_ASN_ENCODING
&& !(dwFormatStrType
& CRYPT_FORMAT_STR_NO_HEX
))
2350 format
= CRYPT_FormatHexString
;
2352 ret
= format(dwCertEncodingType
, dwFormatType
, dwFormatStrType
,
2353 pFormatStruct
, lpszStructType
, pbEncoded
, cbEncoded
, pbFormat
,
2356 CryptFreeOIDFunctionAddress(hFunc
, 0);