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_QueryContextBlob(const CERT_BLOB
*blob
,
65 DWORD dwExpectedContentTypeFlags
, HCERTSTORE store
,
66 DWORD
*contentType
, const void **ppvContext
)
70 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
)
72 ret
= pCertInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
73 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
74 if (ret
&& contentType
)
75 *contentType
= CERT_QUERY_CONTENT_CERT
;
77 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
))
79 ret
= pCRLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
80 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
81 if (ret
&& contentType
)
82 *contentType
= CERT_QUERY_CONTENT_CRL
;
84 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
86 ret
= pCTLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
87 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
88 if (ret
&& contentType
)
89 *contentType
= CERT_QUERY_CONTENT_CTL
;
94 static BOOL
CRYPT_QueryContextObject(DWORD dwObjectType
, const void *pvObject
,
95 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
96 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, DWORD
*pdwFormatType
,
97 HCERTSTORE
*phCertStore
, const void **ppvContext
)
100 const CERT_BLOB
*blob
;
103 DWORD formatType
= 0;
105 switch (dwObjectType
)
107 case CERT_QUERY_OBJECT_FILE
:
108 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
109 * just read the file directly
111 ret
= CRYPT_ReadBlobFromFile(pvObject
, &fileBlob
);
114 case CERT_QUERY_OBJECT_BLOB
:
119 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
126 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
127 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
128 if (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
)
130 ret
= CRYPT_QueryContextBlob(blob
, dwExpectedContentTypeFlags
, store
,
131 pdwContentType
, ppvContext
);
133 formatType
= CERT_QUERY_FORMAT_BINARY
;
136 (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED
))
138 CRYPT_DATA_BLOB trimmed
= { blob
->cbData
, blob
->pbData
};
139 CRYPT_DATA_BLOB decoded
;
141 while (trimmed
.cbData
&& !trimmed
.pbData
[trimmed
.cbData
- 1])
143 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
, trimmed
.cbData
,
144 CRYPT_STRING_BASE64_ANY
, NULL
, &decoded
.cbData
, NULL
, NULL
);
147 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
150 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
,
151 trimmed
.cbData
, CRYPT_STRING_BASE64_ANY
, decoded
.pbData
,
152 &decoded
.cbData
, NULL
, NULL
);
155 ret
= CRYPT_QueryContextBlob(&decoded
,
156 dwExpectedContentTypeFlags
, store
, pdwContentType
,
159 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
161 CryptMemFree(decoded
.pbData
);
169 if (pdwMsgAndCertEncodingType
)
170 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
172 *pdwFormatType
= formatType
;
174 *phCertStore
= CertDuplicateStore(store
);
176 CertCloseStore(store
, 0);
177 if (blob
== &fileBlob
)
178 CryptMemFree(blob
->pbData
);
179 TRACE("returning %d\n", ret
);
183 static BOOL
CRYPT_QuerySerializedContextObject(DWORD dwObjectType
,
184 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
185 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
186 HCERTSTORE
*phCertStore
, const void **ppvContext
)
189 const CERT_BLOB
*blob
;
190 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
195 switch (dwObjectType
)
197 case CERT_QUERY_OBJECT_FILE
:
198 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
199 * just read the file directly
201 ret
= CRYPT_ReadBlobFromFile(pvObject
, &fileBlob
);
204 case CERT_QUERY_OBJECT_BLOB
:
209 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
216 context
= CRYPT_ReadSerializedElement(blob
->pbData
, blob
->cbData
,
217 CERT_STORE_ALL_CONTEXT_FLAG
, &contextType
);
220 DWORD contentType
, certStoreOffset
;
225 case CERT_STORE_CERTIFICATE_CONTEXT
:
226 contextInterface
= pCertInterface
;
227 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CERT
;
228 certStoreOffset
= offsetof(CERT_CONTEXT
, hCertStore
);
229 if (!(dwExpectedContentTypeFlags
&
230 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
))
232 SetLastError(ERROR_INVALID_DATA
);
237 case CERT_STORE_CRL_CONTEXT
:
238 contextInterface
= pCRLInterface
;
239 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CRL
;
240 certStoreOffset
= offsetof(CRL_CONTEXT
, hCertStore
);
241 if (!(dwExpectedContentTypeFlags
&
242 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
))
244 SetLastError(ERROR_INVALID_DATA
);
249 case CERT_STORE_CTL_CONTEXT
:
250 contextInterface
= pCTLInterface
;
251 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CTL
;
252 certStoreOffset
= offsetof(CTL_CONTEXT
, hCertStore
);
253 if (!(dwExpectedContentTypeFlags
&
254 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
))
256 SetLastError(ERROR_INVALID_DATA
);
262 SetLastError(ERROR_INVALID_DATA
);
266 if (pdwMsgAndCertEncodingType
)
267 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
269 *pdwContentType
= contentType
;
271 *phCertStore
= CertDuplicateStore(
272 *(HCERTSTORE
*)((const BYTE
*)context
+ certStoreOffset
));
275 *ppvContext
= context
;
276 Context_AddRef(context_from_ptr(context
));
281 if (contextInterface
&& context
)
282 Context_Release(context_from_ptr(context
));
283 if (blob
== &fileBlob
)
284 CryptMemFree(blob
->pbData
);
285 TRACE("returning %d\n", ret
);
289 static BOOL
CRYPT_QuerySerializedStoreFromFile(LPCWSTR fileName
,
290 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
291 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
296 TRACE("%s\n", debugstr_w(fileName
));
297 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
298 OPEN_EXISTING
, 0, NULL
);
299 if (file
!= INVALID_HANDLE_VALUE
)
301 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
302 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
304 ret
= CRYPT_ReadSerializedStoreFromFile(file
, store
);
307 if (pdwMsgAndCertEncodingType
)
308 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
310 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
312 *phCertStore
= CertDuplicateStore(store
);
314 CertCloseStore(store
, 0);
317 TRACE("returning %d\n", ret
);
321 static BOOL
CRYPT_QuerySerializedStoreFromBlob(const CRYPT_DATA_BLOB
*blob
,
322 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
323 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
325 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
326 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
329 TRACE("(%d, %p)\n", blob
->cbData
, blob
->pbData
);
331 ret
= CRYPT_ReadSerializedStoreFromBlob(blob
, store
);
334 if (pdwMsgAndCertEncodingType
)
335 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
337 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
339 *phCertStore
= CertDuplicateStore(store
);
341 CertCloseStore(store
, 0);
342 TRACE("returning %d\n", ret
);
346 static BOOL
CRYPT_QuerySerializedStoreObject(DWORD dwObjectType
,
347 const void *pvObject
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
348 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
350 switch (dwObjectType
)
352 case CERT_QUERY_OBJECT_FILE
:
353 return CRYPT_QuerySerializedStoreFromFile(pvObject
,
354 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
355 case CERT_QUERY_OBJECT_BLOB
:
356 return CRYPT_QuerySerializedStoreFromBlob(pvObject
,
357 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
359 FIXME("unimplemented for type %d\n", dwObjectType
);
360 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
365 static BOOL
CRYPT_QuerySignedMessage(const CRYPT_DATA_BLOB
*blob
,
366 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, HCRYPTMSG
*phMsg
)
368 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
372 if ((msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
)))
374 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
377 DWORD type
, len
= sizeof(type
);
379 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
382 if (type
!= CMSG_SIGNED
)
384 SetLastError(ERROR_INVALID_DATA
);
392 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_SIGNED
, 0, NULL
,
396 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
407 if (pdwMsgAndCertEncodingType
)
408 *pdwMsgAndCertEncodingType
= encodingType
;
410 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
417 static BOOL
CRYPT_QueryUnsignedMessage(const CRYPT_DATA_BLOB
*blob
,
418 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, HCRYPTMSG
*phMsg
)
420 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
424 if ((msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
)))
426 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
429 DWORD type
, len
= sizeof(type
);
431 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
434 if (type
!= CMSG_DATA
)
436 SetLastError(ERROR_INVALID_DATA
);
444 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_DATA
, 0,
448 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
459 if (pdwMsgAndCertEncodingType
)
460 *pdwMsgAndCertEncodingType
= encodingType
;
462 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
469 /* Used to decode non-embedded messages */
470 static BOOL
CRYPT_QueryMessageObject(DWORD dwObjectType
, const void *pvObject
,
471 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
472 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, DWORD
*pdwFormatType
,
473 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
476 const CERT_BLOB
*blob
;
478 HCRYPTMSG msg
= NULL
;
479 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
480 DWORD formatType
= 0;
482 TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType
, pvObject
,
483 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
484 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
, phCertStore
,
487 switch (dwObjectType
)
489 case CERT_QUERY_OBJECT_FILE
:
490 /* This isn't an embedded PKCS7 message, so just read the file
493 ret
= CRYPT_ReadBlobFromFile(pvObject
, &fileBlob
);
496 case CERT_QUERY_OBJECT_BLOB
:
501 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
508 if (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
)
510 /* Try it first as a signed message */
511 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
512 ret
= CRYPT_QuerySignedMessage(blob
, pdwMsgAndCertEncodingType
,
513 pdwContentType
, &msg
);
514 /* Failing that, try as an unsigned message */
516 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
517 ret
= CRYPT_QueryUnsignedMessage(blob
, pdwMsgAndCertEncodingType
,
518 pdwContentType
, &msg
);
520 formatType
= CERT_QUERY_FORMAT_BINARY
;
523 (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED
))
525 CRYPT_DATA_BLOB trimmed
= { blob
->cbData
, blob
->pbData
};
526 CRYPT_DATA_BLOB decoded
;
528 while (trimmed
.cbData
&& !trimmed
.pbData
[trimmed
.cbData
- 1])
530 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
, trimmed
.cbData
,
531 CRYPT_STRING_BASE64_ANY
, NULL
, &decoded
.cbData
, NULL
, NULL
);
534 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
537 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
,
538 trimmed
.cbData
, CRYPT_STRING_BASE64_ANY
, decoded
.pbData
,
539 &decoded
.cbData
, NULL
, NULL
);
542 /* Try it first as a signed message */
543 if (dwExpectedContentTypeFlags
&
544 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
545 ret
= CRYPT_QuerySignedMessage(&decoded
,
546 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
547 /* Failing that, try as an unsigned message */
548 if (!ret
&& (dwExpectedContentTypeFlags
&
549 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
550 ret
= CRYPT_QueryUnsignedMessage(&decoded
,
551 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
553 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
555 CryptMemFree(decoded
.pbData
);
560 if (!ret
&& !(blob
->cbData
% sizeof(WCHAR
)))
562 CRYPT_DATA_BLOB decoded
;
563 LPWSTR str
= (LPWSTR
)blob
->pbData
;
564 DWORD strLen
= blob
->cbData
/ sizeof(WCHAR
);
566 /* Try again, assuming the input string is UTF-16 base64 */
567 while (strLen
&& !str
[strLen
- 1])
569 ret
= CryptStringToBinaryW(str
, strLen
, CRYPT_STRING_BASE64_ANY
,
570 NULL
, &decoded
.cbData
, NULL
, NULL
);
573 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
576 ret
= CryptStringToBinaryW(str
, strLen
,
577 CRYPT_STRING_BASE64_ANY
, decoded
.pbData
, &decoded
.cbData
,
581 /* Try it first as a signed message */
582 if (dwExpectedContentTypeFlags
&
583 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
584 ret
= CRYPT_QuerySignedMessage(&decoded
,
585 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
586 /* Failing that, try as an unsigned message */
587 if (!ret
&& (dwExpectedContentTypeFlags
&
588 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
589 ret
= CRYPT_QueryUnsignedMessage(&decoded
,
590 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
592 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
594 CryptMemFree(decoded
.pbData
);
604 *pdwFormatType
= formatType
;
606 *phCertStore
= CertOpenStore(CERT_STORE_PROV_MSG
, encodingType
, 0,
613 if (blob
== &fileBlob
)
614 CryptMemFree(blob
->pbData
);
615 TRACE("returning %d\n", ret
);
619 static BOOL
CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType
,
620 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
621 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
622 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
628 TRACE("%s\n", debugstr_w(pvObject
));
630 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
632 WARN("don't know what to do for type %d embedded signed messages\n",
634 SetLastError(E_INVALIDARG
);
637 file
= CreateFileW(pvObject
, GENERIC_READ
, FILE_SHARE_READ
,
638 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
639 if (file
!= INVALID_HANDLE_VALUE
)
641 ret
= CryptSIPRetrieveSubjectGuid(pvObject
, file
, &subject
);
644 SIP_DISPATCH_INFO sip
;
646 memset(&sip
, 0, sizeof(sip
));
647 sip
.cbSize
= sizeof(sip
);
648 ret
= CryptSIPLoad(&subject
, 0, &sip
);
651 SIP_SUBJECTINFO subjectInfo
;
655 memset(&subjectInfo
, 0, sizeof(subjectInfo
));
656 subjectInfo
.cbSize
= sizeof(subjectInfo
);
657 subjectInfo
.pgSubjectType
= &subject
;
658 subjectInfo
.hFile
= file
;
659 subjectInfo
.pwsFileName
= pvObject
;
660 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0, &blob
.cbData
,
664 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
667 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0,
668 &blob
.cbData
, blob
.pbData
);
671 ret
= CRYPT_QueryMessageObject(
672 CERT_QUERY_OBJECT_BLOB
, &blob
,
673 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
674 CERT_QUERY_FORMAT_FLAG_BINARY
,
675 pdwMsgAndCertEncodingType
, NULL
, NULL
,
677 if (ret
&& pdwContentType
)
678 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
;
680 CryptMemFree(blob
.pbData
);
684 SetLastError(ERROR_OUTOFMEMORY
);
692 TRACE("returning %d\n", ret
);
696 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
697 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
698 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
699 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
700 const void **ppvContext
)
702 static const DWORD unimplementedTypes
=
703 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
704 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
707 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
708 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
709 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
710 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
712 if (dwObjectType
!= CERT_QUERY_OBJECT_BLOB
&&
713 dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
715 WARN("unsupported type %d\n", dwObjectType
);
716 SetLastError(E_INVALIDARG
);
721 WARN("missing required argument\n");
722 SetLastError(E_INVALIDARG
);
725 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
726 WARN("unimplemented for types %08x\n",
727 dwExpectedContentTypeFlags
& unimplementedTypes
);
730 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
739 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
740 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
741 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
743 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
744 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
745 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
, phCertStore
,
749 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
751 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
752 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
755 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
756 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
757 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
759 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
760 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
761 phCertStore
, ppvContext
);
764 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
765 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
767 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
768 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
769 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
,
773 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
775 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
776 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
780 SetLastError(CRYPT_E_NO_MATCH
);
781 TRACE("returning %d\n", ret
);
785 static BOOL WINAPI
CRYPT_FormatHexString(DWORD dwCertEncodingType
,
786 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
787 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
794 bytesNeeded
= (cbEncoded
* 3) * sizeof(WCHAR
);
796 bytesNeeded
= sizeof(WCHAR
);
799 *pcbFormat
= bytesNeeded
;
802 else if (*pcbFormat
< bytesNeeded
)
804 *pcbFormat
= bytesNeeded
;
805 SetLastError(ERROR_MORE_DATA
);
810 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
811 static const WCHAR endFmt
[] = { '%','0','2','x',0 };
813 LPWSTR ptr
= pbFormat
;
815 *pcbFormat
= bytesNeeded
;
818 for (i
= 0; i
< cbEncoded
; i
++)
820 if (i
< cbEncoded
- 1)
821 ptr
+= sprintfW(ptr
, fmt
, pbEncoded
[i
]);
823 ptr
+= sprintfW(ptr
, endFmt
, pbEncoded
[i
]);
833 #define MAX_STRING_RESOURCE_LEN 128
835 static const WCHAR commaSpace
[] = { ',',' ',0 };
841 WCHAR str
[MAX_STRING_RESOURCE_LEN
];
844 static BOOL
CRYPT_FormatBits(BYTE bits
, const struct BitToString
*map
,
845 DWORD mapEntries
, void *pbFormat
, DWORD
*pcbFormat
, BOOL
*first
)
847 DWORD bytesNeeded
= sizeof(WCHAR
);
849 BOOL ret
= TRUE
, localFirst
= *first
;
851 for (i
= 0; i
< mapEntries
; i
++)
852 if (bits
& map
[i
].bit
)
855 bytesNeeded
+= strlenW(commaSpace
) * sizeof(WCHAR
);
857 bytesNeeded
+= strlenW(map
[i
].str
) * sizeof(WCHAR
);
862 *pcbFormat
= bytesNeeded
;
864 else if (*pcbFormat
< bytesNeeded
)
867 *pcbFormat
= bytesNeeded
;
868 SetLastError(ERROR_MORE_DATA
);
873 LPWSTR str
= pbFormat
;
876 *pcbFormat
= bytesNeeded
;
877 for (i
= 0; i
< mapEntries
; i
++)
878 if (bits
& map
[i
].bit
)
882 strcpyW(str
, commaSpace
);
883 str
+= strlenW(commaSpace
);
886 strcpyW(str
, map
[i
].str
);
887 str
+= strlenW(map
[i
].str
);
894 static struct BitToString keyUsageByte0Map
[] = {
895 { CERT_DIGITAL_SIGNATURE_KEY_USAGE
, IDS_DIGITAL_SIGNATURE
, { 0 } },
896 { CERT_NON_REPUDIATION_KEY_USAGE
, IDS_NON_REPUDIATION
, { 0 } },
897 { CERT_KEY_ENCIPHERMENT_KEY_USAGE
, IDS_KEY_ENCIPHERMENT
, { 0 } },
898 { CERT_DATA_ENCIPHERMENT_KEY_USAGE
, IDS_DATA_ENCIPHERMENT
, { 0 } },
899 { CERT_KEY_AGREEMENT_KEY_USAGE
, IDS_KEY_AGREEMENT
, { 0 } },
900 { CERT_KEY_CERT_SIGN_KEY_USAGE
, IDS_CERT_SIGN
, { 0 } },
901 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE
, IDS_OFFLINE_CRL_SIGN
, { 0 } },
902 { CERT_CRL_SIGN_KEY_USAGE
, IDS_CRL_SIGN
, { 0 } },
903 { CERT_ENCIPHER_ONLY_KEY_USAGE
, IDS_ENCIPHER_ONLY
, { 0 } },
905 static struct BitToString keyUsageByte1Map
[] = {
906 { CERT_DECIPHER_ONLY_KEY_USAGE
, IDS_DECIPHER_ONLY
, { 0 } },
909 static BOOL WINAPI
CRYPT_FormatKeyUsage(DWORD dwCertEncodingType
,
910 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
911 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
915 CRYPT_BIT_BLOB
*bits
;
920 SetLastError(E_INVALIDARG
);
923 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_KEY_USAGE
,
924 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
926 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
927 DWORD bytesNeeded
= sizeof(WCHAR
);
929 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
930 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
931 if (!bits
->cbData
|| bits
->cbData
> 2)
933 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
935 *pcbFormat
= bytesNeeded
;
936 else if (*pcbFormat
< bytesNeeded
)
938 *pcbFormat
= bytesNeeded
;
939 SetLastError(ERROR_MORE_DATA
);
944 LPWSTR str
= pbFormat
;
946 *pcbFormat
= bytesNeeded
;
947 strcpyW(str
, infoNotAvailable
);
952 static BOOL stringsLoaded
= FALSE
;
960 i
< sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]);
962 LoadStringW(hInstance
, keyUsageByte0Map
[i
].id
,
963 keyUsageByte0Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
965 i
< sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]);
967 LoadStringW(hInstance
, keyUsageByte1Map
[i
].id
,
968 keyUsageByte1Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
969 stringsLoaded
= TRUE
;
971 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
972 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
973 NULL
, &bitStringLen
, &first
);
974 bytesNeeded
+= bitStringLen
;
975 if (bits
->cbData
== 2)
977 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
978 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
979 NULL
, &bitStringLen
, &first
);
980 bytesNeeded
+= bitStringLen
;
982 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
983 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
984 bits
->cbData
, NULL
, &size
);
987 *pcbFormat
= bytesNeeded
;
988 else if (*pcbFormat
< bytesNeeded
)
990 *pcbFormat
= bytesNeeded
;
991 SetLastError(ERROR_MORE_DATA
);
996 LPWSTR str
= pbFormat
;
998 bitStringLen
= bytesNeeded
;
1000 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
1001 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
1002 str
, &bitStringLen
, &first
);
1003 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
1004 if (bits
->cbData
== 2)
1006 bitStringLen
= bytesNeeded
;
1007 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
1008 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
1009 str
, &bitStringLen
, &first
);
1010 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
1014 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
1015 bits
->cbData
, str
, &size
);
1016 str
+= size
/ sizeof(WCHAR
) - 1;
1026 static const WCHAR crlf
[] = { '\r','\n',0 };
1028 static WCHAR subjectTypeHeader
[MAX_STRING_RESOURCE_LEN
];
1029 static WCHAR subjectTypeCA
[MAX_STRING_RESOURCE_LEN
];
1030 static WCHAR subjectTypeEndCert
[MAX_STRING_RESOURCE_LEN
];
1031 static WCHAR pathLengthHeader
[MAX_STRING_RESOURCE_LEN
];
1033 static BOOL WINAPI
CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType
,
1034 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1035 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1039 CERT_BASIC_CONSTRAINTS2_INFO
*info
;
1044 SetLastError(E_INVALIDARG
);
1047 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BASIC_CONSTRAINTS2
,
1048 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1050 static const WCHAR pathFmt
[] = { '%','d',0 };
1051 static BOOL stringsLoaded
= FALSE
;
1052 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
1053 WCHAR pathLength
[MAX_STRING_RESOURCE_LEN
];
1054 LPCWSTR sep
, subjectType
;
1057 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1060 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1065 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1070 LoadStringW(hInstance
, IDS_SUBJECT_TYPE
, subjectTypeHeader
,
1071 sizeof(subjectTypeHeader
) / sizeof(subjectTypeHeader
[0]));
1072 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_CA
, subjectTypeCA
,
1073 sizeof(subjectTypeCA
) / sizeof(subjectTypeCA
[0]));
1074 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_END_CERT
,
1076 sizeof(subjectTypeEndCert
) / sizeof(subjectTypeEndCert
[0]));
1077 LoadStringW(hInstance
, IDS_PATH_LENGTH
, pathLengthHeader
,
1078 sizeof(pathLengthHeader
) / sizeof(pathLengthHeader
[0]));
1079 stringsLoaded
= TRUE
;
1081 bytesNeeded
+= strlenW(subjectTypeHeader
) * sizeof(WCHAR
);
1083 subjectType
= subjectTypeCA
;
1085 subjectType
= subjectTypeEndCert
;
1086 bytesNeeded
+= strlenW(subjectType
) * sizeof(WCHAR
);
1087 bytesNeeded
+= sepLen
;
1088 bytesNeeded
+= strlenW(pathLengthHeader
) * sizeof(WCHAR
);
1089 if (info
->fPathLenConstraint
)
1090 sprintfW(pathLength
, pathFmt
, info
->dwPathLenConstraint
);
1092 LoadStringW(hInstance
, IDS_PATH_LENGTH_NONE
, pathLength
,
1093 sizeof(pathLength
) / sizeof(pathLength
[0]));
1094 bytesNeeded
+= strlenW(pathLength
) * sizeof(WCHAR
);
1096 *pcbFormat
= bytesNeeded
;
1097 else if (*pcbFormat
< bytesNeeded
)
1099 *pcbFormat
= bytesNeeded
;
1100 SetLastError(ERROR_MORE_DATA
);
1105 LPWSTR str
= pbFormat
;
1107 *pcbFormat
= bytesNeeded
;
1108 strcpyW(str
, subjectTypeHeader
);
1109 str
+= strlenW(subjectTypeHeader
);
1110 strcpyW(str
, subjectType
);
1111 str
+= strlenW(subjectType
);
1113 str
+= sepLen
/ sizeof(WCHAR
);
1114 strcpyW(str
, pathLengthHeader
);
1115 str
+= strlenW(pathLengthHeader
);
1116 strcpyW(str
, pathLength
);
1123 static BOOL
CRYPT_FormatHexStringWithPrefix(const CRYPT_DATA_BLOB
*blob
, int id
,
1124 LPWSTR str
, DWORD
*pcbStr
)
1126 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1130 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1131 CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
1132 blob
->pbData
, blob
->cbData
, NULL
, &bytesNeeded
);
1133 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1136 *pcbStr
= bytesNeeded
;
1139 else if (*pcbStr
< bytesNeeded
)
1141 *pcbStr
= bytesNeeded
;
1142 SetLastError(ERROR_MORE_DATA
);
1147 *pcbStr
= bytesNeeded
;
1149 str
+= strlenW(str
);
1150 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
1151 ret
= CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
1152 blob
->pbData
, blob
->cbData
, str
, &bytesNeeded
);
1157 static BOOL
CRYPT_FormatKeyId(const CRYPT_DATA_BLOB
*keyId
, LPWSTR str
,
1160 return CRYPT_FormatHexStringWithPrefix(keyId
, IDS_KEY_ID
, str
, pcbStr
);
1163 static BOOL
CRYPT_FormatCertSerialNumber(const CRYPT_DATA_BLOB
*serialNum
, LPWSTR str
,
1166 return CRYPT_FormatHexStringWithPrefix(serialNum
, IDS_CERT_SERIAL_NUMBER
,
1170 static const WCHAR indent
[] = { ' ',' ',' ',' ',' ',0 };
1171 static const WCHAR colonCrlf
[] = { ':','\r','\n',0 };
1173 static BOOL
CRYPT_FormatAltNameEntry(DWORD dwFormatStrType
, DWORD indentLevel
,
1174 const CERT_ALT_NAME_ENTRY
*entry
, LPWSTR str
, DWORD
*pcbStr
)
1177 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1178 WCHAR mask
[MAX_STRING_RESOURCE_LEN
];
1179 WCHAR ipAddrBuf
[32];
1181 DWORD bytesNeeded
= sizeof(WCHAR
);
1182 DWORD strType
= CERT_X500_NAME_STR
| CERT_NAME_STR_REVERSE_FLAG
;
1184 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1185 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1186 switch (entry
->dwAltNameChoice
)
1188 case CERT_ALT_NAME_RFC822_NAME
:
1189 LoadStringW(hInstance
, IDS_ALT_NAME_RFC822_NAME
, buf
,
1190 sizeof(buf
) / sizeof(buf
[0]));
1191 bytesNeeded
+= strlenW(entry
->u
.pwszRfc822Name
) * sizeof(WCHAR
);
1194 case CERT_ALT_NAME_DNS_NAME
:
1195 LoadStringW(hInstance
, IDS_ALT_NAME_DNS_NAME
, buf
,
1196 sizeof(buf
) / sizeof(buf
[0]));
1197 bytesNeeded
+= strlenW(entry
->u
.pwszDNSName
) * sizeof(WCHAR
);
1200 case CERT_ALT_NAME_DIRECTORY_NAME
:
1202 DWORD directoryNameLen
;
1204 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1205 strType
|= CERT_NAME_STR_CRLF_FLAG
;
1206 directoryNameLen
= cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1207 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, NULL
, 0);
1208 LoadStringW(hInstance
, IDS_ALT_NAME_DIRECTORY_NAME
, buf
,
1209 sizeof(buf
) / sizeof(buf
[0]));
1210 bytesNeeded
+= (directoryNameLen
- 1) * sizeof(WCHAR
);
1211 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1212 bytesNeeded
+= strlenW(colonCrlf
) * sizeof(WCHAR
);
1214 bytesNeeded
+= sizeof(WCHAR
); /* '=' */
1218 case CERT_ALT_NAME_URL
:
1219 LoadStringW(hInstance
, IDS_ALT_NAME_URL
, buf
,
1220 sizeof(buf
) / sizeof(buf
[0]));
1221 bytesNeeded
+= strlenW(entry
->u
.pwszURL
) * sizeof(WCHAR
);
1224 case CERT_ALT_NAME_IP_ADDRESS
:
1226 static const WCHAR ipAddrWithMaskFmt
[] = { '%','d','.','%','d','.',
1227 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1229 static const WCHAR ipAddrFmt
[] = { '%','d','.','%','d','.','%','d',
1232 LoadStringW(hInstance
, IDS_ALT_NAME_IP_ADDRESS
, buf
,
1233 sizeof(buf
) / sizeof(buf
[0]));
1234 if (entry
->u
.IPAddress
.cbData
== 8)
1236 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1238 LoadStringW(hInstance
, IDS_ALT_NAME_MASK
, mask
,
1239 sizeof(mask
) / sizeof(mask
[0]));
1240 bytesNeeded
+= strlenW(mask
) * sizeof(WCHAR
);
1241 sprintfW(ipAddrBuf
, ipAddrFmt
,
1242 entry
->u
.IPAddress
.pbData
[0],
1243 entry
->u
.IPAddress
.pbData
[1],
1244 entry
->u
.IPAddress
.pbData
[2],
1245 entry
->u
.IPAddress
.pbData
[3]);
1246 bytesNeeded
+= strlenW(ipAddrBuf
) * sizeof(WCHAR
);
1247 /* indent again, for the mask line */
1248 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1249 sprintfW(maskBuf
, ipAddrFmt
,
1250 entry
->u
.IPAddress
.pbData
[4],
1251 entry
->u
.IPAddress
.pbData
[5],
1252 entry
->u
.IPAddress
.pbData
[6],
1253 entry
->u
.IPAddress
.pbData
[7]);
1254 bytesNeeded
+= strlenW(maskBuf
) * sizeof(WCHAR
);
1255 bytesNeeded
+= strlenW(crlf
) * sizeof(WCHAR
);
1259 sprintfW(ipAddrBuf
, ipAddrWithMaskFmt
,
1260 entry
->u
.IPAddress
.pbData
[0],
1261 entry
->u
.IPAddress
.pbData
[1],
1262 entry
->u
.IPAddress
.pbData
[2],
1263 entry
->u
.IPAddress
.pbData
[3],
1264 entry
->u
.IPAddress
.pbData
[4],
1265 entry
->u
.IPAddress
.pbData
[5],
1266 entry
->u
.IPAddress
.pbData
[6],
1267 entry
->u
.IPAddress
.pbData
[7]);
1268 bytesNeeded
+= (strlenW(ipAddrBuf
) + 1) * sizeof(WCHAR
);
1274 FIXME("unknown IP address format (%d bytes)\n",
1275 entry
->u
.IPAddress
.cbData
);
1281 FIXME("unimplemented for %d\n", entry
->dwAltNameChoice
);
1286 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1288 *pcbStr
= bytesNeeded
;
1289 else if (*pcbStr
< bytesNeeded
)
1291 *pcbStr
= bytesNeeded
;
1292 SetLastError(ERROR_MORE_DATA
);
1299 *pcbStr
= bytesNeeded
;
1300 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1302 for (i
= 0; i
< indentLevel
; i
++)
1304 strcpyW(str
, indent
);
1305 str
+= strlenW(indent
);
1309 str
+= strlenW(str
);
1310 switch (entry
->dwAltNameChoice
)
1312 case CERT_ALT_NAME_RFC822_NAME
:
1313 case CERT_ALT_NAME_DNS_NAME
:
1314 case CERT_ALT_NAME_URL
:
1315 strcpyW(str
, entry
->u
.pwszURL
);
1317 case CERT_ALT_NAME_DIRECTORY_NAME
:
1318 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1320 strcpyW(str
, colonCrlf
);
1321 str
+= strlenW(colonCrlf
);
1325 cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1326 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, str
,
1327 bytesNeeded
/ sizeof(WCHAR
));
1329 case CERT_ALT_NAME_IP_ADDRESS
:
1330 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1332 strcpyW(str
, ipAddrBuf
);
1333 str
+= strlenW(ipAddrBuf
);
1335 str
+= strlenW(crlf
);
1336 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1338 for (i
= 0; i
< indentLevel
; i
++)
1340 strcpyW(str
, indent
);
1341 str
+= strlenW(indent
);
1345 str
+= strlenW(mask
);
1346 strcpyW(str
, maskBuf
);
1349 strcpyW(str
, ipAddrBuf
);
1357 static BOOL
CRYPT_FormatAltNameInfo(DWORD dwFormatStrType
, DWORD indentLevel
,
1358 const CERT_ALT_NAME_INFO
*name
, LPWSTR str
, DWORD
*pcbStr
)
1360 DWORD i
, size
, bytesNeeded
= 0;
1365 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1368 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1373 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1376 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1378 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1379 &name
->rgAltEntry
[i
], NULL
, &size
);
1382 bytesNeeded
+= size
- sizeof(WCHAR
);
1383 if (i
< name
->cAltEntry
- 1)
1384 bytesNeeded
+= sepLen
;
1389 bytesNeeded
+= sizeof(WCHAR
);
1391 *pcbStr
= bytesNeeded
;
1392 else if (*pcbStr
< bytesNeeded
)
1394 *pcbStr
= bytesNeeded
;
1395 SetLastError(ERROR_MORE_DATA
);
1400 *pcbStr
= bytesNeeded
;
1401 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1403 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1404 &name
->rgAltEntry
[i
], str
, &size
);
1407 str
+= size
/ sizeof(WCHAR
) - 1;
1408 if (i
< name
->cAltEntry
- 1)
1411 str
+= sepLen
/ sizeof(WCHAR
);
1420 static const WCHAR colonSep
[] = { ':',' ',0 };
1422 static BOOL WINAPI
CRYPT_FormatAltName(DWORD dwCertEncodingType
,
1423 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1424 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1428 CERT_ALT_NAME_INFO
*info
;
1431 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ALTERNATE_NAME
,
1432 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1434 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 0, info
, pbFormat
, pcbFormat
);
1440 static BOOL
CRYPT_FormatCertIssuer(DWORD dwFormatStrType
,
1441 const CERT_ALT_NAME_INFO
*issuer
, LPWSTR str
, DWORD
*pcbStr
)
1443 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1444 DWORD bytesNeeded
, sepLen
;
1448 LoadStringW(hInstance
, IDS_CERT_ISSUER
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1449 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, NULL
,
1451 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1452 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1455 sepLen
= strlenW(colonCrlf
) * sizeof(WCHAR
);
1460 sepLen
= strlenW(colonSep
) * sizeof(WCHAR
);
1462 bytesNeeded
+= sepLen
;
1466 *pcbStr
= bytesNeeded
;
1467 else if (*pcbStr
< bytesNeeded
)
1469 *pcbStr
= bytesNeeded
;
1470 SetLastError(ERROR_MORE_DATA
);
1475 *pcbStr
= bytesNeeded
;
1477 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
1478 str
+= strlenW(str
);
1480 str
+= sepLen
/ sizeof(WCHAR
);
1481 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, str
,
1488 static BOOL WINAPI
CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType
,
1489 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1490 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1493 CERT_AUTHORITY_KEY_ID2_INFO
*info
;
1499 SetLastError(E_INVALIDARG
);
1502 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_AUTHORITY_KEY_ID2
,
1503 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1505 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
1508 BOOL needSeparator
= FALSE
;
1510 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1513 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1518 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1521 if (info
->KeyId
.cbData
)
1523 needSeparator
= TRUE
;
1524 ret
= CRYPT_FormatKeyId(&info
->KeyId
, NULL
, &size
);
1527 /* don't include NULL-terminator more than once */
1528 bytesNeeded
+= size
- sizeof(WCHAR
);
1531 if (info
->AuthorityCertIssuer
.cAltEntry
)
1534 bytesNeeded
+= sepLen
;
1535 needSeparator
= TRUE
;
1536 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1537 &info
->AuthorityCertIssuer
, NULL
, &size
);
1540 /* don't include NULL-terminator more than once */
1541 bytesNeeded
+= size
- sizeof(WCHAR
);
1544 if (info
->AuthorityCertSerialNumber
.cbData
)
1547 bytesNeeded
+= sepLen
;
1548 ret
= CRYPT_FormatCertSerialNumber(
1549 &info
->AuthorityCertSerialNumber
, NULL
, &size
);
1552 /* don't include NULL-terminator more than once */
1553 bytesNeeded
+= size
- sizeof(WCHAR
);
1559 *pcbFormat
= bytesNeeded
;
1560 else if (*pcbFormat
< bytesNeeded
)
1562 *pcbFormat
= bytesNeeded
;
1563 SetLastError(ERROR_MORE_DATA
);
1568 LPWSTR str
= pbFormat
;
1570 *pcbFormat
= bytesNeeded
;
1571 needSeparator
= FALSE
;
1572 if (info
->KeyId
.cbData
)
1574 needSeparator
= TRUE
;
1575 /* Overestimate size available, it's already been checked
1579 ret
= CRYPT_FormatKeyId(&info
->KeyId
, str
, &size
);
1581 str
+= size
/ sizeof(WCHAR
) - 1;
1583 if (info
->AuthorityCertIssuer
.cAltEntry
)
1588 str
+= sepLen
/ sizeof(WCHAR
);
1590 needSeparator
= TRUE
;
1591 /* Overestimate size available, it's already been checked
1595 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1596 &info
->AuthorityCertIssuer
, str
, &size
);
1598 str
+= size
/ sizeof(WCHAR
) - 1;
1600 if (info
->AuthorityCertSerialNumber
.cbData
)
1605 str
+= sepLen
/ sizeof(WCHAR
);
1607 /* Overestimate size available, it's already been checked
1611 ret
= CRYPT_FormatCertSerialNumber(
1612 &info
->AuthorityCertSerialNumber
, str
, &size
);
1621 static WCHAR aia
[MAX_STRING_RESOURCE_LEN
];
1622 static WCHAR accessMethod
[MAX_STRING_RESOURCE_LEN
];
1623 static WCHAR ocsp
[MAX_STRING_RESOURCE_LEN
];
1624 static WCHAR caIssuers
[MAX_STRING_RESOURCE_LEN
];
1625 static WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
1626 static WCHAR accessLocation
[MAX_STRING_RESOURCE_LEN
];
1628 static BOOL WINAPI
CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType
,
1629 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1630 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1633 CERT_AUTHORITY_INFO_ACCESS
*info
;
1639 SetLastError(E_INVALIDARG
);
1642 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
1643 X509_AUTHORITY_INFO_ACCESS
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
,
1644 NULL
, &info
, &size
)))
1646 DWORD bytesNeeded
= sizeof(WCHAR
);
1648 if (!info
->cAccDescr
)
1650 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
1652 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
1653 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
1654 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
1656 *pcbFormat
= bytesNeeded
;
1657 else if (*pcbFormat
< bytesNeeded
)
1659 *pcbFormat
= bytesNeeded
;
1660 SetLastError(ERROR_MORE_DATA
);
1665 *pcbFormat
= bytesNeeded
;
1666 strcpyW(pbFormat
, infoNotAvailable
);
1671 static const WCHAR numFmt
[] = { '%','d',0 };
1672 static const WCHAR equal
[] = { '=',0 };
1673 static BOOL stringsLoaded
= FALSE
;
1675 LPCWSTR headingSep
, accessMethodSep
, locationSep
;
1676 WCHAR accessDescrNum
[11];
1680 LoadStringW(hInstance
, IDS_AIA
, aia
,
1681 sizeof(aia
) / sizeof(aia
[0]));
1682 LoadStringW(hInstance
, IDS_ACCESS_METHOD
, accessMethod
,
1683 sizeof(accessMethod
) / sizeof(accessMethod
[0]));
1684 LoadStringW(hInstance
, IDS_ACCESS_METHOD_OCSP
, ocsp
,
1685 sizeof(ocsp
) / sizeof(ocsp
[0]));
1686 LoadStringW(hInstance
, IDS_ACCESS_METHOD_CA_ISSUERS
, caIssuers
,
1687 sizeof(caIssuers
) / sizeof(caIssuers
[0]));
1688 LoadStringW(hInstance
, IDS_ACCESS_METHOD_UNKNOWN
, unknown
,
1689 sizeof(unknown
) / sizeof(unknown
[0]));
1690 LoadStringW(hInstance
, IDS_ACCESS_LOCATION
, accessLocation
,
1691 sizeof(accessLocation
) / sizeof(accessLocation
[0]));
1692 stringsLoaded
= TRUE
;
1694 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1697 accessMethodSep
= crlf
;
1698 locationSep
= colonCrlf
;
1702 headingSep
= colonSep
;
1703 accessMethodSep
= commaSpace
;
1704 locationSep
= equal
;
1707 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1710 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
1711 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1712 bytesNeeded
+= strlenW(accessDescrNum
) * sizeof(WCHAR
);
1713 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
1714 bytesNeeded
+= strlenW(aia
) * sizeof(WCHAR
);
1715 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
1717 bytesNeeded
+= strlenW(accessMethod
) * sizeof(WCHAR
);
1718 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1719 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1720 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1722 bytesNeeded
+= strlenW(ocsp
) * sizeof(WCHAR
);
1723 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1724 szOID_PKIX_CA_ISSUERS
))
1725 bytesNeeded
+= strlenW(caIssuers
) * sizeof(caIssuers
);
1727 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
1728 bytesNeeded
+= sizeof(WCHAR
); /* space */
1729 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
1730 bytesNeeded
+= strlen(info
->rgAccDescr
[i
].pszAccessMethod
)
1732 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
1733 /* Delimiter between access method and location */
1734 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1735 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1736 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1737 bytesNeeded
+= strlenW(accessLocation
) * sizeof(WCHAR
);
1738 bytesNeeded
+= strlenW(locationSep
) * sizeof(WCHAR
);
1739 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1740 &info
->rgAccDescr
[i
].AccessLocation
, NULL
, &size
);
1742 bytesNeeded
+= size
- sizeof(WCHAR
);
1743 /* Need extra delimiter between access method entries */
1744 if (i
< info
->cAccDescr
- 1)
1745 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1750 *pcbFormat
= bytesNeeded
;
1751 else if (*pcbFormat
< bytesNeeded
)
1753 *pcbFormat
= bytesNeeded
;
1754 SetLastError(ERROR_MORE_DATA
);
1759 LPWSTR str
= pbFormat
;
1760 DWORD altNameEntrySize
;
1762 *pcbFormat
= bytesNeeded
;
1763 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1768 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1769 strcpyW(str
, accessDescrNum
);
1770 str
+= strlenW(accessDescrNum
);
1773 str
+= strlenW(aia
);
1774 strcpyW(str
, headingSep
);
1775 str
+= strlenW(headingSep
);
1776 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1778 strcpyW(str
, indent
);
1779 str
+= strlenW(indent
);
1781 strcpyW(str
, accessMethod
);
1782 str
+= strlenW(accessMethod
);
1783 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1787 str
+= strlenW(ocsp
);
1789 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1790 szOID_PKIX_CA_ISSUERS
))
1792 strcpyW(str
, caIssuers
);
1793 str
+= strlenW(caIssuers
);
1797 strcpyW(str
, unknown
);
1798 str
+= strlenW(unknown
);
1802 for (oidPtr
= info
->rgAccDescr
[i
].pszAccessMethod
;
1803 *oidPtr
; oidPtr
++, str
++)
1806 strcpyW(str
, accessMethodSep
);
1807 str
+= strlenW(accessMethodSep
);
1808 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1810 strcpyW(str
, indent
);
1811 str
+= strlenW(indent
);
1813 strcpyW(str
, accessLocation
);
1814 str
+= strlenW(accessLocation
);
1815 strcpyW(str
, locationSep
);
1816 str
+= strlenW(locationSep
);
1817 /* This overestimates the size available, but that
1818 * won't matter since we checked earlier whether enough
1819 * space for the entire string was available.
1821 altNameEntrySize
= bytesNeeded
;
1822 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1823 &info
->rgAccDescr
[i
].AccessLocation
, str
,
1826 str
+= altNameEntrySize
/ sizeof(WCHAR
) - 1;
1827 if (i
< info
->cAccDescr
- 1)
1829 strcpyW(str
, accessMethodSep
);
1830 str
+= strlenW(accessMethodSep
);
1841 static WCHAR keyCompromise
[MAX_STRING_RESOURCE_LEN
];
1842 static WCHAR caCompromise
[MAX_STRING_RESOURCE_LEN
];
1843 static WCHAR affiliationChanged
[MAX_STRING_RESOURCE_LEN
];
1844 static WCHAR superseded
[MAX_STRING_RESOURCE_LEN
];
1845 static WCHAR operationCeased
[MAX_STRING_RESOURCE_LEN
];
1846 static WCHAR certificateHold
[MAX_STRING_RESOURCE_LEN
];
1848 struct reason_map_entry
1854 static struct reason_map_entry reason_map
[] = {
1855 { CRL_REASON_KEY_COMPROMISE_FLAG
, keyCompromise
, IDS_REASON_KEY_COMPROMISE
},
1856 { CRL_REASON_CA_COMPROMISE_FLAG
, caCompromise
, IDS_REASON_CA_COMPROMISE
},
1857 { CRL_REASON_AFFILIATION_CHANGED_FLAG
, affiliationChanged
,
1858 IDS_REASON_AFFILIATION_CHANGED
},
1859 { CRL_REASON_SUPERSEDED_FLAG
, superseded
, IDS_REASON_SUPERSEDED
},
1860 { CRL_REASON_CESSATION_OF_OPERATION_FLAG
, operationCeased
,
1861 IDS_REASON_CESSATION_OF_OPERATION
},
1862 { CRL_REASON_CERTIFICATE_HOLD_FLAG
, certificateHold
,
1863 IDS_REASON_CERTIFICATE_HOLD
},
1866 static BOOL
CRYPT_FormatReason(DWORD dwFormatStrType
,
1867 const CRYPT_BIT_BLOB
*reasonFlags
, LPWSTR str
, DWORD
*pcbStr
)
1869 static const WCHAR sep
[] = { ',',' ',0 };
1870 static const WCHAR bitsFmt
[] = { ' ','(','%','0','2','x',')',0 };
1871 static BOOL stringsLoaded
= FALSE
;
1872 unsigned int i
, numReasons
= 0;
1874 DWORD bytesNeeded
= sizeof(WCHAR
);
1879 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1880 LoadStringW(hInstance
, reason_map
[i
].id
, reason_map
[i
].reason
,
1881 MAX_STRING_RESOURCE_LEN
);
1882 stringsLoaded
= TRUE
;
1884 /* No need to check reasonFlags->cbData, we already know it's positive.
1885 * Ignore any other bytes, as they're for undefined bits.
1887 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1889 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1891 bytesNeeded
+= strlenW(reason_map
[i
].reason
) * sizeof(WCHAR
);
1893 bytesNeeded
+= strlenW(sep
) * sizeof(WCHAR
);
1896 sprintfW(bits
, bitsFmt
, reasonFlags
->pbData
[0]);
1897 bytesNeeded
+= strlenW(bits
);
1899 *pcbStr
= bytesNeeded
;
1900 else if (*pcbStr
< bytesNeeded
)
1902 *pcbStr
= bytesNeeded
;
1903 SetLastError(ERROR_MORE_DATA
);
1908 *pcbStr
= bytesNeeded
;
1909 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1911 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1913 strcpyW(str
, reason_map
[i
].reason
);
1914 str
+= strlenW(reason_map
[i
].reason
);
1915 if (i
< sizeof(reason_map
) / sizeof(reason_map
[0]) - 1 &&
1919 str
+= strlenW(sep
);
1928 static WCHAR crlDistPoint
[MAX_STRING_RESOURCE_LEN
];
1929 static WCHAR distPointName
[MAX_STRING_RESOURCE_LEN
];
1930 static WCHAR fullName
[MAX_STRING_RESOURCE_LEN
];
1931 static WCHAR rdnName
[MAX_STRING_RESOURCE_LEN
];
1932 static WCHAR reason
[MAX_STRING_RESOURCE_LEN
];
1933 static WCHAR issuer
[MAX_STRING_RESOURCE_LEN
];
1935 static BOOL WINAPI
CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType
,
1936 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1937 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1940 CRL_DIST_POINTS_INFO
*info
;
1946 SetLastError(E_INVALIDARG
);
1949 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_CRL_DIST_POINTS
,
1950 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1952 static const WCHAR numFmt
[] = { '%','d',0 };
1953 static const WCHAR colon
[] = { ':',0 };
1954 static BOOL stringsLoaded
= FALSE
;
1955 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for NULL terminator */
1956 BOOL haveAnEntry
= FALSE
;
1957 LPCWSTR headingSep
, nameSep
;
1958 WCHAR distPointNum
[11];
1963 LoadStringW(hInstance
, IDS_CRL_DIST_POINT
, crlDistPoint
,
1964 sizeof(crlDistPoint
) / sizeof(crlDistPoint
[0]));
1965 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_NAME
, distPointName
,
1966 sizeof(distPointName
) / sizeof(distPointName
[0]));
1967 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_FULL_NAME
, fullName
,
1968 sizeof(fullName
) / sizeof(fullName
[0]));
1969 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_RDN_NAME
, rdnName
,
1970 sizeof(rdnName
) / sizeof(rdnName
[0]));
1971 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_REASON
, reason
,
1972 sizeof(reason
) / sizeof(reason
[0]));
1973 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_ISSUER
, issuer
,
1974 sizeof(issuer
) / sizeof(issuer
[0]));
1975 stringsLoaded
= TRUE
;
1977 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1980 nameSep
= colonCrlf
;
1984 headingSep
= colonSep
;
1988 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
1990 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
1992 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
1993 CRL_DIST_POINT_NO_NAME
)
1995 bytesNeeded
+= strlenW(distPointName
) * sizeof(WCHAR
);
1996 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1997 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
1998 CRL_DIST_POINT_FULL_NAME
)
1999 bytesNeeded
+= strlenW(fullName
) * sizeof(WCHAR
);
2001 bytesNeeded
+= strlenW(rdnName
) * sizeof(WCHAR
);
2002 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
2003 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2004 bytesNeeded
+= 2 * strlenW(indent
) * sizeof(WCHAR
);
2005 /* The indent level (3) is higher than when used as the issuer,
2006 * because the name is subordinate to the name type (full vs.
2009 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
2010 &distPoint
->DistPointName
.u
.FullName
, NULL
, &size
);
2012 bytesNeeded
+= size
- sizeof(WCHAR
);
2015 else if (distPoint
->ReasonFlags
.cbData
)
2017 bytesNeeded
+= strlenW(reason
) * sizeof(WCHAR
);
2018 ret
= CRYPT_FormatReason(dwFormatStrType
,
2019 &distPoint
->ReasonFlags
, NULL
, &size
);
2021 bytesNeeded
+= size
- sizeof(WCHAR
);
2024 else if (distPoint
->CRLIssuer
.cAltEntry
)
2026 bytesNeeded
+= strlenW(issuer
) * sizeof(WCHAR
);
2027 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
2028 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
2029 &distPoint
->CRLIssuer
, NULL
, &size
);
2031 bytesNeeded
+= size
- sizeof(WCHAR
);
2036 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
2037 sprintfW(distPointNum
, numFmt
, i
+ 1);
2038 bytesNeeded
+= strlenW(distPointNum
) * sizeof(WCHAR
);
2039 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
2040 bytesNeeded
+= strlenW(crlDistPoint
) * sizeof(WCHAR
);
2041 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
2042 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2043 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
2048 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
2050 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
2051 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
2052 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
2054 *pcbFormat
= bytesNeeded
;
2055 else if (*pcbFormat
< bytesNeeded
)
2057 *pcbFormat
= bytesNeeded
;
2058 SetLastError(ERROR_MORE_DATA
);
2063 *pcbFormat
= bytesNeeded
;
2064 strcpyW(pbFormat
, infoNotAvailable
);
2070 *pcbFormat
= bytesNeeded
;
2071 else if (*pcbFormat
< bytesNeeded
)
2073 *pcbFormat
= bytesNeeded
;
2074 SetLastError(ERROR_MORE_DATA
);
2079 LPWSTR str
= pbFormat
;
2081 *pcbFormat
= bytesNeeded
;
2082 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2084 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
2087 sprintfW(distPointNum
, numFmt
, i
+ 1);
2088 strcpyW(str
, distPointNum
);
2089 str
+= strlenW(distPointNum
);
2091 strcpyW(str
, crlDistPoint
);
2092 str
+= strlenW(crlDistPoint
);
2093 strcpyW(str
, headingSep
);
2094 str
+= strlenW(headingSep
);
2095 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2097 strcpyW(str
, indent
);
2098 str
+= strlenW(indent
);
2100 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
2101 CRL_DIST_POINT_NO_NAME
)
2103 DWORD altNameSize
= bytesNeeded
;
2105 strcpyW(str
, distPointName
);
2106 str
+= strlenW(distPointName
);
2107 strcpyW(str
, nameSep
);
2108 str
+= strlenW(nameSep
);
2109 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2111 strcpyW(str
, indent
);
2112 str
+= strlenW(indent
);
2113 strcpyW(str
, indent
);
2114 str
+= strlenW(indent
);
2116 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
2117 CRL_DIST_POINT_FULL_NAME
)
2119 strcpyW(str
, fullName
);
2120 str
+= strlenW(fullName
);
2124 strcpyW(str
, rdnName
);
2125 str
+= strlenW(rdnName
);
2127 strcpyW(str
, nameSep
);
2128 str
+= strlenW(nameSep
);
2129 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
2130 &distPoint
->DistPointName
.u
.FullName
, str
,
2133 str
+= altNameSize
/ sizeof(WCHAR
) - 1;
2135 else if (distPoint
->ReasonFlags
.cbData
)
2137 DWORD reasonSize
= bytesNeeded
;
2139 strcpyW(str
, reason
);
2140 str
+= strlenW(reason
);
2141 ret
= CRYPT_FormatReason(dwFormatStrType
,
2142 &distPoint
->ReasonFlags
, str
, &reasonSize
);
2144 str
+= reasonSize
/ sizeof(WCHAR
) - 1;
2146 else if (distPoint
->CRLIssuer
.cAltEntry
)
2148 DWORD crlIssuerSize
= bytesNeeded
;
2150 strcpyW(str
, issuer
);
2151 str
+= strlenW(issuer
);
2152 strcpyW(str
, nameSep
);
2153 str
+= strlenW(nameSep
);
2154 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
2155 &distPoint
->CRLIssuer
, str
,
2158 str
+= crlIssuerSize
/ sizeof(WCHAR
) - 1;
2168 static BOOL WINAPI
CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType
,
2169 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2170 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2173 CERT_ENHKEY_USAGE
*usage
;
2179 SetLastError(E_INVALIDARG
);
2182 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ENHANCED_KEY_USAGE
,
2183 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &usage
, &size
)))
2185 WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
2187 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
2191 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2194 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2199 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2202 LoadStringW(hInstance
, IDS_USAGE_UNKNOWN
, unknown
,
2203 sizeof(unknown
) / sizeof(unknown
[0]));
2204 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2206 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2207 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2210 bytesNeeded
+= strlenW(info
->pwszName
) * sizeof(WCHAR
);
2212 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
2213 bytesNeeded
+= sizeof(WCHAR
); /* space */
2214 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
2215 bytesNeeded
+= strlen(usage
->rgpszUsageIdentifier
[i
]) *
2217 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
2218 if (i
< usage
->cUsageIdentifier
- 1)
2219 bytesNeeded
+= sepLen
;
2222 *pcbFormat
= bytesNeeded
;
2223 else if (*pcbFormat
< bytesNeeded
)
2225 *pcbFormat
= bytesNeeded
;
2226 SetLastError(ERROR_MORE_DATA
);
2231 LPWSTR str
= pbFormat
;
2233 *pcbFormat
= bytesNeeded
;
2234 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2236 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2237 usage
->rgpszUsageIdentifier
[i
],
2238 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2243 strcpyW(str
, info
->pwszName
);
2244 str
+= strlenW(info
->pwszName
);
2248 strcpyW(str
, unknown
);
2249 str
+= strlenW(unknown
);
2253 for (oidPtr
= usage
->rgpszUsageIdentifier
[i
]; *oidPtr
; oidPtr
++)
2257 if (i
< usage
->cUsageIdentifier
- 1)
2260 str
+= sepLen
/ sizeof(WCHAR
);
2269 static struct BitToString netscapeCertTypeMap
[] = {
2270 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_CLIENT
, { 0 } },
2271 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_SERVER
, { 0 } },
2272 { NETSCAPE_SMIME_CERT_TYPE
, IDS_NETSCAPE_SMIME
, { 0 } },
2273 { NETSCAPE_SIGN_CERT_TYPE
, IDS_NETSCAPE_SIGN
, { 0 } },
2274 { NETSCAPE_SSL_CA_CERT_TYPE
, IDS_NETSCAPE_SSL_CA
, { 0 } },
2275 { NETSCAPE_SMIME_CA_CERT_TYPE
, IDS_NETSCAPE_SMIME_CA
, { 0 } },
2276 { NETSCAPE_SIGN_CA_CERT_TYPE
, IDS_NETSCAPE_SIGN_CA
, { 0 } },
2279 static BOOL WINAPI
CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType
,
2280 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2281 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2285 CRYPT_BIT_BLOB
*bits
;
2290 SetLastError(E_INVALIDARG
);
2293 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BITS
,
2294 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
2296 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
2297 DWORD bytesNeeded
= sizeof(WCHAR
);
2299 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
2300 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
2301 if (!bits
->cbData
|| bits
->cbData
> 1)
2303 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
2305 *pcbFormat
= bytesNeeded
;
2306 else if (*pcbFormat
< bytesNeeded
)
2308 *pcbFormat
= bytesNeeded
;
2309 SetLastError(ERROR_MORE_DATA
);
2314 LPWSTR str
= pbFormat
;
2316 *pcbFormat
= bytesNeeded
;
2317 strcpyW(str
, infoNotAvailable
);
2322 static BOOL stringsLoaded
= FALSE
;
2329 for (i
= 0; i
< sizeof(netscapeCertTypeMap
) /
2330 sizeof(netscapeCertTypeMap
[0]); i
++)
2331 LoadStringW(hInstance
, netscapeCertTypeMap
[i
].id
,
2332 netscapeCertTypeMap
[i
].str
, MAX_STRING_RESOURCE_LEN
);
2333 stringsLoaded
= TRUE
;
2335 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2336 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2337 NULL
, &bitStringLen
, &first
);
2338 bytesNeeded
+= bitStringLen
;
2339 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
2340 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2341 bits
->cbData
, NULL
, &size
);
2342 bytesNeeded
+= size
;
2344 *pcbFormat
= bytesNeeded
;
2345 else if (*pcbFormat
< bytesNeeded
)
2347 *pcbFormat
= bytesNeeded
;
2348 SetLastError(ERROR_MORE_DATA
);
2353 LPWSTR str
= pbFormat
;
2355 bitStringLen
= bytesNeeded
;
2357 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2358 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2359 str
, &bitStringLen
, &first
);
2360 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
2363 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2364 bits
->cbData
, str
, &size
);
2365 str
+= size
/ sizeof(WCHAR
) - 1;
2375 static WCHAR financialCriteria
[MAX_STRING_RESOURCE_LEN
];
2376 static WCHAR available
[MAX_STRING_RESOURCE_LEN
];
2377 static WCHAR notAvailable
[MAX_STRING_RESOURCE_LEN
];
2378 static WCHAR meetsCriteria
[MAX_STRING_RESOURCE_LEN
];
2379 static WCHAR yes
[MAX_STRING_RESOURCE_LEN
];
2380 static WCHAR no
[MAX_STRING_RESOURCE_LEN
];
2382 static BOOL WINAPI
CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType
,
2383 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2384 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2387 SPC_FINANCIAL_CRITERIA criteria
;
2388 DWORD size
= sizeof(criteria
);
2393 SetLastError(E_INVALIDARG
);
2396 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
2397 SPC_FINANCIAL_CRITERIA_STRUCT
, pbEncoded
, cbEncoded
, 0, NULL
, &criteria
,
2400 static BOOL stringsLoaded
= FALSE
;
2401 DWORD bytesNeeded
= sizeof(WCHAR
);
2407 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA
, financialCriteria
,
2408 sizeof(financialCriteria
) / sizeof(financialCriteria
[0]));
2409 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_AVAILABLE
, available
,
2410 sizeof(available
) / sizeof(available
[0]));
2411 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE
,
2412 notAvailable
, sizeof(notAvailable
) / sizeof(notAvailable
[0]));
2413 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA
,
2414 meetsCriteria
, sizeof(meetsCriteria
) / sizeof(meetsCriteria
[0]));
2415 LoadStringW(hInstance
, IDS_YES
, yes
, sizeof(yes
) / sizeof(yes
[0]));
2416 LoadStringW(hInstance
, IDS_NO
, no
, sizeof(no
) / sizeof(no
[0]));
2417 stringsLoaded
= TRUE
;
2419 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2422 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2427 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2429 bytesNeeded
+= strlenW(financialCriteria
) * sizeof(WCHAR
);
2430 if (criteria
.fFinancialInfoAvailable
)
2432 bytesNeeded
+= strlenW(available
) * sizeof(WCHAR
);
2433 bytesNeeded
+= sepLen
;
2434 bytesNeeded
+= strlenW(meetsCriteria
) * sizeof(WCHAR
);
2435 if (criteria
.fMeetsCriteria
)
2436 bytesNeeded
+= strlenW(yes
) * sizeof(WCHAR
);
2438 bytesNeeded
+= strlenW(no
) * sizeof(WCHAR
);
2441 bytesNeeded
+= strlenW(notAvailable
) * sizeof(WCHAR
);
2443 *pcbFormat
= bytesNeeded
;
2444 else if (*pcbFormat
< bytesNeeded
)
2446 *pcbFormat
= bytesNeeded
;
2447 SetLastError(ERROR_MORE_DATA
);
2452 LPWSTR str
= pbFormat
;
2454 *pcbFormat
= bytesNeeded
;
2455 strcpyW(str
, financialCriteria
);
2456 str
+= strlenW(financialCriteria
);
2457 if (criteria
.fFinancialInfoAvailable
)
2459 strcpyW(str
, available
);
2460 str
+= strlenW(available
);
2462 str
+= sepLen
/ sizeof(WCHAR
);
2463 strcpyW(str
, meetsCriteria
);
2464 str
+= strlenW(meetsCriteria
);
2465 if (criteria
.fMeetsCriteria
)
2472 strcpyW(str
, notAvailable
);
2479 static BOOL WINAPI
CRYPT_FormatUnicodeString(DWORD dwCertEncodingType
,
2480 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2481 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2484 CERT_NAME_VALUE
*value
;
2490 SetLastError(E_INVALIDARG
);
2493 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_UNICODE_ANY_STRING
,
2494 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &value
, &size
)))
2497 *pcbFormat
= value
->Value
.cbData
;
2498 else if (*pcbFormat
< value
->Value
.cbData
)
2500 *pcbFormat
= value
->Value
.cbData
;
2501 SetLastError(ERROR_MORE_DATA
);
2506 LPWSTR str
= pbFormat
;
2508 *pcbFormat
= value
->Value
.cbData
;
2509 strcpyW(str
, (LPWSTR
)value
->Value
.pbData
);
2515 typedef BOOL (WINAPI
*CryptFormatObjectFunc
)(DWORD
, DWORD
, DWORD
, void *,
2516 LPCSTR
, const BYTE
*, DWORD
, void *, DWORD
*);
2518 static CryptFormatObjectFunc
CRYPT_GetBuiltinFormatFunction(DWORD encodingType
,
2519 DWORD formatStrType
, LPCSTR lpszStructType
)
2521 CryptFormatObjectFunc format
= NULL
;
2523 if ((encodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
)
2525 SetLastError(ERROR_FILE_NOT_FOUND
);
2528 if (IS_INTOID(lpszStructType
))
2530 switch (LOWORD(lpszStructType
))
2532 case LOWORD(X509_KEY_USAGE
):
2533 format
= CRYPT_FormatKeyUsage
;
2535 case LOWORD(X509_ALTERNATE_NAME
):
2536 format
= CRYPT_FormatAltName
;
2538 case LOWORD(X509_BASIC_CONSTRAINTS2
):
2539 format
= CRYPT_FormatBasicConstraints2
;
2541 case LOWORD(X509_AUTHORITY_KEY_ID2
):
2542 format
= CRYPT_FormatAuthorityKeyId2
;
2544 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
2545 format
= CRYPT_FormatAuthorityInfoAccess
;
2547 case LOWORD(X509_CRL_DIST_POINTS
):
2548 format
= CRYPT_FormatCRLDistPoints
;
2550 case LOWORD(X509_ENHANCED_KEY_USAGE
):
2551 format
= CRYPT_FormatEnhancedKeyUsage
;
2553 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT
):
2554 format
= CRYPT_FormatSpcFinancialCriteria
;
2558 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2559 format
= CRYPT_FormatAltName
;
2560 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2561 format
= CRYPT_FormatAltName
;
2562 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2563 format
= CRYPT_FormatKeyUsage
;
2564 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2565 format
= CRYPT_FormatAltName
;
2566 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2567 format
= CRYPT_FormatAltName
;
2568 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2569 format
= CRYPT_FormatBasicConstraints2
;
2570 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
2571 format
= CRYPT_FormatAuthorityInfoAccess
;
2572 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
2573 format
= CRYPT_FormatAuthorityKeyId2
;
2574 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2575 format
= CRYPT_FormatCRLDistPoints
;
2576 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2577 format
= CRYPT_FormatEnhancedKeyUsage
;
2578 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_CERT_TYPE
))
2579 format
= CRYPT_FormatNetscapeCertType
;
2580 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_BASE_URL
) ||
2581 !strcmp(lpszStructType
, szOID_NETSCAPE_REVOCATION_URL
) ||
2582 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_REVOCATION_URL
) ||
2583 !strcmp(lpszStructType
, szOID_NETSCAPE_CERT_RENEWAL_URL
) ||
2584 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_POLICY_URL
) ||
2585 !strcmp(lpszStructType
, szOID_NETSCAPE_SSL_SERVER_NAME
) ||
2586 !strcmp(lpszStructType
, szOID_NETSCAPE_COMMENT
))
2587 format
= CRYPT_FormatUnicodeString
;
2588 else if (!strcmp(lpszStructType
, SPC_FINANCIAL_CRITERIA_OBJID
))
2589 format
= CRYPT_FormatSpcFinancialCriteria
;
2593 BOOL WINAPI
CryptFormatObject(DWORD dwCertEncodingType
, DWORD dwFormatType
,
2594 DWORD dwFormatStrType
, void *pFormatStruct
, LPCSTR lpszStructType
,
2595 const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
, DWORD
*pcbFormat
)
2597 CryptFormatObjectFunc format
= NULL
;
2598 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2601 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType
,
2602 dwFormatType
, dwFormatStrType
, pFormatStruct
, debugstr_a(lpszStructType
),
2603 pbEncoded
, cbEncoded
, pbFormat
, pcbFormat
);
2605 if (!(format
= CRYPT_GetBuiltinFormatFunction(dwCertEncodingType
,
2606 dwFormatStrType
, lpszStructType
)))
2608 static HCRYPTOIDFUNCSET set
= NULL
;
2611 set
= CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC
, 0);
2612 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2613 (void **)&format
, &hFunc
);
2615 if (!format
&& (dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) ==
2616 X509_ASN_ENCODING
&& !(dwFormatStrType
& CRYPT_FORMAT_STR_NO_HEX
))
2617 format
= CRYPT_FormatHexString
;
2619 ret
= format(dwCertEncodingType
, dwFormatType
, dwFormatStrType
,
2620 pFormatStruct
, lpszStructType
, pbEncoded
, cbEncoded
, pbFormat
,
2623 CryptFreeOIDFunctionAddress(hFunc
, 0);