crypt32: Don't underreport the size available when formatting szOID_AUTHORITY_KEY_IDE...
[wine/hacks.git] / dlls / crypt32 / object.c
blobf5a64839c7724bf6707c3a121723c184bb6f7437
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_QueryContextObject(DWORD dwObjectType, const void *pvObject,
65 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
66 DWORD *pdwContentType, HCERTSTORE *phCertStore, const void **ppvContext)
68 CERT_BLOB fileBlob;
69 const CERT_BLOB *blob;
70 HCERTSTORE store;
71 DWORD contentType;
72 BOOL ret;
74 switch (dwObjectType)
76 case CERT_QUERY_OBJECT_FILE:
77 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
78 * just read the file directly
80 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
81 blob = &fileBlob;
82 break;
83 case CERT_QUERY_OBJECT_BLOB:
84 blob = (const CERT_BLOB *)pvObject;
85 ret = TRUE;
86 break;
87 default:
88 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
89 ret = FALSE;
91 if (!ret)
92 return FALSE;
94 store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
95 CERT_STORE_CREATE_NEW_FLAG, NULL);
96 ret = FALSE;
97 if (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT)
99 ret = pCertInterface->addEncodedToStore(store, X509_ASN_ENCODING,
100 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
101 if (ret)
102 contentType = CERT_QUERY_CONTENT_CERT;
104 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL))
106 ret = pCRLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
107 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
108 if (ret)
109 contentType = CERT_QUERY_CONTENT_CRL;
111 if (!ret && (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
113 ret = pCTLInterface->addEncodedToStore(store, X509_ASN_ENCODING,
114 blob->pbData, blob->cbData, CERT_STORE_ADD_ALWAYS, ppvContext);
115 if (ret)
116 contentType = CERT_QUERY_CONTENT_CTL;
118 if (ret)
120 if (pdwMsgAndCertEncodingType)
121 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
122 if (pdwContentType)
123 *pdwContentType = contentType;
124 if (phCertStore)
125 *phCertStore = CertDuplicateStore(store);
127 CertCloseStore(store, 0);
128 if (blob == &fileBlob)
129 CryptMemFree(blob->pbData);
130 TRACE("returning %d\n", ret);
131 return ret;
134 static BOOL CRYPT_QuerySerializedContextObject(DWORD dwObjectType,
135 const void *pvObject, DWORD dwExpectedContentTypeFlags,
136 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
137 HCERTSTORE *phCertStore, const void **ppvContext)
139 CERT_BLOB fileBlob;
140 const CERT_BLOB *blob;
141 const WINE_CONTEXT_INTERFACE *contextInterface = NULL;
142 const void *context;
143 DWORD contextType;
144 BOOL ret;
146 switch (dwObjectType)
148 case CERT_QUERY_OBJECT_FILE:
149 /* Cert, CRL, and CTL contexts can't be "embedded" in a file, so
150 * just read the file directly
152 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
153 blob = &fileBlob;
154 break;
155 case CERT_QUERY_OBJECT_BLOB:
156 blob = (const CERT_BLOB *)pvObject;
157 ret = TRUE;
158 break;
159 default:
160 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
161 ret = FALSE;
163 if (!ret)
164 return FALSE;
166 context = CRYPT_ReadSerializedElement(blob->pbData, blob->cbData,
167 CERT_STORE_ALL_CONTEXT_FLAG, &contextType);
168 if (context)
170 DWORD contentType, certStoreOffset;
172 ret = TRUE;
173 switch (contextType)
175 case CERT_STORE_CERTIFICATE_CONTEXT:
176 contextInterface = pCertInterface;
177 contentType = CERT_QUERY_CONTENT_SERIALIZED_CERT;
178 certStoreOffset = offsetof(CERT_CONTEXT, hCertStore);
179 if (!(dwExpectedContentTypeFlags &
180 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT))
182 SetLastError(ERROR_INVALID_DATA);
183 ret = FALSE;
184 goto end;
186 break;
187 case CERT_STORE_CRL_CONTEXT:
188 contextInterface = pCRLInterface;
189 contentType = CERT_QUERY_CONTENT_SERIALIZED_CRL;
190 certStoreOffset = offsetof(CRL_CONTEXT, hCertStore);
191 if (!(dwExpectedContentTypeFlags &
192 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL))
194 SetLastError(ERROR_INVALID_DATA);
195 ret = FALSE;
196 goto end;
198 break;
199 case CERT_STORE_CTL_CONTEXT:
200 contextInterface = pCTLInterface;
201 contentType = CERT_QUERY_CONTENT_SERIALIZED_CTL;
202 certStoreOffset = offsetof(CTL_CONTEXT, hCertStore);
203 if (!(dwExpectedContentTypeFlags &
204 CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL))
206 SetLastError(ERROR_INVALID_DATA);
207 ret = FALSE;
208 goto end;
210 break;
211 default:
212 SetLastError(ERROR_INVALID_DATA);
213 ret = FALSE;
214 goto end;
216 if (pdwMsgAndCertEncodingType)
217 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
218 if (pdwContentType)
219 *pdwContentType = contentType;
220 if (phCertStore)
221 *phCertStore = CertDuplicateStore(
222 *(HCERTSTORE *)((const BYTE *)context + certStoreOffset));
223 if (ppvContext)
224 *ppvContext = contextInterface->duplicate(context);
227 end:
228 if (contextInterface && context)
229 contextInterface->free(context);
230 if (blob == &fileBlob)
231 CryptMemFree(blob->pbData);
232 TRACE("returning %d\n", ret);
233 return ret;
236 static BOOL CRYPT_QuerySerializedStoreObject(DWORD dwObjectType,
237 const void *pvObject, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
238 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
240 LPCWSTR fileName = (LPCWSTR)pvObject;
241 HANDLE file;
242 BOOL ret = FALSE;
244 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
246 FIXME("unimplemented for non-file type %d\n", dwObjectType);
247 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
248 return FALSE;
250 TRACE("%s\n", debugstr_w(fileName));
251 file = CreateFileW(fileName, GENERIC_READ, FILE_SHARE_READ, NULL,
252 OPEN_EXISTING, 0, NULL);
253 if (file != INVALID_HANDLE_VALUE)
255 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
256 CERT_STORE_CREATE_NEW_FLAG, NULL);
258 ret = CRYPT_ReadSerializedStoreFromFile(file, store);
259 if (ret)
261 if (pdwMsgAndCertEncodingType)
262 *pdwMsgAndCertEncodingType = X509_ASN_ENCODING;
263 if (pdwContentType)
264 *pdwContentType = CERT_QUERY_CONTENT_SERIALIZED_STORE;
265 if (phCertStore)
266 *phCertStore = CertDuplicateStore(store);
268 CertCloseStore(store, 0);
269 CloseHandle(file);
271 TRACE("returning %d\n", ret);
272 return ret;
275 /* Used to decode non-embedded messages */
276 static BOOL CRYPT_QueryMessageObject(DWORD dwObjectType, const void *pvObject,
277 DWORD dwExpectedContentTypeFlags, DWORD *pdwMsgAndCertEncodingType,
278 DWORD *pdwContentType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
280 CERT_BLOB fileBlob;
281 const CERT_BLOB *blob;
282 BOOL ret;
283 HCRYPTMSG msg = NULL;
284 DWORD encodingType = X509_ASN_ENCODING | PKCS_7_ASN_ENCODING;
286 switch (dwObjectType)
288 case CERT_QUERY_OBJECT_FILE:
289 /* This isn't an embedded PKCS7 message, so just read the file
290 * directly
292 ret = CRYPT_ReadBlobFromFile((LPCWSTR)pvObject, &fileBlob);
293 blob = &fileBlob;
294 break;
295 case CERT_QUERY_OBJECT_BLOB:
296 blob = (const CERT_BLOB *)pvObject;
297 ret = TRUE;
298 break;
299 default:
300 SetLastError(E_INVALIDARG); /* FIXME: is this the correct error? */
301 ret = FALSE;
303 if (!ret)
304 return FALSE;
306 ret = FALSE;
307 /* Try it first as a PKCS content info */
308 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
309 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
311 msg = CryptMsgOpenToDecode(encodingType, 0, 0, 0, NULL, NULL);
312 if (msg)
314 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
315 if (ret)
317 DWORD type, len = sizeof(type);
319 ret = CryptMsgGetParam(msg, CMSG_TYPE_PARAM, 0, &type, &len);
320 if (ret)
322 if ((dwExpectedContentTypeFlags &
323 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
325 if (type != CMSG_SIGNED)
327 SetLastError(ERROR_INVALID_DATA);
328 ret = FALSE;
330 else if (pdwContentType)
331 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
333 else if ((dwExpectedContentTypeFlags &
334 CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
336 if (type != CMSG_DATA)
338 SetLastError(ERROR_INVALID_DATA);
339 ret = FALSE;
341 else if (pdwContentType)
342 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
346 if (!ret)
348 CryptMsgClose(msg);
349 msg = NULL;
353 /* Failing that, try explicitly typed messages */
354 if (!ret &&
355 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED))
357 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_SIGNED, 0, NULL, NULL);
358 if (msg)
360 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
361 if (!ret)
363 CryptMsgClose(msg);
364 msg = NULL;
367 if (msg && pdwContentType)
368 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_SIGNED;
370 if (!ret &&
371 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED))
373 msg = CryptMsgOpenToDecode(encodingType, 0, CMSG_DATA, 0, NULL, NULL);
374 if (msg)
376 ret = CryptMsgUpdate(msg, blob->pbData, blob->cbData, TRUE);
377 if (!ret)
379 CryptMsgClose(msg);
380 msg = NULL;
383 if (msg && pdwContentType)
384 *pdwContentType = CERT_QUERY_CONTENT_PKCS7_UNSIGNED;
386 if (pdwMsgAndCertEncodingType)
387 *pdwMsgAndCertEncodingType = encodingType;
388 if (msg)
390 if (phMsg)
391 *phMsg = msg;
392 if (phCertStore)
393 *phCertStore = CertOpenStore(CERT_STORE_PROV_MSG, encodingType, 0,
394 0, msg);
396 if (blob == &fileBlob)
397 CryptMemFree(blob->pbData);
398 TRACE("returning %d\n", ret);
399 return ret;
402 static BOOL CRYPT_QueryEmbeddedMessageObject(DWORD dwObjectType,
403 const void *pvObject, DWORD dwExpectedContentTypeFlags,
404 DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
405 HCERTSTORE *phCertStore, HCRYPTMSG *phMsg)
407 HANDLE file;
408 GUID subject;
409 BOOL ret = FALSE;
411 TRACE("%s\n", debugstr_w((LPCWSTR)pvObject));
413 if (dwObjectType != CERT_QUERY_OBJECT_FILE)
415 FIXME("don't know what to do for type %d embedded signed messages\n",
416 dwObjectType);
417 SetLastError(E_INVALIDARG);
418 return FALSE;
420 file = CreateFileW((LPCWSTR)pvObject, GENERIC_READ, FILE_SHARE_READ,
421 NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
422 if (file != INVALID_HANDLE_VALUE)
424 ret = CryptSIPRetrieveSubjectGuid((LPCWSTR)pvObject, file, &subject);
425 if (ret)
427 SIP_DISPATCH_INFO sip;
429 memset(&sip, 0, sizeof(sip));
430 sip.cbSize = sizeof(sip);
431 ret = CryptSIPLoad(&subject, 0, &sip);
432 if (ret)
434 SIP_SUBJECTINFO subjectInfo;
435 CERT_BLOB blob;
436 DWORD encodingType;
438 memset(&subjectInfo, 0, sizeof(subjectInfo));
439 subjectInfo.cbSize = sizeof(subjectInfo);
440 subjectInfo.pgSubjectType = &subject;
441 subjectInfo.hFile = file;
442 subjectInfo.pwsFileName = (LPCWSTR)pvObject;
443 ret = sip.pfGet(&subjectInfo, &encodingType, 0, &blob.cbData,
444 NULL);
445 if (ret)
447 blob.pbData = CryptMemAlloc(blob.cbData);
448 if (blob.pbData)
450 ret = sip.pfGet(&subjectInfo, &encodingType, 0,
451 &blob.cbData, blob.pbData);
452 if (ret)
454 ret = CRYPT_QueryMessageObject(
455 CERT_QUERY_OBJECT_BLOB, &blob,
456 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED,
457 pdwMsgAndCertEncodingType, NULL, phCertStore,
458 phMsg);
459 if (ret && pdwContentType)
460 *pdwContentType =
461 CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED;
463 CryptMemFree(blob.pbData);
465 else
467 SetLastError(ERROR_OUTOFMEMORY);
468 ret = FALSE;
473 CloseHandle(file);
475 TRACE("returning %d\n", ret);
476 return ret;
479 BOOL WINAPI CryptQueryObject(DWORD dwObjectType, const void *pvObject,
480 DWORD dwExpectedContentTypeFlags, DWORD dwExpectedFormatTypeFlags,
481 DWORD dwFlags, DWORD *pdwMsgAndCertEncodingType, DWORD *pdwContentType,
482 DWORD *pdwFormatType, HCERTSTORE *phCertStore, HCRYPTMSG *phMsg,
483 const void **ppvContext)
485 static const DWORD unimplementedTypes =
486 CERT_QUERY_CONTENT_FLAG_PKCS10 | CERT_QUERY_CONTENT_FLAG_PFX |
487 CERT_QUERY_CONTENT_FLAG_CERT_PAIR;
488 BOOL ret = TRUE;
490 TRACE("(%08x, %p, %08x, %08x, %08x, %p, %p, %p, %p, %p, %p)\n",
491 dwObjectType, pvObject, dwExpectedContentTypeFlags,
492 dwExpectedFormatTypeFlags, dwFlags, pdwMsgAndCertEncodingType,
493 pdwContentType, pdwFormatType, phCertStore, phMsg, ppvContext);
495 if (dwExpectedContentTypeFlags & unimplementedTypes)
496 WARN("unimplemented for types %08x\n",
497 dwExpectedContentTypeFlags & unimplementedTypes);
498 if (!(dwExpectedFormatTypeFlags & CERT_QUERY_FORMAT_FLAG_BINARY))
500 FIXME("unimplemented for anything but binary\n");
501 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
502 return FALSE;
504 if (pdwFormatType)
505 *pdwFormatType = CERT_QUERY_FORMAT_BINARY;
507 if (phCertStore)
508 *phCertStore = NULL;
509 if (phMsg)
510 *phMsg = NULL;
511 if (ppvContext)
512 *ppvContext = NULL;
514 ret = FALSE;
515 if ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CERT) ||
516 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CRL) ||
517 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_CTL))
519 ret = CRYPT_QueryContextObject(dwObjectType, pvObject,
520 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
521 phCertStore, ppvContext);
523 if (!ret &&
524 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE))
526 ret = CRYPT_QuerySerializedStoreObject(dwObjectType, pvObject,
527 pdwMsgAndCertEncodingType, pdwContentType, phCertStore, phMsg);
529 if (!ret &&
530 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT) ||
531 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL) ||
532 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL)))
534 ret = CRYPT_QuerySerializedContextObject(dwObjectType, pvObject,
535 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
536 phCertStore, ppvContext);
538 if (!ret &&
539 ((dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED) ||
540 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED)))
542 ret = CRYPT_QueryMessageObject(dwObjectType, pvObject,
543 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
544 phCertStore, phMsg);
546 if (!ret &&
547 (dwExpectedContentTypeFlags & CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED))
549 ret = CRYPT_QueryEmbeddedMessageObject(dwObjectType, pvObject,
550 dwExpectedContentTypeFlags, pdwMsgAndCertEncodingType, pdwContentType,
551 phCertStore, phMsg);
553 TRACE("returning %d\n", ret);
554 return ret;
557 static BOOL WINAPI CRYPT_FormatHexString(DWORD dwCertEncodingType,
558 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
559 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
560 DWORD *pcbFormat)
562 BOOL ret;
563 DWORD bytesNeeded;
565 if (cbEncoded)
566 bytesNeeded = (cbEncoded * 3) * sizeof(WCHAR);
567 else
568 bytesNeeded = sizeof(WCHAR);
569 if (!pbFormat)
571 *pcbFormat = bytesNeeded;
572 ret = TRUE;
574 else if (*pcbFormat < bytesNeeded)
576 *pcbFormat = bytesNeeded;
577 SetLastError(ERROR_MORE_DATA);
578 ret = FALSE;
580 else
582 static const WCHAR fmt[] = { '%','0','2','x',' ',0 };
583 static const WCHAR endFmt[] = { '%','0','2','x',0 };
584 DWORD i;
585 LPWSTR ptr = pbFormat;
587 *pcbFormat = bytesNeeded;
588 if (cbEncoded)
590 for (i = 0; i < cbEncoded; i++)
592 if (i < cbEncoded - 1)
593 ptr += sprintfW(ptr, fmt, pbEncoded[i]);
594 else
595 ptr += sprintfW(ptr, endFmt, pbEncoded[i]);
598 else
599 *ptr = 0;
600 ret = TRUE;
602 return ret;
605 #define MAX_STRING_RESOURCE_LEN 128
607 static const WCHAR crlf[] = { '\r','\n',0 };
608 static const WCHAR commaSpace[] = { ',',' ',0 };
610 static WCHAR subjectTypeHeader[MAX_STRING_RESOURCE_LEN];
611 static WCHAR subjectTypeCA[MAX_STRING_RESOURCE_LEN];
612 static WCHAR subjectTypeEndCert[MAX_STRING_RESOURCE_LEN];
613 static WCHAR pathLengthHeader[MAX_STRING_RESOURCE_LEN];
615 static BOOL WINAPI CRYPT_FormatBasicConstraints2(DWORD dwCertEncodingType,
616 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
617 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
618 DWORD *pcbFormat)
620 DWORD size;
621 CERT_BASIC_CONSTRAINTS2_INFO *info;
622 BOOL ret;
624 if (!cbEncoded)
626 SetLastError(E_INVALIDARG);
627 return FALSE;
629 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_BASIC_CONSTRAINTS2,
630 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
632 static const WCHAR pathFmt[] = { '%','d',0 };
633 static BOOL stringsLoaded = FALSE;
634 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
635 WCHAR pathLength[MAX_STRING_RESOURCE_LEN];
636 LPCWSTR sep, subjectType;
637 DWORD sepLen;
639 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
641 sep = crlf;
642 sepLen = strlenW(crlf) * sizeof(WCHAR);
644 else
646 sep = commaSpace;
647 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
650 if (!stringsLoaded)
652 LoadStringW(hInstance, IDS_SUBJECT_TYPE, subjectTypeHeader,
653 sizeof(subjectTypeHeader) / sizeof(subjectTypeHeader[0]));
654 LoadStringW(hInstance, IDS_SUBJECT_TYPE_CA, subjectTypeCA,
655 sizeof(subjectTypeCA) / sizeof(subjectTypeCA[0]));
656 LoadStringW(hInstance, IDS_SUBJECT_TYPE_END_CERT,
657 subjectTypeEndCert,
658 sizeof(subjectTypeEndCert) / sizeof(subjectTypeEndCert[0]));
659 LoadStringW(hInstance, IDS_PATH_LENGTH, pathLengthHeader,
660 sizeof(pathLengthHeader) / sizeof(pathLengthHeader[0]));
661 stringsLoaded = TRUE;
663 bytesNeeded += strlenW(subjectTypeHeader) * sizeof(WCHAR);
664 if (info->fCA)
665 subjectType = subjectTypeCA;
666 else
667 subjectType = subjectTypeEndCert;
668 bytesNeeded += strlenW(subjectType) * sizeof(WCHAR);
669 bytesNeeded += sepLen;
670 bytesNeeded += strlenW(pathLengthHeader) * sizeof(WCHAR);
671 if (info->fPathLenConstraint)
672 sprintfW(pathLength, pathFmt, info->dwPathLenConstraint);
673 else
674 LoadStringW(hInstance, IDS_PATH_LENGTH_NONE, pathLength,
675 sizeof(pathLength) / sizeof(pathLength[0]));
676 bytesNeeded += strlenW(pathLength) * sizeof(WCHAR);
677 if (!pbFormat)
678 *pcbFormat = bytesNeeded;
679 else if (*pcbFormat < bytesNeeded)
681 *pcbFormat = bytesNeeded;
682 SetLastError(ERROR_MORE_DATA);
683 ret = FALSE;
685 else
687 LPWSTR str = pbFormat;
689 *pcbFormat = bytesNeeded;
690 strcpyW(str, subjectTypeHeader);
691 str += strlenW(subjectTypeHeader);
692 strcpyW(str, subjectType);
693 str += strlenW(subjectType);
694 strcpyW(str, sep);
695 str += sepLen / sizeof(WCHAR);
696 strcpyW(str, pathLengthHeader);
697 str += strlenW(pathLengthHeader);
698 strcpyW(str, pathLength);
699 str += strlenW(pathLength);
701 LocalFree(info);
703 return ret;
706 static BOOL CRYPT_FormatHexStringWithPrefix(CRYPT_DATA_BLOB *blob, int id,
707 LPWSTR str, DWORD *pcbStr)
709 WCHAR buf[MAX_STRING_RESOURCE_LEN];
710 DWORD bytesNeeded;
711 BOOL ret;
713 LoadStringW(hInstance, id, buf, sizeof(buf) / sizeof(buf[0]));
714 CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
715 blob->pbData, blob->cbData, NULL, &bytesNeeded);
716 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
717 if (!str)
719 *pcbStr = bytesNeeded;
720 ret = TRUE;
722 else if (*pcbStr < bytesNeeded)
724 *pcbStr = bytesNeeded;
725 SetLastError(ERROR_MORE_DATA);
726 ret = FALSE;
728 else
730 *pcbStr = bytesNeeded;
731 strcpyW(str, buf);
732 str += strlenW(str);
733 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
734 ret = CRYPT_FormatHexString(X509_ASN_ENCODING, 0, 0, NULL, NULL,
735 blob->pbData, blob->cbData, str, &bytesNeeded);
737 return ret;
740 static BOOL CRYPT_FormatKeyId(CRYPT_DATA_BLOB *keyId, LPWSTR str,
741 DWORD *pcbStr)
743 return CRYPT_FormatHexStringWithPrefix(keyId, IDS_KEY_ID, str, pcbStr);
746 static BOOL CRYPT_FormatCertSerialNumber(CRYPT_DATA_BLOB *serialNum, LPWSTR str,
747 DWORD *pcbStr)
749 return CRYPT_FormatHexStringWithPrefix(serialNum, IDS_CERT_SERIAL_NUMBER,
750 str, pcbStr);
753 static const WCHAR indent[] = { ' ',' ',' ',' ',' ',0 };
755 static BOOL CRYPT_FormatAltNameEntry(DWORD dwFormatStrType, DWORD indentLevel,
756 CERT_ALT_NAME_ENTRY *entry, LPWSTR str, DWORD *pcbStr)
758 BOOL ret;
759 WCHAR buf[MAX_STRING_RESOURCE_LEN];
760 WCHAR mask[MAX_STRING_RESOURCE_LEN];
761 WCHAR ipAddrBuf[32];
762 WCHAR maskBuf[16];
763 DWORD bytesNeeded = sizeof(WCHAR);
765 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
766 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
767 switch (entry->dwAltNameChoice)
769 case CERT_ALT_NAME_RFC822_NAME:
770 LoadStringW(hInstance, IDS_ALT_NAME_RFC822_NAME, buf,
771 sizeof(buf) / sizeof(buf[0]));
772 bytesNeeded += strlenW(entry->u.pwszRfc822Name) * sizeof(WCHAR);
773 ret = TRUE;
774 break;
775 case CERT_ALT_NAME_DNS_NAME:
776 LoadStringW(hInstance, IDS_ALT_NAME_DNS_NAME, buf,
777 sizeof(buf) / sizeof(buf[0]));
778 bytesNeeded += strlenW(entry->u.pwszDNSName) * sizeof(WCHAR);
779 ret = TRUE;
780 break;
781 case CERT_ALT_NAME_URL:
782 LoadStringW(hInstance, IDS_ALT_NAME_URL, buf,
783 sizeof(buf) / sizeof(buf[0]));
784 bytesNeeded += strlenW(entry->u.pwszURL) * sizeof(WCHAR);
785 ret = TRUE;
786 break;
787 case CERT_ALT_NAME_IP_ADDRESS:
789 static const WCHAR ipAddrWithMaskFmt[] = { '%','d','.','%','d','.',
790 '%','d','.','%','d','/','%','d','.','%','d','.','%','d','.','%','d',0
792 static const WCHAR ipAddrFmt[] = { '%','d','.','%','d','.','%','d',
793 '.','%','d',0 };
795 LoadStringW(hInstance, IDS_ALT_NAME_IP_ADDRESS, buf,
796 sizeof(buf) / sizeof(buf[0]));
797 if (entry->u.IPAddress.cbData == 8)
799 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
801 LoadStringW(hInstance, IDS_ALT_NAME_MASK, mask,
802 sizeof(mask) / sizeof(mask[0]));
803 bytesNeeded += strlenW(mask) * sizeof(WCHAR);
804 sprintfW(ipAddrBuf, ipAddrFmt,
805 entry->u.IPAddress.pbData[0],
806 entry->u.IPAddress.pbData[1],
807 entry->u.IPAddress.pbData[2],
808 entry->u.IPAddress.pbData[3]);
809 bytesNeeded += strlenW(ipAddrBuf) * sizeof(WCHAR);
810 /* indent again, for the mask line */
811 bytesNeeded += indentLevel * strlenW(indent) * sizeof(WCHAR);
812 sprintfW(maskBuf, ipAddrFmt,
813 entry->u.IPAddress.pbData[4],
814 entry->u.IPAddress.pbData[5],
815 entry->u.IPAddress.pbData[6],
816 entry->u.IPAddress.pbData[7]);
817 bytesNeeded += strlenW(maskBuf) * sizeof(WCHAR);
818 bytesNeeded += strlenW(crlf) * sizeof(WCHAR);
820 else
822 sprintfW(ipAddrBuf, ipAddrWithMaskFmt,
823 entry->u.IPAddress.pbData[0],
824 entry->u.IPAddress.pbData[1],
825 entry->u.IPAddress.pbData[2],
826 entry->u.IPAddress.pbData[3],
827 entry->u.IPAddress.pbData[4],
828 entry->u.IPAddress.pbData[5],
829 entry->u.IPAddress.pbData[6],
830 entry->u.IPAddress.pbData[7]);
831 bytesNeeded += (strlenW(ipAddrBuf) + 1) * sizeof(WCHAR);
833 ret = TRUE;
835 else
837 FIXME("unknown IP address format (%d bytes)\n",
838 entry->u.IPAddress.cbData);
839 ret = FALSE;
841 break;
843 default:
844 FIXME("unimplemented for %d\n", entry->dwAltNameChoice);
845 ret = FALSE;
847 if (ret)
849 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
850 if (!str)
851 *pcbStr = bytesNeeded;
852 else if (*pcbStr < bytesNeeded)
854 *pcbStr = bytesNeeded;
855 SetLastError(ERROR_MORE_DATA);
856 ret = FALSE;
858 else
860 DWORD i;
862 *pcbStr = bytesNeeded;
863 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
865 for (i = 0; i < indentLevel; i++)
867 strcpyW(str, indent);
868 str += strlenW(indent);
871 strcpyW(str, buf);
872 str += strlenW(str);
873 switch (entry->dwAltNameChoice)
875 case CERT_ALT_NAME_RFC822_NAME:
876 case CERT_ALT_NAME_DNS_NAME:
877 case CERT_ALT_NAME_URL:
878 strcpyW(str, entry->u.pwszURL);
879 break;
880 case CERT_ALT_NAME_IP_ADDRESS:
881 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
883 strcpyW(str, ipAddrBuf);
884 str += strlenW(ipAddrBuf);
885 strcpyW(str, crlf);
886 str += strlenW(crlf);
887 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
889 for (i = 0; i < indentLevel; i++)
891 strcpyW(str, indent);
892 str += strlenW(indent);
895 strcpyW(str, mask);
896 str += strlenW(mask);
897 strcpyW(str, maskBuf);
899 else
900 strcpyW(str, ipAddrBuf);
901 break;
905 return ret;
908 static BOOL CRYPT_FormatAltNameInfo(DWORD dwFormatStrType, DWORD indentLevel,
909 CERT_ALT_NAME_INFO *name, LPWSTR str, DWORD *pcbStr)
911 DWORD i, size, bytesNeeded = 0;
912 BOOL ret = TRUE;
913 LPCWSTR sep;
914 DWORD sepLen;
916 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
918 sep = crlf;
919 sepLen = strlenW(crlf) * sizeof(WCHAR);
921 else
923 sep = commaSpace;
924 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
927 for (i = 0; ret && i < name->cAltEntry; i++)
929 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
930 &name->rgAltEntry[i], NULL, &size);
931 if (ret)
933 bytesNeeded += size - sizeof(WCHAR);
934 if (i < name->cAltEntry - 1)
935 bytesNeeded += sepLen;
938 if (ret)
940 bytesNeeded += sizeof(WCHAR);
941 if (!str)
942 *pcbStr = bytesNeeded;
943 else if (*pcbStr < bytesNeeded)
945 *pcbStr = bytesNeeded;
946 SetLastError(ERROR_MORE_DATA);
947 ret = FALSE;
949 else
951 *pcbStr = bytesNeeded;
952 for (i = 0; ret && i < name->cAltEntry; i++)
954 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, indentLevel,
955 &name->rgAltEntry[i], str, &size);
956 if (ret)
958 str += size / sizeof(WCHAR) - 1;
959 if (i < name->cAltEntry - 1)
961 strcpyW(str, sep);
962 str += sepLen / sizeof(WCHAR);
968 return ret;
971 static BOOL CRYPT_FormatCertIssuer(DWORD dwFormatStrType,
972 CERT_ALT_NAME_INFO *issuer, LPWSTR str, DWORD *pcbStr)
974 WCHAR buf[MAX_STRING_RESOURCE_LEN];
975 DWORD bytesNeeded;
976 BOOL ret;
978 LoadStringW(hInstance, IDS_CERT_ISSUER, buf, sizeof(buf) / sizeof(buf[0]));
979 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, issuer, NULL,
980 &bytesNeeded);
981 bytesNeeded += strlenW(buf) * sizeof(WCHAR);
982 if (ret)
984 if (!str)
985 *pcbStr = bytesNeeded;
986 else if (*pcbStr < bytesNeeded)
988 *pcbStr = bytesNeeded;
989 SetLastError(ERROR_MORE_DATA);
990 ret = FALSE;
992 else
994 *pcbStr = bytesNeeded;
995 strcpyW(str, buf);
996 str += strlenW(str);
997 bytesNeeded -= strlenW(str) * sizeof(WCHAR);
998 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 0, issuer, str,
999 &bytesNeeded);
1002 return ret;
1005 static BOOL WINAPI CRYPT_FormatAuthorityKeyId2(DWORD dwCertEncodingType,
1006 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1007 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1008 DWORD *pcbFormat)
1010 CERT_AUTHORITY_KEY_ID2_INFO *info;
1011 DWORD size;
1012 BOOL ret = FALSE;
1014 if (!cbEncoded)
1016 SetLastError(E_INVALIDARG);
1017 return FALSE;
1019 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_AUTHORITY_KEY_ID2,
1020 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1022 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1023 LPCWSTR sep;
1024 DWORD sepLen;
1025 BOOL needSeparator = FALSE;
1027 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1029 sep = crlf;
1030 sepLen = strlenW(crlf) * sizeof(WCHAR);
1032 else
1034 sep = commaSpace;
1035 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1038 if (info->KeyId.cbData)
1040 needSeparator = TRUE;
1041 ret = CRYPT_FormatKeyId(&info->KeyId, NULL, &size);
1042 if (ret)
1044 /* don't include NULL-terminator more than once */
1045 bytesNeeded += size - sizeof(WCHAR);
1048 if (info->AuthorityCertIssuer.cAltEntry)
1050 if (needSeparator)
1051 bytesNeeded += sepLen;
1052 needSeparator = TRUE;
1053 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1054 &info->AuthorityCertIssuer, NULL, &size);
1055 if (ret)
1057 /* don't include NULL-terminator more than once */
1058 bytesNeeded += size - sizeof(WCHAR);
1061 if (info->AuthorityCertSerialNumber.cbData)
1063 if (needSeparator)
1064 bytesNeeded += sepLen;
1065 ret = CRYPT_FormatCertSerialNumber(
1066 &info->AuthorityCertSerialNumber, NULL, &size);
1067 if (ret)
1069 /* don't include NULL-terminator more than once */
1070 bytesNeeded += size - sizeof(WCHAR);
1073 if (ret)
1075 if (!pbFormat)
1076 *pcbFormat = bytesNeeded;
1077 else if (*pcbFormat < bytesNeeded)
1079 *pcbFormat = bytesNeeded;
1080 SetLastError(ERROR_MORE_DATA);
1081 ret = FALSE;
1083 else
1085 LPWSTR str = pbFormat;
1087 *pcbFormat = bytesNeeded;
1088 needSeparator = FALSE;
1089 if (info->KeyId.cbData)
1091 needSeparator = TRUE;
1092 /* Overestimate size available, it's already been checked
1093 * above.
1095 size = bytesNeeded;
1096 ret = CRYPT_FormatKeyId(&info->KeyId, str, &size);
1097 if (ret)
1098 str += size / sizeof(WCHAR);
1100 if (info->AuthorityCertIssuer.cAltEntry)
1102 if (needSeparator)
1104 strcpyW(str, sep);
1105 str += sepLen / sizeof(WCHAR);
1107 needSeparator = TRUE;
1108 /* Overestimate size available, it's already been checked
1109 * above.
1111 size = bytesNeeded;
1112 ret = CRYPT_FormatCertIssuer(dwFormatStrType,
1113 &info->AuthorityCertIssuer, str, &size);
1114 if (ret)
1115 str += size / sizeof(WCHAR);
1117 if (info->AuthorityCertSerialNumber.cbData)
1119 if (needSeparator)
1121 strcpyW(str, sep);
1122 str += sepLen / sizeof(WCHAR);
1124 /* Overestimate size available, it's already been checked
1125 * above.
1127 size = bytesNeeded;
1128 ret = CRYPT_FormatCertSerialNumber(
1129 &info->AuthorityCertSerialNumber, str, &size);
1133 LocalFree(info);
1135 return ret;
1138 static const WCHAR colonCrlf[] = { ':','\r','\n',0 };
1140 static WCHAR aia[MAX_STRING_RESOURCE_LEN];
1141 static WCHAR accessMethod[MAX_STRING_RESOURCE_LEN];
1142 static WCHAR ocsp[MAX_STRING_RESOURCE_LEN];
1143 static WCHAR caIssuers[MAX_STRING_RESOURCE_LEN];
1144 static WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1145 static WCHAR accessLocation[MAX_STRING_RESOURCE_LEN];
1146 static BOOL WINAPI CRYPT_FormatAuthorityInfoAccess(DWORD dwCertEncodingType,
1148 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1149 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1150 DWORD *pcbFormat)
1152 CERT_AUTHORITY_INFO_ACCESS *info;
1153 DWORD size;
1154 BOOL ret = FALSE;
1156 if (!cbEncoded)
1158 SetLastError(E_INVALIDARG);
1159 return FALSE;
1161 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
1162 X509_AUTHORITY_INFO_ACCESS, pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG,
1163 NULL, &info, &size)))
1165 DWORD bytesNeeded = sizeof(WCHAR);
1167 if (!info->cAccDescr)
1169 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1171 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1172 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1173 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1174 if (!pbFormat)
1175 *pcbFormat = bytesNeeded;
1176 else if (*pcbFormat < bytesNeeded)
1178 *pcbFormat = bytesNeeded;
1179 SetLastError(ERROR_MORE_DATA);
1180 ret = FALSE;
1182 else
1184 *pcbFormat = bytesNeeded;
1185 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1188 else
1190 static const WCHAR colonSep[] = { ':',' ',0 };
1191 static const WCHAR numFmt[] = { '%','d',0 };
1192 static const WCHAR equal[] = { '=',0 };
1193 static BOOL stringsLoaded = FALSE;
1194 DWORD i;
1195 LPCWSTR headingSep, accessMethodSep, locationSep;
1196 WCHAR accessDescrNum[11];
1198 if (!stringsLoaded)
1200 LoadStringW(hInstance, IDS_AIA, aia,
1201 sizeof(aia) / sizeof(aia[0]));
1202 LoadStringW(hInstance, IDS_ACCESS_METHOD, accessMethod,
1203 sizeof(accessMethod) / sizeof(accessMethod[0]));
1204 LoadStringW(hInstance, IDS_ACCESS_METHOD_OCSP, ocsp,
1205 sizeof(ocsp) / sizeof(ocsp[0]));
1206 LoadStringW(hInstance, IDS_ACCESS_METHOD_CA_ISSUERS, caIssuers,
1207 sizeof(caIssuers) / sizeof(caIssuers[0]));
1208 LoadStringW(hInstance, IDS_ACCESS_METHOD_UNKNOWN, unknown,
1209 sizeof(unknown) / sizeof(unknown[0]));
1210 LoadStringW(hInstance, IDS_ACCESS_LOCATION, accessLocation,
1211 sizeof(accessLocation) / sizeof(accessLocation[0]));
1212 stringsLoaded = TRUE;
1214 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1216 headingSep = crlf;
1217 accessMethodSep = crlf;
1218 locationSep = colonCrlf;
1220 else
1222 headingSep = colonSep;
1223 accessMethodSep = commaSpace;
1224 locationSep = equal;
1227 for (i = 0; ret && i < info->cAccDescr; i++)
1229 /* Heading */
1230 bytesNeeded += sizeof(WCHAR); /* left bracket */
1231 sprintfW(accessDescrNum, numFmt, i + 1);
1232 bytesNeeded += strlenW(accessDescrNum) * sizeof(WCHAR);
1233 bytesNeeded += sizeof(WCHAR); /* right bracket */
1234 bytesNeeded += strlenW(aia) * sizeof(WCHAR);
1235 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1236 /* Access method */
1237 bytesNeeded += strlenW(accessMethod) * sizeof(WCHAR);
1238 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1239 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1240 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1241 szOID_PKIX_OCSP))
1242 bytesNeeded += strlenW(ocsp) * sizeof(WCHAR);
1243 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1244 szOID_PKIX_CA_ISSUERS))
1245 bytesNeeded += strlenW(caIssuers) * sizeof(caIssuers);
1246 else
1247 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1248 bytesNeeded += sizeof(WCHAR); /* space */
1249 bytesNeeded += sizeof(WCHAR); /* left paren */
1250 bytesNeeded += strlen(info->rgAccDescr[i].pszAccessMethod)
1251 * sizeof(WCHAR);
1252 bytesNeeded += sizeof(WCHAR); /* right paren */
1253 /* Delimiter between access method and location */
1254 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1255 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1256 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1257 bytesNeeded += strlenW(accessLocation) * sizeof(WCHAR);
1258 bytesNeeded += strlenW(locationSep) * sizeof(WCHAR);
1259 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1260 &info->rgAccDescr[i].AccessLocation, NULL, &size);
1261 if (ret)
1262 bytesNeeded += size - sizeof(WCHAR);
1263 /* Need extra delimiter between access method entries */
1264 if (i < info->cAccDescr - 1)
1265 bytesNeeded += strlenW(accessMethodSep) * sizeof(WCHAR);
1267 if (ret)
1269 if (!pbFormat)
1270 *pcbFormat = bytesNeeded;
1271 else if (*pcbFormat < bytesNeeded)
1273 *pcbFormat = bytesNeeded;
1274 SetLastError(ERROR_MORE_DATA);
1275 ret = FALSE;
1277 else
1279 LPWSTR str = pbFormat;
1280 DWORD altNameEntrySize;
1282 *pcbFormat = bytesNeeded;
1283 for (i = 0; ret && i < info->cAccDescr; i++)
1285 LPCSTR oidPtr;
1287 *str++ = '[';
1288 sprintfW(accessDescrNum, numFmt, i + 1);
1289 strcpyW(str, accessDescrNum);
1290 str += strlenW(accessDescrNum);
1291 *str++ = ']';
1292 strcpyW(str, aia);
1293 str += strlenW(aia);
1294 strcpyW(str, headingSep);
1295 str += strlenW(headingSep);
1296 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1298 strcpyW(str, indent);
1299 str += strlenW(indent);
1301 strcpyW(str, accessMethod);
1302 str += strlenW(accessMethod);
1303 if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1304 szOID_PKIX_OCSP))
1306 strcpyW(str, ocsp);
1307 str += strlenW(ocsp);
1309 else if (!strcmp(info->rgAccDescr[i].pszAccessMethod,
1310 szOID_PKIX_CA_ISSUERS))
1312 strcpyW(str, caIssuers);
1313 str += strlenW(caIssuers);
1315 else
1317 strcpyW(str, unknown);
1318 str += strlenW(unknown);
1320 *str++ = ' ';
1321 *str++ = '(';
1322 for (oidPtr = info->rgAccDescr[i].pszAccessMethod;
1323 *oidPtr; oidPtr++, str++)
1324 *str = *oidPtr;
1325 *str++ = ')';
1326 strcpyW(str, accessMethodSep);
1327 str += strlenW(accessMethodSep);
1328 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1330 strcpyW(str, indent);
1331 str += strlenW(indent);
1333 strcpyW(str, accessLocation);
1334 str += strlenW(accessLocation);
1335 strcpyW(str, locationSep);
1336 str += strlenW(locationSep);
1337 /* This overestimates the size available, but that
1338 * won't matter since we checked earlier whether enough
1339 * space for the entire string was available.
1341 altNameEntrySize = bytesNeeded;
1342 ret = CRYPT_FormatAltNameEntry(dwFormatStrType, 2,
1343 &info->rgAccDescr[i].AccessLocation, str,
1344 &altNameEntrySize);
1345 if (ret)
1346 str += altNameEntrySize / sizeof(WCHAR) - 1;
1347 if (i < info->cAccDescr - 1)
1349 strcpyW(str, accessMethodSep);
1350 str += strlenW(accessMethodSep);
1356 LocalFree(info);
1358 return ret;
1361 static WCHAR keyCompromise[MAX_STRING_RESOURCE_LEN];
1362 static WCHAR caCompromise[MAX_STRING_RESOURCE_LEN];
1363 static WCHAR affiliationChanged[MAX_STRING_RESOURCE_LEN];
1364 static WCHAR superceded[MAX_STRING_RESOURCE_LEN];
1365 static WCHAR operationCeased[MAX_STRING_RESOURCE_LEN];
1366 static WCHAR certificateHold[MAX_STRING_RESOURCE_LEN];
1368 struct reason_map_entry
1370 BYTE reasonBit;
1371 LPWSTR reason;
1372 int id;
1374 static struct reason_map_entry reason_map[] = {
1375 { CRL_REASON_KEY_COMPROMISE_FLAG, keyCompromise, IDS_REASON_KEY_COMPROMISE },
1376 { CRL_REASON_CA_COMPROMISE_FLAG, caCompromise, IDS_REASON_CA_COMPROMISE },
1377 { CRL_REASON_AFFILIATION_CHANGED_FLAG, affiliationChanged,
1378 IDS_REASON_AFFILIATION_CHANGED },
1379 { CRL_REASON_SUPERSEDED_FLAG, superceded, IDS_REASON_SUPERCEDED },
1380 { CRL_REASON_CESSATION_OF_OPERATION_FLAG, operationCeased,
1381 IDS_REASON_CESSATION_OF_OPERATION },
1382 { CRL_REASON_CERTIFICATE_HOLD_FLAG, certificateHold,
1383 IDS_REASON_CERTIFICATE_HOLD },
1386 static BOOL CRYPT_FormatReason(DWORD dwFormatStrType,
1387 const CRYPT_BIT_BLOB *reasonFlags, LPWSTR str, DWORD *pcbStr)
1389 static const WCHAR sep[] = { ',',' ',0 };
1390 static const WCHAR bitsFmt[] = { ' ','(','%','0','2','x',')',0 };
1391 static BOOL stringsLoaded = FALSE;
1392 int i, numReasons = 0;
1393 BOOL ret = TRUE;
1394 DWORD bytesNeeded = sizeof(WCHAR);
1395 WCHAR bits[6];
1397 if (!stringsLoaded)
1399 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1400 LoadStringW(hInstance, reason_map[i].id, reason_map[i].reason,
1401 MAX_STRING_RESOURCE_LEN);
1402 stringsLoaded = TRUE;
1404 /* No need to check reasonFlags->cbData, we already know it's positive.
1405 * Ignore any other bytes, as they're for undefined bits.
1407 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1409 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1411 bytesNeeded += strlenW(reason_map[i].reason) * sizeof(WCHAR);
1412 if (numReasons++)
1413 bytesNeeded += strlenW(sep) * sizeof(WCHAR);
1416 sprintfW(bits, bitsFmt, reasonFlags->pbData[0]);
1417 bytesNeeded += strlenW(bits);
1418 if (!str)
1419 *pcbStr = bytesNeeded;
1420 else if (*pcbStr < bytesNeeded)
1422 *pcbStr = bytesNeeded;
1423 SetLastError(ERROR_MORE_DATA);
1424 ret = FALSE;
1426 else
1428 *pcbStr = bytesNeeded;
1429 for (i = 0; i < sizeof(reason_map) / sizeof(reason_map[0]); i++)
1431 if (reasonFlags->pbData[0] & reason_map[i].reasonBit)
1433 strcpyW(str, reason_map[i].reason);
1434 str += strlenW(reason_map[i].reason);
1435 if (i < sizeof(reason_map) / sizeof(reason_map[0]) - 1 &&
1436 numReasons)
1438 strcpyW(str, sep);
1439 str += strlenW(sep);
1443 strcpyW(str, bits);
1445 return ret;
1448 static WCHAR crlDistPoint[MAX_STRING_RESOURCE_LEN];
1449 static WCHAR distPointName[MAX_STRING_RESOURCE_LEN];
1450 static WCHAR fullName[MAX_STRING_RESOURCE_LEN];
1451 static WCHAR rdnName[MAX_STRING_RESOURCE_LEN];
1452 static WCHAR reason[MAX_STRING_RESOURCE_LEN];
1453 static WCHAR issuer[MAX_STRING_RESOURCE_LEN];
1455 static BOOL WINAPI CRYPT_FormatCRLDistPoints(DWORD dwCertEncodingType,
1456 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1457 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1458 DWORD *pcbFormat)
1460 CRL_DIST_POINTS_INFO *info;
1461 DWORD size;
1462 BOOL ret = FALSE;
1464 if (!cbEncoded)
1466 SetLastError(E_INVALIDARG);
1467 return FALSE;
1469 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_CRL_DIST_POINTS,
1470 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size)))
1472 static const WCHAR numFmt[] = { '%','d',0 };
1473 static const WCHAR colonSep[] = { ':',' ',0 };
1474 static const WCHAR commaSep[] = { ',',' ',0 };
1475 static const WCHAR colon[] = { ':',0 };
1476 static BOOL stringsLoaded = FALSE;
1477 DWORD bytesNeeded = sizeof(WCHAR); /* space for NULL terminator */
1478 BOOL haveAnEntry = FALSE;
1479 LPCWSTR headingSep, distPointSep, nameSep;
1480 WCHAR distPointNum[11];
1481 DWORD i;
1483 if (!stringsLoaded)
1485 LoadStringW(hInstance, IDS_CRL_DIST_POINT, crlDistPoint,
1486 sizeof(crlDistPoint) / sizeof(crlDistPoint[0]));
1487 LoadStringW(hInstance, IDS_CRL_DIST_POINT_NAME, distPointName,
1488 sizeof(distPointName) / sizeof(distPointName[0]));
1489 LoadStringW(hInstance, IDS_CRL_DIST_POINT_FULL_NAME, fullName,
1490 sizeof(fullName) / sizeof(fullName[0]));
1491 LoadStringW(hInstance, IDS_CRL_DIST_POINT_RDN_NAME, rdnName,
1492 sizeof(rdnName) / sizeof(rdnName[0]));
1493 LoadStringW(hInstance, IDS_CRL_DIST_POINT_REASON, reason,
1494 sizeof(reason) / sizeof(reason[0]));
1495 LoadStringW(hInstance, IDS_CRL_DIST_POINT_ISSUER, issuer,
1496 sizeof(issuer) / sizeof(issuer[0]));
1497 stringsLoaded = TRUE;
1499 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1501 headingSep = crlf;
1502 distPointSep = crlf;
1503 nameSep = colonCrlf;
1505 else
1507 headingSep = colonSep;
1508 distPointSep = commaSep;
1509 nameSep = colon;
1512 for (i = 0; ret && i < info->cDistPoint; i++)
1514 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1516 if (distPoint->DistPointName.dwDistPointNameChoice !=
1517 CRL_DIST_POINT_NO_NAME)
1519 bytesNeeded += strlenW(distPointName) * sizeof(WCHAR);
1520 bytesNeeded += strlenW(colon) * sizeof(WCHAR);
1521 if (distPoint->DistPointName.dwDistPointNameChoice ==
1522 CRL_DIST_POINT_FULL_NAME)
1523 bytesNeeded += strlenW(fullName) * sizeof(WCHAR);
1524 else
1525 bytesNeeded += strlenW(rdnName) * sizeof(WCHAR);
1526 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1527 /* The indent level (3) is higher than when used as the issuer,
1528 * because the name is suppordinate to the name type (full vs.
1529 * RDN.)
1531 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1532 &distPoint->DistPointName.u.FullName, NULL, &size);
1533 if (ret)
1534 bytesNeeded += size - sizeof(WCHAR);
1535 haveAnEntry = TRUE;
1537 else if (distPoint->ReasonFlags.cbData)
1539 bytesNeeded += strlenW(reason) * sizeof(WCHAR);
1540 ret = CRYPT_FormatReason(dwFormatStrType,
1541 &distPoint->ReasonFlags, NULL, &size);
1542 if (ret)
1543 bytesNeeded += size - sizeof(WCHAR);
1544 haveAnEntry = TRUE;
1546 else if (distPoint->CRLIssuer.cAltEntry)
1548 bytesNeeded += strlenW(issuer) * sizeof(WCHAR);
1549 bytesNeeded += strlenW(nameSep) * sizeof(WCHAR);
1550 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1551 &distPoint->CRLIssuer, NULL, &size);
1552 if (ret)
1553 bytesNeeded += size - sizeof(WCHAR);
1554 haveAnEntry = TRUE;
1556 if (haveAnEntry)
1558 bytesNeeded += sizeof(WCHAR); /* left bracket */
1559 sprintfW(distPointNum, numFmt, i + 1);
1560 bytesNeeded += strlenW(distPointNum) * sizeof(WCHAR);
1561 bytesNeeded += sizeof(WCHAR); /* right bracket */
1562 bytesNeeded += strlenW(crlDistPoint) * sizeof(WCHAR);
1563 bytesNeeded += strlenW(headingSep) * sizeof(WCHAR);
1564 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1565 bytesNeeded += strlenW(indent) * sizeof(WCHAR);
1568 if (!haveAnEntry)
1570 WCHAR infoNotAvailable[MAX_STRING_RESOURCE_LEN];
1572 LoadStringW(hInstance, IDS_INFO_NOT_AVAILABLE, infoNotAvailable,
1573 sizeof(infoNotAvailable) / sizeof(infoNotAvailable[0]));
1574 bytesNeeded += strlenW(infoNotAvailable) * sizeof(WCHAR);
1575 if (!pbFormat)
1576 *pcbFormat = bytesNeeded;
1577 else if (*pcbFormat < bytesNeeded)
1579 *pcbFormat = bytesNeeded;
1580 SetLastError(ERROR_MORE_DATA);
1581 ret = FALSE;
1583 else
1585 *pcbFormat = bytesNeeded;
1586 strcpyW((LPWSTR)pbFormat, infoNotAvailable);
1589 else
1591 if (!pbFormat)
1592 *pcbFormat = bytesNeeded;
1593 else if (*pcbFormat < bytesNeeded)
1595 *pcbFormat = bytesNeeded;
1596 SetLastError(ERROR_MORE_DATA);
1597 ret = FALSE;
1599 else
1601 LPWSTR str = pbFormat;
1603 *pcbFormat = bytesNeeded;
1604 for (i = 0; ret && i < info->cDistPoint; i++)
1606 CRL_DIST_POINT *distPoint = &info->rgDistPoint[i];
1608 *str++ = '[';
1609 sprintfW(distPointNum, numFmt, i + 1);
1610 strcpyW(str, distPointNum);
1611 str += strlenW(distPointNum);
1612 *str++ = ']';
1613 strcpyW(str, crlDistPoint);
1614 str += strlenW(crlDistPoint);
1615 strcpyW(str, headingSep);
1616 str += strlenW(headingSep);
1617 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1619 strcpyW(str, indent);
1620 str += strlenW(indent);
1622 if (distPoint->DistPointName.dwDistPointNameChoice !=
1623 CRL_DIST_POINT_NO_NAME)
1625 DWORD altNameSize = bytesNeeded;
1627 strcpyW(str, distPointName);
1628 str += strlenW(distPointName);
1629 strcpyW(str, colon);
1630 str += strlenW(colon);
1631 if (distPoint->DistPointName.dwDistPointNameChoice ==
1632 CRL_DIST_POINT_FULL_NAME)
1634 strcpyW(str, fullName);
1635 str += strlenW(fullName);
1637 else
1639 strcpyW(str, rdnName);
1640 str += strlenW(rdnName);
1642 strcpyW(str, nameSep);
1643 str += strlenW(nameSep);
1644 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 3,
1645 &distPoint->DistPointName.u.FullName, str,
1646 &altNameSize);
1647 if (ret)
1648 str += altNameSize / sizeof(WCHAR) - 1;
1650 else if (distPoint->ReasonFlags.cbData)
1652 DWORD reasonSize = bytesNeeded;
1654 strcpyW(str, reason);
1655 str += strlenW(reason);
1656 ret = CRYPT_FormatReason(dwFormatStrType,
1657 &distPoint->ReasonFlags, str, &reasonSize);
1658 if (ret)
1659 str += reasonSize / sizeof(WCHAR) - 1;
1661 else if (distPoint->CRLIssuer.cAltEntry)
1663 DWORD crlIssuerSize = bytesNeeded;
1665 strcpyW(str, issuer);
1666 str += strlenW(issuer);
1667 strcpyW(str, nameSep);
1668 str += strlenW(nameSep);
1669 ret = CRYPT_FormatAltNameInfo(dwFormatStrType, 2,
1670 &distPoint->CRLIssuer, str,
1671 &crlIssuerSize);
1672 if (ret)
1673 str += crlIssuerSize / sizeof(WCHAR) - 1;
1678 LocalFree(info);
1680 return ret;
1683 static BOOL WINAPI CRYPT_FormatEnhancedKeyUsage(DWORD dwCertEncodingType,
1684 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1685 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1686 DWORD *pcbFormat)
1688 CERT_ENHKEY_USAGE *usage;
1689 DWORD size;
1690 BOOL ret = FALSE;
1692 if (!cbEncoded)
1694 SetLastError(E_INVALIDARG);
1695 return FALSE;
1697 if ((ret = CryptDecodeObjectEx(dwCertEncodingType, X509_ENHANCED_KEY_USAGE,
1698 pbEncoded, cbEncoded, CRYPT_DECODE_ALLOC_FLAG, NULL, &usage, &size)))
1700 WCHAR unknown[MAX_STRING_RESOURCE_LEN];
1701 DWORD i;
1702 DWORD bytesNeeded = sizeof(WCHAR); /* space for the NULL terminator */
1703 LPCWSTR sep;
1704 DWORD sepLen;
1706 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1708 sep = crlf;
1709 sepLen = strlenW(crlf) * sizeof(WCHAR);
1711 else
1713 sep = commaSpace;
1714 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1717 LoadStringW(hInstance, IDS_USAGE_UNKNOWN, unknown,
1718 sizeof(unknown) / sizeof(unknown[0]));
1719 for (i = 0; i < usage->cUsageIdentifier; i++)
1721 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
1722 usage->rgpszUsageIdentifier[i], CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
1724 if (info)
1725 bytesNeeded += strlenW(info->pwszName) * sizeof(WCHAR);
1726 else
1727 bytesNeeded += strlenW(unknown) * sizeof(WCHAR);
1728 bytesNeeded += sizeof(WCHAR); /* space */
1729 bytesNeeded += sizeof(WCHAR); /* left paren */
1730 bytesNeeded += strlen(usage->rgpszUsageIdentifier[i]) *
1731 sizeof(WCHAR);
1732 bytesNeeded += sizeof(WCHAR); /* right paren */
1733 if (i < usage->cUsageIdentifier - 1)
1734 bytesNeeded += sepLen;
1736 if (!pbFormat)
1737 *pcbFormat = bytesNeeded;
1738 else if (*pcbFormat < bytesNeeded)
1740 *pcbFormat = bytesNeeded;
1741 SetLastError(ERROR_MORE_DATA);
1742 ret = FALSE;
1744 else
1746 LPWSTR str = pbFormat;
1748 *pcbFormat = bytesNeeded;
1749 for (i = 0; i < usage->cUsageIdentifier; i++)
1751 PCCRYPT_OID_INFO info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY,
1752 usage->rgpszUsageIdentifier[i],
1753 CRYPT_ENHKEY_USAGE_OID_GROUP_ID);
1754 LPCSTR oidPtr;
1756 if (info)
1758 strcpyW(str, info->pwszName);
1759 str += strlenW(info->pwszName);
1761 else
1763 strcpyW(str, unknown);
1764 str += strlenW(unknown);
1766 *str++ = ' ';
1767 *str++ = '(';
1768 for (oidPtr = usage->rgpszUsageIdentifier[i]; *oidPtr; oidPtr++)
1769 *str++ = *oidPtr;
1770 *str++ = ')';
1771 *str = 0;
1772 if (i < usage->cUsageIdentifier - 1)
1774 strcpyW(str, sep);
1775 str += sepLen / sizeof(WCHAR);
1779 LocalFree(usage);
1781 return ret;
1784 static WCHAR financialCriteria[MAX_STRING_RESOURCE_LEN];
1785 static WCHAR available[MAX_STRING_RESOURCE_LEN];
1786 static WCHAR notAvailable[MAX_STRING_RESOURCE_LEN];
1787 static WCHAR meetsCriteria[MAX_STRING_RESOURCE_LEN];
1788 static WCHAR yes[MAX_STRING_RESOURCE_LEN];
1789 static WCHAR no[MAX_STRING_RESOURCE_LEN];
1791 static BOOL WINAPI CRYPT_FormatSpcFinancialCriteria(DWORD dwCertEncodingType,
1792 DWORD dwFormatType, DWORD dwFormatStrType, void *pFormatStruct,
1793 LPCSTR lpszStructType, const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat,
1794 DWORD *pcbFormat)
1796 SPC_FINANCIAL_CRITERIA criteria;
1797 DWORD size = sizeof(criteria);
1798 BOOL ret = FALSE;
1800 if (!cbEncoded)
1802 SetLastError(E_INVALIDARG);
1803 return FALSE;
1805 if ((ret = CryptDecodeObjectEx(dwCertEncodingType,
1806 SPC_FINANCIAL_CRITERIA_STRUCT, pbEncoded, cbEncoded, 0, NULL, &criteria,
1807 &size)))
1809 static BOOL stringsLoaded = FALSE;
1810 DWORD bytesNeeded = sizeof(WCHAR);
1811 LPCWSTR sep;
1812 DWORD sepLen;
1814 if (!stringsLoaded)
1816 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA, financialCriteria,
1817 sizeof(financialCriteria) / sizeof(financialCriteria[0]));
1818 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_AVAILABLE, available,
1819 sizeof(available) / sizeof(available[0]));
1820 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_NOT_AVAILABLE,
1821 notAvailable, sizeof(notAvailable) / sizeof(notAvailable[0]));
1822 LoadStringW(hInstance, IDS_FINANCIAL_CRITERIA_MEETS_CRITERIA,
1823 meetsCriteria, sizeof(meetsCriteria) / sizeof(meetsCriteria[0]));
1824 LoadStringW(hInstance, IDS_YES, yes, sizeof(yes) / sizeof(yes[0]));
1825 LoadStringW(hInstance, IDS_NO, no, sizeof(no) / sizeof(no[0]));
1826 stringsLoaded = TRUE;
1828 if (dwFormatStrType & CRYPT_FORMAT_STR_MULTI_LINE)
1830 sep = crlf;
1831 sepLen = strlenW(crlf) * sizeof(WCHAR);
1833 else
1835 sep = commaSpace;
1836 sepLen = strlenW(commaSpace) * sizeof(WCHAR);
1838 bytesNeeded += strlenW(financialCriteria) * sizeof(WCHAR);
1839 if (criteria.fFinancialInfoAvailable)
1841 bytesNeeded += strlenW(available) * sizeof(WCHAR);
1842 bytesNeeded += sepLen;
1843 bytesNeeded += strlenW(meetsCriteria) * sizeof(WCHAR);
1844 if (criteria.fMeetsCriteria)
1845 bytesNeeded += strlenW(yes) * sizeof(WCHAR);
1846 else
1847 bytesNeeded += strlenW(no) * sizeof(WCHAR);
1849 else
1850 bytesNeeded += strlenW(notAvailable) * sizeof(WCHAR);
1851 if (!pbFormat)
1852 *pcbFormat = bytesNeeded;
1853 else if (*pcbFormat < bytesNeeded)
1855 *pcbFormat = bytesNeeded;
1856 SetLastError(ERROR_MORE_DATA);
1857 ret = FALSE;
1859 else
1861 LPWSTR str = pbFormat;
1863 *pcbFormat = bytesNeeded;
1864 strcpyW(str, financialCriteria);
1865 str += strlenW(financialCriteria);
1866 if (criteria.fFinancialInfoAvailable)
1868 strcpyW(str, available);
1869 str += strlenW(available);
1870 strcpyW(str, sep);
1871 str += sepLen / sizeof(WCHAR);
1872 strcpyW(str, meetsCriteria);
1873 str += strlenW(meetsCriteria);
1874 if (criteria.fMeetsCriteria)
1875 strcpyW(str, yes);
1876 else
1877 strcpyW(str, no);
1879 else
1881 strcpyW(str, notAvailable);
1882 str += strlenW(notAvailable);
1886 return ret;
1889 typedef BOOL (WINAPI *CryptFormatObjectFunc)(DWORD, DWORD, DWORD, void *,
1890 LPCSTR, const BYTE *, DWORD, void *, DWORD *);
1892 static CryptFormatObjectFunc CRYPT_GetBuiltinFormatFunction(DWORD encodingType,
1893 DWORD formatStrType, LPCSTR lpszStructType)
1895 CryptFormatObjectFunc format = NULL;
1897 if ((encodingType & CERT_ENCODING_TYPE_MASK) != X509_ASN_ENCODING)
1899 SetLastError(ERROR_FILE_NOT_FOUND);
1900 return NULL;
1902 if (!HIWORD(lpszStructType))
1904 switch (LOWORD(lpszStructType))
1906 case LOWORD(X509_BASIC_CONSTRAINTS2):
1907 format = CRYPT_FormatBasicConstraints2;
1908 break;
1909 case LOWORD(X509_AUTHORITY_KEY_ID2):
1910 format = CRYPT_FormatAuthorityKeyId2;
1911 break;
1912 case LOWORD(X509_AUTHORITY_INFO_ACCESS):
1913 format = CRYPT_FormatAuthorityInfoAccess;
1914 break;
1915 case LOWORD(X509_CRL_DIST_POINTS):
1916 format = CRYPT_FormatCRLDistPoints;
1917 break;
1918 case LOWORD(X509_ENHANCED_KEY_USAGE):
1919 format = CRYPT_FormatEnhancedKeyUsage;
1920 break;
1921 case LOWORD(SPC_FINANCIAL_CRITERIA_STRUCT):
1922 format = CRYPT_FormatSpcFinancialCriteria;
1923 break;
1926 else if (!strcmp(lpszStructType, szOID_BASIC_CONSTRAINTS2))
1927 format = CRYPT_FormatBasicConstraints2;
1928 else if (!strcmp(lpszStructType, szOID_AUTHORITY_INFO_ACCESS))
1929 format = CRYPT_FormatAuthorityInfoAccess;
1930 else if (!strcmp(lpszStructType, szOID_AUTHORITY_KEY_IDENTIFIER2))
1931 format = CRYPT_FormatAuthorityKeyId2;
1932 else if (!strcmp(lpszStructType, szOID_CRL_DIST_POINTS))
1933 format = CRYPT_FormatCRLDistPoints;
1934 else if (!strcmp(lpszStructType, szOID_ENHANCED_KEY_USAGE))
1935 format = CRYPT_FormatEnhancedKeyUsage;
1936 else if (!strcmp(lpszStructType, SPC_FINANCIAL_CRITERIA_OBJID))
1937 format = CRYPT_FormatSpcFinancialCriteria;
1938 if (!format && !(formatStrType & CRYPT_FORMAT_STR_NO_HEX))
1939 format = CRYPT_FormatHexString;
1940 return format;
1943 BOOL WINAPI CryptFormatObject(DWORD dwCertEncodingType, DWORD dwFormatType,
1944 DWORD dwFormatStrType, void *pFormatStruct, LPCSTR lpszStructType,
1945 const BYTE *pbEncoded, DWORD cbEncoded, void *pbFormat, DWORD *pcbFormat)
1947 CryptFormatObjectFunc format = NULL;
1948 HCRYPTOIDFUNCADDR hFunc = NULL;
1949 BOOL ret = FALSE;
1951 TRACE("(%08x, %d, %08x, %p, %s, %p, %d, %p, %p)\n", dwCertEncodingType,
1952 dwFormatType, dwFormatStrType, pFormatStruct, debugstr_a(lpszStructType),
1953 pbEncoded, cbEncoded, pbFormat, pcbFormat);
1955 if (!(format = CRYPT_GetBuiltinFormatFunction(dwCertEncodingType,
1956 dwFormatStrType, lpszStructType)))
1958 static HCRYPTOIDFUNCSET set = NULL;
1960 if (!set)
1961 set = CryptInitOIDFunctionSet(CRYPT_OID_FORMAT_OBJECT_FUNC, 0);
1962 CryptGetOIDFunctionAddress(set, dwCertEncodingType, lpszStructType, 0,
1963 (void **)&format, &hFunc);
1965 if (format)
1966 ret = format(dwCertEncodingType, dwFormatType, dwFormatStrType,
1967 pFormatStruct, lpszStructType, pbEncoded, cbEncoded, pbFormat,
1968 pcbFormat);
1969 if (hFunc)
1970 CryptFreeOIDFunctionAddress(hFunc, 0);
1971 return ret;