crypt32: Support base64-encoded context objects in CryptQueryObject.
[wine/wine64.git] / dlls / crypt32 / object.c
blob97f35f7c6a2828df60e94edb2efa95a988cbfd68
1 /*
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
20 #include <stdarg.h>
21 #define NONAMELESSUNION
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wincrypt.h"
25 #include "mssip.h"
26 #include "winuser.h"
27 #include "wintrust.h"
28 #include "crypt32_private.h"
29 #include "cryptres.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)
37 BOOL ret = FALSE;
38 HANDLE file;
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)
46 ret = TRUE;
47 blob->cbData = GetFileSize(file, NULL);
48 if (blob->cbData)
50 blob->pbData = CryptMemAlloc(blob->cbData);
51 if (blob->pbData)
53 DWORD read;
55 ret = ReadFile(file, blob->pbData, blob->cbData, &read, NULL);
58 CloseHandle(file);
60 TRACE("returning %d\n", ret);
61 return ret;
64 static BOOL CRYPT_QueryContextBlob(const CERT_BLOB *blob,
65 DWORD dwExpectedContentTypeFlags, HCERTSTORE store,
66 DWORD *contentType, const void **ppvContext)
68 BOOL ret = FALSE;
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;
91 return ret;
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)
99 CERT_BLOB fileBlob;
100 const CERT_BLOB *blob;
101 HCERTSTORE store;
102 BOOL ret;
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((LPCWSTR)pvObject, &fileBlob);
112 blob = &fileBlob;
113 break;
114 case CERT_QUERY_OBJECT_BLOB:
115 blob = (const CERT_BLOB *)pvObject;
116 ret = TRUE;
117 break;
118 default:
119 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
120 ret = FALSE;
122 if (!ret)
123 return FALSE;
125 ret = FALSE;
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);
132 if (ret)
133 formatType = CERT_QUERY_FORMAT_BINARY;
135 if (!ret &&
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])
142 trimmed.cbData--;
143 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData, trimmed.cbData,
144 CRYPT_STRING_BASE64_ANY, NULL, &decoded.cbData, NULL, NULL);
145 if (ret)
147 decoded.pbData = CryptMemAlloc(decoded.cbData);
148 if (decoded.pbData)
150 ret = CryptStringToBinaryA((LPSTR)trimmed.pbData,
151 trimmed.cbData, CRYPT_STRING_BASE64_ANY, decoded.pbData,
152 &decoded.cbData, NULL, NULL);
153 if (ret)
155 ret = CRYPT_QueryContextBlob(&decoded,
156 dwExpectedContentTypeFlags, store, pdwContentType,
157 ppvContext);
158 if (ret)
159 formatType = CERT_QUERY_FORMAT_BASE64_ENCODED;
161 CryptMemFree(decoded.pbData);
163 else
164 ret = FALSE;
167 if (ret)
169 if (pdwMsgAndCertEncodingType)
170 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
171 if (pdwFormatType)
172 *pdwFormatType = formatType;
173 if (phCertStore)
174 *phCertStore = CertDuplicateStore(store);
176 CertCloseStore(store, 0);
177 if (blob == &fileBlob)
178 CryptMemFree(blob->pbData);
179 TRACE("returning %d\n", ret);
180 return 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)
188 CERT_BLOB fileBlob;
189 const CERT_BLOB *blob;
190 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
191 const void *context;
192 DWORD contextType;
193 BOOL ret;
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((LPCWSTR)pvObject, &fileBlob);
202 blob = &fileBlob;
203 break;
204 case CERT_QUERY_OBJECT_BLOB:
205 blob = (const CERT_BLOB *)pvObject;
206 ret = TRUE;
207 break;
208 default:
209 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
210 ret = FALSE;
212 if (!ret)
213 return FALSE;
215 ret = FALSE;
216 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData,
217 CERT_STORE_ALL_CONTEXT_FLAG, &contextType);
218 if (context)
220 DWORD contentType, certStoreOffset;
222 ret = TRUE;
223 switch (contextType)
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);
233 ret = FALSE;
234 goto end;
236 break;
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);
245 ret = FALSE;
246 goto end;
248 break;
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);
257 ret = FALSE;
258 goto end;
260 break;
261 default:
262 SetLastError(ERROR_INVALID_DATA);
263 ret = FALSE;
264 goto end;
266 if (pdwMsgAndCertEncodingType)
267 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
268 if (pdwContentType)
269 *pdwContentType = contentType;
270 if (phCertStore)
271 *phCertStore = CertDuplicateStore(
272 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
273 if (ppvContext)
274 *ppvContext = contextInterface->duplicate(context);
277 end:
278 if (contextInterface && context)
279 contextInterface->free(context);
280 if (blob == &fileBlob)
281 CryptMemFree(blob->pbData);
282 TRACE("returning %d\n", ret);
283 return ret;
286 static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType,
287 const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
288 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
290 LPCWSTR fileName = (LPCWSTR)pvObject;
291 HANDLE file;
292 BOOL ret = FALSE;
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? */
298 return FALSE;
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);
309 if (ret)
311 if (pdwMsgAndCertEncodingType)
312 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
313 if (pdwContentType)
314 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
315 if (phCertStore)
316 *phCertStore = CertDuplicateStore(store);
318 CertCloseStore(store, 0);
319 CloseHandle(file);
321 TRACE("returning %d\n", ret);
322 return ret;
325 /* Used to decode non-embedded messages */
326 static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject,
327 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
328 DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
330 CERT_BLOB fileBlob;
331 const CERT_BLOB *blob;
332 BOOL ret;
333 HCRYPTMSG msg = NULL;
334 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
336 switch (dwObjectType)
338 case CERT_QUERY_OBJECT_FILE:
339 /* This isn't an embedded PKCS7 message, so just read the file
340 * directly
342 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
343 blob = &fileBlob;
344 break;
345 case CERT_QUERY_OBJECT_BLOB:
346 blob = (const CERT_BLOB *)pvObject;
347 ret = TRUE;
348 break;
349 default:
350 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
351 ret = FALSE;
353 if (!ret)
354 return FALSE;
356 ret = FALSE;
357 /* Try it first as a PKCS content info */
358 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
359 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
361 msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL);
362 if (msg)
364 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
365 if (ret)
367 DWORD type, len = sizeof(type);
369 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
370 if (ret)
372 if ((dwExpectedContentTypeFlags &
373 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
375 if (type != CMSG_SIGNED)
377 SetLastError(ERROR_INVALID_DATA);
378 ret = FALSE;
380 else if (pdwContentType)
381 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
383 else if ((dwExpectedContentTypeFlags &
384 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
386 if (type != CMSG_DATA)
388 SetLastError(ERROR_INVALID_DATA);
389 ret = FALSE;
391 else if (pdwContentType)
392 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
396 if (!ret)
398 CryptMsgClose(msg);
399 msg = NULL;
403 /* Failing that, try explicitly typed messages */
404 if (!ret &&
405 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
407 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL);
408 if (msg)
410 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
411 if (!ret)
413 CryptMsgClose(msg);
414 msg = NULL;
417 if (msg && pdwContentType)
418 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
420 if (!ret &&
421 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
423 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL);
424 if (msg)
426 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
427 if (!ret)
429 CryptMsgClose(msg);
430 msg = NULL;
433 if (msg && pdwContentType)
434 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
436 if (pdwMsgAndCertEncodingType)
437 *pdwMsgAndCertEncodingType = encodingType;
438 if (msg)
440 if (phMsg)
441 *phMsg = msg;
442 if (phCertStore)
443 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0,
444 0, msg);
446 if (blob == &fileBlob)
447 CryptMemFree(blob->pbData);
448 TRACE("returning %d\n", ret);
449 return ret;
452 static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType,
453 const void *pvObject, DWORD dwExpectedContentTypeFlags,
454 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
455 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
457 HANDLE file;
458 GUID subject;
459 BOOL ret = FALSE;
461 TRACE("%s\n", debugstr_w((LPCWSTR)pvObject));
463 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
465 WARN("don't know what to do for type %d embedded signed messages\n",
466 dwObjectType);
467 SetLastError(E_INVALIDARG);
468 return FALSE;
470 file = CreateFileW((LPCWSTR)pvObject, GENERIC_READ, FILE_SHARE_READ,
471 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
472 if (file != INVALID_HANDLE_VALUE)
474 ret = CryptSIPRetrieveSubjectGuid((LPCWSTR)pvObject, file, &subject);
475 if (ret)
477 SIP_DISPATCH_INFO sip;
479 memset(&sip, 0, sizeof(sip));
480 sip.cbSize = sizeof(sip);
481 ret = CryptSIPLoad(&subject, 0, &sip);
482 if (ret)
484 SIP_SUBJECTINFO subjectInfo;
485 CERT_BLOB blob;
486 DWORD encodingType;
488 memset(&subjectInfo, 0, sizeof(subjectInfo));
489 subjectInfo.cbSize = sizeof(subjectInfo);
490 subjectInfo.pgSubjectType = &subject;
491 subjectInfo.hFile = file;
492 subjectInfo.pwsFileName = (LPCWSTR)pvObject;
493 ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData,
494 NULL);
495 if (ret)
497 blob.pbData = CryptMemAlloc(blob.cbData);
498 if (blob.pbData)
500 ret = sip.pfGet(&subjectInfo, &encodingType, 0,
501 &blob.cbData, blob.pbData);
502 if (ret)
504 ret = CRYPT_QueryMessageObject(
505 CERT_QUERY_OBJECT_BLOB, &blob,
506 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
507 pdwMsgAndCertEncodingType, NULL, phCertStore,
508 phMsg);
509 if (ret && pdwContentType)
510 *pdwContentType =
511 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED;
513 CryptMemFree(blob.pbData);
515 else
517 SetLastError(ERROR_OUTOFMEMORY);
518 ret = FALSE;
523 CloseHandle(file);
525 TRACE("returning %d\n", ret);
526 return ret;
529 BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject,
530 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
531 DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
532 DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg,
533 const void **ppvContext)
535 static const DWORD unimplementedTypes =
536 CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX |
537 CERT_QUERY_CONTENT_FLAG_CERT_PAIR;
538 BOOL ret = TRUE;
540 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
541 dwObjectType, pvObject, dwExpectedContentTypeFlags,
542 dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType,
543 pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext);
545 if (dwObjectType != CERT_QUERY_OBJECT_BLOB &&
546 dwObjectType != CERT_QUERY_OBJECT_FILE)
548 WARN("unsupported type %d\n", dwObjectType);
549 SetLastError(E_INVALIDARG);
550 return FALSE;
552 if (!pvObject)
554 WARN("missing required argument\n");
555 SetLastError(E_INVALIDARG);
556 return FALSE;
558 if (dwExpectedContentTypeFlags & unimplementedTypes)
559 WARN("unimplemented for types %08x\n",
560 dwExpectedContentTypeFlags & unimplementedTypes);
562 if (pdwFormatType)
563 *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
564 if (phCertStore)
565 *phCertStore = NULL;
566 if (phMsg)
567 *phMsg = NULL;
568 if (ppvContext)
569 *ppvContext = NULL;
571 ret = FALSE;
572 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) ||
573 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) ||
574 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
576 ret = CRYPT_QueryContextObject(dwObjectType, pvObject,
577 dwExpectedContentTypeFlags, dwExpectedFormatTypeFlags,
578 pdwMsgAndCertEncodingType, pdwContentType, pdwFormatType, phCertStore,
579 ppvContext);
581 if (!ret &&
582 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE))
584 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject,
585 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
587 if (!ret &&
588 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) ||
589 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) ||
590 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)))
592 ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject,
593 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
594 phCertStore, ppvContext);
596 if (!ret &&
597 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
598 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)))
600 ret = CRYPT_QueryMessageObject(dwObjectType, pvObject,
601 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
602 phCertStore, phMsg);
604 if (!ret &&
605 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED))
607 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject,
608 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
609 phCertStore, phMsg);
611 if (!ret)
612 SetLastError(CRYPT_E_NO_MATCH);
613 TRACE("returning %d\n", ret);
614 return ret;
617 static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType,
618 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
619 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
620 DWORD *pcbFormat)
622 BOOL ret;
623 DWORD bytesNeeded;
625 if (cbEncoded)
626 bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR);
627 else
628 bytesNeeded = sizeof(WCHAR);
629 if (!pbFormat)
631 *pcbFormat = bytesNeeded;
632 ret = TRUE;
634 else if (*pcbFormat < bytesNeeded)
636 *pcbFormat = bytesNeeded;
637 SetLastError(ERROR_MORE_DATA);
638 ret = FALSE;
640 else
642 static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
643 static const WCHAR endFmt[] = { '%','0','2','x',0 };
644 DWORD i;
645 LPWSTR ptr = pbFormat;
647 *pcbFormat = bytesNeeded;
648 if (cbEncoded)
650 for (i = 0; i < cbEncoded; i++)
652 if (i < cbEncoded - 1)
653 ptr += sprintfW(ptr, fmt, pbEncoded[i]);
654 else
655 ptr += sprintfW(ptr, endFmt, pbEncoded[i]);
658 else
659 *ptr = 0;
660 ret = TRUE;
662 return ret;
665 #define MAX_STRING_RESOURCE_LEN 128
667 static const WCHAR commaSpace[] = { ',',' ',0 };
669 struct BitToString
671 BYTE bit;
672 int id;
673 WCHAR str[MAX_STRING_RESOURCE_LEN];
676 static BOOL CRYPT_FormatBits(BYTE bits, const struct BitToString *map,
677 DWORD mapEntries, void *pbFormat, DWORD *pcbFormat, BOOL *first)
679 DWORD bytesNeeded = sizeof(WCHAR);
680 int i;
681 BOOL ret = TRUE, localFirst = *first;
683 for (i = 0; i < mapEntries; i++)
684 if (bits & map[i].bit)
686 if (!localFirst)
687 bytesNeeded += strlenW(commaSpace) * sizeof(WCHAR);
688 localFirst = FALSE;
689 bytesNeeded += strlenW(map[i].str) * sizeof(WCHAR);
691 if (!pbFormat)
693 *first = localFirst;
694 *pcbFormat = bytesNeeded;
696 else if (*pcbFormat < bytesNeeded)
698 *first = localFirst;
699 *pcbFormat = bytesNeeded;
700 SetLastError(ERROR_MORE_DATA);
701 ret = FALSE;
703 else
705 LPWSTR str = pbFormat;
707 localFirst = *first;
708 *pcbFormat = bytesNeeded;
709 for (i = 0; i < mapEntries; i++)
710 if (bits & map[i].bit)
712 if (!localFirst)
714 strcpyW(str, commaSpace);
715 str += strlenW(commaSpace);
717 localFirst = FALSE;
718 strcpyW(str, map[i].str);
719 str += strlenW(map[i].str);
721 *first = localFirst;
723 return ret;
726 static struct BitToString keyUsageByte0Map[] = {
727 { CERT_DIGITAL_SIGNATURE_KEY_USAGE, IDS_DIGITAL_SIGNATURE, { 0 } },
728 { CERT_NON_REPUDIATION_KEY_USAGE, IDS_NON_REPUDIATION, { 0 } },
729 { CERT_KEY_ENCIPHERMENT_KEY_USAGE, IDS_KEY_ENCIPHERMENT, { 0 } },
730 { CERT_DATA_ENCIPHERMENT_KEY_USAGE, IDS_DATA_ENCIPHERMENT, { 0 } },
731 { CERT_KEY_AGREEMENT_KEY_USAGE, IDS_KEY_AGREEMENT, { 0 } },
732 { CERT_KEY_CERT_SIGN_KEY_USAGE, IDS_CERT_SIGN, { 0 } },
733 { CERT_OFFLINE_CRL_SIGN_KEY_USAGE, IDS_OFFLINE_CRL_SIGN, { 0 } },
734 { CERT_CRL_SIGN_KEY_USAGE, IDS_CRL_SIGN, { 0 } },
735 { CERT_ENCIPHER_ONLY_KEY_USAGE, IDS_ENCIPHER_ONLY, { 0 } },
737 static struct BitToString keyUsageByte1Map[] = {
738 { CERT_DECIPHER_ONLY_KEY_USAGE, IDS_DECIPHER_ONLY, { 0 } },
741 static BOOL WINAPI CRYPT_FormatKeyUsage(DWORD dwCertEncodingType,
742 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
743 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
744 DWORD *pcbFormat)
746 DWORD size;
747 CRYPT_BIT_BLOB *bits;
748 BOOL ret;
750 if (!cbEncoded)
752 SetLastError(E_INVALIDARG);
753 return FALSE;
755 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_KEY_USAGE,
756 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
758 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
759 DWORD bytesNeeded = sizeof(WCHAR);
761 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
762 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
763 if (!bits->cbData || bits->cbData > 2)
765 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
766 if (!pbFormat)
767 *pcbFormat = bytesNeeded;
768 else if (*pcbFormat < bytesNeeded)
770 *pcbFormat = bytesNeeded;
771 SetLastError(ERROR_MORE_DATA);
772 ret = FALSE;
774 else
776 LPWSTR str = pbFormat;
778 *pcbFormat = bytesNeeded;
779 strcpyW(str, infoNotAvailable);
782 else
784 static BOOL stringsLoaded = FALSE;
785 int i;
786 DWORD bitStringLen;
787 BOOL first = TRUE;
789 if (!stringsLoaded)
791 for (i = 0;
792 i < sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]);
793 i++)
794 LoadStringW(hInstance, keyUsageByte0Map[i].id,
795 keyUsageByte0Map[i].str, MAX_STRING_RESOURCE_LEN);
796 for (i = 0;
797 i < sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]);
798 i++)
799 LoadStringW(hInstance, keyUsageByte1Map[i].id,
800 keyUsageByte1Map[i].str, MAX_STRING_RESOURCE_LEN);
801 stringsLoaded = TRUE;
803 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
804 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
805 NULL, &bitStringLen, &first);
806 bytesNeeded += bitStringLen;
807 if (bits->cbData == 2)
809 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
810 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
811 NULL, &bitStringLen, &first);
812 bytesNeeded += bitStringLen;
814 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
815 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
816 bits->cbData, NULL, &size);
817 bytesNeeded += size;
818 if (!pbFormat)
819 *pcbFormat = bytesNeeded;
820 else if (*pcbFormat < bytesNeeded)
822 *pcbFormat = bytesNeeded;
823 SetLastError(ERROR_MORE_DATA);
824 ret = FALSE;
826 else
828 LPWSTR str = pbFormat;
830 bitStringLen = bytesNeeded;
831 first = TRUE;
832 CRYPT_FormatBits(bits->pbData[0], keyUsageByte0Map,
833 sizeof(keyUsageByte0Map) / sizeof(keyUsageByte0Map[0]),
834 str, &bitStringLen, &first);
835 str += bitStringLen / sizeof(WCHAR) - 1;
836 if (bits->cbData == 2)
838 bitStringLen = bytesNeeded;
839 CRYPT_FormatBits(bits->pbData[1], keyUsageByte1Map,
840 sizeof(keyUsageByte1Map) / sizeof(keyUsageByte1Map[0]),
841 str, &bitStringLen, &first);
842 str += bitStringLen / sizeof(WCHAR) - 1;
844 *str++ = ' ';
845 *str++ = '(';
846 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
847 bits->cbData, str, &size);
848 str += size / sizeof(WCHAR) - 1;
849 *str++ = ')';
850 *str = 0;
853 LocalFree(bits);
855 return ret;
858 static const WCHAR crlf[] = { '\r','\n',0 };
860 static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN];
861 static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN];
862 static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN];
863 static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN];
865 static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType,
866 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
867 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
868 DWORD *pcbFormat)
870 DWORD size;
871 CERT_BASIC_CONSTRAINTS2_INFO *info;
872 BOOL ret;
874 if (!cbEncoded)
876 SetLastError(E_INVALIDARG);
877 return FALSE;
879 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2,
880 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
882 static const WCHAR pathFmt[] = { '%','d',0 };
883 static BOOL stringsLoaded = FALSE;
884 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
885 WCHAR pathLength[MAX_STRING_RESOURCE_LEN];
886 LPCWSTR sep, subjectType;
887 DWORD sepLen;
889 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
891 sep = crlf;
892 sepLen = strlenW(crlf) * sizeof(WCHAR);
894 else
896 sep = commaSpace;
897 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
900 if (!stringsLoaded)
902 LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader,
903 sizeof(subjectTypeHeader) / sizeof(subjectTypeHeader[0]));
904 LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA,
905 sizeof(subjectTypeCA) / sizeof(subjectTypeCA[0]));
906 LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT,
907 subjectTypeEndCert,
908 sizeof(subjectTypeEndCert) / sizeof(subjectTypeEndCert[0]));
909 LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader,
910 sizeof(pathLengthHeader) / sizeof(pathLengthHeader[0]));
911 stringsLoaded = TRUE;
913 bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR);
914 if (info->fCA)
915 subjectType = subjectTypeCA;
916 else
917 subjectType = subjectTypeEndCert;
918 bytesNeeded += strlenW(subjectType) * sizeof(WCHAR);
919 bytesNeeded += sepLen;
920 bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR);
921 if (info->fPathLenConstraint)
922 sprintfW(pathLength, pathFmt, info->dwPathLenConstraint);
923 else
924 LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength,
925 sizeof(pathLength) / sizeof(pathLength[0]));
926 bytesNeeded += strlenW(pathLength) * sizeof(WCHAR);
927 if (!pbFormat)
928 *pcbFormat = bytesNeeded;
929 else if (*pcbFormat < bytesNeeded)
931 *pcbFormat = bytesNeeded;
932 SetLastError(ERROR_MORE_DATA);
933 ret = FALSE;
935 else
937 LPWSTR str = pbFormat;
939 *pcbFormat = bytesNeeded;
940 strcpyW(str, subjectTypeHeader);
941 str += strlenW(subjectTypeHeader);
942 strcpyW(str, subjectType);
943 str += strlenW(subjectType);
944 strcpyW(str, sep);
945 str += sepLen / sizeof(WCHAR);
946 strcpyW(str, pathLengthHeader);
947 str += strlenW(pathLengthHeader);
948 strcpyW(str, pathLength);
949 str += strlenW(pathLength);
951 LocalFree(info);
953 return ret;
956 static BOOL CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB *blob, int id,
957 LPWSTR str, DWORD *pcbStr)
959 WCHAR buf[MAX_STRING_RESOURCE_LEN];
960 DWORD bytesNeeded;
961 BOOL ret;
963 LoadStringW(hInstance, id, buf, sizeof(buf) / sizeof(buf[0]));
964 CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
965 blob->pbData, blob->cbData, NULL, &bytesNeeded);
966 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
967 if (!str)
969 *pcbStr = bytesNeeded;
970 ret = TRUE;
972 else if (*pcbStr < bytesNeeded)
974 *pcbStr = bytesNeeded;
975 SetLastError(ERROR_MORE_DATA);
976 ret = FALSE;
978 else
980 *pcbStr = bytesNeeded;
981 strcpyW(str, buf);
982 str += strlenW(str);
983 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
984 ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
985 blob->pbData, blob->cbData, str, &bytesNeeded);
987 return ret;
990 static BOOL CRYPT_FormatKeyId(CRYPT_DATA_BLOB *keyId, LPWSTR str,
991 DWORD *pcbStr)
993 return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr);
996 static BOOL CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB *serialNum, LPWSTR str,
997 DWORD *pcbStr)
999 return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER,
1000 str, pcbStr);
1003 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
1004 static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
1006 static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel,
1007 CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr)
1009 BOOL ret;
1010 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1011 WCHAR mask[MAX_STRING_RESOURCE_LEN];
1012 WCHAR ipAddrBuf[32];
1013 WCHAR maskBuf[16];
1014 DWORD bytesNeeded = sizeof(WCHAR);
1015 DWORD strType = CERT_X500_NAME_STR | CERT_NAME_STR_REVERSE_FLAG;
1017 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1018 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1019 switch (entry->dwAltNameChoice)
1021 case CERT_ALT_NAME_RFC822_NAME:
1022 LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf,
1023 sizeof(buf) / sizeof(buf[0]));
1024 bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR);
1025 ret = TRUE;
1026 break;
1027 case CERT_ALT_NAME_DNS_NAME:
1028 LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf,
1029 sizeof(buf) / sizeof(buf[0]));
1030 bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR);
1031 ret = TRUE;
1032 break;
1033 case CERT_ALT_NAME_DIRECTORY_NAME:
1035 DWORD directoryNameLen;
1037 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1038 strType |= CERT_NAME_STR_CRLF_FLAG;
1039 directoryNameLen = cert_name_to_str_with_indent(X509_ASN_ENCODING,
1040 indentLevel + 1, &entry->u.DirectoryName, strType, NULL, 0);
1041 LoadStringW(hInstance, IDS_ALT_NAME_DIRECTORY_NAME, buf,
1042 sizeof(buf) / sizeof(buf[0]));
1043 bytesNeeded += (directoryNameLen - 1) * sizeof(WCHAR);
1044 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1045 bytesNeeded += strlenW(colonCrlf) * sizeof(WCHAR);
1046 else
1047 bytesNeeded += sizeof(WCHAR); /* '=' */
1048 ret = TRUE;
1049 break;
1051 case CERT_ALT_NAME_URL:
1052 LoadStringW(hInstance, IDS_ALT_NAME_URL, buf,
1053 sizeof(buf) / sizeof(buf[0]));
1054 bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR);
1055 ret = TRUE;
1056 break;
1057 case CERT_ALT_NAME_IP_ADDRESS:
1059 static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.',
1060 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
1062 static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d',
1063 '.','%','d',0 };
1065 LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf,
1066 sizeof(buf) / sizeof(buf[0]));
1067 if (entry->u.IPAddress.cbData == 8)
1069 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1071 LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask,
1072 sizeof(mask) / sizeof(mask[0]));
1073 bytesNeeded += strlenW(mask) * sizeof(WCHAR);
1074 sprintfW(ipAddrBuf, ipAddrFmt,
1075 entry->u.IPAddress.pbData[0],
1076 entry->u.IPAddress.pbData[1],
1077 entry->u.IPAddress.pbData[2],
1078 entry->u.IPAddress.pbData[3]);
1079 bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR);
1080 /* indent again, for the mask line */
1081 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
1082 sprintfW(maskBuf, ipAddrFmt,
1083 entry->u.IPAddress.pbData[4],
1084 entry->u.IPAddress.pbData[5],
1085 entry->u.IPAddress.pbData[6],
1086 entry->u.IPAddress.pbData[7]);
1087 bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR);
1088 bytesNeeded += strlenW(crlf) * sizeof(WCHAR);
1090 else
1092 sprintfW(ipAddrBuf, ipAddrWithMaskFmt,
1093 entry->u.IPAddress.pbData[0],
1094 entry->u.IPAddress.pbData[1],
1095 entry->u.IPAddress.pbData[2],
1096 entry->u.IPAddress.pbData[3],
1097 entry->u.IPAddress.pbData[4],
1098 entry->u.IPAddress.pbData[5],
1099 entry->u.IPAddress.pbData[6],
1100 entry->u.IPAddress.pbData[7]);
1101 bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR);
1103 ret = TRUE;
1105 else
1107 FIXME("unknown IP address format (%d bytes)\n",
1108 entry->u.IPAddress.cbData);
1109 ret = FALSE;
1111 break;
1113 default:
1114 FIXME("unimplemented for %d\n", entry->dwAltNameChoice);
1115 ret = FALSE;
1117 if (ret)
1119 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1120 if (!str)
1121 *pcbStr = bytesNeeded;
1122 else if (*pcbStr < bytesNeeded)
1124 *pcbStr = bytesNeeded;
1125 SetLastError(ERROR_MORE_DATA);
1126 ret = FALSE;
1128 else
1130 DWORD i;
1132 *pcbStr = bytesNeeded;
1133 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1135 for (i = 0; i < indentLevel; i++)
1137 strcpyW(str, indent);
1138 str += strlenW(indent);
1141 strcpyW(str, buf);
1142 str += strlenW(str);
1143 switch (entry->dwAltNameChoice)
1145 case CERT_ALT_NAME_RFC822_NAME:
1146 case CERT_ALT_NAME_DNS_NAME:
1147 case CERT_ALT_NAME_URL:
1148 strcpyW(str, entry->u.pwszURL);
1149 break;
1150 case CERT_ALT_NAME_DIRECTORY_NAME:
1151 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1153 strcpyW(str, colonCrlf);
1154 str += strlenW(colonCrlf);
1156 else
1157 *str++ = '=';
1158 cert_name_to_str_with_indent(X509_ASN_ENCODING,
1159 indentLevel + 1, &entry->u.DirectoryName, strType, str,
1160 bytesNeeded / sizeof(WCHAR));
1161 break;
1162 case CERT_ALT_NAME_IP_ADDRESS:
1163 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1165 strcpyW(str, ipAddrBuf);
1166 str += strlenW(ipAddrBuf);
1167 strcpyW(str, crlf);
1168 str += strlenW(crlf);
1169 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1171 for (i = 0; i < indentLevel; i++)
1173 strcpyW(str, indent);
1174 str += strlenW(indent);
1177 strcpyW(str, mask);
1178 str += strlenW(mask);
1179 strcpyW(str, maskBuf);
1181 else
1182 strcpyW(str, ipAddrBuf);
1183 break;
1187 return ret;
1190 static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel,
1191 CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr)
1193 DWORD i, size, bytesNeeded = 0;
1194 BOOL ret = TRUE;
1195 LPCWSTR sep;
1196 DWORD sepLen;
1198 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1200 sep = crlf;
1201 sepLen = strlenW(crlf) * sizeof(WCHAR);
1203 else
1205 sep = commaSpace;
1206 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1209 for (i = 0; ret && i < name->cAltEntry; i++)
1211 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1212 &name->rgAltEntry[i], NULL, &size);
1213 if (ret)
1215 bytesNeeded += size - sizeof(WCHAR);
1216 if (i < name->cAltEntry - 1)
1217 bytesNeeded += sepLen;
1220 if (ret)
1222 bytesNeeded += sizeof(WCHAR);
1223 if (!str)
1224 *pcbStr = bytesNeeded;
1225 else if (*pcbStr < bytesNeeded)
1227 *pcbStr = bytesNeeded;
1228 SetLastError(ERROR_MORE_DATA);
1229 ret = FALSE;
1231 else
1233 *pcbStr = bytesNeeded;
1234 for (i = 0; ret && i < name->cAltEntry; i++)
1236 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
1237 &name->rgAltEntry[i], str, &size);
1238 if (ret)
1240 str += size / sizeof(WCHAR) - 1;
1241 if (i < name->cAltEntry - 1)
1243 strcpyW(str, sep);
1244 str += sepLen / sizeof(WCHAR);
1250 return ret;
1253 static const WCHAR colonSep[] = { ':',' ',0 };
1255 static BOOL WINAPI CRYPT_FormatAltName(DWORD dwCertEncodingType,
1256 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1257 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1258 DWORD *pcbFormat)
1260 BOOL ret;
1261 CERT_ALT_NAME_INFO *info;
1262 DWORD size;
1264 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ALTERNATE_NAME,
1265 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1267 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, info, pbFormat, pcbFormat);
1268 LocalFree(info);
1270 return ret;
1273 static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType,
1274 CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr)
1276 WCHAR buf[MAX_STRING_RESOURCE_LEN];
1277 DWORD bytesNeeded, sepLen;
1278 LPCWSTR sep;
1279 BOOL ret;
1281 LoadStringW(hInstance, IDS_CERT_ISSUER, buf, sizeof(buf) / sizeof(buf[0]));
1282 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, NULL,
1283 &bytesNeeded);
1284 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
1285 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1287 sep = colonCrlf;
1288 sepLen = strlenW(colonCrlf) * sizeof(WCHAR);
1290 else
1292 sep = colonSep;
1293 sepLen = strlenW(colonSep) * sizeof(WCHAR);
1295 bytesNeeded += sepLen;
1296 if (ret)
1298 if (!str)
1299 *pcbStr = bytesNeeded;
1300 else if (*pcbStr < bytesNeeded)
1302 *pcbStr = bytesNeeded;
1303 SetLastError(ERROR_MORE_DATA);
1304 ret = FALSE;
1306 else
1308 *pcbStr = bytesNeeded;
1309 strcpyW(str, buf);
1310 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
1311 str += strlenW(str);
1312 strcpyW(str, sep);
1313 str += sepLen / sizeof(WCHAR);
1314 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 1, issuer, str,
1315 &bytesNeeded);
1318 return ret;
1321 static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType,
1322 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1323 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1324 DWORD *pcbFormat)
1326 CERT_AUTHORITY_KEY_ID2_INFO *info;
1327 DWORD size;
1328 BOOL ret = FALSE;
1330 if (!cbEncoded)
1332 SetLastError(E_INVALIDARG);
1333 return FALSE;
1335 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2,
1336 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1338 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1339 LPCWSTR sep;
1340 DWORD sepLen;
1341 BOOL needSeparator = FALSE;
1343 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1345 sep = crlf;
1346 sepLen = strlenW(crlf) * sizeof(WCHAR);
1348 else
1350 sep = commaSpace;
1351 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1354 if (info->KeyId.cbData)
1356 needSeparator = TRUE;
1357 ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size);
1358 if (ret)
1360 /* don't include NULL-terminator more than once */
1361 bytesNeeded += size - sizeof(WCHAR);
1364 if (info->AuthorityCertIssuer.cAltEntry)
1366 if (needSeparator)
1367 bytesNeeded += sepLen;
1368 needSeparator = TRUE;
1369 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1370 &info->AuthorityCertIssuer, NULL, &size);
1371 if (ret)
1373 /* don't include NULL-terminator more than once */
1374 bytesNeeded += size - sizeof(WCHAR);
1377 if (info->AuthorityCertSerialNumber.cbData)
1379 if (needSeparator)
1380 bytesNeeded += sepLen;
1381 ret = CRYPT_FormatCertSerialNumber(
1382 &info->AuthorityCertSerialNumber, NULL, &size);
1383 if (ret)
1385 /* don't include NULL-terminator more than once */
1386 bytesNeeded += size - sizeof(WCHAR);
1389 if (ret)
1391 if (!pbFormat)
1392 *pcbFormat = bytesNeeded;
1393 else if (*pcbFormat < bytesNeeded)
1395 *pcbFormat = bytesNeeded;
1396 SetLastError(ERROR_MORE_DATA);
1397 ret = FALSE;
1399 else
1401 LPWSTR str = pbFormat;
1403 *pcbFormat = bytesNeeded;
1404 needSeparator = FALSE;
1405 if (info->KeyId.cbData)
1407 needSeparator = TRUE;
1408 /* Overestimate size available, it's already been checked
1409 * above.
1411 size = bytesNeeded;
1412 ret = CRYPT_FormatKeyId(&info->KeyId, str, &size);
1413 if (ret)
1414 str += size / sizeof(WCHAR) - 1;
1416 if (info->AuthorityCertIssuer.cAltEntry)
1418 if (needSeparator)
1420 strcpyW(str, sep);
1421 str += sepLen / sizeof(WCHAR);
1423 needSeparator = TRUE;
1424 /* Overestimate size available, it's already been checked
1425 * above.
1427 size = bytesNeeded;
1428 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1429 &info->AuthorityCertIssuer, str, &size);
1430 if (ret)
1431 str += size / sizeof(WCHAR) - 1;
1433 if (info->AuthorityCertSerialNumber.cbData)
1435 if (needSeparator)
1437 strcpyW(str, sep);
1438 str += sepLen / sizeof(WCHAR);
1440 /* Overestimate size available, it's already been checked
1441 * above.
1443 size = bytesNeeded;
1444 ret = CRYPT_FormatCertSerialNumber(
1445 &info->AuthorityCertSerialNumber, str, &size);
1449 LocalFree(info);
1451 return ret;
1454 static WCHAR aia[MAX_STRING_RESOURCE_LEN];
1455 static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN];
1456 static WCHAR ocsp[MAX_STRING_RESOURCE_LEN];
1457 static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN];
1458 static WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1459 static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN];
1461 static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType,
1462 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1463 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1464 DWORD *pcbFormat)
1466 CERT_AUTHORITY_INFO_ACCESS *info;
1467 DWORD size;
1468 BOOL ret = FALSE;
1470 if (!cbEncoded)
1472 SetLastError(E_INVALIDARG);
1473 return FALSE;
1475 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
1476 X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG,
1477 NULL, &info, &size)))
1479 DWORD bytesNeeded = sizeof(WCHAR);
1481 if (!info->cAccDescr)
1483 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1485 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1486 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1487 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1488 if (!pbFormat)
1489 *pcbFormat = bytesNeeded;
1490 else if (*pcbFormat < bytesNeeded)
1492 *pcbFormat = bytesNeeded;
1493 SetLastError(ERROR_MORE_DATA);
1494 ret = FALSE;
1496 else
1498 *pcbFormat = bytesNeeded;
1499 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1502 else
1504 static const WCHAR numFmt[] = { '%','d',0 };
1505 static const WCHAR equal[] = { '=',0 };
1506 static BOOL stringsLoaded = FALSE;
1507 DWORD i;
1508 LPCWSTR headingSep, accessMethodSep, locationSep;
1509 WCHAR accessDescrNum[11];
1511 if (!stringsLoaded)
1513 LoadStringW(hInstance, IDS_AIA, aia,
1514 sizeof(aia) / sizeof(aia[0]));
1515 LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod,
1516 sizeof(accessMethod) / sizeof(accessMethod[0]));
1517 LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp,
1518 sizeof(ocsp) / sizeof(ocsp[0]));
1519 LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers,
1520 sizeof(caIssuers) / sizeof(caIssuers[0]));
1521 LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown,
1522 sizeof(unknown) / sizeof(unknown[0]));
1523 LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation,
1524 sizeof(accessLocation) / sizeof(accessLocation[0]));
1525 stringsLoaded = TRUE;
1527 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1529 headingSep = crlf;
1530 accessMethodSep = crlf;
1531 locationSep = colonCrlf;
1533 else
1535 headingSep = colonSep;
1536 accessMethodSep = commaSpace;
1537 locationSep = equal;
1540 for (i = 0; ret && i < info->cAccDescr; i++)
1542 /* Heading */
1543 bytesNeeded += sizeof(WCHAR); /* left bracket */
1544 sprintfW(accessDescrNum, numFmt, i + 1);
1545 bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR);
1546 bytesNeeded += sizeof(WCHAR); /* right bracket */
1547 bytesNeeded += strlenW(aia) * sizeof(WCHAR);
1548 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1549 /* Access method */
1550 bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR);
1551 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1552 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1553 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1554 szOID_PKIX_OCSP))
1555 bytesNeeded += strlenW(ocsp) * sizeof(WCHAR);
1556 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1557 szOID_PKIX_CA_ISSUERS))
1558 bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers);
1559 else
1560 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1561 bytesNeeded += sizeof(WCHAR); /* space */
1562 bytesNeeded += sizeof(WCHAR); /* left paren */
1563 bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod)
1564 * sizeof(WCHAR);
1565 bytesNeeded += sizeof(WCHAR); /* right paren */
1566 /* Delimiter between access method and location */
1567 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1568 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1569 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1570 bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR);
1571 bytesNeeded += strlenW(locationSep) * sizeof(WCHAR);
1572 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1573 &info->rgAccDescr[i].AccessLocation, NULL, &size);
1574 if (ret)
1575 bytesNeeded += size - sizeof(WCHAR);
1576 /* Need extra delimiter between access method entries */
1577 if (i < info->cAccDescr - 1)
1578 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1580 if (ret)
1582 if (!pbFormat)
1583 *pcbFormat = bytesNeeded;
1584 else if (*pcbFormat < bytesNeeded)
1586 *pcbFormat = bytesNeeded;
1587 SetLastError(ERROR_MORE_DATA);
1588 ret = FALSE;
1590 else
1592 LPWSTR str = pbFormat;
1593 DWORD altNameEntrySize;
1595 *pcbFormat = bytesNeeded;
1596 for (i = 0; ret && i < info->cAccDescr; i++)
1598 LPCSTR oidPtr;
1600 *str++ = '[';
1601 sprintfW(accessDescrNum, numFmt, i + 1);
1602 strcpyW(str, accessDescrNum);
1603 str += strlenW(accessDescrNum);
1604 *str++ = ']';
1605 strcpyW(str, aia);
1606 str += strlenW(aia);
1607 strcpyW(str, headingSep);
1608 str += strlenW(headingSep);
1609 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1611 strcpyW(str, indent);
1612 str += strlenW(indent);
1614 strcpyW(str, accessMethod);
1615 str += strlenW(accessMethod);
1616 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1617 szOID_PKIX_OCSP))
1619 strcpyW(str, ocsp);
1620 str += strlenW(ocsp);
1622 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1623 szOID_PKIX_CA_ISSUERS))
1625 strcpyW(str, caIssuers);
1626 str += strlenW(caIssuers);
1628 else
1630 strcpyW(str, unknown);
1631 str += strlenW(unknown);
1633 *str++ = ' ';
1634 *str++ = '(';
1635 for (oidPtr = info->rgAccDescr[i].pszAccessMethod;
1636 *oidPtr; oidPtr++, str++)
1637 *str = *oidPtr;
1638 *str++ = ')';
1639 strcpyW(str, accessMethodSep);
1640 str += strlenW(accessMethodSep);
1641 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1643 strcpyW(str, indent);
1644 str += strlenW(indent);
1646 strcpyW(str, accessLocation);
1647 str += strlenW(accessLocation);
1648 strcpyW(str, locationSep);
1649 str += strlenW(locationSep);
1650 /* This overestimates the size available, but that
1651 * won't matter since we checked earlier whether enough
1652 * space for the entire string was available.
1654 altNameEntrySize = bytesNeeded;
1655 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1656 &info->rgAccDescr[i].AccessLocation, str,
1657 &altNameEntrySize);
1658 if (ret)
1659 str += altNameEntrySize / sizeof(WCHAR) - 1;
1660 if (i < info->cAccDescr - 1)
1662 strcpyW(str, accessMethodSep);
1663 str += strlenW(accessMethodSep);
1669 LocalFree(info);
1671 return ret;
1674 static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN];
1675 static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN];
1676 static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN];
1677 static WCHAR superseded[MAX_STRING_RESOURCE_LEN];
1678 static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN];
1679 static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN];
1681 struct reason_map_entry
1683 BYTE reasonBit;
1684 LPWSTR reason;
1685 int id;
1687 static struct reason_map_entry reason_map[] = {
1688 { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE },
1689 { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE },
1690 { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged,
1691 IDS_REASON_AFFILIATION_CHANGED },
1692 { CRL_REASON_SUPERSEDED_FLAG, superseded, IDS_REASON_SUPERSEDED },
1693 { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased,
1694 IDS_REASON_CESSATION_OF_OPERATION },
1695 { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold,
1696 IDS_REASON_CERTIFICATE_HOLD },
1699 static BOOL CRYPT_FormatReason(DWORD dwFormatStrType,
1700 const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr)
1702 static const WCHAR sep[] = { ',',' ',0 };
1703 static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 };
1704 static BOOL stringsLoaded = FALSE;
1705 int i, numReasons = 0;
1706 BOOL ret = TRUE;
1707 DWORD bytesNeeded = sizeof(WCHAR);
1708 WCHAR bits[6];
1710 if (!stringsLoaded)
1712 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1713 LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason,
1714 MAX_STRING_RESOURCE_LEN);
1715 stringsLoaded = TRUE;
1717 /* No need to check reasonFlags->cbData, we already know it's positive.
1718 * Ignore any other bytes, as they're for undefined bits.
1720 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1722 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1724 bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR);
1725 if (numReasons++)
1726 bytesNeeded += strlenW(sep) * sizeof(WCHAR);
1729 sprintfW(bits, bitsFmt, reasonFlags->pbData[0]);
1730 bytesNeeded += strlenW(bits);
1731 if (!str)
1732 *pcbStr = bytesNeeded;
1733 else if (*pcbStr < bytesNeeded)
1735 *pcbStr = bytesNeeded;
1736 SetLastError(ERROR_MORE_DATA);
1737 ret = FALSE;
1739 else
1741 *pcbStr = bytesNeeded;
1742 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1744 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1746 strcpyW(str, reason_map[i].reason);
1747 str += strlenW(reason_map[i].reason);
1748 if (i < sizeof(reason_map) / sizeof(reason_map[0]) - 1 &&
1749 numReasons)
1751 strcpyW(str, sep);
1752 str += strlenW(sep);
1756 strcpyW(str, bits);
1758 return ret;
1761 static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN];
1762 static WCHAR distPointName[MAX_STRING_RESOURCE_LEN];
1763 static WCHAR fullName[MAX_STRING_RESOURCE_LEN];
1764 static WCHAR rdnName[MAX_STRING_RESOURCE_LEN];
1765 static WCHAR reason[MAX_STRING_RESOURCE_LEN];
1766 static WCHAR issuer[MAX_STRING_RESOURCE_LEN];
1768 static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType,
1769 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1770 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1771 DWORD *pcbFormat)
1773 CRL_DIST_POINTS_INFO *info;
1774 DWORD size;
1775 BOOL ret = FALSE;
1777 if (!cbEncoded)
1779 SetLastError(E_INVALIDARG);
1780 return FALSE;
1782 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS,
1783 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1785 static const WCHAR numFmt[] = { '%','d',0 };
1786 static const WCHAR colon[] = { ':',0 };
1787 static BOOL stringsLoaded = FALSE;
1788 DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */
1789 BOOL haveAnEntry = FALSE;
1790 LPCWSTR headingSep, nameSep;
1791 WCHAR distPointNum[11];
1792 DWORD i;
1794 if (!stringsLoaded)
1796 LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint,
1797 sizeof(crlDistPoint) / sizeof(crlDistPoint[0]));
1798 LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName,
1799 sizeof(distPointName) / sizeof(distPointName[0]));
1800 LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName,
1801 sizeof(fullName) / sizeof(fullName[0]));
1802 LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName,
1803 sizeof(rdnName) / sizeof(rdnName[0]));
1804 LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason,
1805 sizeof(reason) / sizeof(reason[0]));
1806 LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer,
1807 sizeof(issuer) / sizeof(issuer[0]));
1808 stringsLoaded = TRUE;
1810 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1812 headingSep = crlf;
1813 nameSep = colonCrlf;
1815 else
1817 headingSep = colonSep;
1818 nameSep = colon;
1821 for (i = 0; ret && i < info->cDistPoint; i++)
1823 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1825 if (distPoint->DistPointName.dwDistPointNameChoice !=
1826 CRL_DIST_POINT_NO_NAME)
1828 bytesNeeded += strlenW(distPointName) * sizeof(WCHAR);
1829 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1830 if (distPoint->DistPointName.dwDistPointNameChoice ==
1831 CRL_DIST_POINT_FULL_NAME)
1832 bytesNeeded += strlenW(fullName) * sizeof(WCHAR);
1833 else
1834 bytesNeeded += strlenW(rdnName) * sizeof(WCHAR);
1835 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1836 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1837 bytesNeeded += 2 * strlenW(indent) * sizeof(WCHAR);
1838 /* The indent level (3) is higher than when used as the issuer,
1839 * because the name is subordinate to the name type (full vs.
1840 * RDN.)
1842 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1843 &distPoint->DistPointName.u.FullName, NULL, &size);
1844 if (ret)
1845 bytesNeeded += size - sizeof(WCHAR);
1846 haveAnEntry = TRUE;
1848 else if (distPoint->ReasonFlags.cbData)
1850 bytesNeeded += strlenW(reason) * sizeof(WCHAR);
1851 ret = CRYPT_FormatReason(dwFormatStrType,
1852 &distPoint->ReasonFlags, NULL, &size);
1853 if (ret)
1854 bytesNeeded += size - sizeof(WCHAR);
1855 haveAnEntry = TRUE;
1857 else if (distPoint->CRLIssuer.cAltEntry)
1859 bytesNeeded += strlenW(issuer) * sizeof(WCHAR);
1860 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1861 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1862 &distPoint->CRLIssuer, NULL, &size);
1863 if (ret)
1864 bytesNeeded += size - sizeof(WCHAR);
1865 haveAnEntry = TRUE;
1867 if (haveAnEntry)
1869 bytesNeeded += sizeof(WCHAR); /* left bracket */
1870 sprintfW(distPointNum, numFmt, i + 1);
1871 bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR);
1872 bytesNeeded += sizeof(WCHAR); /* right bracket */
1873 bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR);
1874 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1875 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1876 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1879 if (!haveAnEntry)
1881 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1883 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1884 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1885 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1886 if (!pbFormat)
1887 *pcbFormat = bytesNeeded;
1888 else if (*pcbFormat < bytesNeeded)
1890 *pcbFormat = bytesNeeded;
1891 SetLastError(ERROR_MORE_DATA);
1892 ret = FALSE;
1894 else
1896 *pcbFormat = bytesNeeded;
1897 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1900 else
1902 if (!pbFormat)
1903 *pcbFormat = bytesNeeded;
1904 else if (*pcbFormat < bytesNeeded)
1906 *pcbFormat = bytesNeeded;
1907 SetLastError(ERROR_MORE_DATA);
1908 ret = FALSE;
1910 else
1912 LPWSTR str = pbFormat;
1914 *pcbFormat = bytesNeeded;
1915 for (i = 0; ret && i < info->cDistPoint; i++)
1917 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1919 *str++ = '[';
1920 sprintfW(distPointNum, numFmt, i + 1);
1921 strcpyW(str, distPointNum);
1922 str += strlenW(distPointNum);
1923 *str++ = ']';
1924 strcpyW(str, crlDistPoint);
1925 str += strlenW(crlDistPoint);
1926 strcpyW(str, headingSep);
1927 str += strlenW(headingSep);
1928 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1930 strcpyW(str, indent);
1931 str += strlenW(indent);
1933 if (distPoint->DistPointName.dwDistPointNameChoice !=
1934 CRL_DIST_POINT_NO_NAME)
1936 DWORD altNameSize = bytesNeeded;
1938 strcpyW(str, distPointName);
1939 str += strlenW(distPointName);
1940 strcpyW(str, nameSep);
1941 str += strlenW(nameSep);
1942 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1944 strcpyW(str, indent);
1945 str += strlenW(indent);
1946 strcpyW(str, indent);
1947 str += strlenW(indent);
1949 if (distPoint->DistPointName.dwDistPointNameChoice ==
1950 CRL_DIST_POINT_FULL_NAME)
1952 strcpyW(str, fullName);
1953 str += strlenW(fullName);
1955 else
1957 strcpyW(str, rdnName);
1958 str += strlenW(rdnName);
1960 strcpyW(str, nameSep);
1961 str += strlenW(nameSep);
1962 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1963 &distPoint->DistPointName.u.FullName, str,
1964 &altNameSize);
1965 if (ret)
1966 str += altNameSize / sizeof(WCHAR) - 1;
1968 else if (distPoint->ReasonFlags.cbData)
1970 DWORD reasonSize = bytesNeeded;
1972 strcpyW(str, reason);
1973 str += strlenW(reason);
1974 ret = CRYPT_FormatReason(dwFormatStrType,
1975 &distPoint->ReasonFlags, str, &reasonSize);
1976 if (ret)
1977 str += reasonSize / sizeof(WCHAR) - 1;
1979 else if (distPoint->CRLIssuer.cAltEntry)
1981 DWORD crlIssuerSize = bytesNeeded;
1983 strcpyW(str, issuer);
1984 str += strlenW(issuer);
1985 strcpyW(str, nameSep);
1986 str += strlenW(nameSep);
1987 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1988 &distPoint->CRLIssuer, str,
1989 &crlIssuerSize);
1990 if (ret)
1991 str += crlIssuerSize / sizeof(WCHAR) - 1;
1996 LocalFree(info);
1998 return ret;
2001 static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType,
2002 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2003 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2004 DWORD *pcbFormat)
2006 CERT_ENHKEY_USAGE *usage;
2007 DWORD size;
2008 BOOL ret = FALSE;
2010 if (!cbEncoded)
2012 SetLastError(E_INVALIDARG);
2013 return FALSE;
2015 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE,
2016 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size)))
2018 WCHAR unknown[MAX_STRING_RESOURCE_LEN];
2019 DWORD i;
2020 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
2021 LPCWSTR sep;
2022 DWORD sepLen;
2024 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2026 sep = crlf;
2027 sepLen = strlenW(crlf) * sizeof(WCHAR);
2029 else
2031 sep = commaSpace;
2032 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2035 LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown,
2036 sizeof(unknown) / sizeof(unknown[0]));
2037 for (i = 0; i < usage->cUsageIdentifier; i++)
2039 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2040 usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2042 if (info)
2043 bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR);
2044 else
2045 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
2046 bytesNeeded += sizeof(WCHAR); /* space */
2047 bytesNeeded += sizeof(WCHAR); /* left paren */
2048 bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) *
2049 sizeof(WCHAR);
2050 bytesNeeded += sizeof(WCHAR); /* right paren */
2051 if (i < usage->cUsageIdentifier - 1)
2052 bytesNeeded += sepLen;
2054 if (!pbFormat)
2055 *pcbFormat = bytesNeeded;
2056 else if (*pcbFormat < bytesNeeded)
2058 *pcbFormat = bytesNeeded;
2059 SetLastError(ERROR_MORE_DATA);
2060 ret = FALSE;
2062 else
2064 LPWSTR str = pbFormat;
2066 *pcbFormat = bytesNeeded;
2067 for (i = 0; i < usage->cUsageIdentifier; i++)
2069 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
2070 usage->rgpszUsageIdentifier[i],
2071 CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
2072 LPCSTR oidPtr;
2074 if (info)
2076 strcpyW(str, info->pwszName);
2077 str += strlenW(info->pwszName);
2079 else
2081 strcpyW(str, unknown);
2082 str += strlenW(unknown);
2084 *str++ = ' ';
2085 *str++ = '(';
2086 for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++)
2087 *str++ = *oidPtr;
2088 *str++ = ')';
2089 *str = 0;
2090 if (i < usage->cUsageIdentifier - 1)
2092 strcpyW(str, sep);
2093 str += sepLen / sizeof(WCHAR);
2097 LocalFree(usage);
2099 return ret;
2102 static struct BitToString netscapeCertTypeMap[] = {
2103 { NETSCAPE_SSL_CLIENT_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_CLIENT, { 0 } },
2104 { NETSCAPE_SSL_SERVER_AUTH_CERT_TYPE, IDS_NETSCAPE_SSL_SERVER, { 0 } },
2105 { NETSCAPE_SMIME_CERT_TYPE, IDS_NETSCAPE_SMIME, { 0 } },
2106 { NETSCAPE_SIGN_CERT_TYPE, IDS_NETSCAPE_SIGN, { 0 } },
2107 { NETSCAPE_SSL_CA_CERT_TYPE, IDS_NETSCAPE_SSL_CA, { 0 } },
2108 { NETSCAPE_SMIME_CA_CERT_TYPE, IDS_NETSCAPE_SMIME_CA, { 0 } },
2109 { NETSCAPE_SIGN_CA_CERT_TYPE, IDS_NETSCAPE_SIGN_CA, { 0 } },
2112 static BOOL WINAPI CRYPT_FormatNetscapeCertType(DWORD dwCertEncodingType,
2113 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2114 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2115 DWORD *pcbFormat)
2117 DWORD size;
2118 CRYPT_BIT_BLOB *bits;
2119 BOOL ret;
2121 if (!cbEncoded)
2123 SetLastError(E_INVALIDARG);
2124 return FALSE;
2126 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BITS,
2127 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &bits, &size)))
2129 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
2130 DWORD bytesNeeded = sizeof(WCHAR);
2132 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
2133 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
2134 if (!bits->cbData || bits->cbData > 1)
2136 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
2137 if (!pbFormat)
2138 *pcbFormat = bytesNeeded;
2139 else if (*pcbFormat < bytesNeeded)
2141 *pcbFormat = bytesNeeded;
2142 SetLastError(ERROR_MORE_DATA);
2143 ret = FALSE;
2145 else
2147 LPWSTR str = pbFormat;
2149 *pcbFormat = bytesNeeded;
2150 strcpyW(str, infoNotAvailable);
2153 else
2155 static BOOL stringsLoaded = FALSE;
2156 int i;
2157 DWORD bitStringLen;
2158 BOOL first = TRUE;
2160 if (!stringsLoaded)
2162 for (i = 0; i < sizeof(netscapeCertTypeMap) /
2163 sizeof(netscapeCertTypeMap[0]); i++)
2164 LoadStringW(hInstance, netscapeCertTypeMap[i].id,
2165 netscapeCertTypeMap[i].str, MAX_STRING_RESOURCE_LEN);
2166 stringsLoaded = TRUE;
2168 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2169 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2170 NULL, &bitStringLen, &first);
2171 bytesNeeded += bitStringLen;
2172 bytesNeeded += 3 * sizeof(WCHAR); /* " (" + ")" */
2173 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2174 bits->cbData, NULL, &size);
2175 bytesNeeded += size;
2176 if (!pbFormat)
2177 *pcbFormat = bytesNeeded;
2178 else if (*pcbFormat < bytesNeeded)
2180 *pcbFormat = bytesNeeded;
2181 SetLastError(ERROR_MORE_DATA);
2182 ret = FALSE;
2184 else
2186 LPWSTR str = pbFormat;
2188 bitStringLen = bytesNeeded;
2189 first = TRUE;
2190 CRYPT_FormatBits(bits->pbData[0], netscapeCertTypeMap,
2191 sizeof(netscapeCertTypeMap) / sizeof(netscapeCertTypeMap[0]),
2192 str, &bitStringLen, &first);
2193 str += bitStringLen / sizeof(WCHAR) - 1;
2194 *str++ = ' ';
2195 *str++ = '(';
2196 CRYPT_FormatHexString(0, 0, 0, NULL, NULL, bits->pbData,
2197 bits->cbData, str, &size);
2198 str += size / sizeof(WCHAR) - 1;
2199 *str++ = ')';
2200 *str = 0;
2203 LocalFree(bits);
2205 return ret;
2208 static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN];
2209 static WCHAR available[MAX_STRING_RESOURCE_LEN];
2210 static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN];
2211 static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN];
2212 static WCHAR yes[MAX_STRING_RESOURCE_LEN];
2213 static WCHAR no[MAX_STRING_RESOURCE_LEN];
2215 static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType,
2216 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2217 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2218 DWORD *pcbFormat)
2220 SPC_FINANCIAL_CRITERIA criteria;
2221 DWORD size = sizeof(criteria);
2222 BOOL ret = FALSE;
2224 if (!cbEncoded)
2226 SetLastError(E_INVALIDARG);
2227 return FALSE;
2229 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
2230 SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria,
2231 &size)))
2233 static BOOL stringsLoaded = FALSE;
2234 DWORD bytesNeeded = sizeof(WCHAR);
2235 LPCWSTR sep;
2236 DWORD sepLen;
2238 if (!stringsLoaded)
2240 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria,
2241 sizeof(financialCriteria) / sizeof(financialCriteria[0]));
2242 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available,
2243 sizeof(available) / sizeof(available[0]));
2244 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE,
2245 notAvailable, sizeof(notAvailable) / sizeof(notAvailable[0]));
2246 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA,
2247 meetsCriteria, sizeof(meetsCriteria) / sizeof(meetsCriteria[0]));
2248 LoadStringW(hInstance, IDS_YES, yes, sizeof(yes) / sizeof(yes[0]));
2249 LoadStringW(hInstance, IDS_NO, no, sizeof(no) / sizeof(no[0]));
2250 stringsLoaded = TRUE;
2252 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
2254 sep = crlf;
2255 sepLen = strlenW(crlf) * sizeof(WCHAR);
2257 else
2259 sep = commaSpace;
2260 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
2262 bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR);
2263 if (criteria.fFinancialInfoAvailable)
2265 bytesNeeded += strlenW(available) * sizeof(WCHAR);
2266 bytesNeeded += sepLen;
2267 bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR);
2268 if (criteria.fMeetsCriteria)
2269 bytesNeeded += strlenW(yes) * sizeof(WCHAR);
2270 else
2271 bytesNeeded += strlenW(no) * sizeof(WCHAR);
2273 else
2274 bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR);
2275 if (!pbFormat)
2276 *pcbFormat = bytesNeeded;
2277 else if (*pcbFormat < bytesNeeded)
2279 *pcbFormat = bytesNeeded;
2280 SetLastError(ERROR_MORE_DATA);
2281 ret = FALSE;
2283 else
2285 LPWSTR str = pbFormat;
2287 *pcbFormat = bytesNeeded;
2288 strcpyW(str, financialCriteria);
2289 str += strlenW(financialCriteria);
2290 if (criteria.fFinancialInfoAvailable)
2292 strcpyW(str, available);
2293 str += strlenW(available);
2294 strcpyW(str, sep);
2295 str += sepLen / sizeof(WCHAR);
2296 strcpyW(str, meetsCriteria);
2297 str += strlenW(meetsCriteria);
2298 if (criteria.fMeetsCriteria)
2299 strcpyW(str, yes);
2300 else
2301 strcpyW(str, no);
2303 else
2305 strcpyW(str, notAvailable);
2306 str += strlenW(notAvailable);
2310 return ret;
2313 static BOOL WINAPI CRYPT_FormatUnicodeString(DWORD dwCertEncodingType,
2314 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
2315 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
2316 DWORD *pcbFormat)
2318 CERT_NAME_VALUE *value;
2319 DWORD size;
2320 BOOL ret;
2322 if (!cbEncoded)
2324 SetLastError(E_INVALIDARG);
2325 return FALSE;
2327 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_UNICODE_ANY_STRING,
2328 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &value, &size)))
2330 if (!pbFormat)
2331 *pcbFormat = value->Value.cbData;
2332 else if (*pcbFormat < value->Value.cbData)
2334 *pcbFormat = value->Value.cbData;
2335 SetLastError(ERROR_MORE_DATA);
2336 ret = FALSE;
2338 else
2340 LPWSTR str = pbFormat;
2342 *pcbFormat = value->Value.cbData;
2343 strcpyW(str, (LPWSTR)value->Value.pbData);
2346 return ret;
2349 typedef BOOL (WINAPI *CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *,
2350 LPCSTR, const BYTE *, DWORD, void *, DWORD *);
2352 static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType,
2353 DWORD formatStrType, LPCSTR lpszStructType)
2355 CryptFormatObjectFunc format = NULL;
2357 if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
2359 SetLastError(ERROR_FILE_NOT_FOUND);
2360 return NULL;
2362 if (!HIWORD(lpszStructType))
2364 switch (LOWORD(lpszStructType))
2366 case LOWORD(X509_KEY_USAGE):
2367 format = CRYPT_FormatKeyUsage;
2368 break;
2369 case LOWORD(X509_ALTERNATE_NAME):
2370 format = CRYPT_FormatAltName;
2371 break;
2372 case LOWORD(X509_BASIC_CONSTRAINTS2):
2373 format = CRYPT_FormatBasicConstraints2;
2374 break;
2375 case LOWORD(X509_AUTHORITY_KEY_ID2):
2376 format = CRYPT_FormatAuthorityKeyId2;
2377 break;
2378 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
2379 format = CRYPT_FormatAuthorityInfoAccess;
2380 break;
2381 case LOWORD(X509_CRL_DIST_POINTS):
2382 format = CRYPT_FormatCRLDistPoints;
2383 break;
2384 case LOWORD(X509_ENHANCED_KEY_USAGE):
2385 format = CRYPT_FormatEnhancedKeyUsage;
2386 break;
2387 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT):
2388 format = CRYPT_FormatSpcFinancialCriteria;
2389 break;
2392 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME))
2393 format = CRYPT_FormatAltName;
2394 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME))
2395 format = CRYPT_FormatAltName;
2396 else if (!strcmp(lpszStructType, szOID_KEY_USAGE))
2397 format = CRYPT_FormatKeyUsage;
2398 else if (!strcmp(lpszStructType, szOID_SUBJECT_ALT_NAME2))
2399 format = CRYPT_FormatAltName;
2400 else if (!strcmp(lpszStructType, szOID_ISSUER_ALT_NAME2))
2401 format = CRYPT_FormatAltName;
2402 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
2403 format = CRYPT_FormatBasicConstraints2;
2404 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
2405 format = CRYPT_FormatAuthorityInfoAccess;
2406 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
2407 format = CRYPT_FormatAuthorityKeyId2;
2408 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
2409 format = CRYPT_FormatCRLDistPoints;
2410 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
2411 format = CRYPT_FormatEnhancedKeyUsage;
2412 else if (!strcmp(lpszStructType, szOID_NETSCAPE_CERT_TYPE))
2413 format = CRYPT_FormatNetscapeCertType;
2414 else if (!strcmp(lpszStructType, szOID_NETSCAPE_BASE_URL) ||
2415 !strcmp(lpszStructType, szOID_NETSCAPE_REVOCATION_URL) ||
2416 !strcmp(lpszStructType, szOID_NETSCAPE_CA_REVOCATION_URL) ||
2417 !strcmp(lpszStructType, szOID_NETSCAPE_CERT_RENEWAL_URL) ||
2418 !strcmp(lpszStructType, szOID_NETSCAPE_CA_POLICY_URL) ||
2419 !strcmp(lpszStructType, szOID_NETSCAPE_SSL_SERVER_NAME) ||
2420 !strcmp(lpszStructType, szOID_NETSCAPE_COMMENT))
2421 format = CRYPT_FormatUnicodeString;
2422 else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID))
2423 format = CRYPT_FormatSpcFinancialCriteria;
2424 return format;
2427 BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType,
2428 DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
2429 const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat)
2431 CryptFormatObjectFunc format = NULL;
2432 HCRYPTOIDFUNCADDR hFunc = NULL;
2433 BOOL ret = FALSE;
2435 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType,
2436 dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType),
2437 pbEncoded, cbEncoded, pbFormat, pcbFormat);
2439 if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType,
2440 dwFormatStrType, lpszStructType)))
2442 static HCRYPTOIDFUNCSET set = NULL;
2444 if (!set)
2445 set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0);
2446 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
2447 (void **)&format, &hFunc);
2449 if (!format && (dwCertEncodingType & CERT_ENCODING_TYPE_MASK) ==
2450 X509_ASN_ENCODING && !(dwFormatStrType & CRYPT_FORMAT_STR_NO_HEX))
2451 format = CRYPT_FormatHexString;
2452 if (format)
2453 ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType,
2454 pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat,
2455 pcbFormat);
2456 if (hFunc)
2457 CryptFreeOIDFunctionAddress(hFunc, 0);
2458 return ret;