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 #include "crypt32_private.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(crypt
);
27 static BOOL
CRYPT_ReadBlobFromFile(LPCWSTR fileName
, PCERT_BLOB blob
)
32 TRACE("%s\n", debugstr_w(fileName
));
34 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
35 OPEN_EXISTING
, 0, NULL
);
36 if (file
!= INVALID_HANDLE_VALUE
)
39 blob
->cbData
= GetFileSize(file
, NULL
);
42 blob
->pbData
= CryptMemAlloc(blob
->cbData
);
47 ret
= ReadFile(file
, blob
->pbData
, blob
->cbData
, &read
, NULL
) && read
== blob
->cbData
;
48 if (!ret
) CryptMemFree(blob
->pbData
);
55 TRACE("returning %d\n", ret
);
59 static BOOL
CRYPT_QueryContextBlob(const CERT_BLOB
*blob
,
60 DWORD dwExpectedContentTypeFlags
, HCERTSTORE store
,
61 DWORD
*contentType
, const void **ppvContext
)
65 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
)
67 ret
= pCertInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
68 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
69 if (ret
&& contentType
)
70 *contentType
= CERT_QUERY_CONTENT_CERT
;
72 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
))
74 ret
= pCRLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
75 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
76 if (ret
&& contentType
)
77 *contentType
= CERT_QUERY_CONTENT_CRL
;
79 if (!ret
&& (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
81 ret
= pCTLInterface
->addEncodedToStore(store
, X509_ASN_ENCODING
,
82 blob
->pbData
, blob
->cbData
, CERT_STORE_ADD_ALWAYS
, ppvContext
);
83 if (ret
&& contentType
)
84 *contentType
= CERT_QUERY_CONTENT_CTL
;
89 static BOOL
CRYPT_QueryContextObject(DWORD dwObjectType
, const void *pvObject
,
90 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
91 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, DWORD
*pdwFormatType
,
92 HCERTSTORE
*phCertStore
, const void **ppvContext
)
95 const CERT_BLOB
*blob
;
100 switch (dwObjectType
)
102 case CERT_QUERY_OBJECT_FILE
:
103 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
104 * just read the file directly
106 ret
= CRYPT_ReadBlobFromFile(pvObject
, &fileBlob
);
109 case CERT_QUERY_OBJECT_BLOB
:
114 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
121 store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
122 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
123 if (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
)
125 ret
= CRYPT_QueryContextBlob(blob
, dwExpectedContentTypeFlags
, store
,
126 pdwContentType
, ppvContext
);
128 formatType
= CERT_QUERY_FORMAT_BINARY
;
131 (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED
))
133 CRYPT_DATA_BLOB trimmed
= { blob
->cbData
, blob
->pbData
};
134 CRYPT_DATA_BLOB decoded
;
136 while (trimmed
.cbData
&& !trimmed
.pbData
[trimmed
.cbData
- 1])
138 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
, trimmed
.cbData
,
139 CRYPT_STRING_BASE64_ANY
, NULL
, &decoded
.cbData
, NULL
, NULL
);
142 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
145 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
,
146 trimmed
.cbData
, CRYPT_STRING_BASE64_ANY
, decoded
.pbData
,
147 &decoded
.cbData
, NULL
, NULL
);
150 ret
= CRYPT_QueryContextBlob(&decoded
,
151 dwExpectedContentTypeFlags
, store
, pdwContentType
,
154 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
156 CryptMemFree(decoded
.pbData
);
164 if (pdwMsgAndCertEncodingType
)
165 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
167 *pdwFormatType
= formatType
;
169 *phCertStore
= CertDuplicateStore(store
);
171 CertCloseStore(store
, 0);
172 if (blob
== &fileBlob
)
173 CryptMemFree(blob
->pbData
);
174 TRACE("returning %d\n", ret
);
178 static BOOL
CRYPT_QuerySerializedContextObject(DWORD dwObjectType
,
179 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
180 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
181 HCERTSTORE
*phCertStore
, const void **ppvContext
)
184 const CERT_BLOB
*blob
;
185 const WINE_CONTEXT_INTERFACE
*contextInterface
= NULL
;
190 switch (dwObjectType
)
192 case CERT_QUERY_OBJECT_FILE
:
193 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
194 * just read the file directly
196 ret
= CRYPT_ReadBlobFromFile(pvObject
, &fileBlob
);
199 case CERT_QUERY_OBJECT_BLOB
:
204 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
211 context
= CRYPT_ReadSerializedElement(blob
->pbData
, blob
->cbData
,
212 CERT_STORE_ALL_CONTEXT_FLAG
, &contextType
);
215 DWORD contentType
, certStoreOffset
;
220 case CERT_STORE_CERTIFICATE_CONTEXT
:
221 contextInterface
= pCertInterface
;
222 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CERT
;
223 certStoreOffset
= offsetof(CERT_CONTEXT
, hCertStore
);
224 if (!(dwExpectedContentTypeFlags
&
225 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
))
227 SetLastError(ERROR_INVALID_DATA
);
232 case CERT_STORE_CRL_CONTEXT
:
233 contextInterface
= pCRLInterface
;
234 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CRL
;
235 certStoreOffset
= offsetof(CRL_CONTEXT
, hCertStore
);
236 if (!(dwExpectedContentTypeFlags
&
237 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
))
239 SetLastError(ERROR_INVALID_DATA
);
244 case CERT_STORE_CTL_CONTEXT
:
245 contextInterface
= pCTLInterface
;
246 contentType
= CERT_QUERY_CONTENT_SERIALIZED_CTL
;
247 certStoreOffset
= offsetof(CTL_CONTEXT
, hCertStore
);
248 if (!(dwExpectedContentTypeFlags
&
249 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
))
251 SetLastError(ERROR_INVALID_DATA
);
257 SetLastError(ERROR_INVALID_DATA
);
261 if (pdwMsgAndCertEncodingType
)
262 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
264 *pdwContentType
= contentType
;
266 *phCertStore
= CertDuplicateStore(
267 *(HCERTSTORE
*)((const BYTE
*)context
+ certStoreOffset
));
270 *ppvContext
= context
;
271 Context_AddRef(context_from_ptr(context
));
276 if (contextInterface
&& context
)
277 Context_Release(context_from_ptr(context
));
278 if (blob
== &fileBlob
)
279 CryptMemFree(blob
->pbData
);
280 TRACE("returning %d\n", ret
);
284 static BOOL
CRYPT_QuerySerializedStoreFromFile(LPCWSTR fileName
,
285 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
286 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
291 TRACE("%s\n", debugstr_w(fileName
));
292 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
293 OPEN_EXISTING
, 0, NULL
);
294 if (file
!= INVALID_HANDLE_VALUE
)
296 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
297 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
299 ret
= CRYPT_ReadSerializedStoreFromFile(file
, store
);
302 if (pdwMsgAndCertEncodingType
)
303 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
305 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
307 *phCertStore
= CertDuplicateStore(store
);
309 CertCloseStore(store
, 0);
312 TRACE("returning %d\n", ret
);
316 static BOOL
CRYPT_QuerySerializedStoreFromBlob(const CRYPT_DATA_BLOB
*blob
,
317 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
318 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
320 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
321 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
324 TRACE("(%d, %p)\n", blob
->cbData
, blob
->pbData
);
326 ret
= CRYPT_ReadSerializedStoreFromBlob(blob
, store
);
329 if (pdwMsgAndCertEncodingType
)
330 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
332 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
334 *phCertStore
= CertDuplicateStore(store
);
336 CertCloseStore(store
, 0);
337 TRACE("returning %d\n", ret
);
341 static BOOL
CRYPT_QuerySerializedStoreObject(DWORD dwObjectType
,
342 const void *pvObject
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
343 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
345 switch (dwObjectType
)
347 case CERT_QUERY_OBJECT_FILE
:
348 return CRYPT_QuerySerializedStoreFromFile(pvObject
,
349 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
350 case CERT_QUERY_OBJECT_BLOB
:
351 return CRYPT_QuerySerializedStoreFromBlob(pvObject
,
352 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
354 FIXME("unimplemented for type %d\n", dwObjectType
);
355 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
360 static BOOL
CRYPT_QuerySignedMessage(const CRYPT_DATA_BLOB
*blob
,
361 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, HCRYPTMSG
*phMsg
)
363 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
367 if ((msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
)))
369 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
372 DWORD type
, len
= sizeof(type
);
374 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
377 if (type
!= CMSG_SIGNED
)
379 SetLastError(ERROR_INVALID_DATA
);
387 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_SIGNED
, 0, NULL
,
391 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
402 if (pdwMsgAndCertEncodingType
)
403 *pdwMsgAndCertEncodingType
= encodingType
;
405 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
412 static BOOL
CRYPT_QueryUnsignedMessage(const CRYPT_DATA_BLOB
*blob
,
413 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, HCRYPTMSG
*phMsg
)
415 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
419 if ((msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
)))
421 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
424 DWORD type
, len
= sizeof(type
);
426 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
429 if (type
!= CMSG_DATA
)
431 SetLastError(ERROR_INVALID_DATA
);
439 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_DATA
, 0,
443 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
454 if (pdwMsgAndCertEncodingType
)
455 *pdwMsgAndCertEncodingType
= encodingType
;
457 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
464 /* Used to decode non-embedded messages */
465 static BOOL
CRYPT_QueryMessageObject(DWORD dwObjectType
, const void *pvObject
,
466 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
467 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, DWORD
*pdwFormatType
,
468 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
471 const CERT_BLOB
*blob
;
473 HCRYPTMSG msg
= NULL
;
474 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
475 DWORD formatType
= 0;
477 TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType
, pvObject
,
478 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
479 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
, phCertStore
,
482 switch (dwObjectType
)
484 case CERT_QUERY_OBJECT_FILE
:
485 /* This isn't an embedded PKCS7 message, so just read the file
488 ret
= CRYPT_ReadBlobFromFile(pvObject
, &fileBlob
);
491 case CERT_QUERY_OBJECT_BLOB
:
496 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
503 if (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
)
505 /* Try it first as a signed message */
506 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
507 ret
= CRYPT_QuerySignedMessage(blob
, pdwMsgAndCertEncodingType
,
508 pdwContentType
, &msg
);
509 /* Failing that, try as an unsigned message */
511 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
512 ret
= CRYPT_QueryUnsignedMessage(blob
, pdwMsgAndCertEncodingType
,
513 pdwContentType
, &msg
);
515 formatType
= CERT_QUERY_FORMAT_BINARY
;
518 (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED
))
520 CRYPT_DATA_BLOB trimmed
= { blob
->cbData
, blob
->pbData
};
521 CRYPT_DATA_BLOB decoded
;
523 while (trimmed
.cbData
&& !trimmed
.pbData
[trimmed
.cbData
- 1])
525 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
, trimmed
.cbData
,
526 CRYPT_STRING_BASE64_ANY
, NULL
, &decoded
.cbData
, NULL
, NULL
);
529 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
532 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
,
533 trimmed
.cbData
, CRYPT_STRING_BASE64_ANY
, decoded
.pbData
,
534 &decoded
.cbData
, NULL
, NULL
);
537 /* Try it first as a signed message */
538 if (dwExpectedContentTypeFlags
&
539 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
540 ret
= CRYPT_QuerySignedMessage(&decoded
,
541 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
542 /* Failing that, try as an unsigned message */
543 if (!ret
&& (dwExpectedContentTypeFlags
&
544 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
545 ret
= CRYPT_QueryUnsignedMessage(&decoded
,
546 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
548 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
550 CryptMemFree(decoded
.pbData
);
555 if (!ret
&& !(blob
->cbData
% sizeof(WCHAR
)))
557 CRYPT_DATA_BLOB decoded
;
558 LPWSTR str
= (LPWSTR
)blob
->pbData
;
559 DWORD strLen
= blob
->cbData
/ sizeof(WCHAR
);
561 /* Try again, assuming the input string is UTF-16 base64 */
562 while (strLen
&& !str
[strLen
- 1])
564 ret
= CryptStringToBinaryW(str
, strLen
, CRYPT_STRING_BASE64_ANY
,
565 NULL
, &decoded
.cbData
, NULL
, NULL
);
568 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
571 ret
= CryptStringToBinaryW(str
, strLen
,
572 CRYPT_STRING_BASE64_ANY
, decoded
.pbData
, &decoded
.cbData
,
576 /* Try it first as a signed message */
577 if (dwExpectedContentTypeFlags
&
578 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
579 ret
= CRYPT_QuerySignedMessage(&decoded
,
580 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
581 /* Failing that, try as an unsigned message */
582 if (!ret
&& (dwExpectedContentTypeFlags
&
583 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
584 ret
= CRYPT_QueryUnsignedMessage(&decoded
,
585 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
587 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
589 CryptMemFree(decoded
.pbData
);
599 *pdwFormatType
= formatType
;
601 *phCertStore
= CertOpenStore(CERT_STORE_PROV_MSG
, encodingType
, 0,
608 if (blob
== &fileBlob
)
609 CryptMemFree(blob
->pbData
);
610 TRACE("returning %d\n", ret
);
614 static BOOL
CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType
,
615 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
616 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
617 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
623 TRACE("%s\n", debugstr_w(pvObject
));
625 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
627 WARN("don't know what to do for type %d embedded signed messages\n",
629 SetLastError(E_INVALIDARG
);
632 file
= CreateFileW(pvObject
, GENERIC_READ
, FILE_SHARE_READ
,
633 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
634 if (file
!= INVALID_HANDLE_VALUE
)
636 ret
= CryptSIPRetrieveSubjectGuid(pvObject
, file
, &subject
);
639 SIP_DISPATCH_INFO sip
;
641 memset(&sip
, 0, sizeof(sip
));
642 sip
.cbSize
= sizeof(sip
);
643 ret
= CryptSIPLoad(&subject
, 0, &sip
);
646 SIP_SUBJECTINFO subjectInfo
;
650 memset(&subjectInfo
, 0, sizeof(subjectInfo
));
651 subjectInfo
.cbSize
= sizeof(subjectInfo
);
652 subjectInfo
.pgSubjectType
= &subject
;
653 subjectInfo
.hFile
= file
;
654 subjectInfo
.pwsFileName
= pvObject
;
655 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0, &blob
.cbData
,
659 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
662 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0,
663 &blob
.cbData
, blob
.pbData
);
666 ret
= CRYPT_QueryMessageObject(
667 CERT_QUERY_OBJECT_BLOB
, &blob
,
668 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
669 CERT_QUERY_FORMAT_FLAG_BINARY
,
670 pdwMsgAndCertEncodingType
, NULL
, NULL
,
672 if (ret
&& pdwContentType
)
673 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED
;
675 CryptMemFree(blob
.pbData
);
679 SetLastError(ERROR_OUTOFMEMORY
);
687 TRACE("returning %d\n", ret
);
691 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
692 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
693 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
694 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
695 const void **ppvContext
)
697 static const DWORD unimplementedTypes
=
698 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
699 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
702 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
703 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
704 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
705 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
707 if (dwObjectType
!= CERT_QUERY_OBJECT_BLOB
&&
708 dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
710 WARN("unsupported type %d\n", dwObjectType
);
711 SetLastError(E_INVALIDARG
);
716 WARN("missing required argument\n");
717 SetLastError(E_INVALIDARG
);
720 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
721 WARN("unimplemented for types %08x\n",
722 dwExpectedContentTypeFlags
& unimplementedTypes
);
725 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
734 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
735 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
736 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
738 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
739 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
740 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
, phCertStore
,
744 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
746 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
747 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
750 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
751 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
752 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
754 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
755 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
756 phCertStore
, ppvContext
);
759 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
760 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
762 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
763 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
764 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
,
768 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
770 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
771 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
775 SetLastError(CRYPT_E_NO_MATCH
);
776 TRACE("returning %d\n", ret
);
780 static BOOL WINAPI
CRYPT_FormatHexString(DWORD dwCertEncodingType
,
781 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
782 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
789 bytesNeeded
= (cbEncoded
* 3) * sizeof(WCHAR
);
791 bytesNeeded
= sizeof(WCHAR
);
794 *pcbFormat
= bytesNeeded
;
797 else if (*pcbFormat
< bytesNeeded
)
799 *pcbFormat
= bytesNeeded
;
800 SetLastError(ERROR_MORE_DATA
);
805 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
806 static const WCHAR endFmt
[] = { '%','0','2','x',0 };
808 LPWSTR ptr
= pbFormat
;
810 *pcbFormat
= bytesNeeded
;
813 for (i
= 0; i
< cbEncoded
; i
++)
815 if (i
< cbEncoded
- 1)
816 ptr
+= sprintfW(ptr
, fmt
, pbEncoded
[i
]);
818 ptr
+= sprintfW(ptr
, endFmt
, pbEncoded
[i
]);
828 #define MAX_STRING_RESOURCE_LEN 128
830 static const WCHAR commaSpace
[] = { ',',' ',0 };
836 WCHAR str
[MAX_STRING_RESOURCE_LEN
];
839 static BOOL
CRYPT_FormatBits(BYTE bits
, const struct BitToString
*map
,
840 DWORD mapEntries
, void *pbFormat
, DWORD
*pcbFormat
, BOOL
*first
)
842 DWORD bytesNeeded
= sizeof(WCHAR
);
844 BOOL ret
= TRUE
, localFirst
= *first
;
846 for (i
= 0; i
< mapEntries
; i
++)
847 if (bits
& map
[i
].bit
)
850 bytesNeeded
+= strlenW(commaSpace
) * sizeof(WCHAR
);
852 bytesNeeded
+= strlenW(map
[i
].str
) * sizeof(WCHAR
);
857 *pcbFormat
= bytesNeeded
;
859 else if (*pcbFormat
< bytesNeeded
)
862 *pcbFormat
= bytesNeeded
;
863 SetLastError(ERROR_MORE_DATA
);
868 LPWSTR str
= pbFormat
;
871 *pcbFormat
= bytesNeeded
;
872 for (i
= 0; i
< mapEntries
; i
++)
873 if (bits
& map
[i
].bit
)
877 strcpyW(str
, commaSpace
);
878 str
+= strlenW(commaSpace
);
881 strcpyW(str
, map
[i
].str
);
882 str
+= strlenW(map
[i
].str
);
889 static struct BitToString keyUsageByte0Map
[] = {
890 { CERT_DIGITAL_SIGNATURE_KEY_USAGE
, IDS_DIGITAL_SIGNATURE
, { 0 } },
891 { CERT_NON_REPUDIATION_KEY_USAGE
, IDS_NON_REPUDIATION
, { 0 } },
892 { CERT_KEY_ENCIPHERMENT_KEY_USAGE
, IDS_KEY_ENCIPHERMENT
, { 0 } },
893 { CERT_DATA_ENCIPHERMENT_KEY_USAGE
, IDS_DATA_ENCIPHERMENT
, { 0 } },
894 { CERT_KEY_AGREEMENT_KEY_USAGE
, IDS_KEY_AGREEMENT
, { 0 } },
895 { CERT_KEY_CERT_SIGN_KEY_USAGE
, IDS_CERT_SIGN
, { 0 } },
896 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE
, IDS_OFFLINE_CRL_SIGN
, { 0 } },
897 { CERT_CRL_SIGN_KEY_USAGE
, IDS_CRL_SIGN
, { 0 } },
898 { CERT_ENCIPHER_ONLY_KEY_USAGE
, IDS_ENCIPHER_ONLY
, { 0 } },
900 static struct BitToString keyUsageByte1Map
[] = {
901 { CERT_DECIPHER_ONLY_KEY_USAGE
, IDS_DECIPHER_ONLY
, { 0 } },
904 static BOOL WINAPI
CRYPT_FormatKeyUsage(DWORD dwCertEncodingType
,
905 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
906 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
910 CRYPT_BIT_BLOB
*bits
;
915 SetLastError(E_INVALIDARG
);
918 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_KEY_USAGE
,
919 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
921 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
922 DWORD bytesNeeded
= sizeof(WCHAR
);
924 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
925 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
926 if (!bits
->cbData
|| bits
->cbData
> 2)
928 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
930 *pcbFormat
= bytesNeeded
;
931 else if (*pcbFormat
< bytesNeeded
)
933 *pcbFormat
= bytesNeeded
;
934 SetLastError(ERROR_MORE_DATA
);
939 LPWSTR str
= pbFormat
;
941 *pcbFormat
= bytesNeeded
;
942 strcpyW(str
, infoNotAvailable
);
947 static BOOL stringsLoaded
= FALSE
;
955 i
< sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]);
957 LoadStringW(hInstance
, keyUsageByte0Map
[i
].id
,
958 keyUsageByte0Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
960 i
< sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]);
962 LoadStringW(hInstance
, keyUsageByte1Map
[i
].id
,
963 keyUsageByte1Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
964 stringsLoaded
= TRUE
;
966 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
967 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
968 NULL
, &bitStringLen
, &first
);
969 bytesNeeded
+= bitStringLen
;
970 if (bits
->cbData
== 2)
972 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
973 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
974 NULL
, &bitStringLen
, &first
);
975 bytesNeeded
+= bitStringLen
;
977 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
978 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
979 bits
->cbData
, NULL
, &size
);
982 *pcbFormat
= bytesNeeded
;
983 else if (*pcbFormat
< bytesNeeded
)
985 *pcbFormat
= bytesNeeded
;
986 SetLastError(ERROR_MORE_DATA
);
991 LPWSTR str
= pbFormat
;
993 bitStringLen
= bytesNeeded
;
995 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
996 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
997 str
, &bitStringLen
, &first
);
998 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
999 if (bits
->cbData
== 2)
1001 bitStringLen
= bytesNeeded
;
1002 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
1003 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
1004 str
, &bitStringLen
, &first
);
1005 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
1009 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
1010 bits
->cbData
, str
, &size
);
1011 str
+= size
/ sizeof(WCHAR
) - 1;
1021 static const WCHAR crlf
[] = { '\r','\n',0 };
1023 static WCHAR subjectTypeHeader
[MAX_STRING_RESOURCE_LEN
];
1024 static WCHAR subjectTypeCA
[MAX_STRING_RESOURCE_LEN
];
1025 static WCHAR subjectTypeEndCert
[MAX_STRING_RESOURCE_LEN
];
1026 static WCHAR pathLengthHeader
[MAX_STRING_RESOURCE_LEN
];
1028 static BOOL WINAPI
CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType
,
1029 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1030 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1034 CERT_BASIC_CONSTRAINTS2_INFO
*info
;
1039 SetLastError(E_INVALIDARG
);
1042 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BASIC_CONSTRAINTS2
,
1043 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1045 static const WCHAR pathFmt
[] = { '%','d',0 };
1046 static BOOL stringsLoaded
= FALSE
;
1047 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
1048 WCHAR pathLength
[MAX_STRING_RESOURCE_LEN
];
1049 LPCWSTR sep
, subjectType
;
1052 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1055 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1060 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1065 LoadStringW(hInstance
, IDS_SUBJECT_TYPE
, subjectTypeHeader
,
1066 sizeof(subjectTypeHeader
) / sizeof(subjectTypeHeader
[0]));
1067 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_CA
, subjectTypeCA
,
1068 sizeof(subjectTypeCA
) / sizeof(subjectTypeCA
[0]));
1069 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_END_CERT
,
1071 sizeof(subjectTypeEndCert
) / sizeof(subjectTypeEndCert
[0]));
1072 LoadStringW(hInstance
, IDS_PATH_LENGTH
, pathLengthHeader
,
1073 sizeof(pathLengthHeader
) / sizeof(pathLengthHeader
[0]));
1074 stringsLoaded
= TRUE
;
1076 bytesNeeded
+= strlenW(subjectTypeHeader
) * sizeof(WCHAR
);
1078 subjectType
= subjectTypeCA
;
1080 subjectType
= subjectTypeEndCert
;
1081 bytesNeeded
+= strlenW(subjectType
) * sizeof(WCHAR
);
1082 bytesNeeded
+= sepLen
;
1083 bytesNeeded
+= strlenW(pathLengthHeader
) * sizeof(WCHAR
);
1084 if (info
->fPathLenConstraint
)
1085 sprintfW(pathLength
, pathFmt
, info
->dwPathLenConstraint
);
1087 LoadStringW(hInstance
, IDS_PATH_LENGTH_NONE
, pathLength
,
1088 sizeof(pathLength
) / sizeof(pathLength
[0]));
1089 bytesNeeded
+= strlenW(pathLength
) * sizeof(WCHAR
);
1091 *pcbFormat
= bytesNeeded
;
1092 else if (*pcbFormat
< bytesNeeded
)
1094 *pcbFormat
= bytesNeeded
;
1095 SetLastError(ERROR_MORE_DATA
);
1100 LPWSTR str
= pbFormat
;
1102 *pcbFormat
= bytesNeeded
;
1103 strcpyW(str
, subjectTypeHeader
);
1104 str
+= strlenW(subjectTypeHeader
);
1105 strcpyW(str
, subjectType
);
1106 str
+= strlenW(subjectType
);
1108 str
+= sepLen
/ sizeof(WCHAR
);
1109 strcpyW(str
, pathLengthHeader
);
1110 str
+= strlenW(pathLengthHeader
);
1111 strcpyW(str
, pathLength
);
1118 static BOOL
CRYPT_FormatHexStringWithPrefix(const CRYPT_DATA_BLOB
*blob
, int id
,
1119 LPWSTR str
, DWORD
*pcbStr
)
1121 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1125 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1126 CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
1127 blob
->pbData
, blob
->cbData
, NULL
, &bytesNeeded
);
1128 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1131 *pcbStr
= bytesNeeded
;
1134 else if (*pcbStr
< bytesNeeded
)
1136 *pcbStr
= bytesNeeded
;
1137 SetLastError(ERROR_MORE_DATA
);
1142 *pcbStr
= bytesNeeded
;
1144 str
+= strlenW(str
);
1145 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
1146 ret
= CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
1147 blob
->pbData
, blob
->cbData
, str
, &bytesNeeded
);
1152 static BOOL
CRYPT_FormatKeyId(const CRYPT_DATA_BLOB
*keyId
, LPWSTR str
,
1155 return CRYPT_FormatHexStringWithPrefix(keyId
, IDS_KEY_ID
, str
, pcbStr
);
1158 static BOOL
CRYPT_FormatCertSerialNumber(const CRYPT_DATA_BLOB
*serialNum
, LPWSTR str
,
1161 return CRYPT_FormatHexStringWithPrefix(serialNum
, IDS_CERT_SERIAL_NUMBER
,
1165 static const WCHAR indent
[] = { ' ',' ',' ',' ',' ',0 };
1166 static const WCHAR colonCrlf
[] = { ':','\r','\n',0 };
1168 static BOOL
CRYPT_FormatAltNameEntry(DWORD dwFormatStrType
, DWORD indentLevel
,
1169 const CERT_ALT_NAME_ENTRY
*entry
, LPWSTR str
, DWORD
*pcbStr
)
1172 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1173 WCHAR mask
[MAX_STRING_RESOURCE_LEN
];
1174 WCHAR ipAddrBuf
[32];
1176 DWORD bytesNeeded
= sizeof(WCHAR
);
1177 DWORD strType
= CERT_X500_NAME_STR
| CERT_NAME_STR_REVERSE_FLAG
;
1179 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1180 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1181 switch (entry
->dwAltNameChoice
)
1183 case CERT_ALT_NAME_RFC822_NAME
:
1184 LoadStringW(hInstance
, IDS_ALT_NAME_RFC822_NAME
, buf
,
1185 sizeof(buf
) / sizeof(buf
[0]));
1186 bytesNeeded
+= strlenW(entry
->u
.pwszRfc822Name
) * sizeof(WCHAR
);
1189 case CERT_ALT_NAME_DNS_NAME
:
1190 LoadStringW(hInstance
, IDS_ALT_NAME_DNS_NAME
, buf
,
1191 sizeof(buf
) / sizeof(buf
[0]));
1192 bytesNeeded
+= strlenW(entry
->u
.pwszDNSName
) * sizeof(WCHAR
);
1195 case CERT_ALT_NAME_DIRECTORY_NAME
:
1197 DWORD directoryNameLen
;
1199 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1200 strType
|= CERT_NAME_STR_CRLF_FLAG
;
1201 directoryNameLen
= cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1202 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, NULL
, 0);
1203 LoadStringW(hInstance
, IDS_ALT_NAME_DIRECTORY_NAME
, buf
,
1204 sizeof(buf
) / sizeof(buf
[0]));
1205 bytesNeeded
+= (directoryNameLen
- 1) * sizeof(WCHAR
);
1206 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1207 bytesNeeded
+= strlenW(colonCrlf
) * sizeof(WCHAR
);
1209 bytesNeeded
+= sizeof(WCHAR
); /* '=' */
1213 case CERT_ALT_NAME_URL
:
1214 LoadStringW(hInstance
, IDS_ALT_NAME_URL
, buf
,
1215 sizeof(buf
) / sizeof(buf
[0]));
1216 bytesNeeded
+= strlenW(entry
->u
.pwszURL
) * sizeof(WCHAR
);
1219 case CERT_ALT_NAME_IP_ADDRESS
:
1221 static const WCHAR ipAddrWithMaskFmt
[] = { '%','d','.','%','d','.',
1222 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1224 static const WCHAR ipAddrFmt
[] = { '%','d','.','%','d','.','%','d',
1227 LoadStringW(hInstance
, IDS_ALT_NAME_IP_ADDRESS
, buf
,
1228 sizeof(buf
) / sizeof(buf
[0]));
1229 if (entry
->u
.IPAddress
.cbData
== 8)
1231 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1233 LoadStringW(hInstance
, IDS_ALT_NAME_MASK
, mask
,
1234 sizeof(mask
) / sizeof(mask
[0]));
1235 bytesNeeded
+= strlenW(mask
) * sizeof(WCHAR
);
1236 sprintfW(ipAddrBuf
, ipAddrFmt
,
1237 entry
->u
.IPAddress
.pbData
[0],
1238 entry
->u
.IPAddress
.pbData
[1],
1239 entry
->u
.IPAddress
.pbData
[2],
1240 entry
->u
.IPAddress
.pbData
[3]);
1241 bytesNeeded
+= strlenW(ipAddrBuf
) * sizeof(WCHAR
);
1242 /* indent again, for the mask line */
1243 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1244 sprintfW(maskBuf
, ipAddrFmt
,
1245 entry
->u
.IPAddress
.pbData
[4],
1246 entry
->u
.IPAddress
.pbData
[5],
1247 entry
->u
.IPAddress
.pbData
[6],
1248 entry
->u
.IPAddress
.pbData
[7]);
1249 bytesNeeded
+= strlenW(maskBuf
) * sizeof(WCHAR
);
1250 bytesNeeded
+= strlenW(crlf
) * sizeof(WCHAR
);
1254 sprintfW(ipAddrBuf
, ipAddrWithMaskFmt
,
1255 entry
->u
.IPAddress
.pbData
[0],
1256 entry
->u
.IPAddress
.pbData
[1],
1257 entry
->u
.IPAddress
.pbData
[2],
1258 entry
->u
.IPAddress
.pbData
[3],
1259 entry
->u
.IPAddress
.pbData
[4],
1260 entry
->u
.IPAddress
.pbData
[5],
1261 entry
->u
.IPAddress
.pbData
[6],
1262 entry
->u
.IPAddress
.pbData
[7]);
1263 bytesNeeded
+= (strlenW(ipAddrBuf
) + 1) * sizeof(WCHAR
);
1269 FIXME("unknown IP address format (%d bytes)\n",
1270 entry
->u
.IPAddress
.cbData
);
1276 FIXME("unimplemented for %d\n", entry
->dwAltNameChoice
);
1281 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1283 *pcbStr
= bytesNeeded
;
1284 else if (*pcbStr
< bytesNeeded
)
1286 *pcbStr
= bytesNeeded
;
1287 SetLastError(ERROR_MORE_DATA
);
1294 *pcbStr
= bytesNeeded
;
1295 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1297 for (i
= 0; i
< indentLevel
; i
++)
1299 strcpyW(str
, indent
);
1300 str
+= strlenW(indent
);
1304 str
+= strlenW(str
);
1305 switch (entry
->dwAltNameChoice
)
1307 case CERT_ALT_NAME_RFC822_NAME
:
1308 case CERT_ALT_NAME_DNS_NAME
:
1309 case CERT_ALT_NAME_URL
:
1310 strcpyW(str
, entry
->u
.pwszURL
);
1312 case CERT_ALT_NAME_DIRECTORY_NAME
:
1313 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1315 strcpyW(str
, colonCrlf
);
1316 str
+= strlenW(colonCrlf
);
1320 cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1321 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, str
,
1322 bytesNeeded
/ sizeof(WCHAR
));
1324 case CERT_ALT_NAME_IP_ADDRESS
:
1325 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1327 strcpyW(str
, ipAddrBuf
);
1328 str
+= strlenW(ipAddrBuf
);
1330 str
+= strlenW(crlf
);
1331 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1333 for (i
= 0; i
< indentLevel
; i
++)
1335 strcpyW(str
, indent
);
1336 str
+= strlenW(indent
);
1340 str
+= strlenW(mask
);
1341 strcpyW(str
, maskBuf
);
1344 strcpyW(str
, ipAddrBuf
);
1352 static BOOL
CRYPT_FormatAltNameInfo(DWORD dwFormatStrType
, DWORD indentLevel
,
1353 const CERT_ALT_NAME_INFO
*name
, LPWSTR str
, DWORD
*pcbStr
)
1355 DWORD i
, size
, bytesNeeded
= 0;
1360 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1363 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1368 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1371 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1373 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1374 &name
->rgAltEntry
[i
], NULL
, &size
);
1377 bytesNeeded
+= size
- sizeof(WCHAR
);
1378 if (i
< name
->cAltEntry
- 1)
1379 bytesNeeded
+= sepLen
;
1384 bytesNeeded
+= sizeof(WCHAR
);
1386 *pcbStr
= bytesNeeded
;
1387 else if (*pcbStr
< bytesNeeded
)
1389 *pcbStr
= bytesNeeded
;
1390 SetLastError(ERROR_MORE_DATA
);
1395 *pcbStr
= bytesNeeded
;
1396 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1398 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1399 &name
->rgAltEntry
[i
], str
, &size
);
1402 str
+= size
/ sizeof(WCHAR
) - 1;
1403 if (i
< name
->cAltEntry
- 1)
1406 str
+= sepLen
/ sizeof(WCHAR
);
1415 static const WCHAR colonSep
[] = { ':',' ',0 };
1417 static BOOL WINAPI
CRYPT_FormatAltName(DWORD dwCertEncodingType
,
1418 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1419 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1423 CERT_ALT_NAME_INFO
*info
;
1426 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ALTERNATE_NAME
,
1427 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1429 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 0, info
, pbFormat
, pcbFormat
);
1435 static BOOL
CRYPT_FormatCertIssuer(DWORD dwFormatStrType
,
1436 const CERT_ALT_NAME_INFO
*issuer
, LPWSTR str
, DWORD
*pcbStr
)
1438 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1439 DWORD bytesNeeded
, sepLen
;
1443 LoadStringW(hInstance
, IDS_CERT_ISSUER
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1444 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, NULL
,
1446 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1447 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1450 sepLen
= strlenW(colonCrlf
) * sizeof(WCHAR
);
1455 sepLen
= strlenW(colonSep
) * sizeof(WCHAR
);
1457 bytesNeeded
+= sepLen
;
1461 *pcbStr
= bytesNeeded
;
1462 else if (*pcbStr
< bytesNeeded
)
1464 *pcbStr
= bytesNeeded
;
1465 SetLastError(ERROR_MORE_DATA
);
1470 *pcbStr
= bytesNeeded
;
1472 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
1473 str
+= strlenW(str
);
1475 str
+= sepLen
/ sizeof(WCHAR
);
1476 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, str
,
1483 static BOOL WINAPI
CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType
,
1484 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1485 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1488 CERT_AUTHORITY_KEY_ID2_INFO
*info
;
1494 SetLastError(E_INVALIDARG
);
1497 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_AUTHORITY_KEY_ID2
,
1498 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1500 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
1503 BOOL needSeparator
= FALSE
;
1505 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1508 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1513 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1516 if (info
->KeyId
.cbData
)
1518 needSeparator
= TRUE
;
1519 ret
= CRYPT_FormatKeyId(&info
->KeyId
, NULL
, &size
);
1522 /* don't include NULL-terminator more than once */
1523 bytesNeeded
+= size
- sizeof(WCHAR
);
1526 if (info
->AuthorityCertIssuer
.cAltEntry
)
1529 bytesNeeded
+= sepLen
;
1530 needSeparator
= TRUE
;
1531 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1532 &info
->AuthorityCertIssuer
, NULL
, &size
);
1535 /* don't include NULL-terminator more than once */
1536 bytesNeeded
+= size
- sizeof(WCHAR
);
1539 if (info
->AuthorityCertSerialNumber
.cbData
)
1542 bytesNeeded
+= sepLen
;
1543 ret
= CRYPT_FormatCertSerialNumber(
1544 &info
->AuthorityCertSerialNumber
, NULL
, &size
);
1547 /* don't include NULL-terminator more than once */
1548 bytesNeeded
+= size
- sizeof(WCHAR
);
1554 *pcbFormat
= bytesNeeded
;
1555 else if (*pcbFormat
< bytesNeeded
)
1557 *pcbFormat
= bytesNeeded
;
1558 SetLastError(ERROR_MORE_DATA
);
1563 LPWSTR str
= pbFormat
;
1565 *pcbFormat
= bytesNeeded
;
1566 needSeparator
= FALSE
;
1567 if (info
->KeyId
.cbData
)
1569 needSeparator
= TRUE
;
1570 /* Overestimate size available, it's already been checked
1574 ret
= CRYPT_FormatKeyId(&info
->KeyId
, str
, &size
);
1576 str
+= size
/ sizeof(WCHAR
) - 1;
1578 if (info
->AuthorityCertIssuer
.cAltEntry
)
1583 str
+= sepLen
/ sizeof(WCHAR
);
1585 needSeparator
= TRUE
;
1586 /* Overestimate size available, it's already been checked
1590 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1591 &info
->AuthorityCertIssuer
, str
, &size
);
1593 str
+= size
/ sizeof(WCHAR
) - 1;
1595 if (info
->AuthorityCertSerialNumber
.cbData
)
1600 str
+= sepLen
/ sizeof(WCHAR
);
1602 /* Overestimate size available, it's already been checked
1606 ret
= CRYPT_FormatCertSerialNumber(
1607 &info
->AuthorityCertSerialNumber
, str
, &size
);
1616 static WCHAR aia
[MAX_STRING_RESOURCE_LEN
];
1617 static WCHAR accessMethod
[MAX_STRING_RESOURCE_LEN
];
1618 static WCHAR ocsp
[MAX_STRING_RESOURCE_LEN
];
1619 static WCHAR caIssuers
[MAX_STRING_RESOURCE_LEN
];
1620 static WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
1621 static WCHAR accessLocation
[MAX_STRING_RESOURCE_LEN
];
1623 static BOOL WINAPI
CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType
,
1624 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1625 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1628 CERT_AUTHORITY_INFO_ACCESS
*info
;
1634 SetLastError(E_INVALIDARG
);
1637 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
1638 X509_AUTHORITY_INFO_ACCESS
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
,
1639 NULL
, &info
, &size
)))
1641 DWORD bytesNeeded
= sizeof(WCHAR
);
1643 if (!info
->cAccDescr
)
1645 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
1647 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
1648 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
1649 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
1651 *pcbFormat
= bytesNeeded
;
1652 else if (*pcbFormat
< bytesNeeded
)
1654 *pcbFormat
= bytesNeeded
;
1655 SetLastError(ERROR_MORE_DATA
);
1660 *pcbFormat
= bytesNeeded
;
1661 strcpyW(pbFormat
, infoNotAvailable
);
1666 static const WCHAR numFmt
[] = { '%','d',0 };
1667 static const WCHAR equal
[] = { '=',0 };
1668 static BOOL stringsLoaded
= FALSE
;
1670 LPCWSTR headingSep
, accessMethodSep
, locationSep
;
1671 WCHAR accessDescrNum
[11];
1675 LoadStringW(hInstance
, IDS_AIA
, aia
,
1676 sizeof(aia
) / sizeof(aia
[0]));
1677 LoadStringW(hInstance
, IDS_ACCESS_METHOD
, accessMethod
,
1678 sizeof(accessMethod
) / sizeof(accessMethod
[0]));
1679 LoadStringW(hInstance
, IDS_ACCESS_METHOD_OCSP
, ocsp
,
1680 sizeof(ocsp
) / sizeof(ocsp
[0]));
1681 LoadStringW(hInstance
, IDS_ACCESS_METHOD_CA_ISSUERS
, caIssuers
,
1682 sizeof(caIssuers
) / sizeof(caIssuers
[0]));
1683 LoadStringW(hInstance
, IDS_ACCESS_METHOD_UNKNOWN
, unknown
,
1684 sizeof(unknown
) / sizeof(unknown
[0]));
1685 LoadStringW(hInstance
, IDS_ACCESS_LOCATION
, accessLocation
,
1686 sizeof(accessLocation
) / sizeof(accessLocation
[0]));
1687 stringsLoaded
= TRUE
;
1689 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1692 accessMethodSep
= crlf
;
1693 locationSep
= colonCrlf
;
1697 headingSep
= colonSep
;
1698 accessMethodSep
= commaSpace
;
1699 locationSep
= equal
;
1702 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1705 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
1706 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1707 bytesNeeded
+= strlenW(accessDescrNum
) * sizeof(WCHAR
);
1708 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
1709 bytesNeeded
+= strlenW(aia
) * sizeof(WCHAR
);
1710 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
1712 bytesNeeded
+= strlenW(accessMethod
) * sizeof(WCHAR
);
1713 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1714 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1715 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1717 bytesNeeded
+= strlenW(ocsp
) * sizeof(WCHAR
);
1718 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1719 szOID_PKIX_CA_ISSUERS
))
1720 bytesNeeded
+= strlenW(caIssuers
) * sizeof(caIssuers
);
1722 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
1723 bytesNeeded
+= sizeof(WCHAR
); /* space */
1724 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
1725 bytesNeeded
+= strlen(info
->rgAccDescr
[i
].pszAccessMethod
)
1727 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
1728 /* Delimiter between access method and location */
1729 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1730 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1731 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1732 bytesNeeded
+= strlenW(accessLocation
) * sizeof(WCHAR
);
1733 bytesNeeded
+= strlenW(locationSep
) * sizeof(WCHAR
);
1734 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1735 &info
->rgAccDescr
[i
].AccessLocation
, NULL
, &size
);
1737 bytesNeeded
+= size
- sizeof(WCHAR
);
1738 /* Need extra delimiter between access method entries */
1739 if (i
< info
->cAccDescr
- 1)
1740 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1745 *pcbFormat
= bytesNeeded
;
1746 else if (*pcbFormat
< bytesNeeded
)
1748 *pcbFormat
= bytesNeeded
;
1749 SetLastError(ERROR_MORE_DATA
);
1754 LPWSTR str
= pbFormat
;
1755 DWORD altNameEntrySize
;
1757 *pcbFormat
= bytesNeeded
;
1758 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1763 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1764 strcpyW(str
, accessDescrNum
);
1765 str
+= strlenW(accessDescrNum
);
1768 str
+= strlenW(aia
);
1769 strcpyW(str
, headingSep
);
1770 str
+= strlenW(headingSep
);
1771 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1773 strcpyW(str
, indent
);
1774 str
+= strlenW(indent
);
1776 strcpyW(str
, accessMethod
);
1777 str
+= strlenW(accessMethod
);
1778 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1782 str
+= strlenW(ocsp
);
1784 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1785 szOID_PKIX_CA_ISSUERS
))
1787 strcpyW(str
, caIssuers
);
1788 str
+= strlenW(caIssuers
);
1792 strcpyW(str
, unknown
);
1793 str
+= strlenW(unknown
);
1797 for (oidPtr
= info
->rgAccDescr
[i
].pszAccessMethod
;
1798 *oidPtr
; oidPtr
++, str
++)
1801 strcpyW(str
, accessMethodSep
);
1802 str
+= strlenW(accessMethodSep
);
1803 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1805 strcpyW(str
, indent
);
1806 str
+= strlenW(indent
);
1808 strcpyW(str
, accessLocation
);
1809 str
+= strlenW(accessLocation
);
1810 strcpyW(str
, locationSep
);
1811 str
+= strlenW(locationSep
);
1812 /* This overestimates the size available, but that
1813 * won't matter since we checked earlier whether enough
1814 * space for the entire string was available.
1816 altNameEntrySize
= bytesNeeded
;
1817 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1818 &info
->rgAccDescr
[i
].AccessLocation
, str
,
1821 str
+= altNameEntrySize
/ sizeof(WCHAR
) - 1;
1822 if (i
< info
->cAccDescr
- 1)
1824 strcpyW(str
, accessMethodSep
);
1825 str
+= strlenW(accessMethodSep
);
1836 static WCHAR keyCompromise
[MAX_STRING_RESOURCE_LEN
];
1837 static WCHAR caCompromise
[MAX_STRING_RESOURCE_LEN
];
1838 static WCHAR affiliationChanged
[MAX_STRING_RESOURCE_LEN
];
1839 static WCHAR superseded
[MAX_STRING_RESOURCE_LEN
];
1840 static WCHAR operationCeased
[MAX_STRING_RESOURCE_LEN
];
1841 static WCHAR certificateHold
[MAX_STRING_RESOURCE_LEN
];
1843 struct reason_map_entry
1849 static struct reason_map_entry reason_map
[] = {
1850 { CRL_REASON_KEY_COMPROMISE_FLAG
, keyCompromise
, IDS_REASON_KEY_COMPROMISE
},
1851 { CRL_REASON_CA_COMPROMISE_FLAG
, caCompromise
, IDS_REASON_CA_COMPROMISE
},
1852 { CRL_REASON_AFFILIATION_CHANGED_FLAG
, affiliationChanged
,
1853 IDS_REASON_AFFILIATION_CHANGED
},
1854 { CRL_REASON_SUPERSEDED_FLAG
, superseded
, IDS_REASON_SUPERSEDED
},
1855 { CRL_REASON_CESSATION_OF_OPERATION_FLAG
, operationCeased
,
1856 IDS_REASON_CESSATION_OF_OPERATION
},
1857 { CRL_REASON_CERTIFICATE_HOLD_FLAG
, certificateHold
,
1858 IDS_REASON_CERTIFICATE_HOLD
},
1861 static BOOL
CRYPT_FormatReason(DWORD dwFormatStrType
,
1862 const CRYPT_BIT_BLOB
*reasonFlags
, LPWSTR str
, DWORD
*pcbStr
)
1864 static const WCHAR sep
[] = { ',',' ',0 };
1865 static const WCHAR bitsFmt
[] = { ' ','(','%','0','2','x',')',0 };
1866 static BOOL stringsLoaded
= FALSE
;
1867 unsigned int i
, numReasons
= 0;
1869 DWORD bytesNeeded
= sizeof(WCHAR
);
1874 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1875 LoadStringW(hInstance
, reason_map
[i
].id
, reason_map
[i
].reason
,
1876 MAX_STRING_RESOURCE_LEN
);
1877 stringsLoaded
= TRUE
;
1879 /* No need to check reasonFlags->cbData, we already know it's positive.
1880 * Ignore any other bytes, as they're for undefined bits.
1882 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1884 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1886 bytesNeeded
+= strlenW(reason_map
[i
].reason
) * sizeof(WCHAR
);
1888 bytesNeeded
+= strlenW(sep
) * sizeof(WCHAR
);
1891 sprintfW(bits
, bitsFmt
, reasonFlags
->pbData
[0]);
1892 bytesNeeded
+= strlenW(bits
);
1894 *pcbStr
= bytesNeeded
;
1895 else if (*pcbStr
< bytesNeeded
)
1897 *pcbStr
= bytesNeeded
;
1898 SetLastError(ERROR_MORE_DATA
);
1903 *pcbStr
= bytesNeeded
;
1904 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1906 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1908 strcpyW(str
, reason_map
[i
].reason
);
1909 str
+= strlenW(reason_map
[i
].reason
);
1910 if (i
< sizeof(reason_map
) / sizeof(reason_map
[0]) - 1 &&
1914 str
+= strlenW(sep
);
1923 static WCHAR crlDistPoint
[MAX_STRING_RESOURCE_LEN
];
1924 static WCHAR distPointName
[MAX_STRING_RESOURCE_LEN
];
1925 static WCHAR fullName
[MAX_STRING_RESOURCE_LEN
];
1926 static WCHAR rdnName
[MAX_STRING_RESOURCE_LEN
];
1927 static WCHAR reason
[MAX_STRING_RESOURCE_LEN
];
1928 static WCHAR issuer
[MAX_STRING_RESOURCE_LEN
];
1930 static BOOL WINAPI
CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType
,
1931 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1932 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1935 CRL_DIST_POINTS_INFO
*info
;
1941 SetLastError(E_INVALIDARG
);
1944 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_CRL_DIST_POINTS
,
1945 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1947 static const WCHAR numFmt
[] = { '%','d',0 };
1948 static const WCHAR colon
[] = { ':',0 };
1949 static BOOL stringsLoaded
= FALSE
;
1950 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for NULL terminator */
1951 BOOL haveAnEntry
= FALSE
;
1952 LPCWSTR headingSep
, nameSep
;
1953 WCHAR distPointNum
[11];
1958 LoadStringW(hInstance
, IDS_CRL_DIST_POINT
, crlDistPoint
,
1959 sizeof(crlDistPoint
) / sizeof(crlDistPoint
[0]));
1960 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_NAME
, distPointName
,
1961 sizeof(distPointName
) / sizeof(distPointName
[0]));
1962 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_FULL_NAME
, fullName
,
1963 sizeof(fullName
) / sizeof(fullName
[0]));
1964 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_RDN_NAME
, rdnName
,
1965 sizeof(rdnName
) / sizeof(rdnName
[0]));
1966 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_REASON
, reason
,
1967 sizeof(reason
) / sizeof(reason
[0]));
1968 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_ISSUER
, issuer
,
1969 sizeof(issuer
) / sizeof(issuer
[0]));
1970 stringsLoaded
= TRUE
;
1972 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1975 nameSep
= colonCrlf
;
1979 headingSep
= colonSep
;
1983 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
1985 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
1987 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
1988 CRL_DIST_POINT_NO_NAME
)
1990 bytesNeeded
+= strlenW(distPointName
) * sizeof(WCHAR
);
1991 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1992 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
1993 CRL_DIST_POINT_FULL_NAME
)
1994 bytesNeeded
+= strlenW(fullName
) * sizeof(WCHAR
);
1996 bytesNeeded
+= strlenW(rdnName
) * sizeof(WCHAR
);
1997 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1998 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1999 bytesNeeded
+= 2 * strlenW(indent
) * sizeof(WCHAR
);
2000 /* The indent level (3) is higher than when used as the issuer,
2001 * because the name is subordinate to the name type (full vs.
2004 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
2005 &distPoint
->DistPointName
.u
.FullName
, NULL
, &size
);
2007 bytesNeeded
+= size
- sizeof(WCHAR
);
2010 else if (distPoint
->ReasonFlags
.cbData
)
2012 bytesNeeded
+= strlenW(reason
) * sizeof(WCHAR
);
2013 ret
= CRYPT_FormatReason(dwFormatStrType
,
2014 &distPoint
->ReasonFlags
, NULL
, &size
);
2016 bytesNeeded
+= size
- sizeof(WCHAR
);
2019 else if (distPoint
->CRLIssuer
.cAltEntry
)
2021 bytesNeeded
+= strlenW(issuer
) * sizeof(WCHAR
);
2022 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
2023 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
2024 &distPoint
->CRLIssuer
, NULL
, &size
);
2026 bytesNeeded
+= size
- sizeof(WCHAR
);
2031 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
2032 sprintfW(distPointNum
, numFmt
, i
+ 1);
2033 bytesNeeded
+= strlenW(distPointNum
) * sizeof(WCHAR
);
2034 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
2035 bytesNeeded
+= strlenW(crlDistPoint
) * sizeof(WCHAR
);
2036 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
2037 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2038 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
2043 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
2045 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
2046 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
2047 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
2049 *pcbFormat
= bytesNeeded
;
2050 else if (*pcbFormat
< bytesNeeded
)
2052 *pcbFormat
= bytesNeeded
;
2053 SetLastError(ERROR_MORE_DATA
);
2058 *pcbFormat
= bytesNeeded
;
2059 strcpyW(pbFormat
, infoNotAvailable
);
2065 *pcbFormat
= bytesNeeded
;
2066 else if (*pcbFormat
< bytesNeeded
)
2068 *pcbFormat
= bytesNeeded
;
2069 SetLastError(ERROR_MORE_DATA
);
2074 LPWSTR str
= pbFormat
;
2076 *pcbFormat
= bytesNeeded
;
2077 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2079 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
2082 sprintfW(distPointNum
, numFmt
, i
+ 1);
2083 strcpyW(str
, distPointNum
);
2084 str
+= strlenW(distPointNum
);
2086 strcpyW(str
, crlDistPoint
);
2087 str
+= strlenW(crlDistPoint
);
2088 strcpyW(str
, headingSep
);
2089 str
+= strlenW(headingSep
);
2090 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2092 strcpyW(str
, indent
);
2093 str
+= strlenW(indent
);
2095 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
2096 CRL_DIST_POINT_NO_NAME
)
2098 DWORD altNameSize
= bytesNeeded
;
2100 strcpyW(str
, distPointName
);
2101 str
+= strlenW(distPointName
);
2102 strcpyW(str
, nameSep
);
2103 str
+= strlenW(nameSep
);
2104 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2106 strcpyW(str
, indent
);
2107 str
+= strlenW(indent
);
2108 strcpyW(str
, indent
);
2109 str
+= strlenW(indent
);
2111 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
2112 CRL_DIST_POINT_FULL_NAME
)
2114 strcpyW(str
, fullName
);
2115 str
+= strlenW(fullName
);
2119 strcpyW(str
, rdnName
);
2120 str
+= strlenW(rdnName
);
2122 strcpyW(str
, nameSep
);
2123 str
+= strlenW(nameSep
);
2124 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
2125 &distPoint
->DistPointName
.u
.FullName
, str
,
2128 str
+= altNameSize
/ sizeof(WCHAR
) - 1;
2130 else if (distPoint
->ReasonFlags
.cbData
)
2132 DWORD reasonSize
= bytesNeeded
;
2134 strcpyW(str
, reason
);
2135 str
+= strlenW(reason
);
2136 ret
= CRYPT_FormatReason(dwFormatStrType
,
2137 &distPoint
->ReasonFlags
, str
, &reasonSize
);
2139 str
+= reasonSize
/ sizeof(WCHAR
) - 1;
2141 else if (distPoint
->CRLIssuer
.cAltEntry
)
2143 DWORD crlIssuerSize
= bytesNeeded
;
2145 strcpyW(str
, issuer
);
2146 str
+= strlenW(issuer
);
2147 strcpyW(str
, nameSep
);
2148 str
+= strlenW(nameSep
);
2149 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
2150 &distPoint
->CRLIssuer
, str
,
2153 str
+= crlIssuerSize
/ sizeof(WCHAR
) - 1;
2163 static BOOL WINAPI
CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType
,
2164 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2165 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2168 CERT_ENHKEY_USAGE
*usage
;
2174 SetLastError(E_INVALIDARG
);
2177 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ENHANCED_KEY_USAGE
,
2178 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &usage
, &size
)))
2180 WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
2182 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
2186 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2189 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2194 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2197 LoadStringW(hInstance
, IDS_USAGE_UNKNOWN
, unknown
,
2198 sizeof(unknown
) / sizeof(unknown
[0]));
2199 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2201 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2202 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2205 bytesNeeded
+= strlenW(info
->pwszName
) * sizeof(WCHAR
);
2207 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
2208 bytesNeeded
+= sizeof(WCHAR
); /* space */
2209 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
2210 bytesNeeded
+= strlen(usage
->rgpszUsageIdentifier
[i
]) *
2212 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
2213 if (i
< usage
->cUsageIdentifier
- 1)
2214 bytesNeeded
+= sepLen
;
2217 *pcbFormat
= bytesNeeded
;
2218 else if (*pcbFormat
< bytesNeeded
)
2220 *pcbFormat
= bytesNeeded
;
2221 SetLastError(ERROR_MORE_DATA
);
2226 LPWSTR str
= pbFormat
;
2228 *pcbFormat
= bytesNeeded
;
2229 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2231 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2232 usage
->rgpszUsageIdentifier
[i
],
2233 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2238 strcpyW(str
, info
->pwszName
);
2239 str
+= strlenW(info
->pwszName
);
2243 strcpyW(str
, unknown
);
2244 str
+= strlenW(unknown
);
2248 for (oidPtr
= usage
->rgpszUsageIdentifier
[i
]; *oidPtr
; oidPtr
++)
2252 if (i
< usage
->cUsageIdentifier
- 1)
2255 str
+= sepLen
/ sizeof(WCHAR
);
2264 static struct BitToString netscapeCertTypeMap
[] = {
2265 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_CLIENT
, { 0 } },
2266 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_SERVER
, { 0 } },
2267 { NETSCAPE_SMIME_CERT_TYPE
, IDS_NETSCAPE_SMIME
, { 0 } },
2268 { NETSCAPE_SIGN_CERT_TYPE
, IDS_NETSCAPE_SIGN
, { 0 } },
2269 { NETSCAPE_SSL_CA_CERT_TYPE
, IDS_NETSCAPE_SSL_CA
, { 0 } },
2270 { NETSCAPE_SMIME_CA_CERT_TYPE
, IDS_NETSCAPE_SMIME_CA
, { 0 } },
2271 { NETSCAPE_SIGN_CA_CERT_TYPE
, IDS_NETSCAPE_SIGN_CA
, { 0 } },
2274 static BOOL WINAPI
CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType
,
2275 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2276 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2280 CRYPT_BIT_BLOB
*bits
;
2285 SetLastError(E_INVALIDARG
);
2288 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BITS
,
2289 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
2291 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
2292 DWORD bytesNeeded
= sizeof(WCHAR
);
2294 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
2295 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
2296 if (!bits
->cbData
|| bits
->cbData
> 1)
2298 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
2300 *pcbFormat
= bytesNeeded
;
2301 else if (*pcbFormat
< bytesNeeded
)
2303 *pcbFormat
= bytesNeeded
;
2304 SetLastError(ERROR_MORE_DATA
);
2309 LPWSTR str
= pbFormat
;
2311 *pcbFormat
= bytesNeeded
;
2312 strcpyW(str
, infoNotAvailable
);
2317 static BOOL stringsLoaded
= FALSE
;
2324 for (i
= 0; i
< sizeof(netscapeCertTypeMap
) /
2325 sizeof(netscapeCertTypeMap
[0]); i
++)
2326 LoadStringW(hInstance
, netscapeCertTypeMap
[i
].id
,
2327 netscapeCertTypeMap
[i
].str
, MAX_STRING_RESOURCE_LEN
);
2328 stringsLoaded
= TRUE
;
2330 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2331 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2332 NULL
, &bitStringLen
, &first
);
2333 bytesNeeded
+= bitStringLen
;
2334 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
2335 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2336 bits
->cbData
, NULL
, &size
);
2337 bytesNeeded
+= size
;
2339 *pcbFormat
= bytesNeeded
;
2340 else if (*pcbFormat
< bytesNeeded
)
2342 *pcbFormat
= bytesNeeded
;
2343 SetLastError(ERROR_MORE_DATA
);
2348 LPWSTR str
= pbFormat
;
2350 bitStringLen
= bytesNeeded
;
2352 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2353 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2354 str
, &bitStringLen
, &first
);
2355 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
2358 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2359 bits
->cbData
, str
, &size
);
2360 str
+= size
/ sizeof(WCHAR
) - 1;
2370 static WCHAR financialCriteria
[MAX_STRING_RESOURCE_LEN
];
2371 static WCHAR available
[MAX_STRING_RESOURCE_LEN
];
2372 static WCHAR notAvailable
[MAX_STRING_RESOURCE_LEN
];
2373 static WCHAR meetsCriteria
[MAX_STRING_RESOURCE_LEN
];
2374 static WCHAR yes
[MAX_STRING_RESOURCE_LEN
];
2375 static WCHAR no
[MAX_STRING_RESOURCE_LEN
];
2377 static BOOL WINAPI
CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType
,
2378 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2379 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2382 SPC_FINANCIAL_CRITERIA criteria
;
2383 DWORD size
= sizeof(criteria
);
2388 SetLastError(E_INVALIDARG
);
2391 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
2392 SPC_FINANCIAL_CRITERIA_STRUCT
, pbEncoded
, cbEncoded
, 0, NULL
, &criteria
,
2395 static BOOL stringsLoaded
= FALSE
;
2396 DWORD bytesNeeded
= sizeof(WCHAR
);
2402 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA
, financialCriteria
,
2403 sizeof(financialCriteria
) / sizeof(financialCriteria
[0]));
2404 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_AVAILABLE
, available
,
2405 sizeof(available
) / sizeof(available
[0]));
2406 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE
,
2407 notAvailable
, sizeof(notAvailable
) / sizeof(notAvailable
[0]));
2408 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA
,
2409 meetsCriteria
, sizeof(meetsCriteria
) / sizeof(meetsCriteria
[0]));
2410 LoadStringW(hInstance
, IDS_YES
, yes
, sizeof(yes
) / sizeof(yes
[0]));
2411 LoadStringW(hInstance
, IDS_NO
, no
, sizeof(no
) / sizeof(no
[0]));
2412 stringsLoaded
= TRUE
;
2414 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2417 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2422 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2424 bytesNeeded
+= strlenW(financialCriteria
) * sizeof(WCHAR
);
2425 if (criteria
.fFinancialInfoAvailable
)
2427 bytesNeeded
+= strlenW(available
) * sizeof(WCHAR
);
2428 bytesNeeded
+= sepLen
;
2429 bytesNeeded
+= strlenW(meetsCriteria
) * sizeof(WCHAR
);
2430 if (criteria
.fMeetsCriteria
)
2431 bytesNeeded
+= strlenW(yes
) * sizeof(WCHAR
);
2433 bytesNeeded
+= strlenW(no
) * sizeof(WCHAR
);
2436 bytesNeeded
+= strlenW(notAvailable
) * sizeof(WCHAR
);
2438 *pcbFormat
= bytesNeeded
;
2439 else if (*pcbFormat
< bytesNeeded
)
2441 *pcbFormat
= bytesNeeded
;
2442 SetLastError(ERROR_MORE_DATA
);
2447 LPWSTR str
= pbFormat
;
2449 *pcbFormat
= bytesNeeded
;
2450 strcpyW(str
, financialCriteria
);
2451 str
+= strlenW(financialCriteria
);
2452 if (criteria
.fFinancialInfoAvailable
)
2454 strcpyW(str
, available
);
2455 str
+= strlenW(available
);
2457 str
+= sepLen
/ sizeof(WCHAR
);
2458 strcpyW(str
, meetsCriteria
);
2459 str
+= strlenW(meetsCriteria
);
2460 if (criteria
.fMeetsCriteria
)
2467 strcpyW(str
, notAvailable
);
2474 static BOOL WINAPI
CRYPT_FormatUnicodeString(DWORD dwCertEncodingType
,
2475 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2476 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2479 CERT_NAME_VALUE
*value
;
2485 SetLastError(E_INVALIDARG
);
2488 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_UNICODE_ANY_STRING
,
2489 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &value
, &size
)))
2492 *pcbFormat
= value
->Value
.cbData
;
2493 else if (*pcbFormat
< value
->Value
.cbData
)
2495 *pcbFormat
= value
->Value
.cbData
;
2496 SetLastError(ERROR_MORE_DATA
);
2501 LPWSTR str
= pbFormat
;
2503 *pcbFormat
= value
->Value
.cbData
;
2504 strcpyW(str
, (LPWSTR
)value
->Value
.pbData
);
2510 typedef BOOL (WINAPI
*CryptFormatObjectFunc
)(DWORD
, DWORD
, DWORD
, void *,
2511 LPCSTR
, const BYTE
*, DWORD
, void *, DWORD
*);
2513 static CryptFormatObjectFunc
CRYPT_GetBuiltinFormatFunction(DWORD encodingType
,
2514 DWORD formatStrType
, LPCSTR lpszStructType
)
2516 CryptFormatObjectFunc format
= NULL
;
2518 if ((encodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
)
2520 SetLastError(ERROR_FILE_NOT_FOUND
);
2523 if (IS_INTOID(lpszStructType
))
2525 switch (LOWORD(lpszStructType
))
2527 case LOWORD(X509_KEY_USAGE
):
2528 format
= CRYPT_FormatKeyUsage
;
2530 case LOWORD(X509_ALTERNATE_NAME
):
2531 format
= CRYPT_FormatAltName
;
2533 case LOWORD(X509_BASIC_CONSTRAINTS2
):
2534 format
= CRYPT_FormatBasicConstraints2
;
2536 case LOWORD(X509_AUTHORITY_KEY_ID2
):
2537 format
= CRYPT_FormatAuthorityKeyId2
;
2539 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
2540 format
= CRYPT_FormatAuthorityInfoAccess
;
2542 case LOWORD(X509_CRL_DIST_POINTS
):
2543 format
= CRYPT_FormatCRLDistPoints
;
2545 case LOWORD(X509_ENHANCED_KEY_USAGE
):
2546 format
= CRYPT_FormatEnhancedKeyUsage
;
2548 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT
):
2549 format
= CRYPT_FormatSpcFinancialCriteria
;
2553 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2554 format
= CRYPT_FormatAltName
;
2555 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2556 format
= CRYPT_FormatAltName
;
2557 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2558 format
= CRYPT_FormatKeyUsage
;
2559 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2560 format
= CRYPT_FormatAltName
;
2561 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2562 format
= CRYPT_FormatAltName
;
2563 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2564 format
= CRYPT_FormatBasicConstraints2
;
2565 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
2566 format
= CRYPT_FormatAuthorityInfoAccess
;
2567 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
2568 format
= CRYPT_FormatAuthorityKeyId2
;
2569 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2570 format
= CRYPT_FormatCRLDistPoints
;
2571 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2572 format
= CRYPT_FormatEnhancedKeyUsage
;
2573 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_CERT_TYPE
))
2574 format
= CRYPT_FormatNetscapeCertType
;
2575 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_BASE_URL
) ||
2576 !strcmp(lpszStructType
, szOID_NETSCAPE_REVOCATION_URL
) ||
2577 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_REVOCATION_URL
) ||
2578 !strcmp(lpszStructType
, szOID_NETSCAPE_CERT_RENEWAL_URL
) ||
2579 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_POLICY_URL
) ||
2580 !strcmp(lpszStructType
, szOID_NETSCAPE_SSL_SERVER_NAME
) ||
2581 !strcmp(lpszStructType
, szOID_NETSCAPE_COMMENT
))
2582 format
= CRYPT_FormatUnicodeString
;
2583 else if (!strcmp(lpszStructType
, SPC_FINANCIAL_CRITERIA_OBJID
))
2584 format
= CRYPT_FormatSpcFinancialCriteria
;
2588 BOOL WINAPI
CryptFormatObject(DWORD dwCertEncodingType
, DWORD dwFormatType
,
2589 DWORD dwFormatStrType
, void *pFormatStruct
, LPCSTR lpszStructType
,
2590 const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
, DWORD
*pcbFormat
)
2592 CryptFormatObjectFunc format
= NULL
;
2593 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2596 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType
,
2597 dwFormatType
, dwFormatStrType
, pFormatStruct
, debugstr_a(lpszStructType
),
2598 pbEncoded
, cbEncoded
, pbFormat
, pcbFormat
);
2600 if (!(format
= CRYPT_GetBuiltinFormatFunction(dwCertEncodingType
,
2601 dwFormatStrType
, lpszStructType
)))
2603 static HCRYPTOIDFUNCSET set
= NULL
;
2606 set
= CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC
, 0);
2607 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2608 (void **)&format
, &hFunc
);
2610 if (!format
&& (dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) ==
2611 X509_ASN_ENCODING
&& !(dwFormatStrType
& CRYPT_FORMAT_STR_NO_HEX
))
2612 format
= CRYPT_FormatHexString
;
2614 ret
= format(dwCertEncodingType
, dwFormatType
, dwFormatStrType
,
2615 pFormatStruct
, lpszStructType
, pbEncoded
, cbEncoded
, pbFormat
,
2618 CryptFreeOIDFunctionAddress(hFunc
, 0);