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
));
274 *ppvContext
= contextInterface
->duplicate(context
);
278 if (contextInterface
&& context
)
279 contextInterface
->free(context
);
280 if (blob
== &fileBlob
)
281 CryptMemFree(blob
->pbData
);
282 TRACE("returning %d\n", ret
);
286 static BOOL
CRYPT_QuerySerializedStoreObject(DWORD dwObjectType
,
287 const void *pvObject
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
288 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
290 LPCWSTR fileName
= pvObject
;
294 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
296 FIXME("unimplemented for non-file type %d\n", dwObjectType
);
297 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
300 TRACE("%s\n", debugstr_w(fileName
));
301 file
= CreateFileW(fileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
302 OPEN_EXISTING
, 0, NULL
);
303 if (file
!= INVALID_HANDLE_VALUE
)
305 HCERTSTORE store
= CertOpenStore(CERT_STORE_PROV_MEMORY
, 0, 0,
306 CERT_STORE_CREATE_NEW_FLAG
, NULL
);
308 ret
= CRYPT_ReadSerializedStoreFromFile(file
, store
);
311 if (pdwMsgAndCertEncodingType
)
312 *pdwMsgAndCertEncodingType
= X509_ASN_ENCODING
;
314 *pdwContentType
= CERT_QUERY_CONTENT_SERIALIZED_STORE
;
316 *phCertStore
= CertDuplicateStore(store
);
318 CertCloseStore(store
, 0);
321 TRACE("returning %d\n", ret
);
325 static BOOL
CRYPT_QuerySignedMessage(const CRYPT_DATA_BLOB
*blob
,
326 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, HCRYPTMSG
*phMsg
)
328 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
332 if ((msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
)))
334 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
337 DWORD type
, len
= sizeof(type
);
339 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
342 if (type
!= CMSG_SIGNED
)
344 SetLastError(ERROR_INVALID_DATA
);
352 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_SIGNED
, 0, NULL
,
356 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
367 if (pdwMsgAndCertEncodingType
)
368 *pdwMsgAndCertEncodingType
= encodingType
;
370 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
377 static BOOL
CRYPT_QueryUnsignedMessage(const CRYPT_DATA_BLOB
*blob
,
378 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, HCRYPTMSG
*phMsg
)
380 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
384 if ((msg
= CryptMsgOpenToDecode(encodingType
, 0, 0, 0, NULL
, NULL
)))
386 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
389 DWORD type
, len
= sizeof(type
);
391 ret
= CryptMsgGetParam(msg
, CMSG_TYPE_PARAM
, 0, &type
, &len
);
394 if (type
!= CMSG_DATA
)
396 SetLastError(ERROR_INVALID_DATA
);
404 msg
= CryptMsgOpenToDecode(encodingType
, 0, CMSG_DATA
, 0,
408 ret
= CryptMsgUpdate(msg
, blob
->pbData
, blob
->cbData
, TRUE
);
419 if (pdwMsgAndCertEncodingType
)
420 *pdwMsgAndCertEncodingType
= encodingType
;
422 *pdwContentType
= CERT_QUERY_CONTENT_PKCS7_SIGNED
;
429 /* Used to decode non-embedded messages */
430 static BOOL
CRYPT_QueryMessageObject(DWORD dwObjectType
, const void *pvObject
,
431 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
432 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
, DWORD
*pdwFormatType
,
433 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
436 const CERT_BLOB
*blob
;
438 HCRYPTMSG msg
= NULL
;
439 DWORD encodingType
= X509_ASN_ENCODING
| PKCS_7_ASN_ENCODING
;
440 DWORD formatType
= 0;
442 TRACE("(%d, %p, %08x, %08x, %p, %p, %p, %p, %p)\n", dwObjectType
, pvObject
,
443 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
444 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
, phCertStore
,
447 switch (dwObjectType
)
449 case CERT_QUERY_OBJECT_FILE
:
450 /* This isn't an embedded PKCS7 message, so just read the file
453 ret
= CRYPT_ReadBlobFromFile(pvObject
, &fileBlob
);
456 case CERT_QUERY_OBJECT_BLOB
:
461 SetLastError(E_INVALIDARG
); /* FIXME: is this the correct error? */
468 if (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BINARY
)
470 /* Try it first as a signed message */
471 if (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
472 ret
= CRYPT_QuerySignedMessage(blob
, pdwMsgAndCertEncodingType
,
473 pdwContentType
, &msg
);
474 /* Failing that, try as an unsigned message */
476 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
477 ret
= CRYPT_QueryUnsignedMessage(blob
, pdwMsgAndCertEncodingType
,
478 pdwContentType
, &msg
);
480 formatType
= CERT_QUERY_FORMAT_BINARY
;
483 (dwExpectedFormatTypeFlags
& CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED
))
485 CRYPT_DATA_BLOB trimmed
= { blob
->cbData
, blob
->pbData
};
486 CRYPT_DATA_BLOB decoded
;
488 while (trimmed
.cbData
&& !trimmed
.pbData
[trimmed
.cbData
- 1])
490 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
, trimmed
.cbData
,
491 CRYPT_STRING_BASE64_ANY
, NULL
, &decoded
.cbData
, NULL
, NULL
);
494 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
497 ret
= CryptStringToBinaryA((LPSTR
)trimmed
.pbData
,
498 trimmed
.cbData
, CRYPT_STRING_BASE64_ANY
, decoded
.pbData
,
499 &decoded
.cbData
, NULL
, NULL
);
502 /* Try it first as a signed message */
503 if (dwExpectedContentTypeFlags
&
504 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
505 ret
= CRYPT_QuerySignedMessage(&decoded
,
506 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
507 /* Failing that, try as an unsigned message */
508 if (!ret
&& (dwExpectedContentTypeFlags
&
509 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
510 ret
= CRYPT_QueryUnsignedMessage(&decoded
,
511 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
513 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
515 CryptMemFree(decoded
.pbData
);
520 if (!ret
&& !(blob
->cbData
% sizeof(WCHAR
)))
522 CRYPT_DATA_BLOB decoded
;
523 LPWSTR str
= (LPWSTR
)blob
->pbData
;
524 DWORD strLen
= blob
->cbData
/ sizeof(WCHAR
);
526 /* Try again, assuming the input string is UTF-16 base64 */
527 while (strLen
&& !str
[strLen
- 1])
529 ret
= CryptStringToBinaryW(str
, strLen
, CRYPT_STRING_BASE64_ANY
,
530 NULL
, &decoded
.cbData
, NULL
, NULL
);
533 decoded
.pbData
= CryptMemAlloc(decoded
.cbData
);
536 ret
= CryptStringToBinaryW(str
, strLen
,
537 CRYPT_STRING_BASE64_ANY
, decoded
.pbData
, &decoded
.cbData
,
541 /* Try it first as a signed message */
542 if (dwExpectedContentTypeFlags
&
543 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
)
544 ret
= CRYPT_QuerySignedMessage(&decoded
,
545 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
546 /* Failing that, try as an unsigned message */
547 if (!ret
&& (dwExpectedContentTypeFlags
&
548 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
))
549 ret
= CRYPT_QueryUnsignedMessage(&decoded
,
550 pdwMsgAndCertEncodingType
, pdwContentType
, &msg
);
552 formatType
= CERT_QUERY_FORMAT_BASE64_ENCODED
;
554 CryptMemFree(decoded
.pbData
);
564 *pdwFormatType
= formatType
;
568 *phCertStore
= CertOpenStore(CERT_STORE_PROV_MSG
, encodingType
, 0,
571 if (blob
== &fileBlob
)
572 CryptMemFree(blob
->pbData
);
573 TRACE("returning %d\n", ret
);
577 static BOOL
CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType
,
578 const void *pvObject
, DWORD dwExpectedContentTypeFlags
,
579 DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
580 HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
)
586 TRACE("%s\n", debugstr_w(pvObject
));
588 if (dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
590 WARN("don't know what to do for type %d embedded signed messages\n",
592 SetLastError(E_INVALIDARG
);
595 file
= CreateFileW(pvObject
, GENERIC_READ
, FILE_SHARE_READ
,
596 NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
597 if (file
!= INVALID_HANDLE_VALUE
)
599 ret
= CryptSIPRetrieveSubjectGuid(pvObject
, file
, &subject
);
602 SIP_DISPATCH_INFO sip
;
604 memset(&sip
, 0, sizeof(sip
));
605 sip
.cbSize
= sizeof(sip
);
606 ret
= CryptSIPLoad(&subject
, 0, &sip
);
609 SIP_SUBJECTINFO subjectInfo
;
613 memset(&subjectInfo
, 0, sizeof(subjectInfo
));
614 subjectInfo
.cbSize
= sizeof(subjectInfo
);
615 subjectInfo
.pgSubjectType
= &subject
;
616 subjectInfo
.hFile
= file
;
617 subjectInfo
.pwsFileName
= pvObject
;
618 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0, &blob
.cbData
,
622 blob
.pbData
= CryptMemAlloc(blob
.cbData
);
625 ret
= sip
.pfGet(&subjectInfo
, &encodingType
, 0,
626 &blob
.cbData
, blob
.pbData
);
629 ret
= CRYPT_QueryMessageObject(
630 CERT_QUERY_OBJECT_BLOB
, &blob
,
631 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
,
632 CERT_QUERY_FORMAT_FLAG_BINARY
,
633 pdwMsgAndCertEncodingType
, NULL
, NULL
,
635 if (ret
&& pdwContentType
)
637 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
;
639 CryptMemFree(blob
.pbData
);
643 SetLastError(ERROR_OUTOFMEMORY
);
651 TRACE("returning %d\n", ret
);
655 BOOL WINAPI
CryptQueryObject(DWORD dwObjectType
, const void *pvObject
,
656 DWORD dwExpectedContentTypeFlags
, DWORD dwExpectedFormatTypeFlags
,
657 DWORD dwFlags
, DWORD
*pdwMsgAndCertEncodingType
, DWORD
*pdwContentType
,
658 DWORD
*pdwFormatType
, HCERTSTORE
*phCertStore
, HCRYPTMSG
*phMsg
,
659 const void **ppvContext
)
661 static const DWORD unimplementedTypes
=
662 CERT_QUERY_CONTENT_FLAG_PKCS10
| CERT_QUERY_CONTENT_FLAG_PFX
|
663 CERT_QUERY_CONTENT_FLAG_CERT_PAIR
;
666 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
667 dwObjectType
, pvObject
, dwExpectedContentTypeFlags
,
668 dwExpectedFormatTypeFlags
, dwFlags
, pdwMsgAndCertEncodingType
,
669 pdwContentType
, pdwFormatType
, phCertStore
, phMsg
, ppvContext
);
671 if (dwObjectType
!= CERT_QUERY_OBJECT_BLOB
&&
672 dwObjectType
!= CERT_QUERY_OBJECT_FILE
)
674 WARN("unsupported type %d\n", dwObjectType
);
675 SetLastError(E_INVALIDARG
);
680 WARN("missing required argument\n");
681 SetLastError(E_INVALIDARG
);
684 if (dwExpectedContentTypeFlags
& unimplementedTypes
)
685 WARN("unimplemented for types %08x\n",
686 dwExpectedContentTypeFlags
& unimplementedTypes
);
689 *pdwFormatType
= CERT_QUERY_FORMAT_BINARY
;
698 if ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CERT
) ||
699 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CRL
) ||
700 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_CTL
))
702 ret
= CRYPT_QueryContextObject(dwObjectType
, pvObject
,
703 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
704 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
, phCertStore
,
708 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE
))
710 ret
= CRYPT_QuerySerializedStoreObject(dwObjectType
, pvObject
,
711 pdwMsgAndCertEncodingType
, pdwContentType
, phCertStore
, phMsg
);
714 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT
) ||
715 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL
) ||
716 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL
)))
718 ret
= CRYPT_QuerySerializedContextObject(dwObjectType
, pvObject
,
719 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
720 phCertStore
, ppvContext
);
723 ((dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED
) ||
724 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED
)))
726 ret
= CRYPT_QueryMessageObject(dwObjectType
, pvObject
,
727 dwExpectedContentTypeFlags
, dwExpectedFormatTypeFlags
,
728 pdwMsgAndCertEncodingType
, pdwContentType
, pdwFormatType
,
732 (dwExpectedContentTypeFlags
& CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED
))
734 ret
= CRYPT_QueryEmbeddedMessageObject(dwObjectType
, pvObject
,
735 dwExpectedContentTypeFlags
, pdwMsgAndCertEncodingType
, pdwContentType
,
739 SetLastError(CRYPT_E_NO_MATCH
);
740 TRACE("returning %d\n", ret
);
744 static BOOL WINAPI
CRYPT_FormatHexString(DWORD dwCertEncodingType
,
745 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
746 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
753 bytesNeeded
= (cbEncoded
* 3) * sizeof(WCHAR
);
755 bytesNeeded
= sizeof(WCHAR
);
758 *pcbFormat
= bytesNeeded
;
761 else if (*pcbFormat
< bytesNeeded
)
763 *pcbFormat
= bytesNeeded
;
764 SetLastError(ERROR_MORE_DATA
);
769 static const WCHAR fmt
[] = { '%','0','2','x',' ',0 };
770 static const WCHAR endFmt
[] = { '%','0','2','x',0 };
772 LPWSTR ptr
= pbFormat
;
774 *pcbFormat
= bytesNeeded
;
777 for (i
= 0; i
< cbEncoded
; i
++)
779 if (i
< cbEncoded
- 1)
780 ptr
+= sprintfW(ptr
, fmt
, pbEncoded
[i
]);
782 ptr
+= sprintfW(ptr
, endFmt
, pbEncoded
[i
]);
792 #define MAX_STRING_RESOURCE_LEN 128
794 static const WCHAR commaSpace
[] = { ',',' ',0 };
800 WCHAR str
[MAX_STRING_RESOURCE_LEN
];
803 static BOOL
CRYPT_FormatBits(BYTE bits
, const struct BitToString
*map
,
804 DWORD mapEntries
, void *pbFormat
, DWORD
*pcbFormat
, BOOL
*first
)
806 DWORD bytesNeeded
= sizeof(WCHAR
);
808 BOOL ret
= TRUE
, localFirst
= *first
;
810 for (i
= 0; i
< mapEntries
; i
++)
811 if (bits
& map
[i
].bit
)
814 bytesNeeded
+= strlenW(commaSpace
) * sizeof(WCHAR
);
816 bytesNeeded
+= strlenW(map
[i
].str
) * sizeof(WCHAR
);
821 *pcbFormat
= bytesNeeded
;
823 else if (*pcbFormat
< bytesNeeded
)
826 *pcbFormat
= bytesNeeded
;
827 SetLastError(ERROR_MORE_DATA
);
832 LPWSTR str
= pbFormat
;
835 *pcbFormat
= bytesNeeded
;
836 for (i
= 0; i
< mapEntries
; i
++)
837 if (bits
& map
[i
].bit
)
841 strcpyW(str
, commaSpace
);
842 str
+= strlenW(commaSpace
);
845 strcpyW(str
, map
[i
].str
);
846 str
+= strlenW(map
[i
].str
);
853 static struct BitToString keyUsageByte0Map
[] = {
854 { CERT_DIGITAL_SIGNATURE_KEY_USAGE
, IDS_DIGITAL_SIGNATURE
, { 0 } },
855 { CERT_NON_REPUDIATION_KEY_USAGE
, IDS_NON_REPUDIATION
, { 0 } },
856 { CERT_KEY_ENCIPHERMENT_KEY_USAGE
, IDS_KEY_ENCIPHERMENT
, { 0 } },
857 { CERT_DATA_ENCIPHERMENT_KEY_USAGE
, IDS_DATA_ENCIPHERMENT
, { 0 } },
858 { CERT_KEY_AGREEMENT_KEY_USAGE
, IDS_KEY_AGREEMENT
, { 0 } },
859 { CERT_KEY_CERT_SIGN_KEY_USAGE
, IDS_CERT_SIGN
, { 0 } },
860 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE
, IDS_OFFLINE_CRL_SIGN
, { 0 } },
861 { CERT_CRL_SIGN_KEY_USAGE
, IDS_CRL_SIGN
, { 0 } },
862 { CERT_ENCIPHER_ONLY_KEY_USAGE
, IDS_ENCIPHER_ONLY
, { 0 } },
864 static struct BitToString keyUsageByte1Map
[] = {
865 { CERT_DECIPHER_ONLY_KEY_USAGE
, IDS_DECIPHER_ONLY
, { 0 } },
868 static BOOL WINAPI
CRYPT_FormatKeyUsage(DWORD dwCertEncodingType
,
869 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
870 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
874 CRYPT_BIT_BLOB
*bits
;
879 SetLastError(E_INVALIDARG
);
882 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_KEY_USAGE
,
883 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
885 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
886 DWORD bytesNeeded
= sizeof(WCHAR
);
888 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
889 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
890 if (!bits
->cbData
|| bits
->cbData
> 2)
892 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
894 *pcbFormat
= bytesNeeded
;
895 else if (*pcbFormat
< bytesNeeded
)
897 *pcbFormat
= bytesNeeded
;
898 SetLastError(ERROR_MORE_DATA
);
903 LPWSTR str
= pbFormat
;
905 *pcbFormat
= bytesNeeded
;
906 strcpyW(str
, infoNotAvailable
);
911 static BOOL stringsLoaded
= FALSE
;
919 i
< sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]);
921 LoadStringW(hInstance
, keyUsageByte0Map
[i
].id
,
922 keyUsageByte0Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
924 i
< sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]);
926 LoadStringW(hInstance
, keyUsageByte1Map
[i
].id
,
927 keyUsageByte1Map
[i
].str
, MAX_STRING_RESOURCE_LEN
);
928 stringsLoaded
= TRUE
;
930 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
931 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
932 NULL
, &bitStringLen
, &first
);
933 bytesNeeded
+= bitStringLen
;
934 if (bits
->cbData
== 2)
936 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
937 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
938 NULL
, &bitStringLen
, &first
);
939 bytesNeeded
+= bitStringLen
;
941 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
942 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
943 bits
->cbData
, NULL
, &size
);
946 *pcbFormat
= bytesNeeded
;
947 else if (*pcbFormat
< bytesNeeded
)
949 *pcbFormat
= bytesNeeded
;
950 SetLastError(ERROR_MORE_DATA
);
955 LPWSTR str
= pbFormat
;
957 bitStringLen
= bytesNeeded
;
959 CRYPT_FormatBits(bits
->pbData
[0], keyUsageByte0Map
,
960 sizeof(keyUsageByte0Map
) / sizeof(keyUsageByte0Map
[0]),
961 str
, &bitStringLen
, &first
);
962 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
963 if (bits
->cbData
== 2)
965 bitStringLen
= bytesNeeded
;
966 CRYPT_FormatBits(bits
->pbData
[1], keyUsageByte1Map
,
967 sizeof(keyUsageByte1Map
) / sizeof(keyUsageByte1Map
[0]),
968 str
, &bitStringLen
, &first
);
969 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
973 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
974 bits
->cbData
, str
, &size
);
975 str
+= size
/ sizeof(WCHAR
) - 1;
985 static const WCHAR crlf
[] = { '\r','\n',0 };
987 static WCHAR subjectTypeHeader
[MAX_STRING_RESOURCE_LEN
];
988 static WCHAR subjectTypeCA
[MAX_STRING_RESOURCE_LEN
];
989 static WCHAR subjectTypeEndCert
[MAX_STRING_RESOURCE_LEN
];
990 static WCHAR pathLengthHeader
[MAX_STRING_RESOURCE_LEN
];
992 static BOOL WINAPI
CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType
,
993 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
994 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
998 CERT_BASIC_CONSTRAINTS2_INFO
*info
;
1003 SetLastError(E_INVALIDARG
);
1006 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BASIC_CONSTRAINTS2
,
1007 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1009 static const WCHAR pathFmt
[] = { '%','d',0 };
1010 static BOOL stringsLoaded
= FALSE
;
1011 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
1012 WCHAR pathLength
[MAX_STRING_RESOURCE_LEN
];
1013 LPCWSTR sep
, subjectType
;
1016 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1019 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1024 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1029 LoadStringW(hInstance
, IDS_SUBJECT_TYPE
, subjectTypeHeader
,
1030 sizeof(subjectTypeHeader
) / sizeof(subjectTypeHeader
[0]));
1031 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_CA
, subjectTypeCA
,
1032 sizeof(subjectTypeCA
) / sizeof(subjectTypeCA
[0]));
1033 LoadStringW(hInstance
, IDS_SUBJECT_TYPE_END_CERT
,
1035 sizeof(subjectTypeEndCert
) / sizeof(subjectTypeEndCert
[0]));
1036 LoadStringW(hInstance
, IDS_PATH_LENGTH
, pathLengthHeader
,
1037 sizeof(pathLengthHeader
) / sizeof(pathLengthHeader
[0]));
1038 stringsLoaded
= TRUE
;
1040 bytesNeeded
+= strlenW(subjectTypeHeader
) * sizeof(WCHAR
);
1042 subjectType
= subjectTypeCA
;
1044 subjectType
= subjectTypeEndCert
;
1045 bytesNeeded
+= strlenW(subjectType
) * sizeof(WCHAR
);
1046 bytesNeeded
+= sepLen
;
1047 bytesNeeded
+= strlenW(pathLengthHeader
) * sizeof(WCHAR
);
1048 if (info
->fPathLenConstraint
)
1049 sprintfW(pathLength
, pathFmt
, info
->dwPathLenConstraint
);
1051 LoadStringW(hInstance
, IDS_PATH_LENGTH_NONE
, pathLength
,
1052 sizeof(pathLength
) / sizeof(pathLength
[0]));
1053 bytesNeeded
+= strlenW(pathLength
) * sizeof(WCHAR
);
1055 *pcbFormat
= bytesNeeded
;
1056 else if (*pcbFormat
< bytesNeeded
)
1058 *pcbFormat
= bytesNeeded
;
1059 SetLastError(ERROR_MORE_DATA
);
1064 LPWSTR str
= pbFormat
;
1066 *pcbFormat
= bytesNeeded
;
1067 strcpyW(str
, subjectTypeHeader
);
1068 str
+= strlenW(subjectTypeHeader
);
1069 strcpyW(str
, subjectType
);
1070 str
+= strlenW(subjectType
);
1072 str
+= sepLen
/ sizeof(WCHAR
);
1073 strcpyW(str
, pathLengthHeader
);
1074 str
+= strlenW(pathLengthHeader
);
1075 strcpyW(str
, pathLength
);
1076 str
+= strlenW(pathLength
);
1083 static BOOL
CRYPT_FormatHexStringWithPrefix(const CRYPT_DATA_BLOB
*blob
, int id
,
1084 LPWSTR str
, DWORD
*pcbStr
)
1086 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1090 LoadStringW(hInstance
, id
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1091 CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
1092 blob
->pbData
, blob
->cbData
, NULL
, &bytesNeeded
);
1093 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1096 *pcbStr
= bytesNeeded
;
1099 else if (*pcbStr
< bytesNeeded
)
1101 *pcbStr
= bytesNeeded
;
1102 SetLastError(ERROR_MORE_DATA
);
1107 *pcbStr
= bytesNeeded
;
1109 str
+= strlenW(str
);
1110 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
1111 ret
= CRYPT_FormatHexString(X509_ASN_ENCODING
, 0, 0, NULL
, NULL
,
1112 blob
->pbData
, blob
->cbData
, str
, &bytesNeeded
);
1117 static BOOL
CRYPT_FormatKeyId(const CRYPT_DATA_BLOB
*keyId
, LPWSTR str
,
1120 return CRYPT_FormatHexStringWithPrefix(keyId
, IDS_KEY_ID
, str
, pcbStr
);
1123 static BOOL
CRYPT_FormatCertSerialNumber(const CRYPT_DATA_BLOB
*serialNum
, LPWSTR str
,
1126 return CRYPT_FormatHexStringWithPrefix(serialNum
, IDS_CERT_SERIAL_NUMBER
,
1130 static const WCHAR indent
[] = { ' ',' ',' ',' ',' ',0 };
1131 static const WCHAR colonCrlf
[] = { ':','\r','\n',0 };
1133 static BOOL
CRYPT_FormatAltNameEntry(DWORD dwFormatStrType
, DWORD indentLevel
,
1134 CERT_ALT_NAME_ENTRY
*entry
, LPWSTR str
, DWORD
*pcbStr
)
1137 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1138 WCHAR mask
[MAX_STRING_RESOURCE_LEN
];
1139 WCHAR ipAddrBuf
[32];
1141 DWORD bytesNeeded
= sizeof(WCHAR
);
1142 DWORD strType
= CERT_X500_NAME_STR
| CERT_NAME_STR_REVERSE_FLAG
;
1144 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1145 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1146 switch (entry
->dwAltNameChoice
)
1148 case CERT_ALT_NAME_RFC822_NAME
:
1149 LoadStringW(hInstance
, IDS_ALT_NAME_RFC822_NAME
, buf
,
1150 sizeof(buf
) / sizeof(buf
[0]));
1151 bytesNeeded
+= strlenW(entry
->u
.pwszRfc822Name
) * sizeof(WCHAR
);
1154 case CERT_ALT_NAME_DNS_NAME
:
1155 LoadStringW(hInstance
, IDS_ALT_NAME_DNS_NAME
, buf
,
1156 sizeof(buf
) / sizeof(buf
[0]));
1157 bytesNeeded
+= strlenW(entry
->u
.pwszDNSName
) * sizeof(WCHAR
);
1160 case CERT_ALT_NAME_DIRECTORY_NAME
:
1162 DWORD directoryNameLen
;
1164 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1165 strType
|= CERT_NAME_STR_CRLF_FLAG
;
1166 directoryNameLen
= cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1167 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, NULL
, 0);
1168 LoadStringW(hInstance
, IDS_ALT_NAME_DIRECTORY_NAME
, buf
,
1169 sizeof(buf
) / sizeof(buf
[0]));
1170 bytesNeeded
+= (directoryNameLen
- 1) * sizeof(WCHAR
);
1171 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1172 bytesNeeded
+= strlenW(colonCrlf
) * sizeof(WCHAR
);
1174 bytesNeeded
+= sizeof(WCHAR
); /* '=' */
1178 case CERT_ALT_NAME_URL
:
1179 LoadStringW(hInstance
, IDS_ALT_NAME_URL
, buf
,
1180 sizeof(buf
) / sizeof(buf
[0]));
1181 bytesNeeded
+= strlenW(entry
->u
.pwszURL
) * sizeof(WCHAR
);
1184 case CERT_ALT_NAME_IP_ADDRESS
:
1186 static const WCHAR ipAddrWithMaskFmt
[] = { '%','d','.','%','d','.',
1187 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1189 static const WCHAR ipAddrFmt
[] = { '%','d','.','%','d','.','%','d',
1192 LoadStringW(hInstance
, IDS_ALT_NAME_IP_ADDRESS
, buf
,
1193 sizeof(buf
) / sizeof(buf
[0]));
1194 if (entry
->u
.IPAddress
.cbData
== 8)
1196 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1198 LoadStringW(hInstance
, IDS_ALT_NAME_MASK
, mask
,
1199 sizeof(mask
) / sizeof(mask
[0]));
1200 bytesNeeded
+= strlenW(mask
) * sizeof(WCHAR
);
1201 sprintfW(ipAddrBuf
, ipAddrFmt
,
1202 entry
->u
.IPAddress
.pbData
[0],
1203 entry
->u
.IPAddress
.pbData
[1],
1204 entry
->u
.IPAddress
.pbData
[2],
1205 entry
->u
.IPAddress
.pbData
[3]);
1206 bytesNeeded
+= strlenW(ipAddrBuf
) * sizeof(WCHAR
);
1207 /* indent again, for the mask line */
1208 bytesNeeded
+= indentLevel
* strlenW(indent
) * sizeof(WCHAR
);
1209 sprintfW(maskBuf
, ipAddrFmt
,
1210 entry
->u
.IPAddress
.pbData
[4],
1211 entry
->u
.IPAddress
.pbData
[5],
1212 entry
->u
.IPAddress
.pbData
[6],
1213 entry
->u
.IPAddress
.pbData
[7]);
1214 bytesNeeded
+= strlenW(maskBuf
) * sizeof(WCHAR
);
1215 bytesNeeded
+= strlenW(crlf
) * sizeof(WCHAR
);
1219 sprintfW(ipAddrBuf
, ipAddrWithMaskFmt
,
1220 entry
->u
.IPAddress
.pbData
[0],
1221 entry
->u
.IPAddress
.pbData
[1],
1222 entry
->u
.IPAddress
.pbData
[2],
1223 entry
->u
.IPAddress
.pbData
[3],
1224 entry
->u
.IPAddress
.pbData
[4],
1225 entry
->u
.IPAddress
.pbData
[5],
1226 entry
->u
.IPAddress
.pbData
[6],
1227 entry
->u
.IPAddress
.pbData
[7]);
1228 bytesNeeded
+= (strlenW(ipAddrBuf
) + 1) * sizeof(WCHAR
);
1234 FIXME("unknown IP address format (%d bytes)\n",
1235 entry
->u
.IPAddress
.cbData
);
1241 FIXME("unimplemented for %d\n", entry
->dwAltNameChoice
);
1246 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1248 *pcbStr
= bytesNeeded
;
1249 else if (*pcbStr
< bytesNeeded
)
1251 *pcbStr
= bytesNeeded
;
1252 SetLastError(ERROR_MORE_DATA
);
1259 *pcbStr
= bytesNeeded
;
1260 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1262 for (i
= 0; i
< indentLevel
; i
++)
1264 strcpyW(str
, indent
);
1265 str
+= strlenW(indent
);
1269 str
+= strlenW(str
);
1270 switch (entry
->dwAltNameChoice
)
1272 case CERT_ALT_NAME_RFC822_NAME
:
1273 case CERT_ALT_NAME_DNS_NAME
:
1274 case CERT_ALT_NAME_URL
:
1275 strcpyW(str
, entry
->u
.pwszURL
);
1277 case CERT_ALT_NAME_DIRECTORY_NAME
:
1278 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1280 strcpyW(str
, colonCrlf
);
1281 str
+= strlenW(colonCrlf
);
1285 cert_name_to_str_with_indent(X509_ASN_ENCODING
,
1286 indentLevel
+ 1, &entry
->u
.DirectoryName
, strType
, str
,
1287 bytesNeeded
/ sizeof(WCHAR
));
1289 case CERT_ALT_NAME_IP_ADDRESS
:
1290 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1292 strcpyW(str
, ipAddrBuf
);
1293 str
+= strlenW(ipAddrBuf
);
1295 str
+= strlenW(crlf
);
1296 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1298 for (i
= 0; i
< indentLevel
; i
++)
1300 strcpyW(str
, indent
);
1301 str
+= strlenW(indent
);
1305 str
+= strlenW(mask
);
1306 strcpyW(str
, maskBuf
);
1309 strcpyW(str
, ipAddrBuf
);
1317 static BOOL
CRYPT_FormatAltNameInfo(DWORD dwFormatStrType
, DWORD indentLevel
,
1318 CERT_ALT_NAME_INFO
*name
, LPWSTR str
, DWORD
*pcbStr
)
1320 DWORD i
, size
, bytesNeeded
= 0;
1325 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1328 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1333 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1336 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1338 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1339 &name
->rgAltEntry
[i
], NULL
, &size
);
1342 bytesNeeded
+= size
- sizeof(WCHAR
);
1343 if (i
< name
->cAltEntry
- 1)
1344 bytesNeeded
+= sepLen
;
1349 bytesNeeded
+= sizeof(WCHAR
);
1351 *pcbStr
= bytesNeeded
;
1352 else if (*pcbStr
< bytesNeeded
)
1354 *pcbStr
= bytesNeeded
;
1355 SetLastError(ERROR_MORE_DATA
);
1360 *pcbStr
= bytesNeeded
;
1361 for (i
= 0; ret
&& i
< name
->cAltEntry
; i
++)
1363 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, indentLevel
,
1364 &name
->rgAltEntry
[i
], str
, &size
);
1367 str
+= size
/ sizeof(WCHAR
) - 1;
1368 if (i
< name
->cAltEntry
- 1)
1371 str
+= sepLen
/ sizeof(WCHAR
);
1380 static const WCHAR colonSep
[] = { ':',' ',0 };
1382 static BOOL WINAPI
CRYPT_FormatAltName(DWORD dwCertEncodingType
,
1383 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1384 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1388 CERT_ALT_NAME_INFO
*info
;
1391 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ALTERNATE_NAME
,
1392 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1394 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 0, info
, pbFormat
, pcbFormat
);
1400 static BOOL
CRYPT_FormatCertIssuer(DWORD dwFormatStrType
,
1401 CERT_ALT_NAME_INFO
*issuer
, LPWSTR str
, DWORD
*pcbStr
)
1403 WCHAR buf
[MAX_STRING_RESOURCE_LEN
];
1404 DWORD bytesNeeded
, sepLen
;
1408 LoadStringW(hInstance
, IDS_CERT_ISSUER
, buf
, sizeof(buf
) / sizeof(buf
[0]));
1409 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, NULL
,
1411 bytesNeeded
+= strlenW(buf
) * sizeof(WCHAR
);
1412 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1415 sepLen
= strlenW(colonCrlf
) * sizeof(WCHAR
);
1420 sepLen
= strlenW(colonSep
) * sizeof(WCHAR
);
1422 bytesNeeded
+= sepLen
;
1426 *pcbStr
= bytesNeeded
;
1427 else if (*pcbStr
< bytesNeeded
)
1429 *pcbStr
= bytesNeeded
;
1430 SetLastError(ERROR_MORE_DATA
);
1435 *pcbStr
= bytesNeeded
;
1437 bytesNeeded
-= strlenW(str
) * sizeof(WCHAR
);
1438 str
+= strlenW(str
);
1440 str
+= sepLen
/ sizeof(WCHAR
);
1441 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 1, issuer
, str
,
1448 static BOOL WINAPI
CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType
,
1449 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1450 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1453 CERT_AUTHORITY_KEY_ID2_INFO
*info
;
1459 SetLastError(E_INVALIDARG
);
1462 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_AUTHORITY_KEY_ID2
,
1463 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1465 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
1468 BOOL needSeparator
= FALSE
;
1470 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1473 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
1478 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
1481 if (info
->KeyId
.cbData
)
1483 needSeparator
= TRUE
;
1484 ret
= CRYPT_FormatKeyId(&info
->KeyId
, NULL
, &size
);
1487 /* don't include NULL-terminator more than once */
1488 bytesNeeded
+= size
- sizeof(WCHAR
);
1491 if (info
->AuthorityCertIssuer
.cAltEntry
)
1494 bytesNeeded
+= sepLen
;
1495 needSeparator
= TRUE
;
1496 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1497 &info
->AuthorityCertIssuer
, NULL
, &size
);
1500 /* don't include NULL-terminator more than once */
1501 bytesNeeded
+= size
- sizeof(WCHAR
);
1504 if (info
->AuthorityCertSerialNumber
.cbData
)
1507 bytesNeeded
+= sepLen
;
1508 ret
= CRYPT_FormatCertSerialNumber(
1509 &info
->AuthorityCertSerialNumber
, NULL
, &size
);
1512 /* don't include NULL-terminator more than once */
1513 bytesNeeded
+= size
- sizeof(WCHAR
);
1519 *pcbFormat
= bytesNeeded
;
1520 else if (*pcbFormat
< bytesNeeded
)
1522 *pcbFormat
= bytesNeeded
;
1523 SetLastError(ERROR_MORE_DATA
);
1528 LPWSTR str
= pbFormat
;
1530 *pcbFormat
= bytesNeeded
;
1531 needSeparator
= FALSE
;
1532 if (info
->KeyId
.cbData
)
1534 needSeparator
= TRUE
;
1535 /* Overestimate size available, it's already been checked
1539 ret
= CRYPT_FormatKeyId(&info
->KeyId
, str
, &size
);
1541 str
+= size
/ sizeof(WCHAR
) - 1;
1543 if (info
->AuthorityCertIssuer
.cAltEntry
)
1548 str
+= sepLen
/ sizeof(WCHAR
);
1550 needSeparator
= TRUE
;
1551 /* Overestimate size available, it's already been checked
1555 ret
= CRYPT_FormatCertIssuer(dwFormatStrType
,
1556 &info
->AuthorityCertIssuer
, str
, &size
);
1558 str
+= size
/ sizeof(WCHAR
) - 1;
1560 if (info
->AuthorityCertSerialNumber
.cbData
)
1565 str
+= sepLen
/ sizeof(WCHAR
);
1567 /* Overestimate size available, it's already been checked
1571 ret
= CRYPT_FormatCertSerialNumber(
1572 &info
->AuthorityCertSerialNumber
, str
, &size
);
1581 static WCHAR aia
[MAX_STRING_RESOURCE_LEN
];
1582 static WCHAR accessMethod
[MAX_STRING_RESOURCE_LEN
];
1583 static WCHAR ocsp
[MAX_STRING_RESOURCE_LEN
];
1584 static WCHAR caIssuers
[MAX_STRING_RESOURCE_LEN
];
1585 static WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
1586 static WCHAR accessLocation
[MAX_STRING_RESOURCE_LEN
];
1588 static BOOL WINAPI
CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType
,
1589 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1590 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1593 CERT_AUTHORITY_INFO_ACCESS
*info
;
1599 SetLastError(E_INVALIDARG
);
1602 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
1603 X509_AUTHORITY_INFO_ACCESS
, pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
,
1604 NULL
, &info
, &size
)))
1606 DWORD bytesNeeded
= sizeof(WCHAR
);
1608 if (!info
->cAccDescr
)
1610 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
1612 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
1613 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
1614 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
1616 *pcbFormat
= bytesNeeded
;
1617 else if (*pcbFormat
< bytesNeeded
)
1619 *pcbFormat
= bytesNeeded
;
1620 SetLastError(ERROR_MORE_DATA
);
1625 *pcbFormat
= bytesNeeded
;
1626 strcpyW(pbFormat
, infoNotAvailable
);
1631 static const WCHAR numFmt
[] = { '%','d',0 };
1632 static const WCHAR equal
[] = { '=',0 };
1633 static BOOL stringsLoaded
= FALSE
;
1635 LPCWSTR headingSep
, accessMethodSep
, locationSep
;
1636 WCHAR accessDescrNum
[11];
1640 LoadStringW(hInstance
, IDS_AIA
, aia
,
1641 sizeof(aia
) / sizeof(aia
[0]));
1642 LoadStringW(hInstance
, IDS_ACCESS_METHOD
, accessMethod
,
1643 sizeof(accessMethod
) / sizeof(accessMethod
[0]));
1644 LoadStringW(hInstance
, IDS_ACCESS_METHOD_OCSP
, ocsp
,
1645 sizeof(ocsp
) / sizeof(ocsp
[0]));
1646 LoadStringW(hInstance
, IDS_ACCESS_METHOD_CA_ISSUERS
, caIssuers
,
1647 sizeof(caIssuers
) / sizeof(caIssuers
[0]));
1648 LoadStringW(hInstance
, IDS_ACCESS_METHOD_UNKNOWN
, unknown
,
1649 sizeof(unknown
) / sizeof(unknown
[0]));
1650 LoadStringW(hInstance
, IDS_ACCESS_LOCATION
, accessLocation
,
1651 sizeof(accessLocation
) / sizeof(accessLocation
[0]));
1652 stringsLoaded
= TRUE
;
1654 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1657 accessMethodSep
= crlf
;
1658 locationSep
= colonCrlf
;
1662 headingSep
= colonSep
;
1663 accessMethodSep
= commaSpace
;
1664 locationSep
= equal
;
1667 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1670 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
1671 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1672 bytesNeeded
+= strlenW(accessDescrNum
) * sizeof(WCHAR
);
1673 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
1674 bytesNeeded
+= strlenW(aia
) * sizeof(WCHAR
);
1675 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
1677 bytesNeeded
+= strlenW(accessMethod
) * sizeof(WCHAR
);
1678 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1679 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1680 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1682 bytesNeeded
+= strlenW(ocsp
) * sizeof(WCHAR
);
1683 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1684 szOID_PKIX_CA_ISSUERS
))
1685 bytesNeeded
+= strlenW(caIssuers
) * sizeof(caIssuers
);
1687 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
1688 bytesNeeded
+= sizeof(WCHAR
); /* space */
1689 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
1690 bytesNeeded
+= strlen(info
->rgAccDescr
[i
].pszAccessMethod
)
1692 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
1693 /* Delimiter between access method and location */
1694 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1695 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1696 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
1697 bytesNeeded
+= strlenW(accessLocation
) * sizeof(WCHAR
);
1698 bytesNeeded
+= strlenW(locationSep
) * sizeof(WCHAR
);
1699 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1700 &info
->rgAccDescr
[i
].AccessLocation
, NULL
, &size
);
1702 bytesNeeded
+= size
- sizeof(WCHAR
);
1703 /* Need extra delimiter between access method entries */
1704 if (i
< info
->cAccDescr
- 1)
1705 bytesNeeded
+= strlenW(accessMethodSep
) * sizeof(WCHAR
);
1710 *pcbFormat
= bytesNeeded
;
1711 else if (*pcbFormat
< bytesNeeded
)
1713 *pcbFormat
= bytesNeeded
;
1714 SetLastError(ERROR_MORE_DATA
);
1719 LPWSTR str
= pbFormat
;
1720 DWORD altNameEntrySize
;
1722 *pcbFormat
= bytesNeeded
;
1723 for (i
= 0; ret
&& i
< info
->cAccDescr
; i
++)
1728 sprintfW(accessDescrNum
, numFmt
, i
+ 1);
1729 strcpyW(str
, accessDescrNum
);
1730 str
+= strlenW(accessDescrNum
);
1733 str
+= strlenW(aia
);
1734 strcpyW(str
, headingSep
);
1735 str
+= strlenW(headingSep
);
1736 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1738 strcpyW(str
, indent
);
1739 str
+= strlenW(indent
);
1741 strcpyW(str
, accessMethod
);
1742 str
+= strlenW(accessMethod
);
1743 if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1747 str
+= strlenW(ocsp
);
1749 else if (!strcmp(info
->rgAccDescr
[i
].pszAccessMethod
,
1750 szOID_PKIX_CA_ISSUERS
))
1752 strcpyW(str
, caIssuers
);
1753 str
+= strlenW(caIssuers
);
1757 strcpyW(str
, unknown
);
1758 str
+= strlenW(unknown
);
1762 for (oidPtr
= info
->rgAccDescr
[i
].pszAccessMethod
;
1763 *oidPtr
; oidPtr
++, str
++)
1766 strcpyW(str
, accessMethodSep
);
1767 str
+= strlenW(accessMethodSep
);
1768 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1770 strcpyW(str
, indent
);
1771 str
+= strlenW(indent
);
1773 strcpyW(str
, accessLocation
);
1774 str
+= strlenW(accessLocation
);
1775 strcpyW(str
, locationSep
);
1776 str
+= strlenW(locationSep
);
1777 /* This overestimates the size available, but that
1778 * won't matter since we checked earlier whether enough
1779 * space for the entire string was available.
1781 altNameEntrySize
= bytesNeeded
;
1782 ret
= CRYPT_FormatAltNameEntry(dwFormatStrType
, 2,
1783 &info
->rgAccDescr
[i
].AccessLocation
, str
,
1786 str
+= altNameEntrySize
/ sizeof(WCHAR
) - 1;
1787 if (i
< info
->cAccDescr
- 1)
1789 strcpyW(str
, accessMethodSep
);
1790 str
+= strlenW(accessMethodSep
);
1801 static WCHAR keyCompromise
[MAX_STRING_RESOURCE_LEN
];
1802 static WCHAR caCompromise
[MAX_STRING_RESOURCE_LEN
];
1803 static WCHAR affiliationChanged
[MAX_STRING_RESOURCE_LEN
];
1804 static WCHAR superseded
[MAX_STRING_RESOURCE_LEN
];
1805 static WCHAR operationCeased
[MAX_STRING_RESOURCE_LEN
];
1806 static WCHAR certificateHold
[MAX_STRING_RESOURCE_LEN
];
1808 struct reason_map_entry
1814 static struct reason_map_entry reason_map
[] = {
1815 { CRL_REASON_KEY_COMPROMISE_FLAG
, keyCompromise
, IDS_REASON_KEY_COMPROMISE
},
1816 { CRL_REASON_CA_COMPROMISE_FLAG
, caCompromise
, IDS_REASON_CA_COMPROMISE
},
1817 { CRL_REASON_AFFILIATION_CHANGED_FLAG
, affiliationChanged
,
1818 IDS_REASON_AFFILIATION_CHANGED
},
1819 { CRL_REASON_SUPERSEDED_FLAG
, superseded
, IDS_REASON_SUPERSEDED
},
1820 { CRL_REASON_CESSATION_OF_OPERATION_FLAG
, operationCeased
,
1821 IDS_REASON_CESSATION_OF_OPERATION
},
1822 { CRL_REASON_CERTIFICATE_HOLD_FLAG
, certificateHold
,
1823 IDS_REASON_CERTIFICATE_HOLD
},
1826 static BOOL
CRYPT_FormatReason(DWORD dwFormatStrType
,
1827 const CRYPT_BIT_BLOB
*reasonFlags
, LPWSTR str
, DWORD
*pcbStr
)
1829 static const WCHAR sep
[] = { ',',' ',0 };
1830 static const WCHAR bitsFmt
[] = { ' ','(','%','0','2','x',')',0 };
1831 static BOOL stringsLoaded
= FALSE
;
1832 int i
, numReasons
= 0;
1834 DWORD bytesNeeded
= sizeof(WCHAR
);
1839 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1840 LoadStringW(hInstance
, reason_map
[i
].id
, reason_map
[i
].reason
,
1841 MAX_STRING_RESOURCE_LEN
);
1842 stringsLoaded
= TRUE
;
1844 /* No need to check reasonFlags->cbData, we already know it's positive.
1845 * Ignore any other bytes, as they're for undefined bits.
1847 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1849 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1851 bytesNeeded
+= strlenW(reason_map
[i
].reason
) * sizeof(WCHAR
);
1853 bytesNeeded
+= strlenW(sep
) * sizeof(WCHAR
);
1856 sprintfW(bits
, bitsFmt
, reasonFlags
->pbData
[0]);
1857 bytesNeeded
+= strlenW(bits
);
1859 *pcbStr
= bytesNeeded
;
1860 else if (*pcbStr
< bytesNeeded
)
1862 *pcbStr
= bytesNeeded
;
1863 SetLastError(ERROR_MORE_DATA
);
1868 *pcbStr
= bytesNeeded
;
1869 for (i
= 0; i
< sizeof(reason_map
) / sizeof(reason_map
[0]); i
++)
1871 if (reasonFlags
->pbData
[0] & reason_map
[i
].reasonBit
)
1873 strcpyW(str
, reason_map
[i
].reason
);
1874 str
+= strlenW(reason_map
[i
].reason
);
1875 if (i
< sizeof(reason_map
) / sizeof(reason_map
[0]) - 1 &&
1879 str
+= strlenW(sep
);
1888 static WCHAR crlDistPoint
[MAX_STRING_RESOURCE_LEN
];
1889 static WCHAR distPointName
[MAX_STRING_RESOURCE_LEN
];
1890 static WCHAR fullName
[MAX_STRING_RESOURCE_LEN
];
1891 static WCHAR rdnName
[MAX_STRING_RESOURCE_LEN
];
1892 static WCHAR reason
[MAX_STRING_RESOURCE_LEN
];
1893 static WCHAR issuer
[MAX_STRING_RESOURCE_LEN
];
1895 static BOOL WINAPI
CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType
,
1896 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
1897 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
1900 CRL_DIST_POINTS_INFO
*info
;
1906 SetLastError(E_INVALIDARG
);
1909 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_CRL_DIST_POINTS
,
1910 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &info
, &size
)))
1912 static const WCHAR numFmt
[] = { '%','d',0 };
1913 static const WCHAR colon
[] = { ':',0 };
1914 static BOOL stringsLoaded
= FALSE
;
1915 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for NULL terminator */
1916 BOOL haveAnEntry
= FALSE
;
1917 LPCWSTR headingSep
, nameSep
;
1918 WCHAR distPointNum
[11];
1923 LoadStringW(hInstance
, IDS_CRL_DIST_POINT
, crlDistPoint
,
1924 sizeof(crlDistPoint
) / sizeof(crlDistPoint
[0]));
1925 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_NAME
, distPointName
,
1926 sizeof(distPointName
) / sizeof(distPointName
[0]));
1927 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_FULL_NAME
, fullName
,
1928 sizeof(fullName
) / sizeof(fullName
[0]));
1929 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_RDN_NAME
, rdnName
,
1930 sizeof(rdnName
) / sizeof(rdnName
[0]));
1931 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_REASON
, reason
,
1932 sizeof(reason
) / sizeof(reason
[0]));
1933 LoadStringW(hInstance
, IDS_CRL_DIST_POINT_ISSUER
, issuer
,
1934 sizeof(issuer
) / sizeof(issuer
[0]));
1935 stringsLoaded
= TRUE
;
1937 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1940 nameSep
= colonCrlf
;
1944 headingSep
= colonSep
;
1948 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
1950 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
1952 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
1953 CRL_DIST_POINT_NO_NAME
)
1955 bytesNeeded
+= strlenW(distPointName
) * sizeof(WCHAR
);
1956 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1957 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
1958 CRL_DIST_POINT_FULL_NAME
)
1959 bytesNeeded
+= strlenW(fullName
) * sizeof(WCHAR
);
1961 bytesNeeded
+= strlenW(rdnName
) * sizeof(WCHAR
);
1962 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1963 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
1964 bytesNeeded
+= 2 * strlenW(indent
) * sizeof(WCHAR
);
1965 /* The indent level (3) is higher than when used as the issuer,
1966 * because the name is subordinate to the name type (full vs.
1969 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
1970 &distPoint
->DistPointName
.u
.FullName
, NULL
, &size
);
1972 bytesNeeded
+= size
- sizeof(WCHAR
);
1975 else if (distPoint
->ReasonFlags
.cbData
)
1977 bytesNeeded
+= strlenW(reason
) * sizeof(WCHAR
);
1978 ret
= CRYPT_FormatReason(dwFormatStrType
,
1979 &distPoint
->ReasonFlags
, NULL
, &size
);
1981 bytesNeeded
+= size
- sizeof(WCHAR
);
1984 else if (distPoint
->CRLIssuer
.cAltEntry
)
1986 bytesNeeded
+= strlenW(issuer
) * sizeof(WCHAR
);
1987 bytesNeeded
+= strlenW(nameSep
) * sizeof(WCHAR
);
1988 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
1989 &distPoint
->CRLIssuer
, NULL
, &size
);
1991 bytesNeeded
+= size
- sizeof(WCHAR
);
1996 bytesNeeded
+= sizeof(WCHAR
); /* left bracket */
1997 sprintfW(distPointNum
, numFmt
, i
+ 1);
1998 bytesNeeded
+= strlenW(distPointNum
) * sizeof(WCHAR
);
1999 bytesNeeded
+= sizeof(WCHAR
); /* right bracket */
2000 bytesNeeded
+= strlenW(crlDistPoint
) * sizeof(WCHAR
);
2001 bytesNeeded
+= strlenW(headingSep
) * sizeof(WCHAR
);
2002 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2003 bytesNeeded
+= strlenW(indent
) * sizeof(WCHAR
);
2008 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
2010 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
2011 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
2012 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
2014 *pcbFormat
= bytesNeeded
;
2015 else if (*pcbFormat
< bytesNeeded
)
2017 *pcbFormat
= bytesNeeded
;
2018 SetLastError(ERROR_MORE_DATA
);
2023 *pcbFormat
= bytesNeeded
;
2024 strcpyW(pbFormat
, infoNotAvailable
);
2030 *pcbFormat
= bytesNeeded
;
2031 else if (*pcbFormat
< bytesNeeded
)
2033 *pcbFormat
= bytesNeeded
;
2034 SetLastError(ERROR_MORE_DATA
);
2039 LPWSTR str
= pbFormat
;
2041 *pcbFormat
= bytesNeeded
;
2042 for (i
= 0; ret
&& i
< info
->cDistPoint
; i
++)
2044 CRL_DIST_POINT
*distPoint
= &info
->rgDistPoint
[i
];
2047 sprintfW(distPointNum
, numFmt
, i
+ 1);
2048 strcpyW(str
, distPointNum
);
2049 str
+= strlenW(distPointNum
);
2051 strcpyW(str
, crlDistPoint
);
2052 str
+= strlenW(crlDistPoint
);
2053 strcpyW(str
, headingSep
);
2054 str
+= strlenW(headingSep
);
2055 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2057 strcpyW(str
, indent
);
2058 str
+= strlenW(indent
);
2060 if (distPoint
->DistPointName
.dwDistPointNameChoice
!=
2061 CRL_DIST_POINT_NO_NAME
)
2063 DWORD altNameSize
= bytesNeeded
;
2065 strcpyW(str
, distPointName
);
2066 str
+= strlenW(distPointName
);
2067 strcpyW(str
, nameSep
);
2068 str
+= strlenW(nameSep
);
2069 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2071 strcpyW(str
, indent
);
2072 str
+= strlenW(indent
);
2073 strcpyW(str
, indent
);
2074 str
+= strlenW(indent
);
2076 if (distPoint
->DistPointName
.dwDistPointNameChoice
==
2077 CRL_DIST_POINT_FULL_NAME
)
2079 strcpyW(str
, fullName
);
2080 str
+= strlenW(fullName
);
2084 strcpyW(str
, rdnName
);
2085 str
+= strlenW(rdnName
);
2087 strcpyW(str
, nameSep
);
2088 str
+= strlenW(nameSep
);
2089 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 3,
2090 &distPoint
->DistPointName
.u
.FullName
, str
,
2093 str
+= altNameSize
/ sizeof(WCHAR
) - 1;
2095 else if (distPoint
->ReasonFlags
.cbData
)
2097 DWORD reasonSize
= bytesNeeded
;
2099 strcpyW(str
, reason
);
2100 str
+= strlenW(reason
);
2101 ret
= CRYPT_FormatReason(dwFormatStrType
,
2102 &distPoint
->ReasonFlags
, str
, &reasonSize
);
2104 str
+= reasonSize
/ sizeof(WCHAR
) - 1;
2106 else if (distPoint
->CRLIssuer
.cAltEntry
)
2108 DWORD crlIssuerSize
= bytesNeeded
;
2110 strcpyW(str
, issuer
);
2111 str
+= strlenW(issuer
);
2112 strcpyW(str
, nameSep
);
2113 str
+= strlenW(nameSep
);
2114 ret
= CRYPT_FormatAltNameInfo(dwFormatStrType
, 2,
2115 &distPoint
->CRLIssuer
, str
,
2118 str
+= crlIssuerSize
/ sizeof(WCHAR
) - 1;
2128 static BOOL WINAPI
CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType
,
2129 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2130 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2133 CERT_ENHKEY_USAGE
*usage
;
2139 SetLastError(E_INVALIDARG
);
2142 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_ENHANCED_KEY_USAGE
,
2143 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &usage
, &size
)))
2145 WCHAR unknown
[MAX_STRING_RESOURCE_LEN
];
2147 DWORD bytesNeeded
= sizeof(WCHAR
); /* space for the NULL terminator */
2151 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2154 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2159 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2162 LoadStringW(hInstance
, IDS_USAGE_UNKNOWN
, unknown
,
2163 sizeof(unknown
) / sizeof(unknown
[0]));
2164 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2166 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2167 usage
->rgpszUsageIdentifier
[i
], CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2170 bytesNeeded
+= strlenW(info
->pwszName
) * sizeof(WCHAR
);
2172 bytesNeeded
+= strlenW(unknown
) * sizeof(WCHAR
);
2173 bytesNeeded
+= sizeof(WCHAR
); /* space */
2174 bytesNeeded
+= sizeof(WCHAR
); /* left paren */
2175 bytesNeeded
+= strlen(usage
->rgpszUsageIdentifier
[i
]) *
2177 bytesNeeded
+= sizeof(WCHAR
); /* right paren */
2178 if (i
< usage
->cUsageIdentifier
- 1)
2179 bytesNeeded
+= sepLen
;
2182 *pcbFormat
= bytesNeeded
;
2183 else if (*pcbFormat
< bytesNeeded
)
2185 *pcbFormat
= bytesNeeded
;
2186 SetLastError(ERROR_MORE_DATA
);
2191 LPWSTR str
= pbFormat
;
2193 *pcbFormat
= bytesNeeded
;
2194 for (i
= 0; i
< usage
->cUsageIdentifier
; i
++)
2196 PCCRYPT_OID_INFO info
= CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY
,
2197 usage
->rgpszUsageIdentifier
[i
],
2198 CRYPT_ENHKEY_USAGE_OID_GROUP_ID
);
2203 strcpyW(str
, info
->pwszName
);
2204 str
+= strlenW(info
->pwszName
);
2208 strcpyW(str
, unknown
);
2209 str
+= strlenW(unknown
);
2213 for (oidPtr
= usage
->rgpszUsageIdentifier
[i
]; *oidPtr
; oidPtr
++)
2217 if (i
< usage
->cUsageIdentifier
- 1)
2220 str
+= sepLen
/ sizeof(WCHAR
);
2229 static struct BitToString netscapeCertTypeMap
[] = {
2230 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_CLIENT
, { 0 } },
2231 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE
, IDS_NETSCAPE_SSL_SERVER
, { 0 } },
2232 { NETSCAPE_SMIME_CERT_TYPE
, IDS_NETSCAPE_SMIME
, { 0 } },
2233 { NETSCAPE_SIGN_CERT_TYPE
, IDS_NETSCAPE_SIGN
, { 0 } },
2234 { NETSCAPE_SSL_CA_CERT_TYPE
, IDS_NETSCAPE_SSL_CA
, { 0 } },
2235 { NETSCAPE_SMIME_CA_CERT_TYPE
, IDS_NETSCAPE_SMIME_CA
, { 0 } },
2236 { NETSCAPE_SIGN_CA_CERT_TYPE
, IDS_NETSCAPE_SIGN_CA
, { 0 } },
2239 static BOOL WINAPI
CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType
,
2240 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2241 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2245 CRYPT_BIT_BLOB
*bits
;
2250 SetLastError(E_INVALIDARG
);
2253 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_BITS
,
2254 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &bits
, &size
)))
2256 WCHAR infoNotAvailable
[MAX_STRING_RESOURCE_LEN
];
2257 DWORD bytesNeeded
= sizeof(WCHAR
);
2259 LoadStringW(hInstance
, IDS_INFO_NOT_AVAILABLE
, infoNotAvailable
,
2260 sizeof(infoNotAvailable
) / sizeof(infoNotAvailable
[0]));
2261 if (!bits
->cbData
|| bits
->cbData
> 1)
2263 bytesNeeded
+= strlenW(infoNotAvailable
) * sizeof(WCHAR
);
2265 *pcbFormat
= bytesNeeded
;
2266 else if (*pcbFormat
< bytesNeeded
)
2268 *pcbFormat
= bytesNeeded
;
2269 SetLastError(ERROR_MORE_DATA
);
2274 LPWSTR str
= pbFormat
;
2276 *pcbFormat
= bytesNeeded
;
2277 strcpyW(str
, infoNotAvailable
);
2282 static BOOL stringsLoaded
= FALSE
;
2289 for (i
= 0; i
< sizeof(netscapeCertTypeMap
) /
2290 sizeof(netscapeCertTypeMap
[0]); i
++)
2291 LoadStringW(hInstance
, netscapeCertTypeMap
[i
].id
,
2292 netscapeCertTypeMap
[i
].str
, MAX_STRING_RESOURCE_LEN
);
2293 stringsLoaded
= TRUE
;
2295 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2296 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2297 NULL
, &bitStringLen
, &first
);
2298 bytesNeeded
+= bitStringLen
;
2299 bytesNeeded
+= 3 * sizeof(WCHAR
); /* " (" + ")" */
2300 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2301 bits
->cbData
, NULL
, &size
);
2302 bytesNeeded
+= size
;
2304 *pcbFormat
= bytesNeeded
;
2305 else if (*pcbFormat
< bytesNeeded
)
2307 *pcbFormat
= bytesNeeded
;
2308 SetLastError(ERROR_MORE_DATA
);
2313 LPWSTR str
= pbFormat
;
2315 bitStringLen
= bytesNeeded
;
2317 CRYPT_FormatBits(bits
->pbData
[0], netscapeCertTypeMap
,
2318 sizeof(netscapeCertTypeMap
) / sizeof(netscapeCertTypeMap
[0]),
2319 str
, &bitStringLen
, &first
);
2320 str
+= bitStringLen
/ sizeof(WCHAR
) - 1;
2323 CRYPT_FormatHexString(0, 0, 0, NULL
, NULL
, bits
->pbData
,
2324 bits
->cbData
, str
, &size
);
2325 str
+= size
/ sizeof(WCHAR
) - 1;
2335 static WCHAR financialCriteria
[MAX_STRING_RESOURCE_LEN
];
2336 static WCHAR available
[MAX_STRING_RESOURCE_LEN
];
2337 static WCHAR notAvailable
[MAX_STRING_RESOURCE_LEN
];
2338 static WCHAR meetsCriteria
[MAX_STRING_RESOURCE_LEN
];
2339 static WCHAR yes
[MAX_STRING_RESOURCE_LEN
];
2340 static WCHAR no
[MAX_STRING_RESOURCE_LEN
];
2342 static BOOL WINAPI
CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType
,
2343 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2344 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2347 SPC_FINANCIAL_CRITERIA criteria
;
2348 DWORD size
= sizeof(criteria
);
2353 SetLastError(E_INVALIDARG
);
2356 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
,
2357 SPC_FINANCIAL_CRITERIA_STRUCT
, pbEncoded
, cbEncoded
, 0, NULL
, &criteria
,
2360 static BOOL stringsLoaded
= FALSE
;
2361 DWORD bytesNeeded
= sizeof(WCHAR
);
2367 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA
, financialCriteria
,
2368 sizeof(financialCriteria
) / sizeof(financialCriteria
[0]));
2369 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_AVAILABLE
, available
,
2370 sizeof(available
) / sizeof(available
[0]));
2371 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE
,
2372 notAvailable
, sizeof(notAvailable
) / sizeof(notAvailable
[0]));
2373 LoadStringW(hInstance
, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA
,
2374 meetsCriteria
, sizeof(meetsCriteria
) / sizeof(meetsCriteria
[0]));
2375 LoadStringW(hInstance
, IDS_YES
, yes
, sizeof(yes
) / sizeof(yes
[0]));
2376 LoadStringW(hInstance
, IDS_NO
, no
, sizeof(no
) / sizeof(no
[0]));
2377 stringsLoaded
= TRUE
;
2379 if (dwFormatStrType
& CRYPT_FORMAT_STR_MULTI_LINE
)
2382 sepLen
= strlenW(crlf
) * sizeof(WCHAR
);
2387 sepLen
= strlenW(commaSpace
) * sizeof(WCHAR
);
2389 bytesNeeded
+= strlenW(financialCriteria
) * sizeof(WCHAR
);
2390 if (criteria
.fFinancialInfoAvailable
)
2392 bytesNeeded
+= strlenW(available
) * sizeof(WCHAR
);
2393 bytesNeeded
+= sepLen
;
2394 bytesNeeded
+= strlenW(meetsCriteria
) * sizeof(WCHAR
);
2395 if (criteria
.fMeetsCriteria
)
2396 bytesNeeded
+= strlenW(yes
) * sizeof(WCHAR
);
2398 bytesNeeded
+= strlenW(no
) * sizeof(WCHAR
);
2401 bytesNeeded
+= strlenW(notAvailable
) * sizeof(WCHAR
);
2403 *pcbFormat
= bytesNeeded
;
2404 else if (*pcbFormat
< bytesNeeded
)
2406 *pcbFormat
= bytesNeeded
;
2407 SetLastError(ERROR_MORE_DATA
);
2412 LPWSTR str
= pbFormat
;
2414 *pcbFormat
= bytesNeeded
;
2415 strcpyW(str
, financialCriteria
);
2416 str
+= strlenW(financialCriteria
);
2417 if (criteria
.fFinancialInfoAvailable
)
2419 strcpyW(str
, available
);
2420 str
+= strlenW(available
);
2422 str
+= sepLen
/ sizeof(WCHAR
);
2423 strcpyW(str
, meetsCriteria
);
2424 str
+= strlenW(meetsCriteria
);
2425 if (criteria
.fMeetsCriteria
)
2432 strcpyW(str
, notAvailable
);
2433 str
+= strlenW(notAvailable
);
2440 static BOOL WINAPI
CRYPT_FormatUnicodeString(DWORD dwCertEncodingType
,
2441 DWORD dwFormatType
, DWORD dwFormatStrType
, void *pFormatStruct
,
2442 LPCSTR lpszStructType
, const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
,
2445 CERT_NAME_VALUE
*value
;
2451 SetLastError(E_INVALIDARG
);
2454 if ((ret
= CryptDecodeObjectEx(dwCertEncodingType
, X509_UNICODE_ANY_STRING
,
2455 pbEncoded
, cbEncoded
, CRYPT_DECODE_ALLOC_FLAG
, NULL
, &value
, &size
)))
2458 *pcbFormat
= value
->Value
.cbData
;
2459 else if (*pcbFormat
< value
->Value
.cbData
)
2461 *pcbFormat
= value
->Value
.cbData
;
2462 SetLastError(ERROR_MORE_DATA
);
2467 LPWSTR str
= pbFormat
;
2469 *pcbFormat
= value
->Value
.cbData
;
2470 strcpyW(str
, (LPWSTR
)value
->Value
.pbData
);
2476 typedef BOOL (WINAPI
*CryptFormatObjectFunc
)(DWORD
, DWORD
, DWORD
, void *,
2477 LPCSTR
, const BYTE
*, DWORD
, void *, DWORD
*);
2479 static CryptFormatObjectFunc
CRYPT_GetBuiltinFormatFunction(DWORD encodingType
,
2480 DWORD formatStrType
, LPCSTR lpszStructType
)
2482 CryptFormatObjectFunc format
= NULL
;
2484 if ((encodingType
& CERT_ENCODING_TYPE_MASK
) != X509_ASN_ENCODING
)
2486 SetLastError(ERROR_FILE_NOT_FOUND
);
2489 if (!HIWORD(lpszStructType
))
2491 switch (LOWORD(lpszStructType
))
2493 case LOWORD(X509_KEY_USAGE
):
2494 format
= CRYPT_FormatKeyUsage
;
2496 case LOWORD(X509_ALTERNATE_NAME
):
2497 format
= CRYPT_FormatAltName
;
2499 case LOWORD(X509_BASIC_CONSTRAINTS2
):
2500 format
= CRYPT_FormatBasicConstraints2
;
2502 case LOWORD(X509_AUTHORITY_KEY_ID2
):
2503 format
= CRYPT_FormatAuthorityKeyId2
;
2505 case LOWORD(X509_AUTHORITY_INFO_ACCESS
):
2506 format
= CRYPT_FormatAuthorityInfoAccess
;
2508 case LOWORD(X509_CRL_DIST_POINTS
):
2509 format
= CRYPT_FormatCRLDistPoints
;
2511 case LOWORD(X509_ENHANCED_KEY_USAGE
):
2512 format
= CRYPT_FormatEnhancedKeyUsage
;
2514 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT
):
2515 format
= CRYPT_FormatSpcFinancialCriteria
;
2519 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME
))
2520 format
= CRYPT_FormatAltName
;
2521 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME
))
2522 format
= CRYPT_FormatAltName
;
2523 else if (!strcmp(lpszStructType
, szOID_KEY_USAGE
))
2524 format
= CRYPT_FormatKeyUsage
;
2525 else if (!strcmp(lpszStructType
, szOID_SUBJECT_ALT_NAME2
))
2526 format
= CRYPT_FormatAltName
;
2527 else if (!strcmp(lpszStructType
, szOID_ISSUER_ALT_NAME2
))
2528 format
= CRYPT_FormatAltName
;
2529 else if (!strcmp(lpszStructType
, szOID_BASIC_CONSTRAINTS2
))
2530 format
= CRYPT_FormatBasicConstraints2
;
2531 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_INFO_ACCESS
))
2532 format
= CRYPT_FormatAuthorityInfoAccess
;
2533 else if (!strcmp(lpszStructType
, szOID_AUTHORITY_KEY_IDENTIFIER2
))
2534 format
= CRYPT_FormatAuthorityKeyId2
;
2535 else if (!strcmp(lpszStructType
, szOID_CRL_DIST_POINTS
))
2536 format
= CRYPT_FormatCRLDistPoints
;
2537 else if (!strcmp(lpszStructType
, szOID_ENHANCED_KEY_USAGE
))
2538 format
= CRYPT_FormatEnhancedKeyUsage
;
2539 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_CERT_TYPE
))
2540 format
= CRYPT_FormatNetscapeCertType
;
2541 else if (!strcmp(lpszStructType
, szOID_NETSCAPE_BASE_URL
) ||
2542 !strcmp(lpszStructType
, szOID_NETSCAPE_REVOCATION_URL
) ||
2543 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_REVOCATION_URL
) ||
2544 !strcmp(lpszStructType
, szOID_NETSCAPE_CERT_RENEWAL_URL
) ||
2545 !strcmp(lpszStructType
, szOID_NETSCAPE_CA_POLICY_URL
) ||
2546 !strcmp(lpszStructType
, szOID_NETSCAPE_SSL_SERVER_NAME
) ||
2547 !strcmp(lpszStructType
, szOID_NETSCAPE_COMMENT
))
2548 format
= CRYPT_FormatUnicodeString
;
2549 else if (!strcmp(lpszStructType
, SPC_FINANCIAL_CRITERIA_OBJID
))
2550 format
= CRYPT_FormatSpcFinancialCriteria
;
2554 BOOL WINAPI
CryptFormatObject(DWORD dwCertEncodingType
, DWORD dwFormatType
,
2555 DWORD dwFormatStrType
, void *pFormatStruct
, LPCSTR lpszStructType
,
2556 const BYTE
*pbEncoded
, DWORD cbEncoded
, void *pbFormat
, DWORD
*pcbFormat
)
2558 CryptFormatObjectFunc format
= NULL
;
2559 HCRYPTOIDFUNCADDR hFunc
= NULL
;
2562 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType
,
2563 dwFormatType
, dwFormatStrType
, pFormatStruct
, debugstr_a(lpszStructType
),
2564 pbEncoded
, cbEncoded
, pbFormat
, pcbFormat
);
2566 if (!(format
= CRYPT_GetBuiltinFormatFunction(dwCertEncodingType
,
2567 dwFormatStrType
, lpszStructType
)))
2569 static HCRYPTOIDFUNCSET set
= NULL
;
2572 set
= CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC
, 0);
2573 CryptGetOIDFunctionAddress(set
, dwCertEncodingType
, lpszStructType
, 0,
2574 (void **)&format
, &hFunc
);
2576 if (!format
&& (dwCertEncodingType
& CERT_ENCODING_TYPE_MASK
) ==
2577 X509_ASN_ENCODING
&& !(dwFormatStrType
& CRYPT_FORMAT_STR_NO_HEX
))
2578 format
= CRYPT_FormatHexString
;
2580 ret
= format(dwCertEncodingType
, dwFormatType
, dwFormatStrType
,
2581 pFormatStruct
, lpszStructType
, pbEncoded
, cbEncoded
, pbFormat
,
2584 CryptFreeOIDFunctionAddress(hFunc
, 0);